Browse Source

feat(quality): 新增质量反馈模块完整功能

- 创建QualityIssue实体类定义质量问题相关字段
- 实现QualityIssueController控制器提供CRUD接口
- 添加质量反馈保存、更新、删除和关闭功能
- 实现质量问题与采购订单绑定功能
- 添加可用采购订单查询和关联操作
- 集成供应商信息查询和事务号管理
- 实现分页查询和批量操作功能
- 添加完整的数据传输对象DTO定义
- 配置MyBatis映射文件和数据库操作
- 实现事务管理和异常处理机制
master
qiankanghui 4 months ago
parent
commit
25dc4c3732
  1. 30
      src/main/java/com/xujie/modules/quality/controller/QualityIssueController.java
  2. 15
      src/main/java/com/xujie/modules/quality/data/QualityIssueBindPoDto.java
  3. 26
      src/main/java/com/xujie/modules/quality/data/QualityIssuePoSelectDto.java
  4. 19
      src/main/java/com/xujie/modules/quality/data/QualityIssueSavePoDto.java
  5. 46
      src/main/java/com/xujie/modules/quality/data/QueryPoDto.java
  6. 3
      src/main/java/com/xujie/modules/quality/entity/QualityIssue.java
  7. 32
      src/main/java/com/xujie/modules/quality/entity/SrmQualityIssuePo.java
  8. 43
      src/main/java/com/xujie/modules/quality/mapper/SrmQualityIssuePoMapper.java
  9. 14
      src/main/java/com/xujie/modules/quality/service/QualityIssueService.java
  10. 110
      src/main/java/com/xujie/modules/quality/service/impl/QualityIssueServiceImpl.java
  11. 103
      src/main/resources/mapper/quality/SrmQualityIssuePoMapper.xml

30
src/main/java/com/xujie/modules/quality/controller/QualityIssueController.java

@ -2,9 +2,13 @@ package com.xujie.modules.quality.controller;
import com.xujie.common.utils.PageUtils;
import com.xujie.common.utils.R;
import com.xujie.modules.quality.data.QualityIssueBindPoDto;
import com.xujie.modules.quality.data.QualityIssuePoSelectDto;
import com.xujie.modules.quality.data.QueryPoDto;
import com.xujie.modules.quality.entity.QualityIssue;
import com.xujie.modules.quality.entity.QualityIssueClaim;
import com.xujie.modules.quality.entity.QualityIssueReply;
import com.xujie.modules.quality.entity.SrmQualityIssuePo;
import com.xujie.modules.quality.service.QualityIssueClaimService;
import com.xujie.modules.quality.service.QualityIssueReplyService;
import com.xujie.modules.quality.service.QualityIssueService;
@ -15,6 +19,8 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/srm/qualityIssue")
public class QualityIssueController {
@ -75,4 +81,28 @@ public class QualityIssueController {
return R.ok();
}
@PostMapping("/bindIssuePo")
public R bindIssuePo(@RequestBody QualityIssueBindPoDto dto){
qualityIssueService.bindIssuePo(dto);
return R.ok();
}
@PostMapping("/getAvailablePoList")
public R getAvailablePoList(@RequestBody QueryPoDto dto){
PageUtils page = qualityIssueService.getAvailablePoList(dto);
return R.ok().put("page", page);
}
@PostMapping("/getIssuePoList")
public R getIssuePoList(@RequestBody QualityIssue qualityIssue){
List<SrmQualityIssuePo> list = qualityIssueService.getIssuePoList(qualityIssue.getSite(), qualityIssue.getIssueNo());
return R.ok().put("data", list);
}
@PostMapping("/deleteIssuePo")
public R deleteIssuePo(@RequestBody QualityIssue qualityIssue){
qualityIssueService.deleteIssuePo(qualityIssue.getSite(), qualityIssue.getIssueNo(), qualityIssue.getPoNo(), qualityIssue.getItemNo());
return R.ok();
}
}

15
src/main/java/com/xujie/modules/quality/data/QualityIssueBindPoDto.java

@ -0,0 +1,15 @@
package com.xujie.modules.quality.data;
import lombok.Data;
import java.util.List;
@Data
public class QualityIssueBindPoDto {
private String site;
private String issueNo;
private List<QualityIssueSavePoDto> poList;
}

26
src/main/java/com/xujie/modules/quality/data/QualityIssuePoSelectDto.java

@ -0,0 +1,26 @@
package com.xujie.modules.quality.data;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class QualityIssuePoSelectDto {
private String site;
private String poNo;
private Integer itemNo;
private String partNo;
private String sku;
private Date poDate;
private BigDecimal qty;
private BigDecimal shippedQty;
}

19
src/main/java/com/xujie/modules/quality/data/QualityIssueSavePoDto.java

@ -0,0 +1,19 @@
package com.xujie.modules.quality.data;
import lombok.Data;
import java.math.BigDecimal;
@Data
public class QualityIssueSavePoDto {
private String poNo;
private Integer itemNo;
private String partNo;
private BigDecimal qty;
private BigDecimal shippedQty;
}

46
src/main/java/com/xujie/modules/quality/data/QueryPoDto.java

@ -0,0 +1,46 @@
package com.xujie.modules.quality.data;
import lombok.Data;
import java.util.Date;
@Data
public class QueryPoDto {
/**
* 站点
*/
private String site;
/**
* 供应商编号
*/
private String supplierNo;
/**
* PO号
*/
private String poNo;
/**
* 料号
*/
private String partNo;
/**
* 开始日期
*/
private Date beginDate;
/**
* 结束日期
*/
private Date endDate;
/**
* 分页
*/
private Integer pageIndex = 1;
private Integer pageSize = 20;
}

3
src/main/java/com/xujie/modules/quality/entity/QualityIssue.java

@ -86,6 +86,9 @@ public class QualityIssue extends QueryPage {
private String poNo;
@TableField(exist = false)
private Integer itemNo;
private BigDecimal batchQty;
private BigDecimal rejectBatchQty;

32
src/main/java/com/xujie/modules/quality/entity/SrmQualityIssuePo.java

@ -0,0 +1,32 @@
package com.xujie.modules.quality.entity;
import com.baomidou.mybatisplus.annotation.TableField;
import lombok.Data;
import java.math.BigDecimal;
import java.util.Date;
@Data
public class SrmQualityIssuePo {
private String site;
private String issueNo;
private String poNo;
private Integer itemNo;
private String partNo;
@TableField(exist = false)
private String sku;
private BigDecimal poQty;
private BigDecimal shippedQty;
private String createBy;
private Date createDate;
}

43
src/main/java/com/xujie/modules/quality/mapper/SrmQualityIssuePoMapper.java

@ -0,0 +1,43 @@
package com.xujie.modules.quality.mapper;
import com.xujie.modules.quality.data.QualityIssuePoSelectDto;
import com.xujie.modules.quality.entity.SrmQualityIssuePo;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
@Mapper
public interface SrmQualityIssuePoMapper {
List<QualityIssuePoSelectDto> getAvailablePoList(
@Param("site") String site,
@Param("supplierNo") String supplierNo,
@Param("poNo") String poNo,
@Param("partNo") String partNo,
@Param("beginDate") Date beginDate,
@Param("endDate") Date endDate
);
int deleteByIssueNo(
@Param("site") String site,
@Param("issueNo") String issueNo
);
int batchInsert(
@Param("list") List<SrmQualityIssuePo> list
);
List<SrmQualityIssuePo> getIssuePoList(
@Param("site") String site,
@Param("issueNo") String issueNo
);
int deleteByPoNo(
@Param("site") String site,
@Param("issueNo") String issueNo,
@Param("poNo") String poNo,
@Param("itemNo") Integer itemNo
);
}

14
src/main/java/com/xujie/modules/quality/service/QualityIssueService.java

@ -2,7 +2,13 @@ package com.xujie.modules.quality.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.xujie.common.utils.PageUtils;
import com.xujie.modules.quality.data.QualityIssueBindPoDto;
import com.xujie.modules.quality.data.QualityIssuePoSelectDto;
import com.xujie.modules.quality.data.QueryPoDto;
import com.xujie.modules.quality.entity.QualityIssue;
import com.xujie.modules.quality.entity.SrmQualityIssuePo;
import java.util.List;
public interface QualityIssueService extends IService<QualityIssue> {
@ -16,4 +22,12 @@ public interface QualityIssueService extends IService<QualityIssue> {
void updateByIssueNo(QualityIssue qualityIssue);
void closeIssue(QualityIssue qualityIssue);
void bindIssuePo(QualityIssueBindPoDto dto);
PageUtils getAvailablePoList(QueryPoDto dto);
List<SrmQualityIssuePo> getIssuePoList(String site, String issueNo);
void deleteIssuePo(String site, String issueNo, String poNo, Integer itemNo);
}

110
src/main/java/com/xujie/modules/quality/service/impl/QualityIssueServiceImpl.java

@ -2,21 +2,32 @@ package com.xujie.modules.quality.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xujie.common.utils.PageUtils;
import com.xujie.common.utils.ShiroUtils;
import com.xujie.modules.quality.data.QualityIssueBindPoDto;
import com.xujie.modules.quality.data.QualityIssuePoSelectDto;
import com.xujie.modules.quality.data.QualityIssueSavePoDto;
import com.xujie.modules.quality.data.QueryPoDto;
import com.xujie.modules.quality.entity.QualityIssue;
import com.xujie.modules.quality.entity.SrmQualityIssuePo;
import com.xujie.modules.quality.mapper.QualityIssueMapper;
import com.xujie.modules.quality.mapper.SrmQualityIssuePoMapper;
import com.xujie.modules.quality.service.QualityIssueService;
import com.xujie.modules.srm.mapper.SrmSupplierMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@Slf4j
@Service
public class QualityIssueServiceImpl extends ServiceImpl<QualityIssueMapper, QualityIssue> implements QualityIssueService {
@Autowired
@ -24,6 +35,8 @@ public class QualityIssueServiceImpl extends ServiceImpl<QualityIssueMapper, Qua
@Autowired
private SrmSupplierMapper srmSupplierMapper;
@Autowired
private SrmQualityIssuePoMapper qualityIssuePoMapper;
@Override
public PageUtils queryPage(QualityIssue qualityIssue) {
@ -126,4 +139,101 @@ public class QualityIssueServiceImpl extends ServiceImpl<QualityIssueMapper, Qua
throw new RuntimeException("关闭失败,质量问题不存在");
}
}
@Transactional(rollbackFor = Exception.class)
@Override
public void bindIssuePo(QualityIssueBindPoDto dto) {
log.info("开始保存PO关联数据: site={}, issueNo={}, poListSize={}",
dto.getSite(), dto.getIssueNo(),
dto.getPoList() != null ? dto.getPoList().size() : 0);
// 参数校验
if (dto.getSite() == null || dto.getSite().trim().isEmpty()) {
throw new RuntimeException("站点(site)不能为空");
}
if (dto.getIssueNo() == null || dto.getIssueNo().trim().isEmpty()) {
throw new RuntimeException("问题单号(issueNo)不能为空");
}
if (CollectionUtils.isEmpty(dto.getPoList())) {
throw new RuntimeException("PO列表不能为空");
}
// 获取当前登录用户的用户名(如:admin)
String userName = ShiroUtils.getUserEntity().getUsername();
log.info("当前用户: {}", userName);
// 限制用户名长度,防止超过数据库字段长度
if (userName != null && userName.length() > 100) {
userName = userName.substring(0, 100);
}
// 先删除旧的关联数据
qualityIssuePoMapper.deleteByIssueNo(dto.getSite(), dto.getIssueNo());
List<SrmQualityIssuePo> list = new ArrayList<>();
for (int i = 0; i < dto.getPoList().size(); i++) {
QualityIssueSavePoDto item = dto.getPoList().get(i);
log.info("处理第{}条PO: poNo={}, itemNo={}, partNo={}, qty={}, shippedQty={}",
i + 1, item.getPoNo(), item.getItemNo(), item.getPartNo(),
item.getQty(), item.getShippedQty());
SrmQualityIssuePo po = new SrmQualityIssuePo();
po.setSite(dto.getSite());
po.setIssueNo(dto.getIssueNo());
po.setPoNo(item.getPoNo());
po.setItemNo(item.getItemNo());
// 限制partNo长度
if (item.getPartNo() != null && item.getPartNo().length() > 100) {
po.setPartNo(item.getPartNo().substring(0, 100));
} else {
po.setPartNo(item.getPartNo());
}
po.setPoQty(item.getQty());
po.setShippedQty(item.getShippedQty()); // 设置已发货数量
po.setCreateBy(userName);
list.add(po);
}
log.info("准备插入{}条PO关联记录", list.size());
qualityIssuePoMapper.batchInsert(list);
log.info("PO关联数据保存成功");
}
@Override
public PageUtils getAvailablePoList(QueryPoDto dto) {
IPage<QualityIssuePoSelectDto> page =
new Page<>(
dto.getPageIndex(),
dto.getPageSize()
);
page.setRecords(
qualityIssuePoMapper.getAvailablePoList(
dto.getSite(),
dto.getSupplierNo(),
dto.getPoNo(),
dto.getPartNo(),
dto.getBeginDate(),
dto.getEndDate()
)
);
return new PageUtils(page);
}
@Override
public List<SrmQualityIssuePo> getIssuePoList(String site, String issueNo) {
return qualityIssuePoMapper.getIssuePoList(site, issueNo);
}
@Override
@Transactional(rollbackFor = Exception.class)
public void deleteIssuePo(String site, String issueNo, String poNo, Integer itemNo) {
int result = qualityIssuePoMapper.deleteByPoNo(site, issueNo, poNo, itemNo);
if (result == 0) {
throw new RuntimeException("删除失败,PO记录不存在");
}
}
}

103
src/main/resources/mapper/quality/SrmQualityIssuePoMapper.xml

@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.xujie.modules.quality.mapper.SrmQualityIssuePoMapper">
<select id="getAvailablePoList" resultType="com.xujie.modules.quality.data.QualityIssuePoSelectDto">
SELECT
p.site,
p.order_ref1 as poNo,
p.item_no as itemNo,
p.part_no as partNo,
pt.sku as sku,
h.order_date as poDate,
p.qty,
p.shipped_qty as shippedQty
FROM PODetail p
LEFT JOIN POHeader h
ON p.site = h.site
AND p.order_no = h.order_no
LEFT JOIN part pt
ON p.part_no = pt.part_no
WHERE p.site = #{site}
AND ISNULL(p.shipped_qty, 0) > 0
<if test="supplierNo != null and supplierNo != ''">
AND h.supplier_no = #{supplierNo}
</if>
<if test="poNo != null and poNo != ''">
AND p.order_ref1 LIKE '%' + #{poNo} + '%'
</if>
<if test="partNo != null and partNo != ''">
AND p.part_no LIKE '%' + #{partNo} + '%'
</if>
<if test="beginDate != null">
AND h.order_date &gt;= #{beginDate}
</if>
<if test="endDate != null">
AND h.order_date &lt;= #{endDate}
</if>
ORDER BY h.order_date DESC
</select>
<!-- 其他方法保持不变 -->
<delete id="deleteByIssueNo">
DELETE FROM srm_quality_issue_po
WHERE site = #{site}
AND issue_no = #{issueNo}
</delete>
<insert id="batchInsert">
INSERT INTO srm_quality_issue_po
(
site,
issue_no,
po_no,
item_no,
part_no,
po_qty,
shipped_qty,
create_by,
create_date
)
VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.site},
#{item.issueNo},
#{item.poNo},
#{item.itemNo},
#{item.partNo},
#{item.poQty},
#{item.shippedQty},
#{item.createBy},
GETDATE()
)
</foreach>
</insert>
<select id="getIssuePoList" resultType="com.xujie.modules.quality.entity.SrmQualityIssuePo">
SELECT
qip.site,
qip.issue_no,
qip.po_no,
qip.item_no,
qip.part_no,
pt.sku,
qip.po_qty,
qip.shipped_qty,
qip.create_by,
qip.create_date
FROM srm_quality_issue_po qip
LEFT JOIN part pt
ON qip.part_no = pt.part_no
WHERE qip.site = #{site}
AND qip.issue_no = #{issueNo}
</select>
<delete id="deleteByPoNo">
DELETE FROM srm_quality_issue_po
WHERE site = #{site}
AND issue_no = #{issueNo}
AND po_no = #{poNo}
AND item_no = #{itemNo}
</delete>
</mapper>
Loading…
Cancel
Save