using Ease.NetCore.DataAccess; using Ease.NetCore.DataAccess.SQL; using Microsoft.AspNetCore.Http; using Microsoft.Data.SqlClient; using Microsoft.Extensions.Options; using OnlineSalesAutoCrop.CoreAPI.Models; using OnlineSalesAutoCrop.CoreAPI.Models.Global; using OnlineSalesAutoCrop.CoreAPI.Models.Requests.MobileApp; using OnlineSalesAutoCrop.CoreAPI.Models.Responses.MobileApp; using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.MobileApp; using OnlineSalesAutoCrop.CoreAPI.Services.Contracts.Systems; using System; using System.Collections.Generic; using System.Data; using System.Linq; using System.Security.Claims; using System.Threading.Tasks; namespace OnlineSalesAutoCrop.CoreAPI.Services.Services.MobileApp; public class OrderService : IOrderService { private readonly AppSettings _settings; private readonly IUserService _userService; private readonly IMobileMasterDataService _masterService; public OrderService(IOptions options, IUserService userService, IMobileMasterDataService masterService) { _settings = options.Value; _userService = userService; _masterService = masterService; } //public async Task SaveOrderAsync(SaveOrderRequest request) //{ // SaveOrderResponse response = new(); // try // { // using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode,true); // GetOrderByUUIDResponse order= await GetOrderByUUIDAsync(tc, request.UUID); // tc.End(); // } // catch(Exception) // { // throw; // } // return new SaveOrderResponse() // { // OrderId = 12345, // OrderDate = DateTime.Now, // OrderNo = "Ord-000001-" + DateTime.Now.ToString("HH-mm-ss"), // UUID = request.UUID, // IsNewOrder =true // }; //} public async Task SaveOrderAsync(SaveOrderRequest request, int userId) { SaveOrderResponse response = new(); try { using TransactionContext tc = await TransactionContext.BeginAsync(_settings.DefaultConnection.ConnectionNode, true); try { // 1. Role - fetched using the claims-resolved UserId UserRoleDto? userRole = await GetUserRoleAsync(tc, userId); if (userRole is null) throw new Exception($"User id '{userId}' was not found."); if (!IsPermissiontoModify(request.OrderStatus ,userRole.RoleId )) { throw new Exception("You are not permitted to submit of modify this order"); } var existingOrder = await GetExistingOrderIdAsync(tc, request.UUID); request.OrderId = (existingOrder != null && existingOrder.OrderId > 0)? existingOrder.OrderId : 0; foreach (var item in request.Items) { item.ItemId = 0; item.OrderId = request.OrderId; } // 2. Insert vs update decision bool isUpdate = existingOrder != null && existingOrder.OrderId > 0 ; // 3. Reference data - SPs only fetch, every pass/fail call happens here CustomerLookupDto? customer = await GetCustomerAsync(tc, request.CustomerCode); if (customer is null) throw new Exception($"Customer code '{request.CustomerCode}' does not exist."); request.CustomerId = customer.CustomerId; PaymentTermLookupDto? paymentTerm = await GetPaymentTermAsync(tc, request.PaymentTermCode, request.SalesOrgCode); if (paymentTerm is null) throw new Exception($"Payment term code '{request.PaymentTermCode}' does not exist for sales org '{request.SalesOrgCode}'."); DiscountLookupDto? discount = await GetDiscountAsync(tc, request.DiscountCode, request.SalesOrgCode); if (discount is null) throw new Exception($"Discount code '{request.DiscountCode}' does not exist."); bool focCodeExists = await CheckFocCodeExistsAsync(tc, request.FocCode, request.SalesOrgCode); if (!focCodeExists) throw new Exception($"FOC code '{request.FocCode}' does not exist."); if (request.Items is null || request.Items.Count == 0) throw new Exception("Order must contain at least one item."); Dictionary materialsByCode = new(StringComparer.OrdinalIgnoreCase); if (request.Items is { Count: > 0 }) { List distinctCodes = request.Items .Select(i => i.MaterialCode) .Distinct(StringComparer.OrdinalIgnoreCase) .ToList(); materialsByCode = await GetMaterialsAsync(tc, distinctCodes); foreach (string code in distinctCodes) { if (!materialsByCode.ContainsKey(code)) throw new Exception($"Material code '{code}' does not exist."); } } var focItem = request.Items.FirstOrDefault(x => x.IsFocItem == true); var dicountItem = request.Items.FirstOrDefault(x => x.DiscountAmount > 0); List promotions = new List(); request.FocValue = 0; promotions.Add(new SaveOrderPromotionRequest() { OrderId = isUpdate ? existingOrder.OrderId : 0, MaterialId = materialsByCode[dicountItem.MaterialCode].MaterialId, PromotionCode =request.DiscountCode , DiscountPercentage = dicountItem.DiscountPercentage, DiscountValue = dicountItem.DiscountAmount, ForQuantity = dicountItem.PromoQuantity, OrderFocQty = 0, ValidatedFocQty = 0, ApprovedFocQty = 0, PromotionType = 1, }); promotions.Add(new SaveOrderPromotionRequest() { OrderId = isUpdate ? existingOrder.OrderId : 0, MaterialId = materialsByCode[focItem.MaterialCode].MaterialId, PromotionCode = request.FocCode, DiscountPercentage = 0, DiscountValue = 0, ForQuantity = focItem.PromoQuantity, OrderFocQty = (request.OrderStatus == OrderStatusEnum.Draft || request.OrderStatus == OrderStatusEnum.InOrderValidation) ? focItem.OrderQuantity : 0, ValidatedFocQty = (request.OrderStatus == OrderStatusEnum.CancelledByValidator || request.OrderStatus == OrderStatusEnum.InOrderApproval) ? focItem.OrderQuantity : 0, ApprovedFocQty = (request.OrderStatus == OrderStatusEnum.CancelledByApprover || request.OrderStatus == OrderStatusEnum.Approved) ? focItem.OrderQuantity : 0, PromotionType = 1, }); // 5. Insert or update int orderId; if (isUpdate) { orderId = existingOrder.OrderId; await UpdateOrderAsync(tc, orderId, request, customer!, paymentTerm!, discount!, materialsByCode, promotions, userId,(int) userRole!.RoleId); response.IsNewOrder = !isUpdate; response.UUID = request.UUID; response.OrderId = orderId; response.OrderDate = existingOrder.OrderDate; } else { response = await InsertOrderAsync(tc, request, customer!, paymentTerm!, discount!, materialsByCode, promotions, userId,(int) userRole!.RoleId); } tc.End(); } catch (Exception ie) { tc?.HandleError(); throw DBCustomError.GenerateCustomError(ie); } } catch (Exception) { throw; } return response; } private bool IsPermissiontoModify(OrderStatusEnum orderStatus, UserRoleTypeEnum roleId) { if( UserRoleTypeEnum.OrderCollector == roleId && ( OrderStatusEnum.Draft == orderStatus || OrderStatusEnum.InOrderValidation == orderStatus)) { return true; } if (UserRoleTypeEnum.OrderValidator == roleId && (OrderStatusEnum.CancelledByValidator == orderStatus || OrderStatusEnum.InOrderApproval == orderStatus)) { return true; } if (UserRoleTypeEnum.OrderApprover == roleId && (OrderStatusEnum.CancelledByApprover == orderStatus || OrderStatusEnum.Approved == orderStatus)) { return true; } return false; } private async Task GetOrderByUUIDAsync(TransactionContext tc, Guid uuid) { GetOrderByUUIDResponse response = null; try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@UUID", pType: SqlDbType.UniqueIdentifier, pValue: uuid) ]; using (IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetOrderDetailsByUUID", parameterValues: p)) { if (dr.Read()) { response = new GetOrderByUUIDResponse { OrderId = dr.GetInt32(0), OrderNo = dr.GetString(1), OrderDate = dr.GetDateTime(2), ExpectedSalesDate = dr.IsDBNull(3) ? null : dr.GetDateTime(3), UUID = dr.GetGuid(4), SalesOrgCode = dr.GetString(5), CustomerId = dr.GetInt32(6), CustomerCode = dr.GetString(7), CustomerName = dr.GetString(8), EmployeeId = dr.GetInt32(9), EmployeeCode = dr.GetString(10), EmployeeName = dr.GetString(11), PaymentTermCode = dr.GetString(12), ReferenceTxtNo = dr.IsDBNull(13) ? null : dr.GetString(13), GrossValue = dr.GetDecimal(14), DiscountValue = dr.GetDecimal(15), FOCValue = dr.GetDecimal(16), NetValue = dr.GetDecimal(17), OrderStatus = dr.GetString(18), SAPReferenceOrderNo = dr.IsDBNull(19) ? null : dr.GetString(19) }; } if (response != null && dr.NextResult()) { while (dr.Read()) { GetOrderItemResponse item = new() { ItemId = dr.GetInt32(0), OrderID = dr.GetInt32(1), MaterialId = dr.GetInt32(2), MaterialCode = dr.GetString(3), MaterialName = dr.GetString(4), UnitPrice = dr.GetDecimal(5), SalesUnit = dr.GetString(6), OrderQuantity = dr.GetDecimal(7), ValidatedQuantity = dr.GetDecimal(8), ApprovedQuantity = dr.GetDecimal(9), DiscountPercentage = dr.GetDecimal(10), DiscountValue = dr.GetDecimal(11), IsFOCItem = dr.GetBoolean(12), OrderFocQuantity = dr.GetDecimal(13), ValidatedFocQuantity = dr.GetDecimal(14), ApprovedFocQuantity = dr.GetDecimal(15), LineTotalValue = dr.GetDecimal(16), }; response.Items.Add(item); } } if (response != null && dr.NextResult()) { while (dr.Read()) { GetOrderPromotionResponse promotion = new() { ItemId = dr.GetInt32(0), OrderID = dr.GetInt32(1), MaterialId = dr.GetInt32(2), PromotionCode = dr.GetString(3), DiscountPercentage = dr.GetDecimal(4), DiscountValue = dr.GetDecimal(5), ForQuantity = dr.GetDecimal(6), OrderFocQuantity = dr.GetDecimal(7), ValidatedFocQuantity = dr.GetDecimal(8), ApprovedFocQuantity = dr.GetDecimal(9), PromotionType = dr.GetInt32(10), }; response.Promotions.Add(promotion); } } dr.Close(); } } catch (Exception) { throw; } return response; } private async Task GetUserRoleAsync(TransactionContext tc, int userId) { try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@UserId", pType: SqlDbType.Int, pValue: userId) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetUserRoleByUserId", parameterValues: p); if (dr.Read()) { return new UserRoleDto { UserId = dr.GetInt32(0), RoleId =(UserRoleTypeEnum) dr.GetInt32(1) }; } return null; } catch (Exception) { throw; } } private async Task GetExistingOrderIdAsync(TransactionContext tc, Guid uuid) { OrderBasicResponse response = null; try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@UUID", pType: SqlDbType.UniqueIdentifier, pValue: uuid) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetOrderHeaderByUUID", parameterValues: p); if( dr.Read()) { response = new OrderBasicResponse() { OrderId = dr.GetInt32(0), OrderNo = dr.GetString(1), OrderDate = dr.GetDateTime(2), UUID = uuid, OrderStatus = (OrderStatusEnum)dr.GetInt32(3) }; } dr.Close(); } catch (Exception) { throw; } return response; } private async Task GetCustomerAsync(TransactionContext tc, string customerCode) { try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: customerCode) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetCustomerByCode", parameterValues: p); if (dr.Read()) { return new CustomerLookupDto { CustomerId = dr.GetInt32(0), CustomerCode = dr.GetString(1), CustomerName = dr.GetString(2) }; } return null; } catch (Exception) { throw; } } private async Task GetPaymentTermAsync(TransactionContext tc, string paymentTermCode, string salesOrgCode) { try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@PaymentTermCode", pType: SqlDbType.VarChar, pValue: paymentTermCode), SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: salesOrgCode) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetPaymentTermByCode", parameterValues: p); if (dr.Read()) { return new PaymentTermLookupDto { PaymentTermId = dr.GetInt32(0), PaymentTermCode = dr.GetString(1) }; } return null; } catch (Exception) { throw; } } private async Task GetDiscountAsync(TransactionContext tc, string discountCode, string salesOrgCode) { try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@DiscountCode", pType: SqlDbType.VarChar, pValue: discountCode), SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: salesOrgCode) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetDiscountByCode", parameterValues: p); if (dr.Read()) { return new DiscountLookupDto { DiscountId = dr.GetInt32(0), DiscountCode = dr.GetString(1) }; } return null; } catch (Exception) { throw; } } private async Task CheckFocCodeExistsAsync(TransactionContext tc, string focCode, string salesOrgCode) { try { SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: salesOrgCode), SqlHelperExtension.CreateInParam(pName: "@FocCode", pType: SqlDbType.VarChar, pValue: focCode) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.CheckFocCodeExists", parameterValues: p); return dr.Read(); } catch (Exception) { throw; } } private async Task> GetMaterialsAsync(TransactionContext tc, IEnumerable materialCodes) { try { Dictionary result = new(StringComparer.OrdinalIgnoreCase); DataTable codesTable = new(); codesTable.Columns.Add("Code", typeof(string)); foreach (string code in materialCodes) codesTable.Rows.Add(code); SqlParameter codesParam = SqlHelperExtension.CreateInParam(pName: "@Codes", pType: SqlDbType.Structured, pValue: codesTable); codesParam.TypeName = "dbo.CodeListTableType"; // CreateInParam has no TypeName slot, so it's set separately SqlParameter[] p = [codesParam]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetMaterialsByCodes", parameterValues: p); while (dr.Read()) { MaterialLookupDto dto = new() { MaterialId = dr.GetInt32(0), MaterialCode = dr.GetString(1), MaterialName = dr.GetString(2) }; result[dto.MaterialCode] = dto; } dr.Close(); return result; } catch (Exception) { throw; } } private async Task> GetFreeGoodsRulesAsync(TransactionContext tc, string salesOrgCode, string focCode, IEnumerable materialIds, DateTime? asOfDate, int customerId) { try { List rules = new(); DataTable idsTable = new(); idsTable.Columns.Add("Id", typeof(int)); foreach (int id in materialIds) idsTable.Rows.Add(id); SqlParameter idsParam = SqlHelperExtension.CreateInParam(pName: "@MaterialIds", pType: SqlDbType.Structured, pValue: idsTable); idsParam.TypeName = "dbo.IntListTableType"; SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: salesOrgCode), SqlHelperExtension.CreateInParam(pName: "@CustomerId", pType: SqlDbType.VarChar, pValue: customerId), SqlHelperExtension.CreateInParam(pName: "@FocCode", pType: SqlDbType.VarChar, pValue: focCode),idsParam, SqlHelperExtension.CreateInParam(pName: "@AsOfDate", pType: SqlDbType.DateTime, pValue: DateTime.Now) ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.GetFreeGoodsRules", parameterValues: p); while (dr.Read()) { rules.Add(new FreeGoodsRuleDto { FreeGoodsId = dr.GetInt32(0), MaterialId = dr.GetInt32(1), MinOrderQuantity = dr.GetDecimal(2), ForQuantity = dr.GetDecimal(3), FreeQuantity = dr.GetDecimal(4), UnitOfMeasure = dr.IsDBNull(5) ? string.Empty : dr.GetString(5), FocUnitOfMeasure = dr.IsDBNull(6) ? string.Empty : dr.GetString(6) }); } dr.Close(); return rules; } catch (Exception) { throw; } } // Once OrderQuantity >= MinOrderQuantity, the material earns FreeQuantity for every // ForQuantity units ordered (e.g. Min 10 / For 10 / Free 1 -> ordering 25 = floor(25/10)*1 = 2 free). // This is my read of "calculate based on order quantity" - swap the formula below if yours differs. private static List BuildFocPromotions(SaveOrderRequest request, Dictionary materialsByCode,List focRules) { try { List promotions = new(); Dictionary rulesByMaterialId = focRules .GroupBy(r => r.MaterialId) .ToDictionary(g => g.Key, g => g.First()); // first active rule wins if more than one overlaps foreach (SaveOrderItemRequest item in request.Items) { if (item.IsFocItem) continue; // a free item doesn't itself trigger more free goods if (!materialsByCode.TryGetValue(item.MaterialCode, out MaterialLookupDto? material)) continue; // already caught by validation - guarded here defensively if (!rulesByMaterialId.TryGetValue(material.MaterialId, out FreeGoodsRuleDto? rule)) continue; // no free-goods rule configured for this material under this FOC code if (rule.ForQuantity <= 0 || item.OrderQuantity < rule.MinOrderQuantity) continue; decimal eligibleSets = Math.Floor(item.OrderQuantity / rule.ForQuantity); decimal focQuantity = eligibleSets * rule.FreeQuantity; if (focQuantity <= 0) continue; promotions.Add(new SaveOrderPromotionRequest { MaterialId = material.MaterialId, PromotionCode = request.FocCode, DiscountPercentage = 0, DiscountValue = 0, ForQuantity = rule.ForQuantity, OrderFocQty = focQuantity, ValidatedFocQty = 0, ApprovedFocQty = 0, PromotionType = 1 // TODO: swap for your real "free goods" PromotionType constant }); } return promotions; } catch (Exception) { throw; } } private static DataTable ToOrderItemTable(IEnumerable items, Dictionary materialsByCode, int orderStatus ) { try { DataTable table = new(); table.Columns.Add("OrderId", typeof(int)); table.Columns.Add("ItemId", typeof(int)); table.Columns.Add("MaterialId", typeof(int)); table.Columns.Add("MaterialCode", typeof(string)); table.Columns.Add("MaterialName", typeof(string)); table.Columns.Add("UnitPrice", typeof(decimal)); table.Columns.Add("SalesUnit", typeof(string)); table.Columns.Add("PromoQty", typeof(decimal)); table.Columns.Add("OrderQuantity", typeof(decimal)); table.Columns.Add("ValidatedQuantity", typeof(decimal)); table.Columns.Add("ApprovedQuantity", typeof(decimal)); table.Columns.Add("DiscountPercentage", typeof(decimal)); table.Columns.Add("DiscountAmount", typeof(decimal)); table.Columns.Add("IsFocItem", typeof(bool)); table.Columns.Add("LineTotalValue", typeof(decimal)); table.Columns.Add("OrderStatus", typeof(int)); foreach (SaveOrderItemRequest item in items) { MaterialLookupDto material = materialsByCode[item.MaterialCode]; table.Rows.Add( item.ItemId, item.OrderId, material.MaterialId, item.MaterialCode, item.MaterialName ?? material.MaterialName, item.UnitPrice, item.SalesUnit, item.PromoQuantity, item.OrderQuantity, item.ValidatedQuantity, item.ApprovedQuantity, item.DiscountPercentage, item.DiscountAmount, item.IsFocItem, item.LineTotalValue, orderStatus); } return table; } catch (Exception) { throw; } } private static DataTable ToOrderPromotionTable(IEnumerable promotions) { try { DataTable table = new(); table.Columns.Add("ItemId", typeof(int)); table.Columns.Add("OrderId", typeof(int)); table.Columns.Add("MaterialId", typeof(int)); table.Columns.Add("PromotionCode", typeof(string)); table.Columns.Add("DiscountPercentage", typeof(decimal)); table.Columns.Add("DiscountValue", typeof(decimal)); table.Columns.Add("ForQuantity", typeof(decimal)); table.Columns.Add("OrderFocQty", typeof(decimal)); table.Columns.Add("ValidatedFocQty", typeof(decimal)); table.Columns.Add("ApprovedFocQty", typeof(decimal)); table.Columns.Add("PromotionType", typeof(int)); foreach (SaveOrderPromotionRequest promo in promotions) { table.Rows.Add( promo.ItemId, promo.OrderId, promo.MaterialId, promo.PromotionCode , promo.DiscountPercentage, promo.DiscountValue, promo.ForQuantity, promo.OrderFocQty, promo.ValidatedFocQty, promo.ApprovedFocQty, promo.PromotionType); } return table; } catch (Exception) { throw; } } private async Task InsertOrderAsync(TransactionContext tc, SaveOrderRequest request, CustomerLookupDto customer, PaymentTermLookupDto paymentTerm, DiscountLookupDto discount, Dictionary materialsByCode, List promotions, int userId, int role) { try { SqlParameter itemsParam = SqlHelperExtension.CreateInParam(pName: "@Items", pType: SqlDbType.Structured, pValue: ToOrderItemTable(request.Items, materialsByCode, (int)request.OrderStatus)); itemsParam.TypeName = "dbo.OrderItemTableType"; SqlParameter promotionsParam = SqlHelperExtension.CreateInParam(pName: "@Promotions", pType: SqlDbType.Structured, pValue: ToOrderPromotionTable(promotions)); promotionsParam.TypeName = "dbo.OrderPromotionTableType"; SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@UUID", pType: SqlDbType.UniqueIdentifier, pValue: request.UUID), SqlHelperExtension.CreateInParam(pName: "@OrderNo", pType: SqlDbType.VarChar, pValue: request.OrderNo), SqlHelperExtension.CreateInParam(pName: "@OrderDate", pType: SqlDbType.DateTime, pValue: request.OrderDate ?? DateTime.Now ), SqlHelperExtension.CreateInParam(pName: "@ExpectedDeliveryDate", pType: SqlDbType.DateTime, pValue: request.ExpectedDeliveryDate ), SqlHelperExtension.CreateInParam(pName: "@SalesOrgCode", pType: SqlDbType.VarChar, pValue: request.SalesOrgCode), SqlHelperExtension.CreateInParam(pName: "@CustomerId", pType: SqlDbType.Int, pValue: customer.CustomerId), SqlHelperExtension.CreateInParam(pName: "@CustomerCode", pType: SqlDbType.VarChar, pValue: request.CustomerCode), SqlHelperExtension.CreateInParam(pName: "@CustomerName", pType: SqlDbType.VarChar, pValue: request.CustomerName), SqlHelperExtension.CreateInParam(pName: "@EmployeeId", pType: SqlDbType.Int, pValue: request.EmployeeId ), SqlHelperExtension.CreateInParam(pName: "@EmployeeCode", pType: SqlDbType.VarChar, pValue: request.EmployeeCode ), SqlHelperExtension.CreateInParam(pName: "@EmployeeName", pType: SqlDbType.VarChar, pValue: request.EmployeeCode ), SqlHelperExtension.CreateInParam(pName: "@PaymentTermCode", pType: SqlDbType.VarChar, pValue: request.PaymentTermCode), SqlHelperExtension.CreateInParam(pName: "@ReferenceTxtNo", pType: SqlDbType.VarChar, pValue: request.ReferenceTxtNo ), SqlHelperExtension.CreateInParam(pName: "@GrossValue", pType: SqlDbType.Decimal, pValue: request.GrossValue), SqlHelperExtension.CreateInParam(pName: "@DiscountValue", pType: SqlDbType.Decimal, pValue: request.DiscountValue), SqlHelperExtension.CreateInParam(pName: "@FOCValue", pType: SqlDbType.Decimal, pValue: request.FocCode), SqlHelperExtension.CreateInParam(pName: "@NetValue", pType: SqlDbType.Decimal, pValue: request.NetValue), SqlHelperExtension.CreateInParam(pName: "@OrderStatus", pType: SqlDbType.Int, pValue: (int)request.OrderStatus), SqlHelperExtension.CreateInParam(pName: "@SapRefferenceOrderNo", pType: SqlDbType.NVarChar, pValue: null), itemsParam, promotionsParam ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.InsertOrder", parameterValues: p); int newOrderId = 0; string orderNo = string.Empty; if (dr.Read()) { newOrderId = dr.GetInt32(0); orderNo = dr.GetString(1); } dr.Close(); return new SaveOrderResponse() { IsNewOrder=true, OrderDate= DateTime.Now, OrderId= newOrderId,OrderNo =orderNo,UUID = request.UUID}; } catch (Exception) { throw; } } private async Task UpdateOrderAsync(TransactionContext tc, int orderId, SaveOrderRequest request, CustomerLookupDto customer, PaymentTermLookupDto paymentTerm, DiscountLookupDto discount, Dictionary materialsByCode, List promotions, int userId, int role) { try { SqlParameter itemsParam = SqlHelperExtension.CreateInParam(pName: "@Items", pType: SqlDbType.Structured, pValue: ToOrderItemTable(request.Items, materialsByCode, (int)request.OrderStatus)); itemsParam.TypeName = "dbo.OrderItemTableType"; SqlParameter promotionsParam = SqlHelperExtension.CreateInParam(pName: "@Promotions", pType: SqlDbType.Structured, pValue: ToOrderPromotionTable(promotions)); promotionsParam.TypeName = "dbo.OrderPromotionTableType"; SqlParameter[] p = [ SqlHelperExtension.CreateInParam(pName: "@OrderId", pType: SqlDbType.Int, pValue: orderId), SqlHelperExtension.CreateInParam(pName: "@ExpectedDeliveryDate", pType: SqlDbType.DateTime, pValue: request.ExpectedDeliveryDate ), SqlHelperExtension.CreateInParam(pName: "@PaymentTermCode", pType: SqlDbType.VarChar, pValue: request.PaymentTermCode), SqlHelperExtension.CreateInParam(pName: "@ReferenceTxtNo", pType: SqlDbType.VarChar, pValue: request.ReferenceTxtNo ), SqlHelperExtension.CreateInParam(pName: "@GrossValue", pType: SqlDbType.Decimal, pValue: request.GrossValue), SqlHelperExtension.CreateInParam(pName: "@DiscountValue", pType: SqlDbType.Decimal, pValue: request.DiscountValue), SqlHelperExtension.CreateInParam(pName: "@FOCValue", pType: SqlDbType.Decimal, pValue: request.FocCode), SqlHelperExtension.CreateInParam(pName: "@NetValue", pType: SqlDbType.Decimal, pValue: request.NetValue), SqlHelperExtension.CreateInParam(pName: "@OrderStatus", pType: SqlDbType.Int, pValue: (int)request.OrderStatus), itemsParam, promotionsParam ]; using IDataReader dr = await tc.ExecuteReaderSpAsync("dbo.UpdateOrder", parameterValues: p); dr.Close(); } catch (Exception) { throw; } } }