103 lines
3.0 KiB
Go
103 lines
3.0 KiB
Go
package service
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
"unicode/utf8"
|
|
|
|
"cmautobuy/admin/model"
|
|
"cmautobuy/admin/repository"
|
|
)
|
|
|
|
const maxShopeeSKUFieldRunes = 500
|
|
|
|
// UpdateShopeeSKUManual 保存采购员对现有蝦皮规格的人工修正。
|
|
// 只修改颜色、尺码和建议说明;规格原文、身份字段和既有采购数据保持不变。
|
|
func UpdateShopeeSKUManual(db *sql.DB, actor *model.User, goodsID, skuRecordID,
|
|
color, size, advice string, now time.Time) error {
|
|
if actor == nil || actor.Status != model.UserActive {
|
|
return ErrUnauthenticated
|
|
}
|
|
goodsID = strings.TrimSpace(goodsID)
|
|
skuRecordID = strings.TrimSpace(skuRecordID)
|
|
color = strings.TrimSpace(color)
|
|
size = strings.TrimSpace(size)
|
|
advice = strings.TrimSpace(advice)
|
|
if goodsID == "" {
|
|
return invalidFieldInput("shopee_goods_id", "蝦皮商品编号不能为空")
|
|
}
|
|
if skuRecordID == "" {
|
|
return invalidFieldInput("sku_record_id", "蝦皮规格记录编号不能为空")
|
|
}
|
|
if color == "" {
|
|
return invalidFieldInput("color", "颜色不能为空")
|
|
}
|
|
if size == "" {
|
|
return invalidFieldInput("size", "尺码不能为空")
|
|
}
|
|
for _, field := range []struct {
|
|
name, label, value string
|
|
}{{"color", "颜色", color}, {"size", "尺码", size}, {"advice", "建议说明", advice}} {
|
|
if utf8.RuneCountInString(field.value) > maxShopeeSKUFieldRunes {
|
|
return invalidFieldInput(field.name, "%s最多 500 个字符", field.label)
|
|
}
|
|
}
|
|
|
|
tx, err := db.Begin()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer tx.Rollback()
|
|
state, err := repository.GetShopeeSKUManualState(tx, skuRecordID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if state == nil || state.GoodsID != goodsID {
|
|
return invalidFieldInput("sku_record_id", "蝦皮规格不存在或不属于当前商品,请刷新页面后重试")
|
|
}
|
|
sources, err := decodeShopeeSKUProvenance(state.FieldSources)
|
|
if err != nil {
|
|
return fmt.Errorf("读取蝦皮规格字段来源失败: %w", err)
|
|
}
|
|
observedTimes, err := decodeShopeeSKUProvenance(state.FieldObservedAt)
|
|
if err != nil {
|
|
return fmt.Errorf("读取蝦皮规格字段时间失败: %w", err)
|
|
}
|
|
at := now.UTC().Format(model.TimeLayout)
|
|
for _, field := range []string{"color", "size", "advice"} {
|
|
sources[field] = "manual"
|
|
observedTimes[field] = at
|
|
}
|
|
sourcesJSON, err := json.Marshal(sources)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
timesJSON, err := json.Marshal(observedTimes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
updated, err := repository.UpdateShopeeSKUManualFields(tx, skuRecordID, goodsID,
|
|
color, size, advice, string(sourcesJSON), string(timesJSON), at)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !updated {
|
|
return invalidFieldInput("sku_record_id", "蝦皮规格已发生变化,请刷新页面后重试")
|
|
}
|
|
return tx.Commit()
|
|
}
|
|
|
|
func decodeShopeeSKUProvenance(raw string) (map[string]string, error) {
|
|
values := map[string]string{}
|
|
if strings.TrimSpace(raw) == "" {
|
|
return values, nil
|
|
}
|
|
if err := json.Unmarshal([]byte(raw), &values); err != nil {
|
|
return nil, err
|
|
}
|
|
return values, nil
|
|
}
|