维他奶出入库业务单修改;
This commit is contained in:
@@ -3,14 +3,17 @@ package com.mhd.system.api.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -368,4 +371,9 @@ public class InMaterialDetail extends BaseVOEntity {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.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 java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
@Data
|
||||
@TableName(value = "reservation_delivery_details_link")
|
||||
public class ReservationDeliveryDetailsLink extends BaseVOEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("编号")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "业务单id")
|
||||
private Long orderId;
|
||||
@ApiModelProperty(value = "业务单号")
|
||||
private String orderNumber;
|
||||
@ApiModelProperty(value = "类别")
|
||||
private String category;
|
||||
|
||||
@ApiModelProperty(value = "发票编号")
|
||||
private String invoiceNumber;
|
||||
|
||||
@ApiModelProperty(value = "客户编号")
|
||||
private String customerNumber;
|
||||
|
||||
@ApiModelProperty(value = "配送名称")
|
||||
private String deliveryName;
|
||||
|
||||
@ApiModelProperty(value = "箱")
|
||||
private Integer box;
|
||||
|
||||
@ApiModelProperty(value = "包")
|
||||
private Integer bag;
|
||||
|
||||
@ApiModelProperty(value = "金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.facade;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.todo.ReservationDeliveryDetailsLinkDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 预约配送明细关联Service接口
|
||||
*
|
||||
* @author gen
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
public interface IReservationDeliveryDetailsLinkService extends IService<ReservationDeliveryDetailsLink>
|
||||
{
|
||||
/**
|
||||
* 分页查询预约配送明细关联列表
|
||||
*/
|
||||
public List<ReservationDeliveryDetailsLinkPO> queryList(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO);
|
||||
|
||||
/**
|
||||
* 新增预约配送明细关联
|
||||
*/
|
||||
public Boolean insert(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO);
|
||||
|
||||
/**
|
||||
* 修改预约配送明细关联
|
||||
*/
|
||||
public Boolean update(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO);
|
||||
|
||||
/**
|
||||
* 批量删除预约配送明细关联
|
||||
*/
|
||||
public Boolean delete(Long[] ids);
|
||||
|
||||
|
||||
/**
|
||||
* 查询预约配送明细关联
|
||||
*/
|
||||
public ReservationDeliveryDetailsLinkPO getInfo(Long id);
|
||||
|
||||
/**
|
||||
* 批量新增
|
||||
*/
|
||||
Boolean batchInsert(List<ReservationDeliveryDetailsLinkDO> reservationDeliveryDetailsLinkDOList);
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.mapper;
|
||||
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.todo.ReservationDeliveryDetailsLinkDO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 预约配送明细关联Mapper接口
|
||||
*
|
||||
* @author gen
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
public interface ReservationDeliveryDetailsLinkMapper extends BaseMapper<ReservationDeliveryDetailsLink>
|
||||
{
|
||||
/**
|
||||
* 查询预约配送明细关联列表
|
||||
*/
|
||||
public List<ReservationDeliveryDetailsLinkPO> queryList(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO);
|
||||
|
||||
}
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.persistence;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.facade.IReservationDeliveryDetailsLinkService;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.mapper.ReservationDeliveryDetailsLinkMapper;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.todo.ReservationDeliveryDetailsLinkDO;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 预约配送明细关联Service业务层处理
|
||||
*
|
||||
* @author gen
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
@Service
|
||||
public class ReservationDeliveryDetailsLinkImpl extends ServiceImpl<ReservationDeliveryDetailsLinkMapper, ReservationDeliveryDetailsLink> implements IReservationDeliveryDetailsLinkService {
|
||||
@Autowired
|
||||
private ReservationDeliveryDetailsLinkMapper reservationDeliveryDetailsLinkMapper;
|
||||
|
||||
/**
|
||||
* 查询预约配送明细关联列表
|
||||
*/
|
||||
@Override
|
||||
public List<ReservationDeliveryDetailsLinkPO> queryList(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO)
|
||||
{
|
||||
return reservationDeliveryDetailsLinkMapper.queryList(reservationDeliveryDetailsLinkDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 新增预约配送明细关联
|
||||
*/
|
||||
@Override
|
||||
public Boolean insert(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO) {
|
||||
ReservationDeliveryDetailsLink reservationDeliveryDetailsLink = new ReservationDeliveryDetailsLink();
|
||||
BeanUtils.copyProperties(reservationDeliveryDetailsLinkDO, reservationDeliveryDetailsLink);
|
||||
return this.save(reservationDeliveryDetailsLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改预约配送明细关联
|
||||
*/
|
||||
@Override
|
||||
public Boolean update(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO) {
|
||||
ReservationDeliveryDetailsLink reservationDeliveryDetailsLink = new ReservationDeliveryDetailsLink();
|
||||
BeanUtils.copyProperties(reservationDeliveryDetailsLinkDO, reservationDeliveryDetailsLink);
|
||||
return this.updateById(reservationDeliveryDetailsLink);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除预约配送明细关联
|
||||
*/
|
||||
@Override
|
||||
public Boolean delete(Long[] ids ) {
|
||||
List<ReservationDeliveryDetailsLink> list = new ArrayList<>();
|
||||
for (Long id : ids) {
|
||||
ReservationDeliveryDetailsLink reservationDeliveryDetailsLink = new ReservationDeliveryDetailsLink();
|
||||
reservationDeliveryDetailsLink.setId(id);
|
||||
reservationDeliveryDetailsLink.setDelFlag(2);
|
||||
list.add(reservationDeliveryDetailsLink);
|
||||
}
|
||||
return this.updateBatchById(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询预约配送明细关联
|
||||
*/
|
||||
@Override
|
||||
public ReservationDeliveryDetailsLinkPO getInfo(Long id) {
|
||||
ReservationDeliveryDetailsLink reservationDeliveryDetailsLink = this.getById(id);
|
||||
ReservationDeliveryDetailsLinkPO reservationDeliveryDetailsLinkPO = new ReservationDeliveryDetailsLinkPO();
|
||||
BeanUtils.copyProperties(reservationDeliveryDetailsLink, reservationDeliveryDetailsLinkPO);
|
||||
return reservationDeliveryDetailsLinkPO;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean batchInsert(List<ReservationDeliveryDetailsLinkDO> reservationDeliveryDetailsLinkDOList) {
|
||||
List<ReservationDeliveryDetailsLink> reservationDeliveryDetailsLinkList = reservationDeliveryDetailsLinkDOList.stream().map(reservationDeliveryDetailsLinkDO -> {
|
||||
ReservationDeliveryDetailsLink reservationDeliveryDetailsLink = new ReservationDeliveryDetailsLink();
|
||||
BeanUtils.copyProperties(reservationDeliveryDetailsLinkDO, reservationDeliveryDetailsLink);
|
||||
return reservationDeliveryDetailsLink;
|
||||
}).collect(Collectors.toList());
|
||||
|
||||
return this.saveBatch(reservationDeliveryDetailsLinkList);
|
||||
}
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
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_receipt_info
|
||||
*
|
||||
* @author gen
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
|
||||
@Data
|
||||
@ApiModel(value = "预约配送明细关联对象", description = "预约配送明细关联响应对象")
|
||||
public class ReservationDeliveryDetailsLinkPO extends BaseVOEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("编号")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "业务单id")
|
||||
private Long orderId;
|
||||
@ApiModelProperty(value = "业务单号")
|
||||
private String orderNumber;
|
||||
@ApiModelProperty(value = "类别")
|
||||
private String category;
|
||||
|
||||
@ApiModelProperty(value = "发票编号")
|
||||
private String invoiceNumber;
|
||||
|
||||
@ApiModelProperty(value = "客户编号")
|
||||
private String customerNumber;
|
||||
|
||||
@ApiModelProperty(value = "配送名称")
|
||||
private String deliveryName;
|
||||
|
||||
@ApiModelProperty(value = "箱")
|
||||
private Integer box;
|
||||
|
||||
@ApiModelProperty(value = "包")
|
||||
private Integer bag;
|
||||
|
||||
@ApiModelProperty(value = "金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
}
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.todo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
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_receipt_info
|
||||
*
|
||||
* @author gen
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
|
||||
@Data
|
||||
public class ReservationDeliveryDetailsLinkDO extends BaseVOEntity {
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
@ApiModelProperty("编号")
|
||||
@TableId(type = IdType.AUTO)
|
||||
private Long id;
|
||||
|
||||
@ApiModelProperty(value = "业务单id")
|
||||
private Long orderId;
|
||||
@ApiModelProperty(value = "业务单号")
|
||||
private String orderNumber;
|
||||
@ApiModelProperty(value = "类别")
|
||||
private String category;
|
||||
|
||||
@ApiModelProperty(value = "发票编号")
|
||||
private String invoiceNumber;
|
||||
|
||||
@ApiModelProperty(value = "客户编号")
|
||||
private String customerNumber;
|
||||
|
||||
@ApiModelProperty(value = "配送名称")
|
||||
private String deliveryName;
|
||||
|
||||
@ApiModelProperty(value = "箱")
|
||||
private Integer box;
|
||||
|
||||
@ApiModelProperty(value = "包")
|
||||
private Integer bag;
|
||||
|
||||
@ApiModelProperty(value = "金额")
|
||||
private BigDecimal amount;
|
||||
|
||||
@ApiModelProperty(name = "组织ID集合")
|
||||
private List<Long> organizationIdList;
|
||||
|
||||
@ApiModelProperty(name = "权限菜单ID")
|
||||
private Long permissionMenuId;
|
||||
}
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
package com.mhd.oms.domain.reservationDeliveryDetailsLink.service;
|
||||
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.facade.IReservationDeliveryDetailsLinkService;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.todo.ReservationDeliveryDetailsLinkDO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 预约配送明细关联
|
||||
*
|
||||
* @author gen
|
||||
* @date 2026-05-26
|
||||
*/
|
||||
@Service
|
||||
@Slf4j
|
||||
public class ReservationDeliveryDetailsLinkDomainService {
|
||||
|
||||
@Autowired
|
||||
private IReservationDeliveryDetailsLinkService reservationDeliveryDetailsLinkService;
|
||||
|
||||
|
||||
/**
|
||||
* 分页查询预约配送明细关联列表
|
||||
*/
|
||||
public List<ReservationDeliveryDetailsLinkPO> queryList(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO) {
|
||||
return reservationDeliveryDetailsLinkService.queryList(reservationDeliveryDetailsLinkDO);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 新增预约配送明细关联
|
||||
*/
|
||||
public Boolean insert(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO) {
|
||||
|
||||
return reservationDeliveryDetailsLinkService.insert(reservationDeliveryDetailsLinkDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改预约配送明细关联
|
||||
*/
|
||||
public Boolean update(ReservationDeliveryDetailsLinkDO reservationDeliveryDetailsLinkDO) {
|
||||
return reservationDeliveryDetailsLinkService.update(reservationDeliveryDetailsLinkDO);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量删除预约配送明细关联
|
||||
*/
|
||||
public Boolean delete(Long[] ids) {
|
||||
return reservationDeliveryDetailsLinkService.delete(ids);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取预约配送明细关联详细信息
|
||||
*/
|
||||
public ReservationDeliveryDetailsLinkPO getInfo(Long id)
|
||||
{
|
||||
return reservationDeliveryDetailsLinkService.getInfo(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量新增
|
||||
*/
|
||||
public Boolean batchInsert(List<ReservationDeliveryDetailsLinkDO> reservationDeliveryDetailsLinkDOList) {
|
||||
return reservationDeliveryDetailsLinkService.batchInsert(reservationDeliveryDetailsLinkDOList);
|
||||
}
|
||||
}
|
||||
+7
@@ -3,14 +3,17 @@ package com.mhd.oms.domain.reservationInMaterialDetail.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -364,4 +367,8 @@ public class ReservationInMaterialDetail extends BaseVOEntity {
|
||||
@ApiModelProperty("lot编号")
|
||||
@Excel(name = "lot编号")
|
||||
private String lotNo;
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+5
-1
@@ -8,6 +8,7 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStock
|
||||
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;
|
||||
@@ -467,5 +468,8 @@ public class ReservationInMaterialDetailPO extends ReservationStockInOrderBasePO
|
||||
@ApiModelProperty("调整后面积")
|
||||
@Excel(name = "调整后面积")
|
||||
private BigDecimal adjustedArea;
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+8
@@ -1,13 +1,16 @@
|
||||
package com.mhd.oms.domain.reservationInMaterialDetail.repository.todo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderBaseDO;
|
||||
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;
|
||||
|
||||
|
||||
@@ -429,4 +432,9 @@ public class ReservationInMaterialDetailDO extends ReservationStockInOrderBaseDO
|
||||
@Excel(name = "调整后面积")
|
||||
private BigDecimal adjustedArea;
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
|
||||
}
|
||||
+8
@@ -1,13 +1,16 @@
|
||||
package com.mhd.oms.domain.reservationInMaterialDetail.repository.todo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -439,4 +442,9 @@ public class ReservationInMaterialDetailDTO extends BaseVOEntity {
|
||||
@ApiModelProperty("调整后面积")
|
||||
@Excel(name = "调整后面积")
|
||||
private BigDecimal adjustedArea;
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+10
@@ -6,6 +6,7 @@ import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStockInOrderPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.DeliveryDataDTO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.StockInDataDTO;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
|
||||
@@ -56,4 +57,13 @@ public interface IReservationStockInOrderService extends IService<ReservationSto
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
DeliveryDataDTO parseExcelFile(MultipartFile file, String sheetName) throws Exception;
|
||||
|
||||
/**
|
||||
* 解析入库单Excel文件
|
||||
* @param file Excel文件
|
||||
* @param sheetName 工作表名称(默认:入库模版)
|
||||
* @return 入库单完整数据(表头+明细)
|
||||
* @throws Exception 解析异常
|
||||
*/
|
||||
StockInDataDTO parseStockInExcel(MultipartFile file, String sheetName) throws Exception;
|
||||
}
|
||||
-210
@@ -1,210 +0,0 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.alibaba.excel.exception.ExcelDataConvertException;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.CustomerDeliveryDetail;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.DeliveryHeader;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.ProductDetail;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Excel解析监听器
|
||||
*/
|
||||
public class DeliveryExcelListener extends AnalysisEventListener<Object> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DeliveryExcelListener.class);
|
||||
|
||||
// 数据存储
|
||||
private DeliveryHeader deliveryHeader = new DeliveryHeader();
|
||||
private List<ProductDetail> productDetailList = new ArrayList<>();
|
||||
private List<CustomerDeliveryDetail> customerDeliveryDetailList = new ArrayList<>();
|
||||
|
||||
// 解析状态标记
|
||||
private boolean isProductDetail = false; // 是否在解析货品明细
|
||||
private boolean isCustomerDetail = false; // 是否在解析客户配送明细
|
||||
|
||||
@Override
|
||||
public void invoke(Object data, AnalysisContext context) {
|
||||
try {
|
||||
// 将数据转为数组(Excel行数据)
|
||||
Object[] rowData = (Object[]) data;
|
||||
|
||||
// 1. 解析表头信息(第1行)
|
||||
if (context.readRowHolder().getRowIndex() == 0) {
|
||||
parseHeaderInfo(rowData);
|
||||
}
|
||||
// 2. 识别数据区域(根据关键字判断)
|
||||
else if (context.readRowHolder().getRowIndex() == 1) {
|
||||
if (rowData[0] != null && "货品明细".equals(rowData[0].toString().trim())) {
|
||||
isProductDetail = true;
|
||||
isCustomerDetail = false;
|
||||
}
|
||||
}
|
||||
else if (context.readRowHolder().getRowIndex() == 7) {
|
||||
// 解析纪录合共(第8行,索引为7)
|
||||
parseTotalRecord(rowData);
|
||||
}
|
||||
else if (context.readRowHolder().getRowIndex() == 8) {
|
||||
if (rowData[0] != null && "客户配送明细".equals(rowData[0].toString().trim())) {
|
||||
isProductDetail = false;
|
||||
isCustomerDetail = true;
|
||||
}
|
||||
}
|
||||
else if (context.readRowHolder().getRowIndex() == 30) {
|
||||
// 解析发票张数(第31行,索引为30)
|
||||
parseInvoiceCount(rowData);
|
||||
}
|
||||
// 3. 解析货品明细(第4-7行,索引3-6)
|
||||
else if (isProductDetail && context.readRowHolder().getRowIndex() >= 3 && context.readRowHolder().getRowIndex() <= 6) {
|
||||
parseProductDetail(rowData);
|
||||
}
|
||||
// 4. 解析客户配送明细(第11-30行,索引10-29)
|
||||
else if (isCustomerDetail && context.readRowHolder().getRowIndex() >= 10 && context.readRowHolder().getRowIndex() <= 29) {
|
||||
parseCustomerDeliveryDetail(rowData);
|
||||
}
|
||||
|
||||
} catch (ExcelDataConvertException e) {
|
||||
LOGGER.error("Excel数据转换异常,行号:{},列号:{}",
|
||||
context.readRowHolder().getRowIndex() + 1,
|
||||
e.getColumnIndex() + 1);
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("Excel解析异常,行号:{}",
|
||||
context.readRowHolder().getRowIndex() + 1, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析表头信息(第1行)
|
||||
*/
|
||||
private void parseHeaderInfo(Object[] rowData) {
|
||||
// 送货日期(第2列,索引1)
|
||||
if (rowData[1] != null) {
|
||||
deliveryHeader.setDeliveryDate((Date) rowData[1]);
|
||||
}
|
||||
// 送货线号(第4列,索引3)
|
||||
if (rowData[3] != null) {
|
||||
deliveryHeader.setDeliveryLineNo(Integer.parseInt(rowData[3].toString()));
|
||||
}
|
||||
// 车次(第6列,索引5)
|
||||
if (rowData[5] != null) {
|
||||
deliveryHeader.setTrainNumber(Integer.parseInt(rowData[5].toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析纪录合共(第8行)
|
||||
*/
|
||||
private void parseTotalRecord(Object[] rowData) {
|
||||
// 纪录合共-货品总数量(第2列,索引1)
|
||||
if (rowData[1] != null) {
|
||||
deliveryHeader.setTotalRecordCount(Integer.parseInt(rowData[1].toString()));
|
||||
}
|
||||
// 总箱数(第5列,索引4)
|
||||
if (rowData[4] != null) {
|
||||
deliveryHeader.setTotalBoxCount(Integer.parseInt(rowData[4].toString()));
|
||||
}
|
||||
// 总支数(第6列,索引5)
|
||||
if (rowData[5] != null) {
|
||||
deliveryHeader.setTotalPieceCount(Integer.parseInt(rowData[5].toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析发票张数(第31行)
|
||||
*/
|
||||
private void parseInvoiceCount(Object[] rowData) {
|
||||
// 发票张数(第2列,索引1)
|
||||
if (rowData[1] != null) {
|
||||
deliveryHeader.setInvoiceCount(Integer.parseInt(rowData[1].toString()));
|
||||
}
|
||||
// 小计-总箱数(第5列,索引4)
|
||||
if (rowData[4] != null) {
|
||||
deliveryHeader.setSubtotalBoxCount(Integer.parseInt(rowData[4].toString()));
|
||||
}
|
||||
// 小计-总支数(第6列,索引5)
|
||||
if (rowData[5] != null) {
|
||||
deliveryHeader.setSubtotalPieceCount(Integer.parseInt(rowData[5].toString()));
|
||||
}
|
||||
// 小计-总金额(第7列,索引6)
|
||||
if (rowData[6] != null) {
|
||||
deliveryHeader.setSubtotalAmount(new BigDecimal(rowData[6].toString()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析货品明细
|
||||
*/
|
||||
private void parseProductDetail(Object[] rowData) {
|
||||
ProductDetail productDetail = new ProductDetail();
|
||||
// 货品编号(第1列,索引0)
|
||||
if (rowData[0] != null) {
|
||||
productDetail.setProductCode(rowData[0].toString().trim());
|
||||
}
|
||||
// 货品简称(第2列,索引1)
|
||||
if (rowData[1] != null) {
|
||||
productDetail.setProductName(rowData[1].toString().trim());
|
||||
}
|
||||
// 箱数(第5列,索引4)
|
||||
if (rowData[4] != null) {
|
||||
productDetail.setBoxCount(Integer.parseInt(rowData[4].toString()));
|
||||
}
|
||||
// 支数(第6列,索引5)
|
||||
if (rowData[5] != null) {
|
||||
productDetail.setPieceCount(Integer.parseInt(rowData[5].toString()));
|
||||
}
|
||||
productDetailList.add(productDetail);
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析客户配送明细
|
||||
*/
|
||||
private void parseCustomerDeliveryDetail(Object[] rowData) {
|
||||
CustomerDeliveryDetail customerDetail = new CustomerDeliveryDetail();
|
||||
// 类别(第1列,索引0)
|
||||
if (rowData[0] != null) {
|
||||
customerDetail.setCategory(rowData[0].toString().trim());
|
||||
}
|
||||
// 发票编号(第2列,索引1)
|
||||
if (rowData[1] != null) {
|
||||
customerDetail.setInvoiceNo(rowData[1].toString().trim());
|
||||
}
|
||||
// 客户编号(第3列,索引2)
|
||||
if (rowData[2] != null) {
|
||||
customerDetail.setCustomerCode(rowData[2].toString().trim());
|
||||
}
|
||||
// 客户名称(第4列,索引3)
|
||||
if (rowData[3] != null) {
|
||||
customerDetail.setCustomerName(rowData[3].toString().trim());
|
||||
}
|
||||
// 箱数(第5列,索引4)
|
||||
if (rowData[4] != null) {
|
||||
customerDetail.setBoxCount(Integer.parseInt(rowData[4].toString()));
|
||||
}
|
||||
// 包数(第6列,索引5)
|
||||
if (rowData[5] != null) {
|
||||
customerDetail.setPackageCount(Integer.parseInt(rowData[5].toString()));
|
||||
}
|
||||
// 金额(第7列,索引6)
|
||||
if (rowData[6] != null) {
|
||||
customerDetail.setAmount(new BigDecimal(rowData[6].toString()));
|
||||
}
|
||||
customerDeliveryDetailList.add(customerDetail);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
LOGGER.info("Excel解析完成,共解析货品明细:{}条,客户配送明细:{}条",
|
||||
productDetailList.size(), customerDeliveryDetailList.size());
|
||||
}
|
||||
|
||||
// Getter方法(供Service层获取解析后的数据)
|
||||
public DeliveryHeader getDeliveryHeader() { return deliveryHeader; }
|
||||
public List<ProductDetail> getProductDetailList() { return productDetailList; }
|
||||
public List<CustomerDeliveryDetail> getCustomerDeliveryDetailList() { return customerDeliveryDetailList; }
|
||||
}
|
||||
+518
@@ -0,0 +1,518 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.alibaba.excel.exception.ExcelDataConvertException;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.CustomerDeliveryDetail;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.DeliveryHeader;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.ProductDetail;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* 维他奶出库Excel解析监听器(最终完整版)
|
||||
* 核心功能:
|
||||
* 1. 正确解析多单元格数据(解决发票张数/纪录合共读取错误)
|
||||
* 2. 支持动态行数的货品明细/客户配送明细解析
|
||||
* 3. 自动处理文本型数字转换(String→Integer/BigDecimal)
|
||||
* 4. 完整的异常处理和日志记录
|
||||
*/
|
||||
public class DynamicDeliveryExcelListener extends AnalysisEventListener<Map<String, Object>> {
|
||||
// 日志实例
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(DynamicDeliveryExcelListener.class);
|
||||
|
||||
// ---------------------- 常量定义(便于维护) ----------------------
|
||||
// 正则表达式:匹配整数(支持正负数)
|
||||
private static final Pattern INTEGER_PATTERN = Pattern.compile("-?\\d+");
|
||||
// 正则表达式:匹配小数(支持正负数和整数形式)
|
||||
private static final Pattern DECIMAL_PATTERN = Pattern.compile("-?\\d+(\\.\\d+)?");
|
||||
// 关键字定义(Excel标签匹配)
|
||||
private static final String KEYWORD_DELIVERY_DATE = "送貨日期";
|
||||
private static final String KEYWORD_PRODUCT_DETAIL = "货品明细";
|
||||
private static final String KEYWORD_TOTAL_RECORD = "紀錄合共";
|
||||
private static final String KEYWORD_CUSTOMER_DETAIL = "客户配送明细";
|
||||
private static final String KEYWORD_INVOICE_COUNT = "發票張數";
|
||||
private static final String KEYWORD_TOTAL_COUNT = "總計";
|
||||
private static final String KEYWORD_SUBTOTAL = "小計";
|
||||
// 支持的日期格式(String转Date)
|
||||
private static final String[] SUPPORTED_DATE_FORMATS = {"yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd", "yyyy-MM-dd HH:mm:ss"};
|
||||
|
||||
// ---------------------- 数据存储(解析结果) ----------------------
|
||||
private DeliveryHeader deliveryHeader = new DeliveryHeader();
|
||||
private List<ProductDetail> productDetailList = new ArrayList<>();
|
||||
private List<CustomerDeliveryDetail> customerDeliveryDetailList = new ArrayList<>();
|
||||
|
||||
// ---------------------- 解析状态管理(动态切换) ----------------------
|
||||
public enum ParseStatus {
|
||||
IDLE, // 空闲状态(未进入任何表格)
|
||||
PRODUCT_DETAIL,// 货品明细解析状态
|
||||
CUSTOMER_DETAIL// 客户配送明细解析状态
|
||||
}
|
||||
private ParseStatus currentStatus = ParseStatus.IDLE;
|
||||
|
||||
// ---------------------- 核心解析方法(EasyExcel回调) ----------------------
|
||||
@Override
|
||||
public void invoke(Map<String, Object> data, AnalysisContext context) {
|
||||
try {
|
||||
int rowNum = context.readRowHolder().getRowIndex() + 1;
|
||||
LOGGER.debug("第{}行:开始解析,所有单元格数据:{}", rowNum, data);
|
||||
|
||||
// 1. 获取第一列数据(用于状态判断,标签通常在第一列)
|
||||
String firstCellValue = getFirstCellValue(data);
|
||||
LOGGER.debug("第{}行:第一列数据(状态判断依据):{}", rowNum, firstCellValue);
|
||||
|
||||
// 2. 状态切换判断(传递完整data,支持多单元格解析)
|
||||
if (isStatusSwitchTrigger(firstCellValue)) {
|
||||
switchStatus(firstCellValue, rowNum, data);
|
||||
return;
|
||||
}
|
||||
|
||||
// 3. 根据当前状态解析对应表格数据
|
||||
switch (currentStatus) {
|
||||
case PRODUCT_DETAIL:
|
||||
if (isValidProductDetailRow(data, firstCellValue)) {
|
||||
parseProductDetail(data, rowNum);
|
||||
}
|
||||
break;
|
||||
case CUSTOMER_DETAIL:
|
||||
if (isValidCustomerDetailRow(data, firstCellValue)) {
|
||||
parseCustomerDeliveryDetail(data, rowNum);
|
||||
}
|
||||
break;
|
||||
case IDLE:
|
||||
// 空闲状态:解析表头信息(送货日期行,多单元格数据)
|
||||
if (firstCellValue.contains(KEYWORD_DELIVERY_DATE)) {
|
||||
parseHeaderInfo(data, rowNum);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
} catch (ExcelDataConvertException e) {
|
||||
// Excel内置转换异常(如日期格式错误)
|
||||
int rowNum = context.readRowHolder().getRowIndex() + 1;
|
||||
LOGGER.error("第{}行:Excel数据转换异常,列号:{},列名:{}",
|
||||
rowNum, e.getColumnIndex() + 1, getColumnNameByIndex(data, e.getColumnIndex()), e);
|
||||
throw new RuntimeException("Excel数据转换异常(行:" + rowNum + ",列:" + (e.getColumnIndex() + 1) + ")", e);
|
||||
} catch (Exception e) {
|
||||
// 其他解析异常
|
||||
int rowNum = context.readRowHolder().getRowIndex() + 1;
|
||||
LOGGER.error("第{}行:Excel解析异常,所有单元格数据:{}", rowNum, data, e);
|
||||
throw new RuntimeException("Excel解析异常(行:" + rowNum + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- 解析完成回调 ----------------------
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
LOGGER.info("Excel解析全部完成!最终统计结果:");
|
||||
LOGGER.info("1. 表头信息:送货日期={},发票张数={},总记录数={},小计金额={}",
|
||||
deliveryHeader.getDeliveryDate(),
|
||||
deliveryHeader.getInvoiceCount(),
|
||||
deliveryHeader.getTotalRecordCount(),
|
||||
deliveryHeader.getSubtotalAmount());
|
||||
LOGGER.info("2. 货品明细:共{}条记录", productDetailList.size());
|
||||
LOGGER.info("3. 客户配送明细:共{}条记录", customerDeliveryDetailList.size());
|
||||
}
|
||||
|
||||
// ---------------------- 状态管理方法(传递完整data) ----------------------
|
||||
/**
|
||||
* 判断是否触发状态切换(根据第一列标签关键字)
|
||||
*/
|
||||
private boolean isStatusSwitchTrigger(String firstCellValue) {
|
||||
return firstCellValue.contains(KEYWORD_PRODUCT_DETAIL)
|
||||
|| firstCellValue.contains(KEYWORD_TOTAL_RECORD)
|
||||
|| firstCellValue.contains(KEYWORD_CUSTOMER_DETAIL)
|
||||
|| firstCellValue.contains(KEYWORD_INVOICE_COUNT);
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换解析状态(核心:传递完整data,支持多单元格解析)
|
||||
*/
|
||||
private void switchStatus(String firstCellValue, int rowNum, Map<String, Object> data) {
|
||||
if (firstCellValue.contains(KEYWORD_PRODUCT_DETAIL)) {
|
||||
currentStatus = ParseStatus.PRODUCT_DETAIL;
|
||||
LOGGER.info("第{}行:检测到【{}】标签,切换到【货品明细】解析状态", rowNum, KEYWORD_PRODUCT_DETAIL);
|
||||
} else if (firstCellValue.contains(KEYWORD_TOTAL_RECORD)) {
|
||||
currentStatus = ParseStatus.IDLE;
|
||||
parseTotalRecord(data, rowNum); // 解析纪录合共(多单元格)
|
||||
LOGGER.info("第{}行:检测到【{}】标签,切换到【空闲】状态,已解析货品明细{}条",
|
||||
rowNum, KEYWORD_TOTAL_RECORD, productDetailList.size());
|
||||
} else if (firstCellValue.contains(KEYWORD_CUSTOMER_DETAIL)) {
|
||||
currentStatus = ParseStatus.CUSTOMER_DETAIL;
|
||||
LOGGER.info("第{}行:检测到【{}】标签,切换到【客户配送明细】解析状态", rowNum, KEYWORD_CUSTOMER_DETAIL);
|
||||
} else if (firstCellValue.contains(KEYWORD_INVOICE_COUNT)) {
|
||||
currentStatus = ParseStatus.IDLE;
|
||||
parseInvoiceCount(data, rowNum); // 解析发票张数(多单元格,核心修复)
|
||||
LOGGER.info("第{}行:检测到【{}】标签,切换到【空闲】状态,已解析客户配送明细{}条",
|
||||
rowNum, KEYWORD_INVOICE_COUNT, customerDeliveryDetailList.size());
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- 数据有效性校验方法 ----------------------
|
||||
/**
|
||||
* 校验货品明细行是否有效(排除表头和空行)
|
||||
*/
|
||||
private boolean isValidProductDetailRow(Map<String, Object> data, String firstCellValue) {
|
||||
// 有效条件:1.货品编号(第一列)不为空 2.不是表头行(表头第一列是"貨品編號")
|
||||
Object productCode = getValueSafely(data, 0);
|
||||
return productCode != null
|
||||
&& !"貨品編號".equals(productCode.toString().trim())
|
||||
&& !productCode.toString().trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验客户配送明细行是否有效(排除表头和空行)
|
||||
*/
|
||||
private boolean isValidCustomerDetailRow(Map<String, Object> data, String firstCellValue) {
|
||||
// 有效条件:1.类别(第一列)不为空 2.不是表头行(表头第一列是"類别")
|
||||
Object category = getValueSafely(data, 0);
|
||||
return category != null
|
||||
&& !"類别".equals(category.toString().trim())
|
||||
&& !category.toString().trim().isEmpty();
|
||||
}
|
||||
|
||||
// ---------------------- 具体数据解析方法(全部支持多单元格) ----------------------
|
||||
/**
|
||||
* 解析表头信息(送货日期、送货线号、车次)
|
||||
* 列对应关系:0=送貨日期标签,1=送貨日期值,2=送貨線號标签,3=送貨線號值,4=車次标签,5=車次值
|
||||
*/
|
||||
private void parseHeaderInfo(Map<String, Object> data, int rowNum) {
|
||||
try {
|
||||
// 读取多单元格数据(标签在左,数值在右)
|
||||
Date deliveryDate = getValueSafely(data, 1, Date.class); // 第2列:送货日期值
|
||||
String deliveryLineNo = getValueSafely(data, 3, String.class); // 第4列:送货线号值
|
||||
Integer trainNumber = getValueSafely(data, 5, Integer.class); // 第6列:车次值
|
||||
|
||||
// 赋值(空值处理)
|
||||
if (deliveryDate != null) {
|
||||
deliveryHeader.setDeliveryDate(deliveryDate);
|
||||
}
|
||||
deliveryHeader.setDeliveryLineNo(deliveryLineNo);
|
||||
deliveryHeader.setTrainNumber(getDefaultValue(trainNumber, 0));
|
||||
|
||||
LOGGER.debug("第{}行:解析表头信息完成,送货日期={},送货线号={},车次={}",
|
||||
rowNum, deliveryHeader.getDeliveryDate(),
|
||||
deliveryHeader.getDeliveryLineNo(), deliveryHeader.getTrainNumber());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("第{}行:解析表头信息失败,所有单元格数据:{}", rowNum, data, e);
|
||||
throw new RuntimeException("解析表头信息失败(行:" + rowNum + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析纪录合共(多单元格版)
|
||||
* 列对应关系:0=紀錄合共标签,1=总记录数值,4=總計标签,5=总箱数值,6=总支数值
|
||||
*/
|
||||
private void parseTotalRecord(Map<String, Object> data, int rowNum) {
|
||||
try {
|
||||
// 1. 验证是否为纪录合共行(第一列包含标签)
|
||||
Object totalRecordLabel = getValueSafely(data, 0, String.class);
|
||||
if (totalRecordLabel == null || !totalRecordLabel.toString().trim().contains(KEYWORD_TOTAL_RECORD)) {
|
||||
LOGGER.warn("第{}行:不是纪录合共行,跳过解析,第一列内容:{}", rowNum, totalRecordLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 读取多单元格数值(标签右侧对应列)
|
||||
Integer totalRecordCount = getValueSafely(data, 1, Integer.class); // 第2列:总记录数
|
||||
Integer totalBoxCount = getValueSafely(data, 5, Integer.class); // 第6列:总箱数
|
||||
Integer totalPieceCount = getValueSafely(data, 6, Integer.class); // 第7列:总支数
|
||||
|
||||
// 3. 赋值与日志
|
||||
deliveryHeader.setTotalRecordCount(getDefaultValue(totalRecordCount, 0));
|
||||
deliveryHeader.setTotalBoxCount(getDefaultValue(totalBoxCount, 0));
|
||||
deliveryHeader.setTotalPieceCount(getDefaultValue(totalPieceCount, 0));
|
||||
|
||||
LOGGER.debug("第{}行:解析纪录合共完成,总记录数={},总箱数={},总支数={}",
|
||||
rowNum, deliveryHeader.getTotalRecordCount(),
|
||||
deliveryHeader.getTotalBoxCount(), deliveryHeader.getTotalPieceCount());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("第{}行:解析纪录合共失败,所有单元格数据:{}", rowNum, data, e);
|
||||
throw new RuntimeException("解析纪录合共失败(行:" + rowNum + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 核心修复:解析发票张数(多单元格版,正确读取右侧单元格)
|
||||
* 列对应关系:
|
||||
* - 0=發票張數标签列(A列),1=发票张数数值列(B列)
|
||||
* - 4=小計标签列(E列),5=小计箱数列(F列),6=小计支数列(G列),7=小计金额列(H列)
|
||||
*/
|
||||
private void parseInvoiceCount(Map<String, Object> data, int rowNum) {
|
||||
try {
|
||||
// 1. 验证是否为发票张数行(第一列包含标签)
|
||||
Object invoiceLabel = getValueSafely(data, 0, String.class);
|
||||
if (invoiceLabel == null || !invoiceLabel.toString().trim().contains(KEYWORD_INVOICE_COUNT)) {
|
||||
LOGGER.warn("第{}行:不是发票张数行,跳过解析,第一列内容:{}", rowNum, invoiceLabel);
|
||||
return;
|
||||
}
|
||||
|
||||
// 2. 解析发票张数(标签右侧第1列:B列,索引1)
|
||||
Integer invoiceCount = getValueSafely(data, 1, Integer.class);
|
||||
deliveryHeader.setInvoiceCount(getDefaultValue(invoiceCount, 0));
|
||||
LOGGER.debug("第{}行:解析发票张数,标签列(A列):{},数值列(B列):{}",
|
||||
rowNum, invoiceLabel, deliveryHeader.getInvoiceCount());
|
||||
|
||||
// 3. 解析小计信息(标签在E列,数值在F/G/H列)
|
||||
Object subtotalLabel = getValueSafely(data, 3, String.class); // E列:小計标签
|
||||
if (subtotalLabel != null && subtotalLabel.toString().trim().contains(KEYWORD_SUBTOTAL)) {
|
||||
Integer subtotalBoxCount = getValueSafely(data, 4, Integer.class); // F列:小计箱数
|
||||
Integer subtotalPieceCount = getValueSafely(data, 5, Integer.class); // G列:小计支数
|
||||
BigDecimal subtotalAmount = getValueSafely(data, 6, BigDecimal.class); // H列:小计金额
|
||||
|
||||
// 赋值(空值处理)
|
||||
deliveryHeader.setSubtotalBoxCount(getDefaultValue(subtotalBoxCount, 0));
|
||||
deliveryHeader.setSubtotalPieceCount(getDefaultValue(subtotalPieceCount, 0));
|
||||
deliveryHeader.setSubtotalAmount(getDefaultValue(subtotalAmount, BigDecimal.ZERO));
|
||||
|
||||
LOGGER.debug("第{}行:解析小计信息,标签列(E列):{},箱数列(F列):{},支数列(G列):{},金额列(H列):{}",
|
||||
rowNum, subtotalLabel,
|
||||
deliveryHeader.getSubtotalBoxCount(),
|
||||
deliveryHeader.getSubtotalPieceCount(),
|
||||
deliveryHeader.getSubtotalAmount());
|
||||
} else {
|
||||
LOGGER.warn("第{}行:未找到小计标签(E列),或标签内容不匹配,跳过小计解析", rowNum);
|
||||
deliveryHeader.setSubtotalBoxCount(0);
|
||||
deliveryHeader.setSubtotalPieceCount(0);
|
||||
deliveryHeader.setSubtotalAmount(BigDecimal.ZERO);
|
||||
}
|
||||
|
||||
// 4. 解析完成日志
|
||||
LOGGER.debug("第{}行:解析发票张数行完成,最终结果:发票张数={},小计金额={}",
|
||||
rowNum, deliveryHeader.getInvoiceCount(), deliveryHeader.getSubtotalAmount());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("第{}行:解析发票张数失败,所有单元格数据:{}", rowNum, data, e);
|
||||
throw new RuntimeException("解析发票张数失败(行:" + rowNum + "),请检查Excel列对应关系", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析货品明细(多单元格,动态行数适配)
|
||||
* 列对应关系:0=貨品編號,1=簡稱,4=箱,5=支
|
||||
*/
|
||||
private void parseProductDetail(Map<String, Object> data, int rowNum) {
|
||||
try {
|
||||
ProductDetail productDetail = new ProductDetail();
|
||||
// 读取对应列的多单元格数据
|
||||
String productCode = getValueSafely(data, 0, String.class); // 第1列:货品编号
|
||||
String productName = getValueSafely(data, 1, String.class); // 第2列:货品简称
|
||||
Integer boxCount = getValueSafely(data, 4, Integer.class); // 第5列:箱数
|
||||
Integer pieceCount = getValueSafely(data, 5, Integer.class); // 第6列:支数
|
||||
|
||||
// 赋值(空值处理+去空格)
|
||||
productDetail.setProductCode(getDefaultValue(productCode, "").trim());
|
||||
productDetail.setProductName(getDefaultValue(productName, "").trim());
|
||||
productDetail.setBoxCount(getDefaultValue(boxCount, 0));
|
||||
productDetail.setPieceCount(getDefaultValue(pieceCount, 0));
|
||||
|
||||
// 添加到列表
|
||||
productDetailList.add(productDetail);
|
||||
LOGGER.debug("第{}行:解析货品明细完成,货品编号={},名称={},箱数={},支数={}",
|
||||
rowNum, productDetail.getProductCode(), productDetail.getProductName(),
|
||||
productDetail.getBoxCount(), productDetail.getPieceCount());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("第{}行:解析货品明细失败,所有单元格数据:{}", rowNum, data, e);
|
||||
throw new RuntimeException("解析货品明细失败(行:" + rowNum + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析客户配送明细(多单元格,动态行数适配)
|
||||
* 列对应关系:0=類别,1=發票編號,2=客户編號,3=名稱,4=箱,5=包,6=金額
|
||||
*/
|
||||
private void parseCustomerDeliveryDetail(Map<String, Object> data, int rowNum) {
|
||||
try {
|
||||
CustomerDeliveryDetail customerDetail = new CustomerDeliveryDetail();
|
||||
// 读取对应列的多单元格数据
|
||||
String category = getValueSafely(data, 0, String.class); // 第1列:类别
|
||||
String invoiceNo = getValueSafely(data, 1, String.class); // 第2列:发票编号
|
||||
String customerCode = getValueSafely(data, 2, String.class); // 第3列:客户编号
|
||||
String customerName = getValueSafely(data, 3, String.class); // 第4列:客户名称
|
||||
Integer boxCount = getValueSafely(data, 4, Integer.class); // 第5列:箱数
|
||||
Integer packageCount = getValueSafely(data, 5, Integer.class); // 第6列:包数
|
||||
BigDecimal amount = getValueSafely(data, 6, BigDecimal.class); // 第7列:金额
|
||||
|
||||
// 赋值(空值处理+去空格)
|
||||
customerDetail.setCategory(getDefaultValue(category, "").trim());
|
||||
customerDetail.setInvoiceNo(getDefaultValue(invoiceNo, "").trim());
|
||||
customerDetail.setCustomerCode(getDefaultValue(customerCode, "").trim());
|
||||
customerDetail.setCustomerName(getDefaultValue(customerName, "").trim());
|
||||
customerDetail.setBoxCount(getDefaultValue(boxCount, 0));
|
||||
customerDetail.setPackageCount(getDefaultValue(packageCount, 0));
|
||||
customerDetail.setAmount(getDefaultValue(amount, BigDecimal.ZERO));
|
||||
|
||||
// 添加到列表
|
||||
customerDeliveryDetailList.add(customerDetail);
|
||||
LOGGER.debug("第{}行:解析客户配送明细完成,客户编号={},名称={},金额={}",
|
||||
rowNum, customerDetail.getCustomerCode(), customerDetail.getCustomerName(),
|
||||
customerDetail.getAmount());
|
||||
} catch (Exception e) {
|
||||
LOGGER.error("第{}行:解析客户配送明细失败,所有单元格数据:{}", rowNum, data, e);
|
||||
throw new RuntimeException("解析客户配送明细失败(行:" + rowNum + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
// ---------------------- 核心工具方法(支持多单元格+类型转换) ----------------------
|
||||
/**
|
||||
* 获取第一列数据(用于状态判断)
|
||||
*/
|
||||
private String getFirstCellValue(Map<String, Object> data) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
return "";
|
||||
}
|
||||
Object firstValue = data.values().iterator().next();
|
||||
return firstValue != null ? firstValue.toString().trim() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据列索引获取列名(用于异常定位)
|
||||
*/
|
||||
private String getColumnNameByIndex(Map<String, Object> data, int columnIndex) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
return "未知列";
|
||||
}
|
||||
int index = 0;
|
||||
for (String key : data.keySet()) {
|
||||
if (index == columnIndex) {
|
||||
return key;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
return "第" + (columnIndex + 1) + "列";
|
||||
}
|
||||
|
||||
/**
|
||||
* 按列索引安全获取原始值(不做类型转换)
|
||||
*/
|
||||
private Object getValueSafely(Map<String, Object> data, int columnIndex) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
int index = 0;
|
||||
for (Object value : data.values()) {
|
||||
if (index == columnIndex) {
|
||||
return value;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
LOGGER.warn("列索引{}超出当前行单元格数量({}列),返回null", columnIndex, data.size());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 按列索引安全获取值(支持多类型转换,核心工具)
|
||||
* 功能:1. 直接类型匹配 2. String转数字/日期 3. 数字类型间转换
|
||||
*/
|
||||
private <T> T getValueSafely(Map<String, Object> data, int columnIndex, Class<T> expectedType) {
|
||||
Object value = getValueSafely(data, columnIndex);
|
||||
if (value == null) {
|
||||
LOGGER.debug("列索引{}:单元格值为null,返回null", columnIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// 1. 直接类型匹配
|
||||
if (expectedType.isInstance(value)) {
|
||||
return expectedType.cast(value);
|
||||
}
|
||||
|
||||
// 2. String类型转目标类型(核心:处理文本型数字)
|
||||
if (value instanceof String) {
|
||||
String strValue = ((String) value).trim();
|
||||
if (strValue.isEmpty()) {
|
||||
LOGGER.debug("列索引{}:单元格值为空字符串,返回null", columnIndex);
|
||||
return null;
|
||||
}
|
||||
|
||||
// String → Integer
|
||||
if (expectedType == Integer.class) {
|
||||
try {
|
||||
return expectedType.cast(Integer.parseInt(strValue));
|
||||
} catch (NumberFormatException e) {
|
||||
LOGGER.warn("列索引{}:String转Integer失败,原始值:{}", columnIndex, strValue, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// String → Long
|
||||
if (expectedType == Long.class) {
|
||||
try {
|
||||
return expectedType.cast(Long.parseLong(strValue));
|
||||
} catch (NumberFormatException e) {
|
||||
LOGGER.warn("列索引{}:String转Long失败,原始值:{}", columnIndex, strValue, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// String → BigDecimal(支持千分位符号,如"1,234.56")
|
||||
if (expectedType == BigDecimal.class) {
|
||||
try {
|
||||
String cleanValue = strValue.replace(",", ""); // 去除千分位逗号
|
||||
return expectedType.cast(new BigDecimal(cleanValue));
|
||||
} catch (NumberFormatException e) {
|
||||
LOGGER.warn("列索引{}:String转BigDecimal失败,原始值:{}", columnIndex, strValue, e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// String → Date(支持多种日期格式)
|
||||
if (expectedType == Date.class) {
|
||||
try {
|
||||
return expectedType.cast(DateUtils.parseDate(strValue, SUPPORTED_DATE_FORMATS));
|
||||
} catch (ParseException e) {
|
||||
LOGGER.warn("列索引{}:String转Date失败,原始值:{},支持格式:{}",
|
||||
columnIndex, strValue, Arrays.toString(SUPPORTED_DATE_FORMATS), e);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. 数字类型间转换(如Double→Integer,Long→BigDecimal)
|
||||
if (value instanceof Number) {
|
||||
Number numValue = (Number) value;
|
||||
if (expectedType == Integer.class) {
|
||||
return expectedType.cast(numValue.intValue());
|
||||
}
|
||||
if (expectedType == Long.class) {
|
||||
return expectedType.cast(numValue.longValue());
|
||||
}
|
||||
if (expectedType == BigDecimal.class) {
|
||||
return expectedType.cast(new BigDecimal(numValue.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
// 4. 不支持的转换
|
||||
LOGGER.warn("列索引{}:不支持的类型转换,期望类型:{},实际类型:{},原始值:{}",
|
||||
columnIndex, expectedType.getSimpleName(), value.getClass().getSimpleName(), value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 空值处理:返回默认值
|
||||
*/
|
||||
private <T> T getDefaultValue(T value, T defaultValue) {
|
||||
return value != null ? value : defaultValue;
|
||||
}
|
||||
|
||||
// ---------------------- Getter方法(供Service层获取解析结果) ----------------------
|
||||
public DeliveryHeader getDeliveryHeader() {
|
||||
return deliveryHeader;
|
||||
}
|
||||
|
||||
public List<ProductDetail> getProductDetailList() {
|
||||
return productDetailList;
|
||||
}
|
||||
|
||||
public List<CustomerDeliveryDetail> getCustomerDeliveryDetailList() {
|
||||
return customerDeliveryDetailList;
|
||||
}
|
||||
}
|
||||
+259
@@ -0,0 +1,259 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.listener;
|
||||
|
||||
import com.alibaba.excel.context.AnalysisContext;
|
||||
import com.alibaba.excel.event.AnalysisEventListener;
|
||||
import com.alibaba.excel.exception.ExcelDataConvertException;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.StockInHeader;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.StockInProductDetail;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.text.ParseException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 入库单Excel解析监听器
|
||||
* 功能:1. 解析第一行表头数据 2. 解析第二行开始的产品明细 3. 支持文本型数字转换
|
||||
*/
|
||||
public class StockInExcelListener extends AnalysisEventListener<Map<String, Object>> {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(StockInExcelListener.class);
|
||||
|
||||
// 存储解析结果
|
||||
private final StockInHeader stockInHeader = new StockInHeader();
|
||||
private final List<StockInProductDetail> productDetailList = new ArrayList<>();
|
||||
|
||||
// 支持的日期格式(用于String转Date)
|
||||
private static final String[] SUPPORTED_DATE_FORMATS = {
|
||||
"yyyy-MM-dd", "yyyy/MM/dd", "yyyyMMdd", "yyyy-MM-dd HH:mm:ss"
|
||||
};
|
||||
|
||||
// 行号标记(用于区分第一行和表格行)
|
||||
private int currentRowNum = 0;
|
||||
|
||||
@Override
|
||||
public void invoke(Map<String, Object> data, AnalysisContext context) {
|
||||
currentRowNum = context.readRowHolder().getRowIndex() + 1; // 行号从1开始
|
||||
try {
|
||||
LOGGER.debug("第{}行解析开始,数据:{}", currentRowNum, data);
|
||||
|
||||
// 1. 解析第一行:表头数据(入库日期、OrderNO)
|
||||
if (currentRowNum == 1) {
|
||||
parseHeaderData(data);
|
||||
}
|
||||
// 2. 解析第二行及以后:产品明细(跳过表头行:第2行是表格列名)
|
||||
else if (currentRowNum >= 3) {
|
||||
if (isValidProductRow(data)) {
|
||||
StockInProductDetail detail = parseProductDetail(data);
|
||||
productDetailList.add(detail);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (ExcelDataConvertException e) {
|
||||
// Excel内置转换异常(如日期格式错误)
|
||||
LOGGER.error("第{}行数据转换异常,列号:{},列名:{}",
|
||||
currentRowNum, e.getColumnIndex() + 1, getColumnNameByIndex(data, e.getColumnIndex()), e);
|
||||
throw new RuntimeException("第" + currentRowNum + "行列" + (e.getColumnIndex() + 1) + "数据格式错误", e);
|
||||
} catch (Exception e) {
|
||||
// 其他解析异常
|
||||
LOGGER.error("第{}行解析异常,数据:{}", currentRowNum, data, e);
|
||||
throw new RuntimeException("第" + currentRowNum + "行数据解析失败", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析第一行表头数据
|
||||
* 列对应关系:0=入库日期标签,1=入库日期值,2=OrderNO标签,3=OrderNO值
|
||||
*/
|
||||
private void parseHeaderData(Map<String, Object> data) {
|
||||
// 入库日期(第2列,索引1)
|
||||
Object stockInDateObj = getValueSafely(data, 1);
|
||||
if (stockInDateObj != null) {
|
||||
Date stockInDate = convertToDate(stockInDateObj);
|
||||
stockInHeader.setStockInDate(stockInDate);
|
||||
LOGGER.debug("第1行:入库日期解析完成,值:{}", stockInDate);
|
||||
}
|
||||
|
||||
// OrderNO(第4列,索引3)
|
||||
Object orderNoObj = getValueSafely(data, 3);
|
||||
if (orderNoObj != null) {
|
||||
String orderNo = orderNoObj.toString().trim();
|
||||
stockInHeader.setOrderNo(orderNo);
|
||||
LOGGER.debug("第1行:OrderNO解析完成,值:{}", orderNo);
|
||||
}
|
||||
|
||||
// 校验表头数据完整性
|
||||
if (stockInHeader.getStockInDate() == null || stockInHeader.getOrderNo().isEmpty()) {
|
||||
LOGGER.warn("第1行表头数据不完整,入库日期:{},OrderNO:{}",
|
||||
stockInHeader.getStockInDate(), stockInHeader.getOrderNo());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析产品明细数据(一行对应一个产品)
|
||||
*/
|
||||
private StockInProductDetail parseProductDetail(Map<String, Object> data) {
|
||||
StockInProductDetail detail = new StockInProductDetail();
|
||||
|
||||
// 产品编号(第1列,索引0)- 支持文本型数字转换
|
||||
detail.setProductCode(convertToInteger(getValueSafely(data, 0)));
|
||||
// 产品名称(第2列,索引1)
|
||||
detail.setProductName(convertToString(getValueSafely(data, 1)));
|
||||
// 箱含量(第5列,索引4)
|
||||
detail.setBoxCapacity(convertToInteger(getValueSafely(data, 4)));
|
||||
// 件数(第6列,索引5)
|
||||
detail.setPieceCount(convertToInteger(getValueSafely(data, 5)));
|
||||
// 箱数(第7列,索引6)
|
||||
detail.setBoxCount(convertToInteger(getValueSafely(data, 6)));
|
||||
// 饮用日期(第8列,索引7)
|
||||
detail.setDrinkDate(convertToDate(getValueSafely(data, 7)));
|
||||
|
||||
LOGGER.debug("第{}行产品明细解析完成,产品编号:{},产品名称:{}",
|
||||
currentRowNum, detail.getProductCode(), detail.getProductName());
|
||||
return detail;
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验产品行是否有效(排除空行和合计行)
|
||||
*/
|
||||
private boolean isValidProductRow(Map<String, Object> data) {
|
||||
// 有效条件:产品编号不为空 + 不是合计行(合计行产品编号为null,且包含"Total")
|
||||
Object productCodeObj = getValueSafely(data, 0);
|
||||
Object productNameObj = getValueSafely(data, 1);
|
||||
|
||||
// 排除合计行(如第7行:Total:68)
|
||||
if (productNameObj != null && productNameObj.toString().contains("Total")) {
|
||||
LOGGER.debug("第{}行是合计行,跳过解析", currentRowNum);
|
||||
return false;
|
||||
}
|
||||
|
||||
// 排除空行(产品编号为空)
|
||||
return productCodeObj != null && !productCodeObj.toString().trim().isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* 解析完成回调
|
||||
*/
|
||||
@Override
|
||||
public void doAfterAllAnalysed(AnalysisContext context) {
|
||||
LOGGER.info("Excel解析全部完成!解析结果:");
|
||||
LOGGER.info("1. 表头信息:入库日期={},OrderNO={}",
|
||||
stockInHeader.getStockInDate(), stockInHeader.getOrderNo());
|
||||
LOGGER.info("2. 产品明细:共{}条记录", productDetailList.size());
|
||||
}
|
||||
|
||||
// ---------------------- 工具方法(类型转换+安全取值) ----------------------
|
||||
/**
|
||||
* 按列索引安全获取值(支持列索引越界处理)
|
||||
*/
|
||||
private Object getValueSafely(Map<String, Object> data, int columnIndex) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (Object value : data.values()) {
|
||||
if (index == columnIndex) {
|
||||
return value;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
LOGGER.warn("第{}行列索引{}超出范围(当前行共{}列),返回null",
|
||||
currentRowNum, columnIndex, data.size());
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据列索引获取列名(用于异常定位)
|
||||
*/
|
||||
private String getColumnNameByIndex(Map<String, Object> data, int columnIndex) {
|
||||
if (data == null || data.isEmpty()) {
|
||||
return "未知列";
|
||||
}
|
||||
|
||||
int index = 0;
|
||||
for (String key : data.keySet()) {
|
||||
if (index == columnIndex) {
|
||||
return key;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
return "第" + (columnIndex + 1) + "列";
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用转换:Object转String
|
||||
*/
|
||||
private String convertToString(Object value) {
|
||||
if (value == null) {
|
||||
return "";
|
||||
}
|
||||
return value.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用转换:Object转Integer(支持文本型数字、Number类型)
|
||||
*/
|
||||
private Integer convertToInteger(Object value) {
|
||||
if (value == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
try {
|
||||
// 文本型数字(如String"1741")
|
||||
if (value instanceof String) {
|
||||
String strValue = ((String) value).trim();
|
||||
return strValue.isEmpty() ? 0 : Integer.parseInt(strValue);
|
||||
}
|
||||
// Number类型(如Double、Long)
|
||||
if (value instanceof Number) {
|
||||
return ((Number) value).intValue();
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
LOGGER.warn("值转换为Integer失败,值:{},返回0", value, e);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用转换:Object转Date(支持Date类型、String类型)
|
||||
*/
|
||||
private Date convertToDate(Object value) {
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// 直接是Date类型
|
||||
if (value instanceof Date) {
|
||||
return (Date) value;
|
||||
}
|
||||
|
||||
// String类型转Date(支持多种格式)
|
||||
if (value instanceof String) {
|
||||
String strValue = ((String) value).trim();
|
||||
try {
|
||||
return DateUtils.parseDate(strValue, SUPPORTED_DATE_FORMATS);
|
||||
} catch (ParseException e) {
|
||||
LOGGER.warn("值转换为Date失败,值:{},支持格式:{}",
|
||||
strValue, String.join(",", SUPPORTED_DATE_FORMATS), e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// ---------------------- Getter方法(供Service层获取解析结果) ----------------------
|
||||
public StockInHeader getStockInHeader() {
|
||||
return stockInHeader;
|
||||
}
|
||||
|
||||
public List<StockInProductDetail> getProductDetailList() {
|
||||
return productDetailList;
|
||||
}
|
||||
}
|
||||
+2
@@ -27,6 +27,8 @@ public interface ReservationStockInOrderMapper extends BaseMapper<ReservationSto
|
||||
|
||||
public MaterialBaseInfoPO getinfo(@Param("id") Long id);
|
||||
|
||||
public MaterialBaseInfoPO getByName(@Param("name") String name);
|
||||
|
||||
public List<MaterialBaseInfoPO> getMaterialBaseInfoList(@Param("id") String id);
|
||||
|
||||
public MaterialWarehouseControlPO getInfoByMaterialBaseInfoIds(@Param("id") Long id);
|
||||
|
||||
+438
-13
@@ -1,15 +1,51 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.persistence;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.json.JSONUtil;
|
||||
import com.alibaba.excel.EasyExcel;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson2.JSONObject;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.mhd.common.core.domain.po.UserPo;
|
||||
import com.mhd.common.core.enums.DictCode;
|
||||
import com.mhd.common.core.exception.ServiceException;
|
||||
import com.mhd.common.core.utils.OrderSequence;
|
||||
import com.mhd.common.core.utils.StringUtils;
|
||||
import com.mhd.common.core.web.domain.AjaxResult;
|
||||
import com.mhd.common.security.utils.SecurityUtils;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.facade.IReservationDeliveryDetailsLinkService;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.facade.IReservationInMaterialDetailService;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.po.ReservationInMaterialDetailPO;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.todo.ReservationInMaterialDetailDO;
|
||||
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.facade.IReservationOutMaterialDetailService;
|
||||
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.todo.ReservationOutMaterialDetailDO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.entity.ReservationStockInOrder;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.facade.IReservationStockInOrderService;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.listener.DeliveryExcelListener;
|
||||
//import com.mhd.oms.domain.reservationStockInOrder.repository.listener.DeliveryExcelListener;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.listener.DynamicDeliveryExcelListener;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.listener.StockInExcelListener;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.mapper.ReservationStockInOrderMapper;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStockInOrderPO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.DeliveryDataDTO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.*;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.entity.ReservationStockOutOrder;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.facade.IReservationStockOutOrderService;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.mapper.ReservationStockOutOrderMapper;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.repository.todo.ReservationStockOutOrderDO;
|
||||
import com.mhd.oms.domain.reservationStockOutOrder.service.ReservationStockOutOrderApplicationService;
|
||||
import com.mhd.system.api.SystemServiceFeign;
|
||||
import com.mhd.system.api.UserServiceFeign;
|
||||
import com.mhd.system.api.domain.SysDictData;
|
||||
import com.mhd.system.api.domain.WarehouseFeignPO;
|
||||
import com.mhd.system.api.domain.cache.AssociationWarehouseCacheDO;
|
||||
import com.mhd.system.api.domain.cache.SystemServiceCacheUtil;
|
||||
import com.mhd.system.api.model.LoginUser;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
@@ -17,8 +53,9 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.math.BigDecimal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* 入库单Service业务层处理
|
||||
@@ -30,6 +67,22 @@ import java.util.List;
|
||||
public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInOrderMapper, ReservationStockInOrder> implements IReservationStockInOrderService {
|
||||
@Autowired
|
||||
private ReservationStockInOrderMapper stockInOrderMapper;
|
||||
@Autowired
|
||||
private ReservationStockOutOrderMapper stockOutOrderMapper;
|
||||
@Autowired
|
||||
private IReservationDeliveryDetailsLinkService reservationDeliveryDetailsLinkService;
|
||||
@Autowired
|
||||
private IReservationStockOutOrderService reservationStockOutOrderService;
|
||||
@Autowired
|
||||
private IReservationOutMaterialDetailService reservationOutMaterialDetailService;
|
||||
@Autowired
|
||||
private ReservationStockOutOrderApplicationService reservationStockOutOrderApplicationService;
|
||||
@Autowired
|
||||
private UserServiceFeign userServiceFeign;
|
||||
@Autowired
|
||||
private SystemServiceFeign systemServiceFeign;
|
||||
@Autowired
|
||||
private IReservationInMaterialDetailService materialDetailService;
|
||||
|
||||
/**
|
||||
* 查询入库单列表
|
||||
@@ -100,33 +153,405 @@ public class ReservationStockInOrderImpl extends ServiceImpl<ReservationStockInO
|
||||
|
||||
@Override
|
||||
public DeliveryDataDTO parseExcelFile(MultipartFile file, String sheetName) throws Exception {
|
||||
// 校验文件
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
// 校验文件和工作表名称(逻辑不变)
|
||||
if (file.isEmpty()) {
|
||||
throw new IllegalArgumentException("上传的Excel文件不能为空");
|
||||
}
|
||||
|
||||
// 校验工作表名称
|
||||
if (!"出库导入".equals(sheetName) && !"参考数据".equals(sheetName)) {
|
||||
throw new IllegalArgumentException("工作表名称必须为'出库导入'或'参考数据'");
|
||||
sheetName = "出库导入";
|
||||
}
|
||||
|
||||
// 使用EasyExcel解析Excel
|
||||
DeliveryExcelListener listener = new DeliveryExcelListener();
|
||||
// 关键变更:使用动态行数监听器
|
||||
DynamicDeliveryExcelListener listener = new DynamicDeliveryExcelListener();
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
EasyExcel.read(inputStream, listener)
|
||||
.sheet(sheetName) // 指定工作表
|
||||
.headRowNumber(0) // 无固定表头,从第1行开始解析
|
||||
.sheet(sheetName)
|
||||
.headRowNumber(0) // 无固定表头,全部行交由监听器处理
|
||||
.doRead();
|
||||
}
|
||||
|
||||
// 封装DTO返回
|
||||
// 封装DTO(逻辑不变)
|
||||
DeliveryDataDTO deliveryDataDTO = new DeliveryDataDTO();
|
||||
deliveryDataDTO.setDeliveryHeader(listener.getDeliveryHeader());
|
||||
deliveryDataDTO.setProductDetailList(listener.getProductDetailList());
|
||||
deliveryDataDTO.setCustomerDeliveryDetailList(listener.getCustomerDeliveryDetailList());
|
||||
List<ProductDetail> productDetailList = deliveryDataDTO.getProductDetailList();
|
||||
List<Map<String,Object>> shipperIds = new ArrayList<>();
|
||||
Set<Long> processedShipperIds = new HashSet<>();
|
||||
for (ProductDetail productDetail : productDetailList) {
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByName(productDetail.getProductName());
|
||||
if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) {
|
||||
Long shipperId = materialBaseInfoPO.getShipperId();
|
||||
if (processedShipperIds.add(shipperId)) {
|
||||
Map<String, Object> shipper = new HashMap<>();
|
||||
shipper.put("shipperId", shipperId);
|
||||
shipper.put("shipperName", materialBaseInfoPO.getShipperName());
|
||||
shipper.put("shipperCode", materialBaseInfoPO.getShipperCode());
|
||||
shipperIds.add(shipper);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (shipperIds.isEmpty()) {
|
||||
throw new Exception("出库物料货主不存在!");
|
||||
}
|
||||
if (shipperIds.size() > 1) {
|
||||
throw new Exception("出库物料不是同一个货主!");
|
||||
}
|
||||
|
||||
ReservationStockOutOrderDO reservationStockOutOrderDO = new ReservationStockOutOrderDO();
|
||||
reservationStockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
|
||||
reservationStockOutOrderDO.setShipperId((Long) shipperIds.get(0).get("shipperId"));
|
||||
reservationStockOutOrderDO.setShipperName((String) shipperIds.get(0).get("shipperName"));
|
||||
reservationStockOutOrderDO.setShipperCode((String) shipperIds.get(0).get("shipperCode"));
|
||||
reservationStockOutOrderDO.setNeedTransportFlag("1");
|
||||
reservationStockOutOrderDO.setNeedDeclareFlag("1");
|
||||
reservationStockOutOrderDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
reservationStockOutOrderDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
reservationStockOutOrderDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
reservationStockOutOrderDO.setIssueStatus(0);
|
||||
reservationStockOutOrderDO.setSalesmanId(loginUser.getUserPo().getUserId().toString());
|
||||
reservationStockOutOrderDO.setSalesmanName(loginUser.getUserPo().getUserName());
|
||||
reservationStockOutOrderDO.setCreateTime(new Date());
|
||||
reservationStockOutOrderDO.setCreateBy(loginUser.getUserPo().getUserId());
|
||||
reservationStockOutOrderDO.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
reservationStockOutOrderDO.setDelFlag(1);
|
||||
reservationStockOutOrderDO.setDocumentCreator(loginUser.getUserPo().getUserId().toString());
|
||||
reservationStockOutOrderDO.setDocumentCreatorName(loginUser.getUserPo().getUserName());
|
||||
reservationStockOutOrderDO.setOrderTypeCode("pu_tong_chu_ku");
|
||||
reservationStockOutOrderDO.setOrderTypeName("普通出库");
|
||||
DeliveryHeader deliveryHeader = deliveryDataDTO.getDeliveryHeader();
|
||||
reservationStockOutOrderDO.setTotalAmount(deliveryHeader.getSubtotalAmount());
|
||||
reservationStockOutOrderDO.setRoute(deliveryHeader.getDeliveryLineNo());
|
||||
reservationStockOutOrderDO.setOutboundDate(deliveryHeader.getDeliveryDate());
|
||||
int index = 1;
|
||||
List<ReservationOutMaterialDetailDO> reservationOutMaterialDetailDOList = new ArrayList<>();
|
||||
for (ProductDetail productDetail : productDetailList) {
|
||||
ReservationOutMaterialDetailDO reservationOutMaterialDetailDO = new ReservationOutMaterialDetailDO();
|
||||
reservationOutMaterialDetailDO.setOutOrderNumber(reservationStockOutOrderDO.getOutOrderNumber());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByName(productDetail.getProductName());
|
||||
reservationOutMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
|
||||
reservationOutMaterialDetailDO.setQuantity(new BigDecimal(productDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP).add(new BigDecimal(productDetail.getBoxCount()).setScale(2, BigDecimal.ROUND_HALF_UP)));
|
||||
reservationOutMaterialDetailDO.setMaterialCode(materialBaseInfoPO.getMaterialCode());
|
||||
reservationOutMaterialDetailDO.setMaterialName(materialBaseInfoPO.getMaterialName());
|
||||
reservationOutMaterialDetailDO.setBarCode(materialBaseInfoPO.getBarCode());
|
||||
reservationOutMaterialDetailDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
reservationOutMaterialDetailDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
reservationOutMaterialDetailDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
reservationOutMaterialDetailDO.setCreateBy(loginUser.getUserPo().getUserId());
|
||||
reservationOutMaterialDetailDO.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
String lot = generateDateSerialNumber();
|
||||
lot = lot+"-"+index;
|
||||
index++;
|
||||
reservationOutMaterialDetailDO.setLotNo(lot);
|
||||
reservationOutMaterialDetailDOList.add(reservationOutMaterialDetailDO);
|
||||
}
|
||||
reservationStockOutOrderDO.setMaterialDetailList(reservationOutMaterialDetailDOList);
|
||||
reservationStockOutOrderApplicationService.insert(reservationStockOutOrderDO);
|
||||
|
||||
List<CustomerDeliveryDetail> customerDeliveryDetailList = deliveryDataDTO.getCustomerDeliveryDetailList();
|
||||
for (CustomerDeliveryDetail customerDeliveryDetail : customerDeliveryDetailList) {
|
||||
ReservationDeliveryDetailsLink reservationDeliveryDetailsLink = new ReservationDeliveryDetailsLink();
|
||||
reservationDeliveryDetailsLink.setInvoiceNumber(customerDeliveryDetail.getInvoiceNo());
|
||||
reservationDeliveryDetailsLink.setAmount(customerDeliveryDetail.getAmount());
|
||||
reservationDeliveryDetailsLink.setCustomerNumber(customerDeliveryDetail.getCustomerCode());
|
||||
reservationDeliveryDetailsLink.setDeliveryName(customerDeliveryDetail.getCustomerName());
|
||||
reservationDeliveryDetailsLink.setBox(customerDeliveryDetail.getBoxCount());
|
||||
reservationDeliveryDetailsLink.setBag(customerDeliveryDetail.getPackageCount());
|
||||
reservationDeliveryDetailsLink.setCategory(customerDeliveryDetail.getCategory());
|
||||
reservationDeliveryDetailsLink.setOrderNumber(reservationStockOutOrderDO.getOutOrderNumber());
|
||||
List<ReservationStockOutOrder> reservationStockOutOrderDOList = stockOutOrderMapper.selectList(new LambdaQueryWrapper<ReservationStockOutOrder>().eq(ReservationStockOutOrder::getOutOrderNumber, reservationStockOutOrderDO.getOutOrderNumber()));
|
||||
if (reservationStockOutOrderDOList != null && !reservationStockOutOrderDOList.isEmpty() && reservationStockOutOrderDOList.get(0) != null) {
|
||||
reservationDeliveryDetailsLink.setOrderId(reservationStockOutOrderDOList.get(0).getOutOrderId());
|
||||
}
|
||||
reservationDeliveryDetailsLinkService.save(reservationDeliveryDetailsLink);
|
||||
}
|
||||
return deliveryDataDTO;
|
||||
}
|
||||
|
||||
public String generateDateSerialNumber() {
|
||||
// 1. 获取当前时间,格式化为:yyMMdd (2位年+2位月+2位日)
|
||||
SimpleDateFormat sdf = new SimpleDateFormat("yyMMdd");
|
||||
String datePart = sdf.format(new Date());
|
||||
|
||||
// 2. 生成 000~999 的 3 位随机数(不足补零)
|
||||
Random random = new Random();
|
||||
int randomNum = random.nextInt(1000); // 0~999
|
||||
String randomPart = String.format("%03d", randomNum); // 自动补前导零
|
||||
|
||||
// 3. 拼接结果
|
||||
return datePart + randomPart;
|
||||
}
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(ReservationStockInOrderImpl.class);
|
||||
// 默认工作表名称(与Excel一致)
|
||||
private static final String DEFAULT_SHEET_NAME = "入库模版";
|
||||
|
||||
@Override
|
||||
public StockInDataDTO parseStockInExcel(MultipartFile file, String sheetName) throws Exception {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
// 1. 校验文件
|
||||
if (file.isEmpty()) {
|
||||
LOGGER.error("上传的Excel文件为空");
|
||||
throw new IllegalArgumentException("Excel文件不能为空");
|
||||
}
|
||||
|
||||
// 2. 校验工作表名称(默认使用"入库模版")
|
||||
String targetSheetName = (sheetName == null || sheetName.trim().isEmpty())
|
||||
? DEFAULT_SHEET_NAME : sheetName.trim();
|
||||
|
||||
// 3. 使用EasyExcel解析(指定监听器)
|
||||
StockInExcelListener listener = new StockInExcelListener();
|
||||
try (InputStream inputStream = file.getInputStream()) {
|
||||
EasyExcel.read(inputStream, listener)
|
||||
.sheet(targetSheetName) // 指定工作表
|
||||
.headRowNumber(0) // 从第1行开始解析(不跳过任何行)
|
||||
.doRead();
|
||||
}
|
||||
|
||||
// 4. 封装DTO返回
|
||||
StockInDataDTO resultDTO = new StockInDataDTO();
|
||||
resultDTO.setStockInHeader(listener.getStockInHeader());
|
||||
resultDTO.setProductDetailList(listener.getProductDetailList());
|
||||
|
||||
LOGGER.info("Excel解析成功,工作表:{},产品明细数:{}",
|
||||
targetSheetName, resultDTO.getProductDetailList().size());
|
||||
List<StockInProductDetail> productDetailList = resultDTO.getProductDetailList();
|
||||
List<Map<String,Object>> shipperIds = new ArrayList<>();
|
||||
Set<Long> processedShipperIds = new HashSet<>();
|
||||
for (StockInProductDetail productDetail : productDetailList) {
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByName(productDetail.getProductName());
|
||||
if (materialBaseInfoPO != null && materialBaseInfoPO.getShipperId() != null) {
|
||||
Long shipperId = materialBaseInfoPO.getShipperId();
|
||||
if (processedShipperIds.add(shipperId)) {
|
||||
Map<String, Object> shipper = new HashMap<>();
|
||||
shipper.put("shipperId", shipperId);
|
||||
shipper.put("shipperName", materialBaseInfoPO.getShipperName());
|
||||
shipper.put("shipperCode", materialBaseInfoPO.getShipperCode());
|
||||
shipperIds.add(shipper);
|
||||
}
|
||||
}
|
||||
}
|
||||
ReservationStockInOrderDO reservationStockInOrderDO = new ReservationStockInOrderDO();
|
||||
reservationStockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
|
||||
reservationStockInOrderDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
reservationStockInOrderDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
reservationStockInOrderDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
reservationStockInOrderDO.setCreateBy(loginUser.getUserPo().getUserId());
|
||||
reservationStockInOrderDO.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
reservationStockInOrderDO.setCreateTime(new Date());
|
||||
reservationStockInOrderDO.setDelFlag(1);
|
||||
reservationStockInOrderDO.setDocumentCreator(loginUser.getUserPo().getUserId().toString());
|
||||
reservationStockInOrderDO.setDocumentCreatorName(loginUser.getUserPo().getUserName());
|
||||
reservationStockInOrderDO.setOrderTypeCode("pu_tong_ru_ku");
|
||||
reservationStockInOrderDO.setOrderTypeName("普通入库");
|
||||
reservationStockInOrderDO.setIssueStatus(0);
|
||||
reservationStockInOrderDO.setSalesmanId(loginUser.getUserPo().getUserId().toString());
|
||||
reservationStockInOrderDO.setSalesmanName(loginUser.getUserPo().getUserName());
|
||||
reservationStockInOrderDO.setShipperId((Long) shipperIds.get(0).get("shipperId"));
|
||||
reservationStockInOrderDO.setShipperName((String) shipperIds.get(0).get("shipperName"));
|
||||
reservationStockInOrderDO.setShipperCode((String) shipperIds.get(0).get("shipperCode"));
|
||||
StockInHeader stockInHeader = resultDTO.getStockInHeader();
|
||||
reservationStockInOrderDO.setWarehouseDate(stockInHeader.getStockInDate());
|
||||
reservationStockInOrderDO.setBusinessOrderNo(stockInHeader.getOrderNo());
|
||||
List<ReservationInMaterialDetailDO> reservationInMaterialDetailDOList = new ArrayList<>();
|
||||
int index = 1;
|
||||
for (StockInProductDetail stockInProductDetail : productDetailList) {
|
||||
ReservationInMaterialDetailDO reservationInMaterialDetailDO = new ReservationInMaterialDetailDO();
|
||||
reservationInMaterialDetailDO.setInOrderNumber(reservationStockInOrderDO.getInOrderNumber());
|
||||
reservationInMaterialDetailDO.setOrganizationId(loginUser.getUserPo().getOrganizationId());
|
||||
reservationInMaterialDetailDO.setOrganizationName(loginUser.getUserPo().getOrganizationName());
|
||||
reservationInMaterialDetailDO.setTopOrganizationId(loginUser.getUserPo().getTopOrganizationId());
|
||||
reservationInMaterialDetailDO.setCreateBy(loginUser.getUserPo().getUserId());
|
||||
reservationInMaterialDetailDO.setCreateByName(loginUser.getUserPo().getUserName());
|
||||
reservationInMaterialDetailDO.setCreateTime(new Date());
|
||||
MaterialBaseInfoPO materialBaseInfoPO = stockInOrderMapper.getByName(stockInProductDetail.getProductName());
|
||||
if (materialBaseInfoPO != null) {
|
||||
reservationInMaterialDetailDO.setMaterialBaseInfoId(materialBaseInfoPO.getMaterialBaseInfoId());
|
||||
reservationInMaterialDetailDO.setMaterialName(materialBaseInfoPO.getMaterialName());
|
||||
reservationInMaterialDetailDO.setMaterialCode(materialBaseInfoPO.getMaterialCode());
|
||||
}
|
||||
reservationInMaterialDetailDO.setQuantity(new BigDecimal(stockInProductDetail.getPieceCount()).setScale(2, BigDecimal.ROUND_HALF_UP));
|
||||
String lot = generateDateSerialNumber();
|
||||
lot = lot+"-"+index;
|
||||
index++;
|
||||
reservationInMaterialDetailDO.setLotNo(lot);
|
||||
reservationInMaterialDetailDO.setDrinkDate(stockInProductDetail.getDrinkDate());
|
||||
reservationInMaterialDetailDOList.add(reservationInMaterialDetailDO);
|
||||
}
|
||||
reservationStockInOrderDO.setMaterialDetailList(reservationInMaterialDetailDOList);
|
||||
insertApplication(reservationStockInOrderDO);
|
||||
return resultDTO;
|
||||
}
|
||||
|
||||
public Boolean insertApplication(ReservationStockInOrderDO stockInOrderDO) {
|
||||
// 如果仓库ID为空,从当前登录用户的关联仓库中获取
|
||||
if (stockInOrderDO.getWarehouseId() == null) {
|
||||
LoginUser loginUser = SecurityUtils.getLoginUser();
|
||||
if (loginUser == null) {
|
||||
throw new ServiceException("登录已失效,请重新登录");
|
||||
}
|
||||
AssociationWarehouseCacheDO associationWarehouseCacheDO = SystemServiceCacheUtil.getAssociationWarehouseCache(loginUser.getUserid());
|
||||
if (associationWarehouseCacheDO == null || associationWarehouseCacheDO.getWarehouseId() == null) {
|
||||
throw new ServiceException("当前用户未配置关联仓库,请先配置仓库");
|
||||
}
|
||||
stockInOrderDO.setWarehouseId(associationWarehouseCacheDO.getWarehouseId());
|
||||
}
|
||||
//设置仓库
|
||||
setWarehouseInfo(stockInOrderDO);
|
||||
// 设置货主信息
|
||||
shipperParam(stockInOrderDO);
|
||||
// 设置供应商信息
|
||||
supplierParam(stockInOrderDO);
|
||||
// 设置数据字典键值
|
||||
setDataDict(stockInOrderDO);
|
||||
return insertDomain(stockInOrderDO);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Boolean insertDomain(ReservationStockInOrderDO stockInOrderDO) {
|
||||
if (stockInOrderDO.getInOrderNumber() == null) {
|
||||
stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
|
||||
}
|
||||
// //统计总计划数
|
||||
BigDecimal quantity = stockInOrderDO.getMaterialDetailList().stream().map(ReservationInMaterialDetailDO::getQuantity).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||
stockInOrderDO.setQuantity(quantity);
|
||||
this.insert(stockInOrderDO);
|
||||
return materialDetailService.batchInsert(stockInOrderDO.getInOrderNumber(), stockInOrderDO.getMaterialDetailList());
|
||||
}
|
||||
|
||||
private void setWarehouseInfo(ReservationStockInOrderDO stockInOrderDO) {
|
||||
if (stockInOrderDO.getWarehouseId() == null) {
|
||||
throw new ServiceException("仓库ID不能为空");
|
||||
}
|
||||
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(stockInOrderDO.getWarehouseId());
|
||||
if (ajaxResult == null) {
|
||||
throw new ServiceException("获取仓库信息失败:返回结果为空,仓库ID:" + stockInOrderDO.getWarehouseId());
|
||||
}
|
||||
Object codeObj = ajaxResult.get("code");
|
||||
if (codeObj == null || !"200".equals(String.valueOf(codeObj))) {
|
||||
String errorMsg = ajaxResult.get("msg") != null ? String.valueOf(ajaxResult.get("msg")) : "未知错误";
|
||||
throw new ServiceException("获取仓库信息失败,仓库ID:" + stockInOrderDO.getWarehouseId() + ",错误信息:" + errorMsg);
|
||||
}
|
||||
Object dataObj = ajaxResult.get("data");
|
||||
if (dataObj == null) {
|
||||
throw new ServiceException("获取仓库信息失败:返回数据为空,仓库ID:" + stockInOrderDO.getWarehouseId());
|
||||
}
|
||||
WarehouseFeignPO warehouseFeignPO = JSON.parseObject(JSONObject.toJSONString(dataObj), WarehouseFeignPO.class);
|
||||
if (warehouseFeignPO == null) {
|
||||
throw new ServiceException("获取仓库信息失败:数据解析失败,仓库ID:" + stockInOrderDO.getWarehouseId());
|
||||
}
|
||||
stockInOrderDO.setWarehouseCode(warehouseFeignPO.getWarehouseCode());
|
||||
stockInOrderDO.setWarehouseName(warehouseFeignPO.getWarehouseName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 封装货主信息(改为与出库单相同的简洁逻辑,使用入库单的字段shipperName)
|
||||
* @author ZhouGY
|
||||
* @date 2024/5/9 20:43
|
||||
* @param stockInOrderDO
|
||||
*/
|
||||
private void shipperParam(ReservationStockInOrderDO stockInOrderDO){
|
||||
// 新增/编辑时前端可能只传 shipperId(下拉选中值),shipperName 为空。
|
||||
// 这里优先按 shipperId 回填货主编码/名称;其次再按 shipperName(名称或数字ID字符串)回填。
|
||||
|
||||
// 1) 优先按 shipperId 查询
|
||||
if (ObjectUtil.isNotNull(stockInOrderDO.getShipperId())) {
|
||||
AjaxResult ajaxResult = userServiceFeign.getInfo(stockInOrderDO.getShipperId());
|
||||
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||
throw new ServiceException("获取货主信息失败");
|
||||
}
|
||||
UserPo userPo = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserPo.class);
|
||||
stockInOrderDO.setShipperId(userPo.getUserId());
|
||||
stockInOrderDO.setShipperCode(userPo.getUserMemberCode());
|
||||
stockInOrderDO.setShipperName(userPo.getUserName());
|
||||
return;
|
||||
}
|
||||
|
||||
// 2) shipperId 为空时,按 shipperName 兜底
|
||||
String shipperName = stockInOrderDO.getShipperName();
|
||||
if (StringUtils.isEmpty(shipperName)) {
|
||||
return;
|
||||
}
|
||||
if (!shipperName.matches("\\d+")) {
|
||||
// 按名称查询
|
||||
AjaxResult ajaxResult = userServiceFeign.getInfoByName(shipperName);
|
||||
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||
throw new ServiceException("获取货主信息失败");
|
||||
}
|
||||
UserPo userPo = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserPo.class);
|
||||
stockInOrderDO.setShipperId(userPo.getUserId());
|
||||
stockInOrderDO.setShipperCode(userPo.getUserMemberCode());
|
||||
stockInOrderDO.setShipperName(userPo.getUserName());
|
||||
} else {
|
||||
// shipperName 是数字:按ID查询
|
||||
AjaxResult ajaxResult = userServiceFeign.getInfo(Long.valueOf(shipperName));
|
||||
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||
throw new ServiceException("获取货主信息失败");
|
||||
}
|
||||
UserPo userPo = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserPo.class);
|
||||
stockInOrderDO.setShipperId(userPo.getUserId());
|
||||
stockInOrderDO.setShipperCode(userPo.getUserMemberCode());
|
||||
stockInOrderDO.setShipperName(userPo.getUserName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 封装供应商信息
|
||||
* @author ZhouGY
|
||||
* @date 2024/5/9 20:43
|
||||
* @param stockInOrderDO
|
||||
*/
|
||||
private void supplierParam(ReservationStockInOrderDO stockInOrderDO){
|
||||
if (ObjectUtil.isNotNull(stockInOrderDO.getSupplierId())){
|
||||
AjaxResult ajaxResult = userServiceFeign.getInfo(stockInOrderDO.getSupplierId());
|
||||
if(!"200".equals(String.valueOf(ajaxResult.get("code")))){
|
||||
throw new ServiceException("获取供应商信息失败");
|
||||
}
|
||||
UserPo userPo = JSON.parseObject(JSONObject.toJSONString(ajaxResult.get("data")), UserPo.class);
|
||||
stockInOrderDO.setSupplierName(userPo.getUserName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @description 设置数据字典键值
|
||||
* @author ZhouGY
|
||||
* @date 2024/4/7 14:33
|
||||
* @param stockInOrderDO
|
||||
*/
|
||||
private void setDataDict(ReservationStockInOrderDO stockInOrderDO){
|
||||
//翻译单据类型
|
||||
if (StringUtils.isNotBlank(stockInOrderDO.getOrderTypeCode())){
|
||||
AjaxResult documentTypeResult = systemServiceFeign.selectListByDictType(DictCode.DOCUMENT_TYPE.getCode());
|
||||
if (!"200".equals(String.valueOf(documentTypeResult.get("code")))) {
|
||||
throw new ServiceException("单据类型数据字典不存在");
|
||||
}
|
||||
List<SysDictData> documentTypeDataList = JSON.parseArray(JSONUtil.toJsonStr(documentTypeResult.get("data")), SysDictData.class);
|
||||
|
||||
SysDictData documentTypeData = documentTypeDataList.stream().filter(info -> ObjectUtil.equal(info.getDictValue(), stockInOrderDO.getOrderTypeCode())).findAny().orElse(null);
|
||||
if (null == documentTypeData) {
|
||||
throw new ServiceException("单据类型【" + stockInOrderDO.getOrderTypeCode() + "】数据字典不存在 请联系管理员");
|
||||
}
|
||||
stockInOrderDO.setOrderTypeName(documentTypeData.getDictLabel());
|
||||
}
|
||||
|
||||
//翻译优先级别类型
|
||||
if (StringUtils.isNotBlank(stockInOrderDO.getPriorityLevelCode())){
|
||||
AjaxResult priorityLevelResult = systemServiceFeign.selectListByDictType(DictCode.PRIORITY_LEVEL.getCode());
|
||||
if (!"200".equals(String.valueOf(priorityLevelResult.get("code")))) {
|
||||
throw new ServiceException("优先级别类型数据字典不存在");
|
||||
}
|
||||
List<SysDictData> priorityLevelDataList = JSON.parseArray(JSONUtil.toJsonStr(priorityLevelResult.get("data")), SysDictData.class);
|
||||
|
||||
SysDictData priorityLevelData = priorityLevelDataList.stream().filter(info -> ObjectUtil.equal(info.getDictValue(), stockInOrderDO.getPriorityLevelCode())).findAny().orElse(null);
|
||||
if (null == priorityLevelData) {
|
||||
throw new ServiceException("优先级别类型【" + stockInOrderDO.getPriorityLevelCode() + "】数据字典不存在 请联系管理员");
|
||||
}
|
||||
stockInOrderDO.setPriorityLevelName(priorityLevelData.getDictLabel());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ public class DeliveryHeader {
|
||||
// 送货日期
|
||||
private Date deliveryDate;
|
||||
// 送货线号
|
||||
private Integer deliveryLineNo;
|
||||
private String deliveryLineNo;
|
||||
// 车次
|
||||
private Integer trainNumber;
|
||||
// 纪录合共-货品总数量
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 入库单数据DTO(封装表头信息和产品明细列表,用于Controller层传输)
|
||||
*/
|
||||
@Data
|
||||
public class StockInDataDTO {
|
||||
// 入库表头信息
|
||||
private StockInHeader stockInHeader;
|
||||
// 入库产品明细列表
|
||||
private List<StockInProductDetail> productDetailList;
|
||||
|
||||
// Getter和Setter方法
|
||||
public StockInHeader getStockInHeader() {
|
||||
return stockInHeader;
|
||||
}
|
||||
|
||||
public void setStockInHeader(StockInHeader stockInHeader) {
|
||||
this.stockInHeader = stockInHeader;
|
||||
}
|
||||
|
||||
public List<StockInProductDetail> getProductDetailList() {
|
||||
return productDetailList;
|
||||
}
|
||||
|
||||
public void setProductDetailList(List<StockInProductDetail> productDetailList) {
|
||||
this.productDetailList = productDetailList;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 入库单表头实体类(对应Excel第一行数据)
|
||||
* 存储:入库日期、OrderNO
|
||||
*/
|
||||
@Data
|
||||
public class StockInHeader {
|
||||
// 入库日期(Excel第一行第2列)
|
||||
private Date stockInDate;
|
||||
// 订单编号(Excel第一行第4列)
|
||||
private String orderNo;
|
||||
|
||||
// Getter和Setter方法
|
||||
public Date getStockInDate() {
|
||||
return stockInDate;
|
||||
}
|
||||
|
||||
public void setStockInDate(Date stockInDate) {
|
||||
this.stockInDate = stockInDate;
|
||||
}
|
||||
|
||||
public String getOrderNo() {
|
||||
return orderNo;
|
||||
}
|
||||
|
||||
public void setOrderNo(String orderNo) {
|
||||
this.orderNo = orderNo;
|
||||
}
|
||||
}
|
||||
+73
@@ -0,0 +1,73 @@
|
||||
package com.mhd.oms.domain.reservationStockInOrder.repository.vo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* 入库产品明细实体类(对应Excel第二行开始的表格数据)
|
||||
*/
|
||||
@Data
|
||||
public class StockInProductDetail {
|
||||
// 产品编号(Excel第1列)
|
||||
private Integer productCode;
|
||||
// 产品名称(Excel第2列)
|
||||
private String productName;
|
||||
// 箱含量(Excel第5列)
|
||||
private Integer boxCapacity;
|
||||
// 件数(Excel第6列)
|
||||
private Integer pieceCount;
|
||||
// 箱数(Excel第7列:Qty(cases))
|
||||
private Integer boxCount;
|
||||
// 饮用日期(Excel第8列)
|
||||
private Date drinkDate;
|
||||
|
||||
// Getter和Setter方法
|
||||
public Integer getProductCode() {
|
||||
return productCode;
|
||||
}
|
||||
|
||||
public void setProductCode(Integer productCode) {
|
||||
this.productCode = productCode;
|
||||
}
|
||||
|
||||
public String getProductName() {
|
||||
return productName;
|
||||
}
|
||||
|
||||
public void setProductName(String productName) {
|
||||
this.productName = productName;
|
||||
}
|
||||
|
||||
public Integer getBoxCapacity() {
|
||||
return boxCapacity;
|
||||
}
|
||||
|
||||
public void setBoxCapacity(Integer boxCapacity) {
|
||||
this.boxCapacity = boxCapacity;
|
||||
}
|
||||
|
||||
public Integer getPieceCount() {
|
||||
return pieceCount;
|
||||
}
|
||||
|
||||
public void setPieceCount(Integer pieceCount) {
|
||||
this.pieceCount = pieceCount;
|
||||
}
|
||||
|
||||
public Integer getBoxCount() {
|
||||
return boxCount;
|
||||
}
|
||||
|
||||
public void setBoxCount(Integer boxCount) {
|
||||
this.boxCount = boxCount;
|
||||
}
|
||||
|
||||
public Date getDrinkDate() {
|
||||
return drinkDate;
|
||||
}
|
||||
|
||||
public void setDrinkDate(Date drinkDate) {
|
||||
this.drinkDate = drinkDate;
|
||||
}
|
||||
}
|
||||
+5
@@ -457,5 +457,10 @@ public class ReservationStockOutOrder extends BaseVOEntity {
|
||||
|
||||
@ApiModelProperty("推送人姓名")
|
||||
private String pushByName;
|
||||
@ApiModelProperty("总金额")
|
||||
@Excel(name = "总金额")
|
||||
private BigDecimal totalAmount;
|
||||
@ApiModelProperty("路线")
|
||||
private String route;
|
||||
|
||||
}
|
||||
+8
@@ -3,6 +3,8 @@ package com.mhd.oms.domain.reservationStockOutOrder.repository.po;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
import com.mhd.common.core.web.domain.BaseVOEntity;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO;
|
||||
import com.mhd.oms.domain.reservationOutMaterialDetail.repository.po.ReservationOutMaterialDetailPO;
|
||||
//import com.mhd.wms.domain.outMaterialDetail.repository.po.OutMaterialCheckPO;
|
||||
//import com.mhd.wms.domain.outMaterialDetail.repository.po.OutMaterialDetailPO;
|
||||
@@ -468,4 +470,10 @@ public class ReservationStockOutOrderPO extends BaseVOEntity {
|
||||
|
||||
@ApiModelProperty("推送人姓名")
|
||||
private String pushByName;
|
||||
@ApiModelProperty("总金额")
|
||||
@Excel(name = "总金额")
|
||||
private BigDecimal totalAmount;
|
||||
@ApiModelProperty("路线")
|
||||
private String route;
|
||||
private List<ReservationDeliveryDetailsLink> reservationDeliveryDetailsLinkList;
|
||||
}
|
||||
+6
@@ -504,4 +504,10 @@ public class ReservationStockOutOrderDO extends BaseVOEntity {
|
||||
|
||||
@ApiModelProperty("推送人姓名")
|
||||
private String pushByName;
|
||||
|
||||
@ApiModelProperty("总金额")
|
||||
@Excel(name = "总金额")
|
||||
private BigDecimal totalAmount;
|
||||
@ApiModelProperty("路线")
|
||||
private String route;
|
||||
}
|
||||
+5
@@ -493,4 +493,9 @@ public class ReservationStockOutOrderDTO extends ReservationStockOutOrderBaseDTO
|
||||
|
||||
@ApiModelProperty("推送人姓名")
|
||||
private String pushByName;
|
||||
@ApiModelProperty("总金额")
|
||||
@Excel(name = "总金额")
|
||||
private BigDecimal totalAmount;
|
||||
@ApiModelProperty("路线")
|
||||
private String route;
|
||||
}
|
||||
+8
-1
@@ -18,6 +18,9 @@ import com.mhd.common.core.web.domain.AjaxResult;
|
||||
import com.mhd.common.security.utils.SecurityUtils;
|
||||
import com.mhd.oms.domain.gwLog.entity.GwLog;
|
||||
import com.mhd.oms.domain.gwLog.repository.mapper.GwLogMapper;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.entity.ReservationDeliveryDetailsLink;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.mapper.ReservationDeliveryDetailsLinkMapper;
|
||||
import com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.entity.ReservationInMaterialDetail;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.facade.IReservationInMaterialDetailService;
|
||||
import com.mhd.oms.domain.reservationInMaterialDetail.repository.mapper.ReservationInMaterialDetailMapper;
|
||||
@@ -105,6 +108,8 @@ public class ReservationStockOutOrderApplicationService {
|
||||
private ReservationStockOutOrderMapper reservationStockOutOrderMapper;
|
||||
@Autowired
|
||||
private ReservationOutMaterialDetailMapper reservationOutMaterialDetailMapper;
|
||||
@Autowired
|
||||
private ReservationDeliveryDetailsLinkMapper reservationDeliveryDetailsLinkMapper;
|
||||
|
||||
@Autowired
|
||||
private ReservationStockInOrderMapper reservationStockInOrderMapper;
|
||||
@@ -355,7 +360,9 @@ public class ReservationStockOutOrderApplicationService {
|
||||
// if (stockOutOrderPO.getStatus() != null && (stockOutOrderPO.getStatus() == 9 || stockOutOrderPO.getStatus() == 12)) {
|
||||
// filterMaterialDetailByPickingQuantity(detailList, stockOutOrderPO.getReview(), stockOutOrderPO.getOutOrderNumber());
|
||||
// }
|
||||
|
||||
List<ReservationDeliveryDetailsLink> reservationDeliveryDetailsLinks = reservationDeliveryDetailsLinkMapper.selectList(new LambdaQueryWrapper<ReservationDeliveryDetailsLink>()
|
||||
.eq(ReservationDeliveryDetailsLink::getOrderNumber, stockOutOrderPO.getOutOrderNumber()));
|
||||
stockOutOrderPO.setReservationDeliveryDetailsLinkList(reservationDeliveryDetailsLinks);
|
||||
return stockOutOrderPO;
|
||||
}
|
||||
|
||||
|
||||
@@ -66,4 +66,8 @@ public class SysTableConfig extends BaseVOEntity {
|
||||
@ApiModelProperty(value = "物料添加方式")
|
||||
@Excel(name = "物料添加方式", width = 15)
|
||||
private String materialAddType;
|
||||
/**配送明细*/
|
||||
@ApiModelProperty(value = "配送明细")
|
||||
@Excel(name = "配送明细", width = 15)
|
||||
private String deliveryDetail;
|
||||
}
|
||||
+4
@@ -64,4 +64,8 @@ public class SysTableConfigPO extends BaseVOEntity {
|
||||
@ApiModelProperty(value = "组织名称")
|
||||
@Excel(name = "组织名称", width = 15)
|
||||
private String organizationName;
|
||||
/**配送明细*/
|
||||
@ApiModelProperty(value = "配送明细")
|
||||
@Excel(name = "配送明细", width = 15)
|
||||
private String deliveryDetail;
|
||||
}
|
||||
+4
@@ -57,6 +57,10 @@ public class SysTableConfigDTO extends BaseVOEntity {
|
||||
@ApiModelProperty(value = "物料添加方式")
|
||||
@Excel(name = "物料添加方式", width = 15)
|
||||
private String materialAddType;
|
||||
/**配送明细*/
|
||||
@ApiModelProperty(value = "配送明细")
|
||||
@Excel(name = "配送明细", width = 15)
|
||||
private String deliveryDetail;
|
||||
/**一级组织ID*/
|
||||
@ApiModelProperty(value = "一级组织ID")
|
||||
@Excel(name = "一级组织ID", width = 15)
|
||||
|
||||
+4
@@ -65,4 +65,8 @@ public class SysTableConfigVO extends BaseVOEntity {
|
||||
@ApiModelProperty(value = "组织名称")
|
||||
@Excel(name = "组织名称", width = 15)
|
||||
private String organizationName;
|
||||
/**配送明细*/
|
||||
@ApiModelProperty(value = "配送明细")
|
||||
@Excel(name = "配送明细", width = 15)
|
||||
private String deliveryDetail;
|
||||
}
|
||||
+33
-5
@@ -9,6 +9,7 @@ import com.mhd.oms.domain.reservationStockInOrder.repository.po.ReservationStock
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.todo.ReservationStockInOrderDTO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.DeliveryDataDTO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.repository.vo.StockInDataDTO;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.service.ReservationStockInOrderApplicationService;
|
||||
import com.mhd.oms.domain.reservationStockInOrder.service.ReservationStockInOrderAssembler;
|
||||
import com.mhd.system.api.domain.InMaterialDetail;
|
||||
@@ -197,12 +198,14 @@ public class ReservationStockInOrderApi extends BaseController {
|
||||
* @return 解析后的出库数据
|
||||
*/
|
||||
@PostMapping("/parseExcel")
|
||||
public ResponseEntity<DeliveryDataDTO> parseExcel(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
@RequestParam("sheetName") String sheetName) {
|
||||
public ResponseEntity<Map<String, Object>> parseExcel(
|
||||
@RequestParam("file") MultipartFile file) {
|
||||
try {
|
||||
DeliveryDataDTO deliveryDataDTO = reservationStockInOrderService.parseExcelFile(file, sheetName);
|
||||
return new ResponseEntity<>(deliveryDataDTO, HttpStatus.OK);
|
||||
DeliveryDataDTO deliveryDataDTO = reservationStockInOrderService.parseExcelFile(file, "");
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("result", deliveryDataDTO);
|
||||
result.put("code",200);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
} catch (IllegalArgumentException e) {
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
} catch (Exception e) {
|
||||
@@ -210,6 +213,31 @@ public class ReservationStockInOrderApi extends BaseController {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 接口1:仅解析Excel文件(返回解析结果,不保存)
|
||||
* 用途:预览Excel解析数据
|
||||
*/
|
||||
@PostMapping("/parse-excel")
|
||||
public ResponseEntity<Map<String, Object>> parseStockInExcel(
|
||||
@RequestParam("file") MultipartFile file,
|
||||
@RequestParam(value = "sheetName", required = false) String sheetName) {
|
||||
try {
|
||||
StockInDataDTO resultDTO = reservationStockInOrderService.parseStockInExcel(file, sheetName);
|
||||
Map<String, Object> result = new HashMap<>();
|
||||
result.put("result", resultDTO);
|
||||
result.put("code",200);
|
||||
return new ResponseEntity<>(result, HttpStatus.OK);
|
||||
} catch (IllegalArgumentException e) {
|
||||
// 参数错误(如文件为空)
|
||||
// LOGGER.error("Excel解析参数错误:{}", e.getMessage());
|
||||
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
|
||||
} catch (Exception e) {
|
||||
// 其他解析异常
|
||||
// LOGGER.error("Excel解析失败:{}", e.getMessage(), e);
|
||||
return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ApiOperation("批量推送")
|
||||
@PostMapping("/batchPush")
|
||||
|
||||
+62
@@ -0,0 +1,62 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!DOCTYPE mapper
|
||||
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
|
||||
<mapper namespace="com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.mapper.ReservationDeliveryDetailsLinkMapper">
|
||||
|
||||
<resultMap type="com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.po.ReservationDeliveryDetailsLinkPO" id="ReservationDeliveryDetailsLinkResult">
|
||||
<result property="id" column="id" />
|
||||
<result property="createBy" column="create_by" />
|
||||
<result property="createTime" column="create_time" />
|
||||
<result property="updateBy" column="update_by" />
|
||||
<result property="updateTime" column="update_time" />
|
||||
<result property="delFlag" column="del_flag" />
|
||||
<result property="orderId" column="order_id" />
|
||||
<result property="category" column="category" />
|
||||
<result property="invoiceNumber" column="invoice_number" />
|
||||
<result property="customerNumber" column="customer_number" />
|
||||
<result property="deliveryName" column="delivery_name" />
|
||||
<result property="box" column="box" />
|
||||
<result property="bag" column="bag" />
|
||||
<result property="amount" column="amount" />
|
||||
</resultMap>
|
||||
|
||||
|
||||
<sql id="selectReservationDeliveryDetailsLinkPo">
|
||||
select id, create_by, create_time, update_by, update_time, del_flag, order_id, category, invoice_number, customer_number, delivery_name, box, bag, amount from RESERVATION_DELIVERY_DETAILS_LINK
|
||||
</sql>
|
||||
|
||||
<sql id="selectReservationDeliveryDetailsLinkPo1">
|
||||
<where>
|
||||
<if test="orderId != null ">
|
||||
and order_id = #{orderId}
|
||||
</if>
|
||||
<if test="category != null and category != ''">
|
||||
and category = #{category}
|
||||
</if>
|
||||
<if test="invoiceNumber != null and invoiceNumber != ''">
|
||||
and invoice_number = #{invoiceNumber}
|
||||
</if>
|
||||
<if test="customerNumber != null and customerNumber != ''">
|
||||
and customer_number = #{customerNumber}
|
||||
</if>
|
||||
<if test="deliveryName != null and deliveryName != ''">
|
||||
and delivery_name like concat('%', #{deliveryName}, '%')
|
||||
</if>
|
||||
<if test="box != null ">
|
||||
and box = #{box}
|
||||
</if>
|
||||
<if test="bag != null ">
|
||||
and bag = #{bag}
|
||||
</if>
|
||||
<if test="amount != null ">
|
||||
and amount = #{amount}
|
||||
</if>
|
||||
</where>
|
||||
</sql>
|
||||
|
||||
<select id="queryList" parameterType="com.mhd.oms.domain.reservationDeliveryDetailsLink.repository.todo.ReservationDeliveryDetailsLinkDO" resultMap="ReservationDeliveryDetailsLinkResult">
|
||||
<include refid="selectReservationDeliveryDetailsLinkPo"/>
|
||||
<include refid="selectReservationDeliveryDetailsLinkPo1"/>
|
||||
</select>
|
||||
</mapper>
|
||||
+4
@@ -454,6 +454,10 @@
|
||||
<select id="getinfo" parameterType="java.lang.Long" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where MATERIAL_BASE_INFO_ID = #{id}
|
||||
</select>
|
||||
|
||||
<select id="getByName" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where MATERIAL_NAME = #{name}
|
||||
</select>
|
||||
<select id="getMaterialBaseInfoList" parameterType="java.lang.String" resultType="com.mhd.oms.domain.reservationStockInOrder.repository.po.MaterialBaseInfoPO">
|
||||
select * from "NGWL_TEST_WMS".MATERIAL_BASE_INFO where material_code = #{id}
|
||||
</select>
|
||||
|
||||
@@ -3,14 +3,17 @@ package com.mhd.wms.domain.inMaterialDetail.entity;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.IdType;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
@@ -372,4 +375,10 @@ public class InMaterialDetail extends BaseVOEntity {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+6
@@ -12,6 +12,7 @@ import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
|
||||
/**
|
||||
@@ -417,4 +418,9 @@ public class InMaterialDetailPO extends StockInOrderBasePO {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+9
@@ -1,5 +1,6 @@
|
||||
package com.mhd.wms.domain.inMaterialDetail.repository.todo;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
@@ -8,8 +9,10 @@ import com.mhd.wms.domain.materialMoreDetail.repository.todo.MaterialMoreDetailD
|
||||
import com.mhd.wms.domain.stockInOrder.repository.todo.StockInOrderBaseDO;
|
||||
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;
|
||||
|
||||
|
||||
@@ -380,4 +383,10 @@ public class InMaterialDetailDO extends StockInOrderBaseDO {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+7
@@ -10,6 +10,7 @@ import com.mhd.common.core.annotation.Excel;
|
||||
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;
|
||||
@@ -366,4 +367,10 @@ public class ReceiptMaterialDetail extends BaseVOEntity {
|
||||
@Excel(name = "抄码数量克重详情")
|
||||
private String copyDetails;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
|
||||
}
|
||||
+8
-1
@@ -14,6 +14,7 @@ import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
|
||||
/**
|
||||
@@ -363,4 +364,10 @@ public class ReceiptMaterialDetailPO extends BaseVOEntity {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
}
|
||||
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+7
-1
@@ -13,6 +13,7 @@ import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
|
||||
/**
|
||||
@@ -358,4 +359,9 @@ public class ReceiptMaterialDetailDO extends BaseVOEntity {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
}
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+1
@@ -570,6 +570,7 @@ public class StockInOrderDomainService {
|
||||
planQty = inMaterialDetailPO.getInboundQuantity();
|
||||
}
|
||||
receiptMaterialDetailDO.setQuantity(planQty);
|
||||
receiptMaterialDetailDO.setDrinkDate(inMaterialDetailPO.getDrinkDate());
|
||||
receiptMaterialDetailDOList.add(receiptMaterialDetailDO);
|
||||
});
|
||||
stockReceiptOrderDO.setMaterialDetailList(receiptMaterialDetailDOList);
|
||||
|
||||
+7
@@ -1,5 +1,6 @@
|
||||
package com.mhd.wms.interfaces.dto.inMaterialDetail;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
import com.mhd.common.core.annotation.Excel;
|
||||
@@ -8,8 +9,10 @@ import com.mhd.wms.interfaces.dto.inMaterialDetailSerialNumber.InMaterialDetailS
|
||||
import com.mhd.wms.interfaces.dto.materialMoreDetail.MaterialMoreDetailDTO;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -380,4 +383,8 @@ public class InMaterialDetailDTO extends BaseVOEntity {
|
||||
@Excel(name = "lot编号")
|
||||
private String lotNo;
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
+9
@@ -1,5 +1,6 @@
|
||||
package com.mhd.wms.interfaces.dto.receiptMaterialDetail;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonFormat;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
|
||||
@@ -9,8 +10,10 @@ import com.mhd.wms.domain.inMaterialDetailSerialNumber.repository.todo.InMateria
|
||||
import com.mhd.wms.interfaces.dto.materialMoreDetail.MaterialMoreDetailDTO;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -307,4 +310,10 @@ public class ReceiptMaterialDetailDTO extends BaseVOEntity {
|
||||
@ApiModelProperty("oms入库单详情id")
|
||||
@Excel(name = "oms入库单详情id")
|
||||
private String omsInMaterialDetail;
|
||||
|
||||
|
||||
@ApiModelProperty(value = "饮用时间")
|
||||
@JsonFormat(timezone = "GMT+8",pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
@DateTimeFormat(pattern="yyyy-MM-dd HH:mm:ss")
|
||||
private Date drinkDate;
|
||||
}
|
||||
Reference in New Issue
Block a user