1
昨天 a422cb5b73799050827251f835ebc53d5757a96b
rsf-server/src/main/java/com/vincent/rsf/server/api/controller/erp/params/SyncOrderParams.java
@@ -1,12 +1,16 @@
package com.vincent.rsf.server.api.controller.erp.params;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.vincent.rsf.framework.common.Cools;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.Valid;
import javax.validation.constraints.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
@@ -18,22 +22,274 @@
    private static final long serialVersionUID = 1L;
    @ApiModelProperty("业务类型")
    /**
     * 业务类型枚举
     */
    public interface BusinessType {
        // 入库单据
        String PUR_RECEIVE_BILL = "PUR_ReceiveBill";        // 收料通知单
        String STK_IN_STOCK = "STK_InStock";                // 采购入库单
        String PUR_MRAPP = "PUR_MRAPP";                     // 退料申请单
        String PUR_MRB = "PUR_MRB";                         // 采购退料单
        String SAL_RETURNNOTICE = "SAL_RETURNNOTICE";      // 退货通知单
        String SAL_RETURNSTOCK = "SAL_RETURNSTOCK";        // 销售退货单
        String PRD_RETURN_MTRL = "PRD_ReturnMtrl";         // 生产退料单 //接驳
        String PRD_INSTOCK = "PRD_INSTOCK";                // 生产入库单 //接驳
        String PRD_MORPT = "PRD_MORPT";                    // 生产汇报单
        String STK_MISCELLANEOUS = "STK_MISCELLANEOUS";    // 其他入库单
        // 出库单据
        String SAL_DELIVERYNOTICE = "SAL_DELIVERYNOTICE";  // 发货通知单
        String SAL_OUTSTOCK = "SAL_OUTSTOCK";              // 销售出库单
        String STK_OUTSTOCK_APPLY = "STK_OutStockApply";   // 出库申请单
        String PRD_PICK_MTRL = "PRD_PickMtrl";             // 生产领料单 //接驳
        String PRD_FEED_MTRL = "PRD_FeedMtrl";             // 生产补料单 //接驳
        String STK_MIS_DELIVERY = "STK_MisDelivery";       // 其他出库单
        // 调拨单据
        String STK_TRANSFER_APPLY = "STK_TRANSFERAPPLY";   // 调拨申请单
        String STK_TRANSFER_DIRECT = "STK_TransferDirect"; // 直接调拨单
    }
    /**
     * 单据类型枚举
     */
    public interface OrderType {
        String OUT_STOCK = "1";    // 出库单
        String IN_STOCK = "2";     // 入库单
        String TRANSFER = "3";     // 调拨单
    }
    @NotBlank(message = "业务类型不能为空")
    @Pattern(regexp = "^(PUR_ReceiveBill|STK_InStock|PUR_MRAPP|PUR_MRB|SAL_RETURNNOTICE|SAL_RETURNSTOCK|"
            + "PRD_ReturnMtrl|PRD_INSTOCK|PRD_MORPT|STK_MISCELLANEOUS|SAL_DELIVERYNOTICE|SAL_OUTSTOCK|"
            + "STK_OutStockApply|PRD_PickMtrl|PRD_FeedMtrl|STK_MisDelivery|STK_TRANSFERAPPLY|STK_TransferDirect)$",
            message = "业务类型格式不正确")
    @ApiModelProperty(value = "业务类型", required = true, example = "STK_InStock")
    private String wkType;
    @ApiModelProperty("单号")
    @NotBlank(message = "单据类型不能为空")
    @Pattern(regexp = "^[123]$", message = "单据类型只能是1(出库单)、2(入库单)或3(调拨单)")
    @ApiModelProperty(value = "单据类型: 1-出库单, 2-入库单, 3-调拨单", required = true, example = "2")
    private String type;
    @NotBlank(message = "单号不能为空")
    @Size(max = 50, message = "单号长度不能超过50个字符")
    @ApiModelProperty(value = "单号", required = true, example = "PO202401010001")
    private String orderNo;
    @ApiModelProperty("订单ID")
    @NotNull(message = "单据内码不能为空")
    @Positive(message = "单据内码必须是正整数")
    @ApiModelProperty(value = "单据内码,唯一标识", required = true, example = "100001")
    private Long orderInternalCode;
//    @NotNull(message = "订单ID不能为空")
//    @Positive(message = "订单ID必须是正整数")
//    @ApiModelProperty(value = "订单ID", required = true, example = "200001")
    private Long orderId;
    @ApiModelProperty("数量")
//    @NotNull(message = "数量不能为空")
//    @DecimalMin(value = "0.0", inclusive = false, message = "数量必须大于0")
//    @ApiModelProperty(value = "数量", required = true, example = "100.5")
    private Double anfme;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:ss:mm")
    @JsonFormat(pattern = "yyyy-MM-dd HH:ss:mm")
    @ApiModelProperty(value = "客户编码", example = "CUST001")
    private String customerId;
    @ApiModelProperty(value = "客户名称", example = "XX科技有限公司")
    private String customerName;
    @ApiModelProperty(value = "供应商编码", example = "SUP001")
    private String supplierId;
    @ApiModelProperty(value = "供应商名称", example = "XX供应商")
    private String supplierName;
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @ApiModelProperty(value = "到达时间", example = "2024-01-01 10:00:00")
    private Date arrTime;
    @ApiModelProperty("单据明细信息")
    private List<SyncOrdersItem> ordersItems;
}
    @NotNull(message = "创建日期不能为空")
    @Positive(message = "创建日期必须是正整数")
    @ApiModelProperty(value = "创建日期,时间戳,精确到秒", required = true, example = "1704067200")
    private Long createTime;
    @NotNull(message = "业务日期不能为空")
    @Positive(message = "业务日期必须是正整数")
    @ApiModelProperty(value = "业务日期,对账使用,时间戳,精确到秒", required = true, example = "1704067200")
    private Long businessTime;
    @Valid
    @NotNull(message = "单据明细信息不能为空")
    @Size(min = 1, message = "至少需要一个明细项")
    @ApiModelProperty(value = "单据明细信息", required = true)
    private List<SyncOrdersItem> orderItems;
    @ApiModelProperty(value = "收料/发货组织", example = "ORG001")
    private String stockOrgId;
    @ApiModelProperty(value = "收料/发货组织名称", example = "发货部")
    private String stockOrgName;
    @ApiModelProperty(value = "采购组织", example = "PUR001")
    private String purchaseOrgId;
    @ApiModelProperty(value = "采购组织名称", example = "采购部")
    private String purchaseOrgName;
    @ApiModelProperty(value = "采购员", example = "USER001")
    private String purchaseUserId;
    @ApiModelProperty(value = "采购员名称", example = "张三")
    private String purchaseUserName;
    @ApiModelProperty(value = "生产组织", example = "PRD001")
    private String prdOrgId;
    @ApiModelProperty(value = "生产组织名称", example = "生产部")
    private String prdOrgName;
    @ApiModelProperty(value = "销售组织", example = "SALE001")
    private String saleOrgId;
    @ApiModelProperty(value = "销售组织名称", example = "销售部")
    private String saleOrgName;
    @ApiModelProperty(value = "销售员", example = "USER002")
    private String saleUserId;
    @ApiModelProperty(value = "销售员名称", example = "李四")
    private String saleUserName;
    @ApiModelProperty(value = "库存方向", example = "IN")
    private String stockDirect;
    @ApiModelProperty(value = "出入库接驳站点,出库时将物料出库后运输至该站点,入库时从该站点将物料运回库中", example = "STATION001")
    private String stationId;
    /**
     * 获取实际到达时间
     * 优先使用 arrTime,如果为空则从 createTime 转换
     */
    @JsonIgnore
    public Date getActualArrTime() {
        if (this.arrTime != null) {
            return this.arrTime;
        }
        if (this.createTime != null) {
            return new Date(this.createTime * 1000L);
        }
        return null;
    }
    /**
     * 获取实际业务时间
     */
    @JsonIgnore
    public Date getActualBusinessTime() {
        if (this.businessTime != null) {
            return new Date(this.businessTime * 1000L);
        }
        return null;
    }
    /**
     * 获取实际创建时间
     */
    @JsonIgnore
    public Date getActualCreateTime() {
        if (this.createTime != null) {
            return new Date(this.createTime * 1000L);
        }
        return null;
    }
    /**
     * 是否入库单
     */
    @JsonIgnore
    public boolean isInStockOrder() {
        return OrderType.IN_STOCK.equals(this.type);
    }
    /**
     * 是否出库单
     */
    @JsonIgnore
    public boolean isOutStockOrder() {
        return OrderType.OUT_STOCK.equals(this.type);
    }
    /**
     * 是否调拨单
     */
    @JsonIgnore
    public boolean isTransferOrder() {
        return OrderType.TRANSFER.equals(this.type);
    }
    /**
     * 业务验证
     */
    public void validateBusiness() {
//        if (isOutStockOrder() && Cools.isEmpty(customerId)) {
//            throw new IllegalArgumentException("出库单必须指定客户");
//        }
//
//        if (isInStockOrder() && Cools.isEmpty(supplierId)) {
//            throw new IllegalArgumentException("入库单必须指定供应商");
//        }
//        if (Cools.isEmpty(stationId) && !isTransferOrder()) {
//            throw new IllegalArgumentException("必须指定接驳站点");
//        }
        // 验证明细总数与主单数量是否一致
//        if (orderItems != null && anfme != null) {
//            double itemsTotal = orderItems.stream()
//                    .mapToDouble(item -> item.getAnfme() != null ? item.getAnfme() : 0.0)
//                    .sum();
//
//            if (Math.abs(itemsTotal - anfme) > 0.001) {
//                throw new IllegalArgumentException(String.format(
//                        "主单数量(%.3f)与明细总数(%.3f)不一致", anfme, itemsTotal));
//            }
//        }
    }
    /**
     * 计算明细总数量
     */
    @JsonIgnore
    public Double calculateItemsTotal() {
        if (orderItems == null || orderItems.isEmpty()) {
            return 0.0;
        }
        return orderItems.stream()
                .mapToDouble(item -> item.getAnfme() != null ? item.getAnfme() : 0.0)
                .sum();
    }
    /**
     * 获取单据摘要
     */
    @JsonIgnore
    public String getSummary() {
        return String.format("单据[%s] 类型[%s] 业务类型[%s] 单据内码[%s]",
                orderNo, type, wkType, orderInternalCode);
    }
    /**
     * 是否有效单据
     */
    @JsonIgnore
    public boolean isValid() {
        return !Cools.isEmpty(orderNo) &&
                orderInternalCode != null && !Cools.isEmpty(orderInternalCode) &&
                type != null && !Cools.isEmpty(type) &&
                wkType != null && !Cools.isEmpty(wkType) &&
                createTime != null && !Cools.isEmpty(createTime) &&
                businessTime != null && !Cools.isEmpty(businessTime) &&
                orderItems != null && !orderItems.isEmpty();
    }
}