@startuml
title Scholarship Application System
left to right direction
scale 2
package entities {
class User {
- userId: long
- username: String
- password: String
- role: String
+ getUserId(): long
+ getUsername(): String
+ getPassword(): String
+ getRole(): String
+ setUsername(name: String): void
+ setPassword(password: String): void
+ setRole(role: String): void
}
class Profile {
- profileId: int
- userId: long
- name: String
- gpa: Double
- major: String
- enrollmentStatus: String
- needsFinancialAid: Boolean
- state: String
- ethnicity: String
- careerGoals: String
- interests: String
+ getters / setters for all fields
}
class Scholarship {
- scholarshipId: int
- name: String
- description: String
- amount: Double
- deadline: LocalDate
- eligibilityCriteria: String
- applicationUrl: String
- fieldOfStudy: String
- state: String
- sourceApi: String
+ getters / setters for all fields
}
class Application {
- applicationId: int
- user: User
- scholarship: Scholarship
- status: ApplicationStatus
- savedDate: LocalDate
- submittedDate: LocalDate
- deadlineAlert: LocalDate
- notes: String
+ getters / setters for all fields
}
enum ApplicationStatus {
SAVED
IN_PROGRESS
SUBMITTED
AWARDED
REJECTED
}
}
User "1" -- "1" Profile : has
User "1" -- "0.." Application : tracks
Scholarship "1" -- "0.." Application : receives
Application --> ApplicationStatus : has an
package repositories {
note "All repositories extend JpaRepository and use SpringBoot's @repository annotation" as N
interface UserRepository {
+ findByUsername(username: String): User
}
interface ProfileRepository {
+ findByUserId(userId: long): Profile
+ deleteByUserId(userId: long): void
}
interface ScholarshipRepository {
+ findByFieldOfStudy(field: String): List<Scholarship>
+ findByState(state: String): List<Scholarship>
}
interface ApplicationRepository {
+ findByUserId(userId: long): List<Application>
+ findByStatus(status: ApplicationStatus): List<Application>
}
JpaRepository <|-- UserRepository : is a
JpaRepository <|-- ProfileRepository : is a
JpaRepository <|-- ScholarshipRepository : is a
JpaRepository <|-- ApplicationRepository : is a
UserRepository ..> User
ProfileRepository ..> Profile
ScholarshipRepository ..> Scholarship
ApplicationRepository ..> Application
}
package services {
class UserService {
- userRepository: UserRepository
+ register(username: String, password: String): User
+ login(username: String, password: String): User
+ deleteAccount(userId: long): void
+ getUserById(userId: long): User
}
class ProfileService {
- profileRepository: ProfileRepository
+ createProfile(profile: Profile): Profile
+ updateProfile(profileId: long, profile: Profile): Profile
+ getProfile(userId: long): Profile
+ deleteProfile(userId: long): void
}
class ScholarshipService {
- scholarshipRepository: ScholarshipRepository
- externalApiClient: ExternalApiClient
+ fetchFromApi(): List<Scholarship>
+ searchScholarships(query: String): List<Scholarship>
+ filterByField(field: String): List<Scholarship>
+ filterByState(state: String): List<Scholarship>
}
class ApplicationService {
- applicationRepository: ApplicationRepository
+ saveScholarship(userId: long, scholarshipId: long): Application
+ updateStatus(applicationId: long, status: ApplicationStatus): Application
+ getTrackedApplications(userId: long): List<Application>
+ deleteTracked(applicationId: long): void
}
class MatchingService {
- profileRepository: ProfileRepository
- scholarshipRepository: ScholarshipRepository
- aiClient: AIClient
+ getMatchesForUser(userId: long): List<Scholarship>
+ buildPrompt(profile: Profile, scholarships: List<Scholarship>): String
+ rankByDeadlinePriority(matches: List<Scholarship>): List<Scholarship>
+ refreshMatchesForUser(userId: long): void
}
class AIClient {
- apiKey: String
- apiUrl: String
- restTemplate: RestTemplate
+ getCompletion(prompt: String): String
}
UserService --> UserRepository
ProfileService --> ProfileRepository
ScholarshipService --> ScholarshipRepository
ApplicationService --> ApplicationRepository
MatchingService --> ProfileRepository
MatchingService --> ScholarshipRepository
MatchingService --> AIClient : uses
}
package controllers {
class UserController {
- userService: UserService
+ register(): ResponseEntity
+ login(): ResponseEntity
+ deleteAccount(): ResponseEntity
+ getUser(): ResponseEntity
}
class ProfileController {
- profileService: ProfileService
+ createProfile(): ResponseEntity
+ updateProfile(): ResponseEntity
+ getProfile(): ResponseEntity
+ deleteProfile(): ResponseEntity
}
class ScholarshipController {
- scholarshipService: ScholarshipService
+ getAllScholarships(): ResponseEntity
+ getScholarshipById(): ResponseEntity
+ searchScholarships(): ResponseEntity
+ fetchFromApi(): ResponseEntity
}
class ApplicationController {
- applicationService: ApplicationService
+ saveScholarship(): ResponseEntity
+ updateStatus(): ResponseEntity
+ getTrackedApplications(): ResponseEntity
+ deleteTracked(): ResponseEntity
}
class MatchController {
- matchingService: MatchingService
+ getMatches(): ResponseEntity
+ refreshMatches(): ResponseEntity
}
UserController --> UserService
ProfileController --> ProfileService
ScholarshipController --> ScholarshipService
ApplicationController --> ApplicationService
MatchController --> MatchingService
}
@enduml
@startuml
title Scholarship Application System
left to right direction
scale 2
package entities {
class User {
- userId: long
- username: String
- password: String
- role: String
+ getUserId(): long
+ getUsername(): String
+ getPassword(): String
+ getRole(): String
+ setUsername(name: String): void
+ setPassword(password: String): void
+ setRole(role: String): void
}
}
User "1" -- "1" Profile : has
User "1" -- "0.." Application : tracks
Scholarship "1" -- "0.." Application : receives
Application --> ApplicationStatus : has an
package repositories {
note "All repositories extend JpaRepository and use SpringBoot's @repository annotation" as N
interface UserRepository {
+ findByUsername(username: String): User
}
}
package services {
}
package controllers {
class UserController {
- userService: UserService
+ register(): ResponseEntity
+ login(): ResponseEntity
+ deleteAccount(): ResponseEntity
+ getUser(): ResponseEntity
}
}
@enduml