141 lines
3.7 KiB
Go
141 lines
3.7 KiB
Go
|
|
package logic
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"database/sql"
|
|||
|
|
"encoding/json"
|
|||
|
|
"fmt"
|
|||
|
|
"math"
|
|||
|
|
"strconv"
|
|||
|
|
"strings"
|
|||
|
|
|
|||
|
|
"muyu-apiserver/model"
|
|||
|
|
"muyu-apiserver/rpc/inventory/pb"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
func nullString(v string) sql.NullString {
|
|||
|
|
return sql.NullString{String: v, Valid: v != ""}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func nullableJSON(v string) sql.NullString {
|
|||
|
|
v = strings.TrimSpace(v)
|
|||
|
|
return sql.NullString{String: v, Valid: v != ""}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func parseDecimalString(v string) float64 {
|
|||
|
|
n, _ := strconv.ParseFloat(strings.TrimSpace(v), 64)
|
|||
|
|
return n
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type yarnRatioPayload struct {
|
|||
|
|
Warp []yarnRatioItem `json:"warp"`
|
|||
|
|
Weft []yarnRatioItem `json:"weft"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
type yarnRatioItem struct {
|
|||
|
|
YarnID string `json:"yarn_id"`
|
|||
|
|
YarnId string `json:"yarnId"`
|
|||
|
|
Ratio float64 `json:"ratio"`
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func (i yarnRatioItem) yarnID() string {
|
|||
|
|
if i.YarnID != "" {
|
|||
|
|
return i.YarnID
|
|||
|
|
}
|
|||
|
|
return i.YarnId
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func validateProductBatchInput(batch *pb.ProductBatchInput) error {
|
|||
|
|
if batch == nil {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
return validateYarnRatio(batch.YarnRatio)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func validateYarnRatio(raw string) error {
|
|||
|
|
raw = strings.TrimSpace(raw)
|
|||
|
|
if raw == "" {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
var payload yarnRatioPayload
|
|||
|
|
if err := json.Unmarshal([]byte(raw), &payload); err != nil {
|
|||
|
|
return fmt.Errorf("纱线配比格式无效")
|
|||
|
|
}
|
|||
|
|
if err := validateYarnRatioSide("经线", payload.Warp); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
return validateYarnRatioSide("纬线", payload.Weft)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func validateYarnRatioSide(label string, items []yarnRatioItem) error {
|
|||
|
|
if len(items) == 0 {
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
total := 0
|
|||
|
|
for _, item := range items {
|
|||
|
|
if strings.TrimSpace(item.yarnID()) == "" {
|
|||
|
|
return fmt.Errorf("%s纱线不能为空", label)
|
|||
|
|
}
|
|||
|
|
if item.Ratio < 1 || item.Ratio > 10 || math.Trunc(item.Ratio) != item.Ratio {
|
|||
|
|
return fmt.Errorf("%s使用配比必须为 1-10 的整数", label)
|
|||
|
|
}
|
|||
|
|
total += int(item.Ratio)
|
|||
|
|
}
|
|||
|
|
if total != 10 {
|
|||
|
|
return fmt.Errorf("%s配比合计必须为 10,当前为 %d", label, total)
|
|||
|
|
}
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func batchInputToModelFields(batch *pb.ProductBatchInput, target *model.InvProductBatch) error {
|
|||
|
|
if batch == nil {
|
|||
|
|
target.ProductionProcess = nullString(defaultProcess)
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
if err := validateProductBatchInput(batch); err != nil {
|
|||
|
|
return err
|
|||
|
|
}
|
|||
|
|
target.YarnRatio = nullableJSON(batch.YarnRatio)
|
|||
|
|
target.WarpWeightGM = parseDecimalString(batch.WarpWeightGM)
|
|||
|
|
target.WeftWeightGM = parseDecimalString(batch.WeftWeightGM)
|
|||
|
|
process := strings.TrimSpace(batch.ProductionProcess)
|
|||
|
|
if process == "" {
|
|||
|
|
process = defaultProcess
|
|||
|
|
}
|
|||
|
|
target.ProductionProcess = nullString(process)
|
|||
|
|
target.Remark = nullString(batch.Remark)
|
|||
|
|
return nil
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func batchToPb(batch *model.InvProductBatch) *pb.ProductBatchInfo {
|
|||
|
|
return &pb.ProductBatchInfo{
|
|||
|
|
BatchId: batch.BatchId,
|
|||
|
|
ProductId: batch.ProductId,
|
|||
|
|
BatchNo: batch.BatchNo,
|
|||
|
|
YarnRatio: batch.YarnRatio.String,
|
|||
|
|
WarpWeightGM: fmt.Sprintf("%.4f", batch.WarpWeightGM),
|
|||
|
|
WeftWeightGM: fmt.Sprintf("%.4f", batch.WeftWeightGM),
|
|||
|
|
ProductionProcess: batch.ProductionProcess.String,
|
|||
|
|
Remark: batch.Remark.String,
|
|||
|
|
Status: batch.Status,
|
|||
|
|
CreatedAt: batch.CreatedAt.Format("2006-01-02 15:04:05"),
|
|||
|
|
UpdatedAt: batch.UpdatedAt.Format("2006-01-02 15:04:05"),
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
func productToPb(product *model.InvProduct) *pb.ProductInfo {
|
|||
|
|
return &pb.ProductInfo{
|
|||
|
|
ProductId: product.ProductId,
|
|||
|
|
ProductName: product.ProductName,
|
|||
|
|
ImageUrl: product.ImageUrl,
|
|||
|
|
Spec: product.Spec,
|
|||
|
|
Color: product.Color,
|
|||
|
|
SalesPrice: fmt.Sprintf("%.2f", product.SalesPrice),
|
|||
|
|
Remark: product.Remark.String,
|
|||
|
|
Status: product.Status,
|
|||
|
|
CreatedAt: product.CreatedAt.Format("2006-01-02 15:04:05"),
|
|||
|
|
UpdatedAt: product.UpdatedAt.Format("2006-01-02 15:04:05"),
|
|||
|
|
ColorNo: product.ColorNo,
|
|||
|
|
ProductCode: product.ProductCode,
|
|||
|
|
}
|
|||
|
|
}
|