diff --git a/src/app/project/service.go b/src/app/project/service.go index 03691430ffd83bab2f88810799d2e545ad34cac4..dfbdbd7c5562d769175f432a0570d3c6f595db68 100644 --- a/src/app/project/service.go +++ b/src/app/project/service.go @@ -26,7 +26,7 @@ func NewProjectService(repo ProjectRepository) *ProjectService { // CreateProject handles the creation of new projects with business logic validation // This method ensures project uniqueness, validates business rules, and creates the project func (s *ProjectService) CreateProject(ctx context.Context, toCreate *ProjectToCreate) (*Project, error) { - log.Printf("INFO: Creating project with ID '%s' and name '%s'", toCreate.ProjectID, toCreate.Name) + log.Printf("INFO: Creating project with ID '%s', shortcut '%s' and name '%s'", toCreate.ProjectID, toCreate.Shortcut, toCreate.Name) // Business Rule 1: Project IDs must be unique across the entire system // Check if a project with this ID already exists before creating a new one @@ -38,7 +38,17 @@ func (s *ProjectService) CreateProject(ctx context.Context, toCreate *ProjectToC return nil, fmt.Errorf("project with ID '%s' already exists", toCreate.ProjectID) } - // Business Rule 2: Project end date must be after the start date + // Business Rule 2: Project shortcuts must be unique across the entire system + // Check if a project with this shortcut already exists before creating a new one + log.Printf("DEBUG: Checking if project shortcut '%s' already exists", toCreate.Shortcut) + existingByShortcut, err := s.repo.FindByShortcut(ctx, toCreate.Shortcut) + if err == nil && existingByShortcut != nil { + // If we found an existing project, the creation should fail + log.Printf("WARN: Project creation failed - shortcut '%s' already exists", toCreate.Shortcut) + return nil, fmt.Errorf("project with shortcut '%s' already exists", toCreate.Shortcut) + } + + // Business Rule 3: Project end date must be after the start date // This prevents creating projects with invalid date ranges if toCreate.EndDate.Before(toCreate.StartDate) { log.Printf("WARN: Project creation failed - end date (%s) before start date (%s)", @@ -111,9 +121,19 @@ func (s *ProjectService) GetProjectWithRequirements(ctx context.Context, id prim // UpdateProject handles project updates with business rule validation // This method ensures that updates maintain data integrity and business rules func (s *ProjectService) UpdateProject(ctx context.Context, update *ProjectToUpdate) (*Project, error) { - log.Printf("INFO: Updating project %s with name '%s'", update.ID.Hex(), update.Name) + log.Printf("INFO: Updating project %s with shortcut '%s' and name '%s'", update.ID.Hex(), update.Shortcut, update.Name) + + // Business Rule 1: Shortcut must be unique across the system (excluding this project) + // Check if another project with this shortcut already exists + log.Printf("DEBUG: Checking if shortcut '%s' is already used by another project", update.Shortcut) + existingByShortcut, err := s.repo.FindByShortcut(ctx, update.Shortcut) + if err == nil && existingByShortcut != nil && existingByShortcut.ID != update.ID { + // If we found a different project with this shortcut, the update should fail + log.Printf("WARN: Project update failed - shortcut '%s' already exists", update.Shortcut) + return nil, fmt.Errorf("project with shortcut '%s' already exists", update.Shortcut) + } - // Business Rule: End date must still be after start date after the update + // Business Rule 2: End date must still be after start date after the update // This validation is applied to updates just like it is for creation if update.EndDate.Before(update.StartDate) { log.Printf("WARN: Project update failed - end date (%s) before start date (%s)",