2026-07-15 18:51:09 +06:00
|
|
|
|
using Ease.NetCore.DataAccess;
|
|
|
|
|
|
using Ease.NetCore.DataAccess.SQL;
|
2026-07-16 18:30:18 +06:00
|
|
|
|
using Microsoft.AspNetCore.Http;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
using Microsoft.Data.SqlClient;
|
|
|
|
|
|
using Microsoft.Extensions.Options;
|
2026-07-16 18:30:18 +06:00
|
|
|
|
using OnlineSalesAutoCrop.CoreAPI.Models;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
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;
|
2026-07-16 18:30:18 +06:00
|
|
|
|
using System.Security.Claims;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
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<AppSettings> options, IUserService userService, IMobileMasterDataService masterService)
|
|
|
|
|
|
{
|
|
|
|
|
|
_settings = options.Value;
|
|
|
|
|
|
_userService = userService;
|
|
|
|
|
|
_masterService = masterService;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
//public async Task<SaveOrderResponse> 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<SaveOrderResponse> SaveOrderAsync(SaveOrderRequest request, int userId)
|
2026-07-15 18:51:09 +06:00
|
|
|
|
{
|
|
|
|
|
|
SaveOrderResponse response = new();
|
2026-07-16 18:30:18 +06:00
|
|
|
|
|
2026-07-15 18:51:09 +06:00
|
|
|
|
try
|
|
|
|
|
|
{
|
2026-07-16 18:30:18 +06:00
|
|
|
|
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 ;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
// 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.");
|
2026-07-15 18:51:09 +06:00
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
request.CustomerId = customer.CustomerId;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
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}'.");
|
2026-07-15 18:51:09 +06:00
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
|
|
|
|
|
|
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<string, MaterialLookupDto> materialsByCode = new(StringComparer.OrdinalIgnoreCase);
|
|
|
|
|
|
if (request.Items is { Count: > 0 })
|
|
|
|
|
|
{
|
|
|
|
|
|
List<string> 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<SaveOrderPromotionRequest> promotions = new List<SaveOrderPromotionRequest>();
|
|
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
2026-07-15 18:51:09 +06:00
|
|
|
|
}
|
2026-07-16 18:30:18 +06:00
|
|
|
|
catch (Exception)
|
2026-07-15 18:51:09 +06:00
|
|
|
|
{
|
2026-07-16 18:30:18 +06:00
|
|
|
|
throw;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
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))
|
2026-07-15 18:51:09 +06:00
|
|
|
|
{
|
2026-07-16 18:30:18 +06:00
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (UserRoleTypeEnum.OrderApprover == roleId && (OrderStatusEnum.CancelledByApprover == orderStatus || OrderStatusEnum.Approved == orderStatus))
|
|
|
|
|
|
{
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
return false;
|
2026-07-15 18:51:09 +06:00
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
|
|
|
|
|
|
private async Task<GetOrderByUUIDResponse> GetOrderByUUIDAsync(TransactionContext tc, Guid uuid)
|
2026-07-15 18:51:09 +06:00
|
|
|
|
{
|
|
|
|
|
|
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);
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
|
2026-07-15 18:51:09 +06:00
|
|
|
|
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;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2026-07-16 18:30:18 +06:00
|
|
|
|
private async Task<UserRoleDto?> 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<OrderBasicResponse?> 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<CustomerLookupDto?> 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<PaymentTermLookupDto?> 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<DiscountLookupDto?> 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<bool> 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<Dictionary<string, MaterialLookupDto>> GetMaterialsAsync(TransactionContext tc, IEnumerable<string> materialCodes)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
Dictionary<string, MaterialLookupDto> 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<List<FreeGoodsRuleDto>> GetFreeGoodsRulesAsync(TransactionContext tc, string salesOrgCode, string focCode, IEnumerable<int> materialIds, DateTime? asOfDate, int customerId)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
List<FreeGoodsRuleDto> 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<SaveOrderPromotionRequest> BuildFocPromotions(SaveOrderRequest request,
|
|
|
|
|
|
Dictionary<string, MaterialLookupDto> materialsByCode,List<FreeGoodsRuleDto> focRules)
|
|
|
|
|
|
{
|
|
|
|
|
|
try
|
|
|
|
|
|
{
|
|
|
|
|
|
List<SaveOrderPromotionRequest> promotions = new();
|
|
|
|
|
|
|
|
|
|
|
|
Dictionary<int, FreeGoodsRuleDto> 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<SaveOrderItemRequest> items, Dictionary<string, MaterialLookupDto> 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<SaveOrderPromotionRequest> 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<SaveOrderResponse> InsertOrderAsync(TransactionContext tc, SaveOrderRequest request, CustomerLookupDto customer, PaymentTermLookupDto paymentTerm,
|
|
|
|
|
|
DiscountLookupDto discount, Dictionary<string, MaterialLookupDto> materialsByCode,
|
|
|
|
|
|
List<SaveOrderPromotionRequest> 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<string, MaterialLookupDto> materialsByCode,
|
|
|
|
|
|
List<SaveOrderPromotionRequest> 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;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2026-07-15 18:51:09 +06:00
|
|
|
|
}
|