Trouble shipping an ItemFulfillment using SuiteTalk - c#

What do I need to do to mark an ItemFulfillment as shipped, including package information and possibly a different shipping method/carrier using SuiteTalk? We use WMS Lite RF Mobile Screen to initially create the ItemFulfillment, then a custom app to ship it.
I initially tried using an ItemFulfillmentPackageList to specify the package, but it seemed to ignore what I specified and add a default package (0.05 lb, no description or tracking).
I then tried ItemFulfillmentPackageUspsList, etc. and correct package information appeared if it matched the carrier previously specified in the order and fulfillment record. If it doesn't match, I get an error "[Code=JS_EXCEPTION] Error: Switching the shipping method to another carrier is an unsupported operation, because it requires reloading the item fulfillment form for that carrier." We need the ability to switch carriers because we offer free shipping for some orders, which ends up being "pick the cheapest rate for the package from the rates offered by the main 3 carriers".
//curShipment is an EasyPost shipment after purchasing postage.
//it contains relevant information about the package
ItemFulfillment fulfillmentUpdate = new ItemFulfillment();
fulfillmentUpdate.internalId = curFulfillment.internalId;
fulfillmentUpdate.shipStatus = ItemFulfillmentShipStatus._shipped;
fulfillmentUpdate.shipStatusSpecified = true;
fulfillmentUpdate.shipMethod = new RecordRef()
{
// Get the internalId from a saved dictionary
internalId = shipMethods.GetNetsuite(curShipment.selected_rate).netsuiteId
};
switch (curShipment.selected_rate.carrier)
{
case "USPS":
ItemFulfillmentPackageUsps pkgUsps = new ItemFulfillmentPackageUsps();
pkgUsps.packageWeightUsps = curShipment.parcel.weight / 16; // Easypost uses Oz, Netsuite uses Lb
pkgUsps.packageWeightUspsSpecified = true;
if (string.IsNullOrWhiteSpace(curShipment.parcel.predefined_package))
{
pkgUsps.packageLengthUsps = (long)curShipment.parcel.length;
pkgUsps.packageLengthUspsSpecified = true;
pkgUsps.packageWidthUsps = (long)curShipment.parcel.width;
pkgUsps.packageWidthUspsSpecified = true;
pkgUsps.packageHeightUsps = (long)curShipment.parcel.height;
}
pkgUsps.packageTrackingNumberUsps = curShipment.tracking_code;
ItemFulfillmentPackageUspsList pkgListUsps = new ItemFulfillmentPackageUspsList();
pkgListUsps.packageUsps = new ItemFulfillmentPackageUsps[] { pkgUsps };
fulfillmentUpdate.packageUspsList = pkgListUsps;
break;
// Cases for the other carriers, almost identical to USPS above
}
SetNetsuitePrefs(); // Sets preferences and authenticates, similar to the ERP example code
WriteResponse response = await System.Threading.Tasks.Task<SearchResult>.Run(() => { return nsService.update(fulfillmentUpdate); });
// Results in error:
// [Code=JS_EXCEPTION] Error: Switching the shipping method to another carrier is an unsupported operation, because it requires reloading the item fulfillment form for that carrier.

Try setting shipMethod to the RecordRef for the Shipping Item you will be using. If the SO was entered with a FedEx Shipping Item and now you want to use UPS, then set shipMethod accordingly and use the carrier-specific package list structure.

Related

Expanding a Source object in a Stripe API call to StripeBalenceService doesn't return any customer info

I'm making a c# call to the Stripe.net API to fetch a balance history for a connected account. I'm trying to expand on the balance transaction object to see where the charge is coming from (ex. the customer who made the charge) as all the charges to connected accounts on my platform are from charge objects with a destination property to the connected account.
Here is my code and a screenshot of what the expanded source looks like, but think I should see a charge id or a customer or something refering me to the initial customer somewhere, but I don't...
var balanceService = new StripeBalanceService();
balanceService.ExpandSource = true;
var list = new List <string> () {
"data.source.source_transfer"
};
StripeList <StripeBalanceTransaction> balanceTransactions
= balanceService.List(
new StripeBalanceTransactionListOptions() {
Limit = 20,
Type = "payment",
Expand = list
},
new StripeRequestOptions() {
StripeConnectAccountId = accountId
}
);
foreach(var transaction in balanceTransactions) {
var test = transaction;
}
I feel like I should see a charge id (ex. ch_xxx) or a Customer value (which is null) all I see of any relevance is a payment id (ex. py_xxx)
It is possible to get the charge object(ch_xxx), it is just a little involved!
As you are using destination charges, the charge(ch_xxx) takes place on the platform account, and then a transfer(tr_xxx) is made to the connected account. That transfer creates a payment(py_xxx) on the connected account, which results in a balance transaction(txn_xxx).
As your code expands the source of those balance transactions, you get the payment(py_xxx). The payment is equivalent to a charge, so it has a source_transfer field. You can expand this field also! This will give you the transfer object(tr_xxx). Finally, the transfer has a source_transaction field, and this can be exapanded to give the original charge(ch_xxx)!
Putting that all together, you will want to expand on "data.source.source_transfer.source_transaction".
If you use a Stripe library in a dynamic language you can see this in action ... unfortunately, stripe-dotnet has an open issue right now which means that you can not do this directly. Instead, you will need to make the API calls manually by calling the various Retrieve functions on the IDs, instead of doing a single expansion. It would look something like this:
var paymentId = transaction.Source.Id;
var chargeService = new StripeChargeService();
var payment = chargeService.Get(
paymentId,
new StripeRequestOptions()
{
StripeConnectAccountId = accountId
}
);
var transferService = new StripeTransferService();
transferService.ExpandSourceTransaction = true;
var transfer = transferService.Get(payment.SourceTransferId);
var charge = transfer.SourceTransaction;
Console.WriteLine(charge.Id);

How to create a direct charge by using a shared customer?

I am attempting to create a direct charge to a connected account from my platform. I have been advised by Stripe support to do this by using a shared customer, however that has just created more issues.
The code itself is very simple, if it worked. It updates the platform customer with the src_... token provided by an iOS app. This works. It then attempts to create a shared customer using the StripeTokenService(). This does not work, despite following the documentation to the letter. The error I receive is:
You provided a customer without specifying a source. The default source of the customer is a source and cannot be shared from existing customers.
I can see no method of providing a source to the shared customer in the Stripe .Net SDK. All I can provide is a Card or BankAccount, neither of which I want to do as the API should remain agnostic of sensitive user information.
What exactly am I doing wrong here?
StripeConfiguration.SetApiKey(Settings.Stripe.SecretKey);
var businessRequestOptions = new StripeRequestOptions { StripeConnectAccountId = businessOwner.StripeAccountId };
var customerService = new StripeCustomerService();
customerService.Update(userDetail.StripeCustomerId, new StripeCustomerUpdateOptions
{
SourceToken = stripeToken // = 'src_...'
});
var tokenService = new StripeTokenService();
// this is the call that generates the error I mentioned above \/ \/
var token = tokenService.Create(new StripeTokenCreateOptions
{
CustomerId = userDetail.StripeCustomerId // = 'cus_...'
}, businessRequestOptions);
// create a direct charge to the business account (taking out application fee)
var chargeService = new StripeChargeService();
var stripeCharge = chargeService.Create(new StripeChargeCreateOptions
{
Amount = Convert.ToInt32(fee),
Currency = currency,
Description = $"Payment to {businessOwner.BusinessName} through Service X",
ApplicationFee = applicationFee,
SourceTokenOrExistingSourceId = token.Id, // use shared customerId here
}, businessRequestOptions);
When using Sources you have to use a different approach which is documented here: https://stripe.com/docs/sources/connect#shared-card-sources
The idea is that you are going to "clone" the Source from the platform to the connected account. This is done using the original_source when creating a new Source. You will then get a new Source object with a different id src_XXXX that you can then charge directly on the connected account.

DynamoDB disable auto-scaling programmatically

I want to run a daily update of a set of Dynamo tables. I have written a console app to do this however I want to be able to programmatically disable the capacity auto-scaling at the start of the update process and then re-enable it at the end.
I have managed to increase the provisioned throughput for both the table and it's Global Secondary Indexes using the UpdateTableAsync method but this does not have any options for handling auto-scaling and I can't find any other functionality to let me do this.
Does it even exist?
EDIT: I have found the CLI command required for this here: https://docs.aws.amazon.com/cli/latest/reference/application-autoscaling/delete-scaling-policy.html. My question is now, does this exist anywhere in the .NET SDK?
After a lot of digging through the AWS documentation (there doesn't seem to be any tutorials or examples, especially for .NET) I've discovered that this functionality does exist but it is not at Dynamo-level. It is an AWS-wide package that handles auto-scaling for all AWS resources.
There is a nuget package called AWSSDK.ApplicationAutoScaling. You'll need to create yourself an instance of AmazonApplicationAutoScalingClient (in the code below, this is represented by autoScaling).
When setting up auto-scaling in the AWS DynamoDB Console, two things are created; a description of the scaling (min capacity, max capacity etc) and a policy which I believe links the auto-scaling with CloudWatch so that alrms can be raised. Both of these objects need to be managed.
To solve my problem of disabling auto-scaling and then re-enabling it after updating my tables I had to following this process:
Save the policies and scaling descriptions (called ScalableTargets) before running the update.
this.preUpdatePolicies = (await autoScaling.DescribeScalingPoliciesAsync(new DescribeScalingPoliciesRequest
{
ResourceId = $"table/{this.tableName}",
ServiceNamespace = ServiceNamespace.Dynamodb,
ScalableDimension = ScalableDimension.DynamodbTableWriteCapacityUnits
})).ScalingPolicies;
this.preUpdateScaling = (await autoScaling.DescribeScalableTargetsAsync(new DescribeScalableTargetsRequest
{
ResourceIds = new List<string>() { $"table/{this.tableName}" },
ServiceNamespace = ServiceNamespace.Dynamodb,
ScalableDimension = ScalableDimension.DynamodbTableWriteCapacityUnits
})).ScalableTargets;
I then deregister the scaling descriptions which also deletes any associated policies.
foreach (var scaling in this.preUpdateScaling)
{
await autoScaling.DeregisterScalableTargetAsync(new DeregisterScalableTargetRequest
{
ResourceId = scaling.ResourceId,
ServiceNamespace = ServiceNamespace.Dynamodb,
ScalableDimension = ScalableDimension.DynamodbTableWriteCapacityUnits
});
}
After I have run my update I then reregister the descriptions/scalable targets and put the policies back based on the values I saved before running the update.
foreach (var scaling in this.preUpdateScaling)
{
await autoScaling.RegisterScalableTargetAsync(new RegisterScalableTargetRequest
{
ResourceId = scaling.ResourceId,
ServiceNamespace = scaling.ServiceNamespace,
ScalableDimension = scaling.ScalableDimension,
RoleARN = scaling.RoleARN,
MinCapacity = scaling.MinCapacity,
MaxCapacity = scaling.MaxCapacity
});
}
foreach (var policy in this.preUpdatePolicies)
{
await autoScaling.PutScalingPolicyAsync(new PutScalingPolicyRequest
{
ServiceNamespace = policy.ServiceNamespace,
ResourceId = policy.ResourceId,
ScalableDimension = policy.ScalableDimension,
PolicyName = policy.PolicyName,
PolicyType = policy.PolicyType,
TargetTrackingScalingPolicyConfiguration = policy.TargetTrackingScalingPolicyConfiguration
});
}
Hopefully this is helpful for anyone else who would like to use .NET to manage auto-scaling.

How to setup Project Backlog in TFS pro grammatically?

I have look around the other post about this Project Backlog, but i want to those missing field in this image here
I need those missing fields like workitem, Title, Assigned To, State, Effort, Business.
I have this code with me right now.
/ Set up default team sprint date and time
var teamConfig = _tfs.GetService<TeamSettingsConfigurationService>();
var css = _tfs.GetService<ICommonStructureService4>();
string rootNodePath = string.Format("\\{0}\\Iteration\\Release 1\\Sprint 1", _selectedTeamProject.Name);
var pathRoot = css.GetNodeFromPath(rootNodePath);
css.SetIterationDates(pathRoot.Uri, DateTime.Now.AddDays(-5), DateTime.Now.AddDays(7));
var configs = teamConfig.GetTeamConfigurationsForUser(new[] { _selectedTeamProject.Uri });
var team = configs.Where(c => c.TeamName == "Demo").FirstOrDefault();
var ts = team.TeamSettings;
ts.BacklogIterationPath = string.Format(#"{0}\Release 1", _selectedTeamProject.Name);
ts.IterationPaths = new string[] { string.Format(#"{0}\Release 1\Sprint 1", _selectedTeamProject.Name), string.Format(#"{0}\Release 1\Sprint 2", _selectedTeamProject.Name) };
var tfv = new TeamFieldValue();
tfv.IncludeChildren = true;
tfv.Value = _selectedTeamProject.Name;
ts.TeamFieldValues = new []{tfv};
teamConfig.SetTeamSettings(team.TeamId, ts);
According to your screenshot, seems you are using the Work item Summary web part. After the upgrade to TFS2018, your TFS SharePoint sites will display, but all integration functionality is disabled.
The official recommended way is using TFS Dashboards for a better way to create dashboards. From that it's more easy to track/display the fields in a work item.
You could directly use some 3-party Work Item widget such as this one which also provides a summary for a selected work item.
To get or update work items such as product backlog fields pro grammatically, you could use Rest API-- Get a list of work items to handle this. It will also return all related fields name and value. Which also include a C# (GetWorkItemsByIDs method) sample code. About how to customize a dashboard in sharepoint, please take a look at this thread.

Updating MetaData on Connected account fails

I am using stripe connect(destination payment) with the help of stripe.net library from Jaymedavis.
The problem that I am facing is that I am not able to retrieve the destination payment ID to update the metadata in the connected account. The following line returns a null preventing me from updating meta data on the connected account. But the strange thing is that when I log in to the dashboard the destination payment ID exists. I am not sure why I am not able to retreive it in code.
Is the charge creation asynchronous?. I am not sure. Stripe's connect documentation does not help either. The following line returns a null. My code is down below. Seeking help.
String deschargeID = result.Transfer.DestinationPayment;
Here is the code that I am using
var service = new StripeChargeService(ZambreroSecretKey);
var result = (Stripe.StripeCharge) null;
try {
result = service.Create(newCharge);
if (result.Paid) {
//get the chargeID on the newgen account and update the metadata.
//Returns null even though it exists in the dashboard
String deschargeID = result.Transfer.DestinationPayment;
var chargeService = new StripeChargeService(newgenSecretKey);
StripeCharge charge = chargeService.Get(deschargeID);
charge.Metadata = myDict;
Response.Redirect("PgeCustSuccess.aspx?OrderID=" + OrderID);
}
} catch (StripeException stripeException) {
Debug.WriteLine(stripeException.Message);
stripe.Text = stripeException.Message;
}
The charge object's transfer attribute is not expanded by default, meaning it's just a string with the ID of the transfer object ("tr_..."), not a full transfer object.
According to Stripe.net's documentation, you can expand the transfer attribute by adding this line:
service.ExpandTransfer = True
before sending the charge creation request.

Categories