no message
parent
070fc764a1
commit
1e9854747d
|
|
@ -1,4 +1,4 @@
|
||||||
package org.cpte.modules.utils;
|
package org.cpte.common.util;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -24,7 +24,7 @@ import java.util.Map;
|
||||||
*/
|
*/
|
||||||
@FeignClient(
|
@FeignClient(
|
||||||
name = "wms-basic-service",
|
name = "wms-basic-service",
|
||||||
url = "${feign.client.wms-basic.url:http://wms-basic-service:80}",
|
url = "${feign.client.wms-basic.url:http://wms-basic-service:8001}",
|
||||||
configuration = FeignClientConfiguration.class,
|
configuration = FeignClientConfiguration.class,
|
||||||
fallbackFactory = BasicServiceFallbackFactory.class
|
fallbackFactory = BasicServiceFallbackFactory.class
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,11 @@ import java.util.concurrent.TimeUnit;
|
||||||
@Configuration
|
@Configuration
|
||||||
public class FeignClientConfiguration {
|
public class FeignClientConfiguration {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public FeignTokenInterceptor feignTokenInterceptor() {
|
||||||
|
return new FeignTokenInterceptor();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 配置 Feign 使用 OkHttp 作为 HTTP 客户端
|
* 配置 Feign 使用 OkHttp 作为 HTTP 客户端
|
||||||
* @return OkHttp 客户端
|
* @return OkHttp 客户端
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.cpte.feign.config;
|
||||||
|
|
||||||
|
import feign.RequestInterceptor;
|
||||||
|
import feign.RequestTemplate;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Feign Token 拦截器
|
||||||
|
* 用于在 Feign 请求头中添加 X-Access-Token
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
public class FeignTokenInterceptor implements RequestInterceptor {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void apply(RequestTemplate template) {
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
if (attributes != null) {
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
String token = request.getHeader("X-Access-Token");
|
||||||
|
if (token == null) {
|
||||||
|
token = request.getParameter("token");
|
||||||
|
}
|
||||||
|
if (token != null && !token.isEmpty()) {
|
||||||
|
template.header("X-Access-Token", token);
|
||||||
|
} else {
|
||||||
|
log.error("Feign 请求未找到 Token,请求头:{}", request.getHeaderNames());
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.error("Feign 请求无法获取 RequestContext,可能是在非 Web 环境中调用");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
@SpringBootApplication(scanBasePackages = {"org.jeecg","org.cpte","org.cpte.modules"})
|
@SpringBootApplication(scanBasePackages = {"org.jeecg","org.cpte","org.cpte.modules"})
|
||||||
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
||||||
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
||||||
@EnableFeignClients(basePackages = {"org.cpte.feign.client"}) // 启用 Feign 客户端
|
@EnableFeignClients(basePackages = {"org.cpte.feign"}) // 启用 Feign 客户端,包含 client 和 config 包
|
||||||
public class WmsBasicApplication extends SpringBootServletInitializer {
|
public class WmsBasicApplication extends SpringBootServletInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
||||||
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
||||||
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
||||||
@EnableFeignClients(basePackages = {"org.cpte.feign.client"}) // 启用 Feign 客户端
|
@EnableFeignClients(basePackages = {"org.cpte.feign"}) // 启用 Feign 客户端,包含 client 和 config 包
|
||||||
public class WmsInboundApplication extends SpringBootServletInitializer {
|
public class WmsInboundApplication extends SpringBootServletInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import jakarta.servlet.http.HttpServletRequest;
|
||||||
import jakarta.servlet.http.HttpServletResponse;
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
import org.cpte.modules.inbound.mapper.AsnDetailMapper;
|
import org.cpte.modules.inbound.mapper.AsnDetailMapper;
|
||||||
|
import org.cpte.modules.inbound.request.ReceiveRequest;
|
||||||
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
import org.jeecgframework.poi.excel.ExcelImportUtil;
|
||||||
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
import org.jeecgframework.poi.excel.def.NormalExcelConstants;
|
||||||
import org.jeecgframework.poi.excel.entity.ExportParams;
|
import org.jeecgframework.poi.excel.entity.ExportParams;
|
||||||
|
|
@ -285,4 +286,17 @@ public class AsnController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@AutoLog(value = "收货整理")
|
||||||
|
@Operation(summary = "收货整理")
|
||||||
|
@RequiresPermissions("inbound:data_asn:receive")
|
||||||
|
@PostMapping(value = "/receive")
|
||||||
|
public Result<String> receive(@RequestBody ReceiveRequest request) {
|
||||||
|
try {
|
||||||
|
asnService.receive(request);
|
||||||
|
return Result.OK("操作成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
return Result.error("收货整理异常:" + e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.jeecgframework.poi.excel.annotation.Excel;
|
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ public interface AsnDetailMapper extends BaseMapper<AsnDetail> {
|
||||||
List<AsnDetail> selectByMainId(@Param("mainId") Long mainId);
|
List<AsnDetail> selectByMainId(@Param("mainId") Long mainId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过入库单 id 集合查询入库明细
|
* 通过入库单 ids 集合查询入库明细
|
||||||
*
|
*
|
||||||
* @param asnIds 入库单 id 集合
|
* @param asnIds 入库单 id 集合
|
||||||
* @return List<AsnDetail>
|
* @return List<AsnDetail>
|
||||||
|
|
@ -49,4 +49,11 @@ public interface AsnDetailMapper extends BaseMapper<AsnDetail> {
|
||||||
*/
|
*/
|
||||||
List<AsnDetail> queryByStockCode(@Param("stockId") Long stockId, @Param("status") Integer status);
|
List<AsnDetail> queryByStockCode(@Param("stockId") Long stockId, @Param("status") Integer status);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除入库明细
|
||||||
|
*
|
||||||
|
* @param asnIds 入库单 id 集合
|
||||||
|
*/
|
||||||
|
void deleteByBatchAsnIds(@Param("asnIds") List<Long> asnIds);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package org.cpte.modules.inbound.request;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 收货参数
|
||||||
|
* @author: cpte
|
||||||
|
* @Date: 2026-03-08
|
||||||
|
* @Version: V1.0
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(description = "收货参数")
|
||||||
|
public class ReceiveRequest implements Serializable {
|
||||||
|
|
||||||
|
@NotBlank(message = "物料编码不能为空")
|
||||||
|
@Schema(description = "物料编码")
|
||||||
|
private String itemCode;
|
||||||
|
|
||||||
|
@NotBlank(message = "库位编码不能为空")
|
||||||
|
@Schema(description = "库位编码")
|
||||||
|
private String pointCode;
|
||||||
|
|
||||||
|
@NotBlank(message = "容器编码不能为空")
|
||||||
|
@Schema(description = "容器编码")
|
||||||
|
private String stockCode;
|
||||||
|
}
|
||||||
|
|
@ -2,7 +2,7 @@ package org.cpte.modules.inbound.rule;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.cpte.modules.utils.CodeGeneratorUtil;
|
import org.cpte.common.util.CodeGeneratorUtil;
|
||||||
import org.jeecg.common.handler.IFillRuleHandler;
|
import org.jeecg.common.handler.IFillRuleHandler;
|
||||||
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
|
||||||
|
|
@ -33,15 +33,6 @@ public interface IAsnDetailService extends IService<AsnDetail> {
|
||||||
*/
|
*/
|
||||||
Map<Long, Asn> queryByAsnIdsToMap(List<Long> asnIds);
|
Map<Long, Asn> queryByAsnIdsToMap(List<Long> asnIds);
|
||||||
|
|
||||||
/**
|
|
||||||
* 保存主表信息
|
|
||||||
*
|
|
||||||
* @param asn 入库单
|
|
||||||
* @param asnDetailList 入库明细
|
|
||||||
*/
|
|
||||||
void processorSaveMain(Asn asn, List<AsnDetail> asnDetailList);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 刷新入库单
|
* 刷新入库单
|
||||||
*
|
*
|
||||||
|
|
@ -50,16 +41,4 @@ public interface IAsnDetailService extends IService<AsnDetail> {
|
||||||
*/
|
*/
|
||||||
void refreshAsn(Asn asn, List<AsnDetail> asnDetails);
|
void refreshAsn(Asn asn, List<AsnDetail> asnDetails);
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 构建入库记录
|
|
||||||
*
|
|
||||||
* @param asnDetail 入库单明细
|
|
||||||
* @param receivedQty 收货数量
|
|
||||||
* @param itemKey 物料属性
|
|
||||||
* @param dstPointId 目标库位 ID
|
|
||||||
* @return ReceiveRecord
|
|
||||||
*/
|
|
||||||
ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKeyDTO itemKey, Long dstPointId);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,8 @@ package org.cpte.modules.inbound.service;
|
||||||
import org.cpte.modules.inbound.entity.AsnDetail;
|
import org.cpte.modules.inbound.entity.AsnDetail;
|
||||||
import org.cpte.modules.inbound.entity.Asn;
|
import org.cpte.modules.inbound.entity.Asn;
|
||||||
import com.baomidou.mybatisplus.extension.service.IService;
|
import com.baomidou.mybatisplus.extension.service.IService;
|
||||||
|
import org.cpte.modules.inbound.request.ReceiveRequest;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -22,7 +24,7 @@ public interface IAsnService extends IService<Asn> {
|
||||||
* @param asn
|
* @param asn
|
||||||
* @param asnDetailList
|
* @param asnDetailList
|
||||||
*/
|
*/
|
||||||
public void saveMain(Asn asn, List<AsnDetail> asnDetailList);
|
void saveMain(Asn asn, List<AsnDetail> asnDetailList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 修改一对多
|
* 修改一对多
|
||||||
|
|
@ -30,21 +32,28 @@ public interface IAsnService extends IService<Asn> {
|
||||||
* @param asn
|
* @param asn
|
||||||
* @param asnDetailList
|
* @param asnDetailList
|
||||||
*/
|
*/
|
||||||
public void updateMain(Asn asn, List<AsnDetail> asnDetailList);
|
void updateMain(Asn asn, List<AsnDetail> asnDetailList);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 删除一对多
|
* 删除一对多
|
||||||
*
|
*
|
||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
public void delMain(Long id);
|
void delMain(Long id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 批量删除一对多
|
* 批量删除一对多
|
||||||
*
|
*
|
||||||
* @param idList
|
* @param idList
|
||||||
*/
|
*/
|
||||||
public void delBatchMain(Collection<? extends Serializable> idList);
|
void delBatchMain(Collection<? extends Serializable> idList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 收货
|
||||||
|
*
|
||||||
|
* @param request 收货请求参数
|
||||||
|
*/
|
||||||
|
void receive(ReceiveRequest request);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 取消操作
|
* 取消操作
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
package org.cpte.modules.inbound.service.impl;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.cpte.modules.inbound.entity.Asn;
|
||||||
|
import org.cpte.modules.inbound.mapper.AsnDetailMapper;
|
||||||
|
import org.cpte.modules.inbound.mapper.AsnMapper;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @Description: 入库单数据处理器(专门处理数据库操作,独立事务管理)
|
||||||
|
* @author: cpte
|
||||||
|
* @Date: 2026-03-08
|
||||||
|
* @Version: V1.0
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AsnDataProcessor {
|
||||||
|
|
||||||
|
private final AsnDetailMapper asnDetailMapper;
|
||||||
|
private final AsnMapper asnMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存入库单
|
||||||
|
*
|
||||||
|
* @param asn 入库单
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void saveAsn(Asn asn) {
|
||||||
|
asnMapper.insert(asn);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 更新入库单
|
||||||
|
*
|
||||||
|
* @param asn 入库单
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void updateAsn(Asn asn) {
|
||||||
|
asnMapper.updateById(asn);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除入库单及明细
|
||||||
|
*
|
||||||
|
* @param asnIds 入库单 ID 集合
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void batchDeleteAsn(List<Long> asnIds) {
|
||||||
|
asnDetailMapper.deleteByBatchAsnIds(asnIds);
|
||||||
|
asnMapper.deleteByIds(asnIds);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除单个入库单及明细
|
||||||
|
*
|
||||||
|
* @param asnId 入库单 ID
|
||||||
|
*/
|
||||||
|
@Transactional(rollbackFor = Exception.class)
|
||||||
|
public void deleteAsn(Long asnId) {
|
||||||
|
asnDetailMapper.deleteByMainId(asnId);
|
||||||
|
asnMapper.deleteById(asnId);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -19,6 +19,7 @@ import org.springframework.stereotype.Service;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -36,10 +37,6 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnMapper asnMapper;
|
private AsnMapper asnMapper;
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private AsnSerialNumberRule asnSerialNumberRule;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<AsnDetail> selectByMainId(Long mainId) {
|
public List<AsnDetail> selectByMainId(Long mainId) {
|
||||||
return this.baseMapper.selectByMainId(mainId);
|
return this.baseMapper.selectByMainId(mainId);
|
||||||
|
|
@ -59,87 +56,42 @@ public class AsnDetailServiceImpl extends ServiceImpl<AsnDetailMapper, AsnDetail
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void processorSaveMain(Asn asn, List<AsnDetail> asnDetailList) {
|
|
||||||
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
|
||||||
asn.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
|
||||||
asn.setSysOrgCode(sysUser.getOrgCode());
|
|
||||||
String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO);
|
|
||||||
asn.setOrderNo(orderNo);
|
|
||||||
asnMapper.insert(asn);
|
|
||||||
|
|
||||||
if (asnDetailList == null || asnDetailList.isEmpty()) {
|
|
||||||
throw new RuntimeException("请新增入库明细");
|
|
||||||
}
|
|
||||||
|
|
||||||
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
|
||||||
for (AsnDetail entity : asnDetailList) {
|
|
||||||
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
|
||||||
entity.setLineNo(lineNoCounter.getAndIncrement());
|
|
||||||
}
|
|
||||||
entity.setAsnId(asn.getId());
|
|
||||||
entity.setTenantId(Long.parseLong(sysUser.getRelTenantIds()));
|
|
||||||
entity.setSysOrgCode(sysUser.getOrgCode());
|
|
||||||
this.baseMapper.insert(entity);
|
|
||||||
}
|
|
||||||
//刷新入库单
|
|
||||||
refreshAsn(asn, asnDetailList);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void refreshAsn(Asn asn, List<AsnDetail> asnDetails) {
|
public void refreshAsn(Asn asn, List<AsnDetail> asnDetails) {
|
||||||
|
|
||||||
if (asnDetails == null) {
|
if (CollectionUtils.isEmpty(asnDetails)) {
|
||||||
asnDetails = new ArrayList<>();
|
asnDetails = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
//需求数量
|
// 计算需求数量总和
|
||||||
BigDecimal orderQty = asnDetails.stream().map(AsnDetail::getOrderQty).reduce(BigDecimal.ZERO, BigDecimal::add);
|
BigDecimal orderQty = asnDetails.stream()
|
||||||
|
.map(AsnDetail::getOrderQty)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
//收货数量
|
// 计算收货数量总和
|
||||||
BigDecimal receivedQty = asnDetails.stream().map(AsnDetail::getReceivedQty).reduce(BigDecimal.ZERO, BigDecimal::add);
|
BigDecimal receivedQty = asnDetails.stream()
|
||||||
|
.map(AsnDetail::getReceivedQty)
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.reduce(BigDecimal.ZERO, BigDecimal::add);
|
||||||
|
|
||||||
//当前状态
|
// 计算入库单状态
|
||||||
Integer status = asn.getStatus();
|
int status;
|
||||||
|
if (orderQty.compareTo(BigDecimal.ZERO) <= 0 || receivedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
||||||
if (orderQty.compareTo(BigDecimal.ZERO) <= 0) {
|
// 无需求量或未收货:创建状态
|
||||||
// 无需求量时设为创建状态
|
|
||||||
status = AsnStatusEnum.CREATED.getValue();
|
|
||||||
} else if (receivedQty.compareTo(BigDecimal.ZERO) <= 0) {
|
|
||||||
// 未收货时为创建状态
|
|
||||||
status = AsnStatusEnum.CREATED.getValue();
|
status = AsnStatusEnum.CREATED.getValue();
|
||||||
} else if (receivedQty.compareTo(orderQty) >= 0) {
|
} else if (receivedQty.compareTo(orderQty) >= 0) {
|
||||||
// 已完全收货
|
// 收货数量 >= 需求数量:收货完成
|
||||||
status = AsnStatusEnum.RECEIVED.getValue();
|
status = AsnStatusEnum.RECEIVED.getValue();
|
||||||
} else {
|
} else {
|
||||||
// 部分收货
|
// 收货数量 < 需求数量:部分收货
|
||||||
status = AsnStatusEnum.RECEIVING.getValue();
|
status = AsnStatusEnum.RECEIVING.getValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 更新入库单
|
||||||
asn.setOrderQty(orderQty);
|
asn.setOrderQty(orderQty);
|
||||||
asn.setReceivedQty(receivedQty);
|
asn.setReceivedQty(receivedQty);
|
||||||
asn.setStatus(status);
|
asn.setStatus(status);
|
||||||
asnMapper.updateById(asn);
|
asnMapper.updateById(asn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ReceiveRecord buildReceiveRecord(AsnDetail asnDetail, BigDecimal receivedQty, ItemKeyDTO itemKey, Long dstPointId) {
|
|
||||||
return ReceiveRecord.builder()
|
|
||||||
.id(IdWorker.getId())
|
|
||||||
.asnId(asnDetail.getAsnId())
|
|
||||||
.asnDetailId(asnDetail.getId())
|
|
||||||
.stockId(asnDetail.getStockId())
|
|
||||||
.fromPointId(asnDetail.getToPointId())
|
|
||||||
.toPointId(dstPointId)
|
|
||||||
.itemId(asnDetail.getItemId())
|
|
||||||
.itemKeyId(itemKey.getId())
|
|
||||||
.receivedQty(receivedQty)
|
|
||||||
.description(asnDetail.getDescription())
|
|
||||||
.tenantId(asnDetail.getTenantId())
|
|
||||||
.sysOrgCode(asnDetail.getSysOrgCode())
|
|
||||||
.createBy(asnDetail.getCreateBy())
|
|
||||||
.createTime(new Date())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,26 +2,26 @@ package org.cpte.modules.inbound.service.impl;
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.apache.commons.collections4.CollectionUtils;
|
import org.apache.commons.collections4.CollectionUtils;
|
||||||
|
import org.apache.shiro.SecurityUtils;
|
||||||
import org.cpte.common.lock.RedissonLockExecutor;
|
import org.cpte.common.lock.RedissonLockExecutor;
|
||||||
|
import org.cpte.modules.constant.GeneralConstant;
|
||||||
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
import org.cpte.modules.constant.enums.AsnStatusEnum;
|
||||||
import org.cpte.modules.inbound.entity.Asn;
|
import org.cpte.modules.inbound.entity.Asn;
|
||||||
import org.cpte.modules.inbound.entity.AsnDetail;
|
import org.cpte.modules.inbound.entity.AsnDetail;
|
||||||
import org.cpte.modules.inbound.mapper.AsnDetailMapper;
|
import org.cpte.modules.inbound.mapper.AsnDetailMapper;
|
||||||
import org.cpte.modules.inbound.mapper.AsnMapper;
|
import org.cpte.modules.inbound.mapper.AsnMapper;
|
||||||
|
import org.cpte.modules.inbound.request.ReceiveRequest;
|
||||||
|
import org.cpte.modules.inbound.rule.AsnSerialNumberRule;
|
||||||
import org.cpte.modules.inbound.service.IAsnDetailService;
|
import org.cpte.modules.inbound.service.IAsnDetailService;
|
||||||
import org.cpte.modules.inbound.service.IAsnService;
|
import org.cpte.modules.inbound.service.IAsnService;
|
||||||
import org.redisson.api.RLock;
|
import org.jeecg.common.system.vo.LoginUser;
|
||||||
import org.redisson.api.RedissonClient;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @Description: 入库单
|
* @Description: 入库单
|
||||||
|
|
@ -35,138 +35,249 @@ public class AsnServiceImpl extends ServiceImpl<AsnMapper, Asn> implements IAsnS
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private AsnDetailMapper asnDetailMapper;
|
private AsnDetailMapper asnDetailMapper;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private IAsnDetailService asnDetailService;
|
private IAsnDetailService asnDetailService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedissonClient redissonClient;
|
private ReceiveServiceImpl receiveService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AsnSerialNumberRule asnSerialNumberRule;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RedissonLockExecutor redissonLockExecutor;
|
private RedissonLockExecutor redissonLockExecutor;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AsnDataProcessor asnDataProcessor;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void saveMain(Asn asn, List<AsnDetail> asnDetailList) {
|
public void saveMain(Asn asn, List<AsnDetail> asnDetailList) {
|
||||||
String lockKey = "asn:lock:" + asn.getNo();
|
String lockKey = "asn:lock:" + asn.getNo();
|
||||||
redissonLockExecutor.executeWithLock(lockKey, () -> {
|
redissonLockExecutor.executeWithLock(lockKey, () -> {
|
||||||
asnDetailService.processorSaveMain(asn, asnDetailList);
|
processorSave(asn, asnDetailList);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
/**
|
||||||
@Transactional(rollbackFor = Exception.class)
|
* 保存入库单及明细
|
||||||
public void updateMain(Asn asn, List<AsnDetail> asnDetailList) {
|
*
|
||||||
this.baseMapper.updateById(asn);
|
* @param asn 入库单
|
||||||
|
* @param asnDetailList 入库单明细
|
||||||
|
*/
|
||||||
|
private void processorSave(Asn asn, List<AsnDetail> asnDetailList) {
|
||||||
|
// 获取当前登录用户信息
|
||||||
|
LoginUser sysUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
|
||||||
|
if (sysUser == null) {
|
||||||
|
throw new RuntimeException("用户未登录");
|
||||||
|
}
|
||||||
|
|
||||||
if (asnDetailList == null || asnDetailList.isEmpty()) {
|
// 设置入库单基础信息
|
||||||
|
Long tenantId = Long.parseLong(sysUser.getRelTenantIds());
|
||||||
|
asn.setTenantId(tenantId);
|
||||||
|
asn.setSysOrgCode(sysUser.getOrgCode());
|
||||||
|
|
||||||
|
// 生成入库单号
|
||||||
|
String orderNo = asnSerialNumberRule.generateSerialNumber(GeneralConstant.ASN_ORDER_NO);
|
||||||
|
asn.setOrderNo(orderNo);
|
||||||
|
|
||||||
|
// 校验明细列表
|
||||||
|
if (CollectionUtils.isEmpty(asnDetailList)) {
|
||||||
|
throw new RuntimeException("请新增入库明细");
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量设置明细属性并插入
|
||||||
|
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
||||||
|
List<AsnDetail> insertDetails = new ArrayList<>();
|
||||||
|
|
||||||
|
for (AsnDetail entity : asnDetailList) {
|
||||||
|
// 自动设置行号
|
||||||
|
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
||||||
|
entity.setLineNo(lineNoCounter.getAndIncrement());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置关联 ID 和租户信息
|
||||||
|
entity.setAsnId(asn.getId());
|
||||||
|
entity.setTenantId(tenantId);
|
||||||
|
entity.setSysOrgCode(sysUser.getOrgCode());
|
||||||
|
|
||||||
|
insertDetails.add(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
//保存入库单
|
||||||
|
asnDataProcessor.saveAsn(asn);
|
||||||
|
|
||||||
|
// 批量插入明细
|
||||||
|
if (CollectionUtils.isNotEmpty(insertDetails)) {
|
||||||
|
asnDetailService.saveBatch(insertDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 刷新入库单
|
||||||
|
asnDetailService.refreshAsn(asn, insertDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateMain(Asn asn, List<AsnDetail> asnDetailList) {
|
||||||
|
String lockKey = "asn:lock:" + asn.getNo();
|
||||||
|
redissonLockExecutor.executeWithWatchdog(lockKey, () -> {
|
||||||
|
processUpdate(asn, asnDetailList);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改入库单及明细
|
||||||
|
*
|
||||||
|
* @param asn 入库单
|
||||||
|
* @param asnDetailList 入库单明细
|
||||||
|
*/
|
||||||
|
private void processUpdate(Asn asn, List<AsnDetail> asnDetailList) {
|
||||||
|
if (CollectionUtils.isEmpty(asnDetailList)) {
|
||||||
throw new RuntimeException("请新增入库明细");
|
throw new RuntimeException("请新增入库明细");
|
||||||
}
|
}
|
||||||
|
|
||||||
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
AtomicInteger lineNoCounter = new AtomicInteger(1);
|
||||||
|
List<AsnDetail> insertDetails = new ArrayList<>();
|
||||||
|
List<AsnDetail> updateDetails = new ArrayList<>();
|
||||||
|
|
||||||
for (AsnDetail entity : asnDetailList) {
|
for (AsnDetail entity : asnDetailList) {
|
||||||
|
// 自动设置行号
|
||||||
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
if (entity.getLineNo() == null || entity.getLineNo() == 0) {
|
||||||
entity.setLineNo(lineNoCounter.getAndIncrement());
|
entity.setLineNo(lineNoCounter.getAndIncrement());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 设置关联 ID
|
||||||
entity.setAsnId(asn.getId());
|
entity.setAsnId(asn.getId());
|
||||||
|
|
||||||
|
// 分类:新增或更新
|
||||||
if (entity.getId() != null) {
|
if (entity.getId() != null) {
|
||||||
asnDetailMapper.updateById(entity);
|
updateDetails.add(entity);
|
||||||
} else {
|
} else {
|
||||||
asnDetailMapper.insert(entity);
|
insertDetails.add(entity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 刷新入库单状态
|
asnDataProcessor.updateAsn(asn);
|
||||||
asnDetailService.refreshAsn(asn, asnDetailList);
|
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(insertDetails)) {
|
||||||
|
asnDetailService.saveBatch(insertDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(updateDetails)) {
|
||||||
|
asnDetailService.updateBatchById(updateDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. 刷新入库单
|
||||||
|
asnDetailService.refreshAsn(asn, asnDetailList);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void delMain(Long id) {
|
public void delMain(Long id) {
|
||||||
Asn asn = this.getById(id);
|
Asn asn = this.getById(id);
|
||||||
if (!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())) {
|
if (!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())) {
|
||||||
throw new RuntimeException("操作失败:【" + asn.getOrderNo() + "】入库单,非创建状态不允许删除");
|
throw new RuntimeException("操作失败:【" + asn.getOrderNo() + "】入库单,非创建状态不允许删除");
|
||||||
}
|
}
|
||||||
asnDetailMapper.deleteByMainId(id);
|
asnDataProcessor.deleteAsn(id);
|
||||||
this.baseMapper.deleteById(id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void delBatchMain(Collection<? extends Serializable> idList) {
|
public void delBatchMain(Collection<? extends Serializable> idList) {
|
||||||
List<String> orderNoList = new ArrayList<>();
|
if (CollectionUtils.isEmpty(idList)) {
|
||||||
for (Serializable id : idList) {
|
throw new RuntimeException("请选择需要删除的入库单");
|
||||||
Asn asn = this.getById(id);
|
}
|
||||||
|
|
||||||
|
List<Long> asnIdList = idList.stream().map(id -> Long.parseLong(id.toString())).toList();
|
||||||
|
Map<Long, Asn> asnMap = asnDetailService.queryByAsnIdsToMap(asnIdList);
|
||||||
|
if (asnMap.isEmpty()) {
|
||||||
|
throw new RuntimeException("未找到需要删除的入库单");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<String> invalidOrderNos = new ArrayList<>();
|
||||||
|
List<Long> asnIds = new ArrayList<>();
|
||||||
|
|
||||||
|
for (Map.Entry<Long, Asn> entry : asnMap.entrySet()) {
|
||||||
|
Asn asn = entry.getValue();
|
||||||
if (!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())) {
|
if (!AsnStatusEnum.CREATED.getValue().equals(asn.getStatus())) {
|
||||||
orderNoList.add(asn.getOrderNo());
|
invalidOrderNos.add(asn.getOrderNo());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
asnDetailMapper.deleteByMainId(Long.parseLong(id.toString()));
|
asnIds.add(asn.getId());
|
||||||
this.baseMapper.deleteById(id);
|
|
||||||
}
|
}
|
||||||
if (!orderNoList.isEmpty()) {
|
|
||||||
throw new RuntimeException("操作失败:【" + orderNoList + "】入库单,非创建状态不允许删除");
|
if (CollectionUtils.isNotEmpty(invalidOrderNos)) {
|
||||||
|
String orderNos = String.join(",", invalidOrderNos);
|
||||||
|
throw new RuntimeException("操作失败:[" + orderNos + "] 入库单非创建状态,不允许删除");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CollectionUtils.isNotEmpty(asnIds)) {
|
||||||
|
asnDataProcessor.batchDeleteAsn(asnIds);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
public void receive(ReceiveRequest request) {
|
||||||
|
String lockKey = "receive:stock:" + request.getStockCode();
|
||||||
|
redissonLockExecutor.executeWithWatchdog(lockKey, () -> {
|
||||||
|
receiveService.receive(request);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void cancelAsn(Asn asn) {
|
public void cancelAsn(Asn asn) {
|
||||||
|
String lockKey = "asn:lock:" + asn.getNo();
|
||||||
|
redissonLockExecutor.executeWithWatchdog(lockKey, () -> {
|
||||||
|
processCancel(asn);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 取消入库单
|
||||||
|
*
|
||||||
|
* @param asn 入库单
|
||||||
|
*/
|
||||||
|
private void processCancel(Asn asn) {
|
||||||
List<AsnDetail> details = asnDetailMapper.selectByMainId(asn.getId());
|
List<AsnDetail> details = asnDetailMapper.selectByMainId(asn.getId());
|
||||||
List<AsnDetail> updateToDetails = new ArrayList<>();
|
if (CollectionUtils.isNotEmpty(details)) {
|
||||||
for (AsnDetail detail : details) {
|
for (AsnDetail detail : details) {
|
||||||
detail.setStatus(AsnStatusEnum.CANCELED.getValue());
|
detail.setStatus(AsnStatusEnum.CANCELED.getValue());
|
||||||
updateToDetails.add(detail);
|
}
|
||||||
}
|
asnDetailService.updateBatchById(details);
|
||||||
if (CollectionUtils.isNotEmpty(updateToDetails)) {
|
|
||||||
asnDetailMapper.updateById(updateToDetails);
|
|
||||||
}
|
}
|
||||||
asn.setStatus(AsnStatusEnum.CANCELED.getValue());
|
asn.setStatus(AsnStatusEnum.CANCELED.getValue());
|
||||||
this.baseMapper.updateById(asn);
|
asnDataProcessor.updateAsn(asn);
|
||||||
|
|
||||||
/* if (CollectionUtils.isNotEmpty(details)) {
|
|
||||||
Stock stock = stockMapper.selectById(details.get(0).getStockId());
|
|
||||||
if (stock != null) {
|
|
||||||
stock.setStatus(CommonStatusEnum.FREE.getValue());
|
|
||||||
stockMapper.updateById(stock);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@Transactional(rollbackFor = Exception.class)
|
|
||||||
public void closeAsn(List<Long> asnIds) {
|
public void closeAsn(List<Long> asnIds) {
|
||||||
if (CollectionUtils.isEmpty(asnIds)) {
|
if (CollectionUtils.isEmpty(asnIds)) {
|
||||||
throw new RuntimeException("请选择需要关闭的入库单");
|
throw new RuntimeException("请选择需要关闭的入库单");
|
||||||
}
|
}
|
||||||
Map<Long, Asn> asnMap = asnDetailService.queryByAsnIdsToMap(asnIds);
|
|
||||||
List<AsnDetail> asnDetails = asnDetailMapper.queryByAsnIds(asnIds);
|
// 批量查询入库单
|
||||||
//根据出库单 ID 分组
|
List<Asn> asnList = this.listByIds(asnIds);
|
||||||
Map<Long, List<AsnDetail>> asnDetailMapGroup = asnDetails.stream().collect(Collectors.groupingBy(AsnDetail::getAsnId));
|
if (CollectionUtils.isEmpty(asnList)) {
|
||||||
for (Map.Entry<Long, List<AsnDetail>> entry : asnDetailMapGroup.entrySet()) {
|
throw new RuntimeException("未找到需要关闭的入库单");
|
||||||
Asn asn = asnMap.get(entry.getKey());
|
|
||||||
List<AsnDetail> asnDetailList = entry.getValue();
|
|
||||||
for (AsnDetail asnDetail : asnDetailList) {
|
|
||||||
asnDetail.setStatus(AsnStatusEnum.CLOSED.getValue());
|
|
||||||
}
|
|
||||||
asnDetailMapper.updateById(asnDetailList);
|
|
||||||
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
|
||||||
this.baseMapper.updateById(asn);
|
|
||||||
}
|
}
|
||||||
//库存可用
|
|
||||||
List<Long> stockIds = asnDetails.stream().map(AsnDetail::getStockId).distinct().toList();
|
|
||||||
/* if(CollectionUtils.isNotEmpty(stockIds)){
|
|
||||||
LambdaQueryWrapper<Inventory> queryWrapper = new LambdaQueryWrapper<>();
|
|
||||||
queryWrapper.in(Inventory::getStockId, stockIds);
|
|
||||||
List<Inventory> inventoryList = inventoryMapper.selectList(queryWrapper);
|
|
||||||
for (Inventory inventory : inventoryList){
|
|
||||||
inventory.setStatus(InventoryStatusEnum.AVAILABLE.getValue());
|
|
||||||
}
|
|
||||||
if (CollectionUtils.isNotEmpty(inventoryList)){
|
|
||||||
inventoryMapper.updateById(inventoryList);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
|
// 提取有效的 ASN ID 集合
|
||||||
|
List<Long> validAsnIds = asnList.stream().map(Asn::getId).toList();
|
||||||
|
|
||||||
|
// 批量查询所有 ASN 明细
|
||||||
|
List<AsnDetail> allAsnDetails = asnDetailMapper.queryByAsnIds(validAsnIds);
|
||||||
|
|
||||||
|
// 批量更新明细状态为已关闭
|
||||||
|
if (CollectionUtils.isNotEmpty(allAsnDetails)) {
|
||||||
|
for (AsnDetail detail : allAsnDetails) {
|
||||||
|
detail.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||||
|
}
|
||||||
|
asnDetailService.updateBatchById(allAsnDetails);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 批量更新主表状态为已关闭
|
||||||
|
for (Asn asn : asnList) {
|
||||||
|
asn.setStatus(AsnStatusEnum.CLOSED.getValue());
|
||||||
|
}
|
||||||
|
this.updateBatchById(asnList);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
package org.cpte.modules.inbound.service.impl;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.cpte.feign.client.BasicServiceClient;
|
||||||
|
import org.cpte.modules.basic.dto.ItemDTO;
|
||||||
|
import org.cpte.modules.inbound.request.ReceiveRequest;
|
||||||
|
import org.jeecg.common.api.vo.Result;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
@Slf4j
|
||||||
|
public class ReceiveServiceImpl {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private BasicServiceClient basicServiceClient;
|
||||||
|
|
||||||
|
public void receive(ReceiveRequest request) {
|
||||||
|
//获取当前时间yyyy-MM-dd HH:MM:ss 这种格式
|
||||||
|
String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
|
||||||
|
|
||||||
|
log.info("开始收货:{},时间:{}", request, currentTime);
|
||||||
|
//1.参数校验
|
||||||
|
validateParams(request);
|
||||||
|
|
||||||
|
//2.校验物料
|
||||||
|
ItemDTO item = validateItem(request.getItemCode());
|
||||||
|
log.info("物料信息:{}", item);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验参数
|
||||||
|
*/
|
||||||
|
private void validateParams(ReceiveRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
throw new IllegalArgumentException("收货参数不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(request.getItemCode())) {
|
||||||
|
throw new IllegalArgumentException("物料编码不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(request.getPointCode())) {
|
||||||
|
throw new IllegalArgumentException("库位编码不能为空");
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(request.getStockCode())) {
|
||||||
|
throw new IllegalArgumentException("容器编码不能为空");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 校验物料
|
||||||
|
*/
|
||||||
|
private ItemDTO validateItem(String itemCode) {
|
||||||
|
Result<ItemDTO> itemResult = basicServiceClient.getItemByCode(itemCode);
|
||||||
|
if (itemResult.isSuccess()) {
|
||||||
|
return itemResult.getResult();
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException(itemResult.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,17 +0,0 @@
|
||||||
package org.cpte.modules.inbound.vo;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import org.cpte.modules.basic.dto.PointDTO;
|
|
||||||
import org.cpte.modules.basic.dto.StockDTO;
|
|
||||||
import org.cpte.modules.inbound.entity.Asn;
|
|
||||||
import org.cpte.modules.inbound.entity.AsnDetail;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Data
|
|
||||||
public class ReceiveData {
|
|
||||||
private Asn asn ;
|
|
||||||
private List<AsnDetail> asnDetails;
|
|
||||||
private StockDTO stock;
|
|
||||||
private PointDTO point;
|
|
||||||
}
|
|
||||||
|
|
@ -257,11 +257,11 @@ feign:
|
||||||
loggerLevel: BASIC
|
loggerLevel: BASIC
|
||||||
# 本地开发环境服务地址配置
|
# 本地开发环境服务地址配置
|
||||||
wms-basic:
|
wms-basic:
|
||||||
url: http://localhost:8001
|
url: http://localhost:8001/cpte-wms-basic
|
||||||
wms-inventory:
|
wms-inventory:
|
||||||
url: http://localhost:8004
|
url: http://localhost:8004/cpte-wms-inventory
|
||||||
wms-schedule:
|
wms-schedule:
|
||||||
url: http://localhost:8005
|
url: http://localhost:8005/cpte-wms-schedule
|
||||||
|
|
||||||
#第三方登录
|
#第三方登录
|
||||||
justauth:
|
justauth:
|
||||||
|
|
|
||||||
|
|
@ -36,4 +36,14 @@
|
||||||
</foreach>
|
</foreach>
|
||||||
ORDER BY line_no
|
ORDER BY line_no
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<delete id="deleteByBatchAsnIds">
|
||||||
|
DELETE
|
||||||
|
FROM data_asn_detail
|
||||||
|
WHERE
|
||||||
|
asn_id IN
|
||||||
|
<foreach item="asnId" index="index" collection="asnIds" open="(" separator="," close=")">
|
||||||
|
#{asnId}
|
||||||
|
</foreach>
|
||||||
|
</delete>
|
||||||
</mapper>
|
</mapper>
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
||||||
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
||||||
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
||||||
@EnableFeignClients(basePackages = {"org.cpte.feign.client"}) // 启用 Feign 客户端
|
@EnableFeignClients(basePackages = {"org.cpte.feign"}) // 启用 Feign 客户端,包含 client 和 config 包
|
||||||
public class WmsInventoryApplication extends SpringBootServletInitializer {
|
public class WmsInventoryApplication extends SpringBootServletInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.cpte.modules.inventory.rule;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.cpte.modules.utils.CodeGeneratorUtil;
|
import org.cpte.common.util.CodeGeneratorUtil;
|
||||||
import org.jeecg.common.handler.IFillRuleHandler;
|
import org.jeecg.common.handler.IFillRuleHandler;
|
||||||
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.cpte.modules.inventory.rule;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.cpte.modules.utils.CodeGeneratorUtil;
|
import org.cpte.common.util.CodeGeneratorUtil;
|
||||||
import org.jeecg.common.handler.IFillRuleHandler;
|
import org.jeecg.common.handler.IFillRuleHandler;
|
||||||
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
package org.cpte.modules.utils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.dao.CannotAcquireLockException;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class CodeGeneratorUtil {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public JdbcTemplate jdbcTemplate;
|
|
||||||
|
|
||||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成业务编号
|
|
||||||
*
|
|
||||||
* @param type 业务类型,如 RK、CK、PK、MK
|
|
||||||
* @return 完整业务编号
|
|
||||||
*/
|
|
||||||
@Transactional
|
|
||||||
public String generateSerialNumber(String type) {
|
|
||||||
try {
|
|
||||||
String dateStr = LocalDate.now().format(DATE_FORMATTER);
|
|
||||||
String sql = "SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? for update";
|
|
||||||
List<Integer> result = jdbcTemplate.queryForList(sql, Integer.class, type, dateStr);
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
String insertSql = "INSERT INTO generator_sequence (type, date_str, current_seq) VALUES (?, ?, 1)";
|
|
||||||
jdbcTemplate.update(insertSql, type, dateStr);
|
|
||||||
return type + dateStr + "000001";
|
|
||||||
} else {
|
|
||||||
Integer currentSeq = result.get(0);
|
|
||||||
String updateSql = "UPDATE generator_sequence SET current_seq = current_seq + 1 WHERE type = ? AND date_str = ?";
|
|
||||||
jdbcTemplate.update(updateSql, type, dateStr);
|
|
||||||
|
|
||||||
String seqStr = String.format("%06d", currentSeq + 1);
|
|
||||||
return type + dateStr + seqStr;
|
|
||||||
}
|
|
||||||
} catch (CannotAcquireLockException e) {
|
|
||||||
throw new RuntimeException("单号生成中,请稍后重试", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
||||||
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
||||||
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
||||||
@EnableFeignClients(basePackages = {"org.cpte.feign.client"}) // 启用 Feign 客户端
|
@EnableFeignClients(basePackages = {"org.cpte.feign"}) // 启用 Feign 客户端,包含 client 和 config 包
|
||||||
public class WmsOutboundApplication extends SpringBootServletInitializer {
|
public class WmsOutboundApplication extends SpringBootServletInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ package org.cpte.modules.outbound.rule;
|
||||||
|
|
||||||
import com.alibaba.fastjson.JSONObject;
|
import com.alibaba.fastjson.JSONObject;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.cpte.modules.utils.CodeGeneratorUtil;
|
import org.cpte.common.util.CodeGeneratorUtil;
|
||||||
import org.jeecg.common.handler.IFillRuleHandler;
|
import org.jeecg.common.handler.IFillRuleHandler;
|
||||||
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
import org.jeecg.modules.system.mapper.SysFillRuleMapper;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
package org.cpte.modules.utils;
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.dao.CannotAcquireLockException;
|
|
||||||
import org.springframework.jdbc.core.JdbcTemplate;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
import java.time.LocalDate;
|
|
||||||
import java.time.format.DateTimeFormatter;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Slf4j
|
|
||||||
@Component
|
|
||||||
public class CodeGeneratorUtil {
|
|
||||||
|
|
||||||
@Autowired
|
|
||||||
public JdbcTemplate jdbcTemplate;
|
|
||||||
|
|
||||||
private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormatter.ofPattern("yyMMdd");
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 生成业务编号
|
|
||||||
*
|
|
||||||
* @param type 业务类型,如 RK、CK、PK、MK
|
|
||||||
* @return 完整业务编号
|
|
||||||
*/
|
|
||||||
@Transactional
|
|
||||||
public String generateSerialNumber(String type) {
|
|
||||||
try {
|
|
||||||
String dateStr = LocalDate.now().format(DATE_FORMATTER);
|
|
||||||
String sql = "SELECT current_seq FROM generator_sequence WHERE type = ? AND date_str = ? for update";
|
|
||||||
List<Integer> result = jdbcTemplate.queryForList(sql, Integer.class, type, dateStr);
|
|
||||||
if (result.isEmpty()) {
|
|
||||||
String insertSql = "INSERT INTO generator_sequence (type, date_str, current_seq) VALUES (?, ?, 1)";
|
|
||||||
jdbcTemplate.update(insertSql, type, dateStr);
|
|
||||||
return type + dateStr + "000001";
|
|
||||||
} else {
|
|
||||||
Integer currentSeq = result.get(0);
|
|
||||||
String updateSql = "UPDATE generator_sequence SET current_seq = current_seq + 1 WHERE type = ? AND date_str = ?";
|
|
||||||
jdbcTemplate.update(updateSql, type, dateStr);
|
|
||||||
|
|
||||||
String seqStr = String.format("%06d", currentSeq + 1);
|
|
||||||
return type + dateStr + seqStr;
|
|
||||||
}
|
|
||||||
} catch (CannotAcquireLockException e) {
|
|
||||||
throw new RuntimeException("单号生成中,请稍后重试", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -26,7 +26,7 @@ import java.util.Map;
|
||||||
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
@SpringBootApplication(scanBasePackages = {"org.jeecg", "org.cpte", "org.cpte.modules"})
|
||||||
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
@EnableAutoConfiguration(exclude = {MongoAutoConfiguration.class})
|
||||||
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
@ImportAutoConfiguration(JustAuthAutoConfiguration.class) // spring boot 3.x justauth 兼容性处理
|
||||||
@EnableFeignClients(basePackages = {"org.cpte.feign.client"}) // 启用 Feign 客户端
|
@EnableFeignClients(basePackages = {"org.cpte.feign"}) // 启用 Feign 客户端,包含 client 和 config 包
|
||||||
public class WmsScheduleApplication extends SpringBootServletInitializer {
|
public class WmsScheduleApplication extends SpringBootServletInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue