| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- package com.jeesite.modules.mes.erp;
- import com.alibaba.fastjson.JSONArray;
- import com.alibaba.fastjson.JSONObject;
- import com.jeesite.common.lang.StringUtils;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.stereotype.Service;
- import java.util.ArrayList;
- import java.util.LinkedHashMap;
- import java.util.List;
- import java.util.Map;
- /**
- * ERP 直接调拨单 BillQuery(STK_TransferDirect)。
- * 固定仅查 HEV / 115 两种物料编码。
- */
- @Service
- public class ErpTransferDirectService {
- private static final Logger logger = LoggerFactory.getLogger(ErpTransferDirectService.class);
- private static final String FORM_ID = "STK_TransferDirect";
- private static final String BILL_TYPE_FIELD = "FBillTypeID.FNUMBER";
- private static final String MATERIAL_NUMBER_FIELD = "FMaterialId.FNUMBER";
- private static final String DETAIL_FIELD_KEYS = String.join(",",
- "FID",
- "FBILLNO",
- "FDate",
- "FDocumentStatus",
- BILL_TYPE_FIELD,
- "FBillTypeID.FNAME",
- "FStockOrgId.FNUMBER",
- "FStockOrgId.FNAME",
- "FStockOutOrgId.FNUMBER",
- "FStockOutOrgId.FNAME",
- "FBillEntry_FEntryID",
- "FBillEntry_FSeq",
- MATERIAL_NUMBER_FIELD,
- "FMaterialName",
- "FUnitID.FNAME",
- "FQty",
- "FSrcStockId.FNUMBER",
- "FSrcStockId.FNAME",
- "FDestStockId.FNUMBER",
- "FDestStockId.FNAME",
- "FLot.FNUMBER",
- "FSrcBillNo",
- "FOrderNo",
- "FNote");
- private final KingdeeErpClient erpClient;
- private final KingdeeErpProperties erpProperties;
- public ErpTransferDirectService(KingdeeErpClient erpClient, KingdeeErpProperties erpProperties) {
- this.erpClient = erpClient;
- this.erpProperties = erpProperties;
- }
- /**
- * 分页查询调拨明细分录(仅 HEV / 115 物料)。
- */
- public List<ErpTransferDirect> findPageList(ErpTransferDirect query, int startRow, int limit) {
- JSONObject data = new JSONObject();
- data.put("FormId", FORM_ID);
- data.put("FieldKeys", DETAIL_FIELD_KEYS);
- data.put("FilterString", buildFilterString(query));
- data.put("OrderString", "FDate DESC,FBILLNO DESC,FBillEntry_FSeq");
- data.put("StartRow", Math.max(startRow, 0));
- data.put("Limit", Math.max(limit, 1));
- logger.info("ERP transfer direct query: {}", data.toJSONString());
- return mapRows(erpClient.billQuery(data));
- }
- /**
- * 指定调拨单号的全部分录(仍限定 HEV / 115 物料)。
- */
- public List<ErpTransferDirect> findDetailList(String billNo) {
- if (StringUtils.isBlank(billNo)) {
- return new ArrayList<>();
- }
- ErpTransferDirect query = new ErpTransferDirect();
- query.setBillNoQuery(billNo.trim());
- return findPageList(query, 0, 2000);
- }
- /**
- * 生产订单下查:优先按源单/订单号/关联内码,再按生产入库批号关联调拨单。
- * ERP 直接调拨单无 FMoBillNo,与生产订单的关联主要通过生产入库批号(FLot)建立。
- */
- public List<ErpTransferDirect> findTraceListByMoBillNo(String moBillNo, String moFid, List<String> instockLots) {
- if (StringUtils.isBlank(moBillNo)) {
- return new ArrayList<>();
- }
- Map<String, ErpTransferDirect> merged = new LinkedHashMap<>();
- appendTraceRows(merged, findTraceByDirectLink(moBillNo.trim(), moFid));
- appendTraceRows(merged, findTraceByInstockLots(instockLots));
- return new ArrayList<>(merged.values());
- }
- private void appendTraceRows(Map<String, ErpTransferDirect> merged, List<ErpTransferDirect> rows) {
- if (rows == null || rows.isEmpty()) {
- return;
- }
- for (ErpTransferDirect row : rows) {
- if (row == null || StringUtils.isBlank(row.getId())) {
- continue;
- }
- merged.putIfAbsent(row.getId(), row);
- }
- }
- private List<ErpTransferDirect> findTraceByDirectLink(String moBillNo, String moFid) {
- String escapedMo = escape(moBillNo);
- StringBuilder linkFilter = new StringBuilder("(FSrcBillNo='").append(escapedMo).append("' OR FOrderNo='")
- .append(escapedMo).append("')");
- if (StringUtils.isNotBlank(moFid)) {
- linkFilter.append(" OR FBillEntry_Link_FSBillId=").append(moFid.trim());
- }
- return queryTraceList("(" + linkFilter + ")");
- }
- private List<ErpTransferDirect> findTraceByInstockLots(List<String> instockLots) {
- if (instockLots == null || instockLots.isEmpty()) {
- return new ArrayList<>();
- }
- List<String> normalizedLots = new ArrayList<>();
- for (String lot : instockLots) {
- if (StringUtils.isBlank(lot)) {
- continue;
- }
- String trimmed = lot.trim();
- if (!normalizedLots.contains(trimmed)) {
- normalizedLots.add(trimmed);
- }
- }
- if (normalizedLots.isEmpty()) {
- return new ArrayList<>();
- }
- StringBuilder builder = new StringBuilder("FLot.FNUMBER IN(");
- for (int i = 0; i < normalizedLots.size(); i++) {
- if (i > 0) {
- builder.append(",");
- }
- builder.append("'").append(escape(normalizedLots.get(i))).append("'");
- }
- builder.append(")");
- return queryTraceList(builder.toString());
- }
- private List<ErpTransferDirect> queryTraceList(String traceFilter) {
- if (StringUtils.isBlank(traceFilter)) {
- return new ArrayList<>();
- }
- JSONObject data = new JSONObject();
- data.put("FormId", FORM_ID);
- data.put("FieldKeys", DETAIL_FIELD_KEYS);
- data.put("FilterString", appendAnd(buildTraceBaseFilter(), traceFilter));
- data.put("OrderString", "FDate DESC,FBILLNO DESC,FBillEntry_FSeq");
- data.put("StartRow", 0);
- data.put("Limit", 2000);
- logger.info("ERP transfer direct trace query: {}", data.toJSONString());
- return mapRows(erpClient.billQuery(data));
- }
- private String buildTraceBaseFilter() {
- return buildBaseFilter();
- }
- private List<ErpTransferDirect> mapRows(JSONArray rows) {
- List<ErpTransferDirect> list = new ArrayList<>();
- for (int i = 0; i < rows.size(); i++) {
- list.add(toDetail(rows.getJSONObject(i), i));
- }
- return list;
- }
- private ErpTransferDirect toDetail(JSONObject row, int index) {
- ErpTransferDirect item = new ErpTransferDirect();
- item.setFid(readString(row, "FID"));
- item.setBillNo(readString(row, "FBILLNO", "FBillNo"));
- item.setEntryId(readString(row, "FBillEntry_FEntryID", "FBillEntry_FEntryId"));
- item.setSeq(readString(row, "FBillEntry_FSeq"));
- String rowId = item.getBillNo();
- if (StringUtils.isNotBlank(item.getEntryId())) {
- rowId = rowId + "-" + item.getEntryId();
- } else if (index >= 0) {
- rowId = rowId + "-" + index;
- }
- item.setId(rowId);
- item.setDocumentStatus(readString(row, "FDocumentStatus"));
- item.setDocumentStatusName(documentStatusName(item.getDocumentStatus()));
- item.setDate(formatErpDate(readString(row, "FDate")));
- item.setBillTypeNumber(readString(row, BILL_TYPE_FIELD, "FBillTypeID.FNumber"));
- item.setBillTypeName(readString(row, "FBillTypeID.FNAME", "FBillTypeID.FName"));
- item.setStockOrgNumber(readString(row, "FStockOrgId.FNUMBER", "FStockOrgId.FNumber"));
- item.setStockOrgName(readString(row, "FStockOrgId.FNAME", "FStockOrgId.FName"));
- item.setStockOutOrgNumber(readString(row, "FStockOutOrgId.FNUMBER", "FStockOutOrgId.FNumber"));
- item.setStockOutOrgName(readString(row, "FStockOutOrgId.FNAME", "FStockOutOrgId.FName"));
- item.setMaterialNumber(readString(row, MATERIAL_NUMBER_FIELD, "FMaterialId.FNumber"));
- item.setMaterialName(readString(row, "FMaterialName", "FMaterialId.FNAME", "FMaterialId.FName"));
- item.setUnitName(readString(row, "FUnitID.FNAME", "FUnitId.FNAME", "FUnitId.FName"));
- item.setQty(ErpKingdeeParseUtils.normalizeQtyNullable(row.getBigDecimal("FQty")));
- item.setSrcStockNumber(readString(row, "FSrcStockId.FNUMBER", "FSrcStockId.FNumber"));
- item.setSrcStockName(readString(row, "FSrcStockId.FNAME", "FSrcStockId.FName"));
- item.setDestStockNumber(readString(row, "FDestStockId.FNUMBER", "FDestStockId.FNumber"));
- item.setDestStockName(readString(row, "FDestStockId.FNAME", "FDestStockId.FName"));
- item.setLotNumber(readString(row, "FLot.FNUMBER", "FLot.FNumber"));
- item.setSrcBillNo(trimToEmpty(readString(row, "FSrcBillNo")));
- item.setOrderNo(trimToEmpty(readString(row, "FOrderNo")));
- item.setNote(readString(row, "FNote"));
- return item;
- }
- private String trimToEmpty(String value) {
- return value == null ? "" : value.trim();
- }
- private String buildFilterString(ErpTransferDirect query) {
- String filter = buildBaseFilter();
- if (query == null) {
- return filter;
- }
- if (StringUtils.isNotBlank(query.getBillNoQuery())) {
- filter = appendAnd(filter, "FBILLNO like '%" + escape(query.getBillNoQuery()) + "%'");
- } else if (StringUtils.isNotBlank(query.getBillNo())) {
- filter = appendAnd(filter, "FBILLNO='" + escape(query.getBillNo()) + "'");
- }
- if (StringUtils.isNotBlank(query.getDocumentStatusQuery())) {
- filter = appendAnd(filter, "FDocumentStatus='" + escape(query.getDocumentStatusQuery()) + "'");
- }
- String materialFilter = buildMaterialFilter(query.getMaterialNumberQuery());
- if (StringUtils.isNotBlank(materialFilter)) {
- filter = appendAnd(filter, materialFilter);
- }
- return filter;
- }
- /**
- * 物料范围:默认固定 HEV + 115;页面可选缩小到其中一个。
- */
- private String buildMaterialFilter(String materialNumberQuery) {
- if (StringUtils.isNotBlank(materialNumberQuery)) {
- String trimmed = materialNumberQuery.trim();
- if (erpProperties.isAllowedTransferDirectMaterial(trimmed)) {
- return MATERIAL_NUMBER_FIELD + "='" + escape(trimmed) + "'";
- }
- }
- return buildAllowedMaterialInFilter();
- }
- private String buildAllowedMaterialInFilter() {
- List<String> materials = erpProperties.getTransferDirectMaterialNumbers();
- if (materials == null || materials.isEmpty()) {
- return MATERIAL_NUMBER_FIELD + "='8.10.HEV.10.047696'";
- }
- StringBuilder builder = new StringBuilder(MATERIAL_NUMBER_FIELD + " IN(");
- for (int i = 0; i < materials.size(); i++) {
- if (i > 0) {
- builder.append(",");
- }
- builder.append("'").append(escape(materials.get(i))).append("'");
- }
- builder.append(")");
- return builder.toString();
- }
- private String buildBaseFilter() {
- String filter = "";
- if (StringUtils.isNotBlank(erpProperties.getTransferDirectBillType())) {
- filter = BILL_TYPE_FIELD + "='" + escape(erpProperties.getTransferDirectBillType()) + "'";
- }
- return appendAnd(filter, buildStockOrgFilter());
- }
- private String buildStockOrgFilter() {
- if (!erpProperties.isFilterCurrentOrg()) {
- return "";
- }
- if (StringUtils.isNotBlank(erpProperties.getOrgNumber())) {
- return "FStockOrgId.FNUMBER='" + escape(erpProperties.getOrgNumber()) + "'";
- }
- Long currentOrganizationId = erpClient.getCurrentOrganizationId();
- if (currentOrganizationId == null) {
- return "1=1";
- }
- return "FStockOrgId=" + currentOrganizationId;
- }
- private String appendAnd(String left, String right) {
- if (StringUtils.isBlank(left)) {
- return right;
- }
- if (StringUtils.isBlank(right)) {
- return left;
- }
- return left + " AND " + right;
- }
- private String escape(String value) {
- return value == null ? "" : value.trim().replace("'", "''");
- }
- private String readString(JSONObject row, String... keys) {
- return ErpKingdeeParseUtils.readString(row, keys);
- }
- private String formatErpDate(String rawValue) {
- if (StringUtils.isBlank(rawValue)) {
- return "";
- }
- String trimmed = rawValue.trim();
- return trimmed.length() >= 10 ? trimmed.substring(0, 10) : trimmed;
- }
- private String documentStatusName(String status) {
- if ("A".equals(status)) {
- return "创建";
- }
- if ("B".equals(status)) {
- return "审核中";
- }
- if ("C".equals(status)) {
- return "已审核";
- }
- if ("D".equals(status)) {
- return "重新审核";
- }
- return status;
- }
- }
|