feat(erp): 为ERP模块添加附件功能支持
- 在付款单、收款单、采购订单、采购申请、销售订单中集成附件上传和展示功能
- 添加附件列表查询接口用于获取相关业务单据的附件
- 实现附件绑定、更新和删除的完整生命周期管理
- 重构文件存储路径配置为/data/javaWork/mom/file
- 为采购申请分页查询添加入库状态过滤条件
- 扩展采购申请响应对象增加工作流编号字段
- 优化MES生产工单创建流程,增加工艺路线校验和工序数据同步
- 新增多个业务类型的存储记录枚举值以支持附件分类管理
| | |
| | | import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; |
| | | import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService; |
| | | import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建付款单") |
| | |
| | | } |
| | | List<ErpFinancePaymentItemDO> paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentId(id); |
| | | return success(BeanUtils.toBean(payment, ErpFinancePaymentRespVO.class, financePaymentVO -> |
| | | financePaymentVO.setItems(BeanUtils.toBean(paymentItemList, ErpFinancePaymentRespVO.Item.class)))); |
| | | financePaymentVO.setItems(BeanUtils.toBean(paymentItemList, ErpFinancePaymentRespVO.Item.class)) |
| | | .setAttachmentList(storageAttachmentApi.listAttachments("erp_finance_payment", id)))); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | import cn.iocoder.yudao.module.erp.service.finance.ErpFinanceReceiptService; |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import cn.iocoder.yudao.module.crm.api.customer.dto.CrmCustomerRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建收款单") |
| | |
| | | } |
| | | List<ErpFinanceReceiptItemDO> receiptItemList = financeReceiptService.getFinanceReceiptItemListByReceiptId(id); |
| | | return success(BeanUtils.toBean(receipt, ErpFinanceReceiptRespVO.class, financeReceiptVO -> |
| | | financeReceiptVO.setItems(BeanUtils.toBean(receiptItemList, ErpFinanceReceiptRespVO.Item.class)))); |
| | | financeReceiptVO.setItems(BeanUtils.toBean(receiptItemList, ErpFinanceReceiptRespVO.Item.class)) |
| | | .setAttachmentList(storageAttachmentApi.listAttachments("erp_finance_receipt", id)))); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | |
| | | @Schema(description = "备注", example = "你猜") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件列表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "创建人", example = "芋道") |
| | | private String creator; |
| | | @Schema(description = "创建人名称", example = "芋道") |
| | |
| | | @Schema(description = "备注", example = "你猜") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件 blobId 列表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotEmpty(message = "付款项列表不能为空") |
| | | @Valid |
| | |
| | | |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | |
| | | @Schema(description = "备注", example = "你猜") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件列表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "创建人", example = "芋道") |
| | | private String creator; |
| | | @Schema(description = "创建人名称", example = "芋道") |
| | |
| | | @Schema(description = "备注", example = "你猜") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件 blobId 列表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "收款项列表", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotEmpty(message = "收款项列表不能为空") |
| | | @Valid |
| | |
| | | import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; |
| | | import cn.iocoder.yudao.module.mdm.api.item.MdmItemApi; |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | private MdmItemApi mdmItemApi; |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建采购订单") |
| | |
| | | item.setStockCount(BigDecimal.ZERO); |
| | | MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName()) |
| | | .setProductBarCode(mdmItem.getBarCode())); |
| | | })))); |
| | | })).setAttachmentList(storageAttachmentApi.listAttachments("erp_purchase_order", id)))); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private DeptApi deptApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建采购申请") |
| | |
| | | purchaseRequestVO.setItems(BeanUtils.toBean(purchaseRequestItemList, ErpPurchaseRequestRespVO.Item.class, item -> { |
| | | MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName()) |
| | | .setProductBarCode(mdmItem.getBarCode())); |
| | | })))); |
| | | })).setAttachmentList(storageAttachmentApi.listAttachments("erp_purchase_request", id)))); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | |
| | | @ExcelProperty("备注") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件列表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "创建人", example = "芋道") |
| | | private String creator; |
| | | @Schema(description = "创建人名称", example = "芋道") |
| | |
| | | @Schema(description = "备注", example = "你猜") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件 blobId 列表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "订单清单列表") |
| | | private List<Item> items; |
| | | |
| | |
| | | @Schema(description = "产品编号", example = "1") |
| | | private Long productId; |
| | | |
| | | @Schema(description = "入库状态(0:未入库 1:部分入库 2:全部入库)", example = "0") |
| | | private Integer inStatus; |
| | | |
| | | } |
| | |
| | | package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.request; |
| | | |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import lombok.Data; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.util.List; |
| | | |
| | | @Schema(description = "管理后台 - ERP 采购申请 Response VO") |
| | | @Data |
| | |
| | | |
| | | @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") |
| | | private Integer status; |
| | | |
| | | @Schema(description = "工作流编号", example = "1043") |
| | | private String processInstanceId; |
| | | |
| | | @Schema(description = "申请人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") |
| | | private Long requestUserId; |
| | |
| | | @Schema(description = "备注", example = "备注") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件列表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "创建时间") |
| | | private LocalDateTime createTime; |
| | | |
| | |
| | | @Schema(description = "备注", example = "备注") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件 blobId 列表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "申请明细列表", requiredMode = Schema.RequiredMode.REQUIRED) |
| | | @NotEmpty(message = "申请明细不能为空") |
| | | @Valid |
| | |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi; |
| | | import cn.iocoder.yudao.module.mes.api.salesnotice.MesWmSalesNoticeApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import io.swagger.v3.oas.annotations.Operation; |
| | |
| | | private MesWmSalesNoticeApi salesNoticeApi; |
| | | @Resource |
| | | private MesProMpsApi mpsApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @PostMapping("/create") |
| | | @Operation(summary = "创建销售订单") |
| | |
| | | item.setStockCount(BigDecimal.ZERO); |
| | | MapUtils.findAndThen(itemMap, item.getProductId(), mdmItem -> item.setProductName(mdmItem.getName()) |
| | | .setProductBarCode(mdmItem.getBarCode())); |
| | | })))); |
| | | })).setAttachmentList(storageAttachmentApi.listAttachments("erp_sale_order", id)))); |
| | | } |
| | | |
| | | @GetMapping("/page") |
| | |
| | | |
| | | import cn.idev.excel.annotation.ExcelIgnoreUnannotated; |
| | | import cn.idev.excel.annotation.ExcelProperty; |
| | | import cn.iocoder.yudao.module.system.api.storage.dto.StorageBlobRespDTO; |
| | | import io.swagger.v3.oas.annotations.media.Schema; |
| | | import jakarta.validation.constraints.NotNull; |
| | | import lombok.Data; |
| | |
| | | @ExcelProperty("备注") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件列表") |
| | | private List<StorageBlobRespDTO> attachmentList; |
| | | |
| | | @Schema(description = "创建人", example = "芋道") |
| | | private String creator; |
| | | @Schema(description = "创建人名称", example = "芋道") |
| | |
| | | @Schema(description = "备注", example = "你猜") |
| | | private String remark; |
| | | |
| | | @Schema(description = "附件 blobId 列表", example = "[1, 2, 3]") |
| | | private List<Long> blobIds; |
| | | |
| | | @Schema(description = "订单清单列表") |
| | | private List<Item> items; |
| | | |
| | |
| | | .eqIfPresent(ErpPurchaseRequestDO::getRequestDeptId, pageReqVO.getRequestDeptId()) |
| | | .eqIfPresent(ErpPurchaseRequestDO::getSupplierId, pageReqVO.getSupplierId()) |
| | | .eqIfPresent(ErpPurchaseRequestDO::getStatus, pageReqVO.getStatus()) |
| | | .eqIfPresent(ErpPurchaseRequestDO::getInStatus, pageReqVO.getInStatus()) |
| | | .betweenIfPresent(ErpPurchaseRequestDO::getRequestTime, pageReqVO.getRequestTime()) |
| | | .orderByDesc(ErpPurchaseRequestDO::getId)); |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; |
| | | import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; |
| | | import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createFinancePayment(ErpFinancePaymentSaveReqVO createReqVO) { |
| | |
| | | // 2.2 插入付款单项 |
| | | paymentItems.forEach(o -> o.setPaymentId(payment.getId())); |
| | | financePaymentItemMapper.insertBatch(paymentItems); |
| | | |
| | | // 2.3 绑定附件 |
| | | storageAttachmentApi.bindAttachments("file", "erp_finance_payment", |
| | | payment.getId(), createReqVO.getBlobIds()); |
| | | |
| | | // 3. 更新采购入库、退货的付款金额情况 |
| | | updatePurchasePrice(paymentItems); |
| | |
| | | financePaymentMapper.updateById(updateObj); |
| | | // 2.2 更新付款单项 |
| | | updateFinancePaymentItemList(updateReqVO.getId(), paymentItems); |
| | | // 2.3 更新附件 |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_finance_payment", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "erp_finance_payment", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | private void calculateTotalPrice(ErpFinancePaymentDO payment, List<ErpFinancePaymentItemDO> paymentItems) { |
| | |
| | | |
| | | // 2. 遍历删除,并记录操作日志 |
| | | payments.forEach(payment -> { |
| | | // 2.1 删除付款单 |
| | | // 2.1 删除附件 |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_finance_payment", payment.getId()); |
| | | // 2.2 删除付款单 |
| | | financePaymentMapper.deleteById(payment.getId()); |
| | | // 2.2 删除付款单项 |
| | | // 2.3 删除付款单项 |
| | | List<ErpFinancePaymentItemDO> paymentItems = financePaymentItemMapper.selectListByPaymentId(payment.getId()); |
| | | financePaymentItemMapper.deleteByIds(convertSet(paymentItems, ErpFinancePaymentItemDO::getId)); |
| | | |
| | |
| | | import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinanceReceiptMapper; |
| | | import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; |
| | | import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import jakarta.annotation.Resource; |
| | | import org.springframework.stereotype.Service; |
| | |
| | | @Resource |
| | | private AdminUserApi adminUserApi; |
| | | |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createFinanceReceipt(ErpFinanceReceiptSaveReqVO createReqVO) { |
| | |
| | | // 2.2 插入收款单项 |
| | | receiptItems.forEach(o -> o.setReceiptId(receipt.getId())); |
| | | financeReceiptItemMapper.insertBatch(receiptItems); |
| | | |
| | | // 2.3 绑定附件 |
| | | storageAttachmentApi.bindAttachments("file", "erp_finance_receipt", |
| | | receipt.getId(), createReqVO.getBlobIds()); |
| | | |
| | | // 3. 更新销售出库、退货的收款金额情况 |
| | | updateSalePrice(receiptItems); |
| | |
| | | financeReceiptMapper.updateById(updateObj); |
| | | // 2.2 更新收款单项 |
| | | updateFinanceReceiptItemList(updateReqVO.getId(), receiptItems); |
| | | // 2.3 更新附件 |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_finance_receipt", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "erp_finance_receipt", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | private void calculateTotalPrice(ErpFinanceReceiptDO receipt, List<ErpFinanceReceiptItemDO> receiptItems) { |
| | |
| | | |
| | | // 2. 遍历删除,并记录操作日志 |
| | | receipts.forEach(receipt -> { |
| | | // 2.1 删除收款单 |
| | | // 2.1 删除附件 |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_finance_receipt", receipt.getId()); |
| | | // 2.2 删除收款单 |
| | | financeReceiptMapper.deleteById(receipt.getId()); |
| | | // 2.2 删除收款单项 |
| | | // 2.3 删除收款单项 |
| | | List<ErpFinanceReceiptItemDO> receiptItems = financeReceiptItemMapper.selectListByReceiptId(receipt.getId()); |
| | | financeReceiptItemMapper.deleteByIds(convertSet(receiptItems, ErpFinanceReceiptItemDO::getId)); |
| | | |
| | |
| | | import cn.iocoder.yudao.module.erp.enums.ErpPurchaseOrderInStatusEnum; |
| | | import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; |
| | | import cn.iocoder.yudao.module.mes.api.arrivalnotice.MesArrivalNoticeApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.flowable.engine.repository.ProcessDefinition; |
| | |
| | | @Resource |
| | | private ErpPurchaseRequestMapper purchaseRequestMapper; |
| | | |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createPurchaseOrder(ErpPurchaseOrderSaveReqVO createReqVO) { |
| | |
| | | // 2.2 插入订单项 |
| | | purchaseOrderItems.forEach(o -> o.setOrderId(purchaseOrder.getId())); |
| | | purchaseOrderItemMapper.insertBatch(purchaseOrderItems); |
| | | // 2.3 绑定附件 |
| | | storageAttachmentApi.bindAttachments("file", "erp_purchase_order", |
| | | purchaseOrder.getId(), createReqVO.getBlobIds()); |
| | | return purchaseOrder.getId(); |
| | | } |
| | | |
| | |
| | | purchaseOrderMapper.updateById(updateObj); |
| | | // 2.2 更新订单项 |
| | | updatePurchaseOrderItemList(updateReqVO.getId(), purchaseOrderItems); |
| | | // 2.3 更新附件 |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_purchase_order", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "erp_purchase_order", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | private void calculateTotalPrice(ErpPurchaseOrderDO purchaseOrder, List<ErpPurchaseOrderItemDO> purchaseOrderItems) { |
| | |
| | | |
| | | // 2. 遍历删除 |
| | | purchaseOrders.forEach(purchaseOrder -> { |
| | | // 2.1 删除附件 |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_purchase_order", purchaseOrder.getId()); |
| | | // 2.2 删除订单 |
| | | purchaseOrderMapper.deleteById(purchaseOrder.getId()); |
| | | // 2.3 删除订单项 |
| | | purchaseOrderItemMapper.deleteByOrderId(purchaseOrder.getId()); |
| | | }); |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; |
| | | import cn.iocoder.yudao.module.erp.enums.ErpPurchaseRequestStatusEnum; |
| | | import cn.iocoder.yudao.module.system.api.dept.DeptApi; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; |
| | | import jakarta.annotation.Resource; |
| | |
| | | private AdminUserApi adminUserApi; |
| | | @Resource |
| | | private DeptApi deptApi; |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | calculateTotalPrice(purchaseRequest, requestItems); |
| | | purchaseRequestMapper.insert(purchaseRequest); |
| | | |
| | | // 6. 插入申请明细 |
| | | // 6. 绑定附件 |
| | | storageAttachmentApi.bindAttachments("file", "erp_purchase_request", |
| | | purchaseRequest.getId(), createReqVO.getBlobIds()); |
| | | |
| | | // 7. 插入申请明细 |
| | | requestItems.forEach(o -> o.setRequestId(purchaseRequest.getId())); |
| | | purchaseRequestItemMapper.insertBatch(requestItems); |
| | | |
| | |
| | | |
| | | // 5. 更新申请明细 |
| | | updatePurchaseRequestItemList(updateReqVO.getId(), requestItems); |
| | | |
| | | // 6. 更新附件 |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_purchase_request", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "erp_purchase_request", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | private void calculateTotalPrice(ErpPurchaseRequestDO purchaseRequest, List<ErpPurchaseRequestItemDO> requestItems) { |
| | |
| | | }); |
| | | |
| | | purchaseRequests.forEach(purchaseRequest -> { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_purchase_request", purchaseRequest.getId()); |
| | | purchaseRequestMapper.deleteById(purchaseRequest.getId()); |
| | | purchaseRequestItemMapper.deleteByRequestId(purchaseRequest.getId()); |
| | | }); |
| | |
| | | import cn.iocoder.yudao.module.mdm.api.item.dto.MdmItemRespDTO; |
| | | import cn.iocoder.yudao.module.mes.api.mps.MesProMpsApi; |
| | | import cn.iocoder.yudao.module.mes.api.mps.dto.MesProMpsCreateReqDTO; |
| | | import cn.iocoder.yudao.module.system.api.storage.StorageAttachmentApi; |
| | | import cn.iocoder.yudao.module.system.api.user.AdminUserApi; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | @Resource |
| | | private MesProMpsApi mpsApi; |
| | | |
| | | @Resource |
| | | private StorageAttachmentApi storageAttachmentApi; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public Long createSaleOrder(ErpSaleOrderSaveReqVO createReqVO) { |
| | |
| | | // 2.2 插入订单项 |
| | | saleOrderItems.forEach(o -> o.setOrderId(saleOrder.getId())); |
| | | saleOrderItemMapper.insertBatch(saleOrderItems); |
| | | // 2.3 绑定附件 |
| | | storageAttachmentApi.bindAttachments("file", "erp_sale_order", |
| | | saleOrder.getId(), createReqVO.getBlobIds()); |
| | | return saleOrder.getId(); |
| | | } |
| | | |
| | |
| | | saleOrderMapper.updateById(updateObj); |
| | | // 2.2 更新订单项 |
| | | updateSaleOrderItemList(updateReqVO.getId(), saleOrderItems); |
| | | // 2.3 更新附件 |
| | | if (updateReqVO.getBlobIds() != null) { |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_sale_order", updateReqVO.getId()); |
| | | storageAttachmentApi.bindAttachments("file", "erp_sale_order", |
| | | updateReqVO.getId(), updateReqVO.getBlobIds()); |
| | | } |
| | | } |
| | | |
| | | private void calculateTotalPrice(ErpSaleOrderDO saleOrder, List<ErpSaleOrderItemDO> saleOrderItems) { |
| | |
| | | |
| | | // 2. 遍历删除,并记录操作日志 |
| | | saleOrders.forEach(saleOrder -> { |
| | | // 2.1 删除订单 |
| | | // 2.1 删除附件 |
| | | storageAttachmentApi.deleteAttachmentsByRecord("erp_sale_order", saleOrder.getId()); |
| | | // 2.2 删除订单 |
| | | saleOrderMapper.deleteById(saleOrder.getId()); |
| | | // 2.2 删除订单项 |
| | | // 2.3 删除订单项 |
| | | saleOrderItemMapper.deleteByOrderId(saleOrder.getId()); |
| | | }); |
| | | } |
| | |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pro.mps.MesProMpsMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pro.mps.MesProMpsMergeItemMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pro.feedback.MesProFeedbackMapper; |
| | | import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper; |
| | | 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.pro.route.MesProRouteProcessDO; |
| | | import cn.iocoder.yudao.module.mes.dal.dataobject.pro.workorder.MesProWorkOrderDO; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProMpsStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProFeedbackStatusEnum; |
| | | import cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderSourceTypeEnum; |
| | | import cn.iocoder.yudao.module.mes.service.md.autocode.MesMdAutoCodeRecordService; |
| | | import cn.iocoder.yudao.module.mes.service.md.item.MesMdItemService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProductService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.route.MesProRouteProcessService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderService; |
| | | import cn.iocoder.yudao.module.mes.service.pro.workorder.MesProWorkOrderProcessService; |
| | | import cn.iocoder.yudao.module.mes.controller.admin.pro.workorder.vo.process.MesProWorkOrderProcessSaveReqVO; |
| | | import cn.iocoder.yudao.module.crm.api.customer.CrmCustomerApi; |
| | | import jakarta.annotation.Resource; |
| | | import lombok.extern.slf4j.Slf4j; |
| | |
| | | import java.math.BigDecimal; |
| | | import java.time.LocalDateTime; |
| | | import java.time.format.DateTimeFormatter; |
| | | import java.util.ArrayList; |
| | | import java.util.Collection; |
| | | import java.util.Collections; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | |
| | | import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; |
| | | import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*; |
| | |
| | | private CrmCustomerApi customerApi; |
| | | @Resource |
| | | private MesProFeedbackMapper feedbackMapper; |
| | | @Resource |
| | | private MesProWorkOrderMapper workOrderMapper; |
| | | @Resource |
| | | private MesProRouteProductService routeProductService; |
| | | @Resource |
| | | private MesProRouteProcessService routeProcessService; |
| | | @Resource |
| | | private MesProWorkOrderProcessService workOrderProcessService; |
| | | |
| | | @Override |
| | | @Transactional(rollbackFor = Exception.class) |
| | |
| | | * 根据 MPS 创建生产工单 |
| | | */ |
| | | private Long createWorkOrderFromMps(MesProMpsDO mps, BigDecimal quantity) { |
| | | // 1. 校验产品是否存在工艺路线 |
| | | MesProRouteProductDO routeProduct = routeProductService.getRouteProductByItemId(mps.getProductId()); |
| | | if (routeProduct == null) { |
| | | throw exception(PRO_ROUTE_NOT_EXISTS); |
| | | } |
| | | Long routeId = routeProduct.getRouteId(); |
| | | |
| | | // 2. 校验工艺路线是否有工序 |
| | | List<MesProRouteProcessDO> routeProcesses = routeProcessService.getRouteProcessListByRouteId(routeId); |
| | | if (CollUtil.isEmpty(routeProcesses)) { |
| | | throw exception(PRO_ROUTE_ENABLE_NO_PROCESS); |
| | | } |
| | | |
| | | // 3. 创建生产工单 |
| | | MesProWorkOrderSaveReqVO workOrderReq = new MesProWorkOrderSaveReqVO(); |
| | | workOrderReq.setCode(generateWorkOrderCode()); |
| | | workOrderReq.setName("生产工单-" + mps.getCode()); |
| | |
| | | |
| | | Long workOrderId = workOrderService.createWorkOrder(workOrderReq); |
| | | |
| | | // 工单直接确认为已确认状态(跳过草稿) |
| | | // 4. 更新工单工艺路线 |
| | | workOrderMapper.updateById(new MesProWorkOrderDO().setId(workOrderId).setRouteId(routeId)); |
| | | |
| | | // 5. 保存工单工序(从工艺路线工序带入,含投料BOM) |
| | | Map<Long, List<MesProRouteProductBomDO>> bomMap = routeProcessService.getRouteProcessBomMapByProductId(mps.getProductId()); |
| | | List<MesProWorkOrderProcessSaveReqVO> processList = new ArrayList<>(); |
| | | for (MesProRouteProcessDO rp : routeProcesses) { |
| | | MesProWorkOrderProcessSaveReqVO process = new MesProWorkOrderProcessSaveReqVO(); |
| | | process.setWorkOrderId(workOrderId); |
| | | process.setProcessId(rp.getProcessId()); |
| | | process.setSort(rp.getSort()); |
| | | process.setKeyFlag(rp.getKeyFlag()); |
| | | process.setCheckFlag(rp.getCheckFlag()); |
| | | process.setBackflushFlag(rp.getBackflushFlag()); |
| | | process.setOutputItemId(rp.getOutputItemId()); |
| | | process.setColorCode(rp.getColorCode()); |
| | | // 带入工序投料BOM |
| | | List<MesProRouteProductBomDO> routeBomItems = bomMap != null ? bomMap.get(rp.getProcessId()) : null; |
| | | if (CollUtil.isNotEmpty(routeBomItems)) { |
| | | List<MesProWorkOrderProcessSaveReqVO.BomItem> bomItems = new ArrayList<>(); |
| | | for (MesProRouteProductBomDO bomDO : routeBomItems) { |
| | | MesProWorkOrderProcessSaveReqVO.BomItem bomItem = new MesProWorkOrderProcessSaveReqVO.BomItem(); |
| | | bomItem.setItemId(bomDO.getItemId()); |
| | | bomItem.setQuantity(bomDO.getQuantity()); |
| | | bomItem.setRemark(bomDO.getRemark()); |
| | | bomItems.add(bomItem); |
| | | } |
| | | process.setBomItems(bomItems); |
| | | } |
| | | processList.add(process); |
| | | } |
| | | workOrderProcessService.batchSaveWorkOrderProcess(processList); |
| | | |
| | | // 6. 工单直接确认为已确认状态 |
| | | workOrderService.confirmWorkOrder(workOrderId); |
| | | |
| | | return workOrderId; |
| | |
| | | NOTICE("notice", "通知公告"), |
| | | |
| | | // ===== 头像 ===== |
| | | AVATAR("avatar", "头像"); |
| | | AVATAR("avatar", "头像"), |
| | | |
| | | // ===== ERP 采购 ===== |
| | | ERP_PURCHASE_REQUEST("erp_purchase_request", "ERP 采购申请"), |
| | | ERP_PURCHASE_ORDER("erp_purchase_order", "ERP 采购订单"), |
| | | |
| | | // ===== ERP 销售 ===== |
| | | ERP_SALE_ORDER("erp_sale_order", "ERP 销售订单"), |
| | | |
| | | // ===== ERP 财务 ===== |
| | | ERP_FINANCE_RECEIPT("erp_finance_receipt", "ERP 收款单"), |
| | | ERP_FINANCE_PAYMENT("erp_finance_payment", "ERP 付款单"), |
| | | |
| | | // ===== CRM ===== |
| | | CRM_SALE_QUOTATION("crm_sale_quotation", "CRM 销售报价单"), |
| | | CRM_FOLLOW_UP_RECORD("crm_follow_up_record", "CRM 跟进记录"), |
| | | |
| | | // ===== HRM ===== |
| | | HRM_LEAVE_APPLICATION("hrm_leave_application", "HRM 请假申请"), |
| | | HRM_TRANSFER_APPLICATION("hrm_transfer_application", "HRM 调动申请"), |
| | | HRM_RESIGNATION_APPLICATION("hrm_resignation_application", "HRM 离职申请"), |
| | | HRM_ATTENDANCE_EXCEPTION("hrm_attendance_exception", "HRM 考勤异常"), |
| | | |
| | | // ===== MES ===== |
| | | MES_PD_DOCUMENT("mes_pd_document", "MES 设计资料"); |
| | | |
| | | private final String type; |
| | | private final String description; |
| | |
| | | miniprogram-state: developer # 跳转小程序类型:开发版为 “developer”;体验版为 “trial”为;正式版为 “formal” |
| | | tencent-lbs-key: TVDBZ-TDILD-4ON4B-PFDZA-RNLKH-VVF6E # QQ 地图的密钥 https://lbs.qq.com/service/staticV2/staticGuide/staticDoc |
| | | storage: # 文件上传配置 |
| | | path: /data/uploads # 文件存储根目录 |
| | | path: /data/javaWork/mom/file # 文件存储根目录 |
| | | url-prefix: /admin-api/system/storage-blob # URL路径前缀 |
| | | domain: https://test.your-domain.com # 域名前缀(按实际域名配置) |
| | | expired: 120 # token过期时间(分钟) |