package logic import ( "context" "database/sql" "fmt" "strconv" "time" "muyu-apiserver/model" "muyu-apiserver/pkg/tenantctx" "muyu-apiserver/pkg/uid" "muyu-apiserver/rpc/production/internal/svc" "muyu-apiserver/rpc/production/pb" "github.com/zeromicro/go-zero/core/logx" ) type CreateProductionPlanLogic struct { ctx context.Context svcCtx *svc.ServiceContext logx.Logger } func NewCreateProductionPlanLogic(ctx context.Context, svcCtx *svc.ServiceContext) *CreateProductionPlanLogic { return &CreateProductionPlanLogic{ctx: ctx, svcCtx: svcCtx, Logger: logx.WithContext(ctx)} } var defaultSteps = []struct { Type string Order int64 }{ {"confirm", 1}, {"yarn_purchase", 2}, {"dyeing", 3}, {"machine_start", 4}, {"fabric_warehouse", 5}, } func (l *CreateProductionPlanLogic) CreateProductionPlan(in *pb.CreateProductionPlanReq) (*pb.IdResp, error) { tenantId := tenantctx.ExtractTenantId(l.ctx) // Generate plan code PP-YYYYMMDD-XXXX today := time.Now().Format("20060102") count, err := l.svcCtx.PlanModel.CountTodayPlans(l.ctx, tenantId, time.Now().Format("2006-01-02")) if err != nil { return nil, err } planCode := fmt.Sprintf("PP-%s-%04d", today, count+1) targetQty, _ := strconv.ParseFloat(in.TargetQuantity, 64) yarnUsage, _ := strconv.ParseFloat(in.YarnUsagePerMeter, 64) price, _ := strconv.ParseFloat(in.ProductionPrice, 64) var startTime sql.NullTime if in.StartTime != "" { if t, err := time.Parse("2006-01-02", in.StartTime); err == nil { startTime = sql.NullTime{Time: t, Valid: true} } } planId := uid.Generate() _, err = l.svcCtx.PlanModel.Insert(l.ctx, &model.ProProductionPlan{ PlanId: planId, TenantId: tenantId, PlanCode: planCode, ProductId: in.ProductId, ProductName: in.ProductName, Color: in.Color, FabricCode: in.FabricCode, ColorCode: in.ColorCode, TargetQuantity: targetQty, YarnUsagePerMeter: yarnUsage, ProductionPrice: price, SupplierId: in.SupplierId, Status: 0, // draft Remark: sql.NullString{String: in.Remark, Valid: in.Remark != ""}, StartTime: startTime, Creator: tenantId, Operator: tenantId, }) if err != nil { return nil, err } // Create yarn ratios if len(in.YarnRatios) > 0 { ratios := make([]*model.ProPlanYarnRatio, 0, len(in.YarnRatios)) for _, yr := range in.YarnRatios { ratio, _ := strconv.ParseFloat(yr.Ratio, 64) amtPerM, _ := strconv.ParseFloat(yr.AmountPerMeter, 64) ratios = append(ratios, &model.ProPlanYarnRatio{ RatioId: uid.Generate(), PlanId: planId, YarnName: yr.YarnName, Ratio: ratio, AmountPerMeter: amtPerM, TotalAmount: amtPerM * targetQty, }) } if err := l.svcCtx.YarnRatioModel.BulkInsert(l.ctx, ratios); err != nil { return nil, err } } // Initialize 5 process steps steps := make([]*model.ProPlanProcessStep, 0, len(defaultSteps)) for _, ds := range defaultSteps { steps = append(steps, &model.ProPlanProcessStep{ StepId: uid.Generate(), PlanId: planId, StepType: ds.Type, StepOrder: ds.Order, Status: 0, // pending }) } if err := l.svcCtx.ProcessStepModel.BulkInsert(l.ctx, steps); err != nil { return nil, err } return &pb.IdResp{Id: planId}, nil }