169 lines
5.2 KiB
Markdown
169 lines
5.2 KiB
Markdown
# SavingsProduct Custom Fields - Implementation Summary
|
|
|
|
## ✅ Completed Changes
|
|
|
|
### 1. **Validator Updates**
|
|
**File:** `fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsProductDataValidator.java`
|
|
|
|
**Changes:**
|
|
- Added `balanceFrequency` to `SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS` whitelist
|
|
- Added `accountClosedZeroBalanceInDayClosing` to `SAVINGS_PRODUCT_REQUEST_DATA_PARAMETERS` whitelist
|
|
|
|
### 2. **API Constants**
|
|
**File:** `fineract-core/src/main/java/org/apache/fineract/portfolio/savings/SavingsApiConstants.java`
|
|
|
|
**Changes:**
|
|
```java
|
|
public static final String balanceFrequencyParamName = "balanceFrequency";
|
|
public static final String accountClosedZeroBalanceInDayClosingParamName = "accountClosedZeroBalanceInDayClosing";
|
|
```
|
|
|
|
### 3. **Entity (Domain Model)**
|
|
**File:** `fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsProduct.java`
|
|
|
|
**Changes:**
|
|
- Added field: `@Column(name = "balance_frequency", length = 50) private String balanceFrequency;`
|
|
- Added field: `@Column(name = "account_closed_zero_balance_in_day_closing") private Boolean accountClosedZeroBalanceInDayClosing = false;`
|
|
- Added getters: `getBalanceFrequency()`, `getAccountClosedZeroBalanceInDayClosing()`
|
|
- Added setters: `setBalanceFrequency()`, `setAccountClosedZeroBalanceInDayClosing()`
|
|
- Added update logic in `update()` method to handle changes to these fields
|
|
|
|
### 4. **Assembler**
|
|
**File:** `fineract-savings/src/main/java/org/apache/fineract/portfolio/savings/domain/SavingsProductAssembler.java`
|
|
|
|
**Changes:**
|
|
```java
|
|
if (command.parameterExists("balanceFrequency")) {
|
|
product.setBalanceFrequency(command.stringValueOfParameterNamed("balanceFrequency"));
|
|
}
|
|
if (command.parameterExists("accountClosedZeroBalanceInDayClosing")) {
|
|
product.setAccountClosedZeroBalanceInDayClosing(command.booleanObjectValueOfParameterNamed("accountClosedZeroBalanceInDayClosing"));
|
|
}
|
|
```
|
|
|
|
### 5. **DTO (Data Transfer Object)**
|
|
**File:** `fineract-core/src/main/java/org/apache/fineract/portfolio/savings/data/SavingsProductData.java`
|
|
|
|
**Changes:**
|
|
```java
|
|
@Getter @Setter private String balanceFrequency;
|
|
@Getter @Setter private Boolean accountClosedZeroBalanceInDayClosing;
|
|
```
|
|
|
|
### 6. **Read Platform Service**
|
|
**File:** `fineract-provider/src/main/java/org/apache/fineract/portfolio/savings/service/SavingsProductReadPlatformServiceImpl.java`
|
|
|
|
**Changes:**
|
|
- SQL Query: Added `sp.balance_frequency as balanceFrequency`
|
|
- SQL Query: Added `sp.account_closed_zero_balance_in_day_closing as accountClosedZeroBalanceInDayClosing`
|
|
- ResultSet mapping: Added extraction of both fields
|
|
|
|
### 7. **Database Migration**
|
|
**File:** `database_migration_add_custom_fields.sql`
|
|
|
|
```sql
|
|
ALTER TABLE m_savings_product
|
|
ADD COLUMN balance_frequency VARCHAR(50) DEFAULT NULL,
|
|
ADD COLUMN account_closed_zero_balance_in_day_closing BOOLEAN DEFAULT FALSE;
|
|
```
|
|
|
|
---
|
|
|
|
## 📋 What These Fields Do
|
|
|
|
### **balanceFrequency** (String)
|
|
- **Purpose:** Defines how often balance is calculated/checked
|
|
- **Example Values:** "Daily", "Monthly", "Quarterly", "Yearly"
|
|
- **Database Column:** `m_savings_product.balance_frequency`
|
|
- **Type:** VARCHAR(50)
|
|
|
|
### **accountClosedZeroBalanceInDayClosing** (Boolean)
|
|
- **Purpose:** Flag to automatically close accounts when balance reaches zero at day end
|
|
- **Example Values:** `true` or `false`
|
|
- **Default:** `false`
|
|
- **Database Column:** `m_savings_product.account_closed_zero_balance_in_day_closing`
|
|
- **Type:** BOOLEAN
|
|
|
|
---
|
|
|
|
## 🎯 API Usage
|
|
|
|
### **POST /v1/savingsproducts** (Create)
|
|
```json
|
|
{
|
|
"name": "Saving Product",
|
|
"shortName": "SD22",
|
|
// ... other fields ...
|
|
"balanceFrequency": "Monthly",
|
|
"accountClosedZeroBalanceInDayClosing": true,
|
|
// ... rest of fields ...
|
|
}
|
|
```
|
|
|
|
### **GET /v1/savingsproducts/{productId}** (Read)
|
|
Response will include:
|
|
```json
|
|
{
|
|
"id": 1,
|
|
"name": "Saving Product",
|
|
// ... other fields ...
|
|
"balanceFrequency": "Monthly",
|
|
"accountClosedZeroBalanceInDayClosing": true,
|
|
// ... rest of fields ...
|
|
}
|
|
```
|
|
|
|
### **PUT /v1/savingsproducts/{productId}** (Update)
|
|
```json
|
|
{
|
|
"balanceFrequency": "Quarterly",
|
|
"accountClosedZeroBalanceInDayClosing": false
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## 🗄️ Database Migration Steps
|
|
|
|
Run this SQL script to add the columns:
|
|
|
|
```bash
|
|
mysql -u root -p your_database < database_migration_add_custom_fields.sql
|
|
```
|
|
|
|
Or manually execute:
|
|
```sql
|
|
ALTER TABLE m_savings_product
|
|
ADD COLUMN balance_frequency VARCHAR(50) DEFAULT NULL,
|
|
ADD COLUMN account_closed_zero_balance_in_day_closing BOOLEAN DEFAULT FALSE;
|
|
```
|
|
|
|
---
|
|
|
|
## ✅ Validation
|
|
|
|
The fields are now:
|
|
- ✅ **Accepted** in CREATE request (POST)
|
|
- ✅ **Saved** to database
|
|
- ✅ **Returned** in GET response
|
|
- ✅ **Updatable** via PUT request
|
|
- ✅ **Validated** (no longer rejected as unsupported)
|
|
|
|
---
|
|
|
|
## 🚀 Next Steps
|
|
|
|
1. **Run Database Migration:** Execute the SQL script
|
|
2. **Rebuild Application:** `./gradlew clean build`
|
|
3. **Restart Server:** Apply the changes
|
|
4. **Test API:** Use your payload to create a savings product
|
|
|
|
---
|
|
|
|
## 📝 Notes
|
|
|
|
- Both fields are **optional** (nullable)
|
|
- `balanceFrequency` accepts any string value (you can add validation later if needed)
|
|
- `accountClosedZeroBalanceInDayClosing` defaults to `false` if not provided
|
|
- Both fields support **partial updates** (you can update just one of them)
|