212 lines
5.1 KiB
Go
212 lines
5.1 KiB
Go
package service
|
|
|
|
import (
|
|
"database/sql"
|
|
"errors"
|
|
"log"
|
|
|
|
"github.com/wmms/wmms/internal/model"
|
|
"github.com/wmms/wmms/internal/repository"
|
|
)
|
|
|
|
var ErrInvalidMaterialCategory = errors.New("请选择有效的小类类型")
|
|
|
|
type MaterialService struct {
|
|
repo *repository.MaterialRepo
|
|
logSvc *MaterialLogService
|
|
}
|
|
|
|
func NewMaterialService() *MaterialService {
|
|
return &MaterialService{
|
|
repo: repository.NewMaterialRepo(),
|
|
logSvc: NewMaterialLogService(),
|
|
}
|
|
}
|
|
|
|
func (s *MaterialService) validateCategory(categoryID *int64, organizationID int64) error {
|
|
if categoryID == nil || *categoryID <= 0 {
|
|
return ErrInvalidMaterialCategory
|
|
}
|
|
exists, err := s.repo.IsActiveSubcategory(*categoryID, organizationID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !exists {
|
|
return ErrInvalidMaterialCategory
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *MaterialService) Create(req *model.CreateMaterialRequest, operator string) (*model.Material, error) {
|
|
organizationID := req.OrganizationID
|
|
if organizationID == 0 {
|
|
organizationID = 1
|
|
}
|
|
if err := s.validateCategory(req.CategoryID, organizationID); err != nil {
|
|
return nil, err
|
|
}
|
|
unit := req.Unit
|
|
if unit == "" {
|
|
unit = "pcs"
|
|
}
|
|
|
|
var materialImage *string
|
|
if req.MaterialImage != nil {
|
|
materialImage = req.MaterialImage
|
|
}
|
|
|
|
m := &model.Material{
|
|
OrganizationID: organizationID,
|
|
MaterialCode: req.MaterialCode,
|
|
Name: req.Name,
|
|
MaterialImage: materialImage,
|
|
Spec: req.Spec,
|
|
CategoryID: req.CategoryID,
|
|
BaseUnitID: req.BaseUnitID,
|
|
Unit: unit,
|
|
Status: "active",
|
|
Version: 1,
|
|
}
|
|
if req.ManufacturerModel != nil {
|
|
m.ManufacturerModel = req.ManufacturerModel
|
|
}
|
|
|
|
// 编码由提交值和编码规则共同决定:值仍等于规则产物说明用户没改过,落库时
|
|
// 顺延号段;改过(或者小类没有规则)则原样保存,号段不动。
|
|
err := s.repo.CreateWithCodeRule(m, req.MaterialCode)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 记录日志
|
|
if err := s.logSvc.LogCreate(m, operator); err != nil {
|
|
log.Printf("Warning: failed to create material log: %v", err)
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func (s *MaterialService) Obsolete(id int64, operator string) error {
|
|
material, _ := s.GetByID(id)
|
|
if err := s.repo.Obsolete(id); err != nil {
|
|
return err
|
|
}
|
|
if material != nil {
|
|
updated := *material
|
|
updated.Status = "obsolete"
|
|
updated.Version++
|
|
if err := s.logSvc.LogUpdate(&updated, material, operator); err != nil {
|
|
log.Printf("Warning: failed to create material log: %v", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *MaterialService) Restore(id int64, operator string) error {
|
|
material, _ := s.GetByID(id)
|
|
if err := s.repo.Restore(id); err != nil {
|
|
return err
|
|
}
|
|
if material != nil {
|
|
updated := *material
|
|
updated.Status = "active"
|
|
updated.Version++
|
|
if err := s.logSvc.LogUpdate(&updated, material, operator); err != nil {
|
|
log.Printf("Warning: failed to create material log: %v", err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (s *MaterialService) GetByID(id int64) (*model.Material, error) {
|
|
m := &model.Material{}
|
|
err := s.repo.GetByID(id, m)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return m, nil
|
|
}
|
|
|
|
func (s *MaterialService) List(search, status string, limit, offset int) ([]model.Material, int64, error) {
|
|
return s.repo.List(search, status, limit, offset)
|
|
}
|
|
|
|
func (s *MaterialService) Update(id int64, req *model.UpdateMaterialRequest, operator string) (*model.Material, error) {
|
|
// 获取修改前的数据
|
|
oldMaterial, err := s.GetByID(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if req.CategoryID == nil || *req.CategoryID <= 0 {
|
|
return nil, ErrInvalidMaterialCategory
|
|
}
|
|
if oldMaterial.CategoryID == nil || *req.CategoryID != *oldMaterial.CategoryID {
|
|
if err := s.validateCategory(req.CategoryID, oldMaterial.OrganizationID); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
err = s.repo.Update(id, req)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// 获取修改后的数据
|
|
newMaterial, err := s.GetByID(id)
|
|
if err != nil {
|
|
log.Printf("Warning: failed to get new material for logging: %v", err)
|
|
}
|
|
|
|
// 记录日志
|
|
if err := s.logSvc.LogUpdate(newMaterial, oldMaterial, operator); err != nil {
|
|
log.Printf("Warning: failed to create material log: %v", err)
|
|
}
|
|
|
|
return newMaterial, nil
|
|
}
|
|
|
|
func (s *MaterialService) Delete(id int64, operator string) error {
|
|
// 获取删除前的数据
|
|
material, _ := s.GetByID(id)
|
|
|
|
err := s.repo.Delete(id)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 记录日志
|
|
if material != nil {
|
|
if err := s.logSvc.LogDelete(material, operator); err != nil {
|
|
log.Printf("Warning: failed to create material log: %v", err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (s *MaterialService) Exists(id int64) (bool, error) {
|
|
m := &model.Material{}
|
|
err := s.repo.GetByID(id, m)
|
|
if err == sql.ErrNoRows {
|
|
return false, nil
|
|
}
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return true, nil
|
|
}
|
|
|
|
// IsActive is intentionally separate from Exists: historical documents still
|
|
// need to resolve retired materials, while new warehouse operations do not.
|
|
func (s *MaterialService) IsActive(id int64) (bool, error) {
|
|
m := &model.Material{}
|
|
err := s.repo.GetByID(id, m)
|
|
if err == sql.ErrNoRows {
|
|
return false, nil
|
|
}
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
return m.Status == "active", nil
|
|
}
|