322 lines
12 KiB
C#
322 lines
12 KiB
C#
using MyCode.Project.Domain.Message.Request.KingDee;
|
||
using MyCode.Project.Domain.Message.Request.KingDee.SaveModel;
|
||
using MyCode.Project.Domain.Message.Response.KingDee.K3Result;
|
||
using MyCode.Project.Domain.Message.Response.KingDee.K3Result.Model;
|
||
using MyCode.Project.Domain.Model;
|
||
using MyCode.Project.Domain.Repositories;
|
||
using MyCode.Project.Infrastructure.Common;
|
||
using MyCode.Project.Infrastructure.Exceptions;
|
||
using MyCode.Project.Infrastructure.Extensions;
|
||
using MyCode.Project.OutSideService;
|
||
using MyCode.Project.Services.IServices;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Linq;
|
||
|
||
namespace MyCode.Project.Services.Implementation
|
||
{
|
||
/// <summary>
|
||
/// 采购入库单服务实现
|
||
/// 功能:处理采购入库单推送到金蝶云星空的业务逻辑
|
||
/// </summary>
|
||
public class PurchaseStockInService : ServiceBase, IPurchaseStockInService
|
||
{
|
||
private const string BILL_TYPE_CODE = "RKD01_SYS";
|
||
private const string OWNER_TYPE = "BD_OwnerOrg";
|
||
private const string EXCHANGE_TYPE = "HLTX01_SYS";
|
||
private const string STOCK_STATUS = "KCZT01_SYS";
|
||
private const string DEFAULT_ORG = "100";
|
||
private const string DEFAULT_CURRENCY = "PRE001";
|
||
private const string DEFAULT_UNIT = "Pcs";
|
||
private const string ROW_TYPE_STANDARD = "Standard";
|
||
private const string ROW_TYPE_SERVICE = "Service";
|
||
private const string FORM_ID = "STK_InStock";
|
||
|
||
private IPushKingDeeGoodsDocInRepository _pushKingDeeGoodsDocInRepository;
|
||
private IBusiOrderGoodsDocInRepository _busiOrderGoodsDocInRepository;
|
||
private IYTKJTShopParameterRepository _yTKJTShopParameterRepository;
|
||
private IKingDeeService _kingDeeService;
|
||
|
||
public PurchaseStockInService(
|
||
IPushKingDeeGoodsDocInRepository pushKingDeeGoodsDocInRepository,
|
||
IBusiOrderGoodsDocInRepository busiOrderGoodsDocInRepository,
|
||
IYTKJTShopParameterRepository yTKJTShopParameterRepository,
|
||
IKingDeeService kingDeeService)
|
||
{
|
||
_pushKingDeeGoodsDocInRepository = pushKingDeeGoodsDocInRepository;
|
||
_busiOrderGoodsDocInRepository = busiOrderGoodsDocInRepository;
|
||
_yTKJTShopParameterRepository = yTKJTShopParameterRepository;
|
||
_kingDeeService = kingDeeService;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 推送采购入库单到金蝶云星空
|
||
/// </summary>
|
||
/// <param name="id">PushKingDeeGoodsDocIn表的主键ID(Guid格式的字符串)</param>
|
||
/// <returns>返回金蝶API的响应结果(JSON格式)</returns>
|
||
public string PushPurchaseStockInToKingDee(string id)
|
||
{
|
||
var goodsDocIn = _pushKingDeeGoodsDocInRepository
|
||
.Queryable()
|
||
.Where(t => id == t.ID.ToString())
|
||
.First();
|
||
|
||
if (goodsDocIn == null)
|
||
{
|
||
throw new BaseException($"未找到ID为 {id} 的采购入库单记录");
|
||
}
|
||
|
||
if (goodsDocIn.Status ==2 )
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 已经推送过,状态为:{goodsDocIn.Status},不允许重复推送");
|
||
}
|
||
|
||
var param = _yTKJTShopParameterRepository
|
||
.Queryable()
|
||
.Where(t => t.FDOCUMENTSTATUS == "C")
|
||
.First();
|
||
|
||
if (param == null)
|
||
{
|
||
throw new BaseException("没有找到已审核的门店参数配置,请联系管理员检查门店参数表");
|
||
}
|
||
|
||
if (param.FPURCHASERECEIVING == "0")
|
||
{
|
||
throw new BaseException("门店参数配置中采购入库单同步功能未启用,请联系管理员检查门店参数配置");
|
||
}
|
||
|
||
if (param.FPURCHASERECEIVING == "1")
|
||
{
|
||
var response = PushKingdeePurchaseStockIn(goodsDocIn, param);
|
||
string result = JsonHelper.ToJson(response);
|
||
|
||
if (response.IsSuccess)
|
||
{
|
||
var allRecords = _pushKingDeeGoodsDocInRepository
|
||
.Queryable()
|
||
.Where(t => t.GoodsdocNo == goodsDocIn.GoodsdocNo)
|
||
.ToList();
|
||
|
||
foreach (var record in allRecords)
|
||
{
|
||
record.Status = 2;
|
||
_pushKingDeeGoodsDocInRepository.Update(record);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
return "";
|
||
}
|
||
|
||
private K3CloudResponseStatus PushKingdeePurchaseStockIn(PushKingDeeGoodsDocIn goodsDocIn, YTKJTShopParameter param)
|
||
{
|
||
// 从BusiOrderGoodsDocIn表获取明细数据
|
||
var detailList = _busiOrderGoodsDocInRepository
|
||
.Queryable()
|
||
.Where(t => t.GoodsdocNo == goodsDocIn.GoodsdocNo)
|
||
.ToList();
|
||
|
||
if (detailList == null || detailList.Count == 0)
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 没有找到明细数据,无法推送");
|
||
}
|
||
|
||
var vendorCodes = detailList.Where(d => !string.IsNullOrEmpty(d.VendCode))
|
||
.Select(d => d.VendCode)
|
||
.Distinct()
|
||
.ToList();
|
||
if (vendorCodes.Count > 1)
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 明细行中存在不同的供应商编码:{string.Join(",", vendorCodes)},无法推送");
|
||
}
|
||
|
||
// 获取第一条明细用于主表信息
|
||
var firstDetail = detailList.FirstOrDefault();
|
||
if (firstDetail == null)
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 明细数据为空,无法推送");
|
||
}
|
||
|
||
// 获取采购组织ID
|
||
string purchaseOrgId = param.FPURCHASEORGID?.ToString() ?? param.FSALEORGID?.ToString() ?? DEFAULT_ORG;
|
||
|
||
// 获取仓库编码
|
||
string warehouseCode = firstDetail.WarehouseCode ?? param.FPURCHASINGWAREHOUSECODE ?? "";
|
||
|
||
// 数据校验
|
||
if (string.IsNullOrEmpty(firstDetail.VendCode))
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 供应商编码为空,无法推送");
|
||
}
|
||
if (string.IsNullOrEmpty(warehouseCode))
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 仓库编码为空,无法推送");
|
||
}
|
||
|
||
// 构建金蝶API的明细行数据
|
||
var entryList = detailList.Select((n, index) => BuildEntryItem(n, param, purchaseOrgId, warehouseCode)).ToList();
|
||
|
||
if (entryList.Count == 0)
|
||
{
|
||
throw new BaseException($"采购入库单 {goodsDocIn.GoodsdocNo} 明细数据转换失败,无法推送");
|
||
}
|
||
|
||
// 构建金蝶API的主表数据
|
||
var model = BuildMainModel(goodsDocIn, firstDetail, param, purchaseOrgId, entryList);
|
||
|
||
// 构建金蝶API请求对象
|
||
BillSave billSave = new BillSave()
|
||
{
|
||
Model = model,
|
||
IsAutoSubmitAndAudit = false,
|
||
};
|
||
|
||
// 调用金蝶服务保存单据
|
||
var responseStatus = _kingDeeService.Save(FORM_ID, billSave);
|
||
return responseStatus;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 构建明细行数据
|
||
/// </summary>
|
||
private FPurchaseStockInEntryItem BuildEntryItem(BusiOrderGoodsDocIn detail, YTKJTShopParameter param, string orgId, string warehouseCode)
|
||
{
|
||
// 根据入库类型动态设置FRowType(如果入库类型包含"服务"或"费用"等关键字,则设置为Service,否则为Standard)
|
||
string rowType = ROW_TYPE_STANDARD;
|
||
if (!string.IsNullOrEmpty(detail.InouttypeName))
|
||
{
|
||
string inoutType = detail.InouttypeName.ToUpper();
|
||
if (inoutType.Contains("服务") || inoutType.Contains("费用") || inoutType.Contains("SERVICE") || inoutType.Contains("FEE"))
|
||
{
|
||
rowType = ROW_TYPE_SERVICE;
|
||
}
|
||
}
|
||
|
||
// 计算折扣后金额(无税金额)
|
||
decimal? allAmountExceptDisCount = detail.BaceCurrencyNoTaxAmount ?? 0;
|
||
|
||
return new FPurchaseStockInEntryItem()
|
||
{
|
||
Fcode = detail.SkuBarcode ?? "",
|
||
FRowType = rowType,
|
||
//FMaterialId = new FMaterialId()
|
||
//{
|
||
// FNumber = detail.SkuBarcode ?? ""
|
||
//},
|
||
//FUnitID = new FUnitID()
|
||
//{
|
||
// FNumber = detail.UnitName ?? DEFAULT_UNIT
|
||
//},
|
||
//FMaterialDesc = detail.GoodsName ?? "",
|
||
FWWPickMtlQty = 0,
|
||
FRealQty = detail.Quantity ?? 0,
|
||
//FPriceUnitID = new FPriceUnitID()
|
||
//{
|
||
// FNumber = detail.UnitName ?? DEFAULT_UNIT
|
||
//},
|
||
FPrice = detail.BaceCurrencyNoTaxPrice ?? 0,
|
||
FDisPriceQty = 0,
|
||
FStockID = new FStockID()
|
||
{
|
||
FNumber = param.FPURCHASINGWAREHOUSECODE
|
||
},
|
||
FStockStatusId = new FStockStatusId()
|
||
{
|
||
FNumber = STOCK_STATUS
|
||
},
|
||
FGiveAway = false,
|
||
FOWNERTYPEID = OWNER_TYPE,
|
||
FExtAuxUnitQty = 0,
|
||
FCheckInComing = false,
|
||
FIsReceiveUpdateStock = false,
|
||
FInvoicedJoinQty = 0,
|
||
FPriceBaseQty = detail.Quantity ?? 0,
|
||
FRemainInStockUnitId = new FRemainInStockUnitId()
|
||
{
|
||
FOrgId = param.FPURCHASEORGID.SafeValue().ToString(),
|
||
},
|
||
FBILLINGCLOSE = false,
|
||
FRemainInStockQty = detail.Quantity ?? 0,
|
||
FRemainInStockBaseQty = detail.Quantity ?? 0,
|
||
FAPNotJoinQty = detail.Quantity ?? 0,
|
||
FTaxPrice = detail.BaceCurrencyWithTaxPrice ?? 0,
|
||
|
||
FOWNERID = new FOwnerId()
|
||
{
|
||
FOrgId = orgId
|
||
},
|
||
|
||
|
||
};
|
||
}
|
||
|
||
private PurchaseStockInModel BuildMainModel(PushKingDeeGoodsDocIn goodsDocIn, BusiOrderGoodsDocIn firstDetail, YTKJTShopParameter param, string orgId, List<FPurchaseStockInEntryItem> entryList)
|
||
{
|
||
string dateStr = goodsDocIn.InOutDate2?.ToString("yyyy-MM-dd HH:mm:ss") ?? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
|
||
|
||
return new PurchaseStockInModel()
|
||
{
|
||
FID = 0,
|
||
FBillTypeID = new FBillTypeID()
|
||
{
|
||
FNUMBER = BILL_TYPE_CODE
|
||
},
|
||
FDate = dateStr,
|
||
IsVerifyBaseDataField=true,
|
||
FStockOrgId = new FStockOrgId()
|
||
{
|
||
FOrgId = orgId
|
||
},
|
||
FDemandOrgId = new FDemandOrgId()
|
||
{
|
||
FOrgId = orgId
|
||
},
|
||
|
||
|
||
FPurchaseOrgId = new FPurchaseOrgId()
|
||
{
|
||
FOrgId = orgId
|
||
},
|
||
|
||
FSupplierId = new FSupplierId()
|
||
{
|
||
FNumber = firstDetail.VendCode
|
||
},
|
||
FOwnerTypeIdHead = OWNER_TYPE,
|
||
FOwnerIdHead = new FOwnerIdHead()
|
||
{
|
||
FOrgId = orgId
|
||
},
|
||
FCDateOffsetValue = 0,
|
||
FSplitBillType = "A",
|
||
|
||
FInStockFin = new FInStockFin()
|
||
{
|
||
|
||
FSettleCurrId = new FSettleCurrId()
|
||
{
|
||
FNumber = DEFAULT_CURRENCY
|
||
},
|
||
FIsIncludedTax = true,
|
||
FPriceTimePoint = "1",
|
||
FLocalCurrId = new FLocalCurrId()
|
||
{
|
||
FNumber = DEFAULT_CURRENCY
|
||
},
|
||
FExchangeTypeId = new FExchangeTypeId()
|
||
{
|
||
FNumber = EXCHANGE_TYPE
|
||
},
|
||
FExchangeRate = 1m,
|
||
FISPRICEEXCLUDETAX = true,
|
||
},
|
||
FInStockEntry = entryList
|
||
};
|
||
}
|
||
}
|
||
}
|
||
|