Change aftersales serial to YYMMNN monthly sequence
User-requested format: zjbf-sh-260501 (26=year, 05=month, 01=monthly seq). Sequence resets each month and skips soft-deleted entries to avoid reuse. Also documents aftersales API and new technician role in AGENTS.md / README. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,7 @@
|
||||
package services
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
@@ -70,20 +68,33 @@ func normalizeAftersalesSerial(sn string) string {
|
||||
}
|
||||
|
||||
// generateUniqueSerial 生成唯一的售后工单序列号
|
||||
// 格式:zjbf-sh-YYMMNN,YY=年份后两位,MM=月份,NN=当月第几单(至少 2 位,溢出自然加宽)
|
||||
func (s *AftersalesService) generateUniqueSerial() (string, error) {
|
||||
for attempt := 0; attempt < 10; attempt++ {
|
||||
randomBytes := make([]byte, 3)
|
||||
if _, err := rand.Read(randomBytes); err != nil {
|
||||
return "", fmt.Errorf("生成随机数失败: %w", err)
|
||||
}
|
||||
randomPart := strings.ToLower(hex.EncodeToString(randomBytes))[:6]
|
||||
candidate := aftersalesSerialPrefix + randomPart
|
||||
now := time.Now()
|
||||
yy := now.Year() % 100
|
||||
mm := int(now.Month())
|
||||
|
||||
monthStart := time.Date(now.Year(), now.Month(), 1, 0, 0, 0, 0, now.Location())
|
||||
nextMonth := monthStart.AddDate(0, 1, 0)
|
||||
|
||||
// 统计本月已创建工单数(含软删除,避免编号回收)
|
||||
var count int64
|
||||
if err := database.DB.Unscoped().Model(&models.AftersalesOrder{}).
|
||||
Where("created_at >= ? AND created_at < ?", monthStart, nextMonth).
|
||||
Count(&count).Error; err != nil {
|
||||
return "", fmt.Errorf("统计当月工单数失败: %w", err)
|
||||
}
|
||||
|
||||
seq := int(count) + 1
|
||||
for attempt := 0; attempt < 100; attempt++ {
|
||||
candidate := fmt.Sprintf("%s%02d%02d%02d", aftersalesSerialPrefix, yy, mm, seq)
|
||||
|
||||
var existing models.AftersalesOrder
|
||||
result := database.DB.Where("serial_number = ?", candidate).First(&existing)
|
||||
result := database.DB.Unscoped().Where("serial_number = ?", candidate).First(&existing)
|
||||
if result.Error != nil {
|
||||
return candidate, nil
|
||||
}
|
||||
seq++
|
||||
}
|
||||
return "", errors.New("生成唯一序列号失败,请重试")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user