package logic import ( "context" "fmt" "bj_power_mes/ent" "bj_power_mes/ent/bomitem" ) type BomItemReq struct { ProductCode string `json:"productCode"` MaterialCode string `json:"materialCode"` MaterialName string `json:"materialName"` Spec string `json:"spec"` Unit string `json:"unit"` ManageMode string `json:"manageMode"` UnitQty float64 `json:"unitQty"` LossRate float64 `json:"lossRate"` RequiredQty float64 `json:"requiredQty"` SerialSns []string `json:"serialSns"` } // SaveBom 保存产品 BOM(覆盖式:按 产品编码+物料编码 做 upsert) func (s *Service) SaveBom(ctx context.Context, productCode string, items []BomItemReq, operator string) error { for _, it := range items { if it.ManageMode == "" { it.ManageMode = "2" } exist, err := s.ctx.EntClient.BomItem.Query(). Where(bomitem.ProductCode(productCode), bomitem.MaterialCode(it.MaterialCode)).First(ctx) if err == nil && exist != nil { u := s.ctx.EntClient.BomItem.UpdateOneID(exist.ID). SetMaterialName(it.MaterialName).SetSpec(it.Spec).SetUnit(it.Unit). SetManageMode(it.ManageMode).SetUnitQty(it.UnitQty).SetLossRate(it.LossRate) if len(it.SerialSns) > 0 { u.SetSerialSns(it.SerialSns) } if _, err := u.Save(ctx); err != nil { return fmt.Errorf("更新BOM物料 %s 失败: %w", it.MaterialCode, err) } } else { b := s.ctx.EntClient.BomItem.Create(). SetProductCode(productCode).SetMaterialCode(it.MaterialCode). SetMaterialName(it.MaterialName).SetSpec(it.Spec).SetUnit(it.Unit). SetManageMode(it.ManageMode).SetUnitQty(it.UnitQty).SetLossRate(it.LossRate) if len(it.SerialSns) > 0 { b.SetSerialSns(it.SerialSns) } if _, err := b.Save(ctx); err != nil { return fmt.Errorf("保存BOM物料 %s 失败: %w", it.MaterialCode, err) } } } s.ctx.EventLog.Write(ctx, "bom.save", "", operator, "product_bom", productCode, "保存产品BOM", map[string]any{"count": len(items)}) return nil } func (s *Service) ListBom(ctx context.Context, productCode string) ([]*ent.BomItem, error) { q := s.ctx.EntClient.BomItem.Query() if productCode != "" { q = q.Where(bomitem.ProductCode(productCode)) } return q.Order(ent.Asc(bomitem.FieldID)).All(ctx) }