214 lines
5.8 KiB
Go
Raw Permalink Normal View History

package service
import (
"context"
"database/sql"
"fmt"
"time"
"github.com/google/uuid"
"github.com/muyuqingfeng/iloom/purchaser-service/internal/model"
"github.com/muyuqingfeng/iloom/purchaser-service/internal/repository"
"github.com/muyuqingfeng/iloom/shared/pkg/types"
)
type PlanService struct {
repo *repository.PlanRepo
db *sql.DB
}
func NewPlanService(repo *repository.PlanRepo, db *sql.DB) *PlanService {
return &PlanService{repo: repo, db: db}
}
type CreatePlanRequest struct {
ProductName string `json:"product_name"`
FabricCode string `json:"fabric_code"`
Color string `json:"color"`
ColorCode string `json:"color_code"`
TargetQuantity float64 `json:"target_quantity"`
ProductionPrice *float64 `json:"production_price"`
YarnUsagePerMeter *float64 `json:"yarn_usage_per_meter"`
Remark string `json:"remark"`
YarnRatios []CreateYarnRatio `json:"yarn_ratios"`
}
type CreateYarnRatio struct {
YarnName string `json:"yarn_name"`
YarnType string `json:"yarn_type"`
Ratio float64 `json:"ratio"`
AmountPerMeter float64 `json:"amount_per_meter"`
TotalAmount float64 `json:"total_amount"`
}
type UpdatePlanRequest struct {
ProductName string `json:"product_name"`
FabricCode string `json:"fabric_code"`
Color string `json:"color"`
ColorCode string `json:"color_code"`
TargetQuantity float64 `json:"target_quantity"`
ProductionPrice *float64 `json:"production_price"`
YarnUsagePerMeter *float64 `json:"yarn_usage_per_meter"`
Status string `json:"status"`
Remark string `json:"remark"`
}
func (s *PlanService) List(ctx context.Context, companyID string, page types.Pagination, status string) ([]model.ProductionPlan, int, error) {
page.Normalize()
return s.repo.List(ctx, companyID, page, status)
}
func (s *PlanService) Create(ctx context.Context, companyID, userID string, req CreatePlanRequest) (*model.ProductionPlan, error) {
now := time.Now()
planCode := fmt.Sprintf("PP%s%03d", now.Format("20060102"), now.UnixMilli()%1000)
var remarkPtr *string
if req.Remark != "" {
remarkPtr = &req.Remark
}
plan := &model.ProductionPlan{
ID: uuid.New().String(),
PlanCode: planCode,
PurchaserID: companyID,
ProductName: req.ProductName,
FabricCode: req.FabricCode,
Color: req.Color,
ColorCode: req.ColorCode,
TargetQuantity: req.TargetQuantity,
CompletedQuantity: 0,
ProductionPrice: req.ProductionPrice,
YarnUsagePerMeter: req.YarnUsagePerMeter,
Status: string(types.PlanPending),
Remark: remarkPtr,
CreatedBy: &userID,
CreatedAt: now,
UpdatedAt: now,
}
var yarnRatios []model.YarnRatio
for _, yr := range req.YarnRatios {
var yarnTypePtr *string
if yr.YarnType != "" {
yarnTypePtr = &yr.YarnType
}
yarnRatios = append(yarnRatios, model.YarnRatio{
ID: uuid.New().String(),
PlanID: plan.ID,
YarnName: yr.YarnName,
YarnType: yarnTypePtr,
Ratio: yr.Ratio,
AmountPerMeter: yr.AmountPerMeter,
TotalAmount: yr.TotalAmount,
CompanyID: &companyID,
CreatedAt: now,
})
}
tx, err := s.db.BeginTx(ctx, nil)
if err != nil {
return nil, fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback()
if err := s.repo.Create(ctx, tx, plan); err != nil {
return nil, err
}
if len(yarnRatios) > 0 {
if err := s.repo.CreateYarnRatios(ctx, tx, yarnRatios); err != nil {
return nil, err
}
}
if err := tx.Commit(); err != nil {
return nil, fmt.Errorf("commit tx: %w", err)
}
plan.YarnRatios = yarnRatios
return plan, nil
}
func (s *PlanService) GetByID(ctx context.Context, id, companyID string) (*model.ProductionPlan, error) {
plan, err := s.repo.GetByID(ctx, id)
if err != nil {
return nil, err
}
if plan == nil {
return nil, fmt.Errorf("plan not found")
}
if plan.PurchaserID != companyID {
return nil, fmt.Errorf("plan not found")
}
steps, err := s.repo.GetSteps(ctx, id)
if err != nil {
return nil, err
}
plan.ProcessSteps = steps
inventory, err := s.repo.GetInventory(ctx, id)
if err != nil {
return nil, err
}
plan.InventoryRecords = inventory
return plan, nil
}
func (s *PlanService) Update(ctx context.Context, id, companyID string, req UpdatePlanRequest) error {
plan, err := s.repo.GetByID(ctx, id)
if err != nil {
return err
}
if plan == nil || plan.PurchaserID != companyID {
return fmt.Errorf("plan not found")
}
if req.ProductName != "" {
plan.ProductName = req.ProductName
}
if req.FabricCode != "" {
plan.FabricCode = req.FabricCode
}
if req.Color != "" {
plan.Color = req.Color
}
if req.ColorCode != "" {
plan.ColorCode = req.ColorCode
}
if req.TargetQuantity > 0 {
plan.TargetQuantity = req.TargetQuantity
}
if req.ProductionPrice != nil {
plan.ProductionPrice = req.ProductionPrice
}
if req.YarnUsagePerMeter != nil {
plan.YarnUsagePerMeter = req.YarnUsagePerMeter
}
if req.Status != "" {
plan.Status = req.Status
}
if req.Remark != "" {
plan.Remark = &req.Remark
}
return s.repo.Update(ctx, plan)
}
func (s *PlanService) Delete(ctx context.Context, id, companyID string) error {
return s.repo.Delete(ctx, id, companyID)
}
func (s *PlanService) AssignFactory(ctx context.Context, planID, factoryID, factoryType string) error {
return s.repo.AssignFactory(ctx, planID, factoryID, factoryType)
}
func (s *PlanService) GetSteps(ctx context.Context, planID string) ([]model.ProcessStep, error) {
return s.repo.GetSteps(ctx, planID)
}
func (s *PlanService) GetInventory(ctx context.Context, planID string) ([]model.InventoryRecord, error) {
return s.repo.GetInventory(ctx, planID)
}