package service import ( "database/sql" "github.com/shopspring/decimal" "github.com/wmms/wmms/internal/model" "github.com/wmms/wmms/internal/repository" ) type StockService struct { stockRepo *repository.StockRepo } func NewStockService() *StockService { return &StockService{ stockRepo: repository.NewStockRepo(), } } func (s *StockService) GetAllStock(search string, limit, offset int) ([]model.Stock, int64, error) { return s.stockRepo.GetAllStock(search, limit, offset) } func (s *StockService) GetByMaterialID(materialID int64) (*model.Stock, error) { return s.stockRepo.GetByMaterialID(materialID) } func (s *StockService) GetWarningStock(limit, offset int) ([]model.Stock, int64, error) { return s.stockRepo.GetWarningStock(limit, offset) } func (s *StockService) UpdateWarningStock(materialID int64, minimumAvailable decimal.Decimal) error { return s.stockRepo.UpdateWarningStock(materialID, minimumAvailable) } func (s *StockService) GetLogsByMaterialID(materialID int64, limit, offset int) ([]model.StockLogResponse, int64, error) { logs, total, err := s.stockRepo.GetLogsByMaterialID(materialID, limit, offset) if err != nil { return nil, 0, err } var responses []model.StockLogResponse balance := decimal.Zero for _, log := range logs { quantity := decimal.NewFromInt(int64(log.Quantity)) if log.Type == "in" { balance = balance.Add(quantity) } else { balance = balance.Sub(quantity) } changeType := "outbound" if log.Type == "in" { changeType = "inbound" } beforeQuantity := balance.Sub(quantity) if log.Type != "in" { beforeQuantity = balance.Add(quantity) } responses = append(responses, model.StockLogResponse{ ID: log.ID, MaterialID: log.MaterialID, ChangeType: changeType, ChangeQuantity: quantity, BeforeQuantity: beforeQuantity, AfterQuantity: balance, ReferenceID: log.RelatedOrderID, ReferenceType: log.RelatedOrderType, CreatedAt: log.CreatedAt, }) } return responses, total, nil } func (s *StockService) GetAllLogs(limit, offset int) ([]model.StockLogResponse, int64, error) { logs, total, err := s.stockRepo.GetAllLogsWithBalance(limit, offset) if err != nil { return nil, 0, err } var responses []model.StockLogResponse for _, log := range logs { changeType := "outbound" if log.Type == "in" { changeType = "inbound" } quantity := decimal.NewFromInt(int64(log.Quantity)) beforeQuantity := log.RunningBalance.Sub(quantity) if log.Type != "in" { beforeQuantity = log.RunningBalance.Add(quantity) } // inbound=+quantity, outbound=-quantity changeQuantity := quantity if log.Type != "in" { changeQuantity = quantity.Neg() } responses = append(responses, model.StockLogResponse{ ID: log.ID, MaterialID: log.MaterialID, ChangeType: changeType, ChangeQuantity: changeQuantity, BeforeQuantity: beforeQuantity, AfterQuantity: log.RunningBalance, ReferenceID: log.RelatedOrderID, ReferenceType: log.RelatedOrderType, CreatedAt: log.CreatedAt, }) } return responses, total, nil } func (s *StockService) MaterialExists(materialID int64) (bool, error) { _, err := s.stockRepo.GetByMaterialID(materialID) if err == sql.ErrNoRows { return false, nil } if err != nil { return false, err } return true, nil } func (s *StockService) GetInventoryBalanceDetails(materialID int64) ([]model.InventoryBalanceDetail, error) { return s.stockRepo.GetInventoryBalanceDetails(materialID) }