2424import lombok .RequiredArgsConstructor ;
2525import lombok .extern .slf4j .Slf4j ;
2626import org .apache .fineract .accounting .glaccount .domain .TrialBalance ;
27+ import org .apache .fineract .accounting .glaccount .domain .TrialBalanceRepository ;
2728import org .apache .fineract .accounting .glaccount .domain .TrialBalanceRepositoryWrapper ;
29+ import org .apache .fineract .accounting .journalentry .domain .JournalEntryRepository ;
2830import org .apache .fineract .infrastructure .core .service .DateUtils ;
2931import org .apache .fineract .infrastructure .core .service .ThreadLocalContextUtil ;
3032import org .apache .fineract .infrastructure .core .service .database .RoutingDataSourceServiceFactory ;
@@ -41,59 +43,87 @@ public class UpdateTrialBalanceDetailsTasklet implements Tasklet {
4143
4244 private final RoutingDataSourceServiceFactory dataSourceServiceFactory ;
4345 private final TrialBalanceRepositoryWrapper trialBalanceRepositoryWrapper ;
46+ private final TrialBalanceRepository trialBalanceRepository ;
47+ private final JournalEntryRepository journalEntryRepository ;
4448
4549 @ Override
4650 public RepeatStatus execute (StepContribution contribution , ChunkContext chunkContext ) throws Exception {
4751 final JdbcTemplate jdbcTemplate = new JdbcTemplate (dataSourceServiceFactory .determineDataSourceService ().retrieveDataSource ());
48- final StringBuilder tbGapSqlBuilder = new StringBuilder (500 );
49- tbGapSqlBuilder .append ("select distinct(je.transaction_date) " ).append ("from acc_gl_journal_entry je " )
50- .append ("where je.transaction_date > (select coalesce(MAX(created_date),'2010-01-01') from m_trial_balance)" );
51- final List <LocalDate > tbGaps = jdbcTemplate .queryForList (tbGapSqlBuilder .toString (), LocalDate .class );
52+
53+ processTrialBalanceGaps (jdbcTemplate );
54+ updateClosingBalances (jdbcTemplate );
55+
56+ return RepeatStatus .FINISHED ;
57+ }
58+
59+ private void processTrialBalanceGaps (JdbcTemplate jdbcTemplate ) {
60+ LocalDate maxCreatedDate = trialBalanceRepository .findMaxCreatedDate ();
61+ LocalDate baselineDate = maxCreatedDate != null ? maxCreatedDate : LocalDate .of (2010 , 1 , 1 );
62+ List <LocalDate > tbGaps = journalEntryRepository .findTransactionDatesAfter (baselineDate );
5263 for (LocalDate tbGap : tbGaps ) {
53- int days = DateUtils .getExactDifferenceInDays (tbGap , DateUtils .getBusinessLocalDate ());
54- if (days < 1 ) {
64+ if (DateUtils .getExactDifferenceInDays (tbGap , DateUtils .getBusinessLocalDate ()) < 1 ) {
5565 continue ;
5666 }
57- final StringBuilder sqlBuilder = new StringBuilder (600 );
58- sqlBuilder .append ("Insert Into m_trial_balance(office_id, account_id, Amount, entry_date, created_date,closing_balance) " )
59- .append ("Select je.office_id, je.account_id, SUM(CASE WHEN je.type_enum=1 THEN (-1) * je.amount ELSE je.amount END) " )
60- .append ("as Amount, Date(je.entry_date) as Entry_Date, je.transaction_date as Created_Date,sum(je.amount) as closing_balance " )
61- .append ("from acc_gl_journal_entry je WHERE je.transaction_date = ? " )
62- .append ("group by je.account_id, je.office_id, je.transaction_date, Date(je.entry_date)" );
63- final int result = jdbcTemplate .update (sqlBuilder .toString (), tbGap );
64- log .debug ("{}: Records affected by updateTrialBalanceDetails: {}" , ThreadLocalContextUtil .getTenant ().getName (), result );
67+ insertTrialBalanceForDate (tbGap );
6568 }
66- String distinctOfficeQuery = "select distinct(office_id) from m_trial_balance where closing_balance is null group by office_id" ;
67- final List <Long > officeIds = jdbcTemplate .queryForList (distinctOfficeQuery , Long .class );
69+ }
70+
71+ private void insertTrialBalanceForDate (LocalDate tbGap ) {
72+ List <Object []> rows = journalEntryRepository .findTrialBalanceLinesForDate (tbGap );
73+
74+ List <TrialBalance > trialBalances = rows .stream ().map (row -> {
75+ TrialBalance tb = new TrialBalance ();
76+ tb .setOfficeId ((Long ) row [0 ]);
77+ tb .setGlAccountId ((Long ) row [1 ]);
78+ tb .setAmount ((BigDecimal ) row [2 ]);
79+ tb .setEntryDate ((LocalDate ) row [3 ]);
80+ tb .setTransactionDate ((LocalDate ) row [4 ]);
81+ tb .setClosingBalance ((BigDecimal ) row [5 ]);
82+ return tb ;
83+ }).toList ();
84+
85+ trialBalanceRepositoryWrapper .save (trialBalances );
86+
87+ log .debug ("{}: Records affected by updateTrialBalanceDetails: {}" , ThreadLocalContextUtil .getTenant ().getName (),
88+ trialBalances .size ());
89+ }
90+
91+ private void updateClosingBalances (JdbcTemplate jdbcTemplate ) {
92+ final List <Long > officeIds = trialBalanceRepository .findDistinctOfficeIdsWithNullClosingBalance ();
93+
6894 for (Long officeId : officeIds ) {
69- String distinctAccountQuery = "select distinct(account_id) from m_trial_balance where office_id=? and closing_balance is null group by account_id" ;
70- final List <Long > accountIds = jdbcTemplate .queryForList (distinctAccountQuery , Long .class , officeId );
71- for (Long accountId : accountIds ) {
72- final String closingBalanceQuery = "select closing_balance from m_trial_balance where office_id=? and account_id=? and closing_balance "
73- + "is not null order by created_date desc, entry_date desc limit 1" ;
74- List <BigDecimal > closingBalanceData = jdbcTemplate .queryForList (closingBalanceQuery , BigDecimal .class , officeId , accountId );
75- List <TrialBalance > tbRows = trialBalanceRepositoryWrapper .findNewByOfficeAndAccount (officeId , accountId );
76- BigDecimal closingBalance = null ;
77- if (!CollectionUtils .isEmpty (closingBalanceData )) {
78- closingBalance = closingBalanceData .get (0 );
79- }
80- if (CollectionUtils .isEmpty (closingBalanceData )) {
81- closingBalance = BigDecimal .ZERO ;
82- for (TrialBalance row : tbRows ) {
83- closingBalance = closingBalance .add (row .getAmount ());
84- row .setClosingBalance (closingBalance );
85- }
86- } else {
87- for (TrialBalance tbRow : tbRows ) {
88- if (closingBalance != null ) {
89- closingBalance = closingBalance .add (tbRow .getAmount ());
90- }
91- tbRow .setClosingBalance (closingBalance );
92- }
93- }
94- trialBalanceRepositoryWrapper .save (tbRows );
95+ updateClosingBalancesForOffice (jdbcTemplate , officeId );
96+ }
97+ }
98+
99+ private void updateClosingBalancesForOffice (JdbcTemplate jdbcTemplate , Long officeId ) {
100+ final List <Long > accountIds = trialBalanceRepository .findDistinctAccountIdsWithNullClosingBalanceByOfficeId (officeId );
101+
102+ for (Long accountId : accountIds ) {
103+ updateClosingBalanceForAccount (jdbcTemplate , officeId , accountId );
104+ }
105+ }
106+
107+ private void updateClosingBalanceForAccount (JdbcTemplate jdbcTemplate , Long officeId , Long accountId ) {
108+ BigDecimal closingBalance = getPreviousClosingBalance (officeId , accountId );
109+ List <TrialBalance > tbRows = trialBalanceRepositoryWrapper .findNewByOfficeAndAccount (officeId , accountId );
110+
111+ updateTrialBalanceRows (tbRows , closingBalance );
112+ }
113+
114+ private BigDecimal getPreviousClosingBalance (Long officeId , Long accountId ) {
115+ List <BigDecimal > closingBalanceData = trialBalanceRepository .findLastClosingBalance (officeId , accountId );
116+ return CollectionUtils .isEmpty (closingBalanceData ) ? BigDecimal .ZERO : closingBalanceData .getFirst ();
117+ }
118+
119+ private void updateTrialBalanceRows (List <TrialBalance > tbRows , BigDecimal initialClosingBalance ) {
120+ BigDecimal closingBalance = initialClosingBalance ;
121+
122+ for (TrialBalance row : tbRows ) {
123+ if (closingBalance != null ) {
124+ closingBalance = closingBalance .add (row .getAmount ());
95125 }
126+ row .setClosingBalance (closingBalance );
96127 }
97- return RepeatStatus .FINISHED ;
98128 }
99129}
0 commit comments