Files
ldpv2/doc/stories/STORY-1-Business-Units.md
T
2026-02-07 17:51:17 +01:00

14 KiB

Story 1: Business Unit Management

Story Overview

As a system administrator
I want to manage business units in the system
So that I can organize applications under their respective organizational units

Story Type: Feature
Priority: High
Estimated Effort: 3-5 days
Dependencies: Story 0 (Foundation)


Business Value

Business units represent the organizational structure within which applications are managed. This story enables:

  • Clear organizational hierarchy
  • Application ownership mapping
  • Contact management at the business unit level
  • Foundation for multi-tenant capabilities

Scope

In Scope

Business unit CRUD operations
Business unit listing with search/filter
Basic contact association (simplified for MVP)
Validation (unique names, required fields)

Out of Scope

Complex hierarchical business units (parent/child relationships)
Full contact management (covered in Story 3)
Business unit-specific permissions
Bulk import of business units


Technical Implementation

Backend Tasks

1. Database Migration

  • Create Liquibase migration file: 003-create-business-unit-tables.xml
  • Create business_unit table:
    - id (UUID, PK)
    - name (VARCHAR(255), unique, not null)
    - description (TEXT, nullable)
    - created_at (TIMESTAMP, not null)
    - updated_at (TIMESTAMP, not null)
    
  • Add index on name for search performance
  • Insert sample data (3-5 business units) for testing

2. JPA Entity

  • Create BusinessUnit entity extending BaseEntity
    @Entity
    @Table(name = "business_unit")
    public class BusinessUnit extends BaseEntity {
        @Column(nullable = false, unique = true)
        private String name;
    
        @Column(columnDefinition = "TEXT")
        private String description;
    
        // Getters, setters, constructors
    }
    

3. Repository Layer

  • Create BusinessUnitRepository interface
    public interface BusinessUnitRepository extends JpaRepository<BusinessUnit, UUID> {
        Optional<BusinessUnit> findByName(String name);
        boolean existsByName(String name);
        Page<BusinessUnit> findByNameContainingIgnoreCase(String name, Pageable pageable);
    }
    

4. DTOs

  • Create CreateBusinessUnitRequest:
    • name (required, max 255 chars)
    • description (optional)
  • Create UpdateBusinessUnitRequest:
    • name (optional, max 255 chars)
    • description (optional)
  • Create BusinessUnitResponse:
    • id, name, description, createdAt, updatedAt
  • Create BusinessUnitSummaryResponse (for lists):
    • id, name

5. Service Layer

  • Create BusinessUnitService with methods:
    BusinessUnitResponse create(CreateBusinessUnitRequest request);
    BusinessUnitResponse update(UUID id, UpdateBusinessUnitRequest request);
    BusinessUnitResponse findById(UUID id);
    Page<BusinessUnitResponse> findAll(Pageable pageable);
    Page<BusinessUnitResponse> search(String query, Pageable pageable);
    void delete(UUID id);
    
  • Implement business logic:
    • Check uniqueness of name on create/update
    • Throw ResourceNotFoundException if not found
    • Throw BadRequestException for duplicate names
  • Add validation for required fields

6. Controller Layer

  • Create BusinessUnitController with endpoints:
    GET    /api/business-units              - List all (paginated)
    GET    /api/business-units/search?q={query} - Search by name
    GET    /api/business-units/{id}         - Get by ID
    POST   /api/business-units              - Create new
    PUT    /api/business-units/{id}         - Update
    DELETE /api/business-units/{id}         - Delete
    
  • Add validation annotations (@Valid, @NotNull, etc.)
  • Add Swagger/OpenAPI annotations
  • Add security: require authentication for all endpoints

7. Testing

  • Unit tests for BusinessUnitService:
    • Test create with valid data
    • Test create with duplicate name (should fail)
    • Test update existing business unit
    • Test delete business unit
    • Test search functionality
  • Integration tests for BusinessUnitController:
    • Test full CRUD flow
    • Test pagination and sorting
    • Test search with various queries
    • Test error cases (404, 400)
  • Test coverage > 80%

Frontend Tasks

1. Models

  • Create business-unit.model.ts:
    export interface BusinessUnit {
      id: string;
      name: string;
      description?: string;
      createdAt: Date;
      updatedAt: Date;
    }
    
    export interface BusinessUnitSummary {
      id: string;
      name: string;
    }
    
    export interface CreateBusinessUnitRequest {
      name: string;
      description?: string;
    }
    
    export interface UpdateBusinessUnitRequest {
      name?: string;
      description?: string;
    }
    

2. Service

  • Create business-unit.service.ts:
    @Injectable({ providedIn: 'root' })
    export class BusinessUnitService {
      getBusinessUnits(page, size, sort): Observable<Page<BusinessUnit>>
      searchBusinessUnits(query, page, size): Observable<Page<BusinessUnit>>
      getBusinessUnit(id): Observable<BusinessUnit>
      createBusinessUnit(data): Observable<BusinessUnit>
      updateBusinessUnit(id, data): Observable<BusinessUnit>
      deleteBusinessUnit(id): Observable<void>
    }
    

3. Components

BusinessUnitListComponent
  • Create component with template and styles
  • Features:
    • Table/list view of business units
    • Columns: Name, Description, Actions
    • Pagination controls (page size: 20)
    • Sort by name
    • Search bar (filter by name)
    • "Create New" button
    • Actions per row: View, Edit, Delete
  • Implement component logic:
    • Load business units on init
    • Handle pagination events
    • Handle sort events
    • Handle search with debounce (300ms)
    • Navigate to detail/form pages
    • Handle delete with confirmation
BusinessUnitDetailComponent
  • Create component with template and styles
  • Features:
    • Display all business unit details
    • "Edit" button
    • "Delete" button
    • "Back to List" button
    • Show created/updated timestamps
  • Load business unit by ID from route params
BusinessUnitFormComponent
  • Create component with template and styles
  • Reactive form with fields:
    • Name (required, max 255 chars)
    • Description (optional, textarea)
  • Form validation:
    • Name required
    • Max length validation
    • Show validation errors
  • Support both create and edit modes (based on route)
  • Handle form submission:
    • Call appropriate service method
    • Show loading indicator during save
    • Navigate to list on success
    • Show error notification on failure
  • "Cancel" button (navigate back)

4. Routing

  • Add routes to app.routes.ts:
    {
      path: 'business-units',
      canActivate: [AuthGuard],
      children: [
        { path: '', component: BusinessUnitListComponent },
        { path: 'new', component: BusinessUnitFormComponent },
        { path: ':id', component: BusinessUnitDetailComponent },
        { path: ':id/edit', component: BusinessUnitFormComponent }
      ]
    }
    

5. Navigation

  • Add "Business Units" link to header/sidebar navigation

6. Testing

  • Unit tests for BusinessUnitService
  • Component tests for BusinessUnitListComponent:
    • Test rendering of business units
    • Test pagination
    • Test search
    • Test navigation to create/edit/detail
  • Component tests for BusinessUnitFormComponent:
    • Test form validation
    • Test create mode
    • Test edit mode
    • Test form submission
  • E2E test: Full CRUD flow
  • Test coverage > 70%

Acceptance Criteria

Backend

  • Business unit can be created with unique name
  • Duplicate business unit names are rejected with 400 error
  • Business unit can be updated
  • Business unit can be deleted
  • Business units can be listed with pagination
  • Business units can be searched by name (case-insensitive)
  • All endpoints are authenticated
  • All endpoints return proper HTTP status codes
  • API is documented in Swagger

Frontend

  • User can view list of all business units
  • List supports pagination (20 items per page)
  • User can search business units by name
  • Search has debounce (doesn't query on every keystroke)
  • User can create new business unit
  • Form validates required fields
  • User cannot create duplicate business unit names
  • User can view business unit details
  • User can edit existing business unit
  • User can delete business unit (with confirmation)
  • Success/error notifications are displayed
  • Navigation is intuitive and works correctly

Testing

  • Backend unit tests pass (>80% coverage)
  • Backend integration tests pass
  • Frontend unit tests pass (>70% coverage)
  • E2E tests pass

Testing Scenarios

Scenario 1: Create Business Unit

  1. Navigate to business units list
  2. Click "Create New Business Unit"
  3. Fill in form:
    • Name: "Digital Services"
    • Description: "Digital transformation initiatives"
  4. Click "Save"
  5. Verify success notification
  6. Verify redirect to business unit list
  7. Verify new business unit appears in list

Scenario 2: Duplicate Name Prevention

  1. Navigate to create business unit form
  2. Enter name of existing business unit
  3. Click "Save"
  4. Verify error message: "Business unit with this name already exists"
  5. Verify business unit is not created

Scenario 3: Edit Business Unit

  1. Navigate to business units list
  2. Click "Edit" on a business unit
  3. Modify description
  4. Click "Save"
  5. Verify success notification
  6. Verify changes are reflected in detail view

Scenario 4: Delete Business Unit

  1. Navigate to business units list
  2. Click "Delete" on a business unit
  3. Confirm deletion in dialog
  4. Verify success notification
  5. Verify business unit is removed from list

Scenario 5: Search Business Units

  1. Navigate to business units list
  2. Enter search query: "digital"
  3. Wait for debounce (300ms)
  4. Verify filtered results contain only matching business units
  5. Clear search
  6. Verify all business units are shown again

Scenario 6: Pagination

  1. Create 25+ business units (if not exists)
  2. Navigate to business units list
  3. Verify only 20 items shown on page 1
  4. Click "Next page"
  5. Verify remaining items shown on page 2
  6. Click "Previous page"
  7. Verify back to page 1

Definition of Done

  • All backend tasks completed
  • All frontend tasks completed
  • All acceptance criteria met
  • All tests passing (unit, integration, E2E)
  • Code reviewed and approved
  • API documented in Swagger
  • User can perform all CRUD operations via UI
  • Demo conducted successfully
  • Code merged to main branch

Technical Debt & Future Improvements

Known Limitations

  • No hierarchical business units (flat structure only)
  • No business unit deactivation (only hard delete)
  • No audit trail for changes
  • No bulk operations

Future Enhancements

  • Add parent-child relationships between business units
  • Implement soft delete with deactivation flag
  • Add audit logging for business unit changes
  • Add bulk import from CSV/Excel
  • Add business unit-specific settings
  • Implement business unit archiving

Dependencies & Blockers

Dependencies

  • Story 0 (Foundation) must be complete

Potential Blockers

  • None identified

API Specification

Endpoints

GET /api/business-units

Description: List all business units
Query Parameters:

  • page (default: 0)
  • size (default: 20)
  • sort (default: name,asc)

Response: 200 OK

{
  "content": [
    {
      "id": "uuid",
      "name": "Digital Services",
      "description": "Digital transformation initiatives",
      "createdAt": "2026-02-01T10:00:00Z",
      "updatedAt": "2026-02-01T10:00:00Z"
    }
  ],
  "pageable": {
    "pageNumber": 0,
    "pageSize": 20,
    "sort": { "sorted": true, "unsorted": false }
  },
  "totalElements": 5,
  "totalPages": 1
}

GET /api/business-units/search

Description: Search business units by name
Query Parameters:

  • q (search query)
  • page, size, sort

Response: Same as GET /api/business-units

GET /api/business-units/{id}

Description: Get business unit by ID
Response: 200 OK

{
  "id": "uuid",
  "name": "Digital Services",
  "description": "Digital transformation initiatives",
  "createdAt": "2026-02-01T10:00:00Z",
  "updatedAt": "2026-02-01T10:00:00Z"
}

Error: 404 Not Found if business unit doesn't exist

POST /api/business-units

Description: Create new business unit
Request Body:

{
  "name": "Digital Services",
  "description": "Digital transformation initiatives"
}

Response: 201 Created

{
  "id": "uuid",
  "name": "Digital Services",
  "description": "Digital transformation initiatives",
  "createdAt": "2026-02-01T10:00:00Z",
  "updatedAt": "2026-02-01T10:00:00Z"
}

Errors:

  • 400 Bad Request if name is duplicate or validation fails
  • 401 Unauthorized if not authenticated

PUT /api/business-units/{id}

Description: Update business unit
Request Body:

{
  "name": "Digital Services",
  "description": "Updated description"
}

Response: 200 OK (same format as POST) Errors:

  • 404 Not Found if business unit doesn't exist
  • 400 Bad Request if validation fails

DELETE /api/business-units/{id}

Description: Delete business unit
Response: 204 No Content
Error: 404 Not Found if business unit doesn't exist


Story Status: Ready for Development
Story Created: February 2026
Estimated Completion: 3-5 days from start