Skip to content

Commit 9249609

Browse files
Naphojuliuspetero
authored andcommitted
feat(CRED-75): Implement Month-End Accrual Journal Entries
1 parent 6a37026 commit 9249609

File tree

13 files changed

+478
-269
lines changed

13 files changed

+478
-269
lines changed

custom/crediblex/build.gradle

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ subprojects {
4545
implementation(project(':fineract-rates'))
4646
implementation(project(':fineract-progressive-loan'))
4747
implementation("org.springframework.boot:spring-boot-starter:${springBootVersion}")
48+
implementation("org.springframework.boot:spring-boot-starter-batch:${springBootVersion}")
49+
implementation("org.springframework.batch:spring-batch-integration:${springBootVersion}"),
50+
4851
compileOnly("org.springframework.boot:spring-boot-autoconfigure:${springBootVersion}")
4952

5053
// Add Spring Data JPA to all modules that need it
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!--
3+
4+
Licensed to the Apache Software Foundation (ASF) under one
5+
or more contributor license agreements. See the NOTICE file
6+
distributed with this work for additional information
7+
regarding copyright ownership. The ASF licenses this file
8+
to you under the Apache License, Version 2.0 (the
9+
"License"); you may not use this file except in compliance
10+
with the License. You may obtain a copy of the License at
11+
12+
http://www.apache.org/licenses/LICENSE-2.0
13+
14+
Unless required by applicable law or agreed to in writing,
15+
software distributed under the License is distributed on an
16+
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17+
KIND, either express or implied. See the License for the
18+
specific language governing permissions and limitations
19+
under the License.
20+
21+
-->
22+
<databaseChangeLog
23+
xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
24+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
25+
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
26+
http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-4.1.xsd">
27+
<changeSet author="CredibleX" id="1">
28+
<preConditions onFail="MARK_RAN">
29+
<not>
30+
<columnExists tableName="m_loan" columnName="is_processed_by_monthly_job"/>
31+
</not>
32+
</preConditions>
33+
<addColumn tableName="m_loan_transaction">
34+
<column name="is_processed_by_monthly_job" type="boolean" defaultValueBoolean="false">
35+
<constraints nullable="false"/>
36+
</column>
37+
</addColumn>
38+
</changeSet>
39+
40+
<changeSet author="CredibleX" id="2">
41+
<preConditions onFail="MARK_RAN" onError="MARK_RAN">
42+
<not>
43+
<tableExists tableName="m_loan_monthly_accrual_job_run_audit"/>
44+
</not>
45+
</preConditions>
46+
<createTable tableName="m_loan_monthly_accrual_job_run_audit">
47+
<column autoIncrement="true" name="id" type="BIGINT">
48+
<constraints nullable="false" primaryKey="true"/>
49+
</column>
50+
<column name="loan_id" type="BIGINT">
51+
<constraints nullable="false"/>
52+
</column>
53+
<column name="accrual_transaction_ids" type="TEXT">
54+
<constraints nullable="false"/>
55+
</column>
56+
<column name="total_interest_accrual_derived" type="DECIMAL(19,6)">
57+
<constraints nullable="false"/>
58+
</column>
59+
<column name="is_posted_to_odoo" type="boolean" defaultValueBoolean="false">
60+
<constraints nullable="false"/>
61+
</column>
62+
<column name="generated_on_date" type="date">
63+
<constraints nullable="false"/>
64+
</column>
65+
<column name="created_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
66+
<column name="created_by" type="BIGINT"/>
67+
<column name="last_modified_on_utc" type="TIMESTAMP WITH TIME ZONE"/>
68+
<column name="last_modified_by" type="BIGINT"/>
69+
</createTable>
70+
</changeSet>
71+
72+
<changeSet author="fineract" id="3">
73+
<insert tableName="job">
74+
<column name="name" value="Generate Loan Monthly Accrual Summations"/>
75+
<column name="display_name" value="Generate Loan Monthly Accrual Summations"/>
76+
<column name="cron_expression" value="0 0 0 L * ?"/>
77+
<column name="create_time" valueDate="${current_datetime}"/>
78+
<column name="task_priority" valueNumeric="10"/>
79+
<column name="group_name"/>
80+
<column name="previous_run_start_time"/>
81+
<column name="job_key" value="Generate Loan Monthly Accrual Summations1 _ DEFAULT"/>
82+
<column name="initializing_errorlog"/>
83+
<column name="is_active" valueBoolean="true"/>
84+
<column name="currently_running" valueBoolean="false"/>
85+
<column name="updates_allowed" valueBoolean="true"/>
86+
<column name="scheduler_group" valueNumeric="0"/>
87+
<column name="is_misfired" valueBoolean="false"/>
88+
<column name="node_id" valueNumeric="1"/>
89+
<column name="is_mismatched_job" valueBoolean="false"/>
90+
</insert>
91+
</changeSet>
92+
</databaseChangeLog>

custom/crediblex/portfolio/accountdetails/src/main/java/com/crediblex/fineract/portfolio/accountdetails/service/CredXAccountDetailsReadPlatformServiceJpaRepositoryImpl.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import org.apache.fineract.portfolio.savings.data.SavingsAccountStatusEnumData;
4949
import org.apache.fineract.portfolio.savings.data.SavingsAccountSubStatusEnumData;
5050
import org.apache.fineract.portfolio.savings.service.SavingsEnumerations;
51+
import org.apache.logging.log4j.util.Strings;
5152
import org.springframework.context.annotation.Primary;
5253
import org.springframework.jdbc.core.RowMapper;
5354
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
@@ -361,7 +362,7 @@ private static final class CredXSavingsAccountSummaryDataMapper implements RowMa
361362
accountsSummary.append("curr.name as currencyName, curr.internationalized_name_code as currencyNameCode, ");
362363
accountsSummary.append("curr.display_symbol as currencyDisplaySymbol, ");
363364
accountsSummary.append("sa.product_id as productId, p.name as productName, p.short_name as shortProductName, ");
364-
accountsSummary.append("sa.deposit_type_enum as depositType, ");
365+
accountsSummary.append("sa.deposit_type_enum as depositType, loc.external_id as locExternalId, ");
365366
accountsSummary.append("ml.id as fromLoanAccountId, ");
366367
accountsSummary.append("ml.account_no as fromLoanAccountNumber ");
367368
accountsSummary.append("from m_savings_account sa ");
@@ -386,6 +387,7 @@ left join (
386387
on sa.id = transfer_info.to_savings_account_id
387388
""");
388389
accountsSummary.append(" left join m_loan ml on ml.id = transfer_info.from_loan_account_id ");
390+
accountsSummary.append(" left join m_line_of_credit loc on sa.id = loc.settlement_savings_account_id ");
389391

390392
this.schemaSql = accountsSummary.toString();
391393
}
@@ -455,7 +457,11 @@ public SavingsAccountSummaryData mapRow(final ResultSet rs, @SuppressWarnings("u
455457
final LocalDate lastActiveTransactionDate = JdbcSupport.getLocalDate(rs, "lastActiveTransactionDate");
456458

457459
final Long fromLoanAccountId = JdbcSupport.getLong(rs, "fromLoanAccountId");
458-
final String fromLoanAccountNumber = rs.getString("fromLoanAccountNumber");
460+
String fromLoanAccountNumber = rs.getString("fromLoanAccountNumber");
461+
462+
if (Strings.isBlank(fromLoanAccountNumber)) {
463+
fromLoanAccountNumber = rs.getString("locExternalId");
464+
}
459465

460466
final SavingsAccountApplicationTimelineData timeline = new SavingsAccountApplicationTimelineData(submittedOnDate,
461467
submittedByUsername, submittedByFirstname, submittedByLastname, rejectedOnDate, rejectedByUsername, rejectedByFirstname,
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package com.crediblex.fineract.portfolio.loanaccount.data;
20+
21+
import java.math.BigDecimal;
22+
23+
@lombok.Data
24+
@lombok.Builder
25+
public class LoanMonthlyAccrualData {
26+
27+
private Long loanId;
28+
private BigDecimal totalInterestAccrualDerived;
29+
private String accrualTransactionIds;
30+
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package com.crediblex.fineract.portfolio.loanaccount.domain;
20+
21+
import jakarta.persistence.Column;
22+
import jakarta.persistence.Entity;
23+
import jakarta.persistence.Table;
24+
import java.math.BigDecimal;
25+
import java.time.LocalDate;
26+
import lombok.Getter;
27+
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
28+
29+
@Getter
30+
@Entity
31+
@Table(name = "m_loan_monthly_accrual_job_run_audit")
32+
public class LoanMonthlyAccrualJobAudit extends AbstractAuditableWithUTCDateTimeCustom<Long> {
33+
34+
@Column(name = "loan_id")
35+
private Long loanId;
36+
37+
@Column(name = "accrual_transaction_ids")
38+
private String accrualTransactionIds;
39+
40+
@Column(name = "total_interest_accrual_derived")
41+
private BigDecimal totalInterestAccrualDerived;
42+
43+
@Column(name = "is_posted_to_odoo")
44+
private boolean postedToOdoo;
45+
46+
@Column(name = "generated_on_date")
47+
private LocalDate generatedOnDate;
48+
49+
private LoanMonthlyAccrualJobAudit(final Long loanId, final String accrualTransactionIds, final BigDecimal totalInterestAccrualDerived,
50+
final boolean postedToOdoo, final LocalDate generatedOnDate) {
51+
this.loanId = loanId;
52+
this.accrualTransactionIds = accrualTransactionIds;
53+
this.totalInterestAccrualDerived = totalInterestAccrualDerived;
54+
this.postedToOdoo = postedToOdoo;
55+
this.generatedOnDate = generatedOnDate;
56+
}
57+
58+
public static LoanMonthlyAccrualJobAudit createNew(final Long loanId, final String accrualTransactionIds,
59+
final BigDecimal totalInterestAccrualDerived, final boolean postedToOdoo, final LocalDate generatedOnDate) {
60+
return new LoanMonthlyAccrualJobAudit(loanId, accrualTransactionIds, totalInterestAccrualDerived, postedToOdoo, generatedOnDate);
61+
}
62+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package com.crediblex.fineract.portfolio.loanaccount.domain;
20+
21+
import org.springframework.data.jpa.repository.JpaRepository;
22+
import org.springframework.stereotype.Repository;
23+
24+
@Repository
25+
public interface LoanMonthlyAccrualJobAuditRepository extends JpaRepository<LoanMonthlyAccrualJobAudit, Long> {
26+
27+
}
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing,
13+
* software distributed under the License is distributed on an
14+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15+
* KIND, either express or implied. See the License for the
16+
* specific language governing permissions and limitations
17+
* under the License.
18+
*/
19+
package com.crediblex.fineract.portfolio.loanaccount.jobs.generateloanmonthlyaccrualsummations;
20+
21+
import com.crediblex.fineract.portfolio.loanaccount.domain.LoanMonthlyAccrualJobAuditRepository;
22+
import org.apache.fineract.infrastructure.jobs.service.JobName;
23+
import org.springframework.batch.core.Job;
24+
import org.springframework.batch.core.Step;
25+
import org.springframework.batch.core.job.builder.JobBuilder;
26+
import org.springframework.batch.core.launch.support.RunIdIncrementer;
27+
import org.springframework.batch.core.repository.JobRepository;
28+
import org.springframework.batch.core.step.builder.StepBuilder;
29+
import org.springframework.beans.factory.annotation.Autowired;
30+
import org.springframework.context.annotation.Bean;
31+
import org.springframework.context.annotation.Configuration;
32+
import org.springframework.jdbc.core.JdbcTemplate;
33+
import org.springframework.transaction.PlatformTransactionManager;
34+
35+
@Configuration
36+
public class GenerateLoanMonthlyAccrualSummationsConfig {
37+
38+
@Autowired
39+
private JobRepository jobRepository;
40+
@Autowired
41+
private PlatformTransactionManager transactionManager;
42+
43+
@Autowired
44+
private LoanMonthlyAccrualJobAuditRepository loanMonthlyAccrualJobAuditRepository;
45+
46+
@Autowired
47+
private JdbcTemplate jdbcTemplate;
48+
49+
@Bean
50+
protected Step generateLoanMonthlyAccrualSummationsStep() {
51+
return new StepBuilder(JobName.GENERATE_LOAN_MONTHLY_ACCRUAL_SUMMATIONS.name(), jobRepository)
52+
.tasklet(generateLoanMonthlyAccrualSummationsTasket(), transactionManager).build();
53+
}
54+
55+
@Bean
56+
public Job generateLoanMonthlyAccrualSummationsJob() {
57+
return new JobBuilder(JobName.GENERATE_LOAN_MONTHLY_ACCRUAL_SUMMATIONS.name(), jobRepository)
58+
.start(generateLoanMonthlyAccrualSummationsStep()).incrementer(new RunIdIncrementer()).build();
59+
}
60+
61+
@Bean
62+
public GenerateLoanMonthlyAccrualSummationsTasket generateLoanMonthlyAccrualSummationsTasket() {
63+
return new GenerateLoanMonthlyAccrualSummationsTasket(this.loanMonthlyAccrualJobAuditRepository, this.jdbcTemplate);
64+
}
65+
}

0 commit comments

Comments
 (0)