package com.ruoyi.system.controller; import com.google.gson.JsonArray; import com.google.gson.JsonObject; import com.kingdee.bos.webapi.sdk.K3CloudApi; import com.ruoyi.common.annotation.Log; import com.ruoyi.common.core.domain.PageQuery; import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.system.domain.bo.ImMaterialBo; import com.ruoyi.system.domain.bo.ImProductionPlanBo; import com.ruoyi.system.domain.dto.*; import com.ruoyi.system.domain.vo.ImMaterialVo; import com.ruoyi.system.domain.vo.InventoryInfoVO; import com.ruoyi.system.runner.JdUtil; import com.ruoyi.system.service.IImMaterialService; import com.ruoyi.system.service.IImProductionPlanService; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.*; import java.text.SimpleDateFormat; import java.util.*; import java.util.concurrent.*; @RequiredArgsConstructor @RestController @RequestMapping("/index") @Slf4j public class IndexController { private static final int MAX_MATERIAL_CODES = 50; private final IImMaterialService iImMaterialService; private final IImProductionPlanService imProductionPlanService; @GetMapping("/list") public TableDataInfo list(ImMaterialBo bo, PageQuery pageQuery) { return iImMaterialService.queryPageList(bo, pageQuery); } /** * 金蝶库存查询(支持单个或多个物料编码) *

* 前端一次传入多个编码;后端对每个物料按原逻辑精确查询后汇总返回(金蝶侧不支持可靠的多码 IN 拼接)。 * 参数任选其一: * - materialCode:单个物料编码(兼容旧调用) * - materialCodes:多个物料编码,逗号分隔 */ @GetMapping("/inventory") public R> handleData( @RequestParam(value = "materialCode", required = false) String materialCode, @RequestParam(value = "materialCodes", required = false) String materialCodes) { List codes = parseMaterialCodes(materialCode, materialCodes); if (codes.isEmpty()) { return R.fail("请指定物料编码"); } if (codes.size() > MAX_MATERIAL_CODES) { return R.fail("单次最多查询 " + MAX_MATERIAL_CODES + " 个物料"); } int poolSize = Math.min(Math.max(codes.size(), 4), 10); ExecutorService executorService = new ThreadPoolExecutor( poolSize, poolSize, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(Math.max(codes.size() * 2, 10)), new ThreadPoolExecutor.CallerRunsPolicy() ); try { List> futures = new ArrayList<>(codes.size()); for (String code : codes) { futures.add(CompletableFuture.supplyAsync(() -> queryOne(code), executorService)); } CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) .get(Math.max(30, codes.size() * 10L), TimeUnit.SECONDS); List result = new ArrayList<>(codes.size()); for (CompletableFuture future : futures) { result.add(future.get()); } return R.ok(result); } catch (Exception e) { log.error("查询库存信息失败", e); return R.fail("查询库存信息失败:" + e.getMessage()); } finally { executorService.shutdown(); } } /** * 单个物料精确查询(与原先单码接口同一套金蝶条件),供多码并行汇总。 */ private InventoryInfoVO queryOne(String materialCode) { try { double inventoryQty = Optional.ofNullable(JdUtil.getKuCun(materialCode)) .map(list -> list.stream().mapToDouble(JDInventoryDTO::getFBaseQty).sum()) .orElse(0.0); double fNoPickedQty = Optional.ofNullable(JdUtil.getWeiLingliao(materialCode)) .map(list -> list.stream().mapToDouble(JDProductionDTO::getFNoPickedQty).sum()) .orElse(0.0); double productionQty = Optional.ofNullable(JdUtil.getProMoList(materialCode)) .map(list -> list.stream().mapToDouble(ProMoDTO::getFQty).sum()) .orElse(0.0); double purchaseQty = Optional.ofNullable(JdUtil.getPurchaseOrderList(materialCode)) .map(list -> list.stream().mapToDouble(PurchaseOrderDTO::getFRemainStockINQty).sum()) .orElse(0.0); double salesOrder = Optional.ofNullable(JdUtil.getSalesOrderList(materialCode)) .map(list -> list.stream().mapToDouble(SalesOrderDTO::getFBaseRemainOutQty).sum()) .orElse(0.0); double keyong = inventoryQty + productionQty + purchaseQty - fNoPickedQty - salesOrder; InventoryInfoVO vo = new InventoryInfoVO(); vo.setMaterialCode(materialCode); vo.setKucun(String.valueOf(inventoryQty)); vo.setQuantity(String.valueOf(fNoPickedQty)); vo.setMaterialName(String.valueOf(purchaseQty)); vo.setStockName(String.valueOf(productionQty)); vo.setStockUnit(String.valueOf(keyong)); vo.setSalesOrder(String.valueOf(salesOrder)); return vo; } catch (Exception e) { log.error("查询单个物料库存失败: {}", materialCode, e); InventoryInfoVO vo = new InventoryInfoVO(); vo.setMaterialCode(materialCode); vo.setKucun("0.0"); vo.setQuantity("0.0"); vo.setMaterialName("0.0"); vo.setStockName("0.0"); vo.setStockUnit("0.0"); vo.setSalesOrder("0.0"); return vo; } } private static List parseMaterialCodes(String materialCode, String materialCodes) { LinkedHashSet set = new LinkedHashSet<>(); addCodes(set, materialCodes); addCodes(set, materialCode); return new ArrayList<>(set); } private static void addCodes(Set set, String raw) { if (StringUtils.isBlank(raw)) { return; } for (String part : raw.split(",")) { if (StringUtils.isNotBlank(part)) { set.add(part.trim()); } } } @Log(title = "生产计划") @PostMapping("/JDList") public void synchronize_lists() { K3CloudApi client = new K3CloudApi(); JsonObject json = new JsonObject(); json.addProperty("FormId", "PRD_MO"); json.addProperty("FieldKeys", "FID,F_UCHN_Text,FBillType.FNUMBER,FMaterialId.FNumber,FMaterialName,FQty,FBillType.FNUMBER,FWorkShopID.FNumber,FDate,FProductType,FPickMtrlStatus"); JsonArray filterString = new JsonArray(); JsonObject filterObject = new JsonObject(); filterObject.addProperty("FieldName", "F_UCHN_Text"); filterObject.addProperty("Compare", "17"); filterObject.addProperty("Value", "QB"); filterObject.addProperty("Left", ""); filterObject.addProperty("Right", ""); filterObject.addProperty("Logic", 0); filterString.add(filterObject); json.add("FilterString", filterString); json.addProperty("OrderString", ""); json.addProperty("TopRowCount", 0); json.addProperty("StartRow", 0); json.addProperty("Limit", 2000); json.addProperty("SubSystemId", ""); String jsonData = json.toString(); try { String input = String.valueOf(client.executeBillQuery(jsonData)); input = input.substring(2, input.length() - 2); String[] split = input.split("]\\, \\["); for (String imProductionn : split) { ImProductionPlanBo imProductionPlan = new ImProductionPlanBo(); String[] imPro = imProductionn.split(","); imProductionPlan.setFID(Long.valueOf(imPro[0])); imProductionPlan.setProductionCode(imPro[1]); imProductionPlan.setTypeName(imPro[2]); imProductionPlan.setWorkShop(imPro[7]); SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); Date parse = simpleDateFormat.parse(imPro[8]); imProductionPlan.setDateF(parse); imProductionPlan.setUnit(imPro[9]); imProductionPlan.setProductTyp(imPro[10]); imProductionPlan.setFigureNumber(imPro[3]); imProductionPlan.setFigureName(imPro[4]); imProductionPlan.setPickmtrlStatus(imPro[10]); imProductionPlan.setUpdateTime(new Date()); imProductionPlan.setSearchValue("1"); imProductionPlan.setUpdateBy("admin"); imProductionPlan.setCreateTime(new Date()); imProductionPlan.setCreateBy("admin"); imProductionPlanService.insertByBo(imProductionPlan); } } catch (Exception e) { e.printStackTrace(); } } }