diff --git a/BBWYB.Server.API/Controllers/OrderController.cs b/BBWYB.Server.API/Controllers/OrderController.cs index b2c77dc..df6335a 100644 --- a/BBWYB.Server.API/Controllers/OrderController.cs +++ b/BBWYB.Server.API/Controllers/OrderController.cs @@ -1,4 +1,4 @@ -using BBWYB.Server.Business.Order; +using BBWYB.Server.Business; using BBWYB.Server.Model.Dto; using Microsoft.AspNetCore.Mvc; diff --git a/BBWYB.Server.API/Controllers/PurchaseOrderController.cs b/BBWYB.Server.API/Controllers/PurchaseOrderController.cs new file mode 100644 index 0000000..f038aa2 --- /dev/null +++ b/BBWYB.Server.API/Controllers/PurchaseOrderController.cs @@ -0,0 +1,37 @@ +using BBWYB.Server.Business; +using BBWYB.Server.Model.Dto; +using Microsoft.AspNetCore.Mvc; + +namespace BBWYB.Server.API.Controllers +{ + public class PurchaseOrderController : BaseApiController + { + private PurchaseOrderBusiness purchaseOrderBusiness; + + public PurchaseOrderController(IHttpContextAccessor httpContextAccessor, PurchaseOrderBusiness purchaseOrderBusiness) : base(httpContextAccessor) + { + this.purchaseOrderBusiness = purchaseOrderBusiness; + } + + /// + /// 预览订单 + /// + /// + /// + [HttpPost] + public PreviewOrderResponse PreviewPurchaseOrder([FromBody] PreviewOrderRequest request) + { + return purchaseOrderBusiness.PreviewPurchaseOrder(request); + } + + /// + /// 创建采购单 + /// + /// + [HttpPost] + public void CreatePurchaseOrder([FromBody] CreateOrderRequest request) + { + purchaseOrderBusiness.CreatePurchaseOrder(request); + } + } +} diff --git a/BBWYB.Server.API/Program.cs b/BBWYB.Server.API/Program.cs index bfbe26c..d0da2b1 100644 --- a/BBWYB.Server.API/Program.cs +++ b/BBWYB.Server.API/Program.cs @@ -11,6 +11,7 @@ using Microsoft.IdentityModel.Tokens; using Microsoft.OpenApi.Models; using Newtonsoft.Json.Serialization; using SDKAdapter.OperationPlatform.Client; +using SDKAdapter.PurchasePlatform.Client; using System.Reflection; using System.Text; using Yitter.IdGenerator; @@ -54,6 +55,7 @@ services.AddCors(options => services.BatchRegisterServices(new Assembly[] { Assembly.Load("BBWYB.Server.Business") }, typeof(IDenpendency)); services.AddSingleton(); +services.AddSingleton(); services.AddMapper(new MappingProfiles()); services.AddControllers(c => diff --git a/BBWYB.Server.Business/PurchaseOrder/PurchaseOrderBusiness.cs b/BBWYB.Server.Business/PurchaseOrder/PurchaseOrderBusiness.cs index 60d381a..97e2c89 100644 --- a/BBWYB.Server.Business/PurchaseOrder/PurchaseOrderBusiness.cs +++ b/BBWYB.Server.Business/PurchaseOrder/PurchaseOrderBusiness.cs @@ -1,6 +1,10 @@ using BBWYB.Common.Log; using BBWYB.Common.Models; +using BBWYB.Server.Model; +using BBWYB.Server.Model.Db; using BBWYB.Server.Model.Dto; +using FreeSql; +using Newtonsoft.Json; using SDKAdapter; using SDKAdapter.PurchasePlatform.Client; using SDKAdapter.PurchasePlatform.Models; @@ -55,5 +59,164 @@ namespace BBWYB.Server.Business } + public void CreatePurchaseOrder(CreateOrderRequest request) + { + nLogManager.Default().Info($"CreatePurchaseOrder\r\n{JsonConvert.SerializeObject(request)}"); + + var dbOrder = fsql.Select(request.OrderId).ToOne(); + if (dbOrder == null) + throw new BusinessException("订单不存在"); + if (dbOrder.OrderState != Enums.OrderState.等待采购 && dbOrder.OrderState != Enums.OrderState.待出库) + throw new BusinessException("只能为等待采购或待出库的订单进行采购"); + + var deleteOrderCostDetail = fsql.Delete().Where(ocd => ocd.OrderId == dbOrder.Id); + var isRepurchase = fsql.Select(dbOrder.Id).Any(); + + #region 合并重复的采购sku + var repeatPurchaseSkuGroups = request.CargoParamList.GroupBy(p => p.SkuId).ToList(); + foreach (var group in repeatPurchaseSkuGroups) + { + if (group.Count() > 1) + { + var repeatSkus = group.ToList(); + foreach (var repeatSku in repeatSkus) + request.CargoParamList.Remove(repeatSku); + request.CargoParamList.Add(new CargoParamRequest() + { + BelongSkuId = repeatSkus[0].BelongSkuId, + ProductId = repeatSkus[0].ProductId, + SkuId = repeatSkus[0].SkuId, + SpecId = repeatSkus[0].SpecId, + Quantity = repeatSkus.Sum(s => s.Quantity) + }); + } + } + #endregion + + var orderSkus = fsql.Select().Where(osku => osku.Price != 0 && osku.OrderId == request.OrderId).ToList(); + var orderSkuIds = orderSkus.Select(osku => osku.Id).ToList(); + + var client = ppPlatformClientFactory.GetClient((AdapterEnums.PlatformType)request.Platform); + + var createOrderResponse = client.CreateOrder(new PP_CreateOrderRequest() + { + AppKey = request.AppKey, + AppSecret = request.AppSecret, + AppToken = request.AppToken, + Consignee = new PP_ConsigneeRequest() + { + Address = request.Consignee.Address, + City = request.Consignee.City, + ContactName = request.Consignee.ContactName, + County = request.Consignee.County, + Mobile = request.Consignee.Mobile, + Province = request.Consignee.Province, + TelePhone = request.Consignee.TelePhone, + Town = request.Consignee.Town + }, + Platform = (AdapterEnums.PlatformType)request.Platform, + PurchaseMode = (AdapterEnums.PurchaseMode)request.PurchaseOrderMode, + Extensions = request.Extensions, + Remark = request.Remark, + OrderProductParamList = request.CargoParamList.Select(p => new PP_OrderProductParamRequest() + { + ProductId = p.ProductId, + Quantity = p.Quantity, + SkuId = p.SkuId, + SpecId = p.SpecId + }).ToList() + }); + + var purchaseOrderSimpleInfo = client.QueryOrderDetail(new PP_QueryOrderDetailRequest() + { + AppKey = request.AppKey, + AppSecret = request.AppSecret, + AppToken = request.AppToken, + OrderId = createOrderResponse.OrderId + }); + + nLogManager.Default().Info($"QueryOrderDetail\r\nShopOrderId {request.OrderId}\r\n purchaseOrderSimpleInfo\r\n{JsonConvert.SerializeObject(purchaseOrderSimpleInfo)}"); + + + List insertOrderCostDetails = new List(); + IInsert insertOrderCost = null; + IUpdate updateOrderCost = null; + + foreach (var orderSku in orderSkus) + { + #region 计算当前sku的采购成本和采购运费 + var currentOrderSkuProductAmount = 0M; //采购成本 + var currentOrderSkuCargoParamList = request.CargoParamList.Where(p => p.BelongSkuId == orderSku.SkuId); //找当前skuId的采购skuId + currentOrderSkuProductAmount = purchaseOrderSimpleInfo.ItemList.Where(p => currentOrderSkuCargoParamList.Any(p1 => p1.SkuId == p.SkuId))?.Sum(p => p.ProductAmount) ?? 0M; + + var currentOrderSkuFreightAmount = purchaseOrderSimpleInfo.FreightAmount / orderSkus.Count(); //采购运费(按sku数均分) + #endregion + + #region 成本明细 + var orderCostDetail = new OrderCostDetail() + { + Id = idGenerator.NewLong(), + ConsumableAmount = 0, + CreateTime = DateTime.Now, + DeductionQuantity = orderSku.ItemTotal.Value, + DeliveryExpressFreight = 0, + FirstFreight = 0, + //OperationAmount = 0, + InStorageAmount = 0, + OutStorageAmount = 0, + OrderId = request.OrderId, + ProductId = orderSku.ProductId, + PurchaseFreight = currentOrderSkuFreightAmount, + //PurchaseOrderPKId = purchaseOrder.Id, + PurchaseOrderId = purchaseOrderSimpleInfo.OrderId, + SkuAmount = currentOrderSkuProductAmount, + SkuId = orderSku.SkuId, + StorageAmount = 0, + //UnitCost = purchaseOrder.UnitCost, + //TotalCost = currentOrderSkuProductAmount + currentOrderSkuFreightAmount//purchaseOrder.UnitCost * orderSku.ItemTotal.Value + }; + //orderCostDetail.SkuGrossProfit = orderSku.Price.Value * orderCostDetail.DeductionQuantity - avgPreferential - (orderCostDetail.TotalCost + orderCostDetail.DeliveryExpressFreight) - orderSku.Price.Value * orderCostDetail.DeductionQuantity * createOnlinePurchaseOrderRequest.PlatformCommissionRatio; + insertOrderCostDetails.Add(orderCostDetail); + #endregion + } + + #region 订单成本 + var orderCost = new OrderCost() + { + OrderId = request.OrderId, + CreateTime = DateTime.Now, + DeliveryExpressFreight = 0, + IsManualEdited = false, + PlatformCommissionRatio = 0, + PreferentialAmount = 0, + PurchaseAmount = purchaseOrderSimpleInfo.TotalAmount + }; + //orderCost.PlatformCommissionAmount = dbOrder.OrderSellerPrice * orderCost.PlatformCommissionRatio; + orderCost.Profit = dbOrder.OrderSellerPrice + + dbOrder.FreightPrice - + orderCost.PurchaseAmount - + orderCost.DeliveryExpressFreight; // -orderCost.PlatformCommissionAmount + if (!isRepurchase) + { + insertOrderCost = fsql.Insert(orderCost); + } + else + { + updateOrderCost = fsql.Update().SetSource(orderCost).IgnoreColumns(a => new { a.CreateTime }); + } + #endregion + + + fsql.Transaction(() => + { + deleteOrderCostDetail.ExecuteAffrows(); + fsql.Insert(insertOrderCostDetails).ExecuteAffrows(); + updateOrderCost?.ExecuteAffrows(); + insertOrderCost?.ExecuteAffrows(); + fsql.Update(request.OrderId).SetIf(dbOrder.OrderState == Enums.OrderState.等待采购, o => o.OrderState, Model.Enums.OrderState.待出库) + .Set(o => o.IsPurchased, true) + .ExecuteAffrows(); + }); + } } } diff --git a/BBWYB.Server.Model/Dto/Request/PurchaseOrder/CreateOrderRequest.cs b/BBWYB.Server.Model/Dto/Request/PurchaseOrder/CreateOrderRequest.cs new file mode 100644 index 0000000..d802ef8 --- /dev/null +++ b/BBWYB.Server.Model/Dto/Request/PurchaseOrder/CreateOrderRequest.cs @@ -0,0 +1,14 @@ +namespace BBWYB.Server.Model.Dto +{ + public class CreateOrderRequest: PreviewOrderRequest + { + public string Extensions { get; set; } + + public string Remark { get; set; } + + /// + /// 店铺订单Id + /// + public string OrderId { get; set; } + } +} diff --git a/SDKAdapter/PurchasePlatform/Client/Base/PP_PlatformClient.cs b/SDKAdapter/PurchasePlatform/Client/Base/PP_PlatformClient.cs index d9cad26..16dd159 100644 --- a/SDKAdapter/PurchasePlatform/Client/Base/PP_PlatformClient.cs +++ b/SDKAdapter/PurchasePlatform/Client/Base/PP_PlatformClient.cs @@ -35,5 +35,16 @@ namespace SDKAdapter.PurchasePlatform.Client { throw new NotImplementedException(); } + + /// + /// 查询订单详情 + /// + /// + /// + /// + public virtual PP_QueryOrderDetailResponse QueryOrderDetail(PP_QueryOrderDetailRequest request) + { + throw new NotImplementedException(); + } } } diff --git a/SDKAdapter/PurchasePlatform/Client/Impl/PP_1688Client.cs b/SDKAdapter/PurchasePlatform/Client/Impl/PP_1688Client.cs index 6fe3495..42b1f5b 100644 --- a/SDKAdapter/PurchasePlatform/Client/Impl/PP_1688Client.cs +++ b/SDKAdapter/PurchasePlatform/Client/Impl/PP_1688Client.cs @@ -191,6 +191,58 @@ namespace SDKAdapter.PurchasePlatform.Client FailProductMessageList = failedOfferJArray == null ? null : failedOfferJArray.Select(failedOfferJToken => failedOfferJToken.ToString()).ToList() }; } + + public override PP_QueryOrderDetailResponse QueryOrderDetail(PP_QueryOrderDetailRequest request) + { + var client = GetSyncAPIClient(request.AppKey, request.AppSecret); + RequestPolicy reqPolicy = new RequestPolicy(); + reqPolicy.HttpMethod = "POST"; + reqPolicy.NeedAuthorization = false; + reqPolicy.RequestSendTimestamp = false; + reqPolicy.UseHttps = false; + reqPolicy.UseSignture = true; + reqPolicy.AccessPrivateApi = false; + + Request _request = new Request(); + APIId apiId = new APIId + { + Name = "alibaba.trade.get.buyerView", + NamespaceValue = "com.alibaba.trade", + Version = 1 + }; + _request.ApiId = apiId; + + var param = new + { + webSite = "1688", + orderId = request.OrderId, + includeFields = "baseInfo,productItems" + }; + _request.RequestEntity = param; + if (!string.IsNullOrEmpty(request.AppToken)) + _request.AccessToken = request.AppToken; + var result = client.NewRequest(_request, reqPolicy); + if (result.Value("success") != true) + throw new Exception(result.Value("errorMessage")); + + + return new PP_QueryOrderDetailResponse() + { + OrderId = request.OrderId, + FreightAmount = result["result"]["baseInfo"].Value("shippingFee"), + ProductAmount = result["result"]["baseInfo"].Value("totalAmount") - result["result"]["baseInfo"].Value("shippingFee"), + TotalAmount = result["result"]["baseInfo"].Value("totalAmount"), + ItemList = result["result"]["productItems"].Select(itemJToken => new PP_QueryOrderDetailSkuResponse() + { + ProductId = itemJToken.Value("productID"), + SkuId = itemJToken.Value("skuID"), + SpecId = itemJToken.Value("specId"), + ProductAmount = itemJToken.Value("itemAmount"), + Quantity = Convert.ToInt32(itemJToken.Value("quantity")), + Price = itemJToken.Value("price") + }).ToList() + }; + } } public class _1688TradeTypeCompare : IEqualityComparer diff --git a/SDKAdapter/PurchasePlatform/Models/Request/Order/PP_QueryOrderDetailRequest.cs b/SDKAdapter/PurchasePlatform/Models/Request/Order/PP_QueryOrderDetailRequest.cs new file mode 100644 index 0000000..5ec74c2 --- /dev/null +++ b/SDKAdapter/PurchasePlatform/Models/Request/Order/PP_QueryOrderDetailRequest.cs @@ -0,0 +1,7 @@ +namespace SDKAdapter.PurchasePlatform.Models +{ + public class PP_QueryOrderDetailRequest: BasePlatformRequest + { + public string OrderId { get; set; } + } +} diff --git a/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_CreateOrderResponse.cs b/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_CreateOrderResponse.cs index f68399b..f076314 100644 --- a/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_CreateOrderResponse.cs +++ b/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_CreateOrderResponse.cs @@ -3,7 +3,7 @@ public class PP_CreateOrderResponse : PP_PreviewOrderResponse { /// - /// 订单Id + /// 采购单Id /// public string OrderId { get; set; } diff --git a/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_QueryOrderDetailResponse.cs b/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_QueryOrderDetailResponse.cs new file mode 100644 index 0000000..769b497 --- /dev/null +++ b/SDKAdapter/PurchasePlatform/Models/Response/Order/PP_QueryOrderDetailResponse.cs @@ -0,0 +1,54 @@ +namespace SDKAdapter.PurchasePlatform.Models +{ + public class PP_QueryOrderDetailResponse + { + /// + /// 采购单号 + /// + public string OrderId { get; set; } + + /// + /// 订单总额 + /// + public decimal TotalAmount { get; set; } + + /// + /// 货款总额 + /// + public decimal ProductAmount { get; set; } + + /// + /// 运费总额 + /// + public decimal FreightAmount { get; set; } + + /// + /// 订单Sku明细列表 + /// + public IList ItemList { get; set; } + } + + /// + /// 采购单简单明细 + /// + public class PP_QueryOrderDetailSkuResponse + { + public string ProductId { get; set; } + + public string SkuId { get; set; } + + public string SpecId { get; set; } + + /// + /// 货款金额 + /// + public decimal ProductAmount { get; set; } + + /// + /// 单价 + /// + public decimal Price { get; set; } + + public int Quantity { get; set; } + } +} diff --git a/bbwyb.sln b/bbwyb.sln index 4097edf..0acbb0f 100644 --- a/bbwyb.sln +++ b/bbwyb.sln @@ -25,15 +25,15 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "SDK", "SDK", "{B4ED118A-2CF EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SDKAdapter", "SDKAdapter\SDKAdapter.csproj", "{442CC858-3A90-48EE-932D-756169EAC2A4}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "QuanTan.SDK", "QuanTan.SDK\QuanTan.SDK.csproj", "{D5D93778-14D7-45F7-A77C-397FDBA408A1}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "QuanTan.SDK", "QuanTan.SDK\QuanTan.SDK.csproj", "{D5D93778-14D7-45F7-A77C-397FDBA408A1}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "C", "C", "{AE01E0D8-FE79-4E30-B68F-862A5907EB3A}" EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "B", "B", "{0142C6AF-5824-4665-8E9E-3A3C547BA109}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "_1688.SDK", "_1688.SDK\_1688.SDK.csproj", "{450F51B1-29E6-47F3-A517-AD5814EC9129}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "_1688.SDK", "_1688.SDK\_1688.SDK.csproj", "{450F51B1-29E6-47F3-A517-AD5814EC9129}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "JD.SDK", "JD.SDK\JD.SDK.csproj", "{A4C4F802-D298-42DE-B410-50C8C87EFFAA}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "JD.SDK", "JD.SDK\JD.SDK.csproj", "{A4C4F802-D298-42DE-B410-50C8C87EFFAA}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -87,6 +87,7 @@ Global EndGlobalSection GlobalSection(NestedProjects) = preSolution {B6039632-07B7-4C74-9F74-F16B6782EF56} = {99D234A0-6830-4C0C-91E8-C626DA939D59} + {99D234A0-6830-4C0C-91E8-C626DA939D59} = {0142C6AF-5824-4665-8E9E-3A3C547BA109} {1E7D36DB-A817-4208-8FC6-36A66FAB17E5} = {0142C6AF-5824-4665-8E9E-3A3C547BA109} {D52D0167-EF94-4FC8-91BF-FCE5B3ED9C6A} = {1E7D36DB-A817-4208-8FC6-36A66FAB17E5} {52DF7178-3C36-4CA6-A2E9-D9E2BB41C0B8} = {99D234A0-6830-4C0C-91E8-C626DA939D59}