I had to create my own Web Service Endpoint for Service Orders. Here is the WSDL: https://imagineersllc.acumatica.com/(W(7))/entity/PileraAPI/19.100.0122?wsdl&company=Imagineers%20LLC%20-%20Prototype I added Attributes to it following an example I found under Stock Items in the Default Endpoint.
I added attributes to the Service Order type and when I try to populate the attributes in my API they remain blank. The Service Order gets created just fine it just does not populate the attributes.
I've tried renaming the attributes and using the code vs the description in my code.
string sServiceOrderType = "MRO"; // Only type supported
string sCustomer = "1003";
string sBranchLocation = "PROPMGMT"; // Only location available
string sWorkflowStage = "ACKNOWLEDGED";
DateTime dDate = DateTime.Parse("7/1/2019");
string sExternalReference = "WO-2345";
string sDescription = "Service Order from Pilera API";
bool bOverride = true; // Used to make Contact and Address editable
string sCompanyName = "DSD Business Systems";
string sAttention = "John Wiles";
string sPhone = "(858) 550-5900";
string sEmail = "johnw#dsdinc.com";
string sAddressLine1 = "1225 Rosemarie Way";
string sAddressLine2 = "";
string sCity = "Chesapeake";
string sState = "VA";
string sPostalCode = "23322";
DateTime dPromisedDate = DateTime.Parse("7/21/2019");
string sSeverity = "Low";
string sPriority = "High";
string sComment = "Comment created by API";
bool bHold = true;
string sCategory = "GENERALREPAIR";
string sCommunity = "Deerfield Condominium Assoc.";
string sContact = "Annamma George";
string sContactPhone = "860-656-6603";
string sContactLocation = "268 Richard Street #1 Newington, CT 06111";
ServiceOrders ServiceOrdersToBeCreated = new ServiceOrders
{
ServiceOrderType = new StringValue { Value = sServiceOrderType },
Customer = new StringValue { Value = sCustomer },
BranchLocation = new StringValue { Value = sBranchLocation },
WorkflowStage = new StringValue { Value = sWorkflowStage },
Date = new DateTimeValue { Value = dDate },
ExternalReference = new StringValue { Value = sExternalReference },
Description = new StringValue { Value = sDescription },
Hold = new BooleanValue { Value = bHold },
PromisedDate = new DateTimeValue { Value = dPromisedDate },
Severity = new StringValue { Value = sSeverity },
Priority = new StringValue { Value = sPriority },
Category = new StringValue { Value = sCategory },
Override = new BooleanValue { Value = bOverride },
CompanyName = new StringValue { Value = sCompanyName },
Attention = new StringValue { Value = sAttention },
Phone = new StringValue { Value = sPhone },
Email = new StringValue { Value = sEmail },
AddressLine1 = new StringValue { Value = sAddressLine1 },
AddressLine2 = new StringValue { Value = sAddressLine2 },
City = new StringValue { Value = sCity },
State = new StringValue { Value = sState },
PostalCode = new StringValue { Value = sPostalCode },
Comment = new StringValue { Value = sComment },
Attributes = new[]
{
new AttributeValue
{
AttributeID = new StringValue { Value = "Community" },
Value = new StringValue { Value = sCommunity }
},
new AttributeValue
{
AttributeID = new StringValue { Value = "Contact" },
Value = new StringValue { Value = sContact }
},
new AttributeValue
{
AttributeID = new StringValue { Value = "Phone" },
Value = new StringValue { Value = sContactPhone }
},
new AttributeValue
{
AttributeID = new StringValue { Value = "Location" },
Value = new StringValue { Value = sContactLocation }
}
}
};
ServiceOrders newServiceOrder = (ServiceOrders)soapClient.Put(ServiceOrdersToBeCreated);
Service Order is created without attributes. No error messages received.
Here is what Support provided:
try
{
ServiceOrders newServiceOrder = (ServiceOrders)client.Put(ServiceOrdersToBeCreated);
List<AttributeValue> attrList = new List<AttributeValue>();
foreach (AttributeValue attrVal in newServiceOrder.Attributes)
{
AttributeValue attr = new AttributeValue();
attr.ID = attrVal.ID;
switch(attrVal.AttributeID.Value)
{
case "Community":
attr.Value = new StringValue { Value = sCommunity };
break;
case "Contact":
attr.Value = new StringValue { Value = sContact };
break;
case "Phone":
attr.Value = new StringValue { Value = sContactPhone };
break;
case "Location":
attr.Value = new StringValue { Value = sContactLocation };
break;
default:
Console.WriteLine("Attribute Not Found!");
break;
}
attrList.Add(attr);
}
newServiceOrder.Attributes = attrList.ToArray();
newServiceOrder = (ServiceOrders)client.Put(newServiceOrder);
}
Related
Good day
I am creating a SOAP contract base connection to Acumatica.
I am getting an error: "System.ArgumentNullException: Value cannot be null."
I am not sure why I am getting the error.
Here is my code
using (var soapClient = new DefaultSoapClient())
{
try
{
soapClient.Login();
InventoryReceipt NewinventoryReceipt = new InventoryReceipt
{
ReferenceNbr = new StringValue { Value = "<NEW>" },
Hold = new BooleanValue { Value = true },
Date = new DateTimeValue { Value = DateTime.Now },
PostPeriod = new StringValue { Value = DateTime.Now.ToString("DD-yyyy") },
TransferNbr = new StringValue { Value = "" },
//External Ref
Description = new StringValue { Value = "" },
Details = new InventoryReceiptDetail[]
{
new InventoryReceiptDetail
{
//branch
InventoryID = new StringValue{Value = "NIS777"},
WarehouseID = new StringValue{Value = "FBTZEST"},
Location = new StringValue {Value = "BULK"},
Qty = new DecimalValue{Value = 1},
UOM = new StringValue{Value = "PALLET"},
UnitCost = new DecimalValue{Value = 91},
ExtCost = new DecimalValue{Value = 91},
LotSerialNbr = new StringValue{Value = "PLN12345"},
ExpirationDate = new DateTimeValue{Value = DateTime.Now},
// ReasonCode
Description = new StringValue{Value = ""}
}
},
};
InventoryReceipt putInventoryReceipt = (InventoryReceipt)soapClient.Put(NewinventoryReceipt);
}
catch (Exception ex)
{
soapClient.Logout();
throw;
}
finally
{
soapClient.Logout();
}
soapClient.Logout();
}
Console.ReadLine();
}
Is there any way to see what is null or what I am missing to post this data?
Have you tried manually entering the data into the UI? The Validation on the web service should be the same as the UI, so you might get more info from the UI. You have a lot of dependent values here since you're referencing a specific Lot perhaps a value is missing. Other than that, you might try adding Project = X.
I created an extension :
SchemaExtension objExtDef = new SchemaExtension()
{
Description = "Extention to Store User Dates",
Id = "UserDates",
Properties = new List<ExtensionSchemaProperty>()
{
new ExtensionSchemaProperty() { Name = "CreateDate", Type = "DateTime" },
new ExtensionSchemaProperty() { Name = "PasswordChangeDate", Type = "DateTime" }
},
TargetTypes = new List<string>()
{
"User"
}
};
SchemaExtension schemaExtension = Task.Run(() => graphserviceClient.SchemaExtensions.Request().AddAsync(objExtDef)).Result;
Made it Available :
var schemaExtension = new SchemaExtension
{
Status = "Available",
};
var result = Task.Run(() => graphserviceClient.SchemaExtensions["extuce7u7qp_UserDates"].Request().UpdateAsync(schemaExtension)).Result;
Searched and confirmed that it is created and available :
var lstAllExtensions = Task.Run(() => graphserviceClient.SchemaExtensions.Request().Filter("id%20eq%20'extuce7u7qp_UserDates'").GetAsync()).Result;
Trying to add user along with additional data in that extension :
UserDatesExtension objUserDatesExtension = new UserDatesExtension();
objUserDatesExtension.CreateDate = DateTime.Today;
objUserDatesExtension.PasswordChangeDate = DateTime.Today;
dctExtensions.Add("extuce7u7qp_UserDates", objUserDatesExtension);
Microsoft.Graph.User objNewUser = new Microsoft.Graph.User
{
AccountEnabled = true,
DisplayName = string.Format("{0} {1}", objUser.FirstName, objUser.LastName),
MailNickname = "TestUC",
PasswordProfile = new PasswordProfile
{
Password = "testpass",
ForceChangePasswordNextSignIn = false
},
UserPrincipalName = string.Format("{0}#test.onmicrosoft.com", objUser.UserIdentity),
GivenName = objUser.FirstName,
Surname = objUser.LastName,
City = objUser.Address != null ? objUser.Address.City : null,
Country = objUser.Address != null ? objUser.Address.Country : null,
State = objUser.Address != null ? objUser.Address.Region : null,
MobilePhone = !string.IsNullOrEmpty(objUser.Phone) ? objUser.Phone : null,
PreferredLanguage = objUser.PreferredLanguage,
AdditionalData = dctExtensions
};
Microsoft.Graph.User objCreatedUser = Task.Run(() => graphserviceClient.Users.Request().AddAsync(objNewUser)).Result;
That is throwing exception that the extension ID is not valid.
This was working earlier.
UserDatesExtension Class, used above :
[JsonObject(MemberSerialization = MemberSerialization.OptIn)]
public class UserDatesExtension
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "CreateDate", Required = Newtonsoft.Json.Required.Default)]
public DateTime CreateDate { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore, PropertyName = "PasswordChangeDate", Required = Newtonsoft.Json.Required.Default)]
public DateTime PasswordChangeDate { get; set; }
}
I'm using Acumatica's contract based API to create sales order from an ASP.net application. I need to update the "Shipping Terms" field under the "Shipping Settings" tab on a Sales Order when I create it (see below), but I can not find the property to use on the ASP.net objects that are provided through the contract based API. How would I accomplish this?
Here is my current code for how I create the sales order:
using (DefaultSoapClient client = new DefaultSoapClient(binding, address))
{
//Sales order data
string customerID = "CUST1234;
string orderDescription = "Automated Order";
string customerOrder = "TEST";
var orderDetails = new List<SalesOrderDetail>();
foreach(var lineItem in order.line_items)
{
orderDetails.Add(new SalesOrderDetail {
InventoryID = new StringValue { Value = lineItem.sku },
Quantity = new DecimalValue { Value = lineItem.quantity },
UnitPrice = new DecimalValue { Value = Decimal.Parse(lineItem.price) }, //TODO this should only be done for MHR owned sites
UOM = new StringValue { Value = "EACH" },
});
}
//Specify the values of a new sales order
SalesOrder orderToBeCreated = new SalesOrder
{
OrderType = new StringValue { Value = "SO" },
CustomerID = new StringValue { Value = customerID },
Description = new StringValue { Value = orderDescription },
CustomerOrder = new StringValue { Value = customerOrder },
ExternalReference = new StringValue { Value = order.order_number.ToString() },
Details = orderDetails.ToArray<SalesOrderDetail>(),
ShippingAddressOverride = new BooleanValue { Value = true },
ShippingContactOverride = new BooleanValue { Value = true },
ShippingContact = new Contact()
{
DisplayName = new StringValue { Value = order.shipping_address.first_name + " " + order.shipping_address.last_name },
FirstName = new StringValue { Value = order.shipping_address.first_name },
LastName = new StringValue { Value = order.shipping_address.last_name },
Address = new Address()
{
AddressLine1 = new StringValue { Value = order.shipping_address.address_1 },
AddressLine2 = new StringValue { Value = order.shipping_address.address_2 },
City = new StringValue { Value = order.shipping_address.city },
State = new StringValue { Value = order.shipping_address.state },
Country = new StringValue { Value = order.shipping_address.country },
PostalCode = new StringValue { Value = order.shipping_address.postcode }
}
},
};
client.Login(_acumaticaUid, _acumaticaPwd, _acumaticaCompany, null, null);
//Create a sales order with the specified values
try
{
SalesOrder newOrder = (SalesOrder)await client.PutAsync(orderToBeCreated);
client.Logout();
return newOrder;
}
catch (Exception e)
{
//order addition to Acumatica failed, update the order status in Woo Commerce
client.Logout();
Console.WriteLine("Acumatica could not add specified entity: " + e);
return null;
}
}
UPDATE:
Based on PatrickChen's comment, I created a new web service endpoint in Acumatica "SalesOrderCustom", where I used all of the default fields and then added "ShippingTerms" to the list as well. I then imported that web service into my .net project (with some headache due to this issue) and was able to use the service to GET the sales order I wanted to add shipping terms to, and try to update it. The code executes ok, but after the PUT operation is done, the object is NOT updated in Acumatica and the ShippingTerms property is returned as NULL. What am I doing wrong? Code below:
public async Task<SalesOrderCustom> UpdateShippingTerms(string customerOrder, string originStore, string shippingSpeed)
{
var binding = CreateNewBinding(true, 655360000, 655360000);
var address = new EndpointAddress(ConfigurationManager.AppSettings["AcumaticaCustomUrl"]);
var soToBeFound = new SalesOrderCustom()
{
OrderType = new StringSearch { Value = "SO" },
CustomerOrder = new StringSearch { Value = customerOrder }
};
using (DefaultSoapClient client = new DefaultSoapClient(binding, address))
{
client.Login(_acumaticaUid, _acumaticaPwd, _acumaticaCompany, null, null);
try
{
var soToBeUpdated = (SalesOrderCustom) await client.GetAsync(soToBeFound);
soToBeUpdated.ShippingTerms = new StringValue { Value = "USPS 1 CLS" };
var updatedOrder = (SalesOrderCustom)await client.PutAsync(soToBeUpdated);
//ShippingTerms is still NULL on returned object even after updating the object!!! WHY???
client.Logout();
return updatedOrder;
}
catch (Exception e)
{
client.Logout();
Console.WriteLine("Acumatica could not find specified entity: " + e);
return null;
}
}
}
Starting Acumatica 6, it's possible to update any field, not included into the Default endpoint. This feature is only available for endpoints implementing system contract of the 2nd version:
Below is the sample showing how to change Shipping Terms for a Sales Order with the Default Contract-Based endpoint by working with the CustomFields collection:
using (var client = new DefaultSoapClient())
{
client.Login("admin", "123", null, null, null);
try
{
var order = new SalesOrder()
{
OrderType = new StringSearch { Value = "SO" },
OrderNbr = new StringSearch { Value = "SO003729" }
};
order = client.Get(order) as SalesOrder;
order.CustomFields = new CustomField[]
{
new CustomStringField
{
fieldName = "ShipTermsID",
viewName = "CurrentDocument",
Value = new StringValue { Value = "FLATRATE2" }
}
};
client.Put(order);
}
finally
{
client.Logout();
}
}
No issues also noticed on my end when updating Sales Order Shipping Terms with the extended Default Contract-Based endpoint on a brand new Acumatica ERP 6.1 instance:
using (var client = new DefaultSoapClient())
{
client.Login("admin", "123", null, null, null);
try
{
var order = new SalesOrder()
{
OrderType = new StringSearch { Value = "SO" },
OrderNbr = new StringSearch { Value = "SO003729" }
};
order = client.Get(order) as SalesOrder;
order.ShippingTerms = new StringValue { Value = "FLATRATE1" };
client.Put(order);
}
finally
{
client.Logout();
}
}
For reference, adding screenshot of my extended Default endpoint used to update Shipping Terms in the SalesOrder entity:
I was able to add Shipping Terms when I created a new 6.0 endpoint. The default endpoint that ships with Acumatica is not extendable.
We are trying to add PO lines to the receipt document using 'ADD PO LINE' smartpanel. Below is the code, but it always chooses the first 2 lines instead of the keys specified in the command.
//select lines from smart panel
foreach (POReceiptLine line in POReceiptlines.OrderBy(x => x.LineNum))
{
AcumaticaInterface.apitest.Command[] Docline = new AcumaticaInterface.apitest.Command[]
{
new Key
{
ObjectName = PORcptSchema.AddPurchaseOrderLine.OrderNbr.ObjectName,
FieldName = PORcptSchema.AddPurchaseOrderLine.OrderNbr.FieldName,
Value = "='" + line.BaseDocNum + "'",
Commit =true
},
new Key
{
ObjectName = PORcptSchema.AddPurchaseOrderLine.LineNbr.ObjectName,
FieldName = PORcptSchema.AddPurchaseOrderLine.LineNbr.FieldName,
Value = "='" + line.BaseLineNum + "'",
Commit =true
},
new Value
{
Value = "True",
LinkedCommand = PORcptSchema.AddPurchaseOrderLine.Selected,
Commit = true
}
};
Document = Document.Concat(Docline).ToArray();
}
// Add PO line and retrieve back the added lines.
var addPOLine = new Command[]
{
addPOLineWithCommit,
////get back the added lines in the grid
PORcptSchema.DocumentDetails.POOrderNbr,
PORcptSchema.DocumentDetails.POLineNbr
};
Document = Document.Concat(addPOLine).ToArray();
var receiptLines = context.PO302000Submit(Document);
We are trying to select the lines of order Nbr '000014' [Line Nbr(1,2)], but the lines added are of Order Nbr '000012' [Line Nbr(1,2)]. Please assist.
The solution is to clear LinkedCommand set by default for the AddPurchaseOrderLine.Selected field:
receiptSchema.AddPurchaseOrderLine.Selected.LinkedCommand = null;
Below is the complete SOAP request, that allows to locate and select records on the Add Purchase Order Line popup via the Screen-Based API:
Content receiptSchema = context.GetSchema();
receiptSchema.Actions.AddPOOrderLine.Commit = true;
receiptSchema.Actions.AddPOOrderLine2.Commit = true;
receiptSchema.AddPurchaseOrderLine.Selected.LinkedCommand = null;
var commands = new Command[]
{
new Value
{
Value = "Receipt",
LinkedCommand = receiptSchema.DocumentSummary.Type
},
new Value
{
Value = "PR000416",
LinkedCommand = receiptSchema.DocumentSummary.ReceiptNbr
},
new Value
{
Value = "OK",
LinkedCommand = receiptSchema.AddPurchaseOrderLine.ServiceCommands.DialogAnswer,
Commit = true
},
receiptSchema.Actions.AddPOOrderLine,
new Key
{
ObjectName = receiptSchema.AddPurchaseOrderLine.OrderNbr.ObjectName,
FieldName = receiptSchema.AddPurchaseOrderLine.OrderNbr.FieldName,
Value = "='PO000483'"
},
new Key
{
ObjectName = receiptSchema.AddPurchaseOrderLine.LineNbr.ObjectName,
FieldName = receiptSchema.AddPurchaseOrderLine.LineNbr.FieldName,
Value = "='1'"
},
new Value
{
Value = "True",
LinkedCommand = receiptSchema.AddPurchaseOrderLine.Selected
},
new Key
{
ObjectName = receiptSchema.AddPurchaseOrderLine.OrderNbr.ObjectName,
FieldName = receiptSchema.AddPurchaseOrderLine.OrderNbr.FieldName,
Value = "='PO000483'"
},
new Key
{
ObjectName = receiptSchema.AddPurchaseOrderLine.LineNbr.ObjectName,
FieldName = receiptSchema.AddPurchaseOrderLine.LineNbr.FieldName,
Value = "='2'"
},
new Value
{
Value = "True",
LinkedCommand = receiptSchema.AddPurchaseOrderLine.Selected
},
receiptSchema.Actions.AddPOOrderLine2,
receiptSchema.Actions.Save
};
I am wondering if a specific attribute can be retrieved in the Web Service API?
I have tried IN202500.AttributesAttributes.Value when exporting but that listed all attributes of the inventory. I also noticed the attributes are saved in the table as [AttributeName]_Attributes in the Inventory table, is there any way of retrieving this?
This is the code I am using (expecting it would retrieve the Attributes)
IN202500Content IN202500 = context.IN202500GetSchema();
context.IN202500Clear();
Command[] oCmd = new Command[] {
IN202500.StockItemSummary.ServiceCommands.EveryInventoryID,
IN202500.StockItemSummary.InventoryID,
IN202500.StockItemSummary.Description,
IN202500.StockItemSummary.ItemStatus,
IN202500.GeneralSettingsItemDefaults.ItemClass,
IN202500.GeneralSettingsItemDefaults.LotSerialClass,
new Field {
ObjectName = IN202500.StockItemSummary.InventoryID.ObjectName,
FieldName = "BARCODE_Attributes"},
new Field {
ObjectName = IN202500.StockItemSummary.InventoryID.ObjectName,
FieldName = "DfltReceiptLocationID"},
new Field {
ObjectName = IN202500.StockItemSummary.InventoryID.ObjectName,
FieldName = "LastModifiedDateTime"}
};
Filter[] oFilter = new Filter[] {
new Filter
{
Field = new Field {
ObjectName = IN202500.StockItemSummary.InventoryID.ObjectName,
FieldName = "LastModifiedDateTime"},
Condition = FilterCondition.Greater,
Value = SyncDate
}
};
String[][] sReturn = context.IN202500Export(oCmd, oFilter, 0, true, false);
But the Attribute field returned is an empty string.
Thanks,
G
You can leverage the dynamic fields that are added to the primary view of the screen to retrieve specific attribute values. These fields don't show up in the WSDL schema, so you have to create a Field object and pass it to the Export function.
I looked up the field name and object name from an Export scenario by displaying the Native Object / Native Field name columns. Resulting Export call looks like this:
var result = screen.Export(new IN202500.Command[] {
new IN202500.Value() { LinkedCommand = schema.StockItemSummary.InventoryID, Value = "Z730P00073"},
schema.StockItemSummary.InventoryID,
schema.StockItemSummary.Description,
new IN202500.Field { FieldName = "COLOR_Attributes", ObjectName = "Item"},
new IN202500.Field { FieldName = "HWMAN_Attributes", ObjectName = "Item"},
}, null, 0, true, true);
This code will retrieve the two attributes value (COLOR and HWMAN Attributes) for a specific inventory item (Z730P00073). The result variable contains a two-dimensional array, let me know if you need help getting results from the array.
This example shows how to add an item and set attributes and image:
byte[] filedata;
using (System.IO.FileStream file = System.IO.File.Open(#"C:\1.jpg", System.IO.FileMode.Open))
{
filedata = new byte[file.Length];
file.Read(filedata, 0, filedata.Length);
}
Random rnd = new Random();
string inventoryID = "CPU0000" + rnd.Next(100).ToString();
context.IN202500Clear();
IN202500result = context.IN202500Submit(
new Command[]
{
IN202500.Actions.Insert,
new Value { Value = inventoryID, LinkedCommand = IN202500.StockItemSummary.InventoryID },
new Value { Value = inventoryID, LinkedCommand = IN202500.StockItemSummary.Description },
new Value { Value = "CPU", LinkedCommand = IN202500.GeneralSettingsItemDefaults.ItemClass, Commit = true },
new Value { Value = "TAXABLE", LinkedCommand = IN202500.GeneralSettingsItemDefaults.TaxCategory, Commit = true },
//attributes - pairs
new Value { Value = "FREQUENCY", LinkedCommand = IN202500.AttributesAttributes.Attribute },
new Value { Value = "1400", LinkedCommand = IN202500.AttributesAttributes.Value, Commit = true },
new Value { Value = "CORE", LinkedCommand = IN202500.AttributesAttributes.Attribute },
new Value { Value = "2 CORES", LinkedCommand = IN202500.AttributesAttributes.Value, Commit = true },
new Value { Value = "INTGRAPH", LinkedCommand = IN202500.AttributesAttributes.Attribute },
new Value { Value = "True", LinkedCommand = IN202500.AttributesAttributes.Value, Commit = true },
//image
new Value { Value = Convert.ToBase64String(filedata), FieldName = "1.jpg", LinkedCommand = IN202500.StockItemSummary.ServiceCommands.Attachment }, //uploads
new Value { Value = "1.jpg", LinkedCommand = IN202500.Attributes.ImageUrl }, //sets as an item picture
IN202500.Actions.Save,
//return the result
IN202500.StockItemSummary.InventoryID
});