public static async Task UseBatch(ErpSession session) { // Update the quantity of several sales order lines in a batch. var order = await session.Client.For("Crm_Sales_SalesOrders") .Key(Guid.Parse("cc661805-a4be-4ad3-a2a5-08570c7d12f7")) .Select("Id,Lines") .Expand("Lines") .Top(1) .FindEntryAsync(); var lines = (IEnumerable <IDictionary <string, object> >)order["Lines"]; var batch = new ODataBatch(session.Client); foreach (var line in lines) { // Quantity is complex type consisted of Value and Unit. var quantity = (IDictionary <string, object>)line["Quantity"]; decimal value = (decimal)quantity["Value"]; string unit = (string)quantity["Unit"]; value += 5; // Update the line batch += c => c.For("Crm_Sales_SalesOrderLines") .Key(line["Id"]) .Set(new { Quantity = new { Value = value, Unit = unit } }) .UpdateEntryAsync(); } await batch.ExecuteAsync(); }
public static async Task ChangeDocumentState(ErpSession session) { var order = await session.Client.For("Crm_Sales_SalesOrders") .Filter("State eq 'FirmPlanned'") .Select("Id", "DocumentType/UserStatuses") .Expand("DocumentType/UserStatuses") .Top(1) .FindEntryAsync(); var userStatus = order.GetNestedValue("DocumentType.UserStatuses").AsEntityList().FirstOrDefault(); Dictionary <string, object> args = new Dictionary <string, object>(); args["newState"] = "FirmPlanned"; if (userStatus != null) { args["userStatus"] = new Dictionary <string, object> { // Simple.OData.Client doesn't allow setting @odata.id property in operation params. // So we set Id and @odata.type instead. // If @odata.type is ommited the type is inferred from the operation parameter type. // This doesn't work!!: ["@odata.id"] = userStatus.Annotations().Id ["Id"] = userStatus.Id() } } ; await session.Client.For("Crm_Sales_SalesOrders") .Key(order) .Action("ChangeState") .Set(args) .ExecuteAsync(); }
static async Task ExecuteSample(string sampleName, ErpSession session) { try { Console.WriteLine($"Executing {sampleName}..."); var m = typeof(Samples).GetMethod(sampleName, BindingFlags.Public | BindingFlags.InvokeMethod | BindingFlags.Static | BindingFlags.IgnoreCase); if (m == null) { throw new Exception($"Sample '{sampleName}' not found."); } var task = ((Task)m.Invoke(null, new object[] { session })); await task; Console.WriteLine($"{sampleName} done."); } catch (Exception ex) { DisplayError(ex); } }
internal static ODataClient CreateODataClient(ErpSession session, string transactionId = null) { var settings = new ODataClientSettings() { BaseUri = session.ServiceRoot, IncludeAnnotationsInResults = true, IgnoreUnmappedProperties = true, BeforeRequest = (req) => { // Debug POST/PATCH requests if (req.Content != null) { req.Content.ReadAsStringAsync().ContinueWith(t => Console.WriteLine(t.Result)); } var options = session.RequestOptions.ToString(); if (!string.IsNullOrEmpty(options)) { if (!string.IsNullOrEmpty(req.RequestUri.Query)) { options = "&options=" + options; } else { options = "?options=" + options; } req.RequestUri = new Uri(req.RequestUri + options); } if (session.authorizationHeader != null) { req.Headers.Add("Authorization", session.authorizationHeader); } if (transactionId != null) { req.Headers.Add("TransactionId", transactionId); } }, AfterResponse = async(resp) => { if (session.Metadata == null && resp.RequestMessage.RequestUri.ToString().Contains("$metadata")) { session.Metadata = await resp.Content.ReadAsStringAsync(); } }, OnTrace = (str, o) => { Console.WriteLine(str, o); }, PayloadFormat = ODataPayloadFormat.Json //IncludeAnnotationsInResults = true }; if (session.Metadata != null) { settings.MetadataDocument = session.Metadata; } return(new ODataClient(settings)); }
public static async Task LoadProducts(ErpSession session) { var products = await session.Client.For("General_Products_Products") .Filter("Active eq true") .Top(10) .Expand("ProductGroup") .Select("PartNumber", "ProductGroup/Code") .FindEntriesAsync(); foreach (var p in products) { Console.WriteLine("{0}\t{1}", ((IDictionary <string, object>)p["ProductGroup"])["Code"], p["PartNumber"]); } }
static async Task ExecuteSamples(string sampleName, Uri root, string user, string pass) { var credentials = new ErpCredentials("Samples", user, pass, "en"); Console.WriteLine("Logging in..."); using (var session = new ErpSession(root)) { await session.LoginAsync(credentials); // Omit null values from JSON result. session.RequestOptions.SkipNulls = true; await ExecuteSample(sampleName, session); } }
public static async Task UpdateProduct(ErpSession session) { var product = await session.Client.For("General_Products_Products") .Filter("PartNumber eq '1000044591'") .Top(1) .FindEntryAsync(); var unit = await session.Client.For("General_MeasurementUnits") .Filter("Code eq 'бр'") .FindEntryAsync(); await session.Client.For("General_Products_Products") .Key(product) .Set(new { MeasurementUnit = unit, ABCClass = "A", StandardLotSizeBase = new { Value = 3.45, Unit = "бр" } }) .UpdateEntryAsync(); }
public static async Task CreateDocumentAdjustment(ErpSession session) { // Begin an api transaction. var tr = await session.BeginTransactionAsync(ErpTransactionDataModel.Common, false); // Ordinary update for released documents is not allowed. // The update is made through adjustment documents. // The API provides method to simplify the creation of adjustment documents: CreateAdjusmentDocuments. // Load a sales order that is on state Released. var order = await tr.Client.For("Crm_Sales_SalesOrders") .Key(Guid.Parse("e4528383-cb1a-4395-8eec-db9b87d78333")) .Select("Id,Lines") .Expand("Lines") .Top(1) .FindEntryAsync(); var lines = (IEnumerable <IDictionary <string, object> >)order["Lines"]; // Update some order lines. // If we commit the front-end transaction an error will be thrown because editing released documents is not allowed. // However we'll update the line and we'll not commit the transaction. foreach (var line in lines) { // Quantity is complex type consisted of Value and Unit. var quantity = (IDictionary <string, object>)line["Quantity"]; decimal value = (decimal)quantity["Value"]; string unit = (string)quantity["Unit"]; value += 5; // Update the line await tr.Client.For("Crm_Sales_SalesOrderLines") .Key(line["Id"]) .Set(new { Quantity = new { Value = value, Unit = unit } }) .UpdateEntryAsync(); } // Call CreateAdjustmentDocuments on the transaction. // This method will create and apply adjustment documents for the modified released documents in the transaction. var result = await tr.Client.ExecuteActionAsScalarAsync <string>("CreateAdjustmentDocuments", null); // Rollback the front-end transaction. await tr.EndTransactionAsync(false); }
public static async Task FilterByReference(ErpSession session) { var productGroup = await session.Client.For("General_Products_ProductGroups") .Filter("Active eq true") .Top(1) .Select("Id") .FindEntryAsync(); // Use dynamic syntax var products = await session.Client.For("General_Products_Products") .Filter($"ProductGroup eq 'General_Products_ProductGroups({productGroup["Id"]})'") .Top(10) .Expand("ProductGroup") .Select("PartNumber", "ProductGroup/Code") .FindEntriesAsync(); foreach (var p in products) { Console.WriteLine("{0}\t{1}", ((IDictionary <string, object>)p["ProductGroup"])["Code"], p["PartNumber"]); } }
public static async Task FrontEndTransaction(ErpSession session) { var tr = await session.BeginTransactionAsync(ErpTransactionDataModel.FrontEnd, true); var order = await tr.Client.For("Crm_Sales_SalesOrders") .Filter("DocumentDate ge 2012-01-01T00:00:00Z and State eq 'FirmPlanned'") .Top(1) .FindEntryAsync(); var customer = await tr.Client.For("Crm_Customers") .Top(1) .FindEntryAsync(); await tr.Client.For("Crm_Sales_SalesOrders") .Key(order) .Set(new { Customer = customer }) .UpdateEntryAsync(); // Get the changes made by POST, PATCH and DELETE requests for the current front-end transaction. // Only the changes made after the last call of GenChanges are returned. var changes = await tr.Client.ExecuteFunctionAsSingleAsync("GetChanges", null); foreach (var operationEntry in changes) { // operationEntry.Key is one of: "insert", "update", "delete". // operationEntry.Value is a JSON hash table containing the changed objects divided by entity name and Id. var value = operationEntry.Value; if (value is string json) { var jobj = JObject.Parse(json); value = jobj.ToString(Newtonsoft.Json.Formatting.Indented); } Console.WriteLine("\r\n{0}:\r\n{1}", operationEntry.Key, value); } // We don't commit here because this is only a test method. await tr.EndTransactionAsync(false); }
public static async Task CreatePartyContact(ErpSession session) { var party = await session.Client.For("General_Contacts_Parties") .Top(1) .FindEntryAsync(); var contactMechanism = await session.Client.For("General_Contacts_ContactMechanisms") .Set(new Dictionary <string, object> { ["ContactMechanismType"] = "Mail", ["Name"] = "*****@*****.**" }) .InsertEntryAsync(true); var data = new Dictionary <string, object> { ["Party"] = party, ["ContactMechanism"] = contactMechanism }; var contact = await session.Client.For("General_Contacts_PartyContactMechanisms").Set(data).InsertEntryAsync(); }
public ErpTransaction(ErpSession session, string transactionId) { TransactionId = transactionId; Client = ErpSession.CreateODataClient(session, transactionId); }