313 lines
12 KiB
C#
Raw Normal View History

2025-11-09 20:26:53 +08:00
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;
2025-11-18 18:44:31 +08:00
using MyCode.Project.Infrastructure.Extensions;
2025-11-09 20:26:53 +08:00
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";
2025-11-18 18:44:31 +08:00
private const string FORM_ID = "STK_InStock";
2025-11-09 20:26:53 +08:00
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表的主键IDGuid格式的字符串</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} 的采购入库单记录");
}
2025-11-18 18:44:31 +08:00
if (goodsDocIn.Status ==2 )
2025-11-09 20:26:53 +08:00
{
2025-11-24 16:06:01 +08:00
throw new BaseException($"{goodsDocIn.InOutDate2}+{goodsDocIn.VendCustomerName}的采购入库单已经推送过,状态为:{goodsDocIn.Status},不允许重复推送");
2025-11-09 20:26:53 +08:00
}
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)
{
2025-11-24 16:06:01 +08:00
goodsDocIn.Status = 2;
_pushKingDeeGoodsDocInRepository.Update(goodsDocIn);
2025-11-09 20:26:53 +08:00
}
return result;
}
return "";
}
private K3CloudResponseStatus PushKingdeePurchaseStockIn(PushKingDeeGoodsDocIn goodsDocIn, YTKJTShopParameter param)
{
// 从BusiOrderGoodsDocIn表获取明细数据
var detailList = _busiOrderGoodsDocInRepository
.Queryable()
2025-11-26 11:56:51 +08:00
.Where(t => t.InOutDate2.Value.ToString("yyyy-MM-dd") == goodsDocIn.InOutDate2.Value.ToString("yyyy-MM-dd") && t.VendCode==goodsDocIn.VendCode && t.Status==1 )
2025-11-09 20:26:53 +08:00
.ToList();
if (detailList == null || detailList.Count == 0)
{
2025-11-24 16:06:01 +08:00
throw new BaseException($"没有找到明细数据,无法推送");
2025-11-09 20:26:53 +08:00
}
// 获取第一条明细用于主表信息
var firstDetail = detailList.FirstOrDefault();
if (firstDetail == null)
{
2025-11-24 16:06:01 +08:00
throw new BaseException($" 明细数据为空,无法推送");
2025-11-09 20:26:53 +08:00
}
// 获取采购组织ID
string purchaseOrgId = param.FPURCHASEORGID?.ToString() ?? param.FSALEORGID?.ToString() ?? DEFAULT_ORG;
// 获取仓库编码
2025-11-24 16:06:01 +08:00
string warehouseCode =param.FPURCHASINGWAREHOUSECODE ;
2025-11-09 20:26:53 +08:00
// 构建金蝶API的明细行数据
var entryList = detailList.Select((n, index) => BuildEntryItem(n, param, purchaseOrgId, warehouseCode)).ToList();
if (entryList.Count == 0)
{
2025-11-24 16:06:01 +08:00
throw new BaseException($"采购入库单明细数据转换失败,无法推送");
2025-11-09 20:26:53 +08:00
}
// 构建金蝶API的主表数据
var model = BuildMainModel(goodsDocIn, firstDetail, param, purchaseOrgId, entryList);
// 构建金蝶API请求对象
BillSave billSave = new BillSave()
{
Model = model,
2025-11-18 18:44:31 +08:00
IsAutoSubmitAndAudit = false,
2025-11-09 20:26:53 +08:00
};
// 调用金蝶服务保存单据
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()
{
2025-11-18 18:44:31 +08:00
Fcode = detail.SkuBarcode ?? "",
2025-11-09 20:26:53 +08:00
FRowType = rowType,
2025-11-18 18:44:31 +08:00
//FMaterialId = new FMaterialId()
//{
// FNumber = detail.SkuBarcode ?? ""
//},
//FUnitID = new FUnitID()
//{
// FNumber = detail.UnitName ?? DEFAULT_UNIT
//},
//FMaterialDesc = detail.GoodsName ?? "",
2025-11-09 20:26:53 +08:00
FWWPickMtlQty = 0,
FRealQty = detail.Quantity ?? 0,
2025-11-18 18:44:31 +08:00
//FPriceUnitID = new FPriceUnitID()
//{
// FNumber = detail.UnitName ?? DEFAULT_UNIT
//},
2025-11-09 20:26:53 +08:00
FPrice = detail.BaceCurrencyNoTaxPrice ?? 0,
FDisPriceQty = 0,
2025-11-18 18:44:31 +08:00
FStockID = new FStockID()
{
FNumber = param.FPURCHASINGWAREHOUSECODE
},
2025-11-09 20:26:53 +08:00
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()
{
2025-11-18 18:44:31 +08:00
FOrgId = param.FPURCHASEORGID.SafeValue().ToString(),
2025-11-09 20:26:53 +08:00
},
FBILLINGCLOSE = false,
FRemainInStockQty = detail.Quantity ?? 0,
FRemainInStockBaseQty = detail.Quantity ?? 0,
FAPNotJoinQty = detail.Quantity ?? 0,
2025-11-18 18:44:31 +08:00
FTaxPrice = detail.BaceCurrencyWithTaxPrice ?? 0,
2025-11-09 20:26:53 +08:00
FOWNERID = new FOwnerId()
{
2025-11-18 18:44:31 +08:00
FOrgId = orgId
2025-11-09 20:26:53 +08:00
},
2025-11-18 18:44:31 +08:00
2025-11-09 20:26:53 +08:00
};
}
private PurchaseStockInModel BuildMainModel(PushKingDeeGoodsDocIn goodsDocIn, BusiOrderGoodsDocIn firstDetail, YTKJTShopParameter param, string orgId, List<FPurchaseStockInEntryItem> entryList)
{
2025-11-24 16:06:01 +08:00
//JKCR+年月日+自增ID三位
2025-11-11 10:14:00 +08:00
string dateStr = goodsDocIn.InOutDate2?.ToString("yyyy-MM-dd HH:mm:ss") ?? DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
2025-11-24 16:06:01 +08:00
string FBillNo = GenerateBillNo(goodsDocIn.SortId, goodsDocIn.InOutDate2.Value);
2025-11-09 20:26:53 +08:00
return new PurchaseStockInModel()
{
2025-11-24 16:06:01 +08:00
FBillNo= FBillNo,
2025-11-09 20:26:53 +08:00
FID = 0,
FBillTypeID = new FBillTypeID()
{
FNUMBER = BILL_TYPE_CODE
},
FDate = dateStr,
2025-11-18 18:44:31 +08:00
IsVerifyBaseDataField=true,
2025-11-09 20:26:53 +08:00
FStockOrgId = new FStockOrgId()
{
2025-11-18 18:44:31 +08:00
FOrgId = orgId
2025-11-09 20:26:53 +08:00
},
FDemandOrgId = new FDemandOrgId()
{
2025-11-18 18:44:31 +08:00
FOrgId = orgId
2025-11-09 20:26:53 +08:00
},
2025-11-18 18:44:31 +08:00
FPurchaseOrgId = new FPurchaseOrgId()
2025-11-09 20:26:53 +08:00
{
2025-11-18 18:44:31 +08:00
FOrgId = orgId
2025-11-09 20:26:53 +08:00
},
2025-11-18 18:44:31 +08:00
2025-11-18 19:09:14 +08:00
FSupplierId = new FSupplierId()
2025-11-09 20:26:53 +08:00
{
2025-11-18 18:44:31 +08:00
FNumber = firstDetail.VendCode
2025-11-09 20:26:53 +08:00
},
FOwnerTypeIdHead = OWNER_TYPE,
FOwnerIdHead = new FOwnerIdHead()
{
2025-11-18 18:44:31 +08:00
FOrgId = orgId
2025-11-09 20:26:53 +08:00
},
FCDateOffsetValue = 0,
FSplitBillType = "A",
2025-11-18 18:44:31 +08:00
2025-11-09 20:26:53 +08:00
FInStockFin = new FInStockFin()
{
2025-11-18 18:44:31 +08:00
2025-11-09 20:26:53 +08:00
FSettleCurrId = new FSettleCurrId()
{
2025-11-18 18:44:31 +08:00
FNumber = DEFAULT_CURRENCY
2025-11-09 20:26:53 +08:00
},
FIsIncludedTax = true,
FPriceTimePoint = "1",
FLocalCurrId = new FLocalCurrId()
{
2025-11-18 18:44:31 +08:00
FNumber = DEFAULT_CURRENCY
2025-11-09 20:26:53 +08:00
},
FExchangeTypeId = new FExchangeTypeId()
{
FNumber = EXCHANGE_TYPE
},
2025-11-18 18:44:31 +08:00
FExchangeRate = 1m,
2025-11-09 20:26:53 +08:00
FISPRICEEXCLUDETAX = true,
},
FInStockEntry = entryList
};
}
2025-11-24 16:06:01 +08:00
/**
* JKXC++ID--
JKXT++ID--退
JKCR++ID--
JKCT++ID--退
**/
private string GenerateBillNo(int Sheet, DateTime date)
{
string prefix = "JKCR" + date.ToString("yyyyMMdd");
string numberPart = (Sheet > 0 ? Sheet.ToString() : "").PadLeft(3, '0');
numberPart = numberPart.Length > 3 ? numberPart.Substring(numberPart.Length - 3) : numberPart;
// 组合并确保只取最后3位数字
string combined = prefix + numberPart;
return combined;
}
2025-11-09 20:26:53 +08:00
}
}