| | |
| | | |
| | | import cn.iocoder.yudao.framework.common.pojo.CommonResult; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastHistorySaveReqVO; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastReqVO; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastRespVO; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastWorkOrderCreateReqVO; |
| | |
| | | return success(forecastService.getForecastList(reqVO.getForecastCode(), beginTime, endTime)); |
| | | } |
| | | |
| | | @PostMapping("/history") |
| | | @Operation(summary = "æ°å¢åå²é¢æµæ°æ®") |
| | | @PreAuthorize("@ss.hasPermission('bi:decision:kpi:update')") |
| | | public CommonResult<Long> createForecastHistory(@Valid @RequestBody DecisionForecastHistorySaveReqVO reqVO) { |
| | | return success(forecastService.createForecastHistory(reqVO)); |
| | | } |
| | | |
| | | @PostMapping("/generate") |
| | | @Operation(summary = "çæé¢æµï¼å ä½ï¼") |
| | | @PreAuthorize("@ss.hasPermission('bi:decision:kpi:query')") |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.bi.controller.admin.decision.vo; |
| | | |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.DecimalMin; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import jakarta.validation.constraints.Size; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | |
| | | @Schema(description = "管çåå° - è´è·é¢æµå岿°æ®æ°å¢ Request VO") |
| | | @Data |
| | | public class DecisionForecastHistorySaveReqVO { |
| | | |
| | | @Schema(description = "颿µç¼ç ", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @Size(max = 64) |
| | | @jakarta.validation.constraints.NotBlank |
| | | private String forecastCode; |
| | | |
| | | @Schema(description = "颿µåç§°", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @Size(max = 128) |
| | | @jakarta.validation.constraints.NotBlank |
| | | private String forecastName; |
| | | |
| | | @Schema(description = "颿µæ¶é´ç¹", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull |
| | | private LocalDateTime pointTime; |
| | | |
| | | @Schema(description = "颿µå¼", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotNull |
| | | @DecimalMin(value = "0", inclusive = true) |
| | | private BigDecimal forecastValue; |
| | | |
| | | @Schema(description = "å®é
å¼") |
| | | @DecimalMin(value = "0", inclusive = true) |
| | | private BigDecimal actualValue; |
| | | |
| | | @Schema(description = "维度") |
| | | @Size(max = 32) |
| | | private String dimension; |
| | | |
| | | @Schema(description = "维度å¼") |
| | | @Size(max = 128) |
| | | private String dimensionValue; |
| | | |
| | | @Schema(description = "夿³¨") |
| | | @Size(max = 500) |
| | | private String remark; |
| | | } |
| | |
| | | .between(BiForecastDataDO::getPointTime, beginTime, endTime) |
| | | .orderByAsc(BiForecastDataDO::getPointTime)); |
| | | } |
| | | |
| | | /** |
| | | * æ¥è¯¢æå®é¢æµç¼ç ä¸æè¿ n æ¡é¢æµæ°æ®ï¼ææ¶é´ååºï¼ç¨äºç§»å¨å¹³åï¼ |
| | | */ |
| | | default List<BiForecastDataDO> selectRecentByCode(String forecastCode, int limit) { |
| | | return selectList(new LambdaQueryWrapper<BiForecastDataDO>() |
| | | .eq(BiForecastDataDO::getForecastCode, forecastCode) |
| | | .orderByDesc(BiForecastDataDO::getPointTime) |
| | | .last("LIMIT " + limit)); |
| | | } |
| | | } |
| | |
| | | |
| | | // ========== å³çæ¯æ - è´è·é¢æµ 1_080_221 ~ 1_080_240 ========== |
| | | ErrorCode BI_FORECAST_NOT_EXISTS = new ErrorCode(1_080_221, "è´è·é¢æµæ°æ®ä¸åå¨"); |
| | | ErrorCode BI_FORECAST_NO_HISTORY = new ErrorCode(1_080_222, "è¯¥é¢æµç¼ç 䏿æ å岿°æ®ï¼æ æ³çæé¢æµ"); |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.bi.service.decision; |
| | | |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastHistorySaveReqVO; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastWorkOrderCreateReqVO; |
| | | import cn.iocoder.yudao.module.bi.dal.dataobject.decision.BiForecastDataDO; |
| | | |
| | |
| | | |
| | | void generateForecast(String forecastCode, LocalDateTime pointTime); |
| | | |
| | | Long createForecastHistory(DecisionForecastHistorySaveReqVO reqVO); |
| | | |
| | | /** |
| | | * è´è·é¢æµèå¨å建ç产工åï¼è¿ç»´/åçµ/æ£ä¿®ç±»ï¼ |
| | | * |
| | |
| | | package cn.iocoder.yudao.module.bi.service.decision; |
| | | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastHistorySaveReqVO; |
| | | import cn.iocoder.yudao.module.bi.controller.admin.decision.vo.DecisionForecastWorkOrderCreateReqVO; |
| | | import cn.iocoder.yudao.module.bi.dal.dataobject.decision.BiForecastDataDO; |
| | | import cn.iocoder.yudao.module.bi.dal.mysql.decision.BiForecastDataMapper; |
| | |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.bi.enums.ErrorCodeConstants.BI_FORECAST_NO_HISTORY; |
| | | import static cn.iocoder.yudao.module.bi.enums.ErrorCodeConstants.BI_FORECAST_NOT_EXISTS; |
| | | |
| | | /** |
| | |
| | | return forecastDataMapper.selectListByCodeAndTimeRange(forecastCode, beginTime, endTime); |
| | | } |
| | | |
| | | /** |
| | | * ç§»å¨å¹³åçªå£å¤§å° |
| | | */ |
| | | private static final int SMA_WINDOW = 12; |
| | | |
| | | @Override |
| | | public Long createForecastHistory(DecisionForecastHistorySaveReqVO reqVO) { |
| | | BiForecastDataDO data = BiForecastDataDO.builder() |
| | | .forecastCode(reqVO.getForecastCode()) |
| | | .forecastName(reqVO.getForecastName()) |
| | | .pointTime(reqVO.getPointTime()) |
| | | .forecastValue(reqVO.getForecastValue()) |
| | | .actualValue(reqVO.getActualValue()) |
| | | .dimension(reqVO.getDimension()) |
| | | .dimensionValue(reqVO.getDimensionValue()) |
| | | .remark(reqVO.getRemark()) |
| | | .modelVersion("manual-history") |
| | | .build(); |
| | | forecastDataMapper.insert(data); |
| | | return data.getId(); |
| | | } |
| | | |
| | | @Override |
| | | public void generateForecast(String forecastCode, LocalDateTime pointTime) { |
| | | // æ¬æå ä½ï¼ç®åç§»å¨å¹³å颿µ |
| | | // å®é
项ç®åºéæ ML 模åï¼ARIMA/Prophet/LSTMï¼ |
| | | log.info("[generateForecast][çæé¢æµ] forecastCode={}, pointTime={}, å½å为å ä½å®ç°", forecastCode, pointTime); |
| | | // åºäºå颿µç¼ç çåå²é¢æµæ°æ®åç®åç§»å¨å¹³åï¼æ å岿°æ®æ¶ä¸ä¼ªé é¶å¼ |
| | | List<BiForecastDataDO> history = forecastDataMapper.selectRecentByCode(forecastCode, SMA_WINDOW); |
| | | if (CollUtil.isEmpty(history)) { |
| | | throw exception(BI_FORECAST_NO_HISTORY); |
| | | } |
| | | BigDecimal sum = history.stream() |
| | | .map(BiForecastDataDO::getForecastValue) |
| | | .filter(value -> value != null) |
| | | .reduce(BigDecimal.ZERO, BigDecimal::add); |
| | | BigDecimal avg = sum.divide(BigDecimal.valueOf(history.size()), 4, RoundingMode.HALF_UP); |
| | | BigDecimal bound = avg.multiply(new BigDecimal("0.10")); |
| | | |
| | | BiForecastDataDO forecast = BiForecastDataDO.builder() |
| | | .forecastCode(forecastCode) |
| | | .forecastName("è´è·é¢æµ(å ä½)") |
| | | .forecastName(history.get(0).getForecastName()) |
| | | .pointTime(pointTime) |
| | | .forecastValue(BigDecimal.ZERO) |
| | | .lowerBound(BigDecimal.ZERO) |
| | | .upperBound(BigDecimal.ZERO) |
| | | .forecastValue(avg) |
| | | .lowerBound(avg.subtract(bound)) |
| | | .upperBound(avg.add(bound)) |
| | | .confidenceLevel(new BigDecimal("95.00")) |
| | | .modelVersion("v1.0-placeholder") |
| | | .modelVersion("v1.0-sma") |
| | | .build(); |
| | | forecastDataMapper.insert(forecast); |
| | | } |
| | |
| | | } |
| | | // 2.8 设置æä»¤ä¸åæ°é |
| | | contractVO.setCommandCount(contractCommandService.countByContractId(contractVO.getId())); |
| | | contractVO.setAuditStatusName(CrmAuditStatusEnum.getNameByStatus(contractVO.getAuditStatus())); |
| | | }); |
| | | } |
| | | |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.erp.api.purchase; |
| | | |
| | | /** |
| | | * éè´è®¢å API æ¥å£ã |
| | | * |
| | | * <p>éè´ä¸å¡å¯¹å¤å¥çº¦ï¼ä¸æ´é² ERP ä¸å¡è·¯ç±ï¼æ§ ERP API ä½ä¸ºå
¼å®¹å¥çº¦ä¿çã</p> |
| | | */ |
| | | public interface PurchaseOrderApi extends ErpPurchaseOrderApi { |
| | | |
| | | String PREFIX = "/rpc-api/purchase/order"; |
| | | |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package cn.iocoder.yudao.module.erp.api.purchase; |
| | | |
| | | /** |
| | | * éè´è®¡å API æ¥å£ã |
| | | * |
| | | * <p>éè´ä¸å¡å¯¹å¤å¥çº¦ï¼æ§ ERP API ä½ä¸ºå
¼å®¹å¥çº¦ä¿çã</p> |
| | | */ |
| | | public interface PurchasePlanApi extends ErpPurchasePlanApi { |
| | | |
| | | String PREFIX = "/rpc-api/purchase/plan"; |
| | | |
| | | } |
| | |
| | | * @author è¶
级管çå |
| | | */ |
| | | @RestController |
| | | @RequestMapping(ErpPurchaseOrderApi.PREFIX) |
| | | @RequestMapping({ErpPurchaseOrderApi.PREFIX, PurchaseOrderApi.PREFIX}) |
| | | @Validated |
| | | public class ErpPurchaseOrderApiImpl implements ErpPurchaseOrderApi { |
| | | public class ErpPurchaseOrderApiImpl implements PurchaseOrderApi { |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderService purchaseOrderService; |
| | |
| | | */ |
| | | @Service |
| | | @Validated |
| | | public class ErpPurchasePlanApiImpl implements ErpPurchasePlanApi { |
| | | public class ErpPurchasePlanApiImpl implements PurchasePlanApi { |
| | | |
| | | @Resource |
| | | private ErpPurchasePlanService purchasePlanService; |
| | |
| | | |
| | | @Tag(name = "管çåå° - ERP éè´æ¥ç¥¨") |
| | | @RestController |
| | | @RequestMapping("/erp/purchase-invoice") |
| | | @RequestMapping({"/erp/purchase-invoice", "/purchase/invoice"}) |
| | | @Validated |
| | | public class ErpPurchaseInvoiceController { |
| | | |
| | |
| | | |
| | | @Tag(name = "管çåå° - ERP éè´è®¢å") |
| | | @RestController |
| | | @RequestMapping("/erp/purchase-order") |
| | | @RequestMapping({"/erp/purchase-order", "/purchase/order"}) |
| | | @Validated |
| | | public class ErpPurchaseOrderController { |
| | | |
| | |
| | | |
| | | @Tag(name = "管çåå° - ERP éè´è®¡å") |
| | | @RestController |
| | | @RequestMapping("/erp/purchase-plan") |
| | | @RequestMapping({"/erp/purchase-plan", "/purchase/plan"}) |
| | | @Validated |
| | | public class ErpPurchasePlanController { |
| | | |
| | |
| | | |
| | | @Tag(name = "管çåå° - ERP éè´ç³è¯·") |
| | | @RestController |
| | | @RequestMapping("/erp/purchase-request") |
| | | @RequestMapping({"/erp/purchase-request", "/purchase/request"}) |
| | | @Validated |
| | | public class ErpPurchaseRequestController { |
| | | |
| | |
| | | |
| | | @Tag(name = "管çåå° - ERP ä¾åºå") |
| | | @RestController |
| | | @RequestMapping("/erp/supplier") |
| | | @RequestMapping({"/erp/supplier", "/purchase/supplier"}) |
| | | @Validated |
| | | public class ErpSupplierController { |
| | | |
| | |
| | | |
| | | @Tag(name = "管çåå° - ERP éè´ç»è®¡") |
| | | @RestController |
| | | @RequestMapping("/erp/purchase-statistics") |
| | | @RequestMapping({"/erp/purchase-statistics", "/purchase/statistics"}) |
| | | @Validated |
| | | public class ErpPurchaseStatisticsController { |
| | | |
| | |
| | | ErrorCode PURCHASE_REQUEST_ORDER_EXISTS = new ErrorCode(1_030_104_007, "éè´ç³è¯·åå·²çæéè´è®¢åï¼è¯·å¿é夿ä½"); |
| | | ErrorCode PURCHASE_REQUEST_BPM_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_104_008, "éè´ç³è¯·å®¡æ¹åç±»ä¸åå¨ï¼è¯·å
å¨BPM模åå建éè´ç³è¯·å®¡æ¹æµç¨åç±»"); |
| | | ErrorCode PURCHASE_REQUEST_BPM_PROCESS_DEFINITION_NOT_EXISTS = new ErrorCode(1_030_104_009, "éè´ç³è¯·å®¡æ¹åç±»ä¸æ²¡æå¯ç¨çæµç¨æ¨¡åï¼è¯·å
å建并å叿µç¨"); |
| | | ErrorCode PURCHASE_REQUEST_ITEM_PRICE_EMPTY = new ErrorCode(1_030_104_021, "éè´ç³è¯·æç»({})éé¢ä¿¡æ¯ä¸å®æ´ï¼æ æ³çæéè´è®¢å"); |
| | | |
| | | // ========== ERP éè´è®¡åï¼1-030-104-010ï¼ ========== |
| | | ErrorCode PURCHASE_PLAN_NOT_EXISTS = new ErrorCode(1_030_104_010, "éè´è®¡åä¸åå¨"); |
| | |
| | | if (ErpPurchaseRequestStatusEnum.APPROVE.getStatus().equals(newStatus) |
| | | && purchaseRequest.getSupplierId() != null |
| | | && purchaseRequest.getOrderId() == null) { |
| | | try { |
| | | Long orderId = doGeneratePurchaseOrder(purchaseRequest); |
| | | log.info("[updatePurchaseRequestAuditStatus] éè´ç³è¯·({}) èªå¨çæéè´è®¢å({})", id, orderId); |
| | | } catch (Exception e) { |
| | | log.error("[updatePurchaseRequestAuditStatus] éè´ç³è¯·({}) èªå¨çæéè´è®¢å失败", id, e); |
| | | // 䏿åºå¼å¸¸ï¼é¿å
å½±åç¶ææ´æ° |
| | | } |
| | | Long orderId = doGeneratePurchaseOrder(purchaseRequest); |
| | | log.info("[updatePurchaseRequestAuditStatus] éè´ç³è¯·({}) èªå¨çæéè´è®¢å({})", id, orderId); |
| | | } |
| | | } |
| | | |
| | |
| | | if (CollUtil.isEmpty(requestItems)) { |
| | | throw exception(PURCHASE_REQUEST_NOT_EXISTS); |
| | | } |
| | | requestItems.forEach(item -> { |
| | | if (item.getProductPrice() == null || item.getTotalPrice() == null || item.getTaxPrice() == null) { |
| | | throw exception(PURCHASE_REQUEST_ITEM_PRICE_EMPTY, item.getId()); |
| | | } |
| | | }); |
| | | |
| | | // 2. çæéè´è®¢åå· |
| | | String orderNo = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX); |
| | |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.hrm.dal.redis.HrmNoRedisDAO; |
| | | import cn.iocoder.yudao.module.hrm.enums.HrmAuditStatusEnum; |
| | | import cn.iocoder.yudao.module.hrm.dal.dataobject.employee.HrmEmployeeDO; |
| | | import cn.iocoder.yudao.module.hrm.service.employee.HrmEmployeeService; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | @Resource |
| | | private BpmProcessDefinitionService bpmProcessDefinitionService; |
| | | @Resource |
| | | private HrmEmployeeService employeeService; |
| | | |
| | | @Override |
| | | public Long createAttendanceException(HrmAttendanceExceptionSaveReqVO createReqVO) { |
| | | HrmEmployeeDO employee = employeeService.getEmployeeByUserId( |
| | | cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId()); |
| | | if (employee == null) { |
| | | throw exception(EMPLOYEE_NOT_EXISTS); |
| | | } |
| | | HrmAttendanceExceptionDO attendanceException = BeanUtils.toBean(createReqVO, HrmAttendanceExceptionDO.class); |
| | | attendanceException.setUserId(employee.getId()).setDeptId(employee.getDeptId()); |
| | | attendanceException.setNo(generateNo()); |
| | | attendanceException.setStatus(HrmAuditStatusEnum.DRAFT.getStatus()); |
| | | attendanceExceptionMapper.insert(attendanceException); |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.materialstock.MesWmMaterialStockDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.materialstock.MesWmMaterialStockMapper; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderItemRespDTO; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | |
| | | @Resource |
| | | private MesWmMaterialStockMapper materialStockMapper; |
| | | @Resource |
| | | private ErpPurchaseOrderApi purchaseOrderApi; |
| | | private PurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建工å BOM") |
| | |
| | | import cn.iocoder.yudao.module.mes.controller.admin.wm.arrivalnotice.vo.MesWmArrivalNoticeSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeDO; |
| | | import cn.iocoder.yudao.module.mes.service.wm.arrivalnotice.MesWmArrivalNoticeService; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderRespDTO; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.dto.SrmSupplierRespDTO; |
| | |
| | | @Resource |
| | | private SrmSupplierApi srmSupplierApi; |
| | | @Resource |
| | | private ErpPurchaseOrderApi purchaseOrderApi; |
| | | private PurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "å建å°è´§éç¥å") |
| | |
| | | /** |
| | | * æææ |
| | | */ |
| | | @TableField(exist = false) |
| | | private LocalDateTime expireDate; |
| | | /** |
| | | * 夿³¨ |
| | |
| | | // ========== MES ç产管ç-å·¥èºè·¯çº¿äº§åï¼1-040-501-200ï¼ ========== |
| | | ErrorCode PRO_ROUTE_PRODUCT_NOT_EXISTS = new ErrorCode(1_040_501_200, "å·¥èºè·¯çº¿äº§åä¸åå¨"); |
| | | ErrorCode PRO_ROUTE_PRODUCT_ITEM_DUPLICATE = new ErrorCode(1_040_501_201, "æ¤äº§åå·²é
ç½®äºå·¥èºè·¯çº¿"); |
| | | ErrorCode PRO_ROUTE_PRODUCT_ITEM_TYPE_INVALID = new ErrorCode(1_040_501_202, "å·¥èºè·¯çº¿åªè½å
³è产åç±»åç©æ"); |
| | | // ========== MES ç产管ç-å·¥èºè·¯çº¿äº§åBOMï¼1-040-501-300ï¼ ========== |
| | | ErrorCode PRO_ROUTE_PRODUCT_BOM_NOT_EXISTS = new ErrorCode(1_040_501_300, "å·¥èºè·¯çº¿äº§å BOM ä¸åå¨"); |
| | | ErrorCode PRO_ROUTE_PRODUCT_BOM_DUPLICATE = new ErrorCode(1_040_501_301, "å½å BOM ç©æå¨æ¤å·¥åºå·²ç»é
ç½®è¿"); |
| | |
| | | ErrorCode PRO_WORK_ORDER_CODE_DUPLICATE = new ErrorCode(1_040_502_001, "ç产工åç¼ç å·²åå¨"); |
| | | ErrorCode PRO_WORK_ORDER_NOT_PREPARE = new ErrorCode(1_040_502_002, "åªæèç¨¿ç¶æçå·¥åæè½æ§è¡æ¤æä½"); |
| | | ErrorCode PRO_WORK_ORDER_NOT_CONFIRMED = new ErrorCode(1_040_502_003, "åªæå·²ç¡®è®¤ç¶æçå·¥åæè½æ§è¡æ¤æä½"); |
| | | ErrorCode PRO_WORK_ORDER_PRODUCTION_NOT_COMPLETE = new ErrorCode(1_040_502_007, "å·¥åå®é
äº§åºæªè¾¾å°è®¡åæ°éï¼ä¸è½å®æ"); |
| | | ErrorCode PRO_WORK_ORDER_HAS_CHILDREN = new ErrorCode(1_040_502_004, "åå¨åå·¥åï¼æ æ³å é¤"); |
| | | ErrorCode PRO_WORK_ORDER_PRODUCT_MISMATCH = new ErrorCode(1_040_502_005, "å½å产åç©æä¸ç产工å产åä¸ä¸è´"); |
| | | ErrorCode PRO_WORK_ORDER_SCHEDULE_QUANTITY_EXCEED = new ErrorCode(1_040_502_006, "æäº§æ°éè¶
éï¼å·¥å{}(计å{}ï¼å·²æäº§{}ï¼æ¬æ¬¡æäº§{})"); |
| | |
| | | ErrorCode PRO_MPS_CODE_DUPLICATE = new ErrorCode(1_040_509_006, "MPS ç¼ç å·²åå¨"); |
| | | ErrorCode PRO_MPS_HAS_WORK_ORDER = new ErrorCode(1_040_509_007, "MPS å·²å
³èç产工åï¼æ æ³å é¤"); |
| | | ErrorCode PRO_MPS_MES_PRODUCT_NOT_EXISTS = new ErrorCode(1_040_509_008, "MES 产åä¸åå¨ï¼æ æ³å建 MPSï¼äº§åï¼{}"); |
| | | ErrorCode PRO_MPS_PRODUCT_TYPE_INVALID = new ErrorCode(1_040_509_009, "æç¨äº§åå¿
é¡»æ¯äº§åç±»åï¼ç¦æ¢ä½¿ç¨ç©æ"); |
| | | |
| | | // ========== MES è´¨é管ç-è´¨æ£æ¹æ¡ï¼1-040-600-000ï¼ ========== |
| | | ErrorCode QC_TEMPLATE_NOT_EXISTS = new ErrorCode(1_040_600_000, "è´¨æ£æ¹æ¡ä¸åå¨"); |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pd.product.MesPdProductDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pd.product.MesPdProductMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.DictTypeConstants; |
| | | import cn.iocoder.yudao.module.mes.enums.pd.MesPdAuditStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.md.autocode.MesMdAutoCodeRuleCodeEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pd.MesPdAuditStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; |
| | |
| | | private void fillDictName(MesPdProductRespVO respVO) { |
| | | respVO.setArchiveTypeName(DictFrameworkUtils.parseDictDataLabel( |
| | | DictTypeConstants.MES_PD_PRODUCT_ARCHIVE_TYPE, respVO.getArchiveType())); |
| | | respVO.setAuditStatusName(DictFrameworkUtils.parseDictDataLabel( |
| | | DictTypeConstants.MES_PD_PRODUCT_AUDIT_STATUS, respVO.getAuditStatus())); |
| | | String auditStatusName = DictFrameworkUtils.parseDictDataLabel( |
| | | DictTypeConstants.MES_PD_PRODUCT_AUDIT_STATUS, respVO.getAuditStatus()); |
| | | respVO.setAuditStatusName(auditStatusName != null |
| | | ? auditStatusName : MesPdAuditStatusEnum.getNameByStatus(respVO.getAuditStatus())); |
| | | } |
| | | |
| | | } |
| | |
| | | import cn.hutool.core.date.DateUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchasePlanApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchasePlanApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchasePlanCreateReqDTO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.maintenanceplan.vo.MesProMaintenancePlanPageReqVO; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.maintenanceplan.vo.MesProMaintenancePlanSaveReqVO; |
| | |
| | | private MesMdItemService itemService; |
| | | |
| | | @Resource |
| | | private ErpPurchasePlanApi erpPurchasePlanApi; |
| | | private PurchasePlanApi purchasePlanApi; |
| | | @Resource |
| | | private MesProWorkOrderService workOrderService; |
| | | |
| | |
| | | createReqDTO.setPlanDate(plan.getPlanDate()); |
| | | createReqDTO.setRemark("æ¥æºè®¡å: " + plan.getCode()); |
| | | createReqDTO.setItems(items); |
| | | return erpPurchasePlanApi.createPurchasePlan(createReqDTO); |
| | | return purchasePlanApi.createPurchasePlan(createReqDTO); |
| | | } |
| | | |
| | | @Override |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.feedback.MesProFeedbackDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductBomDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; |
| | | import cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum; |
| | |
| | | @Resource |
| | | private MesMdItemService itemService; |
| | | @Resource |
| | | private MesMdItemTypeService itemTypeService; |
| | | @Resource |
| | | private MesMdAutoCodeRecordService autoCodeRecordService; |
| | | @Resource |
| | | private CrmCustomerApi customerApi; |
| | |
| | | Long mdmItemId, String productName, BigDecimal quantity, Long clientId, |
| | | String requestDate, String remark) { |
| | | // 1. æ ¹æ® MDM ç©æ ID æ¥æ¾ MES 产å |
| | | cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO mesItem = itemService.getItemByMdmItemId(mdmItemId); |
| | | MesMdItemDO mesItem = itemService.getItemByMdmItemId(mdmItemId); |
| | | if (mesItem == null) { |
| | | // MES 产åä¸åå¨ï¼æåºå¼å¸¸å¹¶å
å«äº§ååç§°æç¤º |
| | | throw exception(PRO_MPS_MES_PRODUCT_NOT_EXISTS, productName != null ? productName : mdmItemId); |
| | | } |
| | | validateProductItem(mesItem.getId()); |
| | | |
| | | // 2. çæ MPS ç¼ç |
| | | String code = generateMpsCode(); |
| | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createMps(MesProMpsSaveReqVO createReqVO) { |
| | | // æ ¡éªäº§ååå¨ |
| | | itemService.validateItemExists(createReqVO.getProductId()); |
| | | // æ ¡éªäº§ååå¨ãå¯ç¨ä¸ä¸ºäº§åç±»å |
| | | validateProductItem(createReqVO.getProductId()); |
| | | |
| | | // 妿æªå¡«åç¼ç ï¼èªå¨çæ |
| | | if (StrUtil.isBlank(createReqVO.getCode())) { |
| | |
| | | public void updateMps(MesProMpsSaveReqVO updateReqVO) { |
| | | // æ ¡éªåå¨ + èç¨¿ç¶æ |
| | | validateMpsExistsAndDraft(updateReqVO.getId()); |
| | | // æ ¡éªäº§ååå¨ãå¯ç¨ä¸ä¸ºäº§åç±»å |
| | | validateProductItem(updateReqVO.getProductId()); |
| | | |
| | | // æ ¡éªç¼ç å¯ä¸ |
| | | validateMpsCodeUnique(updateReqVO.getId(), updateReqVO.getCode()); |
| | |
| | | } |
| | | |
| | | /** |
| | | * æ ¡éªäº§ååå¨ãå¯ç¨ä¸ä¸ºäº§åç±»å |
| | | */ |
| | | private void validateProductItem(Long itemId) { |
| | | MesMdItemDO item = itemService.validateItemExistsAndEnable(itemId); |
| | | MesMdItemTypeDO itemType = itemTypeService.getItemType(item.getItemTypeId()); |
| | | if (itemType == null || !MesMdItemTypeEnum.isProduct(itemType.getItemOrProduct())) { |
| | | throw exception(PRO_MPS_PRODUCT_TYPE_INVALID); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * æ ¹æ® MPS å建ç产工å |
| | | */ |
| | | private Long createWorkOrderFromMps(MesProMpsDO mps, BigDecimal quantity) { |
| | |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.route.vo.product.MesProRouteProductSaveReqVO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.route.MesProRouteProductDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.md.item.MesMdItemTypeDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pro.route.MesProRouteProductMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.md.MesMdItemTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemTypeService; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.context.annotation.Lazy; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @Resource |
| | | @Lazy |
| | | private MesProRouteProductBomService routeProductBomService; |
| | | @Resource |
| | | private MesMdItemService itemService; |
| | | @Resource |
| | | private MesMdItemTypeService itemTypeService; |
| | | |
| | | @Override |
| | | public Long createRouteProduct(MesProRouteProductSaveReqVO createReqVO) { |
| | | // 1.0 å·²å¯ç¨çå·¥èºè·¯çº¿ï¼ä¸å
许æä½ |
| | | routeService.validateRouteNotEnable(createReqVO.getRouteId()); |
| | | // 1.1 æ ¡éªäº§åå¯ä¸æ§ï¼ä¸ä¸ªäº§ååªè½å
³è䏿¡å·¥èºè·¯çº¿ï¼ |
| | | // 1.1 æ ¡éªäº§ååå¨ãå¯ç¨ä¸ç±»åæ£ç¡® |
| | | validateProductItem(createReqVO.getItemId()); |
| | | // 1.2 æ ¡éªäº§åå¯ä¸æ§ï¼ä¸ä¸ªäº§ååªè½å
³è䏿¡å·¥èºè·¯çº¿ï¼ |
| | | validateItemUnique(null, createReqVO.getItemId()); |
| | | |
| | | // 2. æå
¥ |
| | |
| | | routeService.validateRouteNotEnable(updateReqVO.getRouteId()); |
| | | // 1.1 æ ¡éªåå¨ |
| | | validateRouteProductExists(updateReqVO.getId()); |
| | | // 1.2 æ ¡éªäº§åå¯ä¸æ§ |
| | | // 1.2 æ ¡éªäº§ååå¨ãå¯ç¨ä¸ç±»åæ£ç¡® |
| | | validateProductItem(updateReqVO.getItemId()); |
| | | // 1.3 æ ¡éªäº§åå¯ä¸æ§ |
| | | validateItemUnique(updateReqVO.getId(), updateReqVO.getItemId()); |
| | | |
| | | // 2. æ´æ° |
| | |
| | | } |
| | | } |
| | | |
| | | private void validateProductItem(Long itemId) { |
| | | MesMdItemDO item = itemService.validateItemExistsAndEnable(itemId); |
| | | MesMdItemTypeDO itemType = itemTypeService.getItemType(item.getItemTypeId()); |
| | | if (itemType == null || !MesMdItemTypeEnum.isProduct(itemType.getItemOrProduct())) { |
| | | throw exception(PRO_ROUTE_PRODUCT_ITEM_TYPE_INVALID); |
| | | } |
| | | } |
| | | |
| | | private void validateItemUnique(Long id, Long itemId) { |
| | | MesProRouteProductDO existing = routeProductMapper.selectByItemId(itemId); |
| | | if (existing == null) { |
| | |
| | | if (ObjUtil.notEqual(workOrder.getStatus(), MesProWorkOrderStatusEnum.CONFIRMED.getStatus())) { |
| | | throw exception(PRO_WORK_ORDER_NOT_CONFIRMED); |
| | | } |
| | | if (workOrder.getQuantityProduced() == null |
| | | || workOrder.getQuantity() == null |
| | | || workOrder.getQuantityProduced().compareTo(workOrder.getQuantity()) < 0) { |
| | | throw exception(PRO_WORK_ORDER_PRODUCTION_NOT_COMPLETE); |
| | | } |
| | | // æ ¡éªæ¯ä¸ªä»»å¡çå®é
äº§åºæ¯å¦å·²è¾¾æè®¡åæ°éï¼ä»»å¡ç¶æåªæå¨å·¥å宿æ¶ç±çº§èæ¹æ³ç½®ä¸ºå·²å®æï¼ä¸è½å¨æ¤æ ¡éªç¶æï¼ |
| | | List<MesProTaskDO> tasks = taskService.getTaskListByWorkOrderIds(Collections.singletonList(id)); |
| | | boolean hasUnfinishedTask = CollUtil.isEmpty(tasks) || tasks.stream().anyMatch(task -> |
| | | task.getProducedQuantity() == null |
| | | || task.getQuantity() == null |
| | | || task.getProducedQuantity().compareTo(task.getQuantity()) < 0); |
| | | if (hasUnfinishedTask) { |
| | | throw exception(PRO_WORK_ORDER_PRODUCTION_NOT_COMPLETE); |
| | | } |
| | | |
| | | // 2. 级è宿ææå
³èä»»å¡ |
| | | taskService.finishTaskByOrderId(id); |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.wm.arrivalnotice.MesWmArrivalNoticeLineDO; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.wm.arrivalnotice.MesWmArrivalNoticeMapper; |
| | | import cn.iocoder.yudao.module.mes.enums.wm.MesWmArrivalNoticeStatusEnum; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderRespDTO; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderItemRespDTO; |
| | |
| | | private SrmSupplierApi srmSupplierApi; |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderApi purchaseOrderApi; |
| | | private PurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @Resource |
| | | private MesMdmItemService mdmItemService; |
| | |
| | | import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO; |
| | | import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; |
| | | import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.srm.api.supplier.SrmSupplierApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | |
| | | private BpmProcessInstanceApi processInstanceApi; |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderApi purchaseOrderApi; |
| | | private PurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | |
| | | if (item == null) { |
| | | continue; |
| | | } |
| | | // å¦æç©æå¼å¯æ¹æ¬¡ç®¡çï¼æ£æ¥è¡ä¸çæ¹æ¬¡å·æ¯å¦ä¸ºç©º |
| | | if (Boolean.TRUE.equals(item.getIsBatchManaged()) && line.getBatchId() == null) { |
| | | throw exception(WM_ITEM_RECEIPT_BATCH_REQUIRED, item.getCode(), item.getName()); |
| | | // å¦æç©æå¼å¯æ¹æ¬¡ç®¡çï¼è¡æå
¶ä¸æ¶æç»å¿
é¡»æºå¸¦æ¹æ¬¡å·ï¼å¦åæ æ³çæåºåäºå¡ |
| | | if (Boolean.TRUE.equals(item.getIsBatchManaged())) { |
| | | boolean hasBatch = line.getBatchId() != null |
| | | || hasDetailBatch(itemReceiptDetailService.getItemReceiptDetailListByLineId(line.getId())); |
| | | if (!hasBatch) { |
| | | throw exception(WM_ITEM_RECEIPT_BATCH_REQUIRED, item.getCode(), item.getName()); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | private boolean hasDetailBatch(List<MesWmItemReceiptDetailDO> details) { |
| | | return details.stream().anyMatch(detail -> detail.getBatchId() != null); |
| | | } |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void stockItemReceipt(Long id) { |
| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderCreateReqDTO; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | |
| | | private MdmItemApi mdmItemApi; |
| | | |
| | | @Resource |
| | | private ErpPurchaseOrderApi erpPurchaseOrderApi; |
| | | private PurchaseOrderApi purchaseOrderApi; |
| | | |
| | | @Resource |
| | | private SrmSupplierApplyService supplierApplyService; |
| | |
| | | createReq.setItems(orderItems); |
| | | createReq.setRemark("SRM 宿 èªå¨çæ, 宿 ç¼å·: " + award.getAwardNo()); |
| | | |
| | | Long purchaseOrderId = erpPurchaseOrderApi.createPurchaseOrder(createReq).getCheckedData(); |
| | | Long purchaseOrderId = purchaseOrderApi.createPurchaseOrder(createReq).getCheckedData(); |
| | | |
| | | // è·åéè´è®¢åå· |
| | | String purchaseOrderNo = null; |
| | | try { |
| | | purchaseOrderNo = erpPurchaseOrderApi.getPurchaseOrder(purchaseOrderId) |
| | | purchaseOrderNo = purchaseOrderApi.getPurchaseOrder(purchaseOrderId) |
| | | .getCheckedData().getNo(); |
| | | } catch (Exception e) { |
| | | log.warn("[generatePurchaseOrder] è·åéè´è®¢åå·å¤±è´¥ï¼purchaseOrderId={}", purchaseOrderId, e); |
| | |
| | | import cn.hutool.core.collection.CollUtil; |
| | | import cn.iocoder.yudao.framework.common.pojo.PageResult; |
| | | import cn.iocoder.yudao.framework.common.util.object.BeanUtils; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.ErpPurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.PurchaseOrderApi; |
| | | import cn.iocoder.yudao.module.erp.api.purchase.dto.ErpPurchaseOrderCreateReqDTO; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | |
| | | @Resource |
| | | private MdmItemApi mdmItemApi; |
| | | @Resource |
| | | private ErpPurchaseOrderApi erpPurchaseOrderApi; |
| | | private PurchaseOrderApi purchaseOrderApi; |
| | | @Resource |
| | | private SrmSupplierApplyService supplierApplyService; |
| | | @Resource |
| | |
| | | createReq.setItems(orderItems); |
| | | createReq.setRemark("SRM ç®ææææ èªå¨çæ, 宿 ç¼å·: " + award.getAwardNo()); |
| | | |
| | | Long purchaseOrderId = erpPurchaseOrderApi.createPurchaseOrder(createReq).getCheckedData(); |
| | | Long purchaseOrderId = purchaseOrderApi.createPurchaseOrder(createReq).getCheckedData(); |
| | | |
| | | // è·åéè´è®¢åå· |
| | | String purchaseOrderNo = null; |
| | | try { |
| | | purchaseOrderNo = erpPurchaseOrderApi.getPurchaseOrder(purchaseOrderId) |
| | | purchaseOrderNo = purchaseOrderApi.getPurchaseOrder(purchaseOrderId) |
| | | .getCheckedData().getNo(); |
| | | } catch (Exception e) { |
| | | log.warn("[generatePurchaseOrderForSimple] è·åéè´è®¢åå·å¤±è´¥ï¼purchaseOrderId={}", purchaseOrderId, e); |