云
4 天以前 8bcec29715251194f7358bd1035033293e955ce1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package cn.iocoder.yudao.module.mes.controller.admin.wm.scrap;
 
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.mes.dal.dataobject.wm.scrap.MesWmScrapReceiptDO;
import cn.iocoder.yudao.module.mes.dal.mysql.pro.workorder.MesProWorkOrderMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.wm.scrap.MesWmScrapReceiptMapper;
import cn.iocoder.yudao.module.mes.enums.wm.MesWmTransactionTypeEnum;
import cn.iocoder.yudao.module.mes.service.wm.transaction.MesWmTransactionService;
import cn.iocoder.yudao.module.mes.service.wm.transaction.dto.MesWmTransactionSaveReqDTO;
import cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseAreaService;
import jakarta.annotation.Resource;
import jakarta.validation.Valid;
import jakarta.validation.constraints.DecimalMin;
import jakarta.validation.constraints.Digits;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.Pattern;
import lombok.Data;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
 
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.util.List;
import java.util.Map;
import cn.iocoder.yudao.framework.common.exception.ServiceException;
 
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
 
/** 独立废料入库:记录和库存流水在同一个事务中提交。 */
@RestController
@RequestMapping("/mes/wm/scrap-receipt")
@Validated
public class MesWmScrapReceiptController {
    @Resource private MesWmScrapReceiptMapper receiptMapper;
    @Resource private MesProWorkOrderMapper workOrderMapper;
    @Resource private MesWmTransactionService transactionService;
    @Resource private MesWmWarehouseAreaService areaService;
    @Resource private cn.iocoder.yudao.module.mes.service.wm.warehouse.MesWmWarehouseService warehouseService;
    @Resource private cn.iocoder.yudao.module.mdm.api.item.MdmItemApi itemApi;
 
    @GetMapping("/order-outputs")
    @PreAuthorize("@ss.hasPermission('mes:wm-scrap-receipt:create')")
    public CommonResult<List<OutputItem>> orderOutputs(@RequestParam("workOrderId") Long workOrderId) {
        var order = workOrderMapper.selectById(workOrderId);
        if (order == null || !java.util.Objects.equals(order.getStatus(), cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum.FINISHED.getStatus()))
            throw new ServiceException(400, "仅已完成的生产订单可以登记废料");
        var list = receiptMapper.selectOrderOutputs(workOrderId, cn.iocoder.yudao.module.mes.enums.wm.MesWmProductProduceStatusEnum.FINISHED.getStatus());
        var items = itemApi.getItemMap(list.stream().map(OutputItem::getItemId).collect(java.util.stream.Collectors.toSet()));
        list.forEach(output -> { var item = items.get(output.getItemId()); if (item != null) { output.setItemName(item.getName()); output.setItemCode(item.getCode()); } });
        return success(list);
    }
 
    @PostMapping("/create-from-output")
    @PreAuthorize("@ss.hasPermission('mes:wm-scrap-receipt:create')")
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Long> createFromOutput(@Valid @RequestBody CreateReq req) {
        var locked = workOrderMapper.lockScheduleOrders(List.of(req.getWorkOrderId()));
        if (locked.isEmpty() || !java.util.Objects.equals(locked.get(0).getStatus(), cn.iocoder.yudao.module.mes.enums.pro.MesProWorkOrderStatusEnum.FINISHED.getStatus()))
            throw new ServiceException(400, "仅已完成的生产订单可以登记废料");
        if (receiptMapper.selectOrderOutputs(req.getWorkOrderId(), cn.iocoder.yudao.module.mes.enums.wm.MesWmProductProduceStatusEnum.FINISHED.getStatus()).stream()
                .noneMatch(item -> java.util.Objects.equals(item.getItemId(), req.getItemId())
                        && java.util.Objects.equals(item.getBatchId(), req.getBatchId())
                        && java.util.Objects.equals(cn.hutool.core.util.StrUtil.blankToDefault(item.getBatchCode(), ""),
                                cn.hutool.core.util.StrUtil.blankToDefault(req.getBatchCode(), ""))))
            throw new ServiceException(400, "所选物料不是该订单的已完成产出");
        var warehouse = warehouseService.validateWarehouseExists(req.getWarehouseId());
        if (!java.util.Objects.equals("废料仓", warehouse.getWarehouseType()) && !java.util.Objects.equals("废料", warehouse.getWarehouseType()))
            throw new ServiceException(400, "请选择仓库类型为废料仓的仓库");
        return create(req);
    }
 
    @Data
    public static class OutputItem {
        private Long itemId;
        private String itemCode;
        private String itemName;
        private Long batchId;
        private String batchCode;
        private BigDecimal quantity;
    }
 
    @PostMapping("/create")
    @PreAuthorize("@ss.hasPermission('mes:wm-scrap-receipt:create')")
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<Long> create(@Valid @RequestBody CreateReq req) {
        var order = workOrderMapper.selectById(req.getWorkOrderId());
        if (order == null) throw new ServiceException(400, "生产工单不存在");
        areaService.validateWarehouseAreaExists(req.getWarehouseId(), req.getLocationId(), req.getAreaId());
        String code = "SCR-" + req.getRequestId();
        if (receiptMapper.selectByCode(code) != null) throw new ServiceException(400, "请求已提交,请刷新入库记录");
        MesWmScrapReceiptDO receipt = new MesWmScrapReceiptDO();
        receipt.setCode(code);
        receipt.setWorkOrderId(order.getId());
        receipt.setWorkOrderCode(order.getCode());
        receipt.setItemId(req.getItemId());
        receipt.setQuantity(req.getQuantity());
        receipt.setWarehouseId(req.getWarehouseId());
        receipt.setLocationId(req.getLocationId());
        receipt.setAreaId(req.getAreaId());
        receipt.setBatchId(req.getBatchId());
        receipt.setBatchCode(req.getBatchCode());
        receipt.setReceiptTime(LocalDateTime.now());
        receipt.setRemark(req.getRemark());
        receiptMapper.insert(receipt);
        Long transactionId = transactionService.createTransaction(new MesWmTransactionSaveReqDTO()
                .setType(MesWmTransactionTypeEnum.IN.getType()).setBizType(cn.iocoder.yudao.module.mes.enums.MesBizTypeConstants.WM_SCRAP_RECEIPT)
                .setBizId(receipt.getId()).setBizLineId(receipt.getId()).setBizCode(receipt.getCode())
                .setItemId(receipt.getItemId()).setQuantity(receipt.getQuantity())
                .setWarehouseId(receipt.getWarehouseId()).setLocationId(receipt.getLocationId())
                .setAreaId(receipt.getAreaId()).setBatchId(receipt.getBatchId()).setBatchCode(receipt.getBatchCode())
                .setReceiptTime(receipt.getReceiptTime()).setForceCreateNewStock(true));
        receipt.setTransactionId(transactionId);
        receiptMapper.updateById(receipt);
        return success(receipt.getId());
    }
 
    @GetMapping("/monthly-summary")
    @PreAuthorize("@ss.hasPermission('mes:wm-scrap-receipt:query')")
    public CommonResult<List<Map<String, Object>>> monthlySummary(@RequestParam String month) {
        YearMonth period = YearMonth.parse(month);
        return success(receiptMapper.summarize(period.atDay(1).atStartOfDay(),
                period.plusMonths(1).atDay(1).atStartOfDay()));
    }
 
    @GetMapping("/page")
    @PreAuthorize("@ss.hasPermission('mes:wm-scrap-receipt:query')")
    public CommonResult<PageResult<MesWmScrapReceiptDO>> page(@Valid PageParam page,
                                                              @RequestParam(required = false) Long workOrderId) {
        return success(receiptMapper.selectReceiptPage(page, workOrderId));
    }
 
    @Data
    public static class CreateReq {
        @NotBlank @Pattern(regexp = "[A-Za-z0-9-]{1,60}") private String requestId;
        @NotNull private Long workOrderId;
        @NotNull private Long itemId;
        @NotNull @DecimalMin(value = "0", inclusive = false) @Digits(integer = 16, fraction = 4) private BigDecimal quantity;
        @NotNull private Long warehouseId;
        @NotNull private Long locationId;
        @NotNull private Long areaId;
        private Long batchId;
        @Size(max = 100) private String batchCode;
        @Size(max = 500) private String remark;
    }
}