Skip to content

Commit

Permalink
Merge pull request #1301 from fiterlatam/SU-199
Browse files Browse the repository at this point in the history
Su 199
  • Loading branch information
oluexpert99 authored Nov 20, 2024
2 parents 23e8028 + cbf8d1b commit 9d03d18
Show file tree
Hide file tree
Showing 14 changed files with 494 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
package org.apache.fineract.infrastructure.configuration.domain;

import java.time.LocalDate;
import java.util.List;
import org.apache.fineract.infrastructure.cache.domain.CacheType;

public interface ConfigurationDomainService {
Expand Down Expand Up @@ -149,4 +150,10 @@ public interface ConfigurationDomainService {

Long retriveMinimumDaysOfArrearsToWriteOff();

Long retrieveInvoiceResolutionExpiryDays();

Long retrieveInvoiceThreshold();

List<String> retrieveInvoiceJobNotificationEmails();

}
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ public enum JobName {
"Compensation"), COMPENSATION_ALERT_EMAIL("Compensation Alert Email"), DAILY_LOAN_ACCRUAL("Devengo de Interés diario"), //
INSURANCE_CHARGE_CANCELLATION_DUE_TO_DEFAULT("Cancel Default Insurance Charges"), INSTALLMENT_LOAN_CHARGE_ACCRUAL(
"Devengo de seguro"), ARCHIVE_LOAN_HISTORY("Archivo de cartera"), //
INSURANCE_CHARGE_SUSPENSION_DUE_TO_DEFAULT("Suspension temporal por mora") // ;
INSURANCE_CHARGE_SUSPENSION_DUE_TO_DEFAULT("Suspension temporal por mora") //
, INVOICE_NUMBERING_LIMIT("Control de Límite de Numeración de Facturación Electrónica"), INVOICE_EXPIRY_RESOLUTION(
"Control de Vencimiento de Resolución de Facturación Electrónica")//
;

private final String name;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,17 @@ public final class EmailMessageWithAttachmentData {
private String text;
private String subject;
private List<File> attachments;
private List<String> recipients;

public static EmailMessageWithAttachmentData createNew(final String to, final String text, final String subject,
final List<File> attachments) {
return new EmailMessageWithAttachmentData().setTo(to).setText(text).setSubject(subject).setAttachments(attachments);
}

public static EmailMessageWithAttachmentData createNew(final String text, final String subject, final List<File> attachments,
final List<String> recipients) {
return new EmailMessageWithAttachmentData().setText(text).setSubject(subject).setAttachments(attachments).setRecipients(recipients)
.setRecipients(recipients);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,12 @@ public void sendEmailWithAttachment(EmailMessageWithAttachmentData emailMessageW
MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(mimeMessage, true);

mimeMessageHelper.setFrom(smtpCredentialsData.getFromEmail());
mimeMessageHelper.setTo(emailMessageWithAttachmentData.getTo());
// if recipient is a list of recipients use the multiple to
if (emailMessageWithAttachmentData.getRecipients() != null && !emailMessageWithAttachmentData.getRecipients().isEmpty()) {
mimeMessageHelper.setTo(emailMessageWithAttachmentData.getRecipients().toArray(new String[0]));
} else {
mimeMessageHelper.setTo(emailMessageWithAttachmentData.getTo());
}
mimeMessageHelper.setText(emailMessageWithAttachmentData.getText(), true);
mimeMessageHelper.setSubject(emailMessageWithAttachmentData.getSubject());
final List<File> attachments = emailMessageWithAttachmentData.getAttachments();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

import jakarta.validation.constraints.NotNull;
import java.time.LocalDate;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
Expand Down Expand Up @@ -54,6 +55,9 @@ public class ConfigurationDomainServiceJpa implements ConfigurationDomainService

public static final String CHARGE_ACCRUAL_DATE_CRITERIA = "charge-accrual-date";
public static final String NEXT_PAYMENT_DUE_DATE = "next-payment-due-date";
public static final String INVOICE_RESOLUTION_EXPIRY = "Días previos para notificar vencimiento de la resolución de facturas";
public static final String REMAINING_INVOICES_THRESHOLD = "Cantidad previa al límte de la numeración de la facturación para notificar";
public static final String INVOICE_NOTIFICATION_EMAILS = "Correo/s para enviar alerta por factura electrónica por vencer o agotarse";

private final PermissionRepository permissionRepository;
private final GlobalConfigurationRepositoryWrapper globalConfigurationRepository;
Expand Down Expand Up @@ -548,4 +552,32 @@ public Long retriveMinimumDaysOfArrearsToWriteOff() {
return property.getValue();
}

@Override
public Long retrieveInvoiceResolutionExpiryDays() {
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(INVOICE_RESOLUTION_EXPIRY);
if (property.isEnabled()) {
return property.getValue();
}

return null;
}

@Override
public Long retrieveInvoiceThreshold() {
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(REMAINING_INVOICES_THRESHOLD);
if (property.isEnabled()) {
return property.getValue();
}
return null;
}

@Override
public List<String> retrieveInvoiceJobNotificationEmails() {
final GlobalConfigurationPropertyData property = getGlobalConfigurationPropertyData(INVOICE_NOTIFICATION_EMAILS);
if (property.isEnabled()) {
return List.of(property.getStringValue().split(","));
}
return List.of();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import org.apache.fineract.infrastructure.core.api.JsonCommand;
import org.apache.fineract.infrastructure.core.domain.AbstractAuditableWithUTCDateTimeCustom;
import org.apache.fineract.infrastructure.core.exception.GeneralPlatformDomainRuleException;
import org.apache.fineract.infrastructure.core.service.DateUtils;
import org.apache.fineract.portfolio.loanproduct.domain.LoanProductType;
import org.apache.fineract.portfolio.loanproductparameterization.data.LoanProductParameterizationData;

Expand Down Expand Up @@ -142,4 +143,36 @@ private static LoanProductParameterization extractParameters(JsonCommand command
return new LoanProductParameterization(productType, billingPrefix, billingResolutionNumber, generationDate, expirationDate,
rangeStartNumber, rangeEndNumber, lastInvoiceNumber, lastCreditNoteNumber, lastDebitNoteNumber);
}

public boolean isInvoiceResolutionExpiring(Long daysPrior) {
LocalDate currentDate = DateUtils.getLocalDateOfTenant();
LocalDate warningDate = currentDate.plusDays(daysPrior);
// Implement logic to check if the invoice resolution is expiring within the specified days
// Return true if the condition is met, otherwise false

// Check if the expiration date is within the specified days
return expirationDate != null && (warningDate.isAfter(expirationDate) || warningDate.isEqual(expirationDate));
}

public boolean isInvoiceNumberingLimitReached(Long threshold) {
// Implement logic to check if the invoice numbering limit is reached within the specified quantity
// Return true if the condition is met, otherwise false
long maximumInvoiceNumber = rangeEndNumber;
long usedInvoiceNumber = lastInvoiceNumber;
long remainingInvoiceNumber = maximumInvoiceNumber - usedInvoiceNumber;

// Check if the last invoice number is within the specified quantity
return remainingInvoiceNumber <= threshold;
}

public Long getInvoiceNumberingRemaining() {
long maximumInvoiceNumber = rangeEndNumber;
long usedInvoiceNumber = lastInvoiceNumber;
return maximumInvoiceNumber - usedInvoiceNumber;
}

public Long getInvoiceResolutionExpiryDays() {
LocalDate currentDate = DateUtils.getLocalDateOfTenant();
return DateUtils.getDifferenceInDays(currentDate, expirationDate);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanproductparameterization.jobs.invoiceexpiryresolution;

import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
@RequiredArgsConstructor
public class InvoiceResolutionExpiryConfig {

private final JobRepository jobRepository;

private final PlatformTransactionManager transactionManager;
private final String jobName = JobName.INVOICE_EXPIRY_RESOLUTION.name();

@Bean
protected Step runInvoiceResolutionExpiryStep(InvoiceResolutionExpiryTasklet invoiceResolutionExpiryTasklet) {
return new StepBuilder(jobName, jobRepository).tasklet(invoiceResolutionExpiryTasklet, transactionManager).build();
}

@Bean
public Job runInvoiceResolutionExpiryJob(InvoiceResolutionExpiryTasklet runInvoiceResolutionExpiryStep) {
return new JobBuilder(jobName, jobRepository).start(runInvoiceResolutionExpiryStep(runInvoiceResolutionExpiryStep))
.incrementer(new RunIdIncrementer()).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanproductparameterization.jobs.invoiceexpiryresolution;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.portfolio.loanproductparameterization.service.LoanProductParameterizationWriteService;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.stereotype.Component;

@Slf4j
@RequiredArgsConstructor
@Component
public class InvoiceResolutionExpiryTasklet implements Tasklet {

private final LoanProductParameterizationWriteService loanProductParameterizationWriteService;

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

List<Throwable> errors = new ArrayList<>();
try {
loanProductParameterizationWriteService.sendIInvoiceResolutionExpiryNotification();
} catch (Exception e) {
log.error("Failed to InvoiceResolutionExpiryTasklet ", e);
errors.add(e);
}
if (!errors.isEmpty()) {
throw new JobExecutionException(errors);
}
return RepeatStatus.FINISHED;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanproductparameterization.jobs.invoicenumberinglimit;

import lombok.RequiredArgsConstructor;
import org.apache.fineract.infrastructure.jobs.service.JobName;
import org.springframework.batch.core.Job;
import org.springframework.batch.core.Step;
import org.springframework.batch.core.job.builder.JobBuilder;
import org.springframework.batch.core.launch.support.RunIdIncrementer;
import org.springframework.batch.core.repository.JobRepository;
import org.springframework.batch.core.step.builder.StepBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.PlatformTransactionManager;

@Configuration
@RequiredArgsConstructor
public class InvoiceNumberingLimitConfig {

private final JobRepository jobRepository;

private final PlatformTransactionManager transactionManager;

@Bean
protected Step runInvoiceNumberingLimitStep(InvoiceNumberingLimitTasklet invoiceNumberingLimitTasklet) {
return new StepBuilder(JobName.INVOICE_NUMBERING_LIMIT.name(), jobRepository)
.tasklet(invoiceNumberingLimitTasklet, transactionManager).build();
}

@Bean
public Job runInvoiceNumberingLimitJob(InvoiceNumberingLimitTasklet invoiceNumberingLimitTasklet) {
return new JobBuilder(JobName.INVOICE_NUMBERING_LIMIT.name(), jobRepository)
.start(runInvoiceNumberingLimitStep(invoiceNumberingLimitTasklet)).incrementer(new RunIdIncrementer()).build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/**
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.fineract.portfolio.loanproductparameterization.jobs.invoicenumberinglimit;

import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.fineract.infrastructure.jobs.exception.JobExecutionException;
import org.apache.fineract.portfolio.loanproductparameterization.service.LoanProductParameterizationWriteService;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.core.step.tasklet.Tasklet;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.stereotype.Component;

@Slf4j
@RequiredArgsConstructor
@Component
public class InvoiceNumberingLimitTasklet implements Tasklet {

private final LoanProductParameterizationWriteService loanProductParameterizationWriteService;

@Override
public RepeatStatus execute(StepContribution contribution, ChunkContext chunkContext) throws Exception {

List<Throwable> errors = new ArrayList<>();
try {
loanProductParameterizationWriteService.sendInvoiceNumberingLimitNotification();

} catch (Exception e) {
log.error("Failed to run InvoiceNumberingLimitTasklet ", e);
errors.add(e);
}
if (!errors.isEmpty()) {
throw new JobExecutionException(errors);
}
return RepeatStatus.FINISHED;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,8 @@ public interface LoanProductParameterizationWriteService {
CommandProcessingResult updateProductParameterization(Long parameterId, JsonCommand command);

CommandProcessingResult deleteProductParameterization(Long parameterId);

void sendInvoiceNumberingLimitNotification();

void sendIInvoiceResolutionExpiryNotification();
}
Loading

0 comments on commit 9d03d18

Please sign in to comment.