package service import ( "context" "time" "erp-mvp/core-service/internal/models" "erp-mvp/core-service/internal/repository" "github.com/google/uuid" "github.com/sirupsen/logrus" ) type OperationsService interface { PlaceItem(ctx context.Context, orgID uuid.UUID, req *models.PlaceItemRequest) (*models.ItemPlacement, error) MoveItem(ctx context.Context, placementID uuid.UUID, newLocationID uuid.UUID, orgID uuid.UUID) error GetItemPlacements(ctx context.Context, itemID uuid.UUID, orgID uuid.UUID) ([]*models.ItemPlacement, error) GetLocationPlacements(ctx context.Context, locationID uuid.UUID, orgID uuid.UUID) ([]*models.ItemPlacement, error) UpdateQuantity(ctx context.Context, placementID uuid.UUID, quantity int, orgID uuid.UUID) error DeletePlacement(ctx context.Context, placementID uuid.UUID, orgID uuid.UUID) error Search(ctx context.Context, orgID uuid.UUID, req *models.SearchRequest) (*models.SearchResponse, error) } type operationsService struct { operationsRepo repository.OperationsRepository itemRepo repository.ItemRepository locationRepo repository.LocationRepository logger *logrus.Logger } func NewOperationsService(operationsRepo repository.OperationsRepository, itemRepo repository.ItemRepository, locationRepo repository.LocationRepository) OperationsService { return &operationsService{ operationsRepo: operationsRepo, itemRepo: itemRepo, locationRepo: locationRepo, logger: logrus.New(), } } func (s *operationsService) PlaceItem(ctx context.Context, orgID uuid.UUID, req *models.PlaceItemRequest) (*models.ItemPlacement, error) { s.logger.Info("Placing item: ", req.ItemID, " in location: ", req.LocationID, " for organization: ", orgID) // Проверяем, что товар существует и принадлежит организации _, err := s.itemRepo.GetByID(ctx, req.ItemID, orgID) if err != nil { s.logger.Error("Item not found or not accessible: ", err) return nil, err } // Проверяем, что место хранения существует и принадлежит организации _, err = s.locationRepo.GetByID(ctx, req.LocationID, orgID) if err != nil { s.logger.Error("Location not found or not accessible: ", err) return nil, err } placement := &models.ItemPlacement{ ID: uuid.New(), OrganizationID: orgID, ItemID: req.ItemID, LocationID: req.LocationID, Quantity: req.Quantity, CreatedAt: time.Now(), } if err := s.operationsRepo.PlaceItem(ctx, placement); err != nil { s.logger.Error("Failed to place item: ", err) return nil, err } s.logger.Info("Item placed successfully: ", placement.ID) return placement, nil } func (s *operationsService) MoveItem(ctx context.Context, placementID uuid.UUID, newLocationID uuid.UUID, orgID uuid.UUID) error { s.logger.Info("Moving item placement: ", placementID, " to location: ", newLocationID, " for organization: ", orgID) // Проверяем, что размещение существует и принадлежит организации placement, err := s.operationsRepo.GetByID(ctx, placementID, orgID) if err != nil { s.logger.Error("Item placement not found or not accessible: ", err) return err } // Проверяем, что новое место хранения существует и принадлежит организации _, err = s.locationRepo.GetByID(ctx, newLocationID, orgID) if err != nil { s.logger.Error("New location not found or not accessible: ", err) return err } if err := s.operationsRepo.MoveItem(ctx, placementID, newLocationID, orgID); err != nil { s.logger.Error("Failed to move item: ", err) return err } s.logger.Info("Item moved successfully from location: ", placement.LocationID, " to: ", newLocationID) return nil } func (s *operationsService) GetItemPlacements(ctx context.Context, itemID uuid.UUID, orgID uuid.UUID) ([]*models.ItemPlacement, error) { s.logger.Info("Getting placements for item: ", itemID, " in organization: ", orgID) // Проверяем, что товар существует и принадлежит организации _, err := s.itemRepo.GetByID(ctx, itemID, orgID) if err != nil { s.logger.Error("Item not found or not accessible: ", err) return nil, err } placements, err := s.operationsRepo.GetByItem(ctx, itemID, orgID) if err != nil { s.logger.Error("Failed to get item placements: ", err) return nil, err } return placements, nil } func (s *operationsService) GetLocationPlacements(ctx context.Context, locationID uuid.UUID, orgID uuid.UUID) ([]*models.ItemPlacement, error) { s.logger.Info("Getting placements for location: ", locationID, " in organization: ", orgID) // Проверяем, что место хранения существует и принадлежит организации _, err := s.locationRepo.GetByID(ctx, locationID, orgID) if err != nil { s.logger.Error("Location not found or not accessible: ", err) return nil, err } placements, err := s.operationsRepo.GetByLocation(ctx, locationID, orgID) if err != nil { s.logger.Error("Failed to get location placements: ", err) return nil, err } return placements, nil } func (s *operationsService) UpdateQuantity(ctx context.Context, placementID uuid.UUID, quantity int, orgID uuid.UUID) error { s.logger.Info("Updating quantity for placement: ", placementID, " to: ", quantity, " in organization: ", orgID) // Проверяем, что размещение существует и принадлежит организации _, err := s.operationsRepo.GetByID(ctx, placementID, orgID) if err != nil { s.logger.Error("Item placement not found or not accessible: ", err) return err } if err := s.operationsRepo.UpdateQuantity(ctx, placementID, quantity, orgID); err != nil { s.logger.Error("Failed to update quantity: ", err) return err } s.logger.Info("Quantity updated successfully for placement: ", placementID) return nil } func (s *operationsService) DeletePlacement(ctx context.Context, placementID uuid.UUID, orgID uuid.UUID) error { s.logger.Info("Deleting placement: ", placementID, " for organization: ", orgID) // Проверяем, что размещение существует и принадлежит организации _, err := s.operationsRepo.GetByID(ctx, placementID, orgID) if err != nil { s.logger.Error("Item placement not found or not accessible: ", err) return err } if err := s.operationsRepo.Delete(ctx, placementID, orgID); err != nil { s.logger.Error("Failed to delete placement: ", err) return err } s.logger.Info("Placement deleted successfully: ", placementID) return nil } func (s *operationsService) Search(ctx context.Context, orgID uuid.UUID, req *models.SearchRequest) (*models.SearchResponse, error) { s.logger.Info("Searching items with locations for organization: ", orgID, " query: ", req.Query) results, err := s.operationsRepo.Search(ctx, orgID, req.Query, req.Category, req.Address) if err != nil { s.logger.Error("Failed to search items with locations: ", err) return nil, err } response := &models.SearchResponse{ Items: results, TotalCount: len(results), } return response, nil }