Merge branch 'refs/heads/dev' into dev_820

This commit is contained in:
王奎兴
2026-08-18 16:36:28 +08:00
73 changed files with 1628 additions and 349 deletions
@@ -18,7 +18,7 @@ import java.util.Set;
/** /**
* bms财务结算系统feign调用接口 * bms财务结算系统feign调用接口
*/ */
@FeignClient(contextId = "BmsService", value = ServiceNameConstants.BMS_SERVICE, url = "http://10.102.192.32:8019",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class) @FeignClient(contextId = "BmsService", value = ServiceNameConstants.BMS_SERVICE, url = "http://10.102.192.3:8019",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface BmsServiceFeign { public interface BmsServiceFeign {
@@ -16,7 +16,7 @@ import org.springframework.web.bind.annotation.RequestBody;
import java.util.List; import java.util.List;
import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletableFuture;
@FeignClient(contextId = "OmsService", value = ServiceNameConstants.OMS_SERVICE,url = "http://10.102.192.33:8017", fallbackFactory = RemoteOmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class) @FeignClient(contextId = "OmsService", value = ServiceNameConstants.OMS_SERVICE, url = "http://10.102.192.4:8017",fallbackFactory = RemoteOmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface OmsServiceFeign { public interface OmsServiceFeign {
@@ -26,7 +26,7 @@ import org.springframework.web.bind.annotation.*;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@FeignClient(contextId = "commonWlhyServiceFeign",value = ServiceNameConstants.WLHY_SERVICE,url = "http://10.102.192.31:8014",configuration = FeignAutoConfiguration.class) @FeignClient(contextId = "commonWlhyServiceFeign",value = ServiceNameConstants.WLHY_SERVICE,url = "http://10.102.192.30:8014",configuration = FeignAutoConfiguration.class)
public interface WlhyServiceFeign { public interface WlhyServiceFeign {
/** /**
@@ -21,7 +21,7 @@ import java.util.Map;
* @description: TODO * @description: TODO
* @date 2024/5/10 8:58 * @date 2024/5/10 8:58
**/ **/
@FeignClient(contextId = "remoteWmsServiceFeign",value = ServiceNameConstants.WMS_SERVICE, url = "http://10.102.192.32:8016", fallbackFactory = RemoteWmsFallbackFactory.class, configuration = FeignAutoConfiguration.class) @FeignClient(contextId = "remoteWmsServiceFeign",value = ServiceNameConstants.WMS_SERVICE, url = "http://10.102.192.3:8016",fallbackFactory = RemoteWmsFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface WmsServiceFeign { public interface WmsServiceFeign {
/** /**
@@ -9,7 +9,7 @@ import com.mhd.system.api.feign.FeignAutoConfiguration;
import org.springframework.cloud.openfeign.FeignClient; import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@FeignClient(contextId = "YmsService", value = ServiceNameConstants.YMS_SERVICE,fallbackFactory = RemoteBmsFeignFallbackFactory.class,url = "http://10.102.192.33:8018", configuration = FeignAutoConfiguration.class) @FeignClient(contextId = "YmsService", value = ServiceNameConstants.YMS_SERVICE,url = "http://10.102.192.4:8018",fallbackFactory = RemoteBmsFeignFallbackFactory.class, configuration = FeignAutoConfiguration.class)
public interface YmsServiceFeign { public interface YmsServiceFeign {
/** /**
@@ -50,8 +50,8 @@ public class StockOutOrder extends BaseVOEntity {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核") @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
@Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -40,6 +40,14 @@ import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import com.mhd.basic.interfaces.dto.shipperLeaseDetailsApi.WarehouseLeaseExportVO;
import com.mhd.common.core.utils.poi.ExcelUtil;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDate; import java.time.LocalDate;
@@ -270,14 +278,15 @@ public class LeaseApplicationService {
* 货主租赁明细 * 货主租赁明细
* 定时任务:每天凌晨1点执行,计算前一天的货主租赁明细 * 定时任务:每天凌晨1点执行,计算前一天的货主租赁明细
*/ */
// @Scheduled(cron = "0 0 1 * * ?") @Scheduled(cron = "0 0 1 * * ?")
public void shipperLeaseDetails() { public void shipperLeaseDetails() {
log.info("开始执行货主租赁明细定时任务"); log.info("开始执行货主租赁明细定时任务");
// 计算前一天的日期,将时间设置为当天的0点0分0秒,只保留日期部分 // 计算前一天的日期,将时间设置为当天的0点0分0秒,只保留日期部分
final Date yesterday = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -1)); final Date yesterday = DateUtil.beginOfDay(DateUtil.offsetDay(new Date(), -1));
LeaseDO leaseDO = new LeaseDO(); LeaseDO leaseDO = new LeaseDO();
leaseDO.setTime(yesterday); leaseDO.setTime(yesterday); // 设置查询时间
leaseDO.setStatus(1); // 只查询启用状态的租赁,停用的不参与出租率计算
//查询有效期内的租赁 //查询有效期内的租赁
List<LeasePO> leasePOS = queryList(leaseDO); List<LeasePO> leasePOS = queryList(leaseDO);
List<LeasePO> entireUnit = leasePOS.stream() List<LeasePO> entireUnit = leasePOS.stream()
@@ -494,6 +503,103 @@ public class LeaseApplicationService {
return warehouseOccupancyRatesList; return warehouseOccupancyRatesList;
} }
/**
* 导出仓库出租率及客户租赁明细(单 sheet,明细行带仓库当日汇总列)
* 参数与 /warehouseOccupancyRate、/list 一致
*/
public void exportOccupancyRate(HttpServletResponse response, ShipperLeaseDetailsDO shipperLeaseDetailsDO) throws IOException {
// 注意:本方法不调用 warehouseOccupancyRate(),因为该方法在不传 warehouseId 时
// totalArea 会算成全系统所有仓库库区面积之和(如 6168),导致导出面积/日租率错误。
// 这里自行按 (业务日期 + 仓库) 维度计算,保证多仓库导出时每个仓库的面积/日租率正确。
// ===== 1. 查全部明细(用副本 DO,避免影响外部)=====
ShipperLeaseDetailsDO detailDO = new ShipperLeaseDetailsDO();
BeanUtils.copyProperties(shipperLeaseDetailsDO, detailDO);
List<ShipperLeaseDetailsPO> detailList = shipperLeaseDetailsService.queryList(detailDO);
if (detailList == null) {
detailList = new ArrayList<>();
}
// ===== 2. 预算每个仓库的总面积(启用库区的 storageRegion 累加),建 warehouseId -> totalArea 映射 =====
Set<Long> warehouseIds = detailList.stream()
.map(ShipperLeaseDetailsPO::getWarehouseId)
.filter(Objects::nonNull)
.collect(Collectors.toSet());
Map<Long, BigDecimal> warehouseTotalAreaMap = new HashMap<>();
for (Long wid : warehouseIds) {
StorageSectionDO storageSectionDO = new StorageSectionDO();
storageSectionDO.setWarehouseId(wid);
storageSectionDO.setOpeningUp(1);
List<StorageSectionPO> sections = storageSectionApplicationService.queryList(storageSectionDO);
BigDecimal area = BigDecimal.ZERO;
for (StorageSectionPO s : sections) {
area = area.add(s.getStorageRegion() == null ? BigDecimal.ZERO : s.getStorageRegion());
}
warehouseTotalAreaMap.put(wid, area);
}
// ===== 3. 按 (业务日期 + 仓库ID) 聚合,算每个仓库当天的整租/散租面积 =====
// summaryMap: key -> [整租面积, 散租面积]
SimpleDateFormat keySdf = new SimpleDateFormat("yyyy-MM-dd");
Map<String, BigDecimal[]> summaryMap = new HashMap<>();
for (ShipperLeaseDetailsPO d : detailList) {
String key = (d.getBusinessDate() == null ? "" : keySdf.format(d.getBusinessDate()))
+ "_" + d.getWarehouseId();
BigDecimal[] arr = summaryMap.computeIfAbsent(key, k -> new BigDecimal[]{BigDecimal.ZERO, BigDecimal.ZERO});
BigDecimal leaseArea = d.getLeaseArea() == null ? BigDecimal.ZERO : d.getLeaseArea();
if ("整租".equals(d.getLeaseType())) {
arr[0] = arr[0].add(leaseArea);
} else {
arr[1] = arr[1].add(leaseArea);
}
}
// ===== 4. 明细为主,每行拼上对应仓库当天的汇总(总面积/日租率按仓库单独算)=====
List<WarehouseLeaseExportVO> exportList = new ArrayList<>();
for (ShipperLeaseDetailsPO d : detailList) {
WarehouseLeaseExportVO vo = new WarehouseLeaseExportVO();
// 明细列
vo.setBusinessDate(d.getBusinessDate());
vo.setOrganizationName(d.getOrganizationName());
vo.setWarehouseName(d.getWarehouseName());
vo.setCargoOwnerName(d.getCargoOwnerName());
vo.setLeaseType(d.getLeaseType());
vo.setLeaseArea(d.getLeaseArea());
// 汇总列
String key = (d.getBusinessDate() == null ? "" : keySdf.format(d.getBusinessDate()))
+ "_" + d.getWarehouseId();
BigDecimal[] arr = summaryMap.get(key);
BigDecimal entireLeaseArea = (arr != null) ? arr[0] : BigDecimal.ZERO;
BigDecimal fractionalLeaseArea = (arr != null) ? arr[1] : BigDecimal.ZERO;
vo.setEntireLeaseArea(entireLeaseArea);
vo.setFractionalLeaseArea(fractionalLeaseArea);
// 该仓库的总面积(按仓库单独算,不再用全局总和)
BigDecimal widTotalArea = warehouseTotalAreaMap.getOrDefault(d.getWarehouseId(), BigDecimal.ZERO);
vo.setTotalArea(widTotalArea);
// 日租率 = (整租+散租) / 总面积 × 100,保留2位小数(直接输出百分比值,如 10.00)
BigDecimal leaseSum = entireLeaseArea.add(fractionalLeaseArea);
BigDecimal dailyRate = widTotalArea.compareTo(BigDecimal.ZERO) == 0
? BigDecimal.ZERO
: leaseSum.multiply(new BigDecimal("100")).divide(widTotalArea, 2, BigDecimal.ROUND_HALF_UP);
vo.setDailyRentalRate(dailyRate);
exportList.add(vo);
}
// ===== 5. 按业务日期降序、仓库名升序排序(null 排最后)=====
exportList.sort(Comparator
.comparing(WarehouseLeaseExportVO::getBusinessDate, Comparator.nullsLast(Comparator.reverseOrder()))
.thenComparing(WarehouseLeaseExportVO::getWarehouseName, Comparator.nullsLast(Comparator.naturalOrder())));
// ===== 6. 用 ExcelUtil 导出(项目通用做法,单 sheet)=====
String fileName = URLEncoder.encode("仓库出租率导出", "UTF-8").replaceAll("\\+", "%20");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
ExcelUtil<WarehouseLeaseExportVO> util = new ExcelUtil<>(WarehouseLeaseExportVO.class);
util.exportExcel(response, exportList, "仓库出租率");
}
/** /**
* 定时任务整租推送到bms * 定时任务整租推送到bms
@@ -581,6 +687,25 @@ public class LeaseApplicationService {
} }
} }
/**
* 启用/停用租赁
* @param leaseIds 租赁ID列表
* @param status 目标状态:1=启用,0=停用
*/
public Boolean updateStatus(List<Long> leaseIds, Integer status) {
LoginUser loginUser = SecurityUtils.getLoginUser();
Long updateBy = loginUser != null ? loginUser.getUserid() : null;
String updateByName = loginUser != null ? loginUser.getUsername() : null;
if (leaseIds == null || leaseIds.isEmpty()) {
throw new ServiceException("租赁ID不能为空");
}
if (status == null || (status != 0 && status != 1)) {
throw new ServiceException("状态值无效:1=启用,0=停用");
}
log.info("启用/停用租赁--结束,leaseIds={},状态={},更新人id={},更新人名称={}",leaseIds,status==0?"停用":"启用",updateBy,updateByName);
return leaseDomainService.updateStatus(leaseIds, status, updateBy, updateByName);
}
// /** // /**
// * @description 设置数据字典键值 // * @description 设置数据字典键值
// * @author ZhouGY // * @author ZhouGY
@@ -30,11 +30,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.*;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
@@ -580,6 +576,40 @@ public class ExpenseAccountApplicationService {
return expenseAccountDomainService.getInfoByCode2(subjectCode,topOrganizationId); return expenseAccountDomainService.getInfoByCode2(subjectCode,topOrganizationId);
} }
/**
* 根据编码和组织ID查询
*/
public ExpenseAccountPO getInfoByOrgAndCode(String subjectCode, Long organizationId) {
if(!StringUtils.isNotEmpty(subjectCode)){
throw new ServiceException("费用科目编码不能为空");
}
if(organizationId == null){
throw new ServiceException("组织ID不能为空");
}
ExpenseAccountPO expenseAccountPO = expenseAccountDomainService.getInfoByOrgAndCode(subjectCode, organizationId);
// // 组装计费单位列表:单位-单位英文
// List<String> unit = new ArrayList<>();
// if (expenseAccountPO != null) {
// unit.add(expenseAccountPO.getBillingUnit() + "-" + expenseAccountPO.getBillingUnitEn());
// unit.add(expenseAccountPO.getBillingUnit2() + "-" + expenseAccountPO.getBillingUnitEn2());
// expenseAccountPO.setUnit(unit);
// }
// 组装计费单位列表(数组)
List<Map<String, String>> unit = new ArrayList<>();
if (expenseAccountPO != null) {
Map<String, String> unit1 = new HashMap<>();
unit1.put("unit", expenseAccountPO.getBillingUnit() + "-" + expenseAccountPO.getBillingUnitEn());
unit.add(unit1);
Map<String, String> unit2 = new HashMap<>();
unit2.put("unit", expenseAccountPO.getBillingUnit2() + "-" + expenseAccountPO.getBillingUnitEn2());
unit.add(unit2);
expenseAccountPO.setUnit(unit);
}
return expenseAccountPO;
}
public List<QueryExpenseAccountPO> selectExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO){ public List<QueryExpenseAccountPO> selectExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO){
setDataPermissionForSearch(searchExpenseAccountDO); setDataPermissionForSearch(searchExpenseAccountDO);
return expenseAccountDomainService.selectExpenseAccount(searchExpenseAccountDO); return expenseAccountDomainService.selectExpenseAccount(searchExpenseAccountDO);
@@ -58,6 +58,11 @@ public interface IExpenseAccountService extends IService<ExpenseAccount>
*/ */
ExpenseAccountPO getInfoByCode(ExpenseAccountDO expenseAccountDO); ExpenseAccountPO getInfoByCode(ExpenseAccountDO expenseAccountDO);
/**
* 根据费用科目code和组织ID查询费用信息
*/
ExpenseAccountPO getInfoByOrgAndCode(ExpenseAccountDO expenseAccountDO);
public List<QueryExpenseAccountPO> selectExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO); public List<QueryExpenseAccountPO> selectExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO);
public List<QueryExpenseAccountPO> selectOtherExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO); public List<QueryExpenseAccountPO> selectOtherExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO);
@@ -39,6 +39,11 @@ public interface ExpenseAccountMapper extends BaseMapper<ExpenseAccount>
*/ */
ExpenseAccountPO getInfoByCode(@Param("expenseAccountDO") ExpenseAccountDO expenseAccountDO); ExpenseAccountPO getInfoByCode(@Param("expenseAccountDO") ExpenseAccountDO expenseAccountDO);
/**
* 根据费用科目code和组织ID查询费用信息
*/
ExpenseAccountPO getInfoByOrgAndCode(@Param("expenseAccountDO") ExpenseAccountDO expenseAccountDO);
public List<QueryExpenseAccountPO> selectExpenseAccount(@Param("searchExpenseAccountDO") SearchExpenseAccountDO searchExpenseAccountDO); public List<QueryExpenseAccountPO> selectExpenseAccount(@Param("searchExpenseAccountDO") SearchExpenseAccountDO searchExpenseAccountDO);
public List<QueryExpenseAccountPO> selectOtherExpenseAccount(@Param("searchExpenseAccountDO") SearchExpenseAccountDO searchExpenseAccountDO); public List<QueryExpenseAccountPO> selectOtherExpenseAccount(@Param("searchExpenseAccountDO") SearchExpenseAccountDO searchExpenseAccountDO);
@@ -129,6 +129,11 @@ public class ExpenseAccountImpl extends ServiceImpl<ExpenseAccountMapper, Expens
return expenseAccountMapper.getInfoByCode(expenseAccountDO); return expenseAccountMapper.getInfoByCode(expenseAccountDO);
} }
@Override
public ExpenseAccountPO getInfoByOrgAndCode(ExpenseAccountDO expenseAccountDO) {
return expenseAccountMapper.getInfoByOrgAndCode(expenseAccountDO);
}
/** /**
* 系统科目查询 * 系统科目查询
* 社会车辆:service_items_code='SHCL'upper_subject_code='shcl_clyf'society_status=1 * 社会车辆:service_items_code='SHCL'upper_subject_code='shcl_clyf'society_status=1
@@ -9,6 +9,7 @@ import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty; import io.swagger.annotations.ApiModelProperty;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.List; import java.util.List;
import java.util.Map;
import com.mhd.common.core.web.domain.BaseVOEntity; import com.mhd.common.core.web.domain.BaseVOEntity;
@@ -159,4 +160,8 @@ public class ExpenseAccountPO extends BaseVOEntity{
@ApiModelProperty("nc科目编码") @ApiModelProperty("nc科目编码")
private String ncSubjectCode; private String ncSubjectCode;
@ApiModelProperty("计费单位列表(单位-单位英文)")
private List<Map<String, String>> unit;
} }
@@ -101,6 +101,16 @@ public class ExpenseAccountDomainService {
expenseAccountDO.setTopOrganizationId(topOrganizationId); expenseAccountDO.setTopOrganizationId(topOrganizationId);
return expenseAccountService.getInfoByCode(expenseAccountDO); return expenseAccountService.getInfoByCode(expenseAccountDO);
} }
/**
* 根据编码和组织ID查询费用科目信息
*/
public ExpenseAccountPO getInfoByOrgAndCode(String subjectCode, Long organizationId) {
ExpenseAccountDO expenseAccountDO = new ExpenseAccountDO();
expenseAccountDO.setSubjectCode(subjectCode);
expenseAccountDO.setOrganizationId(organizationId);
return expenseAccountService.getInfoByOrgAndCode(expenseAccountDO);
}
public List<QueryExpenseAccountPO> selectExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO){ public List<QueryExpenseAccountPO> selectExpenseAccount(SearchExpenseAccountDO searchExpenseAccountDO){
return expenseAccountService.selectExpenseAccount(searchExpenseAccountDO); return expenseAccountService.selectExpenseAccount(searchExpenseAccountDO);
} }
@@ -96,4 +96,7 @@ public class Lease extends BaseVOEntity{
@ApiModelProperty("业务员ID") @ApiModelProperty("业务员ID")
private String salesmanId; private String salesmanId;
@ApiModelProperty("状态:1=正常,0=停用")
private Integer status;
} }
@@ -97,4 +97,7 @@ public class LeasePO extends BaseVOEntity{
@ApiModelProperty("业务员ID") @ApiModelProperty("业务员ID")
private String salesmanId; private String salesmanId;
@ApiModelProperty("状态:1=正常,0=停用")
private Integer status;
} }
@@ -113,4 +113,7 @@ public class LeaseDO extends BaseVOEntity{
@ApiModelProperty("业务员ID") @ApiModelProperty("业务员ID")
private String salesmanId; private String salesmanId;
@ApiModelProperty("状态:1=正常,0=停用")
private Integer status;
} }
@@ -89,4 +89,22 @@ public class LeaseDomainService {
.in(Lease::getId, leaseIds) .in(Lease::getId, leaseIds)
.eq(Lease::getDelFlag, 1)); .eq(Lease::getDelFlag, 1));
} }
/**
* 启用/停用租赁
* @param leaseIds 租赁ID列表
* @param status 目标状态:1=启用,0=停用
* @param updateBy 操作人ID
* @param updateByName 操作人名称
*/
public Boolean updateStatus(List<Long> leaseIds, Integer status, Long updateBy, String updateByName) {
return leaseService.update(new UpdateWrapper<Lease>().lambda()
.set(Lease::getStatus, status)
.set(Lease::getUpdateBy, updateBy)
.set(Lease::getUpdateByName, updateByName)
.set(Lease::getUpdateTime, new Date())
.in(Lease::getId, leaseIds)
.eq(Lease::getDelFlag, 1));
}
} }
@@ -168,9 +168,11 @@ public class WarehouseDomainService {
warehouseLinkagePO.setName(warehousePO.getWarehouseName()); warehouseLinkagePO.setName(warehousePO.getWarehouseName());
StorageSectionDO storageSectionDO = new StorageSectionDO(); StorageSectionDO storageSectionDO = new StorageSectionDO();
storageSectionDO.setWarehouseId(warehousePO.getWarehouseId()); storageSectionDO.setWarehouseId(warehousePO.getWarehouseId());
storageSectionDO.setNullify(1);
List<StorageSectionPO> storageSectionPOList = storageSectionService.queryList(storageSectionDO); List<StorageSectionPO> storageSectionPOList = storageSectionService.queryList(storageSectionDO);
StorageLocationDO storageLocationDO = new StorageLocationDO(); StorageLocationDO storageLocationDO = new StorageLocationDO();
storageLocationDO.setWarehouseId(warehousePO.getWarehouseId()); storageLocationDO.setWarehouseId(warehousePO.getWarehouseId());
storageLocationDO.setNullify(1);
List<StorageLocationPO> storageLocationPOList = storageLocationService.queryList(storageLocationDO); List<StorageLocationPO> storageLocationPOList = storageLocationService.queryList(storageLocationDO);
//根据库区唯一标识进行分组 //根据库区唯一标识进行分组
Map<String, List<StorageLocationPO>> storageLocationListMap = storageLocationPOList.stream().collect(Collectors.groupingBy(StorageLocationPO::getStorageCode)); Map<String, List<StorageLocationPO>> storageLocationListMap = storageLocationPOList.stream().collect(Collectors.groupingBy(StorageLocationPO::getStorageCode));
@@ -110,4 +110,7 @@ public class LeaseDTO extends BaseVOEntity{
@ApiModelProperty("业务员ID") @ApiModelProperty("业务员ID")
private String salesmanId; private String salesmanId;
@ApiModelProperty("状态:1=正常,0=停用")
private Integer status;
} }
@@ -0,0 +1,65 @@
package com.mhd.basic.interfaces.dto.shipperLeaseDetailsApi;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.mhd.common.core.annotation.Excel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.math.BigDecimal;
import java.util.Date;
/**
* 仓库出租率及客户租赁明细 导出VO(单 sheet)
* 明细为主行,附该仓库当日汇总列
*/
@Data
public class WarehouseLeaseExportVO {
private static final long serialVersionUID = 1L;
@ApiModelProperty("仓库")
@Excel(name = "仓库")
private String warehouseName;
@ApiModelProperty("业务日期")
@Excel(name = "业务日期", width = 20, dateFormat = "yyyy-MM-dd")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
@DateTimeFormat(pattern = "yyyy-MM-dd")
private Date businessDate;
@ApiModelProperty("整租面积(m²)")
@Excel(name = "整租面积(m²)")
private BigDecimal entireLeaseArea;
@ApiModelProperty("散租面积(m²)")
@Excel(name = "散租面积(m²)")
private BigDecimal fractionalLeaseArea;
@ApiModelProperty("总面积(m²)")
@Excel(name = "总面积(m²)")
private BigDecimal totalArea;
@ApiModelProperty("日租率(%)")
@Excel(name = "日租率(%)")
private BigDecimal dailyRentalRate;
@ApiModelProperty("组织名称")
@Excel(name = "组织名称")
private String organizationName;
@ApiModelProperty("货主名称")
@Excel(name = "货主名称")
private String cargoOwnerName;
@ApiModelProperty("租赁方式")
@Excel(name = "租赁方式")
private String leaseType;
@ApiModelProperty("租赁面积(m²)")
@Excel(name = "租赁面积(m²)")
private BigDecimal leaseArea;
// ===== 以下为仓库当日汇总列(同一仓库同一天的多行会重复,属正常)=====
}
@@ -328,5 +328,13 @@ public class ExpenseAccountApi extends BaseController{
return AjaxResult.success(expenseAccountPO); return AjaxResult.success(expenseAccountPO);
} }
@ApiOperation("根据code和组织ID获取数据")
@GetMapping(value = "/getInfoByOrgAndCode")
public AjaxResult getInfoByOrgAndCode(@RequestParam("subjectCode") String subjectCode,@RequestParam("organizationId") Long organizationId)
{
ExpenseAccountPO expenseAccountPO = expenseAccountApplicationService.getInfoByOrgAndCode(subjectCode, organizationId);
return AjaxResult.success(expenseAccountPO.getUnit());
}
} }
@@ -130,4 +130,18 @@ public class LeaseApi extends BaseController{
return AjaxResult.success(); return AjaxResult.success();
} }
/**
* 启用/停用租赁
* @param leaseIds 租赁ID集合
* @param status 目标状态(启用/停用)
* @return 操作结果
*/
@ApiOperation("启用/停用租赁")
@PutMapping("/updateStatus/{leaseIds}/{status}")
public AjaxResult updateStatus(@PathVariable("leaseIds") List<Long> leaseIds,
@PathVariable("status") Integer status)
{
return toAjax(leaseApplicationService.updateStatus(leaseIds, status));
}
} }
@@ -20,6 +20,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Comparator; import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -157,5 +159,17 @@ public class ShipperLeaseDetailsApi extends BaseController{
return getDataTable(warehouseOccupancyRates); return getDataTable(warehouseOccupancyRates);
} }
/**
* 导出仓库出租率及客户租赁明细
* 参数与 /warehouseOccupancyRate、/list 一致
*/
@ApiOperation("导出仓库出租率及客户租赁明细")
@GetMapping(value = "/export", produces = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")
public void export(ShipperLeaseDetailsDTO shipperLeaseDetailsDTO, HttpServletResponse response) throws IOException
{
ShipperLeaseDetailsDO shipperLeaseDetailsDO = shipperLeaseDetailsAssembler.toDO(shipperLeaseDetailsDTO);
leaseApplicationService.exportOccupancyRate(response, shipperLeaseDetailsDO);
}
} }
@@ -151,6 +151,22 @@
LIMIT 1 LIMIT 1
</select> </select>
<select id="getInfoByOrgAndCode" resultType="com.mhd.basic.domain.expenseAccount.repository.po.ExpenseAccountPO" parameterType="com.mhd.basic.domain.expenseAccount.repository.todo.ExpenseAccountDO">
SELECT
a.* ,
b.tax_rate,
b.service_items_name,
b.service_items_code
FROM
expense_account a
LEFT JOIN service_items_manage b ON a.service_items_manage_id = b.service_items_manage_id
WHERE
a.del_flag = 1
AND a.organization_id = #{expenseAccountDO.organizationId}
AND a.subject_code = #{expenseAccountDO.subjectCode}
AND a.status = 1
LIMIT 1
</select>
<sql id="common_where_two"> <sql id="common_where_two">
<!-- 数据权限:南光组织(organizationId=2827)查全部,其他组织查自己 --> <!-- 数据权限:南光组织(organizationId=2827)查全部,其他组织查自己 -->
@@ -35,6 +35,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<result property="updateBy" column="update_by" /> <result property="updateBy" column="update_by" />
<result property="updateByName" column="update_by_name" /> <result property="updateByName" column="update_by_name" />
<result property="delFlag" column="del_flag" /> <result property="delFlag" column="del_flag" />
<result property="status" column="status" />
</resultMap> </resultMap>
@@ -68,7 +69,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
a.bill_time, a.bill_time,
a.salesman_name, a.salesman_name,
a.settlement_currency, a.settlement_currency,
a.salesman_id a.salesman_id,
a.status
from lease a from lease a
LEFT JOIN warehouse w ON a.warehouse_id = w.warehouse_id AND w.del_flag = 1 LEFT JOIN warehouse w ON a.warehouse_id = w.warehouse_id AND w.del_flag = 1
</sql> </sql>
@@ -136,6 +138,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
AND a.start_date &lt;= #{time} AND a.start_date &lt;= #{time}
AND a.end_date &gt;= #{time} AND a.end_date &gt;= #{time}
</if> </if>
<!-- 停用状态过滤:status 不为空时按状态过滤 -->
<if test="status != null">
AND a.status = #{status}
</if>
<!-- 删除标记 --> <!-- 删除标记 -->
<choose> <choose>
<when test="delFlag != null"> and a.del_flag = #{delFlag} </when> <when test="delFlag != null"> and a.del_flag = #{delFlag} </when>
@@ -88,4 +88,10 @@ public class BillDetail extends BaseVOEntity{
private String invoiceItemName; private String invoiceItemName;
@ApiModelProperty(value = "费用类别") @ApiModelProperty(value = "费用类别")
private String feeType; private String feeType;
@ApiModelProperty(value = "计费单位")
private String billingUnit;
@ApiModelProperty(value = "计费数量")
private BigDecimal billingNum;
@ApiModelProperty(value = "计费单价")
private BigDecimal billingUnitPrice;
} }
@@ -134,5 +134,11 @@ public class BillDetailPO extends BaseVOEntity{
private String invoiceItemName; private String invoiceItemName;
@ApiModelProperty(value = "费用类别") @ApiModelProperty(value = "费用类别")
private String feeType; private String feeType;
@ApiModelProperty(value = "计费单位")
private String billingUnit;
@ApiModelProperty(value = "计费数量")
private BigDecimal billingNum;
@ApiModelProperty(value = "计费单价")
private BigDecimal billingUnitPrice;
} }
@@ -262,4 +262,9 @@ public class BillManagePO extends BaseVOEntity{
@ApiModelProperty("收款帐户名称") @ApiModelProperty("收款帐户名称")
private String paymentAccountName; private String paymentAccountName;
private List<BillDetail> billDetailList; private List<BillDetail> billDetailList;
@ApiModelProperty("最近收款时间")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
@Excel(name = "最近收款时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
private Date collectionTime;
} }
@@ -98,4 +98,10 @@ public class BillDetailDO extends BaseVOEntity{
private String invoiceItemName; private String invoiceItemName;
@ApiModelProperty(value = "费用类别") @ApiModelProperty(value = "费用类别")
private String feeType; private String feeType;
@ApiModelProperty(value = "计费单位")
private String billingUnit;
@ApiModelProperty(value = "计费数量")
private BigDecimal billingNum;
@ApiModelProperty(value = "计费单价")
private BigDecimal billingUnitPrice;
} }
@@ -180,6 +180,9 @@ public class ReceiptManageDomainService {
receiptManageDO.setCreateBy(loginUser.getUserPo().getUserId()); receiptManageDO.setCreateBy(loginUser.getUserPo().getUserId());
receiptManageDO.setCreateByName(loginUser.getUserPo().getUserName()); receiptManageDO.setCreateByName(loginUser.getUserPo().getUserName());
receiptManageDO.setCreateTime(new Date()); receiptManageDO.setCreateTime(new Date());
if (receiptManageDO.getCollectionTime() == null) {
receiptManageDO.setCollectionTime(new Date());
}
ReceiptManage receiptManage = new ReceiptManage(); ReceiptManage receiptManage = new ReceiptManage();
BeanUtils.copyProperties(receiptManageDO,receiptManage); BeanUtils.copyProperties(receiptManageDO,receiptManage);
Boolean flagTwo = receiptManageService.save(receiptManage); Boolean flagTwo = receiptManageService.save(receiptManage);
@@ -139,4 +139,10 @@ public class BillDetailDTO extends BaseVOEntity{
private String invoiceItemName; private String invoiceItemName;
@ApiModelProperty(value = "费用类别") @ApiModelProperty(value = "费用类别")
private String feeType; private String feeType;
@ApiModelProperty(value = "计费单位")
private String billingUnit;
@ApiModelProperty(value = "计费数量")
private BigDecimal billingNum;
@ApiModelProperty(value = "计费单价")
private BigDecimal billingUnitPrice;
} }
+4 -4
View File
@@ -18,15 +18,15 @@ spring:
discovery: discovery:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.30:6848 server-addr: 10.102.192.30:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
config: config:
# server-addr: 127.0.0.1:8848 # server-addr: 127.0.0.1:8848
# 线上测试环境配置 容器名+端口号 # 线上测试环境配置 容器名+端口号
server-addr: 10.33.0.129:6010 # server-addr: 10.33.0.129:6010
# server-addr: 10.102.192.30:6848 server-addr: 10.102.192.30:6848
username: nacos username: nacos
password: manhuoda@2023 password: manhuoda@2023
group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置 group: DEFAULT_GROUP # 默认分组就是DEFAULT_GROUP,如果使用默认分组可以不配置
@@ -8,7 +8,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="queryList" parameterType="com.mhd.bms.domain.billManage.repository.todo.BillManageDO" resultType="com.mhd.bms.domain.billManage.repository.po.BillManagePO"> <select id="queryList" parameterType="com.mhd.bms.domain.billManage.repository.todo.BillManageDO" resultType="com.mhd.bms.domain.billManage.repository.po.BillManagePO">
select select
a.*,b.SETTLEMENT_ENTITY_ID as settlementEntityId a.*,
b.SETTLEMENT_ENTITY_ID as settlementEntityId,
(SELECT MAX(c.collection_time)
FROM receipt_detail rd
LEFT JOIN receipt_manage c ON rd.receipt_manage_id = c.receipt_manage_id
WHERE rd.bill_manage_id = a.bill_manage_id
AND rd.del_flag = 1
AND c.del_flag = 1) AS collectionTime
from bill_manage a LEFT JOIN SETTLEMENT_CUSTOMERS b on a.SETTLEMENT_CUSTOMERS_ID = b.SETTLEMENT_CUSTOMERS_ID from bill_manage a LEFT JOIN SETTLEMENT_CUSTOMERS b on a.SETTLEMENT_CUSTOMERS_ID = b.SETTLEMENT_CUSTOMERS_ID
where a.del_flag = 1 where a.del_flag = 1
<include refid="common_where"/> <include refid="common_where"/>
@@ -147,6 +147,14 @@ public class BusinessDocumentOrderApplicationService {
{ {
return businessDocumentOrderDomainService.audit(businessAuditDTO); return businessDocumentOrderDomainService.audit(businessAuditDTO);
} }
/**
* 业务单反审核
*/
public Boolean cancelAudit(BusinessAuditDTO businessAuditDTO)
{
return businessDocumentOrderDomainService.cancelAudit(businessAuditDTO);
}
public boolean execute(List<Long> ids) { public boolean execute(List<Long> ids) {
return businessDocumentOrderDomainService.execute(ids); return businessDocumentOrderDomainService.execute(ids);
} }
@@ -49,6 +49,11 @@ public interface IBusinessDocumentOrderService extends IService<BusinessDocument
public Boolean audit( List<Long> ids, Long reviewStatus, String SalesManager,String reviewOpinion); public Boolean audit( List<Long> ids, Long reviewStatus, String SalesManager,String reviewOpinion);
/**
* 业务单反审核(将已审核订单恢复到待审核)
*/
public Boolean cancelAudit(List<Long> ids);
String selectByMakerCodeNc(String salesmanCodeNc); String selectByMakerCodeNc(String salesmanCodeNc);
String selectByMakerCodeNc1(String salesmanCodeNc); String selectByMakerCodeNc1(String salesmanCodeNc);
@@ -37,4 +37,10 @@ public interface BusinessDocumentOrderMapper extends BaseMapper<BusinessDocument
TmsTransportNote getTmsTransportNote(@Param("tmsOrderId") String tmsOrderId); TmsTransportNote getTmsTransportNote(@Param("tmsOrderId") String tmsOrderId);
String getPushVerifyByOrgId(@Param("organizationId") Long organizationId); String getPushVerifyByOrgId(@Param("organizationId") Long organizationId);
/**
* 统计指定日期前缀(yyMMdd)下已生成的新格式业务单号数量
* 仅统计新格式(长度<=12)过滤历史16位旧数据保证序号每日从001正确累计
*/
int countByGoodsNumberPrefix(@Param("prefix") String prefix);
} }
@@ -5,6 +5,7 @@ import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil; import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mhd.common.core.domain.po.UserPo; import com.mhd.common.core.domain.po.UserPo;
import com.mhd.common.core.utils.OrderSequence; import com.mhd.common.core.utils.OrderSequence;
@@ -19,6 +20,7 @@ import com.mhd.oms.domain.businessDocumentOrder.repository.facade.IBusinessDocum
import com.mhd.oms.domain.businessDocumentOrder.repository.mapper.BusinessDocumentOrderMapper; import com.mhd.oms.domain.businessDocumentOrder.repository.mapper.BusinessDocumentOrderMapper;
import com.mhd.oms.domain.businessDocumentOrder.repository.po.BusinessDocumentOrderPO; import com.mhd.oms.domain.businessDocumentOrder.repository.po.BusinessDocumentOrderPO;
import com.mhd.oms.domain.businessDocumentOrder.repository.todo.BusinessDocumentOrderDO; import com.mhd.oms.domain.businessDocumentOrder.repository.todo.BusinessDocumentOrderDO;
import com.mhd.oms.domain.businessDocumentOrder.service.GoodsNumberGenerator;
import com.mhd.oms.domain.executeOrder.entity.ExecuteOrder; import com.mhd.oms.domain.executeOrder.entity.ExecuteOrder;
import com.mhd.oms.domain.executeOrder.repository.mapper.ExecuteOrderMapper; import com.mhd.oms.domain.executeOrder.repository.mapper.ExecuteOrderMapper;
import com.mhd.oms.domain.executeOrder.repository.todo.ExecuteOrderDO; import com.mhd.oms.domain.executeOrder.repository.todo.ExecuteOrderDO;
@@ -88,6 +90,9 @@ public class BusinessDocumentOrderImpl extends ServiceImpl<BusinessDocumentOrder
@Autowired @Autowired
private WlhyServiceFeign wlhyServiceFeign; private WlhyServiceFeign wlhyServiceFeign;
@Autowired
private GoodsNumberGenerator goodsNumberGenerator;
/** /**
* 查询请填写功能名称列表 * 查询请填写功能名称列表
@@ -173,28 +178,6 @@ public class BusinessDocumentOrderImpl extends ServiceImpl<BusinessDocumentOrder
} }
public static String getOrderCodeByDate(Date date){
return new StringBuffer()
.append(getSecondPartByDate(date))
.append(getThreePart())
.toString();
}
private static String getSecondPartByDate(Date date) {
if (date == null) {
date = new Date();
}
String temp_current_time = DateUtil.format(date, datePattern());
return temp_current_time.substring(2, temp_current_time.length());
}
private static String datePattern() {
return "yyyyMMddHHmmss";
}
private static String getThreePart() {
return RandomUtil.randomNumbers(4);
}
@Override @Override
public Boolean audit(List<Long> ids, Long reviewStatus, String SalesManager,String reviewOpinion ) { public Boolean audit(List<Long> ids, Long reviewStatus, String SalesManager,String reviewOpinion ) {
LoginUser loginUser = SecurityUtils.getLoginUser();//获取登录人 LoginUser loginUser = SecurityUtils.getLoginUser();//获取登录人
@@ -225,7 +208,6 @@ public class BusinessDocumentOrderImpl extends ServiceImpl<BusinessDocumentOrder
BeanUtils.copyProperties(businessDocumentOrder, subOrder); BeanUtils.copyProperties(businessDocumentOrder, subOrder);
subOrder.setId(null); subOrder.setId(null);
subOrder.setGoodsNumber(OrderSequence.getOrderCode()); // 生成新的子单号
// 设置子单的拼单类型和主单关系 // 设置子单的拼单类型和主单关系
subOrder.setSplicingOrderType(3L); // 合单-子单 subOrder.setSplicingOrderType(3L); // 合单-子单
@@ -255,31 +237,10 @@ public class BusinessDocumentOrderImpl extends ServiceImpl<BusinessDocumentOrder
subOrder.setRecipientName(user.getUserName()); subOrder.setRecipientName(user.getUserName());
String orderCode = null; //生成子单货源单号yyMMdd + 当日顺序号
int maxRetryCount = 100; String orderCode = goodsNumberGenerator.generateUniqueGoodsNumber(subOrder.getDocumentDate());
int retryCount = 0;
while (retryCount < maxRetryCount) {
orderCode = getOrderCodeByDate(subOrder.getDocumentDate());
retryCount++;
List<BusinessDocumentOrder> checkOrderCodes = businessDocumentOrderMapper.selectList(
new QueryWrapper<BusinessDocumentOrder>().eq("goods_number", orderCode)
);
if (CollectionUtils.isEmpty(checkOrderCodes)) {
break;
}
if (retryCount >= maxRetryCount) {
throw new com.aliyun.oss.ServiceException("生成唯一订单编号失败,已达到最大重试次数:" + maxRetryCount);
}
}
//生成货源单号
subOrder.setGoodsNumber(orderCode); subOrder.setGoodsNumber(orderCode);
businessDocumentOrderMapper.insert(subOrder); businessDocumentOrderMapper.insert(subOrder);
subOrderCount++; // 增加子单计数 subOrderCount++; // 增加子单计数
@@ -338,6 +299,88 @@ public class BusinessDocumentOrderImpl extends ServiceImpl<BusinessDocumentOrder
return null; return null;
} }
@Override
@Transactional(rollbackFor = Exception.class)
public Boolean cancelAudit(List<Long> ids) { // 取消审核 后端暂时未加鉴权
if (CollectionUtils.isEmpty(ids)) {
throw new ServiceException("未选择反审核的业务单");
}
for (Long id : ids) {
BusinessDocumentOrder order = businessDocumentOrderMapper.selectById(id);
if (ObjectUtil.isNull(order)) {
throw new ServiceException("未查询到业务单信息");
}
// 校验1子单(splicingOrderType=3)不允许单独反审核需对主单操作
if (order.getSplicingOrderType() != null && order.getSplicingOrderType() == 3L) {
throw new ServiceException("业务单【" + order.getGoodsNumber() + "】为子单,请对主单进行反审核");
}
// 校验2"审核通过(reviewStatus=1)"可反审核
if (order.getReviewStatus() == null || order.getReviewStatus() != 1L) {
throw new ServiceException("业务单【" + order.getGoodsNumber() + "】非已审核状态,无法反审核");
}
// 校验3已生成执行单的不允许反审核需先取消执行
ExecuteOrder existExec = executeOrderMapper.selectOne(new LambdaQueryWrapper<ExecuteOrder>()
.eq(ExecuteOrder::getBusinessDocumentId, id)
.eq(ExecuteOrder::getDelFlag, 1).last("LIMIT 1"));
if (ObjectUtil.isNotNull(existExec)) {
throw new ServiceException("业务单【" + order.getGoodsNumber() + "】已生成执行单,无法进行反审核");
}
boolean isMain = order.getSplicingOrderType() != null && order.getSplicingOrderType() == 4L;
// 拆单主单(isMain)清理审核时生成的子单子单地址以及回填到配送明细的 subOrderId
if (isMain) {
List<BusinessDocumentOrder> subOrders = businessDocumentOrderMapper.selectList(
new LambdaQueryWrapper<BusinessDocumentOrder>()
.eq(BusinessDocumentOrder::getMainOrderId, String.valueOf(id))
.eq(BusinessDocumentOrder::getDelFlag, 1));
if (subOrders != null && !subOrders.isEmpty()) {
List<String> subIdStrs = new ArrayList<>();
for (BusinessDocumentOrder sub : subOrders) {
// 校验4子单若已生成执行单主单不可反审核
ExecuteOrder subExec = executeOrderMapper.selectOne(new LambdaQueryWrapper<ExecuteOrder>()
.eq(ExecuteOrder::getBusinessDocumentId, sub.getId())
.eq(ExecuteOrder::getDelFlag, 1).last("LIMIT 1"));
if (ObjectUtil.isNotNull(subExec)) {
throw new ServiceException("子单【" + sub.getGoodsNumber() + "】已生成执行单,无法反审核主单");
}
subIdStrs.add(String.valueOf(sub.getId()));
// 逻辑删除子单( delete() 方法一致delFlag 2)
sub.setDelFlag(2);
businessDocumentOrderMapper.updateById(sub);
}
// 逻辑删除子单的地址(审核时按 orderId=子单id 生成)
businessDocumentAddressMultiMapper.update(null,
new LambdaUpdateWrapper<BusinessDocumentAddressMulti>()
.in(BusinessDocumentAddressMulti::getOrderId, subIdStrs)
.set(BusinessDocumentAddressMulti::getDelFlag, 2));
// 清空审核时回填到 business_delivery_details_link.sub_order_id 的子单id
businessDeliveryDetailsLinkMapper.update(null,
new LambdaUpdateWrapper<BusinessDeliveryDetailsLink>()
.eq(BusinessDeliveryDetailsLink::getOrderId, id)
.isNotNull(BusinessDeliveryDetailsLink::getSubOrderId)
.set(BusinessDeliveryDetailsLink::getSubOrderId, null));
}
}
// 状态复位 + 清空审核信息( UpdateWrapper.set 确保 null 能写入updateById 默认不更新 null)
LambdaUpdateWrapper<BusinessDocumentOrder> updateWrapper = new LambdaUpdateWrapper<BusinessDocumentOrder>()
.eq(BusinessDocumentOrder::getId, id)
.set(BusinessDocumentOrder::getReviewStatus, 0L) // 未审核
.set(BusinessDocumentOrder::getOrderStatus, 0L) // 待审核
.set(BusinessDocumentOrder::getExecuteStatus, 0L) // 无状态
.set(BusinessDocumentOrder::getReviewId, null)
.set(BusinessDocumentOrder::getReview, null)
.set(BusinessDocumentOrder::getReviewTime, null)
.set(BusinessDocumentOrder::getReviewOpinion, null)
.set(BusinessDocumentOrder::getSalesManager, null);
if (isMain) {
updateWrapper.set(BusinessDocumentOrder::getDeliveryProgress, null); // 清空主单拆单数
}
businessDocumentOrderMapper.update(null, updateWrapper);
}
return true;
}
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean execute(List<Long> ids) { public Boolean execute(List<Long> ids) {
@@ -102,6 +102,9 @@ public class BusinessDocumentOrderDomainService {
@Autowired @Autowired
private UserServiceFeign userServiceFeign; private UserServiceFeign userServiceFeign;
@Autowired
private GoodsNumberGenerator goodsNumberGenerator;
/** /**
* 分页查询请填写功能名称列表 * 分页查询请填写功能名称列表
*/ */
@@ -109,26 +112,6 @@ public class BusinessDocumentOrderDomainService {
return businessDocumentOrderService.queryList(businessDocumentOrderDO); return businessDocumentOrderService.queryList(businessDocumentOrderDO);
} }
public static String getOrderCodeByDate(Date date){
return new StringBuffer()
.append(getSecondPartByDate(date))
.append(getThreePart())
.toString();
}
private static String getSecondPartByDate(Date date) {
if (date == null) {
date = new Date();
}
String temp_current_time = DateUtil.format(date, datePattern());
return temp_current_time.substring(2, temp_current_time.length());
}
private static String datePattern() {
return "yyyyMMddHHmmss";
}
private static String getThreePart() {
return RandomUtil.randomNumbers(4);
}
/** /**
* 新增请填写功能名称 * 新增请填写功能名称
*/ */
@@ -302,30 +285,8 @@ public class BusinessDocumentOrderDomainService {
} }
} }
//生成货源单号 //生成货源单号yyMMdd + 当日顺序号每日重置
String orderCode = goodsNumberGenerator.generateUniqueGoodsNumber(tmsOrder.getDocumentDate());
String orderCode = null;
int maxRetryCount = 100;
int retryCount = 0;
while (retryCount < maxRetryCount) {
orderCode = getOrderCodeByDate(tmsOrder.getDocumentDate());
retryCount++;
List<BusinessDocumentOrder> checkOrderCodes = businessDocumentOrderMapper.selectList(
new QueryWrapper<BusinessDocumentOrder>().eq("goods_number", orderCode)
);
if (CollectionUtils.isEmpty(checkOrderCodes)) {
break;
}
if (retryCount >= maxRetryCount) {
throw new ServiceException("生成唯一订单编号失败,已达到最大重试次数:" + maxRetryCount);
}
}
//生成货源单号
tmsOrder.setGoodsNumber(orderCode); tmsOrder.setGoodsNumber(orderCode);
ReservationStockOutOrder reservationStockOutOrder = reservationStockOutOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockOutOrder>() ReservationStockOutOrder reservationStockOutOrder = reservationStockOutOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockOutOrder>()
@@ -513,6 +474,8 @@ public class BusinessDocumentOrderDomainService {
tmsOrderAccount.setOrderId(String.valueOf(tmsOrder.getId())); tmsOrderAccount.setOrderId(String.valueOf(tmsOrder.getId()));
tmsOrderAccount.setCreateBy(String.valueOf(u.getUserid())); tmsOrderAccount.setCreateBy(String.valueOf(u.getUserid()));
tmsOrderAccount.setCreateTime(new Date()); tmsOrderAccount.setCreateTime(new Date());
// 复制新增时科目行会带原订单的id避免报错
tmsOrderAccount.setId(null);
// 设置组织信息 // 设置组织信息
if (businessDocumentOrderDO.getOrganizationId() != null) { if (businessDocumentOrderDO.getOrganizationId() != null) {
tmsOrderAccount.setOrganizationId(businessDocumentOrderDO.getOrganizationId()); tmsOrderAccount.setOrganizationId(businessDocumentOrderDO.getOrganizationId());
@@ -774,28 +737,8 @@ public class BusinessDocumentOrderDomainService {
// boolean istrue=businessDocumentOrderService.update(businessDocumentOrderDO); // boolean istrue=businessDocumentOrderService.update(businessDocumentOrderDO);
String orderCode = null; //生成货源单号yyMMdd + 当日顺序号每日重置 原更新操作会将 电脑更细为当日的日期默认和之前的逻辑一样保持不变
int maxRetryCount = 100; String orderCode = goodsNumberGenerator.generateUniqueGoodsNumber(tmsOrder.getDocumentDate());
int retryCount = 0;
while (retryCount < maxRetryCount) {
orderCode = getOrderCodeByDate(tmsOrder.getDocumentDate());
retryCount++;
List<BusinessDocumentOrder> checkOrderCodes = businessDocumentOrderMapper.selectList(
new QueryWrapper<BusinessDocumentOrder>().eq("goods_number", orderCode)
);
if (CollectionUtils.isEmpty(checkOrderCodes)) {
break;
}
if (retryCount >= maxRetryCount) {
throw new ServiceException("生成唯一订单编号失败,已达到最大重试次数:" + maxRetryCount);
}
}
//生成货源单号
tmsOrder.setGoodsNumber(orderCode); tmsOrder.setGoodsNumber(orderCode);
ReservationStockOutOrder reservationStockOutOrder = reservationStockOutOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockOutOrder>() ReservationStockOutOrder reservationStockOutOrder = reservationStockOutOrderMapper.selectOne(new LambdaQueryWrapper<ReservationStockOutOrder>()
@@ -989,6 +932,15 @@ public class BusinessDocumentOrderDomainService {
return businessDocumentOrderService.audit(businessAuditDTO.getIds(),businessAuditDTO.getReviewStatus(),businessAuditDTO.getSalesManager(),businessAuditDTO.getReviewOpinion()); return businessDocumentOrderService.audit(businessAuditDTO.getIds(),businessAuditDTO.getReviewStatus(),businessAuditDTO.getSalesManager(),businessAuditDTO.getReviewOpinion());
} }
/**
* 业务单反审核
*/
public Boolean cancelAudit(BusinessAuditDTO businessAuditDTO)
{
return businessDocumentOrderService.cancelAudit(businessAuditDTO.getIds());
}
public Boolean execute(List<Long> ids) { public Boolean execute(List<Long> ids) {
return businessDocumentOrderService.execute(ids); return businessDocumentOrderService.execute(ids);
} }
@@ -0,0 +1,53 @@
package com.mhd.oms.domain.businessDocumentOrder.service;
import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.mhd.common.core.exception.ServiceException;
import com.mhd.oms.domain.businessDocumentOrder.entity.BusinessDocumentOrder;
import com.mhd.oms.domain.businessDocumentOrder.repository.mapper.BusinessDocumentOrderMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import java.util.Date;
import java.util.List;
/**
* 业务单据订单(goodsNumber)单号生成器
* 规则: yyMMdd(取自单据日期) + 当日顺序号(每日重置, 3位起步, 超999自动扩位)
* 示例: 2608040012608049992608041000
*/
@Component
public class GoodsNumberGenerator {
private static final int MAX_RETRY = 100;
@Autowired
private BusinessDocumentOrderMapper businessDocumentOrderMapper;
/**
* 生成唯一业务单号
* @param documentDate 单据日期(为空取当前日期)
*/
public String generateUniqueGoodsNumber(Date documentDate) {
Date date = (documentDate == null) ? new Date() : documentDate;
String datePart = DateUtil.format(date, "yyMMdd");
// count 只查一次作为序号基线
long seq = (long) businessDocumentOrderMapper.countByGoodsNumberPrefix(datePart) + 1;
int retryCount = 0;
while (retryCount < MAX_RETRY) {
String orderCode = datePart + String.format("%03d", seq);
retryCount++;
List<BusinessDocumentOrder> exist = businessDocumentOrderMapper.selectList(
new QueryWrapper<BusinessDocumentOrder>().eq("goods_number", orderCode)
);
if (CollectionUtils.isEmpty(exist)) {
return orderCode;
}
seq++; // 关键查重失败序号往后递增找空位而不是重新count
}
throw new ServiceException("生成唯一业务单号失败,已达到最大重试次数:" + MAX_RETRY);
}
}
@@ -163,6 +163,13 @@ public class ReservationStockInOrderPO extends BaseVOEntity {
@Excel(name = "入库数量") @Excel(name = "入库数量")
private BigDecimal inQuantity; private BigDecimal inQuantity;
/**
* 申报数量入库单明细中申报数量(DECLARED_QUANTITY)汇总
*/
@ApiModelProperty("申报数量")
@Excel(name = "申报数量")
private BigDecimal declaredQuantity;
/** /**
* 计划入库数量取入库单明细中的入库数量汇总 * 计划入库数量取入库单明细中的入库数量汇总
*/ */
@@ -553,6 +553,31 @@ public class ReservationStockInOrderDomainService {
*/ */
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Boolean issueOrder(ReservationStockInOrderDO stockInOrderDO) { public Boolean issueOrder(ReservationStockInOrderDO stockInOrderDO) {
// ===== 新增校验 =====
List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
if (inOrderIds == null || inOrderIds.isEmpty()) {
throw new ServiceException("下发失败:未选择单据");
}
List<ReservationStockInOrder> checkOrders = stockInOrderService.list(
new QueryWrapper<ReservationStockInOrder>().lambda()
.in(ReservationStockInOrder::getInOrderId, inOrderIds));
for (ReservationStockInOrder order : checkOrders) {
// 校验1必须已审核issueStatus==2 表示审核成功
if (order.getIssueStatus() == null || order.getIssueStatus() != 2) {
throw new ServiceException("下发失败:单据[" + order.getInOrderNumber() + "]未审核,无法下发");
}
// 校验2防止重复下发issueTime 有值表示已下发过
if (order.getIssueTime() != null) {
throw new ServiceException("下发失败:单据[" + order.getInOrderNumber() + "]已下发,不可重复下发");
}
// 校验3WMS 必填字段warehouseId 不能为空
if (order.getWarehouseId() == null) {
throw new ServiceException("下发失败:单据[" + order.getInOrderNumber() + "]缺少入库仓库,无法下发");
}
}
// ===== 校验结束 =====
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
// 获取用户姓名优先从UserPo获取如果为空则使用realname最后使用username作为兜底 // 获取用户姓名优先从UserPo获取如果为空则使用realname最后使用username作为兜底
@@ -570,26 +595,34 @@ public class ReservationStockInOrderDomainService {
.in(ReservationStockInOrder::getInOrderId, stockInOrderDO.getInOrderIds())); .in(ReservationStockInOrder::getInOrderId, stockInOrderDO.getInOrderIds()));
//todo下发推送到wms //todo下发推送到wms
// List<Long> inOrderIds = stockInOrderDO.getInOrderIds(); for (Long inOrderId : inOrderIds) {
// for (Long inOrderId : inOrderIds) { ReservationStockInOrder byId = stockInOrderService.getById(inOrderId);
// ReservationStockInOrder byId = stockInOrderService.getById(inOrderId); StockInOrder stockInOrder = new StockInOrder();
// StockInOrder stockInOrder = new StockInOrder(); BeanUtils.copyProperties(byId, stockInOrder, "inOrderId");
// BeanUtils.copyProperties(byId, stockInOrder,"inOrderId"); stockInOrder.setOmsStockInOrderId(String.valueOf(byId.getInOrderId()));
// stockInOrder.setOmsStockInOrderId(String.valueOf(byId.getInOrderId()));
// wmsServiceFeign.omsInOrderAdd(stockInOrder); try {
// String inOrderNumber = stockInOrder.getInOrderNumber(); wmsServiceFeign.omsInOrderAdd(stockInOrder); // 推主单
// List<ReservationInMaterialDetail> materialDetailList = materialDetailService.list(new QueryWrapper<ReservationInMaterialDetail>().lambda().eq(ReservationInMaterialDetail::getInOrderNumber, inOrderNumber));
// List<InMaterialDetail> inMaterialDetailList = new ArrayList<>(); String inOrderNumber = stockInOrder.getInOrderNumber();
// for (ReservationInMaterialDetail reservationInMaterialDetail : materialDetailList) { List<ReservationInMaterialDetail> materialDetailList = materialDetailService.list(
// InMaterialDetail inMaterialDetail = new InMaterialDetail(); new QueryWrapper<ReservationInMaterialDetail>().lambda()
// BeanUtils.copyProperties(reservationInMaterialDetail, inMaterialDetail,"materialDetailId"); .eq(ReservationInMaterialDetail::getInOrderNumber, inOrderNumber));
// inMaterialDetail.setOmsInMaterialDetail(String.valueOf(reservationInMaterialDetail.getMaterialDetailId())); List<InMaterialDetail> inMaterialDetailList = new ArrayList<>();
// inMaterialDetailList.add(inMaterialDetail); for (ReservationInMaterialDetail reservationInMaterialDetail : materialDetailList) {
// } InMaterialDetail inMaterialDetail = new InMaterialDetail();
// wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList); BeanUtils.copyProperties(reservationInMaterialDetail, inMaterialDetail, "materialDetailId");
// } inMaterialDetail.setOmsInMaterialDetail(String.valueOf(reservationInMaterialDetail.getMaterialDetailId()));
inMaterialDetailList.add(inMaterialDetail);
}
wmsServiceFeign.omsInOrderAddDetail(inMaterialDetailList); // 推明细会触发WMS自动审核
log.info("下发到WMS成功,单据号:{}", byId.getInOrderNumber());
} catch (Exception e) {
log.error("下发到WMS失败,单据号:{}", byId.getInOrderNumber(), e);
throw new ServiceException("下发到WMS失败:" + e.getMessage());
}
}
//todo下发推送到入库业务单 //todo下发推送到入库业务单
List<Long> inOrderIds = stockInOrderDO.getInOrderIds();
for (Long inOrderId : inOrderIds) { for (Long inOrderId : inOrderIds) {
// Long inOrderId = stockInOrderDO.getInOrderId(); // Long inOrderId = stockInOrderDO.getInOrderId();
ReservationStockInOrder byId = stockInOrderService.getById(inOrderId); ReservationStockInOrder byId = stockInOrderService.getById(inOrderId);
@@ -22,7 +22,7 @@ import java.util.Map;
/** /**
* 三方服务 Feign * 三方服务 Feign
*/ */
@FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.102.192.31:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class) @FeignClient(contextId = "thirdPartyServiceFeign",url = "http://10.102.192.30:8012", value = ServiceNameConstants.THIRDPARTY_CENTER, configuration = FeignAutoConfiguration.class)
public interface ThirdPartyServiceFeign { public interface ThirdPartyServiceFeign {
//查询当前组织所有三方接口信息 //查询当前组织所有三方接口信息
@@ -108,6 +108,16 @@ public class BusinessDocumentOrderApi extends BaseController{
return AjaxResult.success(businessDocumentOrderApplicationService.audit(businessAuditDTO)); return AjaxResult.success(businessDocumentOrderApplicationService.audit(businessAuditDTO));
} }
/**
* 业务单反审核将已审核订单恢复到待审核便于修改
*/
@ApiOperation("业务单反审核")
@PostMapping(value = "/cancelAudit")
public AjaxResult cancelAudit(@RequestBody BusinessAuditDTO businessAuditDTO)
{
return toAjax(businessDocumentOrderApplicationService.cancelAudit(businessAuditDTO));
}
/** /**
* 批量执行业务单 * 批量执行业务单
*/ */
@@ -709,7 +709,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="queryList" parameterType="com.mhd.oms.domain.businessDocumentOrder.repository.todo.BusinessDocumentOrderDO" resultMap="BusinessDocumentOrderResult"> <select id="queryList" parameterType="com.mhd.oms.domain.businessDocumentOrder.repository.todo.BusinessDocumentOrderDO" resultMap="BusinessDocumentOrderResult">
<include refid="selectBusinessDocumentOrderPo"/> <include refid="selectBusinessDocumentOrderPo"/>
<include refid="selectBusinessDocumentOrderPo1"/> <include refid="selectBusinessDocumentOrderPo1"/>
order by create_time desc order by lay_date desc, create_time desc
</select> </select>
<select id="selectByMakerCodeNc" parameterType="java.lang.String" resultType="java.lang.String"> <select id="selectByMakerCodeNc" parameterType="java.lang.String" resultType="java.lang.String">
select DOCUMENT_PREPARER_NC_code from NGWL_TEST_USER."USER" where USER_ID = #{salesmanCodeNc}</select> select DOCUMENT_PREPARER_NC_code from NGWL_TEST_USER."USER" where USER_ID = #{salesmanCodeNc}</select>
@@ -1272,4 +1272,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
select PUSH_VERIFY from NGWL_TEST_PRODUCT.SYS_ORGANIZATION where ORGANIZATION_ID = #{organizationId} select PUSH_VERIFY from NGWL_TEST_PRODUCT.SYS_ORGANIZATION where ORGANIZATION_ID = #{organizationId}
</select> </select>
<select id="countByGoodsNumberPrefix" resultType="java.lang.Integer">
SELECT COUNT(1)
FROM business_document_order
WHERE goods_number LIKE concat(#{prefix}, '%')
AND LENGTH(goods_number) &lt;= 12
</select>
</mapper> </mapper>
@@ -131,7 +131,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<select id="queryList" parameterType="com.mhd.oms.domain.executeOrder.repository.todo.ExecuteOrderDO" resultMap="ExecuteOrderResult"> <select id="queryList" parameterType="com.mhd.oms.domain.executeOrder.repository.todo.ExecuteOrderDO" resultMap="ExecuteOrderResult">
<include refid="selectExecuteOrderPo"/> <include refid="selectExecuteOrderPo"/>
<include refid="selectExecuteOrderPo1"/> <include refid="selectExecuteOrderPo1"/>
order by CREATE_TIME desc order by lay_date desc, CREATE_TIME desc
</select> </select>
<select id="getOrgNameByOrgId" resultType="java.lang.String"> <select id="getOrgNameByOrgId" resultType="java.lang.String">
select ORGANIZATION_NAME from NGWL_TEST_PRODUCT.SYS_ORGANIZATION where ORGANIZATION_ID=#{organizationId} select ORGANIZATION_NAME from NGWL_TEST_PRODUCT.SYS_ORGANIZATION where ORGANIZATION_ID=#{organizationId}
@@ -33,6 +33,7 @@
<result property="directWarehouse" column="direct_warehouse" /> <result property="directWarehouse" column="direct_warehouse" />
<result property="annexUrl" column="annex_url" /> <result property="annexUrl" column="annex_url" />
<result property="quantity" column="quantity" /> <result property="quantity" column="quantity" />
<result property="declaredQuantity" column="declared_quantity" />
<result property="planInQuantity" column="plan_in_quantity" /> <result property="planInQuantity" column="plan_in_quantity" />
<result property="receiptQuantity" column="receipt_quantity" /> <result property="receiptQuantity" column="receipt_quantity" />
<result property="shelvesQuantity" column="shelves_quantity" /> <result property="shelvesQuantity" column="shelves_quantity" />
@@ -136,6 +137,13 @@
<!-- where sso.in_order_number = a.in_order_number--> <!-- where sso.in_order_number = a.in_order_number-->
<!-- and sso.del_flag = 1--> <!-- and sso.del_flag = 1-->
<!-- ) as shelves_quantity,--> <!-- ) as shelves_quantity,-->
-- 申报数量:入库单明细表 reservation_in_material_detail 的 DECLARED_QUANTITY 汇总
(select ifnull(sum(imd.declared_quantity), 0)
from reservation_in_material_detail imd
where imd.in_order_number = a.in_order_number
and imd.del_flag = 1
and (imd.level is null or imd.level = 1)
) as declared_quantity,
a.weight_limit, a.volume_limit, a.cancel_order, a.cancel_remark, a.cancel_by,a.PICTURE_URL, a.weight_limit, a.volume_limit, a.cancel_order, a.cancel_remark, a.cancel_by,a.PICTURE_URL,
a.cancel_by_name, a.cancel_time, a.close_order, a.close_remark, a.close_by, a.close_by_name, a.close_time, a.remark, a.create_time, a.create_by, a.cancel_by_name, a.cancel_time, a.close_order, a.close_remark, a.close_by, a.close_by_name, a.close_time, a.remark, a.create_time, a.create_by,
a.create_by_name, a.update_time, a.update_by, a.update_by_name, a.del_flag, a.over_stock_id, a.over_stock_status, a.over_stock_type, a.create_by_name, a.update_time, a.update_by, a.update_by_name, a.del_flag, a.over_stock_id, a.over_stock_status, a.over_stock_type,
@@ -8,6 +8,7 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient; import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.ComponentScan;
import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication @SpringBootApplication
@EnableRyFeignClients @EnableRyFeignClients
@@ -15,6 +16,7 @@ import org.springframework.scheduling.annotation.EnableAsync;
@MapperScan("com.mhd.wms.domain.**.mapper") @MapperScan("com.mhd.wms.domain.**.mapper")
@EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache") @EnableMethodCache(basePackages = "com.mhd.platform.domain.**.cache")
@EnableAsync @EnableAsync
//@EnableScheduling
@ComponentScan(basePackages = { @ComponentScan(basePackages = {
"com.mhd.wms", "com.mhd.wms",
"com.mhd.system.api.factory" "com.mhd.system.api.factory"
@@ -270,10 +270,17 @@ public class HandoverTaskOrderApplicationService {
.eq(HandoverTaskOrder::getOrderNumber, orderNumber) .eq(HandoverTaskOrder::getOrderNumber, orderNumber)
.set(HandoverTaskOrder::getBillingJson, handoverTaskOrderDO.getBillingJson()) .set(HandoverTaskOrder::getBillingJson, handoverTaskOrderDO.getBillingJson())
.set(HandoverTaskOrder::getPictureApp, handoverTaskOrderDO.getPictureApp())); .set(HandoverTaskOrder::getPictureApp, handoverTaskOrderDO.getPictureApp()));
// 2. PDA上传图片插入出库管理状态改为已出库 // // 2. 状态按是否报关仅通宇(2830)+需报关已交接(13)否则已出库(9)
// StockOutOrder soo = stockOutOrderService.getOne(new LambdaQueryWrapper<StockOutOrder>()
// .eq(StockOutOrder::getOutOrderNumber, orderNumber));
// boolean needCustoms = soo != null
// && Long.valueOf(2830L).equals(soo.getOrganizationId())
// && "1".equals(soo.getNeedDeclareFlag());
// int targetStatus = needCustoms ? 13 : 9;
stockOutOrderService.update(new LambdaUpdateWrapper<StockOutOrder>() stockOutOrderService.update(new LambdaUpdateWrapper<StockOutOrder>()
.eq(StockOutOrder::getOutOrderNumber, orderNumber) .eq(StockOutOrder::getOutOrderNumber, orderNumber)
.set(StockOutOrder::getStatus, "9") // .set(StockOutOrder::getStatus, targetStatus)
.set(StockOutOrder::getStatus, 9) // 不注释之后需要删除
.set(StockOutOrder::getBillingJson, handoverTaskOrderDO.getBillingJson()) .set(StockOutOrder::getBillingJson, handoverTaskOrderDO.getBillingJson())
.set(StockOutOrder::getPictureApp, handoverTaskOrderDO.getPictureApp())); .set(StockOutOrder::getPictureApp, handoverTaskOrderDO.getPictureApp()));
// 3. 参考PC端完成交接根据orderNumber查询交接单ID执行库存扣减+交接状态更新 // 3. 参考PC端完成交接根据orderNumber查询交接单ID执行库存扣减+交接状态更新
@@ -36,6 +36,7 @@ import com.mhd.wms.domain.handoverTaskOrder.repository.facade.IHandoverTaskOrder
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail; import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService; import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO; import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo; import com.mhd.wms.domain.materialBaseInfo.entity.MaterialBaseInfo;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
@@ -242,7 +243,40 @@ public class StockInOrderApplicationService {
} }
} }
List<StockInOrderPO> stockInOrderPOS = stockInOrderDomainService.queryList(stockInOrderDO); List<StockInOrderPO> stockInOrderPOS = stockInOrderDomainService.queryList(stockInOrderDO);
if (CollectionUtils.isEmpty(stockInOrderPOS)) {
return stockInOrderPOS;
}
List<String> inOrderNumbers = stockInOrderPOS.stream()
.map(StockInOrderPO::getInOrderNumber)
.filter(Objects::nonNull)
.collect(Collectors.toList());
// 列表页展示按入库单号批量取去重后的 Invoice No
Map<String, String> invoiceNoByNum = new HashMap<>();
inMaterialDetailService.selectDistinctInvoiceNoForStockInList(inOrderNumbers)
.stream()
.filter(a -> StringUtils.isNotBlank(a.getInvoiceNo()))
.forEach(a -> invoiceNoByNum.merge(a.getInOrderNumber(), a.getInvoiceNo().trim(), (o, n) -> o + "," + n));
// 导出场景needDetail=true批量取出完整明细树level=1 父行 + children按入库单号分组挂到列表
// 注释掉 needDetail 判断列表/导出统一返回明细
Map<String, List<InMaterialDetailPO>> detailByNum = Collections.emptyMap();
// if (Boolean.TRUE.equals(stockInOrderDO.getNeedDetail()) && !CollectionUtils.isEmpty(inOrderNumbers)) {
if (!CollectionUtils.isEmpty(inOrderNumbers)) {
InMaterialDetailDO detailQuery = new InMaterialDetailDO();
detailQuery.setInOrderNumberList(inOrderNumbers);
List<InMaterialDetailPO> detailTreeList = inMaterialDetailService.queryListChildren(detailQuery);
detailByNum = detailTreeList.stream()
.collect(Collectors.groupingBy(InMaterialDetailPO::getInOrderNumber));
}
for (StockInOrderPO stockInOrderPO : stockInOrderPOS) { for (StockInOrderPO stockInOrderPO : stockInOrderPOS) {
if (invoiceNoByNum.containsKey(stockInOrderPO.getInOrderNumber())) {
stockInOrderPO.setInvoiceNo(invoiceNoByNum.get(stockInOrderPO.getInOrderNumber()));
}
// if (Boolean.TRUE.equals(stockInOrderDO.getNeedDetail())) {
stockInOrderPO.setMaterialDetailList(detailByNum.getOrDefault(stockInOrderPO.getInOrderNumber(), Collections.emptyList()));
// }
Long inOrderId = stockInOrderPO.getInOrderId(); Long inOrderId = stockInOrderPO.getInOrderId();
List<ReceiptOrderAccount> list = receiptOrderAccountService.list(new LambdaQueryWrapper<ReceiptOrderAccount>().eq(ReceiptOrderAccount::getOrderId, inOrderId).eq(ReceiptOrderAccount::getInOrOut, "in")); List<ReceiptOrderAccount> list = receiptOrderAccountService.list(new LambdaQueryWrapper<ReceiptOrderAccount>().eq(ReceiptOrderAccount::getOrderId, inOrderId).eq(ReceiptOrderAccount::getInOrOut, "in"));
stockInOrderPO.setReceiptOrderAccountList(list); stockInOrderPO.setReceiptOrderAccountList(list);
@@ -253,9 +253,35 @@ public class StockOutOrderApplicationService {
accountByOrderId = accounts.stream().collect(Collectors.groupingBy(ReceiptOrderAccount::getOrderId)); accountByOrderId = accounts.stream().collect(Collectors.groupingBy(ReceiptOrderAccount::getOrderId));
} }
// 列表页展示按出库单号批量取去重后的 Invoice No
Map<String, String> invoiceNoByNum = new HashMap<>();
outMaterialDetailService.selectDistinctInvoiceNoForStockOutList(outOrderNumbers)
.stream()
.filter(a -> StringUtils.isNotBlank(a.getInvoiceNo()))
.forEach(a -> invoiceNoByNum.merge(a.getOutOrderNumber(), a.getInvoiceNo().trim(), (o, n) -> o + "," + n));
// 导出场景needDetail=true批量取出完整明细树level=1 父行 + children按出库单号分组挂到列表
// 注释掉 needDetail 判断列表/导出统一返回明细
Map<String, List<OutMaterialDetailPO>> detailByNum = Collections.emptyMap();
// if (Boolean.TRUE.equals(stockOutOrderDO.getNeedDetail()) && !CollectionUtils.isEmpty(outOrderNumbers)) {
if (!CollectionUtils.isEmpty(outOrderNumbers)) {
OutMaterialDetailDO detailQuery = new OutMaterialDetailDO();
detailQuery.setOutOrderNumberList(outOrderNumbers);
List<OutMaterialDetailPO> detailTreeList = outMaterialDetailService.queryListChildren(detailQuery);
detailByNum = detailTreeList.stream()
.collect(Collectors.groupingBy(OutMaterialDetailPO::getOutOrderNumber));
}
for (StockOutOrderPO stockOutOrderPO : stockOutOrderPOS) { for (StockOutOrderPO stockOutOrderPO : stockOutOrderPOS) {
String outOrderNumber = stockOutOrderPO.getOutOrderNumber(); String outOrderNumber = stockOutOrderPO.getOutOrderNumber();
if (invoiceNoByNum.containsKey(outOrderNumber)) {
stockOutOrderPO.setInvoiceNo(invoiceNoByNum.get(outOrderNumber));
}
// if (Boolean.TRUE.equals(stockOutOrderDO.getNeedDetail())) {
stockOutOrderPO.setMaterialDetailList(detailByNum.getOrDefault(outOrderNumber, Collections.emptyList()));
// }
List<DeliveryDetailsLink> list = deliveryDetailsLinkService.list(new LambdaQueryWrapper<DeliveryDetailsLink>().eq(DeliveryDetailsLink::getOrderNumber, outOrderNumber)); List<DeliveryDetailsLink> list = deliveryDetailsLinkService.list(new LambdaQueryWrapper<DeliveryDetailsLink>().eq(DeliveryDetailsLink::getOrderNumber, outOrderNumber));
stockOutOrderPO.setDeliveryDetailsLinkList(list); stockOutOrderPO.setDeliveryDetailsLinkList(list);
@@ -2915,6 +2915,7 @@ public class StockReceiptOrderApplicationService {
returnReceiptMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight()); returnReceiptMaterialDetailDO.setTotalGrossWeight(receiptMaterialDetailDO.getTotalGrossWeight());
returnReceiptMaterialDetailDO.setTotalVolume(receiptMaterialDetailDO.getTotalVolume()); returnReceiptMaterialDetailDO.setTotalVolume(receiptMaterialDetailDO.getTotalVolume());
returnReceiptMaterialDetailDO.setTotalArea(receiptMaterialDetailDO.getTotalArea()); returnReceiptMaterialDetailDO.setTotalArea(receiptMaterialDetailDO.getTotalArea());
returnReceiptMaterialDetailDO.setDimensions(receiptMaterialDetailDO.getDimensions());
BigDecimal parentRetAlreadyQty = receiptMaterialDetailDO.getAlreadyReceiptQuantity() != null BigDecimal parentRetAlreadyQty = receiptMaterialDetailDO.getAlreadyReceiptQuantity() != null
? receiptMaterialDetailDO.getAlreadyReceiptQuantity() : BigDecimal.ZERO; ? receiptMaterialDetailDO.getAlreadyReceiptQuantity() : BigDecimal.ZERO;
returnReceiptMaterialDetailDO.setAlreadyReceiptQuantity(parentRetAlreadyQty); returnReceiptMaterialDetailDO.setAlreadyReceiptQuantity(parentRetAlreadyQty);
@@ -1,5 +1,18 @@
package com.mhd.wms.domain.handoverTaskOrder.service; package com.mhd.wms.domain.handoverTaskOrder.service;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.mhd.common.core.web.domain.AjaxResult;
import com.mhd.wms.domain.customsDeclarationDetail.repository.todo.CustomsDeclarationDetailDO;
import com.mhd.wms.domain.customsDeclarationDetail.repository.facade.ICustomsDeclarationDetailService;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.util.EntityUtils;
import org.springframework.scheduling.annotation.Scheduled;
import java.text.SimpleDateFormat;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -86,6 +99,29 @@ public class HandoverTaskOrderDomainService {
private CopyCodeReferenceDomainService copyCodeReferenceDomainService; private CopyCodeReferenceDomainService copyCodeReferenceDomainService;
@Autowired @Autowired
private OmsServiceFeign omsServiceFeign; private OmsServiceFeign omsServiceFeign;
// @Autowired
// private ICustomsDeclarationDetailService customsDeclarationDetailService;
// // 报关回写相关常量
// private static final String CUSTOMS_PUSH_API_URL = "http://10.102.192.15/nagu-erp-api/transfer/pushData";
// private static final String CUSTOMS_VERIFY = "ESLuxAmB6VXCgbqP1eFzxTPVRagkQ62BUkfhElrgQ6XmE/g2reHVflY/SiCSU7JD";
// // 通宇组织ID只有通宇才启用报关出库流程
// private static final Long TONGYU_ORGANIZATION_ID = 2830L;
// // 视为海关已放行/结关的状态码建议做成 @Value("${gw.customs.pass-status:P,I,R,F,K,B}")
// // 视为海关已放行的状态码ERP 确认只有 P=海关已放行 才表示货物可出库
// private static final String[] CUSTOMS_PASS_STATUS = {"P"};
// // 退单/失败状态码记告警用
// private static final String[] CUSTOMS_FAIL_STATUS = {"E", "A", "D", "Z", "c", "H"};
//
// /**
// * 判断是否需要走报关出库流程仅通宇 + needDeclareFlag=1
// * 其它组织一律走老流程交接直接出库
// */
// private boolean isCustomsDeclareOrder(StockOutOrder stockOutOrder) {
// return stockOutOrder != null
// && TONGYU_ORGANIZATION_ID.equals(stockOutOrder.getOrganizationId())
// && "1".equals(stockOutOrder.getNeedDeclareFlag());
// }
/** /**
@@ -293,16 +329,22 @@ public class HandoverTaskOrderDomainService {
LoginUser loginUser = SecurityUtils.getLoginUser(); LoginUser loginUser = SecurityUtils.getLoginUser();
//修改库存 //修改库存
xgkc(handoverTaskOrderIds,loginUser); xgkc(handoverTaskOrderIds,loginUser);
//推送oms //推送oms需报关的单子等海关确认放行后再推
for (Long handoverTaskOrderId : handoverTaskOrderIds) { for (Long handoverTaskOrderId : handoverTaskOrderIds) {
HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getById(handoverTaskOrderId); // HandoverTaskOrder hto = handoverTaskOrderService.getById(handoverTaskOrderId);
String orderNumber = handoverTaskOrder.getOrderNumber(); // if (hto == null) {
StockOutOrder stockOutOrder = stockOutOrderService.getOne(new LambdaQueryWrapper<StockOutOrder>() // continue;
.eq(StockOutOrder::getOutOrderNumber, orderNumber) // }
.eq(StockOutOrder::getDelFlag, 1), false); // StockOutOrder soo = stockOutOrderMapper.selectOne(new QueryWrapper<StockOutOrder>().lambda()
if (stockOutOrder != null && !"yang_pin_chu_ku".equals(stockOutOrder.getBusinessType())) { // .eq(StockOutOrder::getOutOrderNumber, hto.getOrderNumber()));
pushOms(handoverTaskOrderId); // if (isCustomsDeclareOrder(soo)) {
} // continue; // 需报关仅通宇跳过
// }
// if (soo != null && !"yang_pin_chu_ku".equals(soo.getBusinessType())) {
// pushOms(handoverTaskOrderId);
// }
// 推送 oms 当上面不注释时需要将这个删除
pushOms(handoverTaskOrderId);
} }
HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getById(handoverTaskOrderIds.get(0)); HandoverTaskOrder handoverTaskOrder = handoverTaskOrderService.getById(handoverTaskOrderIds.get(0));
stockOutOrderService.update(null,new UpdateWrapper<StockOutOrder>().lambda().set(StockOutOrder::getBillingJson,handoverTaskOrderDO.getBillingJson()).eq(StockOutOrder::getOutOrderNumber,handoverTaskOrder.getOrderNumber())); stockOutOrderService.update(null,new UpdateWrapper<StockOutOrder>().lambda().set(StockOutOrder::getBillingJson,handoverTaskOrderDO.getBillingJson()).eq(StockOutOrder::getOutOrderNumber,handoverTaskOrder.getOrderNumber()));
@@ -346,191 +388,271 @@ public class HandoverTaskOrderDomainService {
if (stockOutOrder == null) { if (stockOutOrder == null) {
continue; continue;
} }
// // 需要报关仅通宇+needDeclareFlag=1交接时只改状态为已交接(13)不扣库存/不推OMS等海关确认放行后再处理
// if (isCustomsDeclareOrder(stockOutOrder)) {
// stockOutOrder.setStatus(13);
// stockOutOrderMapper.updateById(stockOutOrder);
// continue; // 跳过下方扣库存逻辑B/C/D/E 全部延后到海关确认
// }
// // 不需要报关维持原逻辑状态改已出库(9)+ 扣库存
//完成交接状态改为已出库 //完成交接状态改为已出库
stockOutOrder.setStatus(9); stockOutOrder.setStatus(9);
stockOutOrderMapper.updateById(stockOutOrder); stockOutOrderMapper.updateById(stockOutOrder);
List<OutMaterialDetail> outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper<OutMaterialDetail>().lambda() doStockOutDeduct(orderNumber, stockOutOrder, loginUser);
.eq(OutMaterialDetail::getOutOrderNumber, orderNumber) }
.eq(OutMaterialDetail::getDelFlag, 1)); }
Integer review = stockOutOrder != null ? stockOutOrder.getReview() : null;
for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) {
//oms详情同步
OMSWarehouseEntryDetails(outMaterialDetail);
if (outMaterialDetail.getCopyCodeReferenceIds() != null){
List<Integer> copyCodeReferenceIds = Arrays.stream(outMaterialDetail.getCopyCodeReferenceIds().split(","))
.map(Integer::parseInt).collect(Collectors.toList());
copyCodeReferenceService.lambdaUpdate()
.set(CopyCodeReference::getMaterialStatusCode, 3)
.set(CopyCodeReference::getMaterialStatusName, "已出库")
.in(CopyCodeReference::getId, copyCodeReferenceIds);
}
Long materialInventoryId = outMaterialDetail.getMaterialInventoryId();
// 复核什么扣减什么需要复核用check_quantity不需要复核用picking_quantity
BigDecimal effectiveQuantity = Integer.valueOf(1).equals(review)
? outMaterialDetail.getCheckQuantity()
: (outMaterialDetail.getPickingQuantity() != null ? outMaterialDetail.getPickingQuantity() : outMaterialDetail.getQuantity());
if (materialInventoryId == null || effectiveQuantity == null || effectiveQuantity.compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
BigDecimal checkQuantity = effectiveQuantity;
BigDecimal checkArea = outMaterialDetail.getCheckArea();
BigDecimal checkVolume = outMaterialDetail.getCheckVolume();
BigDecimal checkGrossWeight = outMaterialDetail.getCheckGrossWeight();
BigDecimal checkNetWeight = outMaterialDetail.getCheckNetWeight();
// 初始化检查数据避免空指针 /**
checkQuantity = checkQuantity != null ? checkQuantity : BigDecimal.ZERO; * 出库扣减同步OMS明细 + 联单状态 + 扣实物库存 + 推OMS库存
checkArea = checkArea != null ? checkArea : BigDecimal.ZERO; * xgkc 抽取不需报关交接海关确认两处复用
checkVolume = checkVolume != null ? checkVolume : BigDecimal.ZERO; */
checkGrossWeight = checkGrossWeight != null ? checkGrossWeight : BigDecimal.ZERO; private void doStockOutDeduct(String orderNumber, StockOutOrder stockOutOrder, LoginUser loginUser) {
checkNetWeight = checkNetWeight != null ? checkNetWeight : BigDecimal.ZERO; List<OutMaterialDetail> outMaterialDetailList = outMaterialDetailMapper.selectList(new QueryWrapper<OutMaterialDetail>().lambda()
.eq(OutMaterialDetail::getOutOrderNumber, orderNumber)
.eq(OutMaterialDetail::getDelFlag, 1));
Integer review = stockOutOrder.getReview();
for (OutMaterialDetail outMaterialDetail : outMaterialDetailList) {
// === 以下把原 L349-513 的循环体原样搬进来一行不改 ===
// oms详情同步
OMSWarehouseEntryDetails(outMaterialDetail);
if (outMaterialDetail.getCopyCodeReferenceIds() != null) {
List<Integer> copyCodeReferenceIds = Arrays.stream(outMaterialDetail.getCopyCodeReferenceIds().split(","))
.map(Integer::parseInt).collect(Collectors.toList());
copyCodeReferenceService.lambdaUpdate()
.set(CopyCodeReference::getMaterialStatusCode, 3)
.set(CopyCodeReference::getMaterialStatusName, "已出库")
.in(CopyCodeReference::getId, copyCodeReferenceIds);
}
Long materialInventoryId = outMaterialDetail.getMaterialInventoryId();
BigDecimal effectiveQuantity = Integer.valueOf(1).equals(review)
? outMaterialDetail.getCheckQuantity()
: (outMaterialDetail.getPickingQuantity() != null ? outMaterialDetail.getPickingQuantity() : outMaterialDetail.getQuantity());
if (materialInventoryId == null || effectiveQuantity == null || effectiveQuantity.compareTo(BigDecimal.ZERO) <= 0) {
continue;
}
BigDecimal checkQuantity = effectiveQuantity;
BigDecimal checkArea = outMaterialDetail.getCheckArea();
BigDecimal checkVolume = outMaterialDetail.getCheckVolume();
BigDecimal checkGrossWeight = outMaterialDetail.getCheckGrossWeight();
BigDecimal checkNetWeight = outMaterialDetail.getCheckNetWeight();
checkQuantity = checkQuantity != null ? checkQuantity : BigDecimal.ZERO;
checkArea = checkArea != null ? checkArea : BigDecimal.ZERO;
checkVolume = checkVolume != null ? checkVolume : BigDecimal.ZERO;
checkGrossWeight = checkGrossWeight != null ? checkGrossWeight : BigDecimal.ZERO;
checkNetWeight = checkNetWeight != null ? checkNetWeight : BigDecimal.ZERO;
MaterialInventory materialInventoryPO = materialInventoryMapper.selectById(materialInventoryId); MaterialInventory materialInventoryPO = materialInventoryMapper.selectById(materialInventoryId);
if (materialInventoryPO != null) {
MaterialInventoryParamDO materialInventoryParamDO = new MaterialInventoryParamDO();
materialInventoryParamDO.setArea(checkArea);
materialInventoryParamDO.setVolume(checkVolume);
materialInventoryParamDO.setGrossWeight(checkGrossWeight);
materialInventoryParamDO.setNetWeight(checkNetWeight);
materialInventoryParamDO.setQuantity(checkQuantity);
materialInventoryParamDO.setMaterialInventoryId(materialInventoryPO.getMaterialInventoryId());
materialInventoryParamDO.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId());
materialInventoryParamDO.setLotNumber(outMaterialDetail.getLotNo());
materialInventoryParamDO.setBatchNumber(outMaterialDetail.getBatchNumber());
materialInventoryParamDO.setInOrderNumber(materialInventoryPO.getInOrderNumber());
materialInventoryParamDO.setProductionDate(materialInventoryPO.getProductionDate());
materialInventoryParamDO.setExpiryDate(materialInventoryPO.getExpiryDate());
materialInventoryParamDO.setType("4");
materialInventoryParamDO.setWarehouseId(materialInventoryPO.getWarehouseId());
//oms库存同步 MaterialInventoryOmsParamDO materialInventoryOmsParamDO = new MaterialInventoryOmsParamDO();
//OMSInventorySynchronization(outMaterialDetail,checkQuantity); BeanUtils.copyProperties(materialInventoryParamDO, materialInventoryOmsParamDO);
if (materialInventoryPO != null) { materialInventoryOmsParamDO.setKctzType("出库");
MaterialInventoryParamDO materialInventoryParamDO = new MaterialInventoryParamDO(); materialInventoryOmsParamDO.setLoginUser(loginUser);
//更新库存数量 if (stockOutOrder != null && !"yang_pin_chu_ku".equals(stockOutOrder.getBusinessType())) {
materialInventoryService.kctzjl(materialInventoryParamDO,"出库",loginUser);
// //库存数量 materialInventoryService.xgkc(materialInventoryParamDO);
// BigDecimal oldInventoryQuantity = materialInventoryPO.getInventoryQuantity(); //库存推送oms
// oldInventoryQuantity = oldInventoryQuantity != null ? oldInventoryQuantity : BigDecimal.ZERO; omsServiceFeign.omsEdit(materialInventoryOmsParamDO);
// //可用数量
// BigDecimal oldAllocationQuantity = materialInventoryPO.getAllocationQuantity();
// oldAllocationQuantity = oldAllocationQuantity != null ? oldAllocationQuantity : BigDecimal.ZERO;
// //冻结数量出库交接不变动冻结数量
// BigDecimal oldFreezeQuantity = materialInventoryPO.getFreezeQuantity();
// oldFreezeQuantity = oldFreezeQuantity != null ? oldFreezeQuantity : BigDecimal.ZERO;
// //扣减后库存数量
// BigDecimal newInventoryQuantity = oldInventoryQuantity.subtract(checkQuantity);
// //扣减后可用数量
// BigDecimal newAllocationQuantity = oldAllocationQuantity.subtract(checkQuantity);
// BigDecimal newFreezeQuantity = oldFreezeQuantity;
//
//
//
// BigDecimal oldArea = materialInventoryPO.getArea();
// BigDecimal oldVolume = materialInventoryPO.getVolume();
// BigDecimal oldGrossWeight = materialInventoryPO.getGrossWeight();
// BigDecimal oldNetWeight = materialInventoryPO.getNetWeight();
//
// // 初始化旧数据避免空指针
// oldArea = oldArea != null ? oldArea : BigDecimal.ZERO;
// oldVolume = oldVolume != null ? oldVolume : BigDecimal.ZERO;
// oldGrossWeight = oldGrossWeight != null ? oldGrossWeight : BigDecimal.ZERO;
// oldNetWeight = oldNetWeight != null ? oldNetWeight : BigDecimal.ZERO;
//
// BigDecimal newArea = oldArea.subtract(checkArea);
// BigDecimal newVolume = oldVolume.subtract(checkVolume);
// BigDecimal newGrossWeight = oldGrossWeight.subtract(checkGrossWeight);
// BigDecimal newNetWeight = oldNetWeight.subtract(checkNetWeight);
//
// materialInventoryPO.setInventoryQuantity(newInventoryQuantity);
// materialInventoryPO.setAllocationQuantity(materialInventoryPO.getAllocationQuantity());
// materialInventoryPO.setFreezeQuantity(materialInventoryPO.getFreezeQuantity().subtract(outMaterialDetail.getCheckQuantity()) );
// materialInventoryPO.setArea(newArea);
// materialInventoryPO.setVolume(newVolume);
// materialInventoryPO.setGrossWeight(newGrossWeight);
// materialInventoryPO.setNetWeight(newNetWeight);
// MaterialInventory materialInventory = new MaterialInventory();
// BeanUtils.copyProperties(materialInventoryPO, materialInventory);
//materialInventoryMapper.updateById(materialInventory);
materialInventoryParamDO.setArea(checkArea);
materialInventoryParamDO.setVolume(checkVolume);
materialInventoryParamDO.setGrossWeight(checkGrossWeight);
materialInventoryParamDO.setNetWeight(checkNetWeight);
materialInventoryParamDO.setQuantity(checkQuantity);
materialInventoryParamDO.setMaterialInventoryId(materialInventoryPO.getMaterialInventoryId());
materialInventoryParamDO.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId());
materialInventoryParamDO.setLotNumber(outMaterialDetail.getLotNo());
materialInventoryParamDO.setBatchNumber(outMaterialDetail.getBatchNumber());
materialInventoryParamDO.setInOrderNumber(materialInventoryPO.getInOrderNumber());
materialInventoryParamDO.setProductionDate(materialInventoryPO.getProductionDate());
materialInventoryParamDO.setExpiryDate(materialInventoryPO.getExpiryDate());
materialInventoryParamDO.setType("4");
materialInventoryParamDO.setWarehouseId(materialInventoryPO.getWarehouseId());
//样品出库不修改库存
MaterialInventoryOmsParamDO materialInventoryOmsParamDO = new MaterialInventoryOmsParamDO();
BeanUtils.copyProperties(materialInventoryParamDO, materialInventoryOmsParamDO);
materialInventoryOmsParamDO.setKctzType("出库");
materialInventoryOmsParamDO.setLoginUser(loginUser);
HandoverTaskOrder h = handoverTaskOrderService.getById(handoverTaskOrderId);
String number = h.getOrderNumber();
StockOutOrder out = stockOutOrderService.getOne(new LambdaQueryWrapper<StockOutOrder>()
.eq(StockOutOrder::getOutOrderNumber, number)
.eq(StockOutOrder::getDelFlag, 1), false);
if (out != null && !"yang_pin_chu_ku".equals(out.getBusinessType())) {
materialInventoryService.kctzjl(materialInventoryParamDO,"出库",loginUser);
materialInventoryService.xgkc(materialInventoryParamDO);
//库存推送oms
omsServiceFeign.omsEdit(materialInventoryOmsParamDO);
}
//库存调整记录
// InventoryAdjustmentRecord inventoryAdjustmentRecord = new InventoryAdjustmentRecord();
// inventoryAdjustmentRecord.setAdjustAction("出库");
// inventoryAdjustmentRecord.setRelateNo(orderNumber);
// inventoryAdjustmentRecord.setAdjustAfterStatusCode(materialInventory.getMaterialStatusCode() == null ? "" : materialInventory.getMaterialStatusCode());
// inventoryAdjustmentRecord.setAdjustBeforeStatusCode(materialInventory.getMaterialStatusCode() == null ? "" : materialInventory.getMaterialStatusCode());
// inventoryAdjustmentRecord.setAdjustAfterStatusName(materialInventory.getMaterialStatusName() == null ? "" : materialInventory.getMaterialStatusName());
// inventoryAdjustmentRecord.setAdjustBeforeStatusName(materialInventory.getMaterialStatusName() == null ? "" : materialInventory.getMaterialStatusName());
//// inventoryAdjustmentRecord.setAdjustBeforeStatusCode("he_ge");
//// inventoryAdjustmentRecord.setAdjustBeforeStatusName("合格");
// inventoryAdjustmentRecord.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId());
// inventoryAdjustmentRecord.setMaterialCode(outMaterialDetail.getMaterialNo());
// inventoryAdjustmentRecord.setMaterialName(outMaterialDetail.getCommodityName());
// inventoryAdjustmentRecord.setBarCode(outMaterialDetail.getBarCode());
// if (inventoryAdjustmentRecord.getBarCode() == null || inventoryAdjustmentRecord.getBarCode().isEmpty()){
// getBarCode(materialInventoryPO, inventoryAdjustmentRecord);
// }
// inventoryAdjustmentRecord.setMaterialBaseInfoId(outMaterialDetail.getMaterialBaseInfoId());
// inventoryAdjustmentRecord.setAdjustType(1L);
// inventoryAdjustmentRecord.setOrganizationId(stockOutOrder.getOrganizationId());
// inventoryAdjustmentRecord.setOrganizationName(stockOutOrder.getOrganizationName());
// inventoryAdjustmentRecord.setTopOrganizationId(stockOutOrder.getTopOrganizationId());
// inventoryAdjustmentRecord.setWarehouseCode(stockOutOrder.getWarehouseCode());
// inventoryAdjustmentRecord.setWarehouseName(stockOutOrder.getWarehouseName());
// inventoryAdjustmentRecord.setWarehouseId(stockOutOrder.getWarehouseId());
// inventoryAdjustmentRecord.setStorageCode(materialInventoryPO.getStorageCode());
// inventoryAdjustmentRecord.setStorageName(materialInventoryPO.getStorageName());
// inventoryAdjustmentRecord.setStorageLocationId(materialInventoryPO.getStorageLocationId());
// inventoryAdjustmentRecord.setStorageLocationCode(materialInventoryPO.getStorageLocationCode());
// inventoryAdjustmentRecord.setStorageLocationName(materialInventoryPO.getStorageLocationName());
// inventoryAdjustmentRecord.setMaterialInventoryId(materialInventoryPO.getMaterialInventoryId());
// inventoryAdjustmentRecord.setMaterialBaseInfoId(materialInventoryPO.getMaterialBaseInfoId());
// inventoryAdjustmentRecord.setShipperId(stockOutOrder.getShipperId());
// inventoryAdjustmentRecord.setShipperName(stockOutOrder.getShipperName());
// inventoryAdjustmentRecord.setStorageSectionId(materialInventoryPO.getStorageSectionId());
// inventoryAdjustmentRecord.setStorageLocationId(materialInventoryPO.getStorageLocationId());
// inventoryAdjustmentRecord.setCreateBy(loginUser.getUserid());
// UserPo userPo = loginUser.getUserPo();
// if (userPo != null) inventoryAdjustmentRecord.setCreateByName(userPo.getUserName());
// inventoryAdjustmentRecord.setCreateTime(new Date());
// inventoryAdjustmentRecord.setAllocationBeforeQuantity(oldAllocationQuantity);
// inventoryAdjustmentRecord.setAllocationAfterQuantity(oldAllocationQuantity);
// inventoryAdjustmentRecord.setFreezeBeforeQuantity(oldFreezeQuantity);
// inventoryAdjustmentRecord.setFreezeAfterQuantity(newFreezeQuantity.subtract(outMaterialDetail.getCheckQuantity()));//调整后 冻结-出库
// inventoryAdjustmentRecord.setInventoryBeforeQuantity(oldInventoryQuantity);
// inventoryAdjustmentRecord.setInventoryAfterQuantity(newInventoryQuantity);
// // 调整前库存数量净重毛重体积面积
// inventoryAdjustmentRecord.setNetWeight(oldNetWeight);
// inventoryAdjustmentRecord.setGrossWeight(oldGrossWeight);
// inventoryAdjustmentRecord.setVolume(oldVolume);
// inventoryAdjustmentRecord.setArea(oldArea);
// // 调整后库存数量 - 复核时填写的数量
// inventoryAdjustmentRecord.setAdjustedNetWeight(newNetWeight);
// inventoryAdjustmentRecord.setAdjustedGrossWeight(newGrossWeight);
// inventoryAdjustmentRecord.setAdjustedVolume(newVolume);
// inventoryAdjustmentRecord.setAdjustedArea(newArea);
//
// inventoryAdjustmentRecordMapper.insert(inventoryAdjustmentRecord);
} }
} }
} }
} }
// /**
// * 定时任务入口每小时整点扫描已交接(13)状态的需报关出库单 sendDec 查报关结果
// * 放行/结关的 状态 139 + 扣库存 + 推OMS未放行 跳过下次再查
// * @Scheduled 触发无需在 sys_job 表配置
// */
// @Scheduled(cron = "0 0 * * * ?")
// public void scheduledCustomsConfirm() {
// log.info("【报关确认出库】定时任务开始执行");
// try {
// AjaxResult result = customsConfirmOut(null);
// log.info("【报关确认出库】定时任务执行完成 result={}", result);
// } catch (Exception e) {
// log.error("【报关确认出库】定时任务执行异常", e);
// }
// }
// /**
// * 海关确认出库轮询/手动入口
// * status=13已交接的需报关出库单 sendDec 查报关状态
// * 放行/结关 状态 139 + 扣库存 + 推OMS
// * 退单 保持13记告警
// * 进行中 跳过下次再查
// * @param outOrderNumbers 传空则扫全部 status=13传值则按指定单号处理
// */
// @Transactional(rollbackFor = Exception.class)
// public AjaxResult customsConfirmOut(List<String> outOrderNumbers) {
// // 1. 确定处理范围只处理通宇status=13 且需要报关的出库单
// LambdaQueryWrapper<StockOutOrder> qw = new LambdaQueryWrapper<StockOutOrder>()
// .eq(StockOutOrder::getOrganizationId, TONGYU_ORGANIZATION_ID)
// .eq(StockOutOrder::getStatus, 13)
// .eq(StockOutOrder::getNeedDeclareFlag, "1");
// if (outOrderNumbers != null && !outOrderNumbers.isEmpty()) {
// qw.in(StockOutOrder::getOutOrderNumber, outOrderNumbers);
// }
// List<StockOutOrder> list = stockOutOrderService.list(qw);
//
// int pass = 0, pending = 0, fail = 0;
// LoginUser loginUser = SecurityUtils.getLoginUser();
//
// for (StockOutOrder soo : list) {
// try {
// // 2. sendDec 查报关状态
// JSONArray decData = queryCustomsDeclaration(
// soo.getOutOrderNumber(),
// soo.getOrganizationId(),
// soo.getOrganizationName());
// if (decData == null || decData.isEmpty()) {
// pending++; // ERP 里还没报关单下次再查
// continue;
// }
//
// // 3. 判断状态遍历全部明细任一命中放行即整单放行
// String decStatus = null;
// boolean passed = false, failed = false;
// for (int i = 0; i < decData.size(); i++) {
// JSONObject item = decData.getJSONObject(i);
// decStatus = item.getString("dec_status");
// if (isInList(decStatus, CUSTOMS_PASS_STATUS)) {
// passed = true;
// // 报关单号写入 customs_declaration_detail补全出库单关联
// saveCustomsDetail(soo, item);
// break;
// }
// if (isInList(decStatus, CUSTOMS_FAIL_STATUS)) {
// failed = true;
// }
// }
//
// if (passed) {
// // 放行状态 139 + 扣库存 + OMS
// soo.setStatus(9);
// stockOutOrderMapper.updateById(soo);
// doStockOutDeduct(soo.getOutOrderNumber(), soo, loginUser);
// pushOmsByOrderNumber(soo.getOutOrderNumber());
// pass++;
// } else if (failed) {
// // 退单保持13记告警日志暂留人工处理
// log.warn("报关退单,请人工处理 outOrderNumber={} decStatus={}",
// soo.getOutOrderNumber(), decStatus);
// fail++;
// } else {
// pending++; // 进行中
// }
// } catch (Exception e) {
// log.error("海关确认出库异常 outOrderNumber={}", soo.getOutOrderNumber(), e);
// fail++;
// }
// }
// Map<String, Object> r = new HashMap<>();
// r.put("pass", pass);
// r.put("pending", pending);
// r.put("fail", fail);
// return AjaxResult.success(r);
// }
// /**
// * sendDec 查询报关回写参考 PickingOrderApplicationService.java:771-818 模板
// * 关键改造 erpBillNo 传出库单号 返回整个 data 数组不只第0条 不在这里处理 dec_status
// */
// private JSONArray queryCustomsDeclaration(String erpBillNo, Long organizationId, String organizationName) throws Exception {
// Map<String, Object> param = new HashMap<>();
// param.put("beginDate", "2020-01-01");
// param.put("endDate", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
// param.put("erpBillNo", erpBillNo);
// param.put("pageIndex", 1);
// param.put("pageSize", 100);
// List<Map<String, Object>> body = new ArrayList<>();
// body.add(param);
//
// // 多租户 URL保证查的地址和推 save_order_e 的地址一致
// String ncUrl = pickingMaterialDetailMapper.getNcUrl("gw", organizationName, organizationId);
// String url = (ncUrl != null) ? ncUrl : CUSTOMS_PUSH_API_URL;
//
// HttpPost post = new HttpPost(url);
// post.setEntity(new StringEntity(JSONObject.toJSONString(body), "UTF-8"));
// post.setHeader("Content-type", "application/json");
// post.setHeader("apiName", "sendDec");
// post.setHeader("verify", CUSTOMS_VERIFY);
// log.info("sendDec 请求 erpBillNo={} url={} body={}", erpBillNo, url,body);
//
// try (CloseableHttpClient client = HttpClients.createDefault();
// CloseableHttpResponse resp = client.execute(post)) {
// String respStr = EntityUtils.toString(resp.getEntity());
// log.info("sendDec 响应 erpBillNo={} resp={}", erpBillNo, respStr);
// if (resp.getStatusLine().getStatusCode() == 200) {
// JSONObject json = JSONObject.parseObject(respStr);
// Integer code = json.getInteger("code");
// if (code != null && code == 200) {
// return json.getJSONArray("data");
// }
// }
// return null;
// }
// }
// private boolean isInList(String v, String[] arr) {
// if (v == null) return false;
// for (String s : arr) {
// if (s.equalsIgnoreCase(v)) return true;
// }
// return false;
// }
// /**
// * 报关明细写入 customs_declaration_detail
// * set outOrderNumber/outOrderId PickingOrder 代码这两字段漏 set
// */
// private void saveCustomsDetail(StockOutOrder soo, JSONObject item) {
// try {
// CustomsDeclarationDetailDO d = new CustomsDeclarationDetailDO();
// d.setDocumentNumber(soo.getOutOrderNumber());
// d.setBondInvtNo(item.getString("entry_id"));
// Object erpGNo = item.get("erp_g_no");
// if (erpGNo != null) {
// d.setInvtRow(erpGNo instanceof Number
// ? ((Number) erpGNo).intValue()
// : Integer.parseInt(erpGNo.toString()));
// }
// d.setOutOrderNumber(soo.getOutOrderNumber());
// d.setOutOrderId(soo.getOutOrderId());
// d.setOrganizationId(soo.getOrganizationId());
// d.setOrganizationName(soo.getOrganizationName());
// d.setTopOrganizationId(soo.getTopOrganizationId());
// customsDeclarationDetailService.insert(d);
// } catch (Exception e) {
// log.error("写报关明细失败 outOrderNumber={}", soo.getOutOrderNumber(), e);
// }
// }
// /** 按 orderNumber 推 OMSpushOms 入参是 handoverTaskOrderId,这里包一层) */
// private void pushOmsByOrderNumber(String orderNumber) {
// List<HandoverTaskOrder> htoList = handoverTaskOrderService.list(
// new LambdaQueryWrapper<HandoverTaskOrder>()
// .eq(HandoverTaskOrder::getOrderNumber, orderNumber));
// for (HandoverTaskOrder hto : htoList) {
// pushOms(hto.getHandoverTaskOrderId());
// }
// }
private void OMSInventorySynchronization(OutMaterialDetail outMaterialDetail,BigDecimal checkQuantity) { private void OMSInventorySynchronization(OutMaterialDetail outMaterialDetail,BigDecimal checkQuantity) {
outMaterialDetail.getLotNo(); outMaterialDetail.getLotNo();
outMaterialDetail.getInOrderNumber(); outMaterialDetail.getInOrderNumber();
@@ -3,6 +3,7 @@ package com.mhd.wms.domain.inMaterialDetail.repository.facade;
import com.baomidou.mybatisplus.extension.service.IService; import com.baomidou.mybatisplus.extension.service.IService;
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail; import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO; import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailBaseDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailBaseDO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO; import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO;
@@ -31,6 +32,11 @@ public interface IInMaterialDetailService extends IService<InMaterialDetail>
*/ */
public List<InMaterialDetailPO> queryListChildren(InMaterialDetailDO inMaterialDetailDO); public List<InMaterialDetailPO> queryListChildren(InMaterialDetailDO inMaterialDetailDO);
/**
* 入库列表页按入库单号批量取去重后的 Invoice No level=1
*/
List<InStockListMaterialAgg> selectDistinctInvoiceNoForStockInList(List<String> inOrderNumbers);
/** /**
* 新增物料明细 * 新增物料明细
*/ */
@@ -3,8 +3,10 @@ package com.mhd.wms.domain.inMaterialDetail.repository.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail; import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO; import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO; import com.mhd.wms.domain.overStock.repository.todo.QueryOrderOverStockDO;
import org.apache.ibatis.annotations.Param;
import java.util.List; import java.util.List;
@@ -26,4 +28,9 @@ public interface InMaterialDetailMapper extends BaseMapper<InMaterialDetail>
*/ */
public List<InMaterialDetailPO> queryInOrderList(QueryOrderOverStockDO queryOrderOverStockDO); public List<InMaterialDetailPO> queryInOrderList(QueryOrderOverStockDO queryOrderOverStockDO);
/**
* 入库列表页按入库单号批量取去重后的 Invoice No level=1
*/
List<InStockListMaterialAgg> selectDistinctInvoiceNoForStockInList(@Param("inOrderNumbers") List<String> inOrderNumbers);
} }
@@ -14,6 +14,7 @@ import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService; import com.mhd.wms.domain.inMaterialDetail.repository.facade.IInMaterialDetailService;
import com.mhd.wms.domain.inMaterialDetail.repository.mapper.InMaterialDetailMapper; import com.mhd.wms.domain.inMaterialDetail.repository.mapper.InMaterialDetailMapper;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO; import com.mhd.wms.domain.inMaterialDetail.repository.po.InMaterialDetailPO;
import com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailBaseDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailBaseDO;
import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO; import com.mhd.wms.domain.inMaterialDetail.repository.todo.InMaterialDetailDO;
import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService; import com.mhd.wms.domain.materialBaseInfo.repository.facade.IMaterialBaseInfoService;
@@ -26,6 +27,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -86,6 +88,14 @@ public class InMaterialDetailImpl extends ServiceImpl<InMaterialDetailMapper, In
return inMaterialDetailPOParentList; return inMaterialDetailPOParentList;
} }
@Override
public List<InStockListMaterialAgg> selectDistinctInvoiceNoForStockInList(List<String> inOrderNumbers) {
if (CollectionUtils.isEmpty(inOrderNumbers)) {
return Collections.emptyList();
}
return inMaterialDetailMapper.selectDistinctInvoiceNoForStockInList(inOrderNumbers);
}
private List<InMaterialDetailPO> getChildren(Long parentUniqueId, List<InMaterialDetailPO> inMaterialDetailPOList, Integer maxLevel){ private List<InMaterialDetailPO> getChildren(Long parentUniqueId, List<InMaterialDetailPO> inMaterialDetailPOList, Integer maxLevel){
List<InMaterialDetailPO> childrenCityList = inMaterialDetailPOList.stream().filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())).collect(Collectors.toList()); List<InMaterialDetailPO> childrenCityList = inMaterialDetailPOList.stream().filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(childrenCityList)){ if (!CollectionUtils.isEmpty(childrenCityList)){
@@ -0,0 +1,12 @@
package com.mhd.wms.domain.inMaterialDetail.repository.po;
import lombok.Data;
/**
* 入库列表页批量取去重后的 Invoice No
*/
@Data
public class InStockListMaterialAgg {
private String inOrderNumber;
private String invoiceNo;
}
@@ -41,6 +41,11 @@ public interface IOutMaterialDetailService extends IService<OutMaterialDetail>
*/ */
List<OutStockListMaterialAgg> selectAggregatesForStockOutList(List<String> outOrderNumbers); List<OutStockListMaterialAgg> selectAggregatesForStockOutList(List<String> outOrderNumbers);
/**
* 出库列表页按出库单号批量取去重后的 Invoice No level=1
*/
List<OutStockListMaterialAgg> selectDistinctInvoiceNoForStockOutList(List<String> outOrderNumbers);
/** /**
* 新增物料明细 * 新增物料明细
*/ */
@@ -60,4 +60,9 @@ public interface OutMaterialDetailMapper extends BaseMapper<OutMaterialDetail>
* 出库列表页按出库单号批量聚合 level=1 * 出库列表页按出库单号批量聚合 level=1
*/ */
List<OutStockListMaterialAgg> selectAggregatesForStockOutList(@Param("outOrderNumbers") List<String> outOrderNumbers); List<OutStockListMaterialAgg> selectAggregatesForStockOutList(@Param("outOrderNumbers") List<String> outOrderNumbers);
/**
* 出库列表页按出库单号批量取去重后的 Invoice No level=1
*/
List<OutStockListMaterialAgg> selectDistinctInvoiceNoForStockOutList(@Param("outOrderNumbers") List<String> outOrderNumbers);
} }
@@ -130,6 +130,14 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
return outMaterialDetailMapper.selectAggregatesForStockOutList(outOrderNumbers); return outMaterialDetailMapper.selectAggregatesForStockOutList(outOrderNumbers);
} }
@Override
public List<OutStockListMaterialAgg> selectDistinctInvoiceNoForStockOutList(List<String> outOrderNumbers) {
if (CollectionUtils.isEmpty(outOrderNumbers)) {
return Collections.emptyList();
}
return outMaterialDetailMapper.selectDistinctInvoiceNoForStockOutList(outOrderNumbers);
}
private List<OutMaterialDetailPO> getChildren(Long parentUniqueId, List<OutMaterialDetailPO> materialDetailPOList, Integer maxLevel){ private List<OutMaterialDetailPO> getChildren(Long parentUniqueId, List<OutMaterialDetailPO> materialDetailPOList, Integer maxLevel){
List<OutMaterialDetailPO> childrenCityList = materialDetailPOList.stream().filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())).collect(Collectors.toList()); List<OutMaterialDetailPO> childrenCityList = materialDetailPOList.stream().filter(materialDetailPO -> parentUniqueId.equals(materialDetailPO.getParentUniqueId())).collect(Collectors.toList());
if (!CollectionUtils.isEmpty(childrenCityList)){ if (!CollectionUtils.isEmpty(childrenCityList)){
@@ -400,7 +408,7 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda() List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda()
.eq(StockOutOrder::getOutOrderNumber, outOrderNumber) .eq(StockOutOrder::getOutOrderNumber, outOrderNumber)
.eq(StockOutOrder::getDelFlag, 1)); .eq(StockOutOrder::getDelFlag, 1));
if (!CollectionUtils.isEmpty(stockOutOrderList) && "yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) { if (!CollectionUtils.isEmpty(stockOutOrderList) && !"yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) {
xgkc(outMaterialDetailList,outOrderNumber,loginUser); xgkc(outMaterialDetailList,outOrderNumber,loginUser);
} }
//保存物料明细信息 //保存物料明细信息
@@ -535,7 +543,7 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda() List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda()
.eq(StockOutOrder::getOutOrderNumber, outOrderNumber) .eq(StockOutOrder::getOutOrderNumber, outOrderNumber)
.eq(StockOutOrder::getDelFlag, 1)); .eq(StockOutOrder::getDelFlag, 1));
if (!CollectionUtils.isEmpty(stockOutOrderList) && "yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) { if (!CollectionUtils.isEmpty(stockOutOrderList) && !"yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) {
qxfp(outMaterialDetailDOList,outOrderNumber,loginUser); qxfp(outMaterialDetailDOList,outOrderNumber,loginUser);
} }
@@ -979,7 +987,7 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda() List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda()
.eq(StockOutOrder::getOutOrderNumber, outOrderNumber) .eq(StockOutOrder::getOutOrderNumber, outOrderNumber)
.eq(StockOutOrder::getDelFlag, 1)); .eq(StockOutOrder::getDelFlag, 1));
if (!CollectionUtils.isEmpty(stockOutOrderList) && "yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) { if (!CollectionUtils.isEmpty(stockOutOrderList) && !"yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) {
qxfp(outMaterialDetailDOList,outOrderNumber,loginUser); qxfp(outMaterialDetailDOList,outOrderNumber,loginUser);
} }
@@ -1088,7 +1096,7 @@ public class OutMaterialDetailImpl extends ServiceImpl<OutMaterialDetailMapper,
List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda() List<StockOutOrder> stockOutOrderList = stockOutOrderMapper.selectList(new QueryWrapper<StockOutOrder>().lambda()
.eq(StockOutOrder::getOutOrderNumber, outOrderNumber) .eq(StockOutOrder::getOutOrderNumber, outOrderNumber)
.eq(StockOutOrder::getDelFlag, 1)); .eq(StockOutOrder::getDelFlag, 1));
if (!CollectionUtils.isEmpty(stockOutOrderList) && "yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) { if (!CollectionUtils.isEmpty(stockOutOrderList) && !"yang_pin_chu_ku".equals(stockOutOrderList.get(0).getBusinessType())) {
childrenqxfp(children,outOrderNumber,loginUser); childrenqxfp(children,outOrderNumber,loginUser);
} }
} }
@@ -13,4 +13,6 @@ public class OutStockListMaterialAgg {
private BigDecimal totalOutboundQuantity; private BigDecimal totalOutboundQuantity;
private BigDecimal checkQuantitySum; private BigDecimal checkQuantitySum;
private Integer materialKindCountDistinct; private Integer materialKindCountDistinct;
/** 列表页展示用:该出库单的 Invoice No */
private String invoiceNo;
} }
@@ -492,6 +492,8 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
} }
//保存物料明细信息 //保存物料明细信息
saveOrUpdateBatch(receiptMaterialDetailList); saveOrUpdateBatch(receiptMaterialDetailList);
// total_volume/total_area 为空时强制落库 NULL绕开 MyBatis-Plus NOT_NULL 更新策略
applyForcedNullTotalMetrics(receiptMaterialDetailList);
//批量新增/更新物料更多属性保留已有值仅更新有值的属性不再先删后插 //批量新增/更新物料更多属性保留已有值仅更新有值的属性不再先删后插
mergeMaterialMoreDetail(materialMoreDetailList, stockReceiptOrderDO, receiptMaterialDetailDOList); mergeMaterialMoreDetail(materialMoreDetailList, stockReceiptOrderDO, receiptMaterialDetailDOList);
//批量新增/更新物料更多属性先删除该收货单下所有明细的旧批次属性再插入新值避免重复插入导致更新失效 //批量新增/更新物料更多属性先删除该收货单下所有明细的旧批次属性再插入新值避免重复插入导致更新失效
@@ -657,6 +659,55 @@ public class ReceiptMaterialDetailImpl extends ServiceImpl<ReceiptMaterialDetail
return val != null && val.compareTo(BigDecimal.ZERO) == 0; return val != null && val.compareTo(BigDecimal.ZERO) == 0;
} }
/**
* total_volume / total_area / dimensions 为空时强制 UPDATE NULL
* 仅对已存在明细material_detail_id 非空生效新插入行由实体空值自然得到 null
*/
private void applyForcedNullTotalMetrics(List<ReceiptMaterialDetail> receiptMaterialDetailList) {
if (CollectionUtils.isEmpty(receiptMaterialDetailList)) {
return;
}
// 列名组合 -> materialDetailId 列表total_volume / total_area / dimensions / 任意组合
Map<String, List<Long>> columnsToIds = new HashMap<>();
for (ReceiptMaterialDetail detail : receiptMaterialDetailList) {
if (detail == null || detail.getMaterialDetailId() == null) {
continue;
}
StringBuilder columns = new StringBuilder();
if (detail.getTotalVolume() == null) {
columns.append("total_volume");
}
if (detail.getTotalArea() == null) {
if (columns.length() > 0) {
columns.append(",");
}
columns.append("total_area");
}
if (detail.getDimensions() == null) {
if (columns.length() > 0) {
columns.append(",");
}
columns.append("dimensions");
}
if (columns.length() == 0) {
continue;
}
columnsToIds.computeIfAbsent(columns.toString(), k -> new ArrayList<>())
.add(detail.getMaterialDetailId());
}
if (columnsToIds.isEmpty()) {
return;
}
for (Map.Entry<String, List<Long>> entry : columnsToIds.entrySet()) {
UpdateWrapper<ReceiptMaterialDetail> wrapper = new UpdateWrapper<>();
for (String column : entry.getKey().split(",")) {
wrapper.set(column, null);
}
wrapper.in("material_detail_id", entry.getValue());
receiptMaterialDetailMapper.update(null, wrapper);
}
}
private void setMore(ReceiptMaterialDetailDO receiptMaterialDetailDO) { private void setMore(ReceiptMaterialDetailDO receiptMaterialDetailDO) {
List<MaterialMoreDetailDO> materialMoreDetailList = receiptMaterialDetailDO.getMaterialMoreDetailList(); List<MaterialMoreDetailDO> materialMoreDetailList = receiptMaterialDetailDO.getMaterialMoreDetailList();
if (!CollectionUtils.isEmpty(materialMoreDetailList)) { if (!CollectionUtils.isEmpty(materialMoreDetailList)) {
@@ -235,6 +235,9 @@ public class StockInOrderPO extends BaseVOEntity {
@Excel(name = "备注") @Excel(name = "备注")
private String remark; private String remark;
@ApiModelProperty("Invoice No(多个用逗号隔开)")
private String invoiceNo;
@ApiModelProperty("物料明细") @ApiModelProperty("物料明细")
private List<InMaterialDetailPO> materialDetailList; private List<InMaterialDetailPO> materialDetailList;
@@ -476,4 +476,7 @@ public class StockInOrderDO extends BaseVOEntity {
*/ */
@ApiModelProperty("作业任务人员模糊查询") @ApiModelProperty("作业任务人员模糊查询")
private String workUserNameLike; private String workUserNameLike;
@ApiModelProperty("是否返回物料明细(导出时传 true")
private Boolean needDetail;
} }
@@ -178,6 +178,171 @@ public class StockInOrderDomainService {
return maxSeq; return maxSeq;
} }
/**
* 新增入库单含复制新建时重置单据生命周期状态
*
* <p>前端复制入库单是取原单详情getInfo后按新单提交/edit 不带 inOrderId
* 若原单已审核审核状态等字段会被原样带入新单导致新单状态是已创建但审核时提示已审核等问题
* 此处统一重置保证新单从初始态开始</p>
*/
private void resetNewOrderState(StockInOrderDO stockInOrderDO) {
//单据状态回到已创建
stockInOrderDO.setStatus(1);
//审核状态回到未审核清空审核信息
stockInOrderDO.setAuditStatus(1);
stockInOrderDO.setAuditRemark(null);
stockInOrderDO.setAuditBy(null);
stockInOrderDO.setAuditByName(null);
stockInOrderDO.setAuditTime(null);
//取消/关闭复位
stockInOrderDO.setCancelOrder(2);
stockInOrderDO.setCancelRemark(null);
stockInOrderDO.setCancelBy(null);
stockInOrderDO.setCancelByName(null);
stockInOrderDO.setCancelTime(null);
stockInOrderDO.setCloseOrder(2);
stockInOrderDO.setCloseRemark(null);
stockInOrderDO.setCloseBy(null);
stockInOrderDO.setCloseByName(null);
stockInOrderDO.setCloseTime(null);
//推送状态复位
stockInOrderDO.setPushStatus(1);
stockInOrderDO.setPushTime(null);
stockInOrderDO.setPushBy(null);
stockInOrderDO.setPushByName(null);
//作业任务复位
stockInOrderDO.setWorkUserId(null);
stockInOrderDO.setWorkUserName(null);
stockInOrderDO.setWorkTaskReceiveStatus(null);
stockInOrderDO.setTaskIssueUserId(null);
//签名状态复位
stockInOrderDO.setSignatureStatus(null);
stockInOrderDO.setSignatureTime(null);
stockInOrderDO.setSignaturePic(null);
stockInOrderDO.setEvidencePics(null);
stockInOrderDO.setSignatureRemark(null);
//复制新增时原单的衍生业务/流程字段不能带入新单新增时前端不传保持初始值
//注意组织/创建人/货主/供应商/仓库等由 Assembler App 层重新赋值或单号生成依赖不在本处清理
stockInOrderDO.setInOrderId(null);
stockInOrderDO.setNoticeNumber(null);
stockInOrderDO.setExpectTime(null);
stockInOrderDO.setSupplyChainNumber(null);
stockInOrderDO.setPriorityLevelCode(null);
stockInOrderDO.setPriorityLevelName(null);
stockInOrderDO.setDirectWarehouse(null);
stockInOrderDO.setAnnexUrl(null);
stockInOrderDO.setWeightLimit(null);
stockInOrderDO.setVolumeLimit(null);
stockInOrderDO.setQuantity(null);
stockInOrderDO.setMobilizeCode(null);
stockInOrderDO.setBusinessOrderNo(null);
stockInOrderDO.setDocumentCreator(null);
stockInOrderDO.setDocumentCreatorName(null);
stockInOrderDO.setDocumentDate(null);
stockInOrderDO.setBillingJson(null);
stockInOrderDO.setReceiptOrderAccountList(null);
}
/**
* 新增入库单含复制新建时重置明细的执行态字段
*
* <p>前端复制入库单是把原单详情getInfo整体提交到新增接口明细会带出原单的
* 主键收货/上架状态已分配库区库位/容器验收/质检结果费用等执行数据
* 规则只清空复制时额外多传的字段新增时前端不传的让新单与直接新增行为一致
* 新增时前端会传的业务属性料号名称规格申报要素报关字段备注入库数量等保留不清理
* 明细的组织/创建人/唯一键等由 batchInsert 按当前登录人重新赋值清理后即恢复初始态</p>
*/
private void resetNewOrderDetailState(List<InMaterialDetailDO> detailList) {
if (CollectionUtils.isEmpty(detailList)) {
return;
}
detailList.forEach(detail -> {
if (detail == null) {
return;
}
//唯一键单号组织审计字段 batchInsert 重新生成/赋值
detail.setUniqueId(null);
detail.setInOrderNumber(null);
detail.setOrganizationId(null);
detail.setOrganizationName(null);
detail.setTopOrganizationId(null);
detail.setCreateBy(null);
detail.setCreateByName(null);
detail.setCreateTime(null);
detail.setUpdateBy(null);
detail.setUpdateByName(null);
detail.setUpdateTime(null);
detail.setDelFlag(null);
//计划数量 batchInsert 按入库数量补齐
detail.setQuantity(null);
//重量/体积限制
detail.setWeightLimit(null);
detail.setVolumeLimit(null);
//收货/上架执行数据
detail.setReceiptQuantity(null);
detail.setShelvesQuantity(null);
detail.setActualQuantity(null);
detail.setReceiptStatus(null);
detail.setShelvesStatus(null);
//包装/单位
detail.setPackId(null);
detail.setPackCode(null);
detail.setPackName(null);
detail.setPackDetailId(null);
detail.setUnitCode(null);
detail.setUnitName(null);
detail.setUnitNumber(null);
detail.setMaterialWarehouseControlId(null);
detail.setSerialNumberManage(null);
detail.setBarCode(null);
//批次仓库/库区/库位容器
detail.setBatchNumber(null);
detail.setMaterialStatusCode(null);
detail.setMaterialStatusName(null);
detail.setWarehouseId(null);
detail.setWarehouseCode(null);
detail.setWarehouseName(null);
detail.setStorageSectionId(null);
detail.setStorageCode(null);
detail.setStorageName(null);
detail.setStorageLocationId(null);
detail.setStorageLocationCode(null);
detail.setStorageLocationName(null);
detail.setContainerId(null);
detail.setContainerCode(null);
detail.setContainerType(null);
detail.setContainerTypeName(null);
//层级结构新单均为一级父行level batchInsert 强制为 1
detail.setParentUniqueId(null);
detail.setChildren(null);
//验收/质检结果
detail.setArrivalAcceptQualified(null);
detail.setPackageDamaged(null);
detail.setIsThawWaterstain(null);
detail.setNotifyCustomerAbnormal(null);
detail.setQualityInspectionResults(null);
//费用/展示
detail.setContractFee(null);
detail.setMonthlyWarehouseFee(null);
detail.setHalfMonthWhFee(null);
detail.setDiscountRate(null);
detail.setSingleVolume(null);
detail.setSingleGrossWeight(null);
detail.setLotNo(null);
//执行数据
detail.setCollectQuantity(null);
detail.setShelfJson(null);
//报关推送映射字段
detail.setLineNumGw(null);
detail.setSpecGw(null);
detail.setUnitGw(null);
detail.setQtyGw(null);
detail.setErpCurrGw(null);
detail.setErpPriceGw(null);
detail.setAmountGw(null);
});
}
/** /**
* 新增入库单 * 新增入库单
@@ -186,6 +351,9 @@ public class StockInOrderDomainService {
public Boolean insert(StockInOrderDO stockInOrderDO) { public Boolean insert(StockInOrderDO stockInOrderDO) {
// stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK")); // stockInOrderDO.setInOrderNumber(OrderSequence.getOrderCode("RK"));
//新增单必须从已创建/未审核初始态开始复制新建时原单状态不能带入新单
resetNewOrderState(stockInOrderDO);
//设置入库单号 //设置入库单号
Long warehouseId = stockInOrderDO.getWarehouseId(); Long warehouseId = stockInOrderDO.getWarehouseId();
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId); AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
@@ -232,6 +400,8 @@ public class StockInOrderDomainService {
// //统计总体积 // //统计总体积
// BigDecimal volumeLimit = stockInOrderDO.getMaterialDetailList().stream().map(InMaterialDetailDO::getVolumeLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add); // BigDecimal volumeLimit = stockInOrderDO.getMaterialDetailList().stream().map(InMaterialDetailDO::getVolumeLimit).filter(Objects::nonNull).reduce(BigDecimal.ZERO, BigDecimal::add);
// stockInOrderDO.setVolumeLimit(volumeLimit); // stockInOrderDO.setVolumeLimit(volumeLimit);
//复制新建时原单明细的收货数量上架数量作业数量等执行数据不能带入新单统一清空
resetNewOrderDetailState(stockInOrderDO.getMaterialDetailList());
stockInOrderService.insert(stockInOrderDO); stockInOrderService.insert(stockInOrderDO);
return materialDetailService.batchInsert(stockInOrderDO.getInOrderNumber(), stockInOrderDO.getMaterialDetailList()); return materialDetailService.batchInsert(stockInOrderDO.getInOrderNumber(), stockInOrderDO.getMaterialDetailList());
} }
@@ -53,8 +53,8 @@ public class StockOutOrderPO extends BaseVOEntity {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
@Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -256,6 +256,9 @@ public class StockOutOrderPO extends BaseVOEntity {
@Excel(name = "备注") @Excel(name = "备注")
private String remark; private String remark;
@ApiModelProperty("Invoice No(多个用逗号隔开)")
private String invoiceNo;
@ApiModelProperty("物料明细") @ApiModelProperty("物料明细")
private List<OutMaterialDetailPO> materialDetailList; private List<OutMaterialDetailPO> materialDetailList;
@@ -49,8 +49,8 @@ public class StockOutOrderDO extends BaseVOEntity {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
@Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -514,6 +514,9 @@ public class StockOutOrderDO extends BaseVOEntity {
@ApiModelProperty("任务移除用户ID") @ApiModelProperty("任务移除用户ID")
private String removeUserId; private String removeUserId;
@ApiModelProperty("是否返回物料明细(导出时传 true")
private Boolean needDetail;
// ========== PDA出库签名字段 ========== // ========== PDA出库签名字段 ==========
@ApiModelProperty("签名状态:1-待签名 2-已签名") @ApiModelProperty("签名状态:1-待签名 2-已签名")
private Integer signatureStatus; private Integer signatureStatus;
@@ -231,6 +231,215 @@ public class StockOutOrderDomainService {
return maxSeq; return maxSeq;
} }
/**
* 新增出库单含复制新建时重置单据生命周期状态
*
* <p>前端复制出库单是取原单详情getInfo后按新单提交/edit 不带 outOrderId
* 若原单已审核/已分配/已出库审核状态分配数量复核/推送/作业任务等字段会被原样带入新单
* 导致新单状态是已创建但审核时提示已审核等问题此处统一重置保证新单从初始态开始</p>
*/
private void resetNewOrderState(StockOutOrderDO stockOutOrderDO) {
//单据状态回到已创建
stockOutOrderDO.setStatus(1);
//审核状态回到未审核清空审核信息
stockOutOrderDO.setAuditStatus(1);
stockOutOrderDO.setAuditRemark(null);
stockOutOrderDO.setAuditBy(null);
stockOutOrderDO.setAuditByName(null);
stockOutOrderDO.setAuditTime(null);
//清空分配/拣货/复核数量等待重新分配产生
stockOutOrderDO.setAllocationQuantity(BigDecimal.ZERO);
stockOutOrderDO.setAlreadyAllocationQuantity(BigDecimal.ZERO);
stockOutOrderDO.setPickingQuantity(BigDecimal.ZERO);
stockOutOrderDO.setCheckQuantity(BigDecimal.ZERO);
//复核状态复位
stockOutOrderDO.setCheckStatus(1);
stockOutOrderDO.setCheckTaskDistribution(2);
stockOutOrderDO.setCheckTaskDistributionTime(null);
stockOutOrderDO.setCheckOperatorsBy(null);
stockOutOrderDO.setCheckOperatorsName(null);
//推送状态复位
stockOutOrderDO.setPushStatus(1);
stockOutOrderDO.setPushTime(null);
stockOutOrderDO.setPushBy(null);
stockOutOrderDO.setPushByName(null);
//取消/关闭复位
stockOutOrderDO.setCancelOrder(2);
stockOutOrderDO.setCancelRemark(null);
stockOutOrderDO.setCancelBy(null);
stockOutOrderDO.setCancelByName(null);
stockOutOrderDO.setCancelTime(null);
stockOutOrderDO.setCloseOrder(2);
stockOutOrderDO.setCloseRemark(null);
stockOutOrderDO.setCloseBy(null);
stockOutOrderDO.setCloseByName(null);
stockOutOrderDO.setCloseTime(null);
//作业任务复位
stockOutOrderDO.setWorkUserId(null);
stockOutOrderDO.setWorkUserName(null);
stockOutOrderDO.setWorkTaskReceiveStatus(null);
stockOutOrderDO.setTaskIssueUserId(null);
//签名状态复位
stockOutOrderDO.setSignatureStatus(null);
stockOutOrderDO.setSignatureTime(null);
stockOutOrderDO.setSignaturePic(null);
stockOutOrderDO.setEvidencePics(null);
stockOutOrderDO.setSignatureRemark(null);
//复制新增时原单的衍生业务/流程字段不能带入新单新增时前端不传保持初始值
//注意组织/创建人/货主/客户等由 Assembler App 层重新赋值不在本处清理
stockOutOrderDO.setOutOrderId(null);
stockOutOrderDO.setNoticeNumber(null);
stockOutOrderDO.setExpectTime(null);
stockOutOrderDO.setSupplyChainNumber(null);
stockOutOrderDO.setPriorityLevelCode(null);
stockOutOrderDO.setPriorityLevelName(null);
stockOutOrderDO.setDirectWarehouse(null);
stockOutOrderDO.setReview(null);
stockOutOrderDO.setAnnexUrl(null);
stockOutOrderDO.setWeightLimit(null);
stockOutOrderDO.setVolumeLimit(null);
stockOutOrderDO.setMobilizeCode(null);
stockOutOrderDO.setTransportModeCode(null);
stockOutOrderDO.setSupervisionModeCode(null);
stockOutOrderDO.setContainerNoName(null);
stockOutOrderDO.setDocumentCreator(null);
stockOutOrderDO.setDocumentCreatorName(null);
stockOutOrderDO.setDocumentDate(null);
stockOutOrderDO.setCarrierName(null);
stockOutOrderDO.setBillingJson(null);
stockOutOrderDO.setReceiptOrderAccountList(null);
stockOutOrderDO.setReturnQuantity(null);
stockOutOrderDO.setTrainNo(null);
}
/**
* 新增出库单含复制新建时重置明细的执行态字段
*
* <p>前端复制出库单是把原单详情getInfo整体提交到新增接口明细会带出原单的
* 主键已分配库存/批次/库区库位/容器拣货复核数量抄码重量收费等执行数据
* 规则只清空复制时额外多传的字段新增时前端不传的让新单与直接新增行为一致
* 新增时前端会传的业务属性料号规格申报要素报关字段备注出库数量等保留不清理
* 明细的组织/创建人/计划数量等由 batchInsert 按当前登录人重新赋值清理后即恢复初始态</p>
*/
private void resetNewOrderDetailState(List<OutMaterialDetailDO> detailList) {
if (CollectionUtils.isEmpty(detailList)) {
return;
}
detailList.forEach(detail -> {
if (detail == null) {
return;
}
//主键与唯一键重新生成避免与原单重复/冲突
detail.setMaterialDetailId(null);
detail.setUniqueId(null);
detail.setOutOrderNumber(null);
//单据组织审计字段 batchInsert 按当前登录人重新赋值
detail.setOrganizationId(null);
detail.setOrganizationName(null);
detail.setTopOrganizationId(null);
detail.setCreateBy(null);
detail.setCreateByName(null);
detail.setCreateTime(null);
detail.setUpdateBy(null);
detail.setUpdateByName(null);
detail.setUpdateTime(null);
detail.setDelFlag(null);
//计划数量 batchInsert 按出库数量重新计算
detail.setQuantity(null);
//执行数量
detail.setInventoryQuantity(null);
detail.setAllocationQuantity(null);
detail.setAlreadyAllocationQuantity(null);
detail.setNowAllocationQuantity(null);
detail.setPickingQuantity(null);
detail.setCheckQuantity(null);
detail.setActualQuantity(null);
//重量/体积限制
detail.setWeightLimit(null);
detail.setVolumeLimit(null);
//物料基础信息batchInsert 会按主数据重填条码/商品名称等
detail.setMaterialCode(null);
detail.setMaterialName(null);
detail.setBarCode(null);
detail.setCommodityName(null);
detail.setCommodityNo(null);
//包装/单位
detail.setPackId(null);
detail.setPackCode(null);
detail.setPackName(null);
detail.setPackDetailId(null);
detail.setUnitCode(null);
detail.setUnitName(null);
detail.setUnitNumber(null);
detail.setMaterialWarehouseControlId(null);
detail.setSerialNumberManage(null);
//已分配库存批次库区/库位容器
detail.setWarehouseId(null);
detail.setWarehouseCode(null);
detail.setWarehouseName(null);
detail.setMaterialInventoryId(null);
detail.setBatchNumber(null);
detail.setMaterialStatusCode(null);
detail.setMaterialStatusName(null);
detail.setStorageSectionId(null);
detail.setStorageCode(null);
detail.setStorageName(null);
detail.setStorageLocationId(null);
detail.setStorageLocationCode(null);
detail.setStorageLocationName(null);
detail.setContainerId(null);
detail.setContainerCode(null);
detail.setContainerType(null);
detail.setContainerTypeName(null);
//层级结构新单均为一级父行子行由 batchInsert 忽略不落库
detail.setLevel(null);
detail.setParentUniqueId(null);
detail.setAllowModify(null);
detail.setGenPickingOrder(null);
detail.setChildren(null);
//复核重量状态标识
detail.setCheckNetWeight(null);
detail.setCheckGrossWeight(null);
detail.setCheckVolume(null);
detail.setCheckArea(null);
detail.setIsAllocated(null);
//抄码数据
detail.setCopyCodeReferenceIds(null);
detail.setCopyTotalWeight(null);
detail.setOutWeight(null);
detail.setOutVolume(null);
detail.setOutQuantity(null);
//库存展示/费用/批次信息
detail.setStockQuantity(null);
detail.setStockUnit(null);
detail.setLotNo(null);
detail.setContractFee(null);
detail.setMonthlyWarehouseFee(null);
detail.setHalfMonthWhFee(null);
detail.setDiscountRate(null);
detail.setSingleVolume(null);
detail.setSingleGrossWeight(null);
detail.setInOrderNumber(null);
detail.setProductionDate(null);
//报关推送映射字段
detail.setLineNumGw(null);
detail.setSpecGw(null);
detail.setUnitGw(null);
detail.setQtyGw(null);
detail.setErpCurrGw(null);
detail.setErpPriceGw(null);
detail.setAmountGw(null);
detail.setInOrderNumberGw(null);
detail.setInLineNumGw(null);
detail.setOpWhLocGw(null);
detail.setWarehouseGw(null);
detail.setInvtRowGw(null);
detail.setBondInvtNoGw(null);
detail.setWhNoGw(null);
detail.setSeatNoGw(null);
});
}
/** /**
* 新增出库单 * 新增出库单
@@ -239,6 +448,9 @@ public class StockOutOrderDomainService {
public Boolean insert(StockOutOrderDO stockOutOrderDO) { public Boolean insert(StockOutOrderDO stockOutOrderDO) {
// stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK")); // stockOutOrderDO.setOutOrderNumber(OrderSequence.getOrderCode("CK"));
//新增单必须从已创建/未审核初始态开始复制新建时原单状态不能带入新单
resetNewOrderState(stockOutOrderDO);
//设置单号 //设置单号
Long warehouseId = stockOutOrderDO.getWarehouseId(); Long warehouseId = stockOutOrderDO.getWarehouseId();
AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId); AjaxResult ajaxResult = systemServiceFeign.getWarehouseInfoByWarehouseId(warehouseId);
@@ -290,6 +502,8 @@ public class StockOutOrderDomainService {
if (stockOutOrderDO.getCheckTaskDistribution() == null) { if (stockOutOrderDO.getCheckTaskDistribution() == null) {
stockOutOrderDO.setCheckTaskDistribution(2); stockOutOrderDO.setCheckTaskDistribution(2);
} }
//复制新建时原单明细的库存数量分配数量拣货/复核数量等执行数据不能带入新单统一清空
resetNewOrderDetailState(stockOutOrderDO.getMaterialDetailList());
stockOutOrderService.insert(stockOutOrderDO); stockOutOrderService.insert(stockOutOrderDO);
return outMaterialDetailService.batchInsert(stockOutOrderDO.getOutOrderNumber(), stockOutOrderDO.getMaterialDetailList()); return outMaterialDetailService.batchInsert(stockOutOrderDO.getOutOrderNumber(), stockOutOrderDO.getMaterialDetailList());
} }
@@ -446,6 +446,9 @@ public class StockInOrderDTO extends StockInOrderBaseDTO {
@ApiModelProperty("任务移除用户ID") @ApiModelProperty("任务移除用户ID")
private String removeUserId; private String removeUserId;
@ApiModelProperty("是否返回物料明细(导出时传 true")
private Boolean needDetail;
// ========== PDA入库签名字段 ========== // ========== PDA入库签名字段 ==========
@ApiModelProperty("签名状态:1-待签名 2-已签名") @ApiModelProperty("签名状态:1-待签名 2-已签名")
private Integer signatureStatus; private Integer signatureStatus;
@@ -47,8 +47,8 @@ public class StockOutOrderDTO extends StockOutOrderBaseDTO {
@Excel(name = "出库单号") @Excel(name = "出库单号")
private String outOrderNumber; private String outOrderNumber;
@ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") @ApiModelProperty("出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
@Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭") @Excel(name = "出库状态: 1-已创建 2-已审核 3-部分分配 4-已分配 5-波次中 6-拣货中 7-拣货完成 8-复核中 9-已出库 10-已取消 11-已关闭 12-已复核 13-已交接")
private Integer status; private Integer status;
@ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过") @ApiModelProperty("出库单审核状态: 1-未审核 2-审核不通过 3-审核通过")
@@ -503,6 +503,9 @@ public class StockOutOrderDTO extends StockOutOrderBaseDTO {
@ApiModelProperty("任务移除用户ID") @ApiModelProperty("任务移除用户ID")
private String removeUserId; private String removeUserId;
@ApiModelProperty("是否返回物料明细(导出时传 true")
private Boolean needDetail;
// ========== PDA出库签名字段 ========== // ========== PDA出库签名字段 ==========
@ApiModelProperty("签名状态:1-待签名 2-已签名") @ApiModelProperty("签名状态:1-待签名 2-已签名")
private Integer signatureStatus; private Integer signatureStatus;
@@ -12,6 +12,7 @@ import com.mhd.wms.domain.copyCodeReference.entity.CopyCodeReference;
import com.mhd.wms.domain.copyCodeReference.repository.po.CopyCodeReferencePO; import com.mhd.wms.domain.copyCodeReference.repository.po.CopyCodeReferencePO;
import com.mhd.wms.domain.handoverTaskOrder.entity.HandoverTaskOrder; import com.mhd.wms.domain.handoverTaskOrder.entity.HandoverTaskOrder;
import com.mhd.wms.domain.handoverTaskOrder.repository.facade.IHandoverTaskOrderService; import com.mhd.wms.domain.handoverTaskOrder.repository.facade.IHandoverTaskOrderService;
import com.mhd.wms.domain.handoverTaskOrder.service.HandoverTaskOrderDomainService;
import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail; import com.mhd.wms.domain.inMaterialDetail.entity.InMaterialDetail;
import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO; import com.mhd.wms.domain.materialInventory.repository.po.MaterialInventoryPO;
import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail; import com.mhd.wms.domain.outMaterialDetail.entity.OutMaterialDetail;
@@ -68,6 +69,8 @@ public class StockOutOrderApi extends BaseController {
private IStockOutOrderService stockOutOrderService; private IStockOutOrderService stockOutOrderService;
@Autowired @Autowired
private ExcelParseService excelParseService; private ExcelParseService excelParseService;
// @Autowired
// private HandoverTaskOrderDomainService handoverTaskOrderDomainService;
/** /**
* 提货单大标题未选时为提货单可传副标题如谷丰--营销部或与弹窗一致传整段提货单--谷丰--营销部后者原样作标题并将 -- 规范为 * 提货单大标题未选时为提货单可传副标题如谷丰--营销部或与弹窗一致传整段提货单--谷丰--营销部后者原样作标题并将 -- 规范为
@@ -106,6 +109,12 @@ public class StockOutOrderApi extends BaseController {
List<StockOutOrderPO> list = stockOutOrderApplicationService.queryList(stockOutOrderDO); List<StockOutOrderPO> list = stockOutOrderApplicationService.queryList(stockOutOrderDO);
return getDataTable(list); return getDataTable(list);
} }
//
// @ApiOperation("海关确认出库(人工批量触发,参数为空则扫全部已交接状态)")
// @PostMapping("/customsConfirmOut")
// public AjaxResult customsConfirmOut(@RequestBody(required = false) List<String> outOrderNumbers) {
// return handoverTaskOrderDomainService.customsConfirmOut(outOrderNumbers);
// }
/** /**
* PDA出库签名列表查询 * PDA出库签名列表查询
@@ -451,4 +451,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</foreach> </foreach>
GROUP BY a.out_order_number GROUP BY a.out_order_number
</select> </select>
<!-- 出库列表页:按出库单号批量取去重后的 Invoice No -->
<select id="selectDistinctInvoiceNoForStockOutList" resultType="com.mhd.wms.domain.outMaterialDetail.repository.po.OutStockListMaterialAgg">
SELECT DISTINCT
a.out_order_number AS outOrderNumber,
a.INVOICE_NO AS invoiceNo
FROM out_material_detail a
WHERE a.del_flag = 1
AND a.level = 1
AND a.INVOICE_NO IS NOT NULL
AND a.INVOICE_NO != ''
AND a.out_order_number IN
<foreach collection="outOrderNumbers" item="num" open="(" separator="," close=")">
#{num}
</foreach>
</select>
</mapper> </mapper>
@@ -356,4 +356,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
<include refid="joinStockInOrderPoWhere"/> <include refid="joinStockInOrderPoWhere"/>
</where> </where>
</select> </select>
<!-- 入库列表页:按入库单号批量取去重后的 Invoice No -->
<select id="selectDistinctInvoiceNoForStockInList" resultType="com.mhd.wms.domain.inMaterialDetail.repository.po.InStockListMaterialAgg">
SELECT DISTINCT
a.in_order_number AS inOrderNumber,
a.INVOICE_NO AS invoiceNo
FROM in_material_detail a
WHERE a.del_flag = 1
AND a.level = 1
AND a.INVOICE_NO IS NOT NULL
AND a.INVOICE_NO != ''
AND a.in_order_number IN
<foreach collection="inOrderNumbers" item="num" open="(" separator="," close=")">
#{num}
</foreach>
</select>
</mapper> </mapper>
@@ -0,0 +1,27 @@
-- ============================================================
-- 功能:租赁表新增 status 状态字段(启用/停用)
-- 数据库:达梦(Dameng192.168.0.49:5236
-- 模式:NGWL_TEST_SYSTEM
-- 表名:LEASE
-- 日期:2026-08-03
-- 说明:status 字段用于控制租赁的启用/停用
-- 1=启用(参与仓库出租率计算)
-- 0=停用(不参与仓库出租率计算)
-- ============================================================
-- 1. 添加字段
ALTER TABLE NGWL_TEST_SYSTEM.LEASE ADD status TINYINT DEFAULT 1;
-- 2. 添加注释(达梦必须单独写)
COMMENT ON COLUMN NGWL_TEST_SYSTEM.LEASE.status IS '状态:1=启用,0=停用';
-- bms
ALTER TABLE "NGWL_TEST_BMS"."BILL_DETAIL" ADD BILLING_UNIT VARCHAR2(100);
ALTER TABLE "NGWL_TEST_BMS"."BILL_DETAIL" ADD BILLING_NUM NUMBER(18,2);
ALTER TABLE "NGWL_TEST_BMS"."BILL_DETAIL" ADD BILLING_UNIT_PRICE NUMBER(18,2);
COMMENT ON COLUMN "NGWL_TEST_BMS"."BILL_DETAIL".BILLING_UNIT IS '计费单位';
COMMENT ON COLUMN "NGWL_TEST_BMS"."BILL_DETAIL".BILLING_NUM IS '计费数量';
COMMENT ON COLUMN "NGWL_TEST_BMS"."BILL_DETAIL".BILLING_UNIT_PRICE IS '计费单价';