Browse Source

2026-03-04

part表增加触发器并且增加记录表,用来记录std_order_qty、estimated_material_cost字段的变化
master
fengyuan_yang 21 hours ago
parent
commit
eacf1ad6da
  1. 16
      src/main/java/com/spring/modules/part/controller/PartInformationController.java
  2. 55
      src/main/java/com/spring/modules/part/entity/PartFieldChangeLogEntity.java
  3. 30
      src/main/java/com/spring/modules/part/mapper/PartFieldChangeLogMapper.java
  4. 8
      src/main/java/com/spring/modules/part/service/PartInformationService.java
  5. 34
      src/main/java/com/spring/modules/part/service/impl/PartInformationServiceImpl.java
  6. 46
      src/main/resources/mapper/part/PartFieldChangeLogMapper.xml

16
src/main/java/com/spring/modules/part/controller/PartInformationController.java

@ -842,4 +842,20 @@ public class PartInformationController {
partInformationService.deleteProjectPart(data);
return R.ok();
}
/**
* 查询物料关键字段std_order_qty / estimated_material_cost变更日志
*
* @param site 工厂必填
* @param partNo 物料编码必填
* @param fieldName 字段名可选std_order_qty / estimated_material_cost不传则查全部
*/
@GetMapping("fieldChangeLog")
@ResponseBody
public R fieldChangeLog(
@RequestParam String site,
@RequestParam String partNo,
@RequestParam(required = false, defaultValue = "") String fieldName) {
return R.ok().put("rows", partInformationService.queryFieldChangeLog(site, partNo, fieldName));
}
}

55
src/main/java/com/spring/modules/part/entity/PartFieldChangeLogEntity.java

@ -0,0 +1,55 @@
package com.spring.modules.part.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import java.io.Serializable;
import java.math.BigDecimal;
import java.util.Date;
/**
* 物料关键字段变更日志
* 追踪 std_order_qty estimated_material_cost 的每次变更
*/
@Data
@TableName("part_field_change_log")
public class PartFieldChangeLogEntity implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(type = IdType.AUTO)
private Long id;
/** 工厂 */
private String site;
/** 物料编码 */
private String partNo;
/** 变更字段名:std_order_qty 或 estimated_material_cost */
private String fieldName;
/** 变更前的值 */
private BigDecimal oldValue;
/** 变更后的值 */
private BigDecimal newValue;
/** 变更时间 */
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date changeTime;
/** 数据库连接账号(触发器记录,可辨别是否来自存储过程/应用) */
private String dbUser;
/** 连接来源程序名(如 Microsoft JDBC Driver for SQL Server) */
private String appName;
/** 发起变更的主机名 */
private String hostName;
/** 备注(Java 层补充写入操作人、操作类型等) */
private String remark;
}

30
src/main/java/com/spring/modules/part/mapper/PartFieldChangeLogMapper.java

@ -0,0 +1,30 @@
package com.spring.modules.part.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.spring.modules.part.entity.PartFieldChangeLogEntity;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface PartFieldChangeLogMapper extends BaseMapper<PartFieldChangeLogEntity> {
/**
* 查询指定物料的字段变更记录
*/
List<PartFieldChangeLogEntity> queryChangeLog(
@Param("site") String site,
@Param("partNo") String partNo,
@Param("fieldName") String fieldName);
/**
* 更新最近一条日志的 db_userPLM 操作人 remark
*/
void updateLastLogUser(
@Param("site") String site,
@Param("partNo") String partNo,
@Param("fieldName") String fieldName,
@Param("operator") String operator,
@Param("remark") String remark);
}

8
src/main/java/com/spring/modules/part/service/PartInformationService.java

@ -173,4 +173,12 @@ public interface PartInformationService {
PageUtils readPartFromFile(MultipartFile file, GetParamInData data, String searchType, String partNos);
void copyPart2(PartInformationVo data);
/**
* 查询物料关键字段变更日志std_order_qty / estimated_material_cost
* @param site 工厂
* @param partNo 物料编码
* @param fieldName 字段名传空字符串则查两个字段
*/
List<PartFieldChangeLogEntity> queryFieldChangeLog(String site, String partNo, String fieldName);
}

34
src/main/java/com/spring/modules/part/service/impl/PartInformationServiceImpl.java

@ -187,6 +187,9 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
@Autowired
private TestInformationMapper testInformationMapper;
@Autowired
private PartFieldChangeLogMapper partFieldChangeLogMapper;
@Autowired
private ProjectToolingApplyMapper projectToolingApplyMapper;
@ -909,6 +912,7 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
updateInformationWrapper.eq("site", data.getSite());
updateInformationWrapper.eq("part_no", data.getPartNo());
partInformationMapper.update(data, updateInformationWrapper);
recordChangeRemark(data.getSite(), data.getPartNo(), data.getUpdateBy(), "用户编辑物料");
if (dataUrl) {
// 判断是否为正式物料
@ -1225,6 +1229,7 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
updateInformationWrapper.eq("site", data.getSite());
updateInformationWrapper.eq("part_no", data.getPartNo());
partInformationMapper.update(data, updateInformationWrapper);
recordChangeRemark(data.getSite(), data.getPartNo(), data.getUpdateBy(), "用户编辑物料(项目页面)");
// 判断是否需要修改项目物料的BU
if (StringUtils.hasText(data.getBuNo())) {
partInformationMapper.updateProjectPartBuNo(data);
@ -2841,6 +2846,7 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
updateInformationWrapper.eq("site", data.getSite());
updateInformationWrapper.eq("part_no", data.getPartNo());
partInformationMapper.update(data, updateInformationWrapper);
recordChangeRemark(data.getSite(), data.getPartNo(), data.getUpdateBy(), "转正式物料");
// 物料属性
PartSubPropertiesValueData valueData = new PartSubPropertiesValueData();
valueData.setSite(data.getSite());
@ -4937,6 +4943,34 @@ public class PartInformationServiceImpl extends ServiceImpl<PartInformationMappe
return formatter.formatCellValue(cell);
}
/**
* 查询物料关键字段变更日志
* @param site 工厂
* @param partNo 物料编码
* @param fieldName 字段名传空则查两个字段
*/
@Override
public List<PartFieldChangeLogEntity> queryFieldChangeLog(String site, String partNo, String fieldName) {
return partFieldChangeLogMapper.queryChangeLog(site, partNo, fieldName);
}
/**
* 触发器写入日志后立即回填 PLM 操作人到 db_user并写入 remark
* db_user 格式"{username}|PLM|"加标记方便与 DB 账号区分
* 使用 try-catch 保证不影响主流程
*/
private void recordChangeRemark(String site, String partNo, String operator, String operationType) {
try {
String user = (operator == null ? "unknown" : operator);
String dbUser = user + "|PLM|";
String remark = operationType;
partFieldChangeLogMapper.updateLastLogUser(site, partNo, "std_order_qty", dbUser, remark);
partFieldChangeLogMapper.updateLastLogUser(site, partNo, "estimated_material_cost", dbUser, remark);
} catch (Exception e) {
log.warn("recordChangeRemark 写入失败,site={}, partNo={}, msg={}", site, partNo, e.getMessage());
}
}
}

46
src/main/resources/mapper/part/PartFieldChangeLogMapper.xml

@ -0,0 +1,46 @@
<?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.spring.modules.part.mapper.PartFieldChangeLogMapper">
<!-- 查询指定物料的字段变更记录 -->
<select id="queryChangeLog" resultType="com.spring.modules.part.entity.PartFieldChangeLogEntity">
SELECT
id,
site,
part_no AS partNo,
field_name AS fieldName,
old_value AS oldValue,
new_value AS newValue,
change_time AS changeTime,
db_user AS dbUser,
app_name AS appName,
host_name AS hostName,
remark
FROM part_field_change_log
WHERE site = #{site}
AND part_no = #{partNo}
<if test="fieldName != null and fieldName != ''">
AND field_name = #{fieldName}
</if>
ORDER BY change_time DESC
</select>
<!-- 触发器写入后,Java 层立即回填 PLM 操作人到 db_user,并补充 remark -->
<update id="updateLastLogUser">
UPDATE part_field_change_log
SET db_user = #{operator},
remark = #{remark}
WHERE id = (
SELECT TOP 1 id
FROM part_field_change_log
WHERE site = #{site}
AND part_no = #{partNo}
AND field_name = #{fieldName}
AND db_user NOT LIKE '%|PLM|%'
ORDER BY change_time DESC
)
</update>
</mapper>
Loading…
Cancel
Save