Database Schema and Entities
Relevant source files
The following files were used as context for generating this wiki page:- src/main/java/com/paymaster/backend/domain/entity/Customer.java
- src/main/java/com/paymaster/backend/domain/entity/Contract.java
- src/main/java/com/paymaster/backend/domain/entity/BaseEntity.java
- src/main/java/com/paymaster/backend/domain/service/ContractService.java
- pom.xml
- src/main/java/com/paymaster/backend/presentation/controller/HomeController.java
The data persistence layer of the PayMaster application is built using Spring Data JPA. It defines the core business entities, their relationships, and how they are mapped to a relational database. The primary entities are Customer, Contract, and Installment, which together model the installment management system's domain.
For development and runtime, the application is configured to use an in-memory H2 database, as specified in the pom.xml. All entities inherit from a BaseEntity class, which provides common fields for primary key and auditing timestamps.
Sources: pom.xml:39-42, src/main/java/com/paymaster/backend/domain/entity/BaseEntity.java
Entity Relationship Diagram
The core data model consists of three main entities: Customer, Contract, and Installment. The following diagram illustrates the relationships between them.
This diagram shows that a CUSTOMER can have one or more CONTRACTs. Each CONTRACT must belong to exactly one CUSTOMER and is composed of one or more INSTALLMENTs.
Sources: src/main/java/com/paymaster/backend/domain/entity/Customer.java:94-96, src/main/java/com/paymaster/backend/domain/entity/Contract.java:146-152
BaseEntity
All persistent entities in the application extend the BaseEntity abstract class. This class provides common fields for all database tables.
Sources: src/main/java/com/paymaster/backend/domain/entity/BaseEntity.java:14-16
Fields
| Field | Type | Description |
|---|---|---|
id | Long | The primary key for the entity, generated automatically (GenerationType.IDENTITY). |
createdAt | LocalDateTime | Timestamp for when the entity was created. Automatically set and not updatable. |
updatedAt | LocalDateTime | Timestamp for the last time the entity was updated. Automatically updated. |
Sources: src/main/java/com/paymaster/backend/domain/entity/BaseEntity.java:22-38
Customer Entity
The Customer entity stores all personal and contact information for a customer. It is mapped to the customers table.
Sources: src/main/java/com/paymaster/backend/domain/entity/Customer.java:16-18
Fields
| Field | Type | Constraints | Description |
|---|---|---|---|
fullName | String | @NotBlank, Size(min=2, max=100) | Customer's full name. |
nationalCode | String | @NotBlank, @Pattern("^\\d{10}$"), unique=true | 10-digit unique national identification code. |
mobile | String | @NotBlank, @Pattern("^09\\d{9}$") | Customer's mobile number. |
phone | String | - | Customer's landline number. |
email | String | @Email | Customer's email address. |
address | String | Size(max=500) | Customer's physical address. |
postalCode | String | @Pattern("^\\d{10}$") | 10-digit postal code. |
status | CustomerStatus | @Enumerated(EnumType.STRING), default=ACTIVE | The status of the customer (e.g., ACTIVE, INACTIVE). |
notes | String | Size(max=1000) | Internal notes about the customer. |
contracts | List<Contract> | @OneToMany(mappedBy="customer", cascade=ALL, orphanRemoval=true) | List of contracts associated with the customer. |
Sources: src/main/java/com/paymaster/backend/domain/entity/Customer.java:25-96
Helper Methods
getActiveContractsCount(): Returns the count of contracts withACTIVEstatus.getTotalDebt(): Calculates the sum of the remaining amounts for all active contracts.
Sources: src/main/java/com/paymaster/backend/domain/entity/Customer.java:103-116
Contract Entity
The Contract entity represents a financial agreement with a customer, including loan details, interest, and installment information. It is mapped to the contracts table.
Sources: src/main/java/com/paymaster/backend/domain/entity/Contract.java:16-18
Fields
| Field | Type | Constraints | Description |
|---|---|---|---|
contractNumber | String | @NotBlank, Size(max=20), unique=true | A unique identifier for the contract. |
principalAmount | Long | @NotNull, @Min(1000000) | The principal amount of the loan. |
interestRate | Double | @NotNull, @DecimalMin("0.0"), @DecimalMax("100.0") | The annual interest rate in percent. |
interestAmount | Long | - | The total calculated interest amount. |
totalAmount | Long | @NotNull | Total amount to be paid (principal + interest). |
installmentCount | Integer | @NotNull, @Min(1), @Max(60) | The total number of installments. |
installmentAmount | Long | - | The amount for each installment. |
startDate | LocalDate | @NotNull | The start date of the contract. |
endDate | LocalDate | - | The calculated end date of the contract. |
penaltyRate | Double | @DecimalMin("0.0"), default=0.5 | The daily penalty rate for late payments. |
status | ContractStatus | @Enumerated(EnumType.STRING), default=DRAFT | The current status of the contract (e.g., ACTIVE, COMPLETED). |
description | String | Size(max=500) | Optional description for the contract. |
customer | Customer | @ManyToOne(fetch=LAZY), @JoinColumn(name="customer_id"), @NotNull | The customer associated with the contract. |
installments | List<Installment> | @OneToMany(mappedBy="contract", cascade=ALL, orphanRemoval=true) | List of installments for this contract. |
Sources: src/main/java/com/paymaster/backend/domain/entity/Contract.java:25-152
Helper Methods
getRemainingAmount(): Calculates the total amount minus the sum of paid amounts from all installments.getPaidInstallmentsCount(): Returns the count of installments marked asPAID.getProgressPercentage(): Calculates the payment progress as a percentage of thetotalAmount.
Sources: src/main/java/com/paymaster/backend/domain/entity/Contract.java:157-183
Installment Entity
The Installment entity represents a single payment installment for a contract. The definition of this entity is inferred from its usage in Contract.java, ContractService.java, and HomeController.java, as the source file was not provided. It is mapped to the installments table.
Inferred Fields
| Field | Type | Description |
|---|---|---|
contract | Contract | The parent contract this installment belongs to (@ManyToOne). |
installmentNumber | Integer | The sequence number of the installment (e.g., 1, 2, 3...). |
amount | Long | The due amount for this installment. |
principalPortion | Long | The portion of the amount that covers the principal. |
interestPortion | Long | The portion of the amount that covers the interest. |
dueDate | LocalDate | The date by which this installment must be paid. |
status | InstallmentStatus | The current status (PENDING, PAID, OVERDUE). |
paidAmount | Long | The actual amount paid by the customer for this installment. |
paymentDate | LocalDate | The date the payment was made. |
paymentMethod | PaymentMethod | The method used for payment (e.g., CASH, CARD). |
receiptNumber | String | An optional receipt or transaction number for the payment. |
notes | String | Optional notes related to the payment. |
Sources: src/main/java/com/paymaster/backend/domain/service/ContractService.java:204-222, src/main/java/com/paymaster/backend/presentation/controller/HomeController.java:312-318
Relationships and Cascade Operations
The entities are interconnected with JPA relationships that define how they interact and how database operations are cascaded.
- Customer to Contract: A
One-to-Manyrelationship exists fromCustomertoContract. Thecascade = CascadeType.ALLandorphanRemoval = truesettings ensure that when aCustomeris deleted, all of their associatedContractentities are also deleted. - Contract to Installment: A
One-to-Manyrelationship exists fromContracttoInstallment, also withCascadeType.ALLandorphanRemoval = true. This means creating aContractand itsInstallmentlist will persist all of them, and deleting aContractwill remove all its associated installments.
Sources: src/main/java/com/paymaster/backend/domain/entity/Customer.java:94-96, src/main/java/com/paymaster/backend/domain/entity/Contract.java:149-152