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;
|
|
@Data
|
@Accessors(chain = true)
|
@ApiModel(value = "SyncOrderParams", description = "单据同步参数")
|
public class SyncOrderParams implements Serializable {
|
|
private static final long serialVersionUID = 1L;
|
|
/**
|
* 业务类型枚举
|
*/
|
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;
|
|
@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;
|
|
@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;
|
|
// @NotNull(message = "数量不能为空")
|
// @DecimalMin(value = "0.0", inclusive = false, message = "数量必须大于0")
|
// @ApiModelProperty(value = "数量", required = true, example = "100.5")
|
private Double anfme;
|
|
@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;
|
|
@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();
|
}
|
}
|