17 KiB
Story 2: Application Management
Story Overview
As a application manager
I want to manage applications in the system
So that I can track all applications and their lifecycle status
Story Type: Feature (Core Domain)
Priority: Highest
Estimated Effort: 5-7 days
Dependencies: Story 1 (Business Units)
Business Value
Applications are the central entity in LDPv2. This story enables:
- Complete application inventory
- Lifecycle status tracking (IDEA → IN_DEVELOPMENT → IN_SERVICE → MAINTENANCE → DECOMMISSIONED)
- Business unit ownership
- Foundation for deployment tracking (Story 6)
- End-of-life and support tracking
Scope
In Scope
✅ Application CRUD operations
✅ Lifecycle status management
✅ Business unit association
✅ End-of-life and end-of-support date tracking
✅ Application search and filtering
✅ Status-based filtering
Out of Scope
❌ Version management (Story 5)
❌ Deployment tracking (Story 6)
❌ Contact/stakeholder management (Story 3)
❌ SLA management (Phase 2)
❌ Technical documentation (Phase 2)
❌ External dependencies (Phase 2)
Technical Implementation
Backend Tasks
1. Database Migration
- Create Liquibase migration:
004-create-application-tables.xml - Create
applicationtable:- id (UUID, PK) - name (VARCHAR(255), not null) - description (TEXT, nullable) - status (VARCHAR(50), not null) -- IDEA, IN_DEVELOPMENT, IN_SERVICE, MAINTENANCE, DECOMMISSIONED - business_unit_id (UUID, FK to business_unit, not null) - end_of_life_date (DATE, nullable) - end_of_support_date (DATE, nullable) - created_at (TIMESTAMP, not null) - updated_at (TIMESTAMP, not null) - Add indexes:
idx_application_statuson statusidx_application_business_uniton business_unit_ididx_application_nameon name (for search)
- Add foreign key constraint:
business_unit_id→business_unit(id) - Insert sample data (5-10 applications with various statuses)
2. Enum
- Create
ApplicationStatusenum:public enum ApplicationStatus { IDEA("Idea"), IN_DEVELOPMENT("In Development"), IN_SERVICE("In Service"), MAINTENANCE("Maintenance"), DECOMMISSIONED("Decommissioned"); private final String displayName; // Constructor, getter }
3. JPA Entity
- Create
Applicationentity extendingBaseEntity:@Entity @Table(name = "application") public class Application extends BaseEntity { @Column(nullable = false) private String name; @Column(columnDefinition = "TEXT") private String description; @Enumerated(EnumType.STRING) @Column(nullable = false, length = 50) private ApplicationStatus status; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn(name = "business_unit_id", nullable = false) private BusinessUnit businessUnit; @Column(name = "end_of_life_date") private LocalDate endOfLifeDate; @Column(name = "end_of_support_date") private LocalDate endOfSupportDate; // Getters, setters, constructors }
4. Repository Layer
- Create
ApplicationRepository:public interface ApplicationRepository extends JpaRepository<Application, UUID> { Page<Application> findByStatus(ApplicationStatus status, Pageable pageable); Page<Application> findByBusinessUnitId(UUID businessUnitId, Pageable pageable); Page<Application> findByNameContainingIgnoreCase(String name, Pageable pageable); Page<Application> findByStatusAndBusinessUnitId(ApplicationStatus status, UUID businessUnitId, Pageable pageable); @Query("SELECT a FROM Application a WHERE " + "(:status IS NULL OR a.status = :status) AND " + "(:businessUnitId IS NULL OR a.businessUnit.id = :businessUnitId) AND " + "(:name IS NULL OR LOWER(a.name) LIKE LOWER(CONCAT('%', :name, '%')))") Page<Application> search( @Param("status") ApplicationStatus status, @Param("businessUnitId") UUID businessUnitId, @Param("name") String name, Pageable pageable ); }
5. DTOs
- Create
CreateApplicationRequest:name(required, max 255 chars)description(optional)status(required, default: IDEA)businessUnitId(required, UUID)endOfLifeDate(optional, LocalDate)endOfSupportDate(optional, LocalDate)
- Create
UpdateApplicationRequest:- All fields optional (partial update support)
- Create
ApplicationResponse:id,name,description,status,businessUnit(summary),endOfLifeDate,endOfSupportDate,createdAt,updatedAt
- Create
ApplicationSummaryResponse(for lists):id,name,status,businessUnitName
- Create
BusinessUnitSummaryDto:id,name
6. Service Layer
- Create
ApplicationServicewith methods:ApplicationResponse create(CreateApplicationRequest request); ApplicationResponse update(UUID id, UpdateApplicationRequest request); ApplicationResponse findById(UUID id); Page<ApplicationResponse> findAll(Pageable pageable); Page<ApplicationResponse> search(ApplicationStatus status, UUID businessUnitId, String name, Pageable pageable); Page<ApplicationResponse> findByStatus(ApplicationStatus status, Pageable pageable); Page<ApplicationResponse> findByBusinessUnit(UUID businessUnitId, Pageable pageable); void delete(UUID id); ApplicationResponse updateStatus(UUID id, ApplicationStatus newStatus); - Implement business logic:
- Validate business unit exists on create/update
- Validate end-of-support date is before end-of-life date
- Throw exceptions for invalid states
- Map entities to DTOs (consider using MapStruct or ModelMapper)
7. Controller Layer
- Create
ApplicationControllerwith endpoints:GET /api/applications - List all (with filters) GET /api/applications/search - Advanced search GET /api/applications/{id} - Get by ID POST /api/applications - Create new PUT /api/applications/{id} - Update PATCH /api/applications/{id}/status - Update status only DELETE /api/applications/{id} - Delete GET /api/applications/by-status/{status} - Filter by status GET /api/applications/by-business-unit/{businessUnitId} - Filter by BU - Add query parameters for filtering:
status: Filter by statusbusinessUnitId: Filter by business unitname: Search by namepage,size,sort: Pagination
- Add validation annotations
- Add Swagger/OpenAPI annotations
- Add security: require authentication
8. Testing
- Unit tests for
ApplicationService:- Test create application
- Test create with invalid business unit (should fail)
- Test update application
- Test update status
- Test search with various filters
- Test validation (end-of-support before end-of-life)
- Integration tests for
ApplicationController:- Test full CRUD flow
- Test filtering by status
- Test filtering by business unit
- Test search functionality
- Test pagination and sorting
- Test error cases (404, 400)
- Test coverage > 80%
Frontend Tasks
1. Models
- Create
application.model.ts:export enum ApplicationStatus { IDEA = 'IDEA', IN_DEVELOPMENT = 'IN_DEVELOPMENT', IN_SERVICE = 'IN_SERVICE', MAINTENANCE = 'MAINTENANCE', DECOMMISSIONED = 'DECOMMISSIONED' } export interface Application { id: string; name: string; description?: string; status: ApplicationStatus; businessUnit: { id: string; name: string }; endOfLifeDate?: Date; endOfSupportDate?: Date; createdAt: Date; updatedAt: Date; } export interface CreateApplicationRequest { name: string; description?: string; status: ApplicationStatus; businessUnitId: string; endOfLifeDate?: Date; endOfSupportDate?: Date; } export interface UpdateApplicationRequest { name?: string; description?: string; status?: ApplicationStatus; businessUnitId?: string; endOfLifeDate?: Date; endOfSupportDate?: Date; }
2. Service
- Create
application.service.ts:@Injectable({ providedIn: 'root' }) export class ApplicationService { getApplications(filters?, page?, size?, sort?): Observable<Page<Application>> searchApplications(criteria): Observable<Page<Application>> getApplication(id): Observable<Application> createApplication(data): Observable<Application> updateApplication(id, data): Observable<Application> updateStatus(id, status): Observable<Application> deleteApplication(id): Observable<void> }
3. Components
ApplicationListComponent
- Create component with template and styles
- Features:
- Table view with columns: Name, Status, Business Unit, End of Life, Actions
- Status badge with color coding:
- IDEA: blue
- IN_DEVELOPMENT: yellow
- IN_SERVICE: green
- MAINTENANCE: orange
- DECOMMISSIONED: gray
- Filters:
- Status dropdown (All, IDEA, IN_DEVELOPMENT, IN_SERVICE, MAINTENANCE, DECOMMISSIONED)
- Business unit dropdown (All + list of BUs)
- Search by name
- Pagination controls (20 items per page)
- Sort by name, status, created date
- "Create New Application" button
- Actions per row: View, Edit, Delete, Change Status
- Implement logic:
- Load applications on init
- Apply filters reactively
- Handle pagination and sorting
- Handle search with debounce
- Quick status change dropdown
- Navigate to detail/form pages
- Handle delete with confirmation
ApplicationDetailComponent
- Create component with template and styles
- Features:
- Display all application details
- Status badge (colored)
- Business unit link (navigate to BU detail)
- Show end-of-life and end-of-support dates (highlight if approaching)
- "Edit" button
- "Change Status" dropdown
- "Delete" button
- "Back to List" button
- Tabs (for future: Versions, Deployments, Contacts)
- Load application by ID from route params
- Reload on status change
ApplicationFormComponent
- Create component with template and styles
- Reactive form with fields:
- Name (required, max 255 chars)
- Description (optional, textarea)
- Status (required, dropdown)
- Business Unit (required, dropdown - load from API)
- End of Life Date (optional, date picker)
- End of Support Date (optional, date picker)
- Form validation:
- Name required
- Status required
- Business unit required
- End of support date must be before end of life date
- Show validation errors
- Support both create and edit modes
- Handle form submission
- "Cancel" button
4. Shared Components
- Create
StatusBadgeComponent:- Input: status (ApplicationStatus)
- Display colored badge based on status
- Reusable across application views
5. Routing
- Add routes:
{ path: 'applications', canActivate: [AuthGuard], children: [ { path: '', component: ApplicationListComponent }, { path: 'new', component: ApplicationFormComponent }, { path: ':id', component: ApplicationDetailComponent }, { path: ':id/edit', component: ApplicationFormComponent } ] }
6. Navigation
- Add "Applications" link to header/sidebar (prominent position)
7. Testing
- Unit tests for
ApplicationService - Component tests for
ApplicationListComponent:- Test rendering
- Test filters (status, business unit, search)
- Test pagination
- Test status change
- Component tests for
ApplicationFormComponent:- Test form validation
- Test date validation (end-of-support before end-of-life)
- Test create and edit modes
- E2E tests:
- Create application flow
- Edit application flow
- Change status flow
- Filter and search flow
- Test coverage > 70%
Acceptance Criteria
Backend
- Application can be created with all required fields
- Application creation fails if business unit doesn't exist
- Application can be updated (partial updates supported)
- Application status can be updated independently
- Application can be deleted
- Applications can be listed with pagination
- Applications can be filtered by status
- Applications can be filtered by business unit
- Applications can be searched by name
- Advanced search combines multiple filters
- End-of-support date validation (must be before end-of-life)
- All endpoints authenticated
- API documented in Swagger
Frontend
- User can view list of all applications
- List shows application name, status, business unit
- Status is displayed with colored badge
- User can filter applications by status
- User can filter applications by business unit
- User can search applications by name
- Filters work together (combined)
- List supports pagination and sorting
- User can create new application
- Form validates all required fields
- Form validates date logic (end-of-support before end-of-life)
- User can view application details
- User can edit existing application
- User can change application status from list or detail view
- User can delete application (with confirmation)
- Approaching end-of-life dates are highlighted
- Success/error notifications displayed
- Navigation is intuitive
Testing
- Backend tests pass (>80% coverage)
- Frontend tests pass (>70% coverage)
- E2E tests pass
Testing Scenarios
Scenario 1: Create Application
- Navigate to applications list
- Click "Create New Application"
- Fill in form:
- Name: "Customer Portal"
- Description: "External customer-facing portal"
- Status: IN_DEVELOPMENT
- Business Unit: Select "Digital Services"
- End of Support: 2028-12-31
- End of Life: 2030-12-31
- Click "Save"
- Verify success notification
- Verify redirect to application list
- Verify new application appears with IN_DEVELOPMENT badge (yellow)
Scenario 2: Filter Applications
- Navigate to applications list
- Select status filter: "IN_SERVICE"
- Verify only IN_SERVICE applications shown
- Select business unit filter: "Digital Services"
- Verify only IN_SERVICE applications from Digital Services shown
- Clear filters
- Verify all applications shown
Scenario 3: Search Applications
- Navigate to applications list
- Enter search query: "portal"
- Wait for debounce
- Verify results contain only matching applications
- Clear search
- Verify all applications shown
Scenario 4: Change Application Status
- Navigate to applications list
- Click "Change Status" dropdown on an application
- Select new status: "IN_SERVICE"
- Verify success notification
- Verify status badge updated to green
- Refresh page
- Verify status persisted
Scenario 5: Edit Application
- Navigate to application detail page
- Click "Edit"
- Modify description and end-of-life date
- Click "Save"
- Verify success notification
- Verify changes reflected in detail view
Scenario 6: Date Validation
- Navigate to create/edit application form
- Set End of Support: 2030-12-31
- Set End of Life: 2028-12-31 (before end-of-support)
- Attempt to save
- Verify validation error: "End of support must be before end of life"
- Correct dates
- Verify form can be saved
Scenario 7: Delete Application
- Navigate to application detail page
- Click "Delete"
- Confirm deletion
- Verify success notification
- Verify redirect to application list
- Verify application removed from list
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 operations via UI
- Demo conducted successfully
- Code merged to main branch
Technical Debt & Future Improvements
Known Limitations
- No application archiving (only hard delete)
- No status change audit trail
- No automated end-of-life notifications
- No application tags/categories
Future Enhancements
- Implement soft delete with archiving
- Add status change history/audit log
- Add automated alerts for approaching end-of-life
- Add tagging system for categorization
- Add application relationships (depends on, integrates with)
- Add bulk status updates
- Add export to Excel/CSV
Dependencies & Blockers
Dependencies
- Story 1 (Business Units) must be complete
Potential Blockers
- None identified
Story Status: Ready for Development
Story Created: February 2026
Estimated Completion: 5-7 days from start