diff --git a/pom.xml b/pom.xml
index 235580c..dcc3e62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -44,7 +44,7 @@
1.0.0
4.4.7
3.5.5
- 8.5.4
+ 7.1.4
diff --git a/src/main/java/com/zg/common/utils/MinioUtil.java b/src/main/java/com/zg/common/utils/MinioUtil.java
index 352e9d7..2e1046d 100644
--- a/src/main/java/com/zg/common/utils/MinioUtil.java
+++ b/src/main/java/com/zg/common/utils/MinioUtil.java
@@ -1,13 +1,16 @@
package com.zg.common.utils;
-import io.minio.*;
+import io.minio.MinioClient;
+import io.minio.PutObjectArgs;
+import io.minio.MakeBucketArgs;
+import io.minio.BucketExistsArgs;
+import io.minio.errors.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
+import javax.annotation.PostConstruct;
import java.io.InputStream;
-import java.time.LocalDate;
-import java.time.format.DateTimeFormatter;
import java.util.UUID;
@Component
@@ -23,38 +26,54 @@ public class MinioUtil {
private String secretKey;
@Value("${minio.bucketName}")
- private String bucketName;
+ private String defaultBucket;
- /**
- * 上传文件到 MinIO,自动根据日期生成路径
- * 如:2025/07/10/uuid-xxx.jpg
- */
- public String uploadFile(MultipartFile file) throws Exception {
- MinioClient client = MinioClient.builder()
+ private MinioClient minioClient;
+
+ @PostConstruct
+ public void init() {
+ minioClient = MinioClient.builder()
.endpoint(endpoint)
.credentials(accessKey, secretKey)
.build();
+ }
- // 检查桶是否存在,不存在则创建
- boolean found = client.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
- if (!found) {
- client.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
+ /**
+ * 上传文件到指定 bucket
+ * @param file 文件
+ * @param bucketName bucket 名称
+ * @return 返回访问URL
+ */
+ public String upload(MultipartFile file, String bucketName) throws Exception {
+ String originalName = file.getOriginalFilename();
+ String ext = originalName != null && originalName.contains(".")
+ ? originalName.substring(originalName.lastIndexOf("."))
+ : "";
+ String objectName = UUID.randomUUID().toString().replace("-", "") + ext;
+
+ InputStream in = file.getInputStream();
+
+ // 自动创建 bucket(如果不存在)
+ boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
+ if (!exists) {
+ minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
}
- String originalFilename = file.getOriginalFilename();
- String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
- String objectName = datePath + "/" + UUID.randomUUID().toString() + "-" + originalFilename;
+ // 上传文件
+ minioClient.putObject(PutObjectArgs.builder()
+ .bucket(bucketName)
+ .object(objectName)
+ .stream(in, file.getSize(), -1)
+ .contentType(file.getContentType())
+ .build());
- try (InputStream inputStream = file.getInputStream()) {
- client.putObject(PutObjectArgs.builder()
- .bucket(bucketName)
- .object(objectName)
- .stream(inputStream, file.getSize(), -1)
- .contentType(file.getContentType())
- .build());
- }
-
- // 返回完整可访问 URL(前端可直接使用)
return endpoint + "/" + bucketName + "/" + objectName;
}
+
+ /**
+ * 上传到默认 bucket
+ */
+ public String upload(MultipartFile file) throws Exception {
+ return upload(file, defaultBucket);
+ }
}
diff --git a/src/main/java/com/zg/project/wisdom/controller/AuditSignatureController.java b/src/main/java/com/zg/project/wisdom/controller/AuditSignatureController.java
new file mode 100644
index 0000000..47b57a2
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/controller/AuditSignatureController.java
@@ -0,0 +1,156 @@
+package com.zg.project.wisdom.controller;
+
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+
+import com.zg.common.exception.ServiceException;
+import com.zg.common.utils.MinioUtil;
+import com.zg.common.utils.SecurityUtils;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.*;
+import com.zg.framework.aspectj.lang.annotation.Log;
+import com.zg.framework.aspectj.lang.enums.BusinessType;
+import com.zg.project.wisdom.domain.AuditSignature;
+import com.zg.project.wisdom.service.IAuditSignatureService;
+import com.zg.framework.web.controller.BaseController;
+import com.zg.framework.web.domain.AjaxResult;
+import com.zg.common.utils.poi.ExcelUtil;
+import com.zg.framework.web.page.TableDataInfo;
+import org.springframework.web.multipart.MultipartFile;
+
+/**
+ * 审批记录Controller
+ *
+ * @author zg
+ * @date 2025-07-11
+ */
+@RestController
+@RequestMapping("/wisdom/signature")
+public class AuditSignatureController extends BaseController
+{
+ @Autowired
+ private IAuditSignatureService auditSignatureService;
+
+ @Autowired
+ private MinioUtil minioUtil;
+
+ /**
+ * 上传签字图片到 MinIO
+ */
+ @PostMapping("/upload")
+ public AjaxResult uploadSignatures(@RequestParam("files") MultipartFile[] files) {
+ if (files == null || files.length == 0) {
+ return AjaxResult.error("上传文件不能为空");
+ }
+
+ List urls = new ArrayList<>();
+ for (MultipartFile file : files) {
+ if (file != null && !file.isEmpty()) {
+ try {
+ String url = minioUtil.upload(file, "signature/");
+ urls.add(url);
+ } catch (Exception e) {
+ return AjaxResult.error("上传失败: " + e.getMessage());
+ }
+ }
+ }
+
+ return AjaxResult.success("上传成功").put("urls", urls);
+ }
+
+ /**
+ * 查询审批记录列表
+ */
+ @PreAuthorize("@ss.hasPermi('wisdom:signature:list')")
+ @GetMapping("/list")
+ public TableDataInfo list(AuditSignature auditSignature)
+ {
+ startPage();
+ List list = auditSignatureService.selectAuditSignatureList(auditSignature);
+ return getDataTable(list);
+ }
+
+ /**
+ * 导出审批记录列表
+ */
+ @PreAuthorize("@ss.hasPermi('wisdom:signature:export')")
+ @Log(title = "审批记录", businessType = BusinessType.EXPORT)
+ @PostMapping("/export")
+ public void export(HttpServletResponse response, AuditSignature auditSignature)
+ {
+ List list = auditSignatureService.selectAuditSignatureList(auditSignature);
+ ExcelUtil util = new ExcelUtil(AuditSignature.class);
+ util.exportExcel(response, list, "审批记录数据");
+ }
+
+ /**
+ * 获取审批记录详细信息
+ */
+ @PreAuthorize("@ss.hasPermi('wisdom:signature:query')")
+ @GetMapping(value = "/{id}")
+ public AjaxResult getInfo(@PathVariable("id") Long id)
+ {
+ return success(auditSignatureService.selectAuditSignatureById(id));
+ }
+
+ /**
+ * 新增审批记录
+ */
+ @PreAuthorize("@ss.hasPermi('wisdom:signature:add')")
+ @Log(title = "审批记录", businessType = BusinessType.INSERT)
+ @PostMapping
+ public AjaxResult add(@RequestBody AuditSignature auditSignature)
+ {
+ return toAjax(auditSignatureService.insertAuditSignature(auditSignature));
+ }
+
+ /**
+ * 修改审批记录
+ */
+ @PreAuthorize("@ss.hasPermi('wisdom:signature:edit')")
+ @Log(title = "审批记录", businessType = BusinessType.UPDATE)
+ @PutMapping
+ public AjaxResult edit(@RequestBody AuditSignature auditSignature)
+ {
+ return toAjax(auditSignatureService.updateAuditSignature(auditSignature));
+ }
+
+ /**
+ * 删除审批记录
+ */
+ @PreAuthorize("@ss.hasPermi('wisdom:signature:remove')")
+ @Log(title = "审批记录", businessType = BusinessType.DELETE)
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids)
+ {
+ return toAjax(auditSignatureService.deleteAuditSignatureByIds(ids));
+ }
+
+ /**
+ * 待审核列表
+ * @return
+ */
+ @GetMapping("/pending")
+ public AjaxResult getPending() {
+ String userId = SecurityUtils.getUserId().toString();
+ List list = auditSignatureService.selectPendingByUser(userId);
+ return AjaxResult.success(list);
+ }
+
+ /**
+ * 审核操作(通过 / 驳回)
+ */
+ @PostMapping("/audit")
+ public AjaxResult audit(@RequestBody AuditSignature audit) {
+ try {
+ auditSignatureService.audit(audit);
+ return AjaxResult.success("审核成功");
+ } catch (ServiceException e) {
+ return AjaxResult.error("审核失败:" + e.getMessage());
+ } catch (Exception e) {
+ return AjaxResult.error("系统异常,请联系管理员");
+ }
+ }
+}
diff --git a/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java b/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java
index 5b172e9..ffd1c03 100644
--- a/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java
+++ b/src/main/java/com/zg/project/wisdom/controller/RkInfoController.java
@@ -7,19 +7,10 @@ import javax.servlet.http.HttpServletResponse;
import com.zg.project.wisdom.domain.dto.PcRkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.RefundRequestDTO;
-import com.zg.project.wisdom.domain.dto.RkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.StockOutDTO;
-import com.zg.project.wisdom.service.IGysJhService;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PostMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.PathVariable;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
import com.zg.framework.aspectj.lang.annotation.Log;
import com.zg.framework.aspectj.lang.enums.BusinessType;
import com.zg.project.wisdom.domain.RkInfo;
@@ -42,6 +33,7 @@ public class RkInfoController extends BaseController
@Autowired
private IRkInfoService rkInfoService;
+
/**
* 查询库存单据主列表
*/
@@ -84,7 +76,8 @@ public class RkInfoController extends BaseController
@PreAuthorize("@ss.hasPermi('wisdom:stock:add')")
@Log(title = "库存单据主", businessType = BusinessType.INSERT)
public AjaxResult batchAdd(@RequestBody PcRkInfoBatchDTO dto) {
- return toAjax(rkInfoService.batchInsert(dto));
+ rkInfoService.batchInsert(dto);
+ return AjaxResult.success("提交成功");
}
/**
@@ -166,4 +159,6 @@ public class RkInfoController extends BaseController
public AjaxResult refundMaterial(@RequestBody RefundRequestDTO dto) {
return toAjax(rkInfoService.refundMaterial(dto));
}
+
+
}
diff --git a/src/main/java/com/zg/project/wisdom/domain/AuditSignature.java b/src/main/java/com/zg/project/wisdom/domain/AuditSignature.java
new file mode 100644
index 0000000..202ab73
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/domain/AuditSignature.java
@@ -0,0 +1,238 @@
+package com.zg.project.wisdom.domain;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.zg.framework.aspectj.lang.annotation.Excel;
+import com.zg.framework.web.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+import java.util.Date;
+
+/**
+ * 签字记录对象 audit_signature
+ */
+public class AuditSignature extends BaseEntity {
+
+ private static final long serialVersionUID = 1L;
+
+ /** 主键ID */
+ private Long id;
+
+ /** 单据编号 */
+ @Excel(name = "单据编号")
+ private String billNo;
+
+ /** 单据类型(0入库 1出库) */
+ @Excel(name = "单据类型")
+ private String billType;
+
+ /** 签字人ID */
+ @Excel(name = "签字人ID")
+ private String signerId;
+
+ /** 审批人ID */
+ @Excel(name = "审批人ID")
+ private String approverId;
+
+ /** 审批人签字图片URL */
+ @Excel(name = "审批人签字图片URL")
+ private String approverSignUrl;
+
+ /** 签字人角色(0发起人 1审批人 2拍照人) */
+ @Excel(name = "签字人角色")
+ private String signerRole;
+
+ /** 签名图片URL */
+ @Excel(name = "签名图片URL")
+ private String signUrl;
+
+ /** 签字时间 */
+ @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+ @Excel(name = "签字时间", width = 30, dateFormat = "yyyy-MM-dd HH:mm:ss")
+ private Date signTime;
+
+ /** 库位码 */
+ @Excel(name = "库位码")
+ private String pcode;
+
+ /** 托盘码 */
+ @Excel(name = "托盘码")
+ private String trayCode;
+
+ /** 审核结果(0通过 1驳回) */
+ @Excel(name = "审核结果")
+ private String auditResult;
+
+ /** 是否当前有效签字(1是 0否) */
+ @Excel(name = "当前有效")
+ private String isCurrent;
+
+ /** 图片类型(0签字 1现场图) */
+ @Excel(name = "图片类型")
+ private String imageType;
+
+ /** 备注 */
+ @Excel(name = "备注")
+ private String remark;
+
+ /** 逻辑删除(0正常 1删除) */
+ private String isDelete;
+
+ // ===== Getter & Setter =====
+
+ public Long getId() {
+ return id;
+ }
+
+ public void setId(Long id) {
+ this.id = id;
+ }
+
+ public String getBillNo() {
+ return billNo;
+ }
+
+ public void setBillNo(String billNo) {
+ this.billNo = billNo;
+ }
+
+ public String getBillType() {
+ return billType;
+ }
+
+ public void setBillType(String billType) {
+ this.billType = billType;
+ }
+
+ public String getSignerId() {
+ return signerId;
+ }
+
+ public void setSignerId(String signerId) {
+ this.signerId = signerId;
+ }
+
+ public String getApproverId() {
+ return approverId;
+ }
+
+ public void setApproverId(String approverId) {
+ this.approverId = approverId;
+ }
+
+ public String getApproverSignUrl() {
+ return approverSignUrl;
+ }
+
+ public void setApproverSignUrl(String approverSignUrl) {
+ this.approverSignUrl = approverSignUrl;
+ }
+
+ public String getSignerRole() {
+ return signerRole;
+ }
+
+ public void setSignerRole(String signerRole) {
+ this.signerRole = signerRole;
+ }
+
+ public String getSignUrl() {
+ return signUrl;
+ }
+
+ public void setSignUrl(String signUrl) {
+ this.signUrl = signUrl;
+ }
+
+ public Date getSignTime() {
+ return signTime;
+ }
+
+ public void setSignTime(Date signTime) {
+ this.signTime = signTime;
+ }
+
+ public String getPcode() {
+ return pcode;
+ }
+
+ public void setPcode(String pcode) {
+ this.pcode = pcode;
+ }
+
+ public String getTrayCode() {
+ return trayCode;
+ }
+
+ public void setTrayCode(String trayCode) {
+ this.trayCode = trayCode;
+ }
+
+ public String getAuditResult() {
+ return auditResult;
+ }
+
+ public void setAuditResult(String auditResult) {
+ this.auditResult = auditResult;
+ }
+
+ public String getIsCurrent() {
+ return isCurrent;
+ }
+
+ public void setIsCurrent(String isCurrent) {
+ this.isCurrent = isCurrent;
+ }
+
+ public String getImageType() {
+ return imageType;
+ }
+
+ public void setImageType(String imageType) {
+ this.imageType = imageType;
+ }
+
+ public String getRemark() {
+ return remark;
+ }
+
+ public void setRemark(String remark) {
+ this.remark = remark;
+ }
+
+ public String getIsDelete() {
+ return isDelete;
+ }
+
+ public void setIsDelete(String isDelete) {
+ this.isDelete = isDelete;
+ }
+
+ // ===== toString =====
+
+ @Override
+ public String toString() {
+ return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE)
+ .append("id", getId())
+ .append("billNo", getBillNo())
+ .append("billType", getBillType())
+ .append("signerId", getSignerId())
+ .append("approverId", getApproverId())
+ .append("approverSignUrl", getApproverSignUrl())
+ .append("signerRole", getSignerRole())
+ .append("signUrl", getSignUrl())
+ .append("signTime", getSignTime())
+ .append("pcode", getPcode())
+ .append("trayCode", getTrayCode())
+ .append("auditResult", getAuditResult())
+ .append("isCurrent", getIsCurrent())
+ .append("imageType", getImageType())
+ .append("remark", getRemark())
+ .append("createBy", getCreateBy())
+ .append("createTime", getCreateTime())
+ .append("updateBy", getUpdateBy())
+ .append("updateTime", getUpdateTime())
+ .append("isDelete", getIsDelete())
+ .toString();
+ }
+}
diff --git a/src/main/java/com/zg/project/wisdom/domain/RkBill.java b/src/main/java/com/zg/project/wisdom/domain/RkBill.java
index 20028c3..83cf74b 100644
--- a/src/main/java/com/zg/project/wisdom/domain/RkBill.java
+++ b/src/main/java/com/zg/project/wisdom/domain/RkBill.java
@@ -57,6 +57,7 @@ public class RkBill extends BaseEntity
// @Excel(name = "理货员")
private String lihuoY;
+
/** 出库类型 */
private String ckType;
@@ -155,6 +156,7 @@ public class RkBill extends BaseEntity
this.lihuoY = lihuoY;
}
+
public String getCkType() {
return ckType;
}
diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/AuditSignatureDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/AuditSignatureDTO.java
new file mode 100644
index 0000000..9a16354
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/domain/dto/AuditSignatureDTO.java
@@ -0,0 +1,13 @@
+package com.zg.project.wisdom.domain.dto;
+
+public class AuditSignatureDTO {
+ private String billNo;
+ private String billType; // 0-入库,1-出库
+ private String signerName;
+ private String signerRole; // 0-起始人,1-审核人,2-拍照人
+ private String signUrl; // 签字图片URL
+ private String pcode;
+ private String trayCode;
+ private String auditResult; // 0-通过,1-驳回
+ private String remark;
+}
\ No newline at end of file
diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java
index 74b680c..2133a2d 100644
--- a/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java
+++ b/src/main/java/com/zg/project/wisdom/domain/dto/PcRkInfoBatchDTO.java
@@ -1,12 +1,21 @@
package com.zg.project.wisdom.domain.dto;
+import lombok.Data;
+
import java.util.List;
/**
* PC端 - 入库请求 DTO
*/
+@Data
public class PcRkInfoBatchDTO {
+ /** 供应计划主键ID */
+ private Long gysJhId;
+
+ /** 审核人用户ID */
+ private String approverId;
+
/** 入库类型 */
private String rkType;
@@ -22,43 +31,10 @@ public class PcRkInfoBatchDTO {
/** 入库记录列表(每条为完整入库项) */
private List rkList;
- public String getRkType() {
- return rkType;
- }
+ /** 发起人签字图片 URL(单张) */
+ private String signatureUrl;
- public void setRkType(String rkType) {
- this.rkType = rkType;
- }
-
- public String getWlType() {
- return wlType;
- }
-
- public void setWlType(String wlType) {
- this.wlType = wlType;
- }
-
- public String getLihuoY() {
- return lihuoY;
- }
-
- public void setLihuoY(String lihuoY) {
- this.lihuoY = lihuoY;
- }
-
- public String getCangku() {
- return cangku;
- }
-
- public void setCangku(String cangku) {
- this.cangku = cangku;
- }
-
- public List getRkList() {
- return rkList;
- }
-
- public void setRkList(List rkList) {
- this.rkList = rkList;
- }
+ /** 现场照片 URL 列表(多张) */
+ private List photoUrls;
}
+
diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/RkInfoBatchDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/RkInfoBatchDTO.java
index a86114e..1abd9cd 100644
--- a/src/main/java/com/zg/project/wisdom/domain/dto/RkInfoBatchDTO.java
+++ b/src/main/java/com/zg/project/wisdom/domain/dto/RkInfoBatchDTO.java
@@ -1,9 +1,14 @@
package com.zg.project.wisdom.domain.dto;
-import java.util.List;
+import lombok.Data;
+import java.util.List;
+@Data
public class RkInfoBatchDTO {
+ /** 审核人用户ID */
+ private String approverId;
+
/** 入库类型 */
private String rkType;
@@ -19,43 +24,9 @@ public class RkInfoBatchDTO {
/** 入库物料列表 */
private List rkList;
- public String getRkType() {
- return rkType;
- }
+ /** 发起人签字图片 URL(单张) */
+ private String signatureUrl;
- public void setRkType(String rkType) {
- this.rkType = rkType;
- }
-
- public String getWlType() {
- return wlType;
- }
-
- public void setWlType(String wlType) {
- this.wlType = wlType;
- }
-
- public String getLihuoY() {
- return lihuoY;
- }
-
- public void setLihuoY(String lihuoY) {
- this.lihuoY = lihuoY;
- }
-
- public String getCangku() {
- return cangku;
- }
-
- public void setCangku(String cangku) {
- this.cangku = cangku;
- }
-
- public List getRkList() {
- return rkList;
- }
-
- public void setRkList(List rkList) {
- this.rkList = rkList;
- }
+ /** 现场照片 URL 列表(多张) */
+ private List photoUrls;
}
diff --git a/src/main/java/com/zg/project/wisdom/domain/dto/StockOutDTO.java b/src/main/java/com/zg/project/wisdom/domain/dto/StockOutDTO.java
index ec39641..7bd5829 100644
--- a/src/main/java/com/zg/project/wisdom/domain/dto/StockOutDTO.java
+++ b/src/main/java/com/zg/project/wisdom/domain/dto/StockOutDTO.java
@@ -39,4 +39,14 @@ public class StockOutDTO {
/** 出库列表 */
private List ckList;
+
+ /** 审核签字图片(发起人签字) */
+ private String signatureUrl;
+
+ /** 审核照片列表(可多张) */
+ private List photoUrls;
+
+ /** 审批人ID(用于记录签字流转) */
+ private String approverId;
+
}
diff --git a/src/main/java/com/zg/project/wisdom/domain/vo/RkSubmitResultVO.java b/src/main/java/com/zg/project/wisdom/domain/vo/RkSubmitResultVO.java
new file mode 100644
index 0000000..e9dfa29
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/domain/vo/RkSubmitResultVO.java
@@ -0,0 +1,25 @@
+package com.zg.project.wisdom.domain.vo;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 入库提交返回 VO
+ * 返回入库单据号、是否需要审核、及托盘信息
+ */
+@Data
+public class RkSubmitResultVO {
+
+ /** 单据号 */
+ private String billNo;
+
+ /** 是否需要审核流程 */
+ private boolean needAudit;
+
+ /** 所有库位码 */
+ private List pcodeList;
+
+ /** 所有托盘码 */
+ private List trayCodeList;
+}
diff --git a/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java b/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java
new file mode 100644
index 0000000..bd6d9ea
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/mapper/AuditSignatureMapper.java
@@ -0,0 +1,89 @@
+package com.zg.project.wisdom.mapper;
+
+import java.util.List;
+import com.zg.project.wisdom.domain.AuditSignature;
+
+/**
+ * 审批记录Mapper接口
+ *
+ * @author zg
+ * @date 2025-07-11
+ */
+public interface AuditSignatureMapper
+{
+ /**
+ * 查询审批记录
+ *
+ * @param id 审批记录主键
+ * @return 审批记录
+ */
+ public AuditSignature selectAuditSignatureById(Long id);
+
+ /**
+ * 查询审批记录列表
+ *
+ * @param auditSignature 审批记录
+ * @return 审批记录集合
+ */
+ public List selectAuditSignatureList(AuditSignature auditSignature);
+
+ /**
+ * 新增审批记录
+ *
+ * @param auditSignature 审批记录
+ * @return 结果
+ */
+ public int insertAuditSignature(AuditSignature auditSignature);
+
+ /**
+ * 修改审批记录
+ *
+ * @param auditSignature 审批记录
+ * @return 结果
+ */
+ public int updateAuditSignature(AuditSignature auditSignature);
+
+ /**
+ * 删除审批记录
+ *
+ * @param id 审批记录主键
+ * @return 结果
+ */
+ public int deleteAuditSignatureById(Long id);
+
+ /**
+ * 批量删除审批记录
+ *
+ * @param ids 需要删除的数据主键集合
+ * @return 结果
+ */
+ public int deleteAuditSignatureByIds(Long[] ids);
+
+ /**
+ * 查询待审批列表
+ * @param userId
+ * @return
+ */
+ List selectPendingByUser(String userId);
+
+ /**
+ * 是否存在提交记录(第一次申请还是驳回后再次申请)
+ * @param
+ * @return
+ */
+ boolean existsCurrentSigner(String billNo, String number);
+
+ /**
+ * 修改当前申请数据的可用状态
+ * @param
+ * @return
+ */
+ void updateIsCurrentToZero(String billNo, String number);
+
+ /**
+ * 新增审核记录
+ * @param
+ * @return
+ */
+ void batchInsert(List recordList);
+}
diff --git a/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java b/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java
index 7c007d3..acccc2d 100644
--- a/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java
+++ b/src/main/java/com/zg/project/wisdom/mapper/RkInfoMapper.java
@@ -1,6 +1,7 @@
package com.zg.project.wisdom.mapper;
import java.util.List;
+import java.util.Map;
import com.zg.project.Inventory.domain.vo.PcdeCntVO;
import com.zg.project.Inventory.domain.vo.RkInfoMatchVO;
@@ -170,4 +171,9 @@ public interface RkInfoMapper
* @return
*/
int insertRkInfo(RkInfo newEntry);
+
+ /**
+ * 修改入库单据状态
+ */
+ int updateStatusByBillNo(RkInfo rkInfo);
}
diff --git a/src/main/java/com/zg/project/wisdom/service/IAuditSignatureService.java b/src/main/java/com/zg/project/wisdom/service/IAuditSignatureService.java
new file mode 100644
index 0000000..48be783
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/service/IAuditSignatureService.java
@@ -0,0 +1,74 @@
+package com.zg.project.wisdom.service;
+
+import java.util.List;
+import com.zg.project.wisdom.domain.AuditSignature;
+
+/**
+ * 审批记录Service接口
+ *
+ * @author zg
+ * @date 2025-07-11
+ */
+public interface IAuditSignatureService
+{
+ /**
+ * 查询审批记录
+ *
+ * @param id 审批记录主键
+ * @return 审批记录
+ */
+ public AuditSignature selectAuditSignatureById(Long id);
+
+ /**
+ * 查询审批记录列表
+ *
+ * @param auditSignature 审批记录
+ * @return 审批记录集合
+ */
+ public List selectAuditSignatureList(AuditSignature auditSignature);
+
+ /**
+ * 新增审批记录
+ *
+ * @param auditSignature 审批记录
+ * @return 结果
+ */
+ public int insertAuditSignature(AuditSignature auditSignature);
+
+ /**
+ * 修改审批记录
+ *
+ * @param auditSignature 审批记录
+ * @return 结果
+ */
+ public int updateAuditSignature(AuditSignature auditSignature);
+
+ /**
+ * 批量删除审批记录
+ *
+ * @param ids 需要删除的审批记录主键集合
+ * @return 结果
+ */
+ public int deleteAuditSignatureByIds(Long[] ids);
+
+ /**
+ * 删除审批记录信息
+ *
+ * @param id 审批记录主键
+ * @return 结果
+ */
+ public int deleteAuditSignatureById(Long id);
+
+ /**
+ * 查询待审核的申请
+ * @param userId
+ * @return
+ */
+ List selectPendingByUser(String userId);
+
+ /**
+ * 审批申请
+ * @param audit
+ */
+ void audit(AuditSignature audit);
+}
diff --git a/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java b/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java
index 3191c10..99ae5f0 100644
--- a/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java
+++ b/src/main/java/com/zg/project/wisdom/service/IRkInfoService.java
@@ -10,6 +10,7 @@ import com.zg.project.wisdom.domain.dto.PcRkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.RefundRequestDTO;
import com.zg.project.wisdom.domain.dto.RkInfoBatchDTO;
import com.zg.project.wisdom.domain.dto.StockOutDTO;
+import com.zg.project.wisdom.domain.vo.RkSubmitResultVO;
/**
* 库存单据主Service接口
@@ -61,11 +62,11 @@ public interface IRkInfoService
public int deleteRkInfoById(Long id);
/**
- * PC新增入库单据
- * @param dto
- * @return
+ * 批量新增入库记录
+ * @param dto 入库数据
+ * @return RkSubmitResultVO 提交结果
*/
- int batchInsert(PcRkInfoBatchDTO dto);
+ void batchInsert(PcRkInfoBatchDTO dto);
/**
* APP新增入库单据
diff --git a/src/main/java/com/zg/project/wisdom/service/impl/AuditSignatureServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/AuditSignatureServiceImpl.java
new file mode 100644
index 0000000..ae0ff02
--- /dev/null
+++ b/src/main/java/com/zg/project/wisdom/service/impl/AuditSignatureServiceImpl.java
@@ -0,0 +1,156 @@
+package com.zg.project.wisdom.service.impl;
+
+import java.util.List;
+
+import com.zg.common.exception.ServiceException;
+import com.zg.common.utils.DateUtils;
+import com.zg.common.utils.SecurityUtils;
+import com.zg.project.wisdom.domain.RkInfo;
+import com.zg.project.wisdom.mapper.RkInfoMapper;
+import org.apache.ibatis.annotations.Param;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import com.zg.project.wisdom.mapper.AuditSignatureMapper;
+import com.zg.project.wisdom.domain.AuditSignature;
+import com.zg.project.wisdom.service.IAuditSignatureService;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * 审批记录Service业务层处理
+ *
+ * @author zg
+ * @date 2025-07-11
+ */
+@Service
+public class AuditSignatureServiceImpl implements IAuditSignatureService
+{
+ @Autowired
+ private AuditSignatureMapper auditSignatureMapper;
+
+ @Autowired
+ private RkInfoMapper rkInfoMapper;
+
+ /**
+ * 查询审批记录
+ *
+ * @param id 审批记录主键
+ * @return 审批记录
+ */
+ @Override
+ public AuditSignature selectAuditSignatureById(Long id)
+ {
+ return auditSignatureMapper.selectAuditSignatureById(id);
+ }
+
+ /**
+ * 查询审批记录列表
+ *
+ * @param auditSignature 审批记录
+ * @return 审批记录
+ */
+ @Override
+ public List selectAuditSignatureList(AuditSignature auditSignature)
+ {
+ return auditSignatureMapper.selectAuditSignatureList(auditSignature);
+ }
+
+ /**
+ * 新增审批记录
+ *
+ * @param auditSignature 审批记录
+ * @return 结果
+ */
+ @Override
+ public int insertAuditSignature(AuditSignature auditSignature)
+ {
+ auditSignature.setCreateTime(DateUtils.getNowDate());
+ return auditSignatureMapper.insertAuditSignature(auditSignature);
+ }
+
+ /**
+ * 修改审批记录
+ *
+ * @param auditSignature 审批记录
+ * @return 结果
+ */
+ @Override
+ public int updateAuditSignature(AuditSignature auditSignature)
+ {
+ auditSignature.setUpdateTime(DateUtils.getNowDate());
+ return auditSignatureMapper.updateAuditSignature(auditSignature);
+ }
+
+ /**
+ * 批量删除审批记录
+ *
+ * @param ids 需要删除的审批记录主键
+ * @return 结果
+ */
+ @Override
+ public int deleteAuditSignatureByIds(Long[] ids)
+ {
+ return auditSignatureMapper.deleteAuditSignatureByIds(ids);
+ }
+
+ /**
+ * 删除审批记录信息
+ *
+ * @param id 审批记录主键
+ * @return 结果
+ */
+ @Override
+ public int deleteAuditSignatureById(Long id)
+ {
+ return auditSignatureMapper.deleteAuditSignatureById(id);
+ }
+
+ /**
+ * 查询待审核的申请
+ * @param userId
+ * @return
+ */
+ @Override
+ public List selectPendingByUser(String userId) {
+ return auditSignatureMapper.selectPendingByUser(userId);
+ }
+
+ @Override
+ @Transactional(rollbackFor = Exception.class)
+ public void audit(AuditSignature audit) {
+ String userId = SecurityUtils.getUserId().toString();
+
+ // 1. 校验记录是否存在
+ AuditSignature db = auditSignatureMapper.selectAuditSignatureById(audit.getId());
+ if (db == null || "1".equals(db.getIsDelete())) {
+ throw new ServiceException("审核记录不存在");
+ }
+
+ // 2. 校验是否已审核
+ if (db.getAuditResult() != null) {
+ throw new ServiceException("该记录已审核,不能重复操作");
+ }
+
+ // 3. 更新审核状态
+ audit.setAuditResult(audit.getAuditResult()); // 必须为 "0"(通过)或 "1"(驳回)
+ audit.setApproverId(userId); // 设置审核人
+ audit.setRemark(audit.getRemark()); // 设置审核意见
+ audit.setUpdateBy(userId);
+ audit.setUpdateTime(DateUtils.getNowDate());
+
+ auditSignatureMapper.updateAuditSignature(audit);
+
+ RkInfo rk = new RkInfo();
+ rk.setBillNo(audit.getBillNo());
+ rk.setUpdateBy(userId);
+ rk.setUpdateTime(DateUtils.getNowDate());
+ if ("0".equals(audit.getAuditResult())) {
+ // 审核通过:rk_info.status = 1(已入库)
+ rk.setStatus("1");
+ } else if ("1".equals(audit.getAuditResult())) {
+ // 审核驳回:rk_info.status = 2(驳回)
+ rk.setStatus("2");
+ }
+ rkInfoMapper.updateStatusByBillNo(rk);
+ }
+
+}
diff --git a/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java b/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java
index 101332f..da80c00 100644
--- a/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java
+++ b/src/main/java/com/zg/project/wisdom/service/impl/RkInfoServiceImpl.java
@@ -2,28 +2,25 @@ package com.zg.project.wisdom.service.impl;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
-import java.time.LocalDateTime;
import java.time.ZoneId;
-import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import com.zg.common.exception.ServiceException;
import com.zg.common.utils.DateUtils;
-import com.zg.common.utils.PageUtils;
import com.zg.common.utils.SecurityUtils;
-import com.zg.framework.web.page.TableDataInfo;
import com.zg.project.Inventory.AutoInventory.mapper.InventoryMatchScanMapper;
import com.zg.project.Inventory.Task.mapper.InventoryTaskMapper;
import com.zg.project.Inventory.domain.dto.QueryDTO;
import com.zg.project.Inventory.domain.entity.InventoryMatchScan;
import com.zg.project.Inventory.domain.vo.ChartDataVO;
import com.zg.project.Inventory.domain.vo.PcdeCntVO;
-import com.zg.project.wisdom.domain.RkBill;
+import com.zg.project.system.service.ISysConfigService;
+import com.zg.project.wisdom.domain.AuditSignature;
import com.zg.project.wisdom.domain.dto.*;
+import com.zg.project.wisdom.mapper.AuditSignatureMapper;
import com.zg.project.wisdom.mapper.GysJhMapper;
-import com.zg.project.wisdom.mapper.RkBillMapper;
import com.zg.project.wisdom.utils.BillNoUtil;
import com.zg.project.wisdom.utils.CodeConvertUtil;
import org.springframework.beans.BeanUtils;
@@ -51,7 +48,7 @@ public class RkInfoServiceImpl implements IRkInfoService
private GysJhMapper gysJhMapper;
@Autowired
- private RkBillMapper rkBillMapper;
+ private AuditSignatureMapper auditSignatureMapper;
@Autowired
private InventoryMatchScanMapper matchScanMapper;
@@ -59,6 +56,9 @@ public class RkInfoServiceImpl implements IRkInfoService
@Autowired
private InventoryTaskMapper taskMapper;
+ @Autowired
+ private ISysConfigService configService;
+
/**
* 查询库存单据主
*
@@ -139,86 +139,97 @@ public class RkInfoServiceImpl implements IRkInfoService
* @return
*/
@Override
- public int batchInsert(PcRkInfoBatchDTO dto) {
- List saveList = new ArrayList<>();
- String username = SecurityUtils.getUsername();
+ @Transactional(rollbackFor = Exception.class)
+ public void batchInsert(PcRkInfoBatchDTO dto) {
+ String billNo = BillNoUtil.generateTodayBillNo("RK");
+ List list = dto.getRkList();
+ List rkInfos = new ArrayList<>();
+
+ boolean needAudit = "1".equals(configService.selectConfigByKey("stock.audit.enabled"));
+ String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
- if (dto.getRkList() == null || dto.getRkList().isEmpty()) {
- throw new ServiceException("rkList 入库明细列表不能为空");
+ for (PcRkInfoItemDTO item : list) {
+ RkInfo rk = new RkInfo();
+ BeanUtils.copyProperties(item, rk);
+ rk.setBillNo(billNo);
+ rk.setRkType(dto.getRkType());
+ rk.setWlType(dto.getWlType());
+ rk.setLihuoY(dto.getLihuoY());
+ rk.setCangku(dto.getCangku());
+ rk.setCreateBy(userId);
+ rk.setCreateTime(now);
+ rk.setIsDelete("0");
+ if (needAudit) {
+ rk.setStatus("0"); // 入库待审核
+ rk.setIsChuku("2"); // 待入库(审核中)
+ } else {
+ rk.setStatus("1"); // 审核通过
+ rk.setIsChuku("0"); // 已入库
+ }
+ rkInfos.add(rk);
}
-// // ✅ 生成统一单据号
- String billNo = BillNoUtil.generateTodayBillNo("RK");
-//
-// // ✅ 插入单据主表
-// RkBill bill = new RkBill();
-// bill.setBillNo(billNo);
-// bill.setRkType(dto.getRkType());
-// bill.setWlType(dto.getWlType());
-// bill.setCangku(dto.getCangku());
-// bill.setRkTime(now);
-// bill.setLihuoY(dto.getLihuoY());
-// bill.setIsChuku("0");
-// bill.setIsDelete("0");
-// bill.setCreateBy(username);
-// bill.setCreateTime(now);
-// rkBillMapper.insertRkBill(bill);
+ rkInfoMapper.batchInsertRkInfo(rkInfos);
- // ✅ 构建明细列表
- for (PcRkInfoItemDTO item : dto.getRkList()) {
- RkInfo entity = new RkInfo();
+ // ====== 写入签字记录(支持重新提交)======
+ if (needAudit) {
+ List records = new ArrayList<>();
- entity.setRkType(dto.getRkType());
- entity.setWlType(dto.getWlType());
- entity.setCangku(dto.getCangku());
- entity.setLihuoY(dto.getLihuoY());
-
- entity.setBillNo(billNo);
-
- entity.setXj(item.getXj());
- entity.setXmNo(item.getXmNo());
- entity.setXmMs(item.getXmMs());
- entity.setSapNo(item.getSapNo());
- entity.setJhQty(item.getJhQty());
- entity.setHtQty(item.getHtQty());
- entity.setJhAmt(item.getJhAmt());
- entity.setHtDj(item.getHtDj());
- entity.setDw(item.getDw());
- entity.setWlNo(item.getWlNo());
- entity.setWlMs(item.getWlMs());
- entity.setGysNo(item.getGysNo());
- entity.setGysMc(item.getGysMc());
-
- entity.setRealQty(item.getRealQty());
- entity.setPcode(item.getPcode());
- if (item.getPcode() != null) {
- entity.setPcodeId(CodeConvertUtil.stringToHex(item.getPcode()));
+ // === 检查是否已有发起人签字记录 ===
+ boolean hasOldSign = auditSignatureMapper.existsCurrentSigner(billNo, "0"); // signerRole = 0 表示发起人
+ if (hasOldSign) {
+ // 将旧记录设为历史
+ auditSignatureMapper.updateIsCurrentToZero(billNo, "0");
}
- entity.setTrayCode(item.getTrayCode());
- entity.setEntityId(item.getEntityId());
- entity.setRemark(item.getRemark());
- // 系统字段
- entity.setIsChuku("0");
- entity.setIsBorrowed("0");
- entity.setIsDelete("0");
- entity.setRkTime(now);
- entity.setCreateBy(username);
- entity.setCreateTime(now);
+ // === 新的主签字记录(发起人 + 审批人) ===
+ AuditSignature mainSign = new AuditSignature();
+ mainSign.setBillNo(billNo); // 单据号
+ mainSign.setBillType("0"); // 单据类型(0:入库)
+ mainSign.setSignerId(userId); // 签字人ID(发起人)
+ mainSign.setSignerRole("0"); // 角色(0:发起人)
+ mainSign.setApproverId(dto.getApproverId()); // 审批人ID
+ mainSign.setSignUrl(dto.getSignatureUrl()); // 发起人签字图片URL
+ mainSign.setImageType("0"); // 图片类型(0:签字)
+ mainSign.setSignTime(now); // 签字时间
+ mainSign.setIsCurrent("1"); // 当前记录
+ mainSign.setIsDelete("0"); // 是否删除
+ mainSign.setCreateBy(userId); // 创建人
+ mainSign.setCreateTime(now); // 创建时间
+ records.add(mainSign);
- saveList.add(entity);
+ // === 现场照片(每张一条记录) ===
+ if (dto.getPhotoUrls() != null && !dto.getPhotoUrls().isEmpty()) {
+ for (String url : dto.getPhotoUrls()) {
+ if (url == null || url.trim().isEmpty()) continue;
- if (item.getGysJhId() != null) {
- gysJhMapper.updateStatusById(item.getGysJhId());
+ AuditSignature photo = new AuditSignature();
+ photo.setBillNo(billNo);
+ photo.setBillType("0");
+ photo.setSignerId(userId);
+ photo.setSignerRole("2"); // 拍照人
+ photo.setImageType("1"); // 现场图片
+ photo.setApproverId(dto.getApproverId());
+ photo.setSignUrl(url);
+ photo.setSignTime(now);
+ photo.setIsCurrent("1");
+ photo.setIsDelete("0");
+ photo.setCreateBy(userId);
+ photo.setCreateTime(now);
+ records.add(photo);
+ }
+ }
+
+ if (!records.isEmpty()) {
+ auditSignatureMapper.batchInsert(records);
+ }
+
+ // ✅ 更新供应计划状态
+ if (dto.getGysJhId() != null) {
+ gysJhMapper.updateStatusById(dto.getGysJhId());
}
}
-
- if (saveList.isEmpty()) {
- throw new ServiceException("未提取到任何可保存的数据");
- }
-
- return rkInfoMapper.batchInsertRkInfo(saveList);
}
@@ -228,97 +239,131 @@ public class RkInfoServiceImpl implements IRkInfoService
* @return
*/
@Override
+ @Transactional(rollbackFor = Exception.class)
public int batchInsertApp(RkInfoBatchDTO dto) {
List saveList = new ArrayList<>();
- String username = SecurityUtils.getUsername();
+ String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
if (dto.getRkList() == null || dto.getRkList().isEmpty()) {
throw new ServiceException("rkList 入库明细列表不能为空");
}
- // ✅ 生成统一的单据号
+ boolean needAudit = "1".equals(configService.selectConfigByKey("stock.audit.enabled"));
String billNo = BillNoUtil.generateTodayBillNo("CK");
- RkBill bill = new RkBill();
- bill.setBillNo(billNo);
- bill.setRkType(dto.getRkType());
- bill.setWlType(dto.getWlType());
- bill.setCangku(dto.getCangku());
- bill.setRkTime(now);
- bill.setLihuoY(dto.getLihuoY());
- bill.setIsChuku("0");
- bill.setIsDelete("0");
- bill.setCreateBy(username);
- bill.setCreateTime(now);
-
- rkBillMapper.insertRkBill(bill);
-
for (RkInfoItemDTO item : dto.getRkList()) {
List scanList = item.getScanList();
- if (scanList == null || scanList.isEmpty()) {
- continue;
- }
+ if (scanList == null || scanList.isEmpty()) continue;
for (RkInfoScanDTO scan : scanList) {
-
RkInfo entity = new RkInfo();
-
- // 批次字段
- entity.setRkType(dto.getRkType());
- entity.setWlType(dto.getWlType());
- entity.setCangku(dto.getCangku());
- entity.setLihuoY(dto.getLihuoY());
-
- entity.setBillNo(billNo);
-
- // 明细字段(RkInfoItemDTO)
- entity.setXj(item.getXj());
- entity.setXmMs(item.getXmMs());
- entity.setXmNo(item.getXmNo());
- entity.setSapNo(item.getSapNo());
- entity.setJhQty(item.getJhQty());
- entity.setHtQty(item.getHtQty());
- entity.setJhAmt(item.getJhAmt());
- entity.setHtDj(item.getHtDj());
- entity.setDw(item.getDw());
- entity.setWlNo(item.getWlNo());
- entity.setWlMs(item.getWlMs());
- entity.setGysNo(item.getGysNo());
- entity.setGysMc(item.getGysMc());
-
- // 扫码记录(RkInfoScanDTO)
- entity.setPcode(scan.getPcode());
- if (scan.getPcode() != null) {
- entity.setPcodeId(CodeConvertUtil.stringToHex(scan.getPcode()));
+ entity.setRkType(dto.getRkType()); // 入库类型
+ entity.setWlType(dto.getWlType()); // 物资类型
+ entity.setCangku(dto.getCangku()); // 所属仓库ID
+ entity.setLihuoY(dto.getLihuoY()); // 理货员
+ entity.setBillNo(billNo); // 单据号(统一生成)
+ entity.setXj(item.getXj()); // 县局
+ entity.setXmMs(item.getXmMs()); // 项目描述
+ entity.setXmNo(item.getXmNo()); // 项目编号
+ entity.setSapNo(item.getSapNo()); // SAP订单编号
+ entity.setJhQty(item.getJhQty()); // 计划交货数量
+ entity.setHtQty(item.getHtQty()); // 合同数量
+ entity.setJhAmt(item.getJhAmt()); // 计划交货金额
+ entity.setHtDj(item.getHtDj()); // 合同单价
+ entity.setDw(item.getDw()); // 计量单位
+ entity.setWlNo(item.getWlNo()); // 物料号
+ entity.setWlMs(item.getWlMs()); // 物料描述
+ entity.setGysNo(item.getGysNo()); // 供应商编号
+ entity.setGysMc(item.getGysMc()); // 供应商名称
+ entity.setPcode(scan.getPcode()); // 库位码(明细)
+ entity.setPcodeId(CodeConvertUtil.stringToHex(scan.getPcode())); // 库位码(16进制编码)
+ entity.setTrayCode(scan.getTrayCode()); // 托盘码
+ entity.setRealQty(scan.getRealQty()); // 实际入库数量
+ entity.setEntityId(scan.getEntityId()); // 实物ID
+ entity.setRemark(scan.getRemark()); // 备注
+ entity.setIsDelete("0"); // 是否删除(0=正常)
+ entity.setIsChuku("0"); // 是否已出库(0=否)
+ if (needAudit) {
+ entity.setStatus("0"); // 入库待审核
+ entity.setIsChuku("3"); // 待入库(审核中)
+ } else {
+ entity.setStatus("1"); // 审核通过
+ entity.setIsChuku("0"); // 已入库
}
- entity.setTrayCode(scan.getTrayCode());
- entity.setRealQty(scan.getRealQty());
- entity.setEntityId(scan.getEntityId());
- entity.setRemark(scan.getRemark());
-
- // 系统字段
- entity.setIsDelete("0");
- entity.setIsChuku("0");
- entity.setRkTime(now);
- entity.setCreateBy(username);
- entity.setCreateTime(now);
+ entity.setRkTime(now); // 入库时间
+ entity.setCreateBy(userId); // 创建人
+ entity.setCreateTime(now); // 创建时间
saveList.add(entity);
}
- // 每个 item 的 供应计划主键ID 更新一次供应计划状态
if (item.getGysJhId() != null) {
- gysJhMapper.updateStatusById(item.getGysJhId());
+ gysJhMapper.updateStatusById(item.getGysJhId()); // 更新供应计划状态
}
-
}
if (saveList.isEmpty()) {
throw new ServiceException("未提取到任何可保存的数据");
}
- return rkInfoMapper.batchInsertRkInfo(saveList);
+ rkInfoMapper.batchInsertRkInfo(saveList); // 批量插入入库数据
+
+ // ✅ 写入签字记录(支持重新提交)
+ if (needAudit) {
+ List recordList = new ArrayList<>();
+
+ // === 判断是否是重新提交 ===
+ boolean isResubmit = auditSignatureMapper.existsCurrentSigner(billNo, "0");
+ if (isResubmit) {
+ auditSignatureMapper.updateIsCurrentToZero(billNo, "0"); // 将旧签字记录置为历史
+ }
+
+ // === 发起人签字记录 ===
+ AuditSignature mainSign = new AuditSignature();
+ mainSign.setBillNo(billNo); // 单据号
+ mainSign.setBillType("0"); // 单据类型:0=入库
+ mainSign.setSignerId(userId); // 签字人ID(当前登录人)
+ mainSign.setSignerRole("0"); // 签字人角色:0=发起人
+ mainSign.setSignUrl(dto.getSignatureUrl()); // 发起人签字图片URL
+ mainSign.setSignTime(now); // 签字时间
+ mainSign.setIsCurrent("1"); // 是否当前记录(1=当前)
+ mainSign.setImageType("0"); // 图片类型:0=签字图
+ mainSign.setApproverId(dto.getApproverId()); // 审批人ID
+ mainSign.setIsDelete("0"); // 是否删除(0=否)
+ mainSign.setCreateBy(userId); // 创建人
+ mainSign.setCreateTime(now); // 创建时间
+ recordList.add(mainSign);
+
+ // === 现场照片记录 ===
+ if (dto.getPhotoUrls() != null) {
+ for (String photoUrl : dto.getPhotoUrls()) {
+ if (photoUrl == null || photoUrl.trim().isEmpty()) continue;
+
+ AuditSignature photo = new AuditSignature();
+ photo.setBillNo(billNo); // 单据号
+ photo.setBillType("0"); // 单据类型:0=入库
+ photo.setSignerId(userId); // 拍照人ID(当前登录人)
+ photo.setSignerRole("2"); // 签字人角色:2=拍照人
+ photo.setSignUrl(photoUrl); // 现场图片URL
+ photo.setImageType("1"); // 图片类型:1=现场图
+ photo.setSignTime(now); // 拍照时间
+ photo.setApproverId(dto.getApproverId()); // 审批人ID
+ photo.setIsCurrent("1"); // 是否当前记录
+ photo.setIsDelete("0"); // 是否删除
+ photo.setCreateBy(userId); // 创建人
+ photo.setCreateTime(now); // 创建时间
+
+ recordList.add(photo);
+ }
+ }
+
+ if (!recordList.isEmpty()) {
+ auditSignatureMapper.batchInsert(recordList); // 批量插入签字记录
+ }
+ }
+
+ return saveList.size();
}
@Transactional
@@ -373,38 +418,105 @@ public class RkInfoServiceImpl implements IRkInfoService
throw new ServiceException("出库数据不能为空");
}
- String username = SecurityUtils.getUsername();
+ String userId = SecurityUtils.getUserId().toString();
Date now = DateUtils.getNowDate();
- // Step 1: 提前生成出库单据号(如 CK202406100001)
+ // Step 1: 判断是否需要审核
+ boolean needAudit = "1".equals(configService.selectConfigByKey("stock.audit.enabled"));
+
+ // Step 2: 生成出库单据号
String billNo = BillNoUtil.generateTodayBillNo("CK");
- // Step 2: 批量更新 rk_info(出库状态 + 单号 + 单据ID)
+ // Step 3: 批量更新 rk_info 出库字段
for (StockOutItemDTO item : dto.getCkList()) {
RkInfo update = new RkInfo();
- update.setId(item.getId());
- update.setBillNoCk(billNo);
- update.setIsChuku("1");
+ update.setId(item.getId()); // 主键ID
+ update.setBillNoCk(billNo); // 出库单号
+ update.setCkType(dto.getCkType()); // 出库类型
+ update.setTeamCode(dto.getTeamCode()); // 施工队编码
+ update.setLyTime(dto.getLyTime()); // 出库时间(领用时间)
+ update.setCkLihuoY(dto.getCkLihuoY()); // 出库理货员
+ update.setCkRemark(item.getCkRemark()); // 出库备注
+ update.setXmNoCk(dto.getXmNoCk()); // 项目编号
+ update.setXmMsCk(dto.getXmMsCk()); // 项目描述
+ update.setUpdateBy(userId); // 修改人
+ update.setUpdateTime(now); // 修改时间
+
if ("JLCK".equals(dto.getCkType())) {
- update.setIsBorrowed("1");
- update.setBorrowTime(dto.getBorrowTime());
- update.setReturnTime(dto.getReturnTime());
+ update.setIsBorrowed("1"); // 是否借料
+ update.setBorrowTime(dto.getBorrowTime()); // 借用时间
+ update.setReturnTime(dto.getReturnTime()); // 归还时间
}
- update.setCkType(dto.getCkType());
- update.setLyTime(dto.getLyTime());
- update.setCkLihuoY(dto.getCkLihuoY());
- update.setTeamCode(dto.getTeamCode());
- update.setCkRemark(item.getCkRemark());
- update.setXmNoCk(dto.getXmNoCk());
- update.setXmMsCk(dto.getXmMsCk());
- update.setUpdateBy(username);
- update.setUpdateTime(now);
+
+ if (needAudit) {
+ update.setStatus("3"); // 出库待审核
+ update.setIsChuku("0"); // 不可直接出库,等待审批
+ } else {
+ update.setIsChuku("1"); // 审核关闭,直接出库
+ update.setStatus("1"); // 设置为审核通过
+ }
+
rkInfoMapper.updateById(update);
}
+ // Step 4: 如果开启审核,写入签字记录
+ if (needAudit) {
+ List recordList = new ArrayList<>();
+
+ // === 判断是否是重新提交(存在发起人记录) ===
+ boolean hasOldSign = auditSignatureMapper.existsCurrentSigner(billNo, "0");
+
+ if (hasOldSign) {
+ auditSignatureMapper.updateIsCurrentToZero(billNo, "0"); // 标记旧记录为历史
+ }
+
+ // === 发起人签字记录 ===
+ AuditSignature sign = new AuditSignature();
+ sign.setBillNo(billNo); // 单据号(出库单号)
+ sign.setBillType("1"); // 单据类型:1=出库
+ sign.setSignerId(userId); // 签字人ID(发起人)
+ sign.setSignerRole("0"); // 角色:0=发起人
+ sign.setSignUrl(dto.getSignatureUrl()); // 签字图 URL
+ sign.setSignTime(now); // 签字时间
+ sign.setImageType("0"); // 图片类型:0=签字图
+ sign.setApproverId(dto.getApproverId()); // 审批人ID
+ sign.setIsCurrent("1"); // 当前记录
+ sign.setIsDelete("0"); // 未删除
+ sign.setCreateBy(userId); // 创建人
+ sign.setCreateTime(now); // 创建时间
+ recordList.add(sign);
+
+ // === 多张现场照片记录 ===
+ if (dto.getPhotoUrls() != null) {
+ for (String url : dto.getPhotoUrls()) {
+ if (url == null || url.trim().isEmpty()) continue;
+
+ AuditSignature photo = new AuditSignature();
+ photo.setBillNo(billNo); // 单据号
+ photo.setBillType("1"); // 出库
+ photo.setSignerId(userId); // 拍照人
+ photo.setSignerRole("2"); // 角色:2=拍照人
+ photo.setSignUrl(url); // 照片URL
+ photo.setImageType("1"); // 图片类型:1=照片
+ photo.setSignTime(now); // 拍照时间
+ photo.setApproverId(dto.getApproverId()); // 审批人ID
+ photo.setIsCurrent("1"); // 当前记录
+ photo.setIsDelete("0"); // 未删除
+ photo.setCreateBy(userId); // 创建人
+ photo.setCreateTime(now); // 创建时间
+ recordList.add(photo);
+ }
+ }
+
+ if (!recordList.isEmpty()) {
+ auditSignatureMapper.batchInsert(recordList); // 批量插入签字记录
+ }
+ }
+
return dto.getCkList().size();
}
+
@Override
public void matchWithStatus(QueryDTO dto) {
List pcdeIds = dto.getIds();
diff --git a/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml b/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml
new file mode 100644
index 0000000..87abcc0
--- /dev/null
+++ b/src/main/resources/mybatis/wisdom/AuditSignatureMapper.xml
@@ -0,0 +1,206 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ select id, bill_no, bill_type, signer_id, signer_role, sign_url, sign_time, pcode, tray_code, approver_id, approver_sign_url, audit_result, image_type, is_current, remark, create_by, create_time, update_by, update_time, is_delete from audit_signature
+
+
+
+
+
+
+
+
+
+
+
+ insert into audit_signature
+
+ bill_no,
+ bill_type,
+ signer_id,
+ signer_role,
+ sign_url,
+ sign_time,
+ pcode,
+ tray_code,
+ approver_id,
+ approver_sign_url,
+ audit_result,
+ image_type,
+ is_current,
+ remark,
+ create_by,
+ create_time,
+ update_by,
+ update_time,
+ is_delete,
+
+
+ #{billNo},
+ #{billType},
+ #{signerId},
+ #{signerRole},
+ #{signUrl},
+ #{signTime},
+ #{pcode},
+ #{trayCode},
+ #{approverId},
+ #{approverSignUrl},
+ #{auditResult},
+ #{imageType},
+ #{isCurrent},
+ #{remark},
+ #{createBy},
+ #{createTime},
+ #{updateBy},
+ #{updateTime},
+ #{isDelete},
+
+
+
+
+ INSERT INTO audit_signature (
+ bill_no,
+ bill_type,
+ signer_id,
+ signer_role,
+ sign_url,
+ sign_time,
+ image_type,
+ approver_id,
+ is_current,
+ is_delete,
+ create_by,
+ create_time
+ )
+ VALUES
+
+ (
+ #{item.billNo},
+ #{item.billType},
+ #{item.signerId},
+ #{item.signerRole},
+ #{item.signUrl},
+ #{item.signTime},
+ #{item.imageType},
+ #{item.approverId},
+ #{item.isCurrent},
+ #{item.isDelete},
+ #{item.createBy},
+ #{item.createTime}
+ )
+
+
+
+
+ update audit_signature
+
+ bill_no = #{billNo},
+ bill_type = #{billType},
+ signer_id = #{signerId},
+ signer_role = #{signerRole},
+ sign_url = #{signUrl},
+ sign_time = #{signTime},
+ pcode = #{pcode},
+ tray_code = #{trayCode},
+ approver_id = #{approverId},
+ approver_sign_url = #{approverSignUrl},
+ audit_result = #{auditResult},
+ image_type = #{imageType},
+ is_current = #{isCurrent},
+ remark = #{remark},
+ create_by = #{createBy},
+ create_time = #{createTime},
+ update_by = #{updateBy},
+ update_time = #{updateTime},
+ is_delete = #{isDelete},
+
+ where id = #{id}
+
+
+
+ UPDATE audit_signature
+ SET is_current = '0',
+ update_time = NOW()
+ WHERE bill_no = #{billNo}
+ AND signer_role = #{signerRole}
+ AND is_current = '1'
+ AND is_delete = '0'
+
+
+
+ delete from audit_signature where id = #{id}
+
+
+
+ delete from audit_signature where id in
+
+ #{id}
+
+
+
\ No newline at end of file
diff --git a/src/main/resources/mybatis/wisdom/RkInfoMapper.xml b/src/main/resources/mybatis/wisdom/RkInfoMapper.xml
index 716ff39..1fcf986 100644
--- a/src/main/resources/mybatis/wisdom/RkInfoMapper.xml
+++ b/src/main/resources/mybatis/wisdom/RkInfoMapper.xml
@@ -93,7 +93,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
jh_qty, ht_qty, jh_amt, ht_dj, dw,
borrow_time, return_time,
pcode, pcode_id, tray_code, real_qty, entity_id,
- remark, is_chuku,is_borrowed, is_delete, create_by, create_time
+ remark, is_chuku,is_borrowed,
+ is_delete, create_by, create_time
)
VALUES
@@ -105,7 +106,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
#{item.jhQty}, #{item.htQty}, #{item.jhAmt}, #{item.htDj}, #{item.dw},
#{item.borrowTime}, #{item.returnTime},
#{item.pcode}, #{item.pcodeId}, #{item.trayCode}, #{item.realQty}, #{item.entityId},
- #{item.remark}, #{item.isChuku}, #{item.isBorrowed},#{item.isDelete}, #{item.createBy}, #{item.createTime}
+ #{item.remark}, #{item.isChuku}, #{item.isBorrowed},
+ #{item.isDelete}, #{item.createBy}, #{item.createTime}
)
@@ -264,9 +266,9 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
SELECT
ri.id, ri.rk_type, ri.wl_type, ri.cangku, ri.rk_time, ri.lihuo_y,
ri.is_chuku, ri.bill_no, ri.bill_no_ck,
- ri.remark, ri.xj, ri.xm_no, ri.xm_ms, ri.wl_no, ri.wl_ms,ri.is_borrowed,
+ ri.remark, ri.xj, ri.xm_no, ri.xm_ms, ri.wl_no, ri.wl_ms, ri.is_borrowed,
ri.gys_no, ri.gys_mc, ri.jh_amt, ri.ht_dj, ri.sap_no, ri.xh,
- ri.jh_qty, ri.ht_qty, ri.dw, ri.real_qty,ri.borrow_time, ri.return_time,
+ ri.jh_qty, ri.ht_qty, ri.dw, ri.real_qty, ri.borrow_time, ri.return_time,
ri.pcode, ri.pcode_id, ri.tray_code, ri.entity_id,
ri.ck_lihuo_y, ri.ck_type, ri.team_code, ri.ly_time, ri.ck_remark,
ri.create_by, ri.create_time, ri.update_by, ri.update_time, ri.is_delete
@@ -282,7 +284,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
SELECT
id, rk_type, wl_type, cangku, rk_time, lihuo_y,
is_chuku, bill_no, bill_no_ck,
- remark, xj, xm_no, xm_ms, wl_no, wl_ms,is_borrowed,
+ remark, xj, xm_no, xm_ms, wl_no, wl_ms, is_borrowed,
gys_no, gys_mc, jh_amt, ht_dj, sap_no, xh,
jh_qty, ht_qty, dw, real_qty,
pcode, pcode_id, tray_code, entity_id,
@@ -422,4 +424,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
WHERE id = #{id}
+
+ UPDATE rk_info
+ SET status = #{status},
+ update_by = #{updateBy},
+ update_time = #{updateTime}
+ WHERE bill_no = #{billNo}
+ AND is_delete = '0'
+
+
\ No newline at end of file