feat(oms): 新增出仓委托单,支持新增/编辑/审核/下发WMS/完成入库

- 订单状态五态:1待审核(新增默认,驳回单编辑后自动回此态) 2已审核(下发后保持,用下发状态区分) 3已驳回 4进行中(预留) 5已入库
- 下发走WMS出库通知单链路(stockOutOrInInsert),返回强校验防吞错;完成入库限已审核+已下发
- 订单类型未传默认普通出库;明细新增单价unitPrice;列表支持invoiceNo/settlementCurrency查询,时间参数只传年月日
- 必填:客户/业务员/仓库/商品名称/申报数量;编辑删除限待审核/已驳回且未下发
- 附达梦建表脚本oms_out_entrust_order(主表+明细表,最终版)
This commit is contained in:
rcx
2026-09-04 10:47:29 +08:00
parent 0eb47793a8
commit 7d3c229b9a
21 changed files with 2823 additions and 0 deletions
@@ -0,0 +1,390 @@
package com.mhd.oms.application.service.outEntrustOrder;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.oms.constant.OutEntrustOrderConstant;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderDetailPO;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
import com.mhd.oms.domain.outEntrustOrder.service.OutEntrustOrderDomainService;
import com.mhd.system.api.SystemServiceFeign;
import com.mhd.system.api.WmsServiceFeign;
import com.mhd.system.api.domain.NoticeMaterialDetailDTO;
import com.mhd.system.api.domain.NoticeOrderDTO;
import com.mhd.system.api.domain.WarehouseFeignPO;
import com.mhd.system.api.model.LoginUser;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
/**
* 出仓委托单ApplicationService
*
* @author rcx
* @date 2026-09-02
*/
@Service
@Slf4j
public class OutEntrustOrderApplicationService {
@Resource
private OutEntrustOrderDomainService outEntrustOrderDomainService;
@Resource
private SystemServiceFeign systemServiceFeign;
@Resource
private WmsServiceFeign wmsServiceFeign;
/**
* 分页查询出仓委托单列表(不做默认状态过滤,显示全部数据)
*/
public List<OutEntrustOrderPO> queryList(OutEntrustOrderDO outEntrustOrderDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null) {
Long topOrganizationId = loginUser.getUserPo().getTopOrganizationId();
if (topOrganizationId != null && topOrganizationId != 1) {
outEntrustOrderDO.setTopOrganizationId(topOrganizationId);
}
}
//结束时间只传年月日(解析为当天00:00:00),归一为当天最后一秒,保证查询包含结束日当天
if (outEntrustOrderDO.getEndCreateTime() != null) {
outEntrustOrderDO.setEndCreateTime(DateUtil.endOfDay(outEntrustOrderDO.getEndCreateTime()));
}
List<OutEntrustOrderPO> orderList = outEntrustOrderDomainService.queryList(outEntrustOrderDO);
fillInvoiceNo(orderList);
return orderList;
}
/**
* 列表回填发票号(明细发票号去重逗号拼接,供列表列展示)
*/
private void fillInvoiceNo(List<OutEntrustOrderPO> orderList) {
if (orderList == null || orderList.isEmpty()) {
return;
}
List<String> entrustNumbers = orderList.stream()
.map(OutEntrustOrderPO::getEntrustNumber).collect(Collectors.toList());
Map<String, String> invoiceNoMap = outEntrustOrderDomainService.getDetailByEntrustNumbers(entrustNumbers).stream()
.filter(detail -> detail.getInvoiceNo() != null && !detail.getInvoiceNo().trim().isEmpty())
.collect(Collectors.toMap(OutEntrustOrderDetailPO::getEntrustNumber, detail -> detail.getInvoiceNo().trim(),
(existing, replacement) -> existing.contains(replacement) ? existing
: existing + "," + replacement));
for (OutEntrustOrderPO order : orderList) {
order.setInvoiceNo(invoiceNoMap.get(order.getEntrustNumber()));
}
}
/**
* 新增出仓委托单(必填:客户、业务员、仓库、商品名称、申报数量)
*/
public Boolean insert(OutEntrustOrderDO outEntrustOrderDO) {
//必填项校验
validateRequired(outEntrustOrderDO);
//订单类型未维护时默认普通出库(落库即生效,列表可见)
setDefaultOrderType(outEntrustOrderDO);
//仓库信息回填(校验仓库存在)
setWarehouseInfo(outEntrustOrderDO);
//组织信息填充
setOrganizationInfo(outEntrustOrderDO);
//汇总申报总数量
outEntrustOrderDO.setDeclareTotalQuantity(sumDeclareQuantity(outEntrustOrderDO.getMaterialDetailList()));
return outEntrustOrderDomainService.insert(outEntrustOrderDO);
}
/**
* 修改出仓委托单(仅待审核/已驳回且未下发可修改;已驳回单编辑后状态重置为待审核)
*/
public Boolean update(OutEntrustOrderDO outEntrustOrderDO) {
//必填项校验
validateRequired(outEntrustOrderDO);
//状态类字段由审核/下发/完成入库接口推进,编辑不允许改动(置null后updateById跳过这些列,防前端误传/绕过审核改状态)
outEntrustOrderDO.setOrderStatus(null);
outEntrustOrderDO.setIssueStatus(null);
outEntrustOrderDO.setAuditRemark(null);
//订单类型未维护时默认普通出库(落库即生效,列表可见)
setDefaultOrderType(outEntrustOrderDO);
//仓库信息回填(校验仓库存在)
setWarehouseInfo(outEntrustOrderDO);
//明细全量替换时明细创建信息随主单更新人
if (outEntrustOrderDO.getCreateBy() == null) {
outEntrustOrderDO.setCreateBy(outEntrustOrderDO.getUpdateBy());
outEntrustOrderDO.setCreateByName(outEntrustOrderDO.getUpdateByName());
outEntrustOrderDO.setCreateTime(outEntrustOrderDO.getUpdateTime());
}
//汇总申报总数量
outEntrustOrderDO.setDeclareTotalQuantity(sumDeclareQuantity(outEntrustOrderDO.getMaterialDetailList()));
return outEntrustOrderDomainService.update(outEntrustOrderDO);
}
/**
* 订单类型未维护时默认普通出库(与下发兜底保持一致,保存即落库)
*/
private void setDefaultOrderType(OutEntrustOrderDO outEntrustOrderDO) {
if (outEntrustOrderDO.getOrderTypeCode() == null || outEntrustOrderDO.getOrderTypeCode().trim().isEmpty()) {
outEntrustOrderDO.setOrderTypeCode(OutEntrustOrderConstant.WMS_ORDER_TYPE_CODE);
outEntrustOrderDO.setOrderTypeName(OutEntrustOrderConstant.WMS_ORDER_TYPE_NAME);
}
}
/**
* 获取出仓委托单详情(含明细)
*/
public OutEntrustOrderPO getInfo(Long id) {
return outEntrustOrderDomainService.getInfo(id);
}
/**
* 批量删除出仓委托单(仅待审核/已驳回且未下发可删除)
*/
public Boolean delete(Long[] ids) {
if (ids == null || ids.length == 0) {
throw new ServiceException("传递的ID值缺失或为空");
}
return outEntrustOrderDomainService.delete(ids);
}
/**
* 批量审核:待审核/已驳回 → 已审核(2)或已驳回(3)
*
* @param dto.idList 委托单ID集合
* @param dto.orderStatus 审核结果:2-审核通过 3-驳回
* @param dto.auditRemark 审核备注(驳回原因,选填)
*/
public Boolean audit(OutEntrustOrderDO outEntrustOrderDO) {
List<Long> ids = outEntrustOrderDO.getIdList();
if (ids == null || ids.isEmpty()) {
throw new ServiceException("传递的ID值缺失或为空");
}
Integer targetStatus = outEntrustOrderDO.getOrderStatus();
if (!OutEntrustOrderConstant.ORDER_STATUS_AUDITED.equals(targetStatus)
&& !OutEntrustOrderConstant.ORDER_STATUS_REJECTED.equals(targetStatus)) {
throw new ServiceException("审核结果参数错误,只能为已审核或已驳回");
}
//只有待审核/已驳回的委托单才可以审核
List<OutEntrustOrderPO> orderList = outEntrustOrderDomainService.queryByIds(ids);
List<Long> unableAuditIds = orderList.stream()
.filter(order -> !OutEntrustOrderConstant.ORDER_STATUS_PENDING_AUDIT.equals(order.getOrderStatus())
&& !OutEntrustOrderConstant.ORDER_STATUS_REJECTED.equals(order.getOrderStatus()))
.map(OutEntrustOrderPO::getId).collect(Collectors.toList());
if (!unableAuditIds.isEmpty()) {
throw new ServiceException("选中数据中存在进行中/已审核/已入库的委托单,只有待审核或已驳回的委托单方可审核");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
Long auditBy = loginUser == null ? null : loginUser.getUserid();
String auditByName = loginUser == null ? null : loginUser.getUsername();
return outEntrustOrderDomainService.audit(ids, targetStatus, auditBy, auditByName, outEntrustOrderDO.getAuditRemark());
}
/**
* 批量下发:已审核的委托单下发到WMS(生成出库通知单),下发后订单状态保持已审核,仅置下发状态为已下发
*/
@Transactional(rollbackFor = Exception.class)
public Boolean issueOrder(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
throw new ServiceException("传递的ID值缺失或为空");
}
//只有已审核且未下发的委托单才可以下发
List<OutEntrustOrderPO> orderList = outEntrustOrderDomainService.queryByIds(ids);
for (OutEntrustOrderPO order : orderList) {
if (!OutEntrustOrderConstant.ORDER_STATUS_AUDITED.equals(order.getOrderStatus())) {
throw new ServiceException(String.format("委托单[%s]未审核,已审核的委托单方可下发", order.getEntrustNumber()));
}
if (!OutEntrustOrderConstant.ISSUE_STATUS_1.equals(order.getIssueStatus())) {
throw new ServiceException(String.format("委托单[%s]已下发,不允许重复下发", order.getEntrustNumber()));
}
}
LoginUser loginUser = SecurityUtils.getLoginUser();
Long issueBy = loginUser == null ? null : loginUser.getUserid();
String issueByName = loginUser == null ? null : loginUser.getUsername();
for (OutEntrustOrderPO order : orderList) {
//组装出库通知单
NoticeOrderDTO noticeOrderDTO = createNoticeOrderInfo(order);
//推送给WMS
AjaxResult ajaxResult = wmsServiceFeign.stockOutOrInInsert(noticeOrderDTO);
//WMS返回成功才允许置为已下发,避免下发失败被静默吞掉
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
String errorMsg = ajaxResult == null ? "WMS服务调用失败" : String.valueOf(ajaxResult.get("msg"));
log.error("出仓委托单[{}]下发WMS失败:{}", order.getEntrustNumber(), errorMsg);
throw new ServiceException(String.format("委托单[%s]下发WMS失败:%s", order.getEntrustNumber(), errorMsg));
}
log.info("出仓委托单[{}]下发WMS成功", order.getEntrustNumber());
}
return outEntrustOrderDomainService.issue(ids, issueBy, issueByName);
}
/**
* 批量完成:已审核(已下发) → 已入库(OMS人工推进,WMS出库完成后由人工确认)
*/
public Boolean finish(List<Long> ids) {
if (ids == null || ids.isEmpty()) {
throw new ServiceException("传递的ID值缺失或为空");
}
//只有已审核且已下发的委托单才可以置为已入库(兼容存量:旧版本曾自动置为进行中的也允许)
List<OutEntrustOrderPO> orderList = outEntrustOrderDomainService.queryByIds(ids);
List<Long> unableFinishIds = orderList.stream()
.filter(order -> !(OutEntrustOrderConstant.ORDER_STATUS_IN_PROGRESS.equals(order.getOrderStatus())
|| (OutEntrustOrderConstant.ORDER_STATUS_AUDITED.equals(order.getOrderStatus())
&& OutEntrustOrderConstant.ISSUE_STATUS_2.equals(order.getIssueStatus()))))
.map(OutEntrustOrderPO::getId).collect(Collectors.toList());
if (!unableFinishIds.isEmpty()) {
throw new ServiceException("选中数据中存在待审核/已驳回或未下发的委托单,只有已审核且已下发的委托单方可置为已入库");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
Long updateBy = loginUser == null ? null : loginUser.getUserid();
String updateByName = loginUser == null ? null : loginUser.getUsername();
return outEntrustOrderDomainService.finish(ids, updateBy, updateByName);
}
/**
* 组装出库通知单信息(客户=货主)
*/
private NoticeOrderDTO createNoticeOrderInfo(OutEntrustOrderPO order) {
NoticeOrderDTO noticeOrderDTO = new NoticeOrderDTO();
noticeOrderDTO.setType(OutEntrustOrderConstant.NOTICE_TYPE_OUT);
//客户订单号记录委托单号,便于WMS侧追溯
noticeOrderDTO.setCustomerOrderNumber(order.getEntrustNumber());
noticeOrderDTO.setWarehouseId(order.getWarehouseId());
//出仓委托单的客户即WMS货主,货主为物料档案/库存作业的归属
noticeOrderDTO.setShipperId(order.getShipperId());
noticeOrderDTO.setShipperName(order.getShipperName());
noticeOrderDTO.setCustomerId(order.getShipperId());
noticeOrderDTO.setCustomerName(order.getShipperName());
//订单类型:未维护时默认普通出库(WMS侧按出库单据类型字典翻译)
noticeOrderDTO.setOrderTypeCode(order.getOrderTypeCode() == null
? OutEntrustOrderConstant.WMS_ORDER_TYPE_CODE : order.getOrderTypeCode());
noticeOrderDTO.setOrderTypeName(order.getOrderTypeName());
noticeOrderDTO.setExpectTime(order.getExpectTime() == null ? new Date() : order.getExpectTime());
noticeOrderDTO.setNullify(2);
//出库通知单仅有限几个业务字段:业务员及委托/报关关键信息拼入备注留存(超长截断)
noticeOrderDTO.setRemark(buildNoticeRemark(order));
//物料明细:申报数量作为通知单计划数量
List<OutEntrustOrderDetailPO> detailList = outEntrustOrderDomainService.getDetailByEntrustNumber(order.getEntrustNumber());
if (detailList == null || detailList.isEmpty()) {
throw new ServiceException(String.format("委托单[%s]缺少商品明细,无法下发", order.getEntrustNumber()));
}
List<NoticeMaterialDetailDTO> materialDetailList = new ArrayList<>();
for (OutEntrustOrderDetailPO detail : detailList) {
NoticeMaterialDetailDTO materialDetail = new NoticeMaterialDetailDTO();
materialDetail.setMaterialBaseInfoId(detail.getMaterialBaseInfoId());
materialDetail.setMaterialCode(detail.getMaterialCode());
//物料名称:档案名优先,无档案时用委托单品名
materialDetail.setMaterialName(detail.getMaterialName() != null && !detail.getMaterialName().trim().isEmpty()
? detail.getMaterialName() : detail.getCommodityName());
materialDetail.setBarCode(detail.getBarCode());
materialDetail.setQuantity(detail.getDeclareQuantity());
materialDetailList.add(materialDetail);
}
noticeOrderDTO.setMaterialDetailList(materialDetailList);
return noticeOrderDTO;
}
/**
* 出库通知单备注:拼入业务员及委托/报关关键信息(通知单无对应字段)
*/
private String buildNoticeRemark(OutEntrustOrderPO order) {
StringBuilder remark = new StringBuilder();
if (order.getRemark() != null && !order.getRemark().trim().isEmpty()) {
remark.append(order.getRemark().trim());
}
appendIfPresent(remark, "业务员", order.getSalesmanName());
appendIfPresent(remark, "委托编号", order.getEntrustNo());
appendIfPresent(remark, "柜号", order.getContainerNo());
appendIfPresent(remark, "承运商", order.getCarrierName() != null ? order.getCarrierName() : order.getCarrier());
appendIfPresent(remark, "To", order.getToReceiver());
appendIfPresent(remark, "联系人", order.getContactPerson());
appendIfPresent(remark, "电话", order.getTel());
appendIfPresent(remark, "申报地关区", order.getDeclareCustoms());
appendIfPresent(remark, "进出境关别", order.getEntryExitCustoms());
//备注列长度保护
return remark.length() > 480 ? remark.substring(0, 480) : remark.toString();
}
private void appendIfPresent(StringBuilder remark, String label, String value) {
if (value != null && !value.trim().isEmpty()) {
remark.append(remark.length() > 0 ? "" : "").append(label).append("").append(value.trim());
}
}
/**
* 必填项校验:客户、业务员、仓库、商品名称、申报数量,其余字段不强制
*/
private void validateRequired(OutEntrustOrderDO outEntrustOrderDO) {
if (outEntrustOrderDO.getShipperId() == null) {
throw new ServiceException("客户不能为空");
}
if (outEntrustOrderDO.getSalesmanId() == null || outEntrustOrderDO.getSalesmanId().trim().isEmpty()) {
throw new ServiceException("业务员不能为空");
}
if (outEntrustOrderDO.getWarehouseId() == null) {
throw new ServiceException("仓库不能为空");
}
if (outEntrustOrderDO.getMaterialDetailList() == null || outEntrustOrderDO.getMaterialDetailList().isEmpty()) {
throw new ServiceException("商品明细不能为空");
}
int index = 1;
for (OutEntrustOrderDetailDO detail : outEntrustOrderDO.getMaterialDetailList()) {
//商品名称:物料档案名/委托单品名至少其一
boolean nameBlank = (detail.getMaterialName() == null || detail.getMaterialName().trim().isEmpty())
&& (detail.getCommodityName() == null || detail.getCommodityName().trim().isEmpty());
if (nameBlank) {
throw new ServiceException(String.format("商品明细第%d行商品名称不能为空", index));
}
if (detail.getDeclareQuantity() == null || detail.getDeclareQuantity().compareTo(BigDecimal.ZERO) <= 0) {
throw new ServiceException(String.format("商品明细第%d行申报数量必须大于0", index));
}
index++;
}
}
/**
* 仓库信息校验并回填编码/名称
*/
private void setWarehouseInfo(OutEntrustOrderDO outEntrustOrderDO) {
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(outEntrustOrderDO.getWarehouseId());
if (ajaxResult == null || !"200".equals(String.valueOf(ajaxResult.get("code")))) {
throw new ServiceException("获取仓库信息失败,请检查仓库是否有效");
}
WarehouseFeignPO warehouseFeignPO = JSONUtil.toBean(JSONUtil.toJsonStr(ajaxResult.get("data")), WarehouseFeignPO.class);
if (warehouseFeignPO == null || Objects.isNull(warehouseFeignPO.getWarehouseId())) {
throw new ServiceException("仓库不存在,请重新选择");
}
outEntrustOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
outEntrustOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
}
/**
* 组织信息填充
*/
private void setOrganizationInfo(OutEntrustOrderDO outEntrustOrderDO) {
LoginUser loginUser = SecurityUtils.getLoginUser();
if (loginUser != null && loginUser.getUserPo() != null) {
outEntrustOrderDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
outEntrustOrderDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
outEntrustOrderDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
}
}
/**
* 汇总明细申报数量
*/
private BigDecimal sumDeclareQuantity(List<OutEntrustOrderDetailDO> detailList) {
return detailList.stream()
.map(OutEntrustOrderDetailDO::getDeclareQuantity)
.reduce(BigDecimal.ZERO, BigDecimal::add);
}
}
@@ -0,0 +1,37 @@
package com.mhd.oms.constant;
/**
* 出仓委托单常量
*
* @author rcx
* @date 2026-09-02
*/
public interface OutEntrustOrderConstant {
/** 出仓委托单号前缀 */
String OUT_ENTRUST_NO_PREFIX = "CKWT";
/** 订单状态:1-待审核(新增默认值;已驳回单重新编辑后也回到此状态) */
Integer ORDER_STATUS_PENDING_AUDIT = 1;
/** 订单状态:2-已审核 */
Integer ORDER_STATUS_AUDITED = 2;
/** 订单状态:3-已驳回 */
Integer ORDER_STATUS_REJECTED = 3;
/** 订单状态:4-进行中(已下发WMS) */
Integer ORDER_STATUS_IN_PROGRESS = 4;
/** 订单状态:5-已入库 */
Integer ORDER_STATUS_STORED = 5;
/** 下发状态:1-未下发 */
Integer ISSUE_STATUS_1 = 1;
/** 下发状态:2-已下发 */
Integer ISSUE_STATUS_2 = 2;
/** 下发WMS出库通知单-订单类型编码 */
String WMS_ORDER_TYPE_CODE = "pu_tong_chu_ku";
/** 下发WMS出库通知单-订单类型名称 */
String WMS_ORDER_TYPE_NAME = "普通出库";
/** 出库通知单类型(NoticeOrderDTO.type1-入库通知单 2-出库通知单) */
Integer NOTICE_TYPE_OUT = 2;
}
@@ -0,0 +1,204 @@
package com.mhd.oms.domain.outEntrustOrder.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.mhd.common.core.web.domain.BaseVOEntity;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* 出仓委托单对象 oms_out_entrust_order
* 表单字段对齐WMS出库管理新增(报关/委托信息块)
*
* @author rcx
* @date 2026-09-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("oms_out_entrust_order")
public class OutEntrustOrder extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
@TableId(type = IdType.AUTO)
private Long id;
@ApiModelProperty("委托单号")
private String entrustNumber;
@ApiModelProperty("出库仓库ID")
private Long warehouseId;
@ApiModelProperty("仓库编码")
private String warehouseCode;
@ApiModelProperty("仓库名称")
private String warehouseName;
@ApiModelProperty("客户ID(货主)")
private Long shipperId;
@ApiModelProperty("客户编码")
private String shipperCode;
@ApiModelProperty("客户名称")
private String shipperName;
@ApiModelProperty("业务员ID")
private String salesmanId;
@ApiModelProperty("业务员名称")
private String salesmanName;
@ApiModelProperty("订单类型编码(字典outDocumentType)")
private String orderTypeCode;
@ApiModelProperty("订单类型名称")
private String orderTypeName;
@ApiModelProperty("结算币种")
private String settlementCurrency;
@ApiModelProperty("优先级别编码")
private String priorityLevelCode;
@ApiModelProperty("优先级别名称")
private String priorityLevelName;
@ApiModelProperty("是否直接出库: 1-是 2-否")
private Integer directWarehouse;
@ApiModelProperty("是否复核: 1-是 2-否")
private Integer review;
@ApiModelProperty("预计出货时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expectTime;
@ApiModelProperty("出仓日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date outboundDate;
@ApiModelProperty("orderDate")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date orderDate;
@ApiModelProperty("完成时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date completeTime;
@ApiModelProperty("To(收货人)")
@TableField("to_receiver")
private String toReceiver;
@ApiModelProperty("联系人")
private String contactPerson;
@ApiModelProperty("车型及车牌")
private String vehicleModelPlate;
@ApiModelProperty("委托编号(客户委托单号)")
private String entrustNo;
@ApiModelProperty("Tel电话")
private String tel;
@ApiModelProperty("Fax传真")
private String fax;
@ApiModelProperty("司机签名")
private String driverSign;
@ApiModelProperty("承运商编码")
private String carrier;
@ApiModelProperty("承运商名称")
private String carrierName;
@ApiModelProperty("柜号")
private String containerNo;
@ApiModelProperty("")
private String containerNoName;
@ApiModelProperty("运输方式编码")
private String transportModeCode;
@ApiModelProperty("运输方式名称")
private String transportModeName;
@ApiModelProperty("监管方式编码")
private String supervisionModeCode;
@ApiModelProperty("监管方式名称")
private String supervisionModeName;
@ApiModelProperty("申报地关区")
private String declareCustoms;
@ApiModelProperty("进出境关别")
private String entryExitCustoms;
@ApiModelProperty("起运/运抵国(地区)")
private String departureArrivalCountry;
@ApiModelProperty("海关是否查验货物")
private String customsInspectionFlag;
@ApiModelProperty("是否需要报关(预留,页面隐藏)")
private String needDeclareFlag;
@ApiModelProperty("是否需要运输(预留,页面隐藏)")
private String needTransportFlag;
@ApiModelProperty("生产商")
private String manufacturer;
@ApiModelProperty("报关员姓名及联系方式")
private String customsDeclarerInfo;
@ApiModelProperty("送货地址")
private String deliveryAddr;
@ApiModelProperty("附件url")
private String annexUrl;
@ApiModelProperty("订单状态:1-待审核 2-已审核 3-已驳回 4-进行中 5-已入库")
private Integer orderStatus;
@ApiModelProperty("审核人ID")
private Long auditBy;
@ApiModelProperty("审核人姓名")
private String auditByName;
@ApiModelProperty("审核时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;
@ApiModelProperty("审核备注(驳回原因)")
private String auditRemark;
@ApiModelProperty("下发状态:1-未下发 2-已下发")
private Integer issueStatus;
@ApiModelProperty("下发人ID")
private Long issueBy;
@ApiModelProperty("下发人姓名")
private String issueByName;
@ApiModelProperty("下发时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date issueTime;
@ApiModelProperty("申报总数量(明细申报数量之和)")
private BigDecimal declareTotalQuantity;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("组织ID")
private Long organizationId;
@ApiModelProperty("组织名称")
private String organizationName;
@ApiModelProperty("一级组织ID")
private Long topOrganizationId;
}
@@ -0,0 +1,98 @@
package com.mhd.oms.domain.outEntrustOrder.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 出仓委托单明细对象 oms_out_entrust_order_detail
* 明细列对齐WMS出库管理新增(出仓委托单明细列)
*
* @author rcx
* @date 2026-09-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
@TableName("oms_out_entrust_order_detail")
public class OutEntrustOrderDetail extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
@TableId(type = IdType.AUTO)
private Long id;
@ApiModelProperty("委托单号(关联主表)")
private String entrustNumber;
@ApiModelProperty("物料基础信息ID")
private Long materialBaseInfoId;
@ApiModelProperty("商品编码")
private String materialCode;
@ApiModelProperty("商品名称(物料档案名)")
private String materialName;
@ApiModelProperty("商品条形码")
private String barCode;
@ApiModelProperty("商品名称(委托单品名)")
private String commodityName;
@ApiModelProperty("商品编号")
private String commodityNo;
@ApiModelProperty("料号")
private String materialNo;
@ApiModelProperty("规格型号")
private String specificationModel;
@ApiModelProperty("SKU码")
private String skucode;
@ApiModelProperty("发票号")
private String invoiceNo;
@ApiModelProperty("申报单位")
private String declareUnit;
@ApiModelProperty("申报数量")
private BigDecimal declareQuantity;
@ApiModelProperty("单价")
private BigDecimal unitPrice;
@ApiModelProperty("单位")
private String unit;
@ApiModelProperty("")
private String liter;
@ApiModelProperty("尺寸")
private String size;
@ApiModelProperty("箱数")
private BigDecimal caseCount;
@ApiModelProperty("件数")
private BigDecimal pieceCount;
@ApiModelProperty("出库数量")
private BigDecimal outboundQuantity;
@ApiModelProperty("总净重(千克)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(千克)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(立方米)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积")
private BigDecimal totalArea;
@ApiModelProperty("总金额")
private BigDecimal totalAmount;
@ApiModelProperty("币制")
private String currency;
@ApiModelProperty("批次")
private String batchRefNo;
@ApiModelProperty("单据参考号")
private String sheetRefNo;
@ApiModelProperty("原产国")
private String countryOfOrigin;
@ApiModelProperty("箱/托盘号")
private String boxPalletNo;
@ApiModelProperty("备注")
private String remark;
}
@@ -0,0 +1,42 @@
package com.mhd.oms.domain.outEntrustOrder.repository.facade;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mhd.oms.domain.outEntrustOrder.entity.OutEntrustOrderDetail;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderDetailPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
import java.util.List;
/**
* 出仓委托单明细Service接口
*
* @author rcx
* @date 2026-09-02
*/
public interface IOutEntrustOrderDetailService extends IService<OutEntrustOrderDetail> {
/**
* 根据委托单号查询有效明细
*/
List<OutEntrustOrderDetailPO> queryByEntrustNumber(String entrustNumber);
/**
* 根据委托单号集合查询有效明细
*/
List<OutEntrustOrderDetailPO> queryByEntrustNumbers(List<String> entrustNumbers);
/**
* 批量保存明细
*/
Boolean batchInsert(String entrustNumber, List<OutEntrustOrderDetailDO> detailDOList);
/**
* 根据委托单号逻辑删除明细
*/
Boolean deleteByEntrustNumber(String entrustNumber);
/**
* 根据委托单号集合逻辑删除明细
*/
Boolean deleteByEntrustNumbers(List<String> entrustNumbers);
}
@@ -0,0 +1,62 @@
package com.mhd.oms.domain.outEntrustOrder.repository.facade;
import com.baomidou.mybatisplus.extension.service.IService;
import com.mhd.oms.domain.outEntrustOrder.entity.OutEntrustOrder;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import java.util.List;
/**
* 出仓委托单Service接口
*
* @author rcx
* @date 2026-09-02
*/
public interface IOutEntrustOrderService extends IService<OutEntrustOrder> {
/**
* 分页查询出仓委托单列表
*/
List<OutEntrustOrderPO> queryList(OutEntrustOrderDO outEntrustOrderDO);
/**
* 新增出仓委托单
*/
Boolean insert(OutEntrustOrderDO outEntrustOrderDO);
/**
* 修改出仓委托单
*/
Boolean update(OutEntrustOrderDO outEntrustOrderDO);
/**
* 批量删除出仓委托单
*/
Boolean delete(Long[] ids);
/**
* 获取出仓委托单详情(含明细)
*/
OutEntrustOrderPO getInfo(Long id);
/**
* 根据编号集合查询出仓委托单列表
*/
List<OutEntrustOrderPO> getInfoByIds(List<Long> ids);
/**
* 审核:待审核/已驳回 → 已审核(2)或已驳回(3)
*/
Boolean audit(List<Long> ids, Integer targetStatus, Long auditBy, String auditByName, String auditRemark);
/**
* 下发:置为已下发,订单状态置为进行中
*/
Boolean issue(List<Long> ids, Long issueBy, String issueByName);
/**
* 完成:进行中 → 已入库
*/
Boolean finish(List<Long> ids, Long updateBy, String updateByName);
}
@@ -0,0 +1,14 @@
package com.mhd.oms.domain.outEntrustOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mhd.oms.domain.outEntrustOrder.entity.OutEntrustOrderDetail;
/**
* 出仓委托单明细Mapper接口
*
* @author rcx
* @date 2026-09-02
*/
public interface OutEntrustOrderDetailMapper extends BaseMapper<OutEntrustOrderDetail> {
}
@@ -0,0 +1,28 @@
package com.mhd.oms.domain.outEntrustOrder.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mhd.oms.domain.outEntrustOrder.entity.OutEntrustOrder;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 出仓委托单Mapper接口
*
* @author rcx
* @date 2026-09-02
*/
public interface OutEntrustOrderMapper extends BaseMapper<OutEntrustOrder> {
/**
* 查询出仓委托单列表
*/
List<OutEntrustOrderPO> queryList(OutEntrustOrderDO outEntrustOrderDO);
/**
* 根据编号集合查询出仓委托单列表
*/
List<OutEntrustOrderPO> getInfoByIds(@Param("idList") List<Long> idList);
}
@@ -0,0 +1,97 @@
package com.mhd.oms.domain.outEntrustOrder.repository.persistence;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mhd.oms.domain.outEntrustOrder.entity.OutEntrustOrderDetail;
import com.mhd.oms.domain.outEntrustOrder.repository.facade.IOutEntrustOrderDetailService;
import com.mhd.oms.domain.outEntrustOrder.repository.mapper.OutEntrustOrderDetailMapper;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderDetailPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.stream.Collectors;
/**
* 出仓委托单明细Service业务层处理
*
* @author rcx
* @date 2026-09-02
*/
@Service
public class OutEntrustOrderDetailImpl extends ServiceImpl<OutEntrustOrderDetailMapper, OutEntrustOrderDetail> implements IOutEntrustOrderDetailService {
/**
* 根据委托单号查询有效明细
*/
@Override
public List<OutEntrustOrderDetailPO> queryByEntrustNumber(String entrustNumber) {
List<OutEntrustOrderDetail> detailList = this.list(new LambdaQueryWrapper<OutEntrustOrderDetail>()
.eq(OutEntrustOrderDetail::getEntrustNumber, entrustNumber)
.eq(OutEntrustOrderDetail::getDelFlag, 1)
.orderByAsc(OutEntrustOrderDetail::getId));
return detailList.stream().map(detail -> {
OutEntrustOrderDetailPO detailPO = new OutEntrustOrderDetailPO();
BeanUtils.copyProperties(detail, detailPO);
return detailPO;
}).collect(Collectors.toList());
}
/**
* 根据委托单号集合查询有效明细
*/
@Override
public List<OutEntrustOrderDetailPO> queryByEntrustNumbers(List<String> entrustNumbers) {
if (entrustNumbers == null || entrustNumbers.isEmpty()) {
return new java.util.ArrayList<>();
}
List<OutEntrustOrderDetail> detailList = this.list(new LambdaQueryWrapper<OutEntrustOrderDetail>()
.in(OutEntrustOrderDetail::getEntrustNumber, entrustNumbers)
.eq(OutEntrustOrderDetail::getDelFlag, 1)
.orderByAsc(OutEntrustOrderDetail::getId));
return detailList.stream().map(detail -> {
OutEntrustOrderDetailPO detailPO = new OutEntrustOrderDetailPO();
BeanUtils.copyProperties(detail, detailPO);
return detailPO;
}).collect(Collectors.toList());
}
/**
* 批量保存明细
*/
@Override
public Boolean batchInsert(String entrustNumber, List<OutEntrustOrderDetailDO> detailDOList) {
List<OutEntrustOrderDetail> detailList = detailDOList.stream().map(detailDO -> {
OutEntrustOrderDetail detail = new OutEntrustOrderDetail();
BeanUtils.copyProperties(detailDO, detail);
detail.setEntrustNumber(entrustNumber);
detail.setDelFlag(1);
return detail;
}).collect(Collectors.toList());
return this.saveBatch(detailList);
}
/**
* 根据委托单号逻辑删除明细
*/
@Override
public Boolean deleteByEntrustNumber(String entrustNumber) {
return this.update(new LambdaUpdateWrapper<OutEntrustOrderDetail>()
.eq(OutEntrustOrderDetail::getEntrustNumber, entrustNumber)
.eq(OutEntrustOrderDetail::getDelFlag, 1)
.set(OutEntrustOrderDetail::getDelFlag, 2));
}
/**
* 根据委托单号集合逻辑删除明细
*/
@Override
public Boolean deleteByEntrustNumbers(List<String> entrustNumbers) {
return this.update(new LambdaUpdateWrapper<OutEntrustOrderDetail>()
.in(OutEntrustOrderDetail::getEntrustNumber, entrustNumbers)
.eq(OutEntrustOrderDetail::getDelFlag, 1)
.set(OutEntrustOrderDetail::getDelFlag, 2));
}
}
@@ -0,0 +1,159 @@
package com.mhd.oms.domain.outEntrustOrder.repository.persistence;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.oms.constant.OutEntrustOrderConstant;
import com.mhd.oms.domain.outEntrustOrder.entity.OutEntrustOrder;
import com.mhd.oms.domain.outEntrustOrder.repository.facade.IOutEntrustOrderService;
import com.mhd.oms.domain.outEntrustOrder.repository.mapper.OutEntrustOrderMapper;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import com.mhd.system.api.model.LoginUser;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 出仓委托单Service业务层处理
*
* @author rcx
* @date 2026-09-02
*/
@Service
public class OutEntrustOrderImpl extends ServiceImpl<OutEntrustOrderMapper, OutEntrustOrder> implements IOutEntrustOrderService {
/**
* 查询出仓委托单列表
*/
@Override
public List<OutEntrustOrderPO> queryList(OutEntrustOrderDO outEntrustOrderDO) {
return baseMapper.queryList(outEntrustOrderDO);
}
/**
* 新增出仓委托单
*/
@Override
public Boolean insert(OutEntrustOrderDO outEntrustOrderDO) {
OutEntrustOrder outEntrustOrder = new OutEntrustOrder();
BeanUtils.copyProperties(outEntrustOrderDO, outEntrustOrder);
return this.save(outEntrustOrder);
}
/**
* 修改出仓委托单
*/
@Override
public Boolean update(OutEntrustOrderDO outEntrustOrderDO) {
OutEntrustOrder outEntrustOrder = new OutEntrustOrder();
BeanUtils.copyProperties(outEntrustOrderDO, outEntrustOrder);
return this.updateById(outEntrustOrder);
}
/**
* 批量删除出仓委托单(仅待审核/已驳回且未下发可删除)
*/
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean delete(Long[] ids) {
List<OutEntrustOrder> outEntrustOrders = this.listByIds(Arrays.asList(ids));
//只有待审核/已驳回且未下发的委托单才可以删除
List<OutEntrustOrder> unableDeleteList = outEntrustOrders.stream()
.filter(order -> !(OutEntrustOrderConstant.ORDER_STATUS_PENDING_AUDIT.equals(order.getOrderStatus())
|| OutEntrustOrderConstant.ORDER_STATUS_REJECTED.equals(order.getOrderStatus()))
|| !OutEntrustOrderConstant.ISSUE_STATUS_1.equals(order.getIssueStatus()))
.collect(Collectors.toList());
if (!unableDeleteList.isEmpty()) {
throw new ServiceException("已审核/进行中/已入库或已下发的委托单不允许删除");
}
LoginUser loginUser = SecurityUtils.getLoginUser();
Date now = new Date();
for (OutEntrustOrder outEntrustOrder : outEntrustOrders) {
outEntrustOrder.setDelFlag(2);
outEntrustOrder.setUpdateBy(loginUser == null ? null : loginUser.getUserid());
outEntrustOrder.setUpdateByName(loginUser == null ? null : loginUser.getUsername());
outEntrustOrder.setUpdateTime(now);
}
return this.updateBatchById(outEntrustOrders);
}
/**
* 获取出仓委托单详情
*/
@Override
public OutEntrustOrderPO getInfo(Long id) {
OutEntrustOrder outEntrustOrder = this.getOne(new LambdaQueryWrapper<OutEntrustOrder>()
.eq(OutEntrustOrder::getId, id).eq(OutEntrustOrder::getDelFlag, 1));
if (outEntrustOrder == null) {
throw new ServiceException("出仓委托单不存在");
}
OutEntrustOrderPO outEntrustOrderPO = new OutEntrustOrderPO();
BeanUtils.copyProperties(outEntrustOrder, outEntrustOrderPO);
return outEntrustOrderPO;
}
/**
* 根据编号集合查询出仓委托单列表
*/
@Override
public List<OutEntrustOrderPO> getInfoByIds(List<Long> ids) {
return baseMapper.getInfoByIds(ids);
}
/**
* 审核:待审核/已驳回 → 已审核(2)或已驳回(3)
*/
@Override
public Boolean audit(List<Long> ids, Integer targetStatus, Long auditBy, String auditByName, String auditRemark) {
return this.update(new LambdaUpdateWrapper<OutEntrustOrder>()
.in(OutEntrustOrder::getId, ids)
.eq(OutEntrustOrder::getDelFlag, 1)
.set(OutEntrustOrder::getOrderStatus, targetStatus)
.set(OutEntrustOrder::getAuditBy, auditBy)
.set(OutEntrustOrder::getAuditByName, auditByName)
.set(OutEntrustOrder::getAuditTime, new Date())
.set(OutEntrustOrder::getAuditRemark, auditRemark)
.set(OutEntrustOrder::getUpdateBy, auditBy)
.set(OutEntrustOrder::getUpdateByName, auditByName)
.set(OutEntrustOrder::getUpdateTime, new Date()));
}
/**
* 下发:下发状态置为已下发(订单状态保持已审核)
*/
@Override
public Boolean issue(List<Long> ids, Long issueBy, String issueByName) {
return this.update(new LambdaUpdateWrapper<OutEntrustOrder>()
.in(OutEntrustOrder::getId, ids)
.eq(OutEntrustOrder::getDelFlag, 1)
.set(OutEntrustOrder::getIssueStatus, OutEntrustOrderConstant.ISSUE_STATUS_2)
.set(OutEntrustOrder::getIssueBy, issueBy)
.set(OutEntrustOrder::getIssueByName, issueByName)
.set(OutEntrustOrder::getIssueTime, new Date())
.set(OutEntrustOrder::getUpdateBy, issueBy)
.set(OutEntrustOrder::getUpdateByName, issueByName)
.set(OutEntrustOrder::getUpdateTime, new Date()));
}
/**
* 完成:已审核(已下发)/进行中 → 已入库
*/
@Override
public Boolean finish(List<Long> ids, Long updateBy, String updateByName) {
return this.update(new LambdaUpdateWrapper<OutEntrustOrder>()
.in(OutEntrustOrder::getId, ids)
.eq(OutEntrustOrder::getDelFlag, 1)
.set(OutEntrustOrder::getOrderStatus, OutEntrustOrderConstant.ORDER_STATUS_STORED)
.set(OutEntrustOrder::getUpdateBy, updateBy)
.set(OutEntrustOrder::getUpdateByName, updateByName)
.set(OutEntrustOrder::getUpdateTime, new Date()));
}
}
@@ -0,0 +1,100 @@
package com.mhd.oms.domain.outEntrustOrder.repository.po;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* 出仓委托单明细对象 oms_out_entrust_order_detail
*
* @author rcx
* @date 2026-09-02
*/
@Data
@ApiModel(value = "出仓委托单明细对象", description = "出仓委托单明细响应对象")
public class OutEntrustOrderDetailPO extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
private Long id;
@ApiModelProperty("委托单号(关联主表)")
private String entrustNumber;
@ApiModelProperty("物料基础信息ID")
private Long materialBaseInfoId;
@ApiModelProperty("商品编码")
private String materialCode;
@ApiModelProperty("商品名称(物料档案名)")
private String materialName;
@ApiModelProperty("商品条形码")
private String barCode;
@ApiModelProperty("商品名称(委托单品名)")
private String commodityName;
@ApiModelProperty("商品编号")
private String commodityNo;
@ApiModelProperty("料号")
private String materialNo;
@ApiModelProperty("规格型号")
private String specificationModel;
@ApiModelProperty("SKU码")
private String skucode;
@ApiModelProperty("发票号")
private String invoiceNo;
@ApiModelProperty("申报单位")
private String declareUnit;
@ApiModelProperty("申报数量")
private BigDecimal declareQuantity;
@ApiModelProperty("单价")
private BigDecimal unitPrice;
@ApiModelProperty("单位")
private String unit;
@ApiModelProperty("")
private String liter;
@ApiModelProperty("尺寸")
private String size;
@ApiModelProperty("箱数")
private BigDecimal caseCount;
@ApiModelProperty("件数")
private BigDecimal pieceCount;
@ApiModelProperty("出库数量")
private BigDecimal outboundQuantity;
@ApiModelProperty("总净重(千克)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(千克)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(立方米)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积")
private BigDecimal totalArea;
@ApiModelProperty("总金额")
private BigDecimal totalAmount;
@ApiModelProperty("币制")
private String currency;
@ApiModelProperty("批次")
private String batchRefNo;
@ApiModelProperty("单据参考号")
private String sheetRefNo;
@ApiModelProperty("原产国")
private String countryOfOrigin;
@ApiModelProperty("箱/托盘号")
private String boxPalletNo;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("创建时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date createTime;
}
@@ -0,0 +1,212 @@
package com.mhd.oms.domain.outEntrustOrder.repository.po;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 出仓委托单对象 oms_out_entrust_order
*
* @author rcx
* @date 2026-09-02
*/
@Data
@ApiModel(value = "出仓委托单对象", description = "出仓委托单响应对象")
public class OutEntrustOrderPO extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
@TableId(type = IdType.AUTO)
private Long id;
@ApiModelProperty("委托单号")
private String entrustNumber;
@ApiModelProperty("出库仓库ID")
private Long warehouseId;
@ApiModelProperty("仓库编码")
private String warehouseCode;
@ApiModelProperty("仓库名称")
private String warehouseName;
@ApiModelProperty("客户ID(货主)")
private Long shipperId;
@ApiModelProperty("客户编码")
private String shipperCode;
@ApiModelProperty("客户名称")
private String shipperName;
@ApiModelProperty("业务员ID")
private String salesmanId;
@ApiModelProperty("业务员名称")
private String salesmanName;
@ApiModelProperty("订单类型编码(字典outDocumentType)")
private String orderTypeCode;
@ApiModelProperty("订单类型名称")
private String orderTypeName;
@ApiModelProperty("结算币种")
private String settlementCurrency;
@ApiModelProperty("优先级别编码")
private String priorityLevelCode;
@ApiModelProperty("优先级别名称")
private String priorityLevelName;
@ApiModelProperty("是否直接出库: 1-是 2-否")
private Integer directWarehouse;
@ApiModelProperty("是否复核: 1-是 2-否")
private Integer review;
@ApiModelProperty("预计出货时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expectTime;
@ApiModelProperty("出仓日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date outboundDate;
@ApiModelProperty("orderDate")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date orderDate;
@ApiModelProperty("完成时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date completeTime;
@ApiModelProperty("To(收货人)")
@JsonProperty("to")
private String toReceiver;
@ApiModelProperty("联系人")
private String contactPerson;
@ApiModelProperty("车型及车牌")
private String vehicleModelPlate;
@ApiModelProperty("委托编号(客户委托单号)")
private String entrustNo;
@ApiModelProperty("Tel电话")
private String tel;
@ApiModelProperty("Fax传真")
private String fax;
@ApiModelProperty("司机签名")
private String driverSign;
@ApiModelProperty("承运商编码")
private String carrier;
@ApiModelProperty("承运商名称")
private String carrierName;
@ApiModelProperty("柜号")
private String containerNo;
@ApiModelProperty("")
private String containerNoName;
@ApiModelProperty("运输方式编码")
private String transportModeCode;
@ApiModelProperty("运输方式名称")
private String transportModeName;
@ApiModelProperty("监管方式编码")
private String supervisionModeCode;
@ApiModelProperty("监管方式名称")
private String supervisionModeName;
@ApiModelProperty("申报地关区")
private String declareCustoms;
@ApiModelProperty("进出境关别")
private String entryExitCustoms;
@ApiModelProperty("起运/运抵国(地区)")
private String departureArrivalCountry;
@ApiModelProperty("海关是否查验货物")
private String customsInspectionFlag;
@ApiModelProperty("是否需要报关(预留,页面隐藏)")
private String needDeclareFlag;
@ApiModelProperty("是否需要运输(预留,页面隐藏)")
private String needTransportFlag;
@ApiModelProperty("生产商")
private String manufacturer;
@ApiModelProperty("报关员姓名及联系方式")
private String customsDeclarerInfo;
@ApiModelProperty("送货地址")
private String deliveryAddr;
@ApiModelProperty("附件url")
private String annexUrl;
@ApiModelProperty("订单状态:1-待审核 2-已审核 3-已驳回 4-进行中 5-已入库")
private Integer orderStatus;
@ApiModelProperty("订单状态")
private String orderStatusStr;
@ApiModelProperty("审核人ID")
private Long auditBy;
@ApiModelProperty("审核人姓名")
private String auditByName;
@ApiModelProperty("审核时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;
@ApiModelProperty("审核备注(驳回原因)")
private String auditRemark;
@ApiModelProperty("下发状态:1-未下发 2-已下发")
private Integer issueStatus;
@ApiModelProperty("下发状态")
private String issueStatusStr;
@ApiModelProperty("下发人ID")
private Long issueBy;
@ApiModelProperty("下发人姓名")
private String issueByName;
@ApiModelProperty("下发时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date issueTime;
@ApiModelProperty("申报总数量(明细申报数量之和)")
private BigDecimal declareTotalQuantity;
@ApiModelProperty("发票号(列表展示用,明细发票号逗号拼接;详情请看明细)")
private String invoiceNo;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("组织ID")
private Long organizationId;
@ApiModelProperty("组织名称")
private String organizationName;
@ApiModelProperty("一级组织ID")
private Long topOrganizationId;
@ApiModelProperty("商品明细")
private List<OutEntrustOrderDetailPO> materialDetailList;
}
@@ -0,0 +1,216 @@
package com.mhd.oms.domain.outEntrustOrder.repository.todo;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 出仓委托单对象 oms_out_entrust_order
*
* @author rcx
* @date 2026-09-02
*/
@Data
public class OutEntrustOrderDO extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
private Long id;
@ApiModelProperty("编号集合")
private List<Long> idList;
@ApiModelProperty(name = "组织ID集合")
private List<Long> organizationIdList;
@ApiModelProperty(name = "权限菜单ID")
private Long permissionMenuId;
@ApiModelProperty("委托单号")
private String entrustNumber;
@ApiModelProperty("出库仓库ID")
private Long warehouseId;
@ApiModelProperty("仓库编码")
private String warehouseCode;
@ApiModelProperty("仓库名称")
private String warehouseName;
@ApiModelProperty("客户ID(货主)")
private Long shipperId;
@ApiModelProperty("客户编码")
private String shipperCode;
@ApiModelProperty("客户名称")
private String shipperName;
@ApiModelProperty("业务员ID")
private String salesmanId;
@ApiModelProperty("业务员名称")
private String salesmanName;
@ApiModelProperty("订单类型编码(字典outDocumentType)")
private String orderTypeCode;
@ApiModelProperty("订单类型名称")
private String orderTypeName;
@ApiModelProperty("结算币种")
private String settlementCurrency;
@ApiModelProperty("优先级别编码")
private String priorityLevelCode;
@ApiModelProperty("优先级别名称")
private String priorityLevelName;
@ApiModelProperty("是否直接出库: 1-是 2-否")
private Integer directWarehouse;
@ApiModelProperty("是否复核: 1-是 2-否")
private Integer review;
@ApiModelProperty("预计出货时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expectTime;
@ApiModelProperty("出仓日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date outboundDate;
@ApiModelProperty("orderDate")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date orderDate;
@ApiModelProperty("完成时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date completeTime;
@ApiModelProperty("To(收货人)")
private String toReceiver;
@ApiModelProperty("联系人")
private String contactPerson;
@ApiModelProperty("车型及车牌")
private String vehicleModelPlate;
@ApiModelProperty("委托编号(客户委托单号)")
private String entrustNo;
@ApiModelProperty("Tel电话")
private String tel;
@ApiModelProperty("Fax传真")
private String fax;
@ApiModelProperty("司机签名")
private String driverSign;
@ApiModelProperty("承运商编码")
private String carrier;
@ApiModelProperty("承运商名称")
private String carrierName;
@ApiModelProperty("柜号")
private String containerNo;
@ApiModelProperty("")
private String containerNoName;
@ApiModelProperty("运输方式编码")
private String transportModeCode;
@ApiModelProperty("运输方式名称")
private String transportModeName;
@ApiModelProperty("监管方式编码")
private String supervisionModeCode;
@ApiModelProperty("监管方式名称")
private String supervisionModeName;
@ApiModelProperty("申报地关区")
private String declareCustoms;
@ApiModelProperty("进出境关别")
private String entryExitCustoms;
@ApiModelProperty("起运/运抵国(地区)")
private String departureArrivalCountry;
@ApiModelProperty("海关是否查验货物")
private String customsInspectionFlag;
@ApiModelProperty("是否需要报关(预留,页面隐藏)")
private String needDeclareFlag;
@ApiModelProperty("是否需要运输(预留,页面隐藏)")
private String needTransportFlag;
@ApiModelProperty("生产商")
private String manufacturer;
@ApiModelProperty("报关员姓名及联系方式")
private String customsDeclarerInfo;
@ApiModelProperty("送货地址")
private String deliveryAddr;
@ApiModelProperty("附件url")
private String annexUrl;
@ApiModelProperty("订单状态:1-待审核 2-已审核 3-已驳回 4-进行中 5-已入库")
private Integer orderStatus;
@ApiModelProperty("审核人ID")
private Long auditBy;
@ApiModelProperty("审核人姓名")
private String auditByName;
@ApiModelProperty("审核时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date auditTime;
@ApiModelProperty("审核备注(驳回原因)")
private String auditRemark;
@ApiModelProperty("下发状态:1-未下发 2-已下发")
private Integer issueStatus;
@ApiModelProperty("下发人ID")
private Long issueBy;
@ApiModelProperty("下发人姓名")
private String issueByName;
@ApiModelProperty("下发时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date issueTime;
@ApiModelProperty("申报总数量(明细申报数量之和)")
private BigDecimal declareTotalQuantity;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("组织ID")
private Long organizationId;
@ApiModelProperty("组织名称")
private String organizationName;
@ApiModelProperty("一级组织ID")
private Long topOrganizationId;
@ApiModelProperty("查询-创建开始时间(年月日yyyy-MM-dd)")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date beginCreateTime;
@ApiModelProperty("查询-创建结束时间(年月日yyyy-MM-dd,含当天)")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endCreateTime;
@ApiModelProperty("查询-发票号(模糊匹配明细发票号)")
private String invoiceNo;
@ApiModelProperty("商品明细")
private List<OutEntrustOrderDetailDO> materialDetailList;
}
@@ -0,0 +1,90 @@
package com.mhd.oms.domain.outEntrustOrder.repository.todo;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
* 出仓委托单明细对象 oms_out_entrust_order_detail
*
* @author rcx
* @date 2026-09-02
*/
@Data
public class OutEntrustOrderDetailDO extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
private Long id;
@ApiModelProperty("委托单号(关联主表)")
private String entrustNumber;
@ApiModelProperty("物料基础信息ID")
private Long materialBaseInfoId;
@ApiModelProperty("商品编码")
private String materialCode;
@ApiModelProperty("商品名称(物料档案名)")
private String materialName;
@ApiModelProperty("商品条形码")
private String barCode;
@ApiModelProperty("商品名称(委托单品名)")
private String commodityName;
@ApiModelProperty("商品编号")
private String commodityNo;
@ApiModelProperty("料号")
private String materialNo;
@ApiModelProperty("规格型号")
private String specificationModel;
@ApiModelProperty("SKU码")
private String skucode;
@ApiModelProperty("发票号")
private String invoiceNo;
@ApiModelProperty("申报单位")
private String declareUnit;
@ApiModelProperty("申报数量")
private BigDecimal declareQuantity;
@ApiModelProperty("单价")
private BigDecimal unitPrice;
@ApiModelProperty("单位")
private String unit;
@ApiModelProperty("")
private String liter;
@ApiModelProperty("尺寸")
private String size;
@ApiModelProperty("箱数")
private BigDecimal caseCount;
@ApiModelProperty("件数")
private BigDecimal pieceCount;
@ApiModelProperty("出库数量")
private BigDecimal outboundQuantity;
@ApiModelProperty("总净重(千克)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(千克)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(立方米)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积")
private BigDecimal totalArea;
@ApiModelProperty("总金额")
private BigDecimal totalAmount;
@ApiModelProperty("币制")
private String currency;
@ApiModelProperty("批次")
private String batchRefNo;
@ApiModelProperty("单据参考号")
private String sheetRefNo;
@ApiModelProperty("原产国")
private String countryOfOrigin;
@ApiModelProperty("箱/托盘号")
private String boxPalletNo;
@ApiModelProperty("备注")
private String remark;
}
@@ -0,0 +1,177 @@
package com.mhd.oms.domain.outEntrustOrder.service;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.common.core.utils.OrderSequence;
import com.mhd.oms.constant.OutEntrustOrderConstant;
import com.mhd.oms.domain.outEntrustOrder.repository.facade.IOutEntrustOrderDetailService;
import com.mhd.oms.domain.outEntrustOrder.repository.facade.IOutEntrustOrderService;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderDetailPO;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.List;
import java.util.stream.Collectors;
/**
* 出仓委托单
*
* @author rcx
* @date 2026-09-02
*/
@Service
@Slf4j
public class OutEntrustOrderDomainService {
@Autowired
private IOutEntrustOrderService outEntrustOrderService;
@Autowired
private IOutEntrustOrderDetailService outEntrustOrderDetailService;
/**
* 分页查询出仓委托单列表
*/
public List<OutEntrustOrderPO> queryList(OutEntrustOrderDO outEntrustOrderDO) {
return outEntrustOrderService.queryList(outEntrustOrderDO);
}
/**
* 新增出仓委托单(主单+明细)
*/
@Transactional(rollbackFor = Exception.class)
public Boolean insert(OutEntrustOrderDO outEntrustOrderDO) {
//生成委托单号,初始状态:待审核、未下发;新单无审核信息
outEntrustOrderDO.setEntrustNumber(OrderSequence.getOrderCode(OutEntrustOrderConstant.OUT_ENTRUST_NO_PREFIX));
outEntrustOrderDO.setOrderStatus(OutEntrustOrderConstant.ORDER_STATUS_PENDING_AUDIT);
outEntrustOrderDO.setIssueStatus(OutEntrustOrderConstant.ISSUE_STATUS_1);
outEntrustOrderDO.setAuditRemark(null);
outEntrustOrderService.insert(outEntrustOrderDO);
outEntrustOrderDetailService.batchInsert(outEntrustOrderDO.getEntrustNumber(), buildDetailList(outEntrustOrderDO));
return true;
}
/**
* 修改出仓委托单(仅已创建且未下发可修改,明细全量替换)
*/
/**
* 修改出仓委托单(仅待审核/已驳回且未下发可修改,明细全量替换)
* 已驳回单重新编辑后状态重置为待审核,待重新审核
*/
@Transactional(rollbackFor = Exception.class)
public Boolean update(OutEntrustOrderDO outEntrustOrderDO) {
OutEntrustOrderPO orderPO = checkEditable(outEntrustOrderDO.getId());
//已驳回 → 编辑后回到待审核;待审核 → 保持不变(置null,updateById跳过该列)
outEntrustOrderDO.setOrderStatus(OutEntrustOrderConstant.ORDER_STATUS_REJECTED.equals(orderPO.getOrderStatus())
? OutEntrustOrderConstant.ORDER_STATUS_PENDING_AUDIT : null);
outEntrustOrderDO.setEntrustNumber(orderPO.getEntrustNumber());
outEntrustOrderService.update(outEntrustOrderDO);
//明细全量替换:逻辑删除旧明细后重新保存
outEntrustOrderDetailService.deleteByEntrustNumber(outEntrustOrderDO.getEntrustNumber());
outEntrustOrderDetailService.batchInsert(outEntrustOrderDO.getEntrustNumber(), buildDetailList(outEntrustOrderDO));
return true;
}
/**
* 批量删除出仓委托单(仅待审核/已驳回且未下发可删除)
*/
@Transactional(rollbackFor = Exception.class)
public Boolean delete(Long[] ids) {
List<OutEntrustOrderPO> orderList = outEntrustOrderService.getInfoByIds(java.util.Arrays.stream(ids).collect(Collectors.toList()));
List<String> entrustNumbers = orderList.stream().map(OutEntrustOrderPO::getEntrustNumber).collect(Collectors.toList());
outEntrustOrderService.delete(ids);
outEntrustOrderDetailService.deleteByEntrustNumbers(entrustNumbers);
return true;
}
/**
* 获取出仓委托单详情(含明细)
*/
public OutEntrustOrderPO getInfo(Long id) {
OutEntrustOrderPO outEntrustOrderPO = outEntrustOrderService.getInfo(id);
List<OutEntrustOrderDetailPO> detailList = outEntrustOrderDetailService.queryByEntrustNumber(outEntrustOrderPO.getEntrustNumber());
outEntrustOrderPO.setMaterialDetailList(detailList);
return outEntrustOrderPO;
}
/**
* 批量审核:待审核/已驳回 → 已审核(2)或已驳回(3)
*/
public Boolean audit(List<Long> ids, Integer targetStatus, Long auditBy, String auditByName, String auditRemark) {
return outEntrustOrderService.audit(ids, targetStatus, auditBy, auditByName, auditRemark);
}
/**
* 批量下发:订单状态保持已审核,下发状态置为已下发(WMS侧单据由ApplicationService推送)
*/
public Boolean issue(List<Long> ids, Long issueBy, String issueByName) {
return outEntrustOrderService.issue(ids, issueBy, issueByName);
}
/**
* 完成:已审核(已下发) → 已入库(OMS人工推进)
*/
public Boolean finish(List<Long> ids, Long updateBy, String updateByName) {
return outEntrustOrderService.finish(ids, updateBy, updateByName);
}
/**
* 根据委托单号查询明细
*/
public List<OutEntrustOrderDetailPO> getDetailByEntrustNumber(String entrustNumber) {
return outEntrustOrderDetailService.queryByEntrustNumber(entrustNumber);
}
/**
* 根据委托单号集合查询明细
*/
public List<OutEntrustOrderDetailPO> getDetailByEntrustNumbers(List<String> entrustNumbers) {
return outEntrustOrderDetailService.queryByEntrustNumbers(entrustNumbers);
}
/**
* 根据编号集合查询出仓委托单列表
*/
public List<OutEntrustOrderPO> queryByIds(List<Long> ids) {
return outEntrustOrderService.getInfoByIds(ids);
}
/**
* 明细补充审计信息(取主单的创建/更新人)
*/
private List<OutEntrustOrderDetailDO> buildDetailList(OutEntrustOrderDO outEntrustOrderDO) {
List<OutEntrustOrderDetailDO> detailDOList = outEntrustOrderDO.getMaterialDetailList();
for (OutEntrustOrderDetailDO detailDO : detailDOList) {
detailDO.setCreateBy(outEntrustOrderDO.getCreateBy());
detailDO.setCreateByName(outEntrustOrderDO.getCreateByName());
detailDO.setCreateTime(outEntrustOrderDO.getCreateTime());
detailDO.setUpdateBy(outEntrustOrderDO.getUpdateBy());
detailDO.setUpdateByName(outEntrustOrderDO.getUpdateByName());
detailDO.setUpdateTime(outEntrustOrderDO.getUpdateTime());
detailDO.setDelFlag(1);
}
return detailDOList;
}
/**
* 校验委托单是否可编辑/删除:仅待审核/已驳回 且未下发
*
* @return 委托单信息(供调用方复用当前状态/委托单号)
*/
private OutEntrustOrderPO checkEditable(Long id) {
OutEntrustOrderPO outEntrustOrderPO = outEntrustOrderService.getInfo(id);
boolean editableStatus = OutEntrustOrderConstant.ORDER_STATUS_PENDING_AUDIT.equals(outEntrustOrderPO.getOrderStatus())
|| OutEntrustOrderConstant.ORDER_STATUS_REJECTED.equals(outEntrustOrderPO.getOrderStatus());
if (!editableStatus) {
throw new ServiceException("已审核/进行中/已入库的委托单不允许修改");
}
if (!OutEntrustOrderConstant.ISSUE_STATUS_1.equals(outEntrustOrderPO.getIssueStatus())) {
throw new ServiceException("已下发的委托单不允许修改");
}
return outEntrustOrderPO;
}
}
@@ -0,0 +1,84 @@
package com.mhd.oms.interfaces.assembler.outEntrustOrder;
import cn.hutool.core.util.ObjectUtil;
import com.mhd.common.core.exception.digitalLogisticsException.DigitalLogisticsException;
import com.mhd.common.core.exception.digitalLogisticsException.UserError;
import com.mhd.common.core.utils.IgnoreNullUtil;
import com.mhd.common.core.utils.bean.BeanUtils;
import com.mhd.common.security.utils.SecurityUtils;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDetailDO;
import com.mhd.oms.interfaces.dto.outEntrustOrder.OutEntrustOrderDTO;
import com.mhd.oms.interfaces.dto.outEntrustOrder.OutEntrustOrderDetailDTO;
import com.mhd.system.api.model.LoginUser;
import org.springframework.stereotype.Component;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
* 出仓委托单Assembler
*
* @author rcx
* @date 2026-09-02
*/
@Component
public class OutEntrustOrderAssembler {
/**
* 转换实体
*/
public OutEntrustOrderDO toDO(OutEntrustOrderDTO outEntrustOrderDTO) {
OutEntrustOrderDO outEntrustOrderDO = new OutEntrustOrderDO();
// 拷贝
BeanUtils.copyProperties(outEntrustOrderDTO, outEntrustOrderDO, IgnoreNullUtil.getNullPropertyNames(outEntrustOrderDTO));
LoginUser loginUser = SecurityUtils.getLoginUser();
if (ObjectUtil.isNull(loginUser)) {
throw new DigitalLogisticsException(UserError.TIMEOUT);
}
String userName = loginUser.getUsername();
// 获取登录人id
Long userId = loginUser.getUserid();
if (outEntrustOrderDTO.getId() != null) {
if (userId != null) {
outEntrustOrderDO.setUpdateBy(userId);
} else {
outEntrustOrderDO.setUpdateBy(0L);
}
outEntrustOrderDO.setUpdateByName(userName);
outEntrustOrderDO.setUpdateTime(new Date());
} else {
if (userId != null) {
outEntrustOrderDO.setCreateBy(userId);
outEntrustOrderDO.setUpdateBy(userId);
} else {
outEntrustOrderDO.setCreateBy(0L);
outEntrustOrderDO.setUpdateBy(0L);
}
outEntrustOrderDO.setCreateByName(userName);
outEntrustOrderDO.setUpdateByName(userName);
outEntrustOrderDO.setCreateTime(new Date());
outEntrustOrderDO.setUpdateTime(new Date());
outEntrustOrderDO.setDelFlag(1);
}
// 明细转换
List<OutEntrustOrderDetailDTO> materialDetailList = outEntrustOrderDTO.getMaterialDetailList();
if (materialDetailList != null) {
outEntrustOrderDO.setMaterialDetailList(toDetailDOList(materialDetailList));
}
return outEntrustOrderDO;
}
/**
* 明细DTO转DO
*/
public List<OutEntrustOrderDetailDO> toDetailDOList(List<OutEntrustOrderDetailDTO> detailDTOList) {
return detailDTOList.stream().map(detailDTO -> {
OutEntrustOrderDetailDO detailDO = new OutEntrustOrderDetailDO();
BeanUtils.copyProperties(detailDTO, detailDO, IgnoreNullUtil.getNullPropertyNames(detailDTO));
return detailDO;
}).collect(Collectors.toList());
}
}
@@ -0,0 +1,198 @@
package com.mhd.oms.interfaces.dto.outEntrustOrder;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
/**
* 出仓委托单对象 oms_out_entrust_order
* 表单字段对齐WMS出库管理新增(报关/委托信息块)
*
* @author rcx
* @date 2026-09-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OutEntrustOrderDTO extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
private Long id;
@ApiModelProperty("编号集合(审核/下发/删除用)")
private List<Long> idList;
@ApiModelProperty(name = "组织ID集合")
private List<Long> organizationIdList;
@ApiModelProperty(name = "权限菜单ID")
private Long permissionMenuId;
@ApiModelProperty("委托单号")
private String entrustNumber;
@ApiModelProperty("出库仓库ID(必填)")
private Long warehouseId;
@ApiModelProperty("仓库编码")
private String warehouseCode;
@ApiModelProperty("仓库名称")
private String warehouseName;
@ApiModelProperty("客户ID(货主,必填)")
private Long shipperId;
@ApiModelProperty("客户编码")
private String shipperCode;
@ApiModelProperty("客户名称")
private String shipperName;
@ApiModelProperty("业务员ID(必填)")
private String salesmanId;
@ApiModelProperty("业务员名称")
private String salesmanName;
@ApiModelProperty("订单类型编码(字典outDocumentType)")
private String orderTypeCode;
@ApiModelProperty("订单类型名称")
private String orderTypeName;
@ApiModelProperty("结算币种")
private String settlementCurrency;
@ApiModelProperty("优先级别编码")
private String priorityLevelCode;
@ApiModelProperty("优先级别名称")
private String priorityLevelName;
@ApiModelProperty("是否直接出库: 1-是 2-否")
private Integer directWarehouse;
@ApiModelProperty("是否复核: 1-是 2-否")
private Integer review;
@ApiModelProperty("预计出货时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date expectTime;
@ApiModelProperty("出仓日期")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date outboundDate;
@ApiModelProperty("orderDate")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date orderDate;
@ApiModelProperty("完成时间")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private Date completeTime;
@ApiModelProperty("To(收货人)")
@JsonProperty("to")
private String toReceiver;
@ApiModelProperty("联系人")
private String contactPerson;
@ApiModelProperty("车型及车牌")
private String vehicleModelPlate;
@ApiModelProperty("委托编号(客户委托单号)")
private String entrustNo;
@ApiModelProperty("Tel电话")
private String tel;
@ApiModelProperty("Fax传真")
private String fax;
@ApiModelProperty("司机签名")
private String driverSign;
@ApiModelProperty("承运商编码")
private String carrier;
@ApiModelProperty("承运商名称")
private String carrierName;
@ApiModelProperty("柜号")
private String containerNo;
@ApiModelProperty("")
private String containerNoName;
@ApiModelProperty("运输方式编码")
private String transportModeCode;
@ApiModelProperty("运输方式名称")
private String transportModeName;
@ApiModelProperty("监管方式编码")
private String supervisionModeCode;
@ApiModelProperty("监管方式名称")
private String supervisionModeName;
@ApiModelProperty("申报地关区")
private String declareCustoms;
@ApiModelProperty("进出境关别")
private String entryExitCustoms;
@ApiModelProperty("起运/运抵国(地区)")
private String departureArrivalCountry;
@ApiModelProperty("海关是否查验货物")
private String customsInspectionFlag;
@ApiModelProperty("是否需要报关(预留,页面隐藏)")
private String needDeclareFlag;
@ApiModelProperty("是否需要运输(预留,页面隐藏)")
private String needTransportFlag;
@ApiModelProperty("生产商")
private String manufacturer;
@ApiModelProperty("报关员姓名及联系方式")
private String customsDeclarerInfo;
@ApiModelProperty("送货地址")
private String deliveryAddr;
@ApiModelProperty("附件url")
private String annexUrl;
@ApiModelProperty("订单状态:1-待审核 2-已审核 3-已驳回 4-进行中 5-已入库")
private Integer orderStatus;
@ApiModelProperty("下发状态:1-未下发 2-已下发")
private Integer issueStatus;
@ApiModelProperty("审核备注(驳回原因,审核时传)")
private String auditRemark;
@ApiModelProperty("申报总数量(服务端按明细汇总,无需传入)")
private BigDecimal declareTotalQuantity;
@ApiModelProperty("备注")
private String remark;
@ApiModelProperty("查询-创建开始时间(年月日yyyy-MM-dd)")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date beginCreateTime;
@ApiModelProperty("查询-创建结束时间(年月日yyyy-MM-dd,含当天)")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date endCreateTime;
@ApiModelProperty("查询-发票号(模糊匹配明细发票号)")
private String invoiceNo;
@ApiModelProperty("商品明细")
private List<OutEntrustOrderDetailDTO> materialDetailList;
}
@@ -0,0 +1,93 @@
package com.mhd.oms.interfaces.dto.outEntrustOrder;
import com.mhd.common.core.web.domain.BaseVOEntity;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import java.math.BigDecimal;
/**
* 出仓委托单明细对象 oms_out_entrust_order_detail
* 明细列对齐WMS出库管理新增(出仓委托单明细列)
*
* @author rcx
* @date 2026-09-02
*/
@EqualsAndHashCode(callSuper = true)
@Data
public class OutEntrustOrderDetailDTO extends BaseVOEntity {
private static final long serialVersionUID = 1L;
@ApiModelProperty("编号")
private Long id;
@ApiModelProperty("委托单号(关联主表)")
private String entrustNumber;
@ApiModelProperty("物料基础信息ID")
private Long materialBaseInfoId;
@ApiModelProperty("商品编码")
private String materialCode;
@ApiModelProperty("商品名称(物料档案名,与commodityName至少其一)")
private String materialName;
@ApiModelProperty("商品条形码")
private String barCode;
@ApiModelProperty("商品名称(委托单品名,与materialName至少其一)")
private String commodityName;
@ApiModelProperty("商品编号")
private String commodityNo;
@ApiModelProperty("料号")
private String materialNo;
@ApiModelProperty("规格型号")
private String specificationModel;
@ApiModelProperty("SKU码")
private String skucode;
@ApiModelProperty("发票号")
private String invoiceNo;
@ApiModelProperty("申报单位")
private String declareUnit;
@ApiModelProperty("申报数量(必填,大于0)")
private BigDecimal declareQuantity;
@ApiModelProperty("单价")
private BigDecimal unitPrice;
@ApiModelProperty("单位")
private String unit;
@ApiModelProperty("")
private String liter;
@ApiModelProperty("尺寸")
private String size;
@ApiModelProperty("箱数")
private BigDecimal caseCount;
@ApiModelProperty("件数")
private BigDecimal pieceCount;
@ApiModelProperty("出库数量")
private BigDecimal outboundQuantity;
@ApiModelProperty("总净重(千克)")
private BigDecimal totalNetWeight;
@ApiModelProperty("总毛重(千克)")
private BigDecimal totalGrossWeight;
@ApiModelProperty("总体积(立方米)")
private BigDecimal totalVolume;
@ApiModelProperty("总面积")
private BigDecimal totalArea;
@ApiModelProperty("总金额")
private BigDecimal totalAmount;
@ApiModelProperty("币制")
private String currency;
@ApiModelProperty("批次")
private String batchRefNo;
@ApiModelProperty("单据参考号")
private String sheetRefNo;
@ApiModelProperty("原产国")
private String countryOfOrigin;
@ApiModelProperty("箱/托盘号")
private String boxPalletNo;
@ApiModelProperty("备注")
private String remark;
}
@@ -0,0 +1,111 @@
package com.mhd.oms.interfaces.facade.outEntrustOrder;
import com.mhd.common.core.web.controller.BaseController;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.common.core.web.page.TableDataInfo;
import com.mhd.oms.application.service.outEntrustOrder.OutEntrustOrderApplicationService;
import com.mhd.oms.domain.outEntrustOrder.repository.po.OutEntrustOrderPO;
import com.mhd.oms.domain.outEntrustOrder.repository.todo.OutEntrustOrderDO;
import com.mhd.oms.interfaces.assembler.outEntrustOrder.OutEntrustOrderAssembler;
import com.mhd.oms.interfaces.dto.outEntrustOrder.OutEntrustOrderDTO;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
/**
* 出仓委托单Api
*
* @author rcx
* @date 2026-09-02
*/
@Slf4j
@RestController
@RequestMapping("/outEntrustOrderApi")
public class OutEntrustOrderApi extends BaseController {
@Autowired
private OutEntrustOrderApplicationService outEntrustOrderApplicationService;
@Resource
private OutEntrustOrderAssembler outEntrustOrderAssembler;
/**
* 分页查询出仓委托单列表(显示全部数据,不做默认状态过滤)
*/
@ApiOperation("查询出仓委托单列表")
@GetMapping("/list")
public TableDataInfo list(OutEntrustOrderDTO outEntrustOrderDTO) {
//转换实体
OutEntrustOrderDO outEntrustOrderDO = outEntrustOrderAssembler.toDO(outEntrustOrderDTO);
startPage();
List<OutEntrustOrderPO> list = outEntrustOrderApplicationService.queryList(outEntrustOrderDO);
return getDataTable(list);
}
/**
* 新增/修改出仓委托单(必填:客户、业务员、仓库、商品名称、申报数量)
*/
@ApiOperation("编辑出仓委托单")
@PostMapping("/edit")
public AjaxResult edit(@RequestBody OutEntrustOrderDTO outEntrustOrderDTO) {
//转换实体
OutEntrustOrderDO outEntrustOrderDO = outEntrustOrderAssembler.toDO(outEntrustOrderDTO);
if (outEntrustOrderDTO.getId() != null) {
return toAjax(outEntrustOrderApplicationService.update(outEntrustOrderDO));
} else {
return toAjax(outEntrustOrderApplicationService.insert(outEntrustOrderDO));
}
}
/**
* 批量删除出仓委托单(仅待审核/已驳回且未下发)
*/
@ApiOperation("批量删除出仓委托单")
@DeleteMapping("/deleteByIds/{ids}")
public AjaxResult delete(@PathVariable Long[] ids) {
return toAjax(outEntrustOrderApplicationService.delete(ids));
}
/**
* 获取出仓委托单详情(含明细)
*/
@ApiOperation("获取出仓委托单")
@GetMapping(value = "/getInfo/{id}")
public AjaxResult getInfo(@PathVariable("id") Long id) {
return AjaxResult.success(outEntrustOrderApplicationService.getInfo(id));
}
/**
* 批量审核:待审核/已驳回 → 已审核(通过)或已驳回
* 请求体:{"idList":[1,2],"orderStatus":3,"auditRemark":"备注"}orderStatus2-审核通过 3-驳回(auditRemark选填)
*/
@ApiOperation("审核出仓委托单")
@PostMapping("/audit")
public AjaxResult audit(@RequestBody OutEntrustOrderDTO outEntrustOrderDTO) {
return toAjax(outEntrustOrderApplicationService.audit(outEntrustOrderAssembler.toDO(outEntrustOrderDTO)));
}
/**
* 批量下发:已审核的委托单下发到WMS(生成出库通知单),下发后订单状态变为进行中
*/
@ApiOperation("下发出仓委托单")
@PostMapping("/issueOrder")
public AjaxResult issueOrder(@RequestBody HashMap<String,List<Long>> body) {
List<Long> ids = body.get("ids");
return toAjax(outEntrustOrderApplicationService.issueOrder(ids));
}
/**
* 批量完成:进行中 → 已入库(WMS出库完成后人工确认)
*/
@ApiOperation("委托单完成入库")
@PostMapping("/finish")
public AjaxResult finish(@RequestBody List<Long> ids) {
return toAjax(outEntrustOrderApplicationService.finish(ids));
}
}