ErpPrdInStockController.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621
  1. package com.jeesite.modules.mes.web;
  2. import com.jeesite.common.config.Global;
  3. import com.jeesite.common.entity.Page;
  4. import com.jeesite.common.lang.StringUtils;
  5. import com.jeesite.common.web.BaseController;
  6. import com.jeesite.modules.mes.entity.MesBatchSn;
  7. import com.jeesite.modules.mes.erp.ErpPrdInStock;
  8. import com.jeesite.modules.mes.erp.ErpPrdInStockResult;
  9. import com.jeesite.modules.mes.erp.ErpPrdInStockSaveService;
  10. import com.jeesite.modules.mes.erp.ErpPrdInStockService;
  11. import com.jeesite.modules.mes.erp.ErpPrdInStockSubmitRequest;
  12. import com.jeesite.modules.mes.erp.ErpProductionOrder;
  13. import com.jeesite.modules.mes.erp.ErpProductionOrderService;
  14. import com.jeesite.modules.mes.erp.ErpStockPdaService;
  15. import com.jeesite.modules.mes.erp.ErpStockOption;
  16. import com.jeesite.modules.mes.erp.ErpStockService;
  17. import com.jeesite.modules.mes.erp.KingdeeErpProperties;
  18. import com.jeesite.modules.mes.erp.ErpPdaRespHelper;
  19. import com.jeesite.modules.mes.erp.MesErpLineMaterialMapping;
  20. import com.jeesite.modules.mes.resp.CommonResp;
  21. import com.jeesite.modules.mes.service.MesBatchSnService;
  22. import com.jeesite.modules.mes.service.MesLogService;
  23. import org.apache.shiro.authz.annotation.RequiresPermissions;
  24. import org.springframework.stereotype.Controller;
  25. import org.springframework.ui.Model;
  26. import org.springframework.web.bind.annotation.PostMapping;
  27. import org.springframework.web.bind.annotation.RequestMapping;
  28. import org.springframework.web.bind.annotation.RequestMethod;
  29. import org.springframework.web.bind.annotation.ResponseBody;
  30. import javax.servlet.http.HttpServletRequest;
  31. import javax.servlet.http.HttpServletResponse;
  32. import java.util.ArrayList;
  33. import java.util.Collections;
  34. import java.util.HashMap;
  35. import java.util.List;
  36. import java.util.Map;
  37. /**
  38. * ERP 生产入库单查询与新增(MES 批次码驱动数量)。
  39. */
  40. @Controller
  41. @RequestMapping(value = "${adminPath}/mes/erpPrdInStock")
  42. public class ErpPrdInStockController extends BaseController {
  43. private final ErpPrdInStockService erpPrdInStockService;
  44. private final ErpPrdInStockSaveService erpPrdInStockSaveService;
  45. private final ErpProductionOrderService erpProductionOrderService;
  46. private final MesBatchSnService mesBatchSnService;
  47. private final ErpStockService erpStockService;
  48. private final ErpStockPdaService erpStockPdaService;
  49. private final KingdeeErpProperties erpProperties;
  50. private final MesLogService mesLogService;
  51. public ErpPrdInStockController(ErpPrdInStockService erpPrdInStockService,
  52. ErpPrdInStockSaveService erpPrdInStockSaveService,
  53. ErpProductionOrderService erpProductionOrderService,
  54. MesBatchSnService mesBatchSnService,
  55. ErpStockService erpStockService,
  56. ErpStockPdaService erpStockPdaService,
  57. KingdeeErpProperties erpProperties,
  58. MesLogService mesLogService) {
  59. this.erpPrdInStockService = erpPrdInStockService;
  60. this.erpPrdInStockSaveService = erpPrdInStockSaveService;
  61. this.erpProductionOrderService = erpProductionOrderService;
  62. this.mesBatchSnService = mesBatchSnService;
  63. this.erpStockService = erpStockService;
  64. this.erpStockPdaService = erpStockPdaService;
  65. this.erpProperties = erpProperties;
  66. this.mesLogService = mesLogService;
  67. }
  68. @RequiresPermissions("mes:erpPrdInStock:view")
  69. @RequestMapping(value = {"list", ""})
  70. public String list(ErpPrdInStock erpPrdInStock, Model model) {
  71. model.addAttribute("erpPrdInStock", erpPrdInStock);
  72. return "modules/mes/erpPrdInStockList";
  73. }
  74. @RequiresPermissions("mes:erpPrdInStock:view")
  75. @RequestMapping(value = "listData")
  76. @ResponseBody
  77. public Page<ErpPrdInStock> listData(ErpPrdInStock erpPrdInStock,
  78. HttpServletRequest request, HttpServletResponse response) {
  79. Page<ErpPrdInStock> page = new Page<>(request, response);
  80. int pageSize = page.getPageSize() > 0 ? page.getPageSize() : 20;
  81. int pageNo = page.getPageNo() > 0 ? page.getPageNo() : 1;
  82. int startRow = (pageNo - 1) * pageSize;
  83. List<ErpPrdInStock> list = erpPrdInStockService.findPageList(erpPrdInStock, startRow, pageSize);
  84. page.setList(list);
  85. page.setCount(startRow + list.size() + (list.size() == pageSize ? 1 : 0));
  86. return page;
  87. }
  88. @RequiresPermissions("mes:erpPrdInStock:view")
  89. @RequestMapping(value = "detail")
  90. public String detail(ErpPrdInStock erpPrdInStock, Model model) {
  91. model.addAttribute("erpPrdInStock", erpPrdInStock);
  92. return "modules/mes/erpPrdInStockDetail";
  93. }
  94. @RequiresPermissions("mes:erpPrdInStock:view")
  95. @RequestMapping(value = "detailData")
  96. @ResponseBody
  97. public Page<ErpPrdInStock> detailData(ErpPrdInStock erpPrdInStock,
  98. HttpServletRequest request, HttpServletResponse response) {
  99. Page<ErpPrdInStock> page = new Page<>(request, response);
  100. List<ErpPrdInStock> list = erpPrdInStockService.findDetailList(erpPrdInStock.getBillNo());
  101. page.setList(list);
  102. page.setCount(list.size());
  103. return page;
  104. }
  105. /**
  106. * PDA:查看生产入库单明细行。
  107. */
  108. @RequiresPermissions("mes:erpPrdInStock:view")
  109. @PostMapping(value = "pda/detailData")
  110. @ResponseBody
  111. public CommonResp<Page<ErpPrdInStock>> pdaDetailData(ErpPrdInStock erpPrdInStock,
  112. HttpServletRequest request, HttpServletResponse response) {
  113. mesLogService.apisave(request);
  114. List<ErpPrdInStock> list = erpPrdInStockService.findDetailList(erpPrdInStock.getBillNo());
  115. return ErpPdaRespHelper.pageAllOk(request, response, list);
  116. }
  117. @RequiresPermissions("mes:erpPrdInStock:view")
  118. @RequestMapping(value = "selectOrder")
  119. public String selectOrder(ErpProductionOrder erpProductionOrder, Model model) {
  120. model.addAttribute("erpProductionOrder", erpProductionOrder);
  121. return "modules/mes/erpPrdInStockSelectOrder";
  122. }
  123. @RequiresPermissions("mes:erpPrdInStock:view")
  124. @RequestMapping(value = "selectOrderData")
  125. @ResponseBody
  126. public Page<ErpProductionOrder> selectOrderData(ErpProductionOrder erpProductionOrder,
  127. HttpServletRequest request, HttpServletResponse response) {
  128. Page<ErpProductionOrder> page = new Page<>(request, response);
  129. int pageSize = page.getPageSize() > 0 ? page.getPageSize() : 20;
  130. int pageNo = page.getPageNo() > 0 ? page.getPageNo() : 1;
  131. int startRow = (pageNo - 1) * pageSize;
  132. List<ErpProductionOrder> list = erpProductionOrderService.findPrdInStockOrderPageList(
  133. erpProductionOrder.getBillNo(), startRow, pageSize);
  134. page.setList(list);
  135. page.setCount(startRow + list.size() + (list.size() == pageSize ? 1 : 0));
  136. return page;
  137. }
  138. @RequiresPermissions("mes:erpPrdInStock:view")
  139. @RequestMapping(value = "selectDetail")
  140. public String selectDetail(ErpProductionOrder erpProductionOrder, Model model) {
  141. model.addAttribute("erpProductionOrder", erpProductionOrder);
  142. return "modules/mes/erpPrdInStockSelectDetail";
  143. }
  144. @RequiresPermissions("mes:erpPrdInStock:view")
  145. @RequestMapping(value = "selectDetailData")
  146. @ResponseBody
  147. public Page<ErpProductionOrder> selectDetailData(ErpProductionOrder erpProductionOrder,
  148. HttpServletRequest request, HttpServletResponse response) {
  149. Page<ErpProductionOrder> page = new Page<>(request, response);
  150. List<ErpProductionOrder> list = erpProductionOrderService.findDetailList(erpProductionOrder.getBillNo());
  151. // 仅保留 HEV/115 物料分录
  152. list.removeIf(row -> row == null || !erpProperties.isAllowedPrdInStockMaterial(row.getMaterialNumber()));
  153. erpPrdInStockService.enrichMoInstockProgress(erpProductionOrder.getBillNo(), list);
  154. page.setList(list);
  155. page.setCount(list.size());
  156. return page;
  157. }
  158. @RequiresPermissions("mes:erpPrdInStock:view")
  159. @RequestMapping(value = "form")
  160. public String form(String moBillNo, String entryId, Model model) {
  161. String billNo = StringUtils.trim(moBillNo);
  162. String moEntryId = StringUtils.trim(entryId);
  163. ErpProductionOrder moEntry = erpProductionOrderService.findInstockMoEntry(billNo, moEntryId);
  164. if (moEntry != null) {
  165. erpPrdInStockService.enrichMoInstockProgress(billNo, java.util.Collections.singletonList(moEntry));
  166. }
  167. List<MesBatchSn> batchList = moEntry == null ? java.util.Collections.emptyList()
  168. : mesBatchSnService.findPendingInstockByMaterial(moEntry.getMaterialNumber());
  169. List<ErpStockOption> stockList = erpStockService.findUsableStockList();
  170. model.addAttribute("moBillNo", billNo);
  171. model.addAttribute("entryId", moEntryId);
  172. model.addAttribute("moEntry", moEntry);
  173. model.addAttribute("batchList", batchList);
  174. model.addAttribute("stockList", stockList);
  175. model.addAttribute("defaultStockNumber", erpStockService.resolveDefaultStockNumber(stockList));
  176. if (moEntry == null) {
  177. model.addAttribute("message", "未找到生产订单分录");
  178. } else if (batchList.isEmpty()) {
  179. model.addAttribute("message", "暂无待入库 MES 批次码。须同时满足:产线含 HEV/115(如 HEVXT、HEVX1、115XT)"
  180. + "、已绑定数量 nums>0、且未入库。"
  181. + " 若批次码记录表有条目但 nums=0,需产线扫码绑定工件后再入库。");
  182. }
  183. return "modules/mes/erpPrdInStockForm";
  184. }
  185. /**
  186. * PDA:生产入库单列表。
  187. */
  188. @RequiresPermissions("mes:erpPrdInStock:view")
  189. @PostMapping(value = "pda/listData")
  190. @ResponseBody
  191. public CommonResp<Page<ErpPrdInStock>> pdaListData(ErpPrdInStock erpPrdInStock,
  192. HttpServletRequest request, HttpServletResponse response) {
  193. mesLogService.apisave(request);
  194. Page<ErpPrdInStock> page = new Page<>(request, response);
  195. int pageSize = page.getPageSize() > 0 ? page.getPageSize() : 20;
  196. int pageNo = page.getPageNo() > 0 ? page.getPageNo() : 1;
  197. int startRow = (pageNo - 1) * pageSize;
  198. List<ErpPrdInStock> list = erpPrdInStockService.findPageList(erpPrdInStock, startRow, pageSize);
  199. return ErpPdaRespHelper.pageOk(request, response, list, startRow, pageSize);
  200. }
  201. /**
  202. * PDA:生产订单列表。
  203. */
  204. @RequiresPermissions("mes:erpPrdInStock:view")
  205. @PostMapping(value = "pda/selectOrderData")
  206. @ResponseBody
  207. public CommonResp<Page<ErpProductionOrder>> pdaSelectOrderData(ErpProductionOrder erpProductionOrder,
  208. HttpServletRequest request, HttpServletResponse response) {
  209. mesLogService.apisave(request);
  210. Page<ErpProductionOrder> page = new Page<>(request, response);
  211. int pageSize = page.getPageSize() > 0 ? page.getPageSize() : 20;
  212. int pageNo = page.getPageNo() > 0 ? page.getPageNo() : 1;
  213. int startRow = (pageNo - 1) * pageSize;
  214. List<ErpProductionOrder> list = erpProductionOrderService.findPrdInStockOrderPageList(
  215. erpProductionOrder.getBillNo(), startRow, pageSize);
  216. return ErpPdaRespHelper.pageOk(request, response, list, startRow, pageSize);
  217. }
  218. /**
  219. * PDA:生产订单分录列表。
  220. */
  221. @RequiresPermissions("mes:erpPrdInStock:view")
  222. @PostMapping(value = "pda/selectDetailData")
  223. @ResponseBody
  224. public CommonResp<Page<ErpProductionOrder>> pdaSelectDetailData(ErpProductionOrder erpProductionOrder,
  225. HttpServletRequest request, HttpServletResponse response) {
  226. mesLogService.apisave(request);
  227. List<ErpProductionOrder> list = erpProductionOrderService.findDetailList(erpProductionOrder.getBillNo());
  228. list.removeIf(row -> row == null || !erpProperties.isAllowedPrdInStockMaterial(row.getMaterialNumber()));
  229. erpPrdInStockService.enrichMoInstockProgress(erpProductionOrder.getBillNo(), list);
  230. return ErpPdaRespHelper.pageAllOk(request, response, list);
  231. }
  232. /**
  233. * PDA:入库仓库列表。
  234. */
  235. @RequiresPermissions("mes:erpPrdInStock:view")
  236. @RequestMapping(value = "stockList", method = {RequestMethod.GET, RequestMethod.POST})
  237. @ResponseBody
  238. public CommonResp<Map<String, Object>> stockList(HttpServletRequest request) {
  239. mesLogService.apisave(request);
  240. return ErpPdaRespHelper.ok("成功", erpStockPdaService.buildStockListData());
  241. }
  242. /**
  243. * PDA:选批次入库页初始化(订单分录 + 待入库 MES 批次码 + 仓库)。
  244. */
  245. @RequiresPermissions("mes:erpPrdInStock:view")
  246. @RequestMapping(value = "formInit", method = {RequestMethod.GET, RequestMethod.POST})
  247. @ResponseBody
  248. public CommonResp<Map<String, Object>> formInit(String moBillNo, String entryId, HttpServletRequest request) {
  249. mesLogService.apisave(request);
  250. Map<String, Object> data = new HashMap<>(10);
  251. String billNo = StringUtils.trim(moBillNo);
  252. String moEntryId = StringUtils.trim(entryId);
  253. data.put("moBillNo", billNo);
  254. data.put("entryId", moEntryId);
  255. if (StringUtils.isBlank(billNo) || StringUtils.isBlank(moEntryId)) {
  256. data.put("moEntry", null);
  257. data.put("batchList", Collections.emptyList());
  258. data.put("stockList", Collections.emptyList());
  259. return ErpPdaRespHelper.fail("生产订单号与分录内码不能为空", data);
  260. }
  261. ErpProductionOrder moEntry = erpProductionOrderService.findInstockMoEntry(billNo, moEntryId);
  262. if (moEntry == null) {
  263. data.put("moEntry", null);
  264. data.put("batchList", Collections.emptyList());
  265. List<ErpStockOption> stocks = erpStockService.findUsableStockList();
  266. data.put("stockList", stocks);
  267. data.put("defaultStockNumber", erpStockService.resolveDefaultStockNumber(stocks));
  268. return ErpPdaRespHelper.fail("未找到生产订单分录", data);
  269. }
  270. erpPrdInStockService.enrichMoInstockProgress(billNo, Collections.singletonList(moEntry));
  271. List<MesBatchSn> batchList = mesBatchSnService.findPendingInstockByMaterial(moEntry.getMaterialNumber());
  272. data.put("moEntry", moEntry);
  273. data.put("batchList", batchList);
  274. String message = "";
  275. if (batchList.isEmpty()) {
  276. message = "暂无待入库 MES 批次码。须产线含 HEV/115(如 HEVXT、HEVX1、115XT)、nums>0、且未入库";
  277. }
  278. List<ErpStockOption> stocks = erpStockService.findUsableStockList();
  279. data.put("stockList", stocks);
  280. data.put("defaultStockNumber", erpStockService.resolveDefaultStockNumber(stocks));
  281. return ErpPdaRespHelper.ok(message, data);
  282. }
  283. /**
  284. * PDA:扫 MES 批次码校验(是否可入当前物料)。
  285. */
  286. @RequiresPermissions("mes:erpPrdInStock:view")
  287. @RequestMapping(value = "batchScan", method = {RequestMethod.GET, RequestMethod.POST})
  288. @ResponseBody
  289. public CommonResp<Map<String, Object>> batchScan(String batchSn, String materialNumber, HttpServletRequest request) {
  290. mesLogService.apisave(request);
  291. Map<String, Object> data = new HashMap<>(4);
  292. String sn = StringUtils.trim(batchSn);
  293. String material = StringUtils.trim(materialNumber);
  294. if (StringUtils.isBlank(sn)) {
  295. return ErpPdaRespHelper.fail("批次码不能为空", data);
  296. }
  297. if (StringUtils.isBlank(material)) {
  298. return ErpPdaRespHelper.fail("物料编码不能为空", data);
  299. }
  300. MesBatchSn batch = mesBatchSnService.findByBatchSn(sn);
  301. if (batch == null) {
  302. return ErpPdaRespHelper.fail("未找到该 MES 批次码", data);
  303. }
  304. data.put("batch", batch);
  305. if (batch.getNums() == null || batch.getNums() <= 0) {
  306. return ErpPdaRespHelper.fail("该批次码绑定数量为 0,需产线扫码绑定工件后再入库", data);
  307. }
  308. if ("1".equals(StringUtils.trim(batch.getInstockStatus()))
  309. || MesBatchSn.BATCH_STATUS_QUALIFIED.equals(batch.getBatchStatus())
  310. || MesBatchSn.BATCH_STATUS_SHIPPED.equals(batch.getBatchStatus())) {
  311. return ErpPdaRespHelper.fail("该批次码已在仓库中,不能重复入库", data);
  312. }
  313. if (!MesErpLineMaterialMapping.isLineAllowedForMaterialLoose(batch.getLineSn(), material)) {
  314. return ErpPdaRespHelper.fail("批次码产线 " + StringUtils.trimToEmpty(batch.getLineSn())
  315. + " 与当前物料 " + material + " 不匹配,不能入库", data);
  316. }
  317. return ErpPdaRespHelper.ok("可以入库", data);
  318. }
  319. /**
  320. * 仓位选项(PDA / PC 共用,统一 CommonResp)。
  321. */
  322. @RequiresPermissions("mes:erpPrdInStock:view")
  323. @RequestMapping(value = "pda/stockLocOptions", method = {RequestMethod.GET, RequestMethod.POST})
  324. @ResponseBody
  325. public CommonResp<Map<String, Object>> pdaStockLocOptions(String stockNumber, HttpServletRequest request) {
  326. return stockLocOptions(stockNumber, request);
  327. }
  328. @RequiresPermissions("mes:erpPrdInStock:view")
  329. @RequestMapping(value = "stockLocOptions", method = {RequestMethod.GET, RequestMethod.POST})
  330. @ResponseBody
  331. public CommonResp<Map<String, Object>> stockLocOptions(String stockNumber, HttpServletRequest request) {
  332. mesLogService.apisave(request);
  333. if (StringUtils.isBlank(stockNumber)) {
  334. return ErpPdaRespHelper.fail("仓库编码不能为空");
  335. }
  336. return ErpPdaRespHelper.ok("成功", erpStockPdaService.buildStockLocOptionsData(stockNumber));
  337. }
  338. @RequiresPermissions("mes:erpPrdInStock:view")
  339. @PostMapping(value = "submit")
  340. @ResponseBody
  341. public CommonResp<Map<String, Object>> submit(HttpServletRequest httpRequest) {
  342. mesLogService.apisave(httpRequest);
  343. ErpPrdInStockSubmitRequest request;
  344. try {
  345. request = ErpPrdInStockSubmitRequest.resolveFromHttpRequest(httpRequest);
  346. } catch (IllegalArgumentException ex) {
  347. return ErpPdaRespHelper.fail(ex.getMessage());
  348. } catch (Exception ex) {
  349. return ErpPdaRespHelper.fail("参数格式错误:" + ex.getMessage());
  350. }
  351. try {
  352. ErpPrdInStockResult result = erpPrdInStockSaveService.submit(request);
  353. if (result.isSuccess()) {
  354. String lotMsg = StringUtils.isNotBlank(result.getLotNumber())
  355. ? ",ERP批号:" + result.getLotNumber() : "";
  356. String message = text("生产入库单保存成功,单号:{0};合计数量 {1},绑定批次 {2} 个{3}",
  357. result.getBillNo(),
  358. result.getTotalQty() == null ? "0" : result.getTotalQty().stripTrailingZeros().toPlainString(),
  359. String.valueOf(result.getBatchCount()), lotMsg);
  360. Map<String, Object> data = new HashMap<>(4);
  361. data.put("billNo", result.getBillNo());
  362. data.put("totalQty", result.getTotalQty());
  363. data.put("batchCount", result.getBatchCount());
  364. data.put("lotNumber", result.getLotNumber());
  365. return ErpPdaRespHelper.ok(message, data);
  366. }
  367. return ErpPdaRespHelper.fail(result.getMessage());
  368. } catch (Exception e) {
  369. return ErpPdaRespHelper.fail(e.getMessage());
  370. }
  371. }
  372. }