Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
H
HARMONY-experimental-branch
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Requirements
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Locked files
Build
Pipelines
Jobs
Pipeline schedules
Test cases
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Code review analytics
Issue analytics
Insights
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Robin Korfmann
HARMONY-experimental-branch
Commits
7fb3d747
Commit
7fb3d747
authored
2 months ago
by
Dasan Ibrahim
Browse files
Options
Downloads
Patches
Plain Diff
Implementation of the business logic for the project management operation
parent
70ce32ab
No related branches found
Branches containing commit
No related tags found
1 merge request
!4
merge dev to main
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
src/Project/service.go
+176
-0
176 additions, 0 deletions
src/Project/service.go
with
176 additions
and
0 deletions
src/Project/service.go
0 → 100644
+
176
−
0
View file @
7fb3d747
package
project
import
(
"context"
"fmt"
"log"
"github.com/google/uuid"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// ProjectService contains the business logic for project management operations
// This service layer sits between the web controllers and the data repository
// It enforces business rules, handles validation, and coordinates data operations
type
ProjectService
struct
{
repo
ProjectRepository
// Repository interface for data access operations
}
// NewProjectService creates and initializes a new ProjectService instance
// The service requires a repository implementation to handle data persistence
func
NewProjectService
(
repo
ProjectRepository
)
*
ProjectService
{
log
.
Println
(
"INFO: ProjectService initialized"
)
return
&
ProjectService
{
repo
:
repo
}
}
// 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
)
// 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
log
.
Printf
(
"DEBUG: Checking if project ID '%s' already exists"
,
toCreate
.
ProjectID
)
existing
,
err
:=
s
.
repo
.
FindByProjectID
(
ctx
,
toCreate
.
ProjectID
)
if
err
==
nil
&&
existing
!=
nil
{
// If we found an existing project, the creation should fail
log
.
Printf
(
"WARN: Project creation failed - ID '%s' already exists"
,
toCreate
.
ProjectID
)
return
nil
,
fmt
.
Errorf
(
"project with ID '%s' already exists"
,
toCreate
.
ProjectID
)
}
// Business Rule 2: 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)"
,
toCreate
.
EndDate
.
Format
(
"2006-01-02"
),
toCreate
.
StartDate
.
Format
(
"2006-01-02"
))
return
nil
,
fmt
.
Errorf
(
"end date must be after start date"
)
}
log
.
Printf
(
"DEBUG: Project validation passed, creating in repository"
)
// All business rules passed, delegate to repository for actual creation
project
,
err
:=
s
.
repo
.
Create
(
ctx
,
toCreate
)
if
err
!=
nil
{
log
.
Printf
(
"ERROR: Failed to create project '%s' in repository: %v"
,
toCreate
.
ProjectID
,
err
)
return
nil
,
err
}
log
.
Printf
(
"INFO: Project '%s' created successfully with MongoDB ID %s"
,
project
.
ProjectID
,
project
.
ID
.
Hex
())
return
project
,
nil
}
// GetProjectsByUser retrieves all projects belonging to a specific user
// This method provides a simple interface for fetching user-specific projects
func
(
s
*
ProjectService
)
GetProjectsByUser
(
ctx
context
.
Context
,
userID
uuid
.
UUID
)
([]
*
Project
,
error
)
{
log
.
Printf
(
"INFO: Getting projects for user %s"
,
userID
)
// Delegate to repository for data retrieval
projects
,
err
:=
s
.
repo
.
FindByCreatedBy
(
ctx
,
userID
)
if
err
!=
nil
{
log
.
Printf
(
"ERROR: Failed to get projects for user %s: %v"
,
userID
,
err
)
return
nil
,
err
}
log
.
Printf
(
"INFO: Found %d projects for user %s"
,
len
(
projects
),
userID
)
// Debug logging: Show project names for troubleshooting
if
len
(
projects
)
>
0
{
log
.
Printf
(
"DEBUG: Projects found: %v"
,
func
()
[]
string
{
names
:=
make
([]
string
,
len
(
projects
))
for
i
,
p
:=
range
projects
{
names
[
i
]
=
p
.
Name
}
return
names
}())
}
return
projects
,
nil
}
// GetProjectWithRequirements retrieves a project along with all its associated requirements
// This method is optimized for displaying project detail pages where both
// project information and requirements are needed simultaneously
func
(
s
*
ProjectService
)
GetProjectWithRequirements
(
ctx
context
.
Context
,
id
primitive
.
ObjectID
)
(
*
ProjectWithRequirements
,
error
)
{
log
.
Printf
(
"INFO: Getting project with requirements for ID %s"
,
id
.
Hex
())
// Use the repository method that efficiently loads project and requirements together
// This is more efficient than making separate calls for project and requirements
projectWithReqs
,
err
:=
s
.
repo
.
FindWithRequirements
(
ctx
,
id
)
if
err
!=
nil
{
log
.
Printf
(
"ERROR: Failed to get project with requirements for ID %s: %v"
,
id
.
Hex
(),
err
)
return
nil
,
err
}
log
.
Printf
(
"INFO: Loaded project '%s' with %d requirements"
,
projectWithReqs
.
Project
.
Name
,
projectWithReqs
.
RequirementCount
)
return
projectWithReqs
,
nil
}
// 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
)
// Business Rule: 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)"
,
update
.
EndDate
.
Format
(
"2006-01-02"
),
update
.
StartDate
.
Format
(
"2006-01-02"
))
return
nil
,
fmt
.
Errorf
(
"end date must be after start date"
)
}
log
.
Printf
(
"DEBUG: Project update validation passed, updating in repository"
)
// Delegate to repository for the actual update operation
project
,
err
:=
s
.
repo
.
Update
(
ctx
,
update
)
if
err
!=
nil
{
log
.
Printf
(
"ERROR: Failed to update project %s: %v"
,
update
.
ID
.
Hex
(),
err
)
return
nil
,
err
}
log
.
Printf
(
"INFO: Project '%s' updated successfully"
,
project
.
Name
)
return
project
,
nil
}
// DeleteProject handles the complete removal of a project and all associated data
// This method ensures that all related requirements are also deleted to maintain data consistency
func
(
s
*
ProjectService
)
DeleteProject
(
ctx
context
.
Context
,
id
primitive
.
ObjectID
)
error
{
log
.
Printf
(
"INFO: Deleting project with ID %s"
,
id
.
Hex
())
// The repository handles the cascading deletion of requirements
// This ensures that no orphaned requirements remain in the database
err
:=
s
.
repo
.
Delete
(
ctx
,
id
)
if
err
!=
nil
{
log
.
Printf
(
"ERROR: Failed to delete project %s: %v"
,
id
.
Hex
(),
err
)
return
err
}
log
.
Printf
(
"INFO: Project %s and all its requirements deleted successfully"
,
id
.
Hex
())
return
nil
}
// SearchProjects provides flexible project search functionality
// This method handles both empty queries (return all projects) and text-based searches
func
(
s
*
ProjectService
)
SearchProjects
(
ctx
context
.
Context
,
query
string
,
userID
uuid
.
UUID
)
([]
*
Project
,
error
)
{
// Handle empty search queries by returning all projects for the user
// This provides a consistent interface regardless of whether a search term is provided
if
query
==
""
{
log
.
Printf
(
"INFO: Empty search query, returning all projects for user %s"
,
userID
)
return
s
.
repo
.
FindByCreatedBy
(
ctx
,
userID
)
}
log
.
Printf
(
"INFO: Searching projects for user %s with query '%s'"
,
userID
,
query
)
// Delegate to repository for the actual search implementation
// The repository handles the specifics of text searching across project fields
projects
,
err
:=
s
.
repo
.
Search
(
ctx
,
query
,
userID
)
if
err
!=
nil
{
log
.
Printf
(
"ERROR: Search failed for query '%s' and user %s: %v"
,
query
,
userID
,
err
)
return
nil
,
err
}
log
.
Printf
(
"INFO: Search completed - found %d projects for query '%s'"
,
len
(
projects
),
query
)
return
projects
,
nil
}
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment