|
|
@@ -0,0 +1,141 @@
|
|
|
+package com.jeesite.modules.mes.service;
|
|
|
+
|
|
|
+import com.jeesite.common.service.ServiceException;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.jdbc.core.JdbcTemplate;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
+
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
+import java.util.Calendar;
|
|
|
+import java.util.Date;
|
|
|
+import java.util.HashMap;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.UUID;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 镭雕客户编码生成与绑定Service
|
|
|
+ * 客户编码规则(21位):
|
|
|
+ * + 项目前缀(4位,T09=KB60/T68=KB87) + IS3031(6位固定)
|
|
|
+ * + 年份字母(1位) + 月份代码(1位) + 日期(2位)
|
|
|
+ * + 当日流水号(4位,从0001开始每日归零) + 01(2位固定原材料追溯码)
|
|
|
+ * @author hzd
|
|
|
+ * @version 2026-07-08
|
|
|
+ */
|
|
|
+@Service
|
|
|
+public class MesLaserService {
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private JdbcTemplate jdbcTemplate;
|
|
|
+
|
|
|
+ // 项目前缀映射:prodCode -> 客户码前缀
|
|
|
+ private static final Map<String, String> PROD_PREFIX = new HashMap<>();
|
|
|
+ static {
|
|
|
+ PROD_PREFIX.put("T09", "KB60");
|
|
|
+ PROD_PREFIX.put("T68", "KB87");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 月份代码:1-9月=数字1-9,10/11/12月=A/B/C
|
|
|
+ private static final String[] MONTH_CODE = {
|
|
|
+ "1","2","3","4","5","6","7","8","9","A","B","C"
|
|
|
+ };
|
|
|
+
|
|
|
+ // 年份字母锚点:2026年=T,按字母顺序连续递增/递减(未跳过易混淆字母,待与朱经理确认)
|
|
|
+ private static final int ANCHOR_YEAR = 2026;
|
|
|
+ private static final char ANCHOR_LETTER = 'T';
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成客户编码并与钢印码绑定,整个过程在一个事务里完成,原子性保证不会出现
|
|
|
+ * 客户码生成了但绑定失败、或者钢印码被重复绑定的情况。
|
|
|
+ * @param prodCode 产品标识 T09/T68
|
|
|
+ * @param steelSn 钢印码(镭雕软件生成并回传)
|
|
|
+ * @param oprno 工位号
|
|
|
+ * @param lineSn 产线编号
|
|
|
+ * @param userCode 操作员
|
|
|
+ * @return 生成的21位客户编码
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public String genAndBindCustomerSn(String prodCode, String steelSn, String oprno, String lineSn, String userCode) {
|
|
|
+ String prefix = PROD_PREFIX.get(prodCode);
|
|
|
+ if (prefix == null) {
|
|
|
+ throw new ServiceException("产品标识不正确,未识别的prodCode:" + prodCode);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 钢印码不能重复绑定
|
|
|
+ Integer existCount = jdbcTemplate.queryForObject(
|
|
|
+ "SELECT COUNT(1) FROM mes_product_laser WHERE steel_sn = ?",
|
|
|
+ Integer.class, steelSn);
|
|
|
+ if (existCount != null && existCount > 0) {
|
|
|
+ throw new ServiceException("该钢印码已绑定过客户编码,不能重复绑定");
|
|
|
+ }
|
|
|
+
|
|
|
+ String customerSn = genCustomerSn(prodCode, prefix);
|
|
|
+
|
|
|
+ // 绑定保存
|
|
|
+ jdbcTemplate.update(
|
|
|
+ "INSERT INTO mes_product_laser(id,prod_code,customer_sn,steel_sn,oprno,line_sn,create_by,create_date,update_by,update_date) " +
|
|
|
+ "VALUES (?,?,?,?,?,?,?,now(),?,now())",
|
|
|
+ UUID.randomUUID().toString().replace("-", ""), prodCode, customerSn, steelSn, oprno, lineSn, userCode, userCode);
|
|
|
+
|
|
|
+ return customerSn;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 只生成客户编码,不做绑定(预留,正常流程走 genAndBindCustomerSn)
|
|
|
+ */
|
|
|
+ @Transactional
|
|
|
+ public String genCustomerSn(String prodCode, String prefix) {
|
|
|
+ if (prefix == null) {
|
|
|
+ prefix = PROD_PREFIX.get(prodCode);
|
|
|
+ }
|
|
|
+ if (prefix == null) {
|
|
|
+ throw new ServiceException("产品标识不正确,未识别的prodCode:" + prodCode);
|
|
|
+ }
|
|
|
+
|
|
|
+ Date now = new Date();
|
|
|
+ String seqDate = new SimpleDateFormat("yyyyMMdd").format(now);
|
|
|
+
|
|
|
+ // 原子自增当日流水号:INSERT...ON DUPLICATE KEY UPDATE 一步完成新增/累加并取回新值
|
|
|
+ jdbcTemplate.update(
|
|
|
+ "INSERT INTO mes_customer_sn_counter(prod_code,seq_date,cur_num,update_date) VALUES (?,?,1,now()) " +
|
|
|
+ "ON DUPLICATE KEY UPDATE cur_num = LAST_INSERT_ID(cur_num + 1), update_date = now()",
|
|
|
+ prodCode, seqDate);
|
|
|
+ Long curNum = jdbcTemplate.queryForObject("SELECT LAST_INSERT_ID()", Long.class);
|
|
|
+ if (curNum == null || curNum < 1) {
|
|
|
+ throw new ServiceException("生成流水号失败");
|
|
|
+ }
|
|
|
+ if (curNum > 9999) {
|
|
|
+ throw new ServiceException("当日流水号已超过9999,无法继续生成客户编码");
|
|
|
+ }
|
|
|
+
|
|
|
+ String dateCode = getYearLetter(now) + getMonthCode(now) + getDayStr(now);
|
|
|
+ String serialStr = String.format("%04d", curNum);
|
|
|
+
|
|
|
+ return "+" + prefix + "IS3031" + dateCode + serialStr + "01";
|
|
|
+ }
|
|
|
+
|
|
|
+ // 年份字母:以2026=T为锚点,按字母顺序连续推算(不跳过易混淆字母,仅为当前实现假设)
|
|
|
+ private String getYearLetter(Date date) {
|
|
|
+ Calendar c = Calendar.getInstance();
|
|
|
+ c.setTime(date);
|
|
|
+ int year = c.get(Calendar.YEAR);
|
|
|
+ int diff = year - ANCHOR_YEAR;
|
|
|
+ char letter = (char) (ANCHOR_LETTER + diff);
|
|
|
+ return String.valueOf(letter);
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getMonthCode(Date date) {
|
|
|
+ Calendar c = Calendar.getInstance();
|
|
|
+ c.setTime(date);
|
|
|
+ int month = c.get(Calendar.MONTH); // 0-11
|
|
|
+ return MONTH_CODE[month];
|
|
|
+ }
|
|
|
+
|
|
|
+ private String getDayStr(Date date) {
|
|
|
+ Calendar c = Calendar.getInstance();
|
|
|
+ c.setTime(date);
|
|
|
+ int day = c.get(Calendar.DAY_OF_MONTH);
|
|
|
+ return String.format("%02d", day);
|
|
|
+ }
|
|
|
+
|
|
|
+}
|