Dynamics GP Web Services: SalesInvoice Creation with Lot Allocation - web-services

I'm trying to use the following code to create a new SalesInvoice based on an existing SalesOrder:
SalesInvoice invoice = new SalesInvoice();
invoice.DocumentTypeKey = new SalesDocumentTypeKey { Type = SalesDocumentType.Invoice };
invoice.CustomerKey = originalOrder.CustomerKey;
invoice.BatchKey = originalOrder.BatchKey;
invoice.Terms = new SalesTerms { DiscountTakenAmount = new MoneyAmount { Value = 0, Currency = "USD", DecimalDigits = 2 }, DiscountAvailableAmount = new MoneyAmount { Value = 0, Currency = "USD", DecimalDigits = 0 } };
invoice.OriginalSalesDocumentKey = originalOrder.Key;
List<SalesInvoiceLine> lineList = new List<SalesInvoiceLine>();
for (int i = 0; i < originalOrder.Lines.Length; i++)
{
SalesInvoiceLine line = new SalesInvoiceLine();
line.ItemKey = originalOrder.Lines[i].ItemKey;
line.Key = new SalesLineKey { LineSequenceNumber = originalOrder.Lines[i].Key.LineSequenceNumber; }
SalesLineLot lot = new SalesLineLot();
lot.LotNumber = originalOrder.Lines[i].Lots[0].LotNumber;
lot.Quantity = new Quantity { Value = 2200 };
lot.Key = new SalesLineLotKey { SequenceNumber = originalOrder.Lines[i].Lots[0].Key.SequenceNumber };
line.Lots = new SalesLineLot[] { lot };
line.Quantity = new Quantity { Value = 2200 };
lineList.Add(line);
}
invoice.Lines = lineList.ToArray();
DynamicsWS.CreateSalesInvoice(invoice, DynamicsContext, DynamicsWS.GetPolicyByOperation("CreateSalesInvoice", DynamicsContext));
When executed, I receive the following error:
SQL Server Exception: Operation expects a parameter which was not supplied.
And the more detailed exception from the Exception Console in Dynamics:
Procedure or function 'taSopLotAuto' expects parameter '#I_vLNITMSEQ',
which was not supplied.
After a considerable amount of digging through Google, I discovered a few things.
'taSopLotAuto' is an eConnect procedure within the Sales Order Processing component that attempts to automatically fill lots. I do not want the lots automatically filled, which is why I try to fill them manually in the code. I've also modified the CreateSalesInvoice policy from Automatic lot fulfillment to Manual lot fulfillment for the GP web services user, but that didn't change which eConnect procedure was called.
'#I_vLNITMSEQ' refers to the LineSequenceNumber. The LineSequenceNumber and SequenceNumber (of the Lot itself) must match. In my case they are both the default: 16384. Not only is this parameter set in the code above, but it also appears in the SOAP message that the server attempted to process - hardly "not supplied."
I can create an invoice sans line items without a hitch, but if I add line items it fails. I do not understand why I am receiving an error for a missing parameter that is clearly present.
Any ideas on how to successfully create a SalesInvoice through Dynamics GP 10.0 Web Services?

Maybe you mess to add the line key to the lot:
lot.Key = new SalesLineKey();
lot.Key.SalesDocumentKey = new SalesDocumentKey();
lot.Key.SalesDocumentKey.Id = seq.ToString();

Related

Authorize.net Sandbox Accept page testing- always declined?

I’m attempting to test Accept Hosted payment page(redirect-method) with my sandbox. For this, I’m using the GetAnAcceptPaymentPage from the Java sample code application to generate a token string for a payment, specified the autoLoginId and transactionKey for my sandbox, and setting $1.00 as the amount. I’m then posting the returned token string to https://test.authorize.net/payment/payment with a “token” form element containing that string. This much appears to be working, and I do get a payment page showing the $1.00 amount. However, no matter what values I enter onto that payment page, pressing the “Pay” button just shows “The transaction has been declined.” in red text at the bottom of the form. I’ve confirmed that my sandbox is set to “Live” mode, and have looked at the following link to use what I believe should be valid values for testing: https://developer.authorize.net/hello_world/testing_guide/. I'm hoping someone can tell me why I can't get any result other than "The transaction has been declined".
public String getTokenValue() {
ApiOperationBase.setEnvironment(Environment.SANDBOX);
MerchantAuthenticationType merchantAuthenticationType = new MerchantAuthenticationType();
merchantAuthenticationType.setName("xxxxx");
merchantAuthenticationType.setTransactionKey("xxxxxx");
ApiOperationBase.setMerchantAuthentication(merchantAuthenticationType);
// Create the payment transaction request
TransactionRequestType txnRequest = new TransactionRequestType();
txnRequest.setTransactionType(TransactionTypeEnum.AUTH_CAPTURE_TRANSACTION.value());
txnRequest.setAmount(new BigDecimal(1.00).setScale(2, RoundingMode.CEILING));
OrderExType order = new OrderExType();
order.setInvoiceNumber("2");
txnRequest.setOrder(order);
CustomerProfilePaymentType cpp = new CustomerProfilePaymentType();
cpp.setCustomerProfileId("xxxx");
cpp.setCreateProfile(true);
txnRequest.setProfile(cpp);
SettingType setting1 = new SettingType();
setting1.setSettingName("hostedPaymentButtonOptions");
setting1.setSettingValue("{\"text\": \"Proceed\"}");
SettingType setting2 = new SettingType();
setting2.setSettingName("hostedPaymentOrderOptions");
setting2.setSettingValue("{\"show\": false}");
SettingType setting3 = new SettingType();
setting3.setSettingName("hostedPaymentPaymentOptions");
setting3.setSettingValue("{\"cardCodeRequired\": true}");
SettingType setting4 = new SettingType();
setting4.setSettingName("hostedPaymentIFrameCommunicatorUrl");
setting4.setSettingValue("{\"url\": \"http://example.com/abc\"}");
ArrayOfSetting alist = new ArrayOfSetting();
alist.getSetting().add(setting1);
alist.getSetting().add(setting2);
alist.getSetting().add(setting3);
alist.getSetting().add(setting4);
GetHostedPaymentPageRequest apiRequest = new GetHostedPaymentPageRequest();
apiRequest.setTransactionRequest(txnRequest);
apiRequest.setHostedPaymentSettings(alist);
GetHostedPaymentPageController controller = new GetHostedPaymentPageController(apiRequest);
controller.execute();
GetHostedPaymentPageResponse response = new GetHostedPaymentPageResponse();
response = controller.getApiResponse();
if (response != null) {
if (response.getMessages().getResultCode() == MessageTypeEnum.OK) {
System.out.println(response.getToken());
} else {
System.out.println("Failed to get hosted payment page: " + response.getMessages().getResultCode());
}
}
return response.getToken();
}
>>> order.setInvoiceNumber("2");
Set the invoice number to a different value than 2, this value is used in Sandbox to trigger decline for testing purposes.

SOAP Fault when Using DocuSign API with Salesforce for Creating Envelope with Templates

I am using Salesforce with DocuSign to try and create an envelope via templates.
DocuSignAPI.EnvelopeTemplates templates = soapService.requestTemplates(accountId, false);
String templateId = templates.EnvelopeTemplateDefinition[0].TemplateID;
DocuSignAPI.EnvelopeTemplate template = soapService.requestTemplate(templateId, false);
DocuSignAPI.EnvelopeInformation envelopeInformation = new DocuSignAPI.EnvelopeInformation();
envelopeInformation.Subject = 'XXXXXXXXXXX';
envelopeInformation.AccountId = accountId;
envelopeInformation.EmailBlurb = 'XXXXXXXXXXXXX';
DocuSignAPI.TemplateReference templateReference = new DocuSignAPI.TemplateReference();
templateReference.RoleAssignments = new DocuSignAPI.ArrayOfTemplateReferenceRoleAssignment();
templateReference.Template = template.EnvelopeTemplateDefinition.TemplateID;
templateReference.TemplateLocation = 'Server';
DocuSignAPI.Recipient recipient = new DocuSignAPI.Recipient();
recipient.ID = currentRecipientIndex + 1;
recipient.Type_x = 'Signer';
recipient.Email = 'XXXXXXXXXXXXXXXX';
recipient.UserName = 'XXXXXXXXXXXXXXXXX';
recipient.RoutingOrder = 1;
DocuSignAPI.ArrayOfRecipient1 recipients = new DocuSignAPI.ArrayOfRecipient1();
recipients.Recipient = new DocuSignAPI.Recipient[1];
recipients.Recipient.add(recipient);
DocuSignAPI.TemplateReferenceRoleAssignment trra = new DocuSignAPI.TemplateReferenceRoleAssignment();
trra.RoleName='Stake holder';
trra.RecipientID = recipient.ID;
templateReference.RoleAssignments.RoleAssignment = new DocuSignAPI.TemplateReferenceRoleAssignment[1];
templateReference.RoleAssignments.RoleAssignment.add(trra);
DocuSignAPI.ArrayOfTemplateReference arrayOfTemplateReference = new DocuSignAPI.ArrayOfTemplateReference();
arrayOfTemplateReference.TemplateReference = new DocuSignAPI.TemplateReference[1];
arrayOfTemplateReference.TemplateReference.add(templateReference);
DocuSignAPI.EnvelopeStatus status = soapService.createEnvelopeFromTemplates(arrayOfTemplateReference, recipients, envelopeInformation, true);
However, upon running the code, I get the following error:
Web service callout failed: WebService returned a SOAP Fault: Unspecified_Error faultcode=soap:Server faultactor=https://demo.docusign.net/api/3.0/dsapi.asmx
And this references the DocuSignAPI where the WebServiceCallout is invoked. Given the ambiguity of the error, I would appreciate any thoughts on what could be causing this.
As an update to this post, I was able to find the error. The indexing for Apex starts at 0 not 1 (unlike MatLab which is what caused my confusion). Because I was starting at index 1, the XML request was passing 'null' values at the 0th index, causing the error. Starting at 0, removed the null values from the XML and the request went through.

Dynamics GP Web Services: Changing policy behavior at runtime

I am creating a payables invoices using Web Services on GP2013. Optionally, my users can provide line item distributions. I can create invoices, but unless I modify the CreatePayablesInvoice policy to "Distributions Will Be Provided" in the dynamics security console, the invoice gets both the system provided distributions as well as the distribution lines I am creating. I want to have the ability to provide distributions if necessary, otherwise I want the system to handle it.
The documentation suggests I should be able to alter the policy in code, but when I get the policy object back from GetPolicyByOperation, the Behaviors array is empty. I have tried creating the behavior manually in code and it doesn't alter what happens when the invoice is created. The only thing that impacts the result is editing the property in the security console.
My code for altering the the policy is below:
payablesInvoiceCreatePolicy = wsDynamicsGP.GetPolicyByOperation("CreatePayablesInvoice", context);
BehaviorKey bk = new BehaviorKey();
bk.Id = new Guid("e476a157-ecf0-4dae-8cef-317dd2cfbe41");
Behavior b = new Behavior();
b.Key = bk;
BehaviorOption opt0 = new BehaviorOption();
opt0.Key = new BehaviorOptionKey();
opt0.Key.Id = 0;
opt0.Name = "Distributions Will Be Provided";
BehaviorOption opt1 = new BehaviorOption();
opt1.Key = new BehaviorOptionKey();
opt1.Key.Id = 1;
opt1.Name = "Automatically Create Distributions";
b.Options = new BehaviorOption[] { opt0, opt1 };
b.SelectedOption = b.Options[1];
payablesInvoiceCreatePolicy.Behaviors = new Behavior[]{b};
wsDynamicsGP.CreatePayablesInvoice(payablesInvoice, context, payablesInvoiceCreatePolicy);
Documentation seems to be sparse on what should or shouldn't work here. I have to assume I should be able to update the policy as I see fit at runtime based on whether or not my user has decided to provide line item distributions.
Does anyone know what I am missing?
Yes. It took me 2 days to fix this myself. After adding the behaviour to the policy object UpdatePolicy before calling the create invoice as below:
wsDynamicsGP.UpdatePolicy(payablesInvoiceCreatePolicy, new RoleKey { Id = "00000000-0000-0000-0000-000000000000" }, context)
wsDynamicsGP.CreatePayablesInvoice(payablesInvoice, context, payablesInvoiceCreatePolicy);
Note that you selected the behavior that automatically creates distribution lines on invoice creation. The behavior's Internal property also must be set to true.
Here is a working example also utilizing FlowerKing's answer:
BehaviorKey bk = new BehaviorKey();
bk.Id = new Guid("e476a157-ecf0-4dae-8cef-317dd2cfbe41");
bk.PolicyKey = payablesInvoiceCreatePolicy.Key;
Behavior b = new Behavior();
b.Key = bk;
b.Internal = true;
BehaviorOption opt0 = new BehaviorOption();
opt0.Key = new BehaviorOptionKey();
opt0.Key.Id = 0;
opt0.Name = "Distributions Will Be Provided";
BehaviorOption opt1 = new BehaviorOption();
opt1.Key = new BehaviorOptionKey();
opt1.Key.Id = 1;
opt1.Name = "Automatically Create Distributions";
b.Options = new BehaviorOption[] { opt0, opt1 };
b.SelectedOption = b.Options[0];
policy.Behaviors = new Behavior[] { b };
client.UpdatePolicy(payablesInvoiceCreatePolicy, new RoleKey { Id = "00000000-0000-0000-0000-000000000000" }, context);
client.CreatePayablesInvoice(payablesInvoice, context, payablesInvoiceCreatePolicy);

Dynamics CRM Web Service Execute returns "Server was unable to process request."

I'm going crazy here with DCRM web services,
I'm trying to create a Connection between two leads dynamically.
I'm getting the following error:
"0x80040216
An unexpected error occurred.
Platform
An unexpected error occurred.
Type:Microsoft.Crm.CrmException ErrorCode:0x80040216
Object reference not set to an instance of an object."
Here is my code:
Guid connectionRoleID = new Guid("64f33a74-0342-e211-b55e-00155d00041e");
connectionroleobjecttypecode connroleobjecttypecode = new connectionroleobjecttypecode() { connectionroleid = new Lookup(){Value = connectionRoleID}, associatedobjecttypecode = EntityName.lead.ToString()};
connection conn = new connection();
List<Property> list = new List<Property>();
Lookup lookup = new Lookup();
lookup.Value = customers[i].ID.Value.Value;
lookup.name = EntityName.lead.ToString();
Lookup lookup2 = new Lookup();
lookup2.Value = customers[j].ID.Value.Value;
lookup2.name = EntityName.lead.ToString();
conn.record1roleid = new Lookup() { name = "duplicate", Value = new Guid("64f33a74-0342-e211-b55e-00155d00041e") };
conn.record2roleid = new Lookup() { name = "duplicate", Value = new Guid("64f33a74-0342-e211-b55e-00155d00041e") };
list.Add(new LookupProperty(){Name = "record1id", Value = lookup});
list.Add(new LookupProperty(){Name = "record2id", Value = lookup2});
list.Add(new LookupProperty(){Name = "record1roleid", Value = conn.record1roleid});
list.Add(new LookupProperty() { Name = "record2roleid", Value = conn.record2roleid });
I've tried tracing (which did not help), and in the eventviewer I get an error, but there is no helpful information.
I'm dying here! Please help... :-)
I think its because you are doing:
conn.record1roleid = new Lookup() { name = "duplicate", Value = new Guid("64f33a74-0342-e211-b55e-00155d00041e") };
name should be the name of an entity, e.g. contact, lead, incident. In this case I believe you should be using: connectionrole.
conn.record1roleid = new Lookup() { name = "connectionrole", Value = new Guid("64f33a74-0342-e211-b55e-00155d00041e") };
I would suggest having at Sample: Create a Connection (Early Bound).
Add type for the entity to lookup
Lookup lookup2 = new Lookup();
lookup2.Value = customers[j].ID.Value.Value;
lookup2.name = EntityName.lead.ToString();
**lookup2.type = "lead";**

Subsonic 3 Save() then Update()?

I need to get the primary key for a row and then insert it into one of the other columns in a string.
So I've tried to do it something like this:
newsObj = new news();
newsObj.name = "test"
newsObj.Save();
newsObj.url = String.Format("blah.aspx?p={0}",newsObj.col_id);
newsObj.Save();
But it doesn't treat it as the same data object so newsObj.col_id always comes back as a zero. Is there another way of doing this? I tried this on another page and to get it to work I had to set newsObj.SetIsLoaded(true);
This is the actual block of code:
page p;
if (pageId > 0)
p = new page(ps => ps.page_id == pageId);
else
p = new page();
if (publish)
p.page_published = 1;
if (User.IsInRole("administrator"))
p.page_approved = 1;
p.page_section = staticParent.page_section;
p.page_name = PageName.Text;
p.page_parent = parentPageId;
p.page_last_modified_date = DateTime.Now;
p.page_last_modified_by = (Guid)Membership.GetUser().ProviderUserKey;
p.Add();
string urlString = String.Empty;
if (parentPageId > 0)
{
urlString = Regex.Replace(staticParent.page_url, "(.aspx).*$", "$1"); // We just want the static page URL (blah.aspx)
p.page_url = String.Format("{0}?p={1}", urlString, p.page_id);
}
p.Save();
If I hover the p.Save(); I can see the correct values in the object but the DB is never updated and there is no exception.
Thanks!
I faced the same problem with that :
po oPo = new po();
oPo.name ="test";
oPo.save(); //till now it works.
oPo.name = "test2";
oPo.save(); //not really working, it's not saving the data since isLoaded is set to false
and the columns are not considered dirty.
it's a bug in the ActiveRecord.tt for version 3.0.0.3.
In the method public void Add(IDataProvider provider)
immediately after SetIsNew(false);
there should be : SetIsLoaded(true);
the reason why the save is not working the second time is because the object can't get dirty if it is not loaded. By adding the SetIsLoaded(true) in the ActiveRecord.tt, when you are going to do run custom tool, it's gonna regenerate the .cs perfectly.