I'm attempting to process creit cards through PayPal and keep getting this weird error:
{"name":"VALIDATION_ERROR","details":[{"field":"transactions[0].amount","issue":"Transaction
amount details (subtotal, tax, shipping) must add up to specified
amount total"}],"message":"Invalid request - see
details","information_link":"https://developer.paypal.com/webapps/developer/docs/api/#VALIDATION_ERROR","debug_id":"6e2cef39d556a"}
Here's the method I'm using:
public ActionResult PaymentWithCreditCard(PayWithCCViewModel model)
{
var cart = ShoppingCart.GetCart(this.HttpContext);
var cartItems = cart.GetCartItems();
List<Item> orderItems = new List<Item>();
foreach (var cartItem in cartItems)
{
var item = new Item();
item.name = cartItem.Product.ProductName;
item.currency = "USD";
item.price = cartItem.ProductPrice.ToString();
item.quantity = cartItem.ProductQuantity.ToString();
orderItems.Add(item);
}
ItemList itemList = new ItemList();
itemList.items = orderItems;
//Address for the payment
Address billingAddress = new Address();
billingAddress.city = model.BillingCity;
billingAddress.country_code = "US";
billingAddress.line1 = model.BillingAddressLine1;
billingAddress.line2 = model.BillingAddressLine2;
billingAddress.postal_code = model.BillingPostalCode;
billingAddress.state = model.BillingState;
//Now Create an object of credit card and add above details to it
CreditCard card = new CreditCard();
card.billing_address = billingAddress;
card.cvv2 = model.CVV2;
card.expire_month = model.ExpirationMonth;
card.expire_year = model.ExpirationYear;
card.first_name = model.FirstName;
card.last_name = model.LastName;
card.number = model.Number;
card.type = model.CardType.ToString();
var subTotal = cart.GetTotal();
var tax = Convert.ToDouble(subTotal) * Convert.ToDouble(.076);
var total = Convert.ToDouble(subTotal) + tax;
// Specify details of your payment amount.
Details details = new Details();
details.shipping = "3";
details.subtotal = subTotal.ToString();
details.tax = tax.ToString();
// Specify your total payment amount and assign the details object
Amount amount = new Amount();
amount.currency = "USD";
// Total = shipping tax + subtotal.
amount.total = total.ToString();
amount.details = details;
// Now make a trasaction object and assign the Amount object
Transaction transaction = new Transaction();
transaction.amount = amount;
transaction.description = "Payment to AccessorizeForLess.net";
transaction.item_list = itemList;
transaction.invoice_number = cart.GetCartId(this.HttpContext);
// Now, we have to make a list of trasaction and add the trasactions object
// to this list. You can create one or more object as per your requirements
List<Transaction> transactions = new List<Transaction>();
transactions.Add(transaction);
// Now we need to specify the FundingInstrument of the Payer
// for credit card payments, set the CreditCard which we made above
FundingInstrument fundInstrument = new FundingInstrument();
fundInstrument.credit_card = card;
// The Payment creation API requires a list of FundingIntrument
List<FundingInstrument> fundingInstrumentList = new List<FundingInstrument>();
fundingInstrumentList.Add(fundInstrument);
// Now create Payer object and assign the fundinginstrument list to the object
Payer payr = new Payer();
payr.funding_instruments = fundingInstrumentList;
payr.payment_method = "credit_card";
// finally create the payment object and assign the payer object & transaction list to it
Payment pymnt = new Payment();
pymnt.intent = "sale";
pymnt.payer = payr;
pymnt.transactions = transactions;
try
{
//getting context from the paypal, basically we are sending the clientID and clientSecret key in this function
//to the get the context from the paypal API to make the payment for which we have created the object above.
// Basically, apiContext has a accesstoken which is sent by the paypal to authenticate the payment to facilitator account. An access token could be an alphanumeric string
APIContext context = PayPalModel.GetAPIContext();
// Create is a Payment class function which actually sends the payment details to the paypal API for the payment. The function is passed with the ApiContext which we received above.
Payment payment = pymnt.Create(context);
//if the createdPayment.State is "approved" it means the payment was successfull else not
if (payment.state.ToLower() != "approved")
{
return View("FailureView");
}
}
catch (PayPalException ex)
{
Logger.Log("Error: " + ex.Message);
return View("FailureView");
}
return View("SuccessView");
}
I've stepped through the code and the total, tax and shipping seem to be correct, anyone have issues when dealing with PayPal before that could led me t a solution?
I forgot to add shipping to the total, now I get an approval
Related
I'm trying add this transaction named placeOrder i want to add a Customer participant
before creating Order asset and map its relationship with the Order asset while processing this transaction. But I'm getting customer not defined error. Can anybody help? Thanks.
My models
namespace org.isn.customer
participant Customer identified by email {
o String firstName
o String lastName
o String email
o String password
}
enum Status{
o ACTIVE
o OFF_THE_ROAD
}
asset Vehicle identified by serial {
o String brand
o String model
o String color
o Status status
o Double price
o String serial
}
asset Order identified by orderId{
o String orderId
o Vehicle item
--> Customer customer
}
transaction PlaceOrder {
o String orderId
--> Vehicle item
o Customer customer
}
script.js
/**
* #param {org.isn.shop.PlaceOrder}orderRequest
* #transaction
*/
async function placeOrder(orderRequest){
const factory = getFactory();
const customerRegistry = await getParticipantRegistry("org.isn.customer.Customer");
const customerExists = await customerRegistry.exists(orderRequest.customer.email);
if(!customerExists){
const customer = factory.newResource("org.isn.customer","Customer",orderRequest.customer.email);
customer.firstName = orderRequest.customer.firstName;
customer.lastName = orderRequest.customer.lastName;
customer.email = orderRequest.customer.email;
customer.password = orderRequest.customer.password;
await customerRegistry.add(customer);
}else{
const customer = await customerRegistry.get(orderRequest.customer.email);
}
const order = await factory.newResource("org.isn.shop","Order",orderRequest.orderId);
order.customer = customer.getIdentifier();
order.item = orderRequest.item;
const orderRegistry = await getAssetRegistry("org.isn.shop.Order");
await orderRegistry.add(order);
const PlaceOrderEvent = factory.newEvent("org.isn.shop","PlaceOrderEvent");
placeOrderEvent.order = order;
emit(placeOrderEvent);
}
o Customer customer needs to become --> Customer customer then you will be able to reference orderRequest.customer.firstName etc also not sure you need order.customer = customer.getIdentifier(); might need to become order.customer.email = customer.getIdentifier();
The following version of the Model and the JS will work for a new and existing customer:
namespace org.isn.customer
participant Customer identified by email {
o String firstName
o String lastName
o String email
o String password
}
enum Status{
o ACTIVE
o OFF_THE_ROAD
}
asset Vehicle identified by serial {
o String brand
o String model
o String color
o Status status
o Double price
o String serial
}
asset Order identified by orderId{
o String orderId
--> Vehicle item
--> Customer customer
}
transaction PlaceOrder {
o String orderId
--> Vehicle item
o Customer customer
}
/**
* #param {org.isn.customer.PlaceOrder}orderRequest
* #transaction
*/
async function placeOrder(orderRequest){
const factory = getFactory();
const customerRegistry = await getParticipantRegistry("org.isn.customer.Customer");
const customerExists = await customerRegistry.exists(orderRequest.customer.email);
if(!customerExists){
var customer = factory.newResource("org.isn.customer","Customer",orderRequest.customer.email);
customer.firstName = orderRequest.customer.firstName;
customer.lastName = orderRequest.customer.lastName;
customer.email = orderRequest.customer.email;
customer.password = orderRequest.customer.password;
await customerRegistry.add(customer);
}else{
var customer = await customerRegistry.get(orderRequest.customer.email);
}
const order = await factory.newResource("org.isn.customer","Order",orderRequest.orderId);
order.customer = factory.newRelationship("org.isn.customer","Customer",customer.getIdentifier());
order.item = orderRequest.item;
const orderRegistry = await getAssetRegistry("org.isn.customer.Order");
await orderRegistry.add(order);
}
Please note the following:
In the Order asset I have changed the o Vehicle to be --> Vehicle item to match up with the Transaction.
I have also used var customer in both the if and else code.
(To make mine work I had to use the same namespace, but perhaps you had separate .cto files)
Basically I am trying to get pagination working when requesting entities of azure table storage. i.e. Press next button gets the next 10 entities & Press previous button gets the previous 10 entities. A relatively close example Gaurav Mantri's Answer. But my question is how do I get the nextPartitionKey and nextRowKey from a HTML button attribute and store in to a array/list in order to keep track of current page so I can get the next/previous items?Code example would be very appreciated.
Thanks!
This is something I have right now which gets a range of data based on pageNumber request
private async Task<List<UserInfo>> queryPage(CloudTable peopleTable, string item, int pageNumber)
{
// Construct the query operation for all customer entities
TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, item));
// Print the fields for each customer.
TableContinuationToken token = null;
//TodoItem data = new TodoItem();
List<UserInfo> data = new List<UserInfo>();
do
{
TableQuerySegment<CustomerEntity> resultSegment = await peopleTable.ExecuteQuerySegmentedAsync(query, token);
token = resultSegment.ContinuationToken;
foreach (CustomerEntity entity in resultSegment.Results)
{
data.Add(new UserInfo
{
// add data
});
}
} while (token != null);
//get a subset of all entity
List<UserInfo> sublist = data.GetRange(0, pageNumber);
return sublist;
}
Managed to solved the problem under Gaurav's help.
Here is the code, not perfect but works.
private async Task<List<UserInfo>> queryPage(CloudTable peopleTable, string item, string NextPartitionKey , string NextRowKey, int itemNumber)
{
// Construct the query operation for all customer entities
TableQuery<CustomerEntity> query = new TableQuery<CustomerEntity>().Where(TableQuery.GenerateFilterCondition("PartitionKey", QueryComparisons.Equal, item)).Take(itemNumber);
// Print the fields for each customer.
List<UserInfo> data = new List<UserInfo>();
Tabletoken.NextPartitionKey = NextPartitionKey;
Tabletoken.NextRowKey = NextRowKey;
TableQuerySegment<CustomerEntity> resultSegment = await peopleTable.ExecuteQuerySegmentedAsync(query, Tabletoken);
Tabletoken = resultSegment.ContinuationToken;
foreach (CustomerEntity entity in resultSegment.Results)
{
data.Add(new UserInfo
{
//add data
});
}
return data;
}
private TableContinuationToken Tabletoken = new TableContinuationToken();
and declare it use a tuple.
Tuple<List<UserInfo>, string, string > tuple =
new Tuple<List<UserInfo>, string, string>(data, Tabletoken.NextPartitionKey, Tabletoken.NextRowKey);
I have used SOAP API to create Embedded signing. I am using template (CreateEnvelopeFromTemplates) to create envelope. I have added a payment field on template which works fine if I send envelope request from docusign website. I get a popup to enter payment information. BUT when I am sending the same template from API then Payment functionality is not working. Payment field is appearing as number.
screenshot
Here is my code
public class DS_Recipe_Signer_View_Controller {
// Embedded signing of an envelope
// Copyright (c) 2016 DocuSign, Inc.
// LICENSE: The MIT License, see https://opensource.org/licenses/MIT
// SETTINGS
// Private static string integration_key = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
// Private static string account_id = 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx';
Private static string integration_key = 'XXXXXXXXXX-98333677e8bd';
Private static string account_id = 'XXXXXXXXXXX-5f66c17b7f9f';
// NOTE: You MUST use the long form of the account id. It's has 32 digits
// with 4 dashes (xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx).
// This version of the account id is shown in the APIs and Connects section
// of your DocuSign Administration tool
Public string signer_email {get;set;} // Required
Public string signer_name {get;set;} // Required
Public string email_message {get;set;} // Required
Public string signer_user_id {get;set;} // Required for embedded signing
Public string signer_return_url {get;set;} // Required. Where DS redirects to after the signing ceremony
Public string output {get;set;}
Public string envelope_id {get;set;}
Public string signer_view_url {get;set;} // Redirect to this url
Public string error_code {get;set;} // Null means no error
Public string error_message {get;set;}
// Using Legacy authentication via an SFDC Named Credential
Private static string ds_server = 'callout:DocuSign_Legacy_Demo/api/3.0/dsapi.asmx';
// If you choose to not use a named credential:
//Private static string ds_server = 'https://requestb.in/119qunn1';
//Private static string ds_server ='https://demo.docusign.net/api/3.0/dsapi.asmx';
Private static string trace_value = 'SFDC_002_SOAP_embedded_signing'; // Used for tracing API calls
Private static string trace_key = 'X-ray';
Private DocuSignTK.APIServiceSoap api_sender = new DocuSignTK.APIServiceSoap();
Public DS_Recipe_Signer_View_Controller(){}
Public void send(){
configure_sender();
send_envelope();
embedded_signing();
if (no_error()) {
output = '<p>The envelope was sent, Envelope ID: ' + envelope_id + '</p>';
output += '<p></p><p>Signer: ' + signer_name + ' <' + signer_email + '></p>';
output += '<p><b>To sign the envelope, redirect the user to the <a href = "' +
signer_view_url + '" target="_blank">DocuSign Signing Ceremony</a></b></p>';
output += '<p>The redirect address is ' + signer_view_url + '</p>';
output += '<p><b>Note:</b> the Signing Ceremony url can only be used for a couple of minutes after ' +
'it has been created. Do NOT store the url for later use. Instead, ' +
'generate the URL immediately before you redirect the user\'s browser.</p>';
output += '<p>After the signer has completed the signing ceremony, his ' +
'browser will be redirected back to your app with some query fields added. Example: </p>' +
'<p>http://www.foo.com/?event=signing_complete</p>';
} else {
output = '<h3>Problem</h3><p>' + error_message + '</p>';
}
}
Private void configure_sender(){
api_sender.endpoint_x = ds_server;
api_sender.inputHttpHeaders_x = new Map<String, String>();
String auth = '<DocuSignCredentials><Username>{!$Credential.Username}</Username>'
+ '<Password>{!$Credential.Password}</Password>'
+ '<IntegratorKey>' + integration_key + '</IntegratorKey></DocuSignCredentials>';
api_sender.inputHttpHeaders_x.put('X-DocuSign-Authentication', auth);
api_sender.inputHttpHeaders_x.put(trace_key, trace_value);
}
Private void embedded_signing() {
// Obtains the embedded Signing Ceremony URL for an envelope's recipient (the signer).
// To use embedded signing:
// 1. The signer must have been added to the envelope as a "captive signer"
// 2. You need the following values:
// 1. EnvelopeID
// 2. Signer's Email that was provided when the signer was added to the envelope.
// 3. Signer's name (UserName field)
// 4. The Signer's User ID (client id) within your app. Must uniquely identify the signer.
// 3. You also need to create an "Assertion" object where you provide information on how
// your app authenticated the signer. This information is stored by DocuSign so you can
// later use the data in case of a dispute.
// Incoming variables used:
// envelope_id, signer_user_id, signer_email, signer_name
// Maintaining state: when DocuSign redirects back to your app after the signing ceremony
// ended, how does your app know what is going on? You can include additional query parameters
// in the signer_return_url that you supply. Eg the recipient ID, envelope ID, etc.
// You can include your app's sessionID. You can use the cookie system to store either
// specific information or your stack's session id for your app.
// Step 1. Create the assertion
DocuSignTK.RequestRecipientTokenAuthenticationAssertion assertion =
new DocuSignTK.RequestRecipientTokenAuthenticationAssertion();
assertion.AssertionID = '1'; // A unique identifier of the authentication
// event executed by your application.
assertion.AuthenticationInstant = Datetime.now(); // The date/time that the end-user was authenticated.
assertion.AuthenticationMethod = 'Password'; // How did your app authenticate the signer?
// Options: Password, Email, PaperDocuments, HTTPBasicAuth, SSLMutualAuth, X509Certificate, Kerberos,
// SingleSignOn_CASiteminder, SingleSignOn_InfoCard, SingleSignOn_MicrosoftActiveDirectory, SingleSignOn_Passport,
// SingleSignOn_SAML, SingleSignOn_Other, Smartcard, RSASecureID, Biometric, None, KnowledgeBasedAuth
assertion.SecurityDomain = 'DS_Recipe_Signer_View_Controller'; // The "domain" (app, sso system, etc)
// to which the user authenticated
// Step 2. Create the redirect URLs for the different outcomes of the Signing Ceremony
DocuSignTK.RequestRecipientTokenClientURLs urls = new DocuSignTK.RequestRecipientTokenClientURLs();
String return_url_base = signer_return_url;
// The supplied url may already include one or more query parameters. In that case, we're appending
// one more query parameters. Otherwiser, we're adding the first set of query parameters.
// Look for a ? to see if the url already includes query parameters
If (return_url_base.contains('?')) {
return_url_base += '&event=';
} Else {
return_url_base += '?event=';
}
urls.OnSigningComplete = return_url_base + 'signing_complete';
urls.OnViewingComplete = return_url_base + 'viewing_complete';
urls.OnCancel = return_url_base + 'cancel';
urls.OnDecline = return_url_base + 'decline';
urls.OnSessionTimeout = return_url_base + 'session_timeout';
urls.OnTTLExpired = return_url_base + 'ttl_expired';
urls.OnException = return_url_base + 'exception';
urls.OnAccessCodeFailed = return_url_base + 'failed_access_code';
urls.OnIdCheckFailed = return_url_base + 'failed_id_check';
urls.OnFaxPending = return_url_base + 'fax_pending';
// Step 3. Make the call
try {
signer_view_url = api_sender.RequestRecipientToken(
envelope_id, signer_user_id, signer_name, signer_email, assertion, urls);
System.debug('Received signer_view_url: = ' + signer_view_url);
} catch ( CalloutException e) {
System.debug('Exception - ' + e );
error_code = 'Problem: ' + e;
error_message = error_code;
}
}
Private void send_envelope() {
// Sends an envelope. The first signer is "captive," so he can sign embedded
// Check input
if (String.isBlank(signer_email) || String.isBlank(signer_name) || !signer_email.contains('#')) {
error_message = 'Please fill in the email and name fields';
error_code = 'INPUT_PROBLEM';
return;
}
// Check configuration
if (integration_key == 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx' ||
account_id == 'xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx') {
error_message = 'Please configure the Apex class DS_Recipe_Send_Env_Email_Controller with your integration key and account id.';
error_code = 'CONFIGURATION_PROBLEM';
return;
}
DocuSignTK.Recipient recipient = new DocuSignTK.Recipient();
recipient.Email = signer_email;
recipient.UserName = signer_name;
recipient.ID = 1;
recipient.Type_x = 'Signer';
recipient.RoutingOrder = 1;
recipient.RoleName = 'Signer';
// We want this signer to be "captive" so we can use embedded signing with him
recipient.CaptiveInfo = new DocuSignTK.RecipientCaptiveInfo();
recipient.CaptiveInfo.ClientUserID = signer_user_id; // Must uniquely identify the
DocuSignTK.ArrayOfRecipient1 recipients = new DocuSignTK.ArrayOfRecipient1();
recipients.Recipient = new DocuSignTK.Recipient[1];
recipients.Recipient[0] = recipient;
// Create the template reference from a server-side template ID
DocuSignTK.TemplateReference templateReference = new DocuSignTK.TemplateReference();
templateReference.Template = '37041580-9d59-4b41-a7c4-7c9bfa3b26c8';//'d0d80082-612b-4a04-b2a1-0672eb720491';
templateReference.TemplateLocation = 'Server';
//templateReference.Sequence = 1;
DocuSignTK.ArrayOfTemplateReferenceRoleAssignment Roles = new DocuSignTK.ArrayOfTemplateReferenceRoleAssignment();
Roles.RoleAssignment = new DocuSignTK.TemplateReferenceRoleAssignment[1];
DocuSignTK.TemplateReferenceRoleAssignment role = new DocuSignTK.TemplateReferenceRoleAssignment();
role.RoleName = 'Signer';
role.RecipientID = 1;
Roles.RoleAssignment[0] = role;
templateReference.RoleAssignments = Roles;
// Construct the envelope information
DocuSignTK.EnvelopeInformation envelopeInfo = new DocuSignTK.EnvelopeInformation();
envelopeInfo.AccountId = account_Id;
envelopeInfo.Subject = 'Subject';
envelopeInfo.EmailBlurb = 'Email content';
DocuSignTK.TemplateReferenceFieldDataDataValue fd2 = new
DocuSignTK.TemplateReferenceFieldDataDataValue();
fd2.TabLabel = 'name';
fd2.Value = 'recipient.UserName';
DocuSignTK.TemplateReferenceFieldDataDataValue fd3 = new
DocuSignTK.TemplateReferenceFieldDataDataValue();
fd3.TabLabel = 'company';
fd3.Value = 'company';
templateReference.FieldData = new DocuSignTK.TemplateReferenceFieldData();
templateReference.FieldData.DataValues = new
DocuSignTK.ArrayOfTemplateReferenceFieldDataDataValue();
templateReference.FieldData.DataValues.DataValue = new
DocuSignTK.TemplateReferenceFieldDataDataValue[2];
templateReference.FieldData.DataValues.DataValue[0] = fd2;
templateReference.FieldData.DataValues.DataValue[1] = fd3;
// Make the call
try {
//DocuSignTK.EnvelopeStatus result = api_sender.CreateAndSendEnvelope(envelope);
// Create draft with all the template information
DocuSignTK.ArrayOfTemplateReference TemplateReferenceArray = new DocuSignTK.ArrayOfTemplateReference();
TemplateReferenceArray.TemplateReference = new DocuSignTK.TemplateReference[1];
TemplateReferenceArray.TemplateReference[0] = templateReference;
DocuSignTK.EnvelopeStatus result = api_sender.CreateEnvelopeFromTemplates( TemplateReferenceArray, recipients, envelopeInfo, true);
envelope_id = result.EnvelopeID;
System.debug('Returned successfully, envelope_id = ' + envelope_id );
} catch ( CalloutException e) {
System.debug('Exception - ' + e );
error_code = 'Problem: ' + e;
error_message = error_code;
}
}
Private Boolean no_error() {
return (String.isEmpty(error_code));
}
}
DocuSign Website uses RESTAPI to send Payment details in an envelope. Payment related APIs are not available in SOAP calls, please try using REST API for payment related calls.
Using the Dynamics GP Web Service API on GP 2013, how do I apply payments to a Sales Invoice? I receive the error in the subject line. Here is my code:
static void CreateInvoice()
{
CompanyKey companyKey;
Context context;
SalesInvoice salesInvoice;
SalesDocumentTypeKey salesInvoiceType;
CustomerKey customerKey;
BatchKey batchKey;
SalesInvoiceLine salesInvoiceLine;
ItemKey invoiceItem;
Quantity invoiceCount;
Policy salesInvoiceCreatePolicy;
// Create an instance of the service
DynamicsGP wsDynamicsGP = new DynamicsGP();
// Be sure the default credentials are used
wsDynamicsGP.UseDefaultCredentials = true;
// Create a context with which to call the service
context = new Context();
// Specify which company to use (sample company)
companyKey = new CompanyKey();
companyKey.Id = (-1);
// Set up the context object
context.OrganizationKey = (OrganizationKey)companyKey;
// Create a sales invoice object
salesInvoice = new SalesInvoice();
// Create a sales document type key for the sales invoice
salesInvoiceType = new SalesDocumentTypeKey();
salesInvoiceType.Type = SalesDocumentType.Invoice;
// Populate the document type key for the sales invoice
salesInvoice.DocumentTypeKey = salesInvoiceType;
// Create a customer key
customerKey = new CustomerKey();
customerKey.Id = "ADMINISTRATORGL";
// Set the customer key property of the sales invoice
salesInvoice.CustomerKey = customerKey;
// Create a batch key
batchKey = new BatchKey();
batchKey.Id = "SALES INVOICES";
// Set the batch key property of the sales invoice object
salesInvoice.BatchKey = batchKey;
// Create a sales invoice line to specify the invoiced item
salesInvoiceLine = new SalesInvoiceLine();
// Create an item key
invoiceItem = new ItemKey();
invoiceItem.Id = "ADI123";
// Set the item key property of the sales invoice line object
salesInvoiceLine.ItemKey = invoiceItem;
// Create a sales invoice quatity object
invoiceCount = new Quantity();
invoiceCount.Value = 2;
// Set the quantity of the sales invoice line object
salesInvoiceLine.Quantity = invoiceCount;
salesInvoiceLine.WarehouseKey = new WarehouseKey { Id = "NORTH" };
// Create an array of sales invoice lines
// Initialize the array with the sales invoice line object
SalesInvoiceLine[] invoiceLines = { salesInvoiceLine };
// Add the sales invoice line array to the sales line object
salesInvoice.Lines = invoiceLines;
//salesInvoice.LineTotalAmount = new MoneyAmount { Value = 399.96M };
salesInvoice.DepositAmount = new MoneyAmount { Value = 399.96M };
salesInvoice.PaymentAmount = new MoneyAmount { Value = 399.96M };
// Get the create policy for the sales invoice object
salesInvoiceCreatePolicy = wsDynamicsGP.GetPolicyByOperation("CreateSalesInvoice", context);
// Create the sales invoice
wsDynamicsGP.CreateSalesInvoice(salesInvoice, context, salesInvoiceCreatePolicy);
}
I had to create a customer and set the credit limit to unlimited.
//assign unlimited class
CustomerCreditLimit cc = new CustomerCreditLimit();
cc.Item = CreditLimitSpecialAmount.UnlimitedCredit;
customer.CreditLimit = cc;
My blog post has more details on the code:
http://www.jmawebtechnologies.com/company-blog/may-2013/appying-payments-to-sales-invoices-and-sales-order
I am using managed client side object model in sharepoint 2010. And I want to get loginaName of the AssignedTo user in Task list.
In server side object model I use SPFieldUserValue.User.LoginName to get this property but in client side object model FieldUserValue.User does not exists.
How can I resolve this situation ?
Thanks
Here is the code for that. I've taken an example of AssignedTo field from Task list. I hope that helps.
public static User GetUserFromAssignedToField(string siteUrl)
{
// create site context
ClientContext ctx = new ClientContext(siteUrl);
// create web object
Web web = ctx.Web;
ctx.Load(web);
// get Tasks list
List list = ctx.Web.Lists.GetByTitle("Tasks");
ctx.Load(list);
// get list item using Id e.g. updating first item in the list
ListItem targetListItem = list.GetItemById(1);
// Load only the assigned to field from the list item
ctx.Load(targetListItem,
item => item["AssignedTo"]);
ctx.ExecuteQuery();
// create and cast the FieldUserValue from the value
FieldUserValue fuv = (FieldUserValue)targetListItem["AssignedTo"];
Console.WriteLine("Request succeeded. \n\n");
Console.WriteLine("Retrieved user Id is: {0}", fuv.LookupId);
Console.WriteLine("Retrieved login name is: {0}", fuv.LookupValue);
User user = ctx.Web.EnsureUser(fuv.LookupValue);
ctx.Load(user);
ctx.ExecuteQuery();
// display the user's email address.
Consol.writeLine("User Email: " + user.Email);
return user;
}
The fuv.LookupValue may contain the display name, not the login name, so my suggestion is (assuming you have the FieldUserValue - fuv in code (as descibed by #ekhanna):
var userId = fuv.LookupId;
var user = ctx.Web.GetUserById(userId);
ctx.Load(user);
ctx.ExecuteQuery();
You get the column which as the FieldUserValue from the list, once you have that you use the lookup id value and then query against the Sites User Info List. In the example below I cache the results to prevent looking up the same id more than once since the query can be expensive.
private readonly Dictionary<int, string> userNameCache = new Dictionary<int, string>();
public string GetUserName(object user)
{
if (user == null)
{
return string.Empty;
}
var username = string.Empty;
var spUser = user as FieldUserValue;
if (spUser != null)
{
if (!userNameCache.TryGetValue(spUser.LookupId, out username))
{
var userInfoList = context.Web.SiteUserInfoList;
context.Load(userInfoList);
var query = new CamlQuery { ViewXml = "<View Scope='RecursiveAll'><Query><Where><Eq><FieldRef Name='ID' /><Value Type='int'>" + spUser.LookupId + "</Value></Eq></Where></Query></View>" };
var users = userInfoList.GetItems(query);
context.Load(users, items => items.Include(
item => item.Id,
item => item["Name"]));
if (context.TryExecuteQuery())
{
var principal = users.GetById(spUser.LookupId);
context.Load(principal);
context.ExecuteQuery()
username = principal["Name"] as string;
userNameCache.Add(spUser.LookupId, username);
}
}
}
return username;
}
Everything above worked for me, but instead of:
FieldUserValue fuv = (FieldUserValue)targetListItem["AssignedTo"];
I used:
FieldUserValue[] fuv = targetListItem["AssignedTo"] as FieldUserValue[];