0729接口逻辑修改

This commit is contained in:
2025-07-29 16:18:53 +08:00
parent 0696040874
commit 20f6be7790
17 changed files with 225 additions and 686 deletions

View File

@@ -8,16 +8,11 @@ import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.PostConstruct;
import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.InputStream;
import java.util.Base64;
import java.util.UUID;
import java.util.Date;
/**
* MinIO 工具类(支持上传并设置 bucket 公共访问权限)
*/
@Component
public class MinioUtil {
@@ -44,29 +39,30 @@ public class MinioUtil {
}
/**
* 上传文件到指定 bucket 的指定目录(自动设置公共权限)
*
* @param file 上传的文件
* @param bucketName bucket 名称
* @param folder 目录前缀(如 "signature/"
* @return 返回公网可访问的 URL
* @throws Exception 异常
* 自动生成今日目录yyyy-MM-dd/
*/
private String getTodayFolder() {
return DateUtils.parseDateToStr("yyyy-MM-dd", DateUtils.getNowDate()) + "/";
}
/**
* 上传文件到指定 bucket 和目录
*/
public String upload(MultipartFile file, String bucketName, String folder) throws Exception {
String originalName = file.getOriginalFilename();
String ext = originalName != null && originalName.contains(".")
String ext = (originalName != null && originalName.contains("."))
? originalName.substring(originalName.lastIndexOf("."))
: "";
String objectName = folder + UUID.randomUUID().toString().replace("-", "") + ext;
try (InputStream in = file.getInputStream()) {
// 如果 bucket 不存在,则创建
// 检查或创建 bucket
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
// 强制设置 bucket 策略为 public-read幂等
// 设置 bucket 公共策略
String policyJson = "{\n" +
" \"Version\":\"2012-10-17\",\n" +
" \"Statement\":[\n" +
@@ -79,14 +75,12 @@ public class MinioUtil {
" ]\n" +
"}";
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(policyJson)
.build()
);
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(policyJson)
.build());
// 上传文件
// 上传
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
.object(objectName)
@@ -97,19 +91,21 @@ public class MinioUtil {
return endpoint + "/" + bucketName + "/" + objectName;
}
/**
* 上传 Base64 图片到指定 bucket 和目录
*/
public String uploadBase64(String imgStr, String bucketName, String folder) {
try {
String objectName = folder + UUID.randomUUID().toString().replace("-", "") + ".png";
imgStr = imgStr.replace("data:image/png;base64,", "").replace("data:image/jpeg;base64,", "");
byte[] imageBytes = Base64.getDecoder().decode(imgStr);
// 确保 bucket 存在
boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
if (!exists) {
minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
// 设置公共访问策略(幂等)
String policyJson = "{\n" +
" \"Version\":\"2012-10-17\",\n" +
" \"Statement\":[\n" +
@@ -122,14 +118,11 @@ public class MinioUtil {
" ]\n" +
"}";
minioClient.setBucketPolicy(
SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(policyJson)
.build()
);
minioClient.setBucketPolicy(SetBucketPolicyArgs.builder()
.bucket(bucketName)
.config(policyJson)
.build());
// 构造 InputStream 上传
try (InputStream inputStream = new java.io.ByteArrayInputStream(imageBytes)) {
minioClient.putObject(PutObjectArgs.builder()
.bucket(bucketName)
@@ -147,17 +140,30 @@ public class MinioUtil {
}
/**
* 上传文件到默认 bucket 根目录
* 默认 bucket 上传
*/
public String upload(MultipartFile file) throws Exception {
return upload(file, defaultBucket, "");
}
/**
* 上传文件到默认 bucket 指定目录
* 默认 bucket 指定目录上传
*/
public String upload(MultipartFile file, String folder) throws Exception {
return upload(file, defaultBucket, folder);
}
/**
* 默认 bucket按日期目录上传MultipartFile
*/
public String uploadToDateFolder(MultipartFile file) throws Exception {
return upload(file, defaultBucket, getTodayFolder());
}
/**
* 默认 bucket按日期目录上传Base64
*/
public String uploadBase64ToDateFolder(String imgStr) {
return uploadBase64(imgStr, defaultBucket, getTodayFolder());
}
}

View File

@@ -37,7 +37,7 @@ public class DeviceInfoController extends BaseController
/**
* 查询设备信息列表
*/
// @PreAuthorize("@ss.hasPermi('information:device:list')")
@PreAuthorize("@ss.hasPermi('information:device:list')")
@GetMapping("/list")
public TableDataInfo list(DeviceInfo deviceInfo)
{

View File

@@ -28,7 +28,7 @@ public class GysJhController extends BaseController
@Autowired
private IGysJhService gysJhService;
/**
/**A
* 查询供应计划列表
*/
@PreAuthorize("@ss.hasPermi('plan:jh:list')")

View File

@@ -35,7 +35,7 @@ public class MoveRecordController extends BaseController
/**
* 新增移库记录
*/
@PreAuthorize("@ss.hasPermi('inventory:move:add')")
@PreAuthorize("@ss.hasPermi('wisdom:stock:move')")
@Log(title = "移库记录", businessType = BusinessType.INSERT)
@PostMapping("/add")
public AjaxResult processMove(@RequestBody MoveRequestDTO dto) {
@@ -47,7 +47,7 @@ public class MoveRecordController extends BaseController
/**
* 查询移库记录列表
*/
@PreAuthorize("@ss.hasPermi('inventory:move:list')")
@PreAuthorize("@ss.hasPermi('wisdom:move:list')")
@GetMapping("/list")
public TableDataInfo list(MoveRecord moveRecord)
{

View File

@@ -85,7 +85,7 @@ public class RkInfoController extends BaseController
*/
@PreAuthorize("@ss.hasPermi('wisdom:stock:edit')")
@Log(title = "库存单据主", businessType = BusinessType.UPDATE)
@PutMapping
@PutMapping("/update")
public AjaxResult edit(@RequestBody RkInfo rkInfo)
{
return toAjax(rkInfoService.updateRkInfo(rkInfo));

View File

@@ -73,9 +73,10 @@ public interface GysJhMapper
/**
* 修改状态
* @param gysJhId
* @param gysJhId 主键ID
* @param status 状态值1=全部入库2=部分入库)
*/
void updateStatusById(Long gysJhId);
void updateStatusById(@Param("id") Long gysJhId, @Param("status") String status);
/**
* 重置状态

View File

@@ -175,7 +175,7 @@ public class AuditSignatureServiceImpl implements IAuditSignatureService
.collect(Collectors.toSet());
for (Long jhId : jhIdSet) {
gysJhMapper.updateStatusById(jhId);
gysJhMapper.updateStatusById(jhId,"1");
}
}

View File

@@ -10,11 +10,13 @@ import com.zg.common.utils.http.HttpUtils;
import com.zg.framework.web.domain.AjaxResult;
import com.zg.project.information.mapper.MtdMapper;
import com.zg.project.wisdom.domain.AgvTaskResult;
import com.zg.project.wisdom.domain.AgyWcs;
import com.zg.project.wisdom.domain.DdTask;
import com.zg.project.wisdom.domain.WcsTaskResult;
import com.zg.project.wisdom.domain.dto.TaskExecuteDTO;
import com.zg.project.wisdom.domain.vo.TaskExecuteResultVO;
import com.zg.project.wisdom.mapper.AgvTaskResultMapper;
import com.zg.project.wisdom.mapper.AgyWcsMapper;
import com.zg.project.wisdom.mapper.DdTaskMapper;
import com.zg.project.wisdom.mapper.WcsTaskResultMapper;
import com.zg.project.wisdom.service.IDdTaskService;
@@ -52,6 +54,9 @@ public class DdTaskServiceImpl implements IDdTaskService {
@Autowired
private MtdMapper mtdMapper;
@Autowired
private AgyWcsMapper agyWcsMapper;
//
// @Value("${agv.job.create-url}")
// private String agvJobCreateUrl;
@@ -126,17 +131,20 @@ public class DdTaskServiceImpl implements IDdTaskService {
return ddTaskMapper.deleteDdTaskById(id);
}
/**
* 执行任务
*/
@Override
@Transactional(rollbackFor = Exception.class)
public TaskExecuteResultVO executeTask(TaskExecuteDTO dto) {
Long id = dto.getId();
String targetName = dto.getTargetName();
Integer materialStatus = dto.getMaterialStatus(); // Materialstatus 前端传入
Integer materialStatus = dto.getMaterialStatus();
if (StringUtils.isBlank(targetName)) {
throw new ServiceException("targetName 不能为空");
}
// 1. 查询任务
DdTask task = ddTaskMapper.selectDdTaskById(id);
if (task == null) {
throw new ServiceException("任务不存在ID = " + id);
@@ -146,84 +154,144 @@ public class DdTaskServiceImpl implements IDdTaskService {
}
String taskNo = task.getTaskNo();
String taskType = task.getTaskType(); // 0入库1出库2移库
String requestId = null; // ✅ AGV 使用
String taskIdParam = null; // ✅ WCS 使用,提前声明防作用域错误
String taskType = task.getTaskType();
String requestId = null;
String taskIdParam = null;
String response;
int code;
String msg;
String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
// 2. 构造参数
JSONObject param = new JSONObject();
param.put("owner", "wms");
param.put("type", taskType);
param.put("priority", 1);
param.put("sourceName", task.getSourceName());
param.put("targetName", targetName);
if ("0".equals(taskType) || "2".equals(taskType)) {
// ✅ 入库/移库 → AGV
requestId = taskNo + ("0".equals(taskType) ? "11" : "12"); // 拼接规则11 入库12 移库
param.put("taskNo", taskNo);
param.put("requestId", requestId);
log.info("[任务执行] 类型={}AGVrequestId={}, param={}", taskType, requestId, param);
response = HttpUtils.sendPost(agvJobCreateUrl, param.toJSONString());
} else if ("1".equals(taskType)) {
// ✅ 出库 → WCS下架不传 requestId只传 TaskID
if ("1".equals(taskType)) {
// 出库任务:先调 WCS
taskIdParam = taskNo + "22";
param.put("TaskID", taskIdParam);
param.put("Materialstatus", materialStatus);
param.put("outBack", 1);
param.put("TrayNo", "");
param.put("Mlocation", task.getSourceName());
JSONObject wcsParam = new JSONObject();
wcsParam.put("TaskID", taskIdParam);
wcsParam.put("TaskType", 2);
wcsParam.put("Mlocation", task.getSourceName());
wcsParam.put("TrayNo", "");
wcsParam.put("Materialstatus", materialStatus);
wcsParam.put("outBack", 1);
if (materialStatus == 0) {
param.put("MaterialCode", "");
param.put("Specification", "");
param.put("Quantity", "");
wcsParam.put("MaterialCode", "");
wcsParam.put("Specification", "");
wcsParam.put("Quantity", "");
} else {
String materialCode = task.getMid();
String quantity = task.getNum().toString();
String specification = mtdMapper.selectWlmsByWlbh(materialCode);
param.put("MaterialCode", materialCode);
param.put("Quantity", quantity);
param.put("Specification", specification == null ? "" : specification);
wcsParam.put("MaterialCode", materialCode);
wcsParam.put("Quantity", quantity);
wcsParam.put("Specification", specification == null ? "" : specification);
}
log.info("[任务执行] 类型=出库WCS下架TaskID={}, param={}", taskIdParam, param);
response = HttpUtils.sendPost(wcsJobCreateUrl, param.toJSONString());
log.info("[任务执行] 出库 → 调用WCStaskId={}, param={}", taskIdParam, wcsParam);
response = HttpUtils.sendPost(wcsJobCreateUrl, wcsParam.toJSONString());
} else {
throw new ServiceException("未知任务类型: " + taskType);
}
System.out.println("这是打印的出库时调用wcs的响应结果" + response);
// 3. 解析响应
JSONObject respJson;
try {
respJson = JSON.parseObject(response);
code = respJson.getInteger("code");
msg = respJson.getString("msg");
} catch (Exception e) {
throw new ServiceException("响应解析失败: " + response);
}
JSONObject respJson;
try {
respJson = JSON.parseObject(response);
code = respJson.getInteger("code");
msg = respJson.getString("msg");
} catch (Exception e) {
throw new ServiceException("WCS响应解析失败: " + response);
}
if (code != 200) {
throw new ServiceException("任务执行失败: " + msg);
}
if (code != 200) {
throw new ServiceException("WCS任务执行失败: " + msg);
}
// 4. 更新任务状态为已提交
task.setTaskStatus(1);
task.setDoCount(Optional.ofNullable(task.getDoCount()).orElse(0) + 1);
task.setUpdateBy(SecurityUtils.getUserId().toString());
task.setUpdateTime(DateUtils.getNowDate());
ddTaskMapper.updateDdTask(task);
// 写入 WCS 执行记录
WcsTaskResult wcs = new WcsTaskResult();
wcs.setTaskId(taskIdParam);
wcs.setTaskStatus("1");
wcs.setMsg(msg);
wcs.setOwner("wms");
wcs.setType(taskType);
wcs.setPriority("1");
wcs.setSourceName(task.getSourceName());
wcs.setTargetName(targetName);
wcs.setIsDelete("0");
wcs.setCreateBy(userId);
wcs.setCreateTime(now);
wcs.setUpdateTime(now);
wcsTaskResultMapper.insertWcsTaskResult(wcs);
// 5. 写入执行记录
String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
// 调用 AGV立即
requestId = taskNo + "12";
JSONObject agvParam = new JSONObject();
agvParam.put("owner", "wms");
agvParam.put("type", "1");
agvParam.put("priority", 1);
agvParam.put("sourceName", task.getSourceName());
agvParam.put("targetName", targetName);
agvParam.put("taskNo", taskNo);
agvParam.put("requestId", requestId);
log.info("[任务执行] 出库 → 调用AGVrequestId={}, param={}", requestId, agvParam);
response = HttpUtils.sendPost(agvJobCreateUrl, agvParam.toJSONString());
try {
respJson = JSON.parseObject(response);
code = respJson.getInteger("code");
msg = respJson.getString("msg");
} catch (Exception e) {
throw new ServiceException("AGV响应解析失败: " + response);
}
if (code != 200) {
throw new ServiceException("AGV任务执行失败: " + msg);
}
AgvTaskResult agv = new AgvTaskResult();
agv.setRequestId(requestId);
agv.setTaskNo(taskNo);
agv.setStatus("CREATED");
agv.setMsg(msg);
agv.setOwner("wms");
agv.setType(taskType);
agv.setPriority("1");
agv.setSourceName(task.getSourceName());
agv.setTargetName(targetName);
agv.setIsDelete("0");
agv.setCreateBy(userId);
agv.setCreateTime(now);
agv.setUpdateTime(now);
agvTaskResultMapper.insertAgvTaskResult(agv);
// ✅ 保存 WCS 与 AGV 映射关系
AgyWcs mapping = new AgyWcs();
mapping.setRequestId(requestId);
mapping.setTaskId(taskIdParam);
agyWcsMapper.insertAgyWcs(mapping);
} else {
// 入库/移库任务 → 调用 AGV
requestId = taskNo + ("0".equals(taskType) ? "11" : "12");
JSONObject param = new JSONObject();
param.put("owner", "wms");
param.put("type", taskType);
param.put("priority", 1);
param.put("sourceName", task.getSourceName());
param.put("targetName", targetName);
param.put("taskNo", taskNo);
param.put("requestId", requestId);
log.info("[任务执行] 类型={}AGVrequestId={}, param={}", taskType, requestId, param);
response = HttpUtils.sendPost(agvJobCreateUrl, param.toJSONString());
JSONObject respJson = JSON.parseObject(response);
code = respJson.getInteger("code");
msg = respJson.getString("msg");
if (code != 200) {
throw new ServiceException("任务执行失败: " + msg);
}
if ("0".equals(taskType) || "2".equals(taskType)) {
AgvTaskResult agv = new AgvTaskResult();
agv.setRequestId(requestId);
agv.setTaskNo(taskNo);
@@ -239,27 +307,16 @@ public class DdTaskServiceImpl implements IDdTaskService {
agv.setCreateTime(now);
agv.setUpdateTime(now);
agvTaskResultMapper.insertAgvTaskResult(agv);
} else if ("1".equals(taskType)) {
WcsTaskResult wcs = new WcsTaskResult();
wcs.setTaskId(taskIdParam);
wcs.setTaskStatus("1");
wcs.setMsg(msg);
wcs.setJobId(null);
wcs.setOwner("wms");
wcs.setType(taskType);
wcs.setPriority("1");
wcs.setSourceName(task.getSourceName());
wcs.setTargetName(targetName);
wcs.setIsDelete("0");
wcs.setCreateBy(userId);
wcs.setCreateTime(now);
wcs.setUpdateTime(now);
wcsTaskResultMapper.insertWcsTaskResult(wcs);
}
// 6. 返回执行结果
task.setTaskStatus(1);
task.setDoCount(Optional.ofNullable(task.getDoCount()).orElse(0) + 1);
task.setUpdateBy(userId);
task.setUpdateTime(now);
ddTaskMapper.updateDdTask(task);
TaskExecuteResultVO vo = new TaskExecuteResultVO();
vo.setRequestId(("0".equals(taskType) || "2".equals(taskType)) ? requestId : null);
vo.setRequestId(requestId);
vo.setCode(code);
vo.setMsg(msg);
return vo;

View File

@@ -188,32 +188,39 @@ public class RkInfoServiceImpl implements IRkInfoService
(a, b) -> b
));
// ✅ 第2步:查询对应供应计划
List<GysJh> jhList = gysJhMapper.selectByIds(new ArrayList<>(realQtyMap.keySet()));
Set<Long> idsToUpdateStatus = new HashSet<>();
// ✅ 第2-4步若包含供应计划ID则处理计划扣减与状态更新
if (!realQtyMap.isEmpty()) {
// ✅ 查询对应供应计划
List<GysJh> jhList = gysJhMapper.selectByIds(new ArrayList<>(realQtyMap.keySet()));
Set<Long> idsToUpdateStatus = new HashSet<>();
// ✅ 第3步更新 jh_qty 和 status根据是否开启审核判断逻辑
for (GysJh jh : jhList) {
Long jhId = jh.getId();
BigDecimal planQty = BigDecimal.valueOf(jh.getJhQty());
BigDecimal realQty = realQtyMap.get(jhId);
if (realQty == null) continue;
// ✅ 更新 jh_qty 和 status根据是否开启审核判断逻辑
for (GysJh jh : jhList) {
Long jhId = jh.getId();
BigDecimal planQty = BigDecimal.valueOf(jh.getJhQty());
BigDecimal realQty = realQtyMap.get(jhId);
if (realQty == null) continue;
boolean isEqual = realQty.compareTo(planQty) == 0;
boolean isEqual = realQty.compareTo(planQty) == 0;
if (!isEqual) {
gysJhMapper.decreaseJhQtyById(jhId, realQty);
idsToUpdateStatus.add(jhId);
} else {
if (!needAudit) {
idsToUpdateStatus.add(jhId);
if (!isEqual) {
// 实到数量小于计划数量,执行扣减 + 设为部分入库2
gysJhMapper.decreaseJhQtyById(jhId, realQty);
if (!needAudit) {
gysJhMapper.updateStatusById(jhId, "2"); // 2 = 部分入库
}
} else {
// 实到数量等于计划数量状态设为全部入库1不做扣减
if (!needAudit) {
gysJhMapper.updateStatusById(jhId, "1"); // 1 = 全部入库
}
}
}
}
// ✅ 第4步批量更新 status = 2
if (!idsToUpdateStatus.isEmpty()) {
gysJhMapper.batchUpdateStatusByIds(idsToUpdateStatus);
// ✅ 批量更新 status = 2
if (!idsToUpdateStatus.isEmpty()) {
gysJhMapper.batchUpdateStatusByIds(idsToUpdateStatus);
}
}
// ✅ 第5步构建 RkInfo 入库记录
@@ -299,6 +306,7 @@ public class RkInfoServiceImpl implements IRkInfoService
}
}
/**
* 新增入库单据APP
* @param dto
@@ -346,13 +354,15 @@ public class RkInfoServiceImpl implements IRkInfoService
boolean isEqual = realQty.compareTo(planQty) == 0;
if (!isEqual) {
// 数量不相等,减数量 + 状态设为 2
// 实到数量小于计划数量,执行扣减 + 设为部分入库2
gysJhMapper.decreaseJhQtyById(jhId, realQty);
idsToUpdateStatus.add(jhId);
} else {
if (!needAudit) {
// 审核关闭且数量相等,仅更新状态
idsToUpdateStatus.add(jhId);
gysJhMapper.updateStatusById(jhId, "2"); // 2 = 部分入库
}
} else {
// 实到数量等于计划数量状态设为全部入库1不做扣减
if (!needAudit) {
gysJhMapper.updateStatusById(jhId, "1"); // 1 = 全部入库
}
}
}