/**
* Axelor Business Solutions
*
* Copyright (C) 2016 Axelor (<http://axelor.com>).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License, version 3,
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.axelor.apps.cash.management.service;
import java.io.IOException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.joda.time.LocalDate;
import com.axelor.apps.ReportFactory;
import com.axelor.apps.account.db.Invoice;
import com.axelor.apps.account.db.repo.InvoiceRepository;
import com.axelor.apps.base.service.CurrencyService;
import com.axelor.apps.base.service.administration.GeneralService;
import com.axelor.apps.cash.management.db.Forecast;
import com.axelor.apps.cash.management.db.ForecastReason;
import com.axelor.apps.cash.management.db.ForecastRecap;
import com.axelor.apps.cash.management.db.ForecastRecapLine;
import com.axelor.apps.cash.management.db.repo.ForecastRecapLineRepository;
import com.axelor.apps.cash.management.db.repo.ForecastRecapRepository;
import com.axelor.apps.cash.management.db.repo.ForecastRepository;
import com.axelor.apps.cash.management.report.IReport;
import com.axelor.apps.crm.db.Opportunity;
import com.axelor.apps.crm.db.repo.OpportunityRepository;
import com.axelor.apps.hr.db.Employee;
import com.axelor.apps.hr.db.Expense;
import com.axelor.apps.hr.db.repo.EmployeeRepository;
import com.axelor.apps.hr.db.repo.ExpenseRepository;
import com.axelor.apps.purchase.db.PurchaseOrder;
import com.axelor.apps.purchase.db.repo.PurchaseOrderRepository;
import com.axelor.apps.sale.db.SaleOrder;
import com.axelor.apps.sale.db.repo.SaleOrderRepository;
import com.axelor.apps.supplychain.db.Timetable;
import com.axelor.apps.supplychain.db.repo.TimetableRepository;
import com.axelor.apps.supplychain.service.TimetableService;
import com.axelor.exception.AxelorException;
import com.axelor.inject.Beans;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
import com.axelor.i18n.I18n;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ForecastRecapService {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Inject
protected TimetableService timetableService;
@Inject
protected GeneralService generalService;
@Inject
protected ForecastRepository forecastRepo;
@Inject
protected ForecastRecapLineRepository forecastRecapLineRepo;
@Inject
protected CurrencyService currencyService;
@Inject
protected ReportFactory reportFactory;
public void populate(ForecastRecap forecastRecap) throws AxelorException{
List<ForecastRecapLine> forecastRecapLineList = forecastRecap.getForecastRecapLineList();
if(forecastRecapLineList != null && !forecastRecapLineList.isEmpty()){
for (ForecastRecapLine forecastRecapLine : forecastRecapLineList) {
if(forecastRecapLine.getId() != null && forecastRecapLine.getId() > 0){
forecastRecapLineRepo.remove(forecastRecapLine);
}
}
forecastRecapLineList.clear();
}
forecastRecap.setCurrentBalance(forecastRecap.getStartingBalance());
if(forecastRecap.getOpportunitiesTypeSelect() != null && forecastRecap.getOpportunitiesTypeSelect() > ForecastRecapRepository.OPPORTUNITY_TYPE_NO){
this.populateWithOpportunities(forecastRecap);
}
this.populateWithInvoices(forecastRecap);
this.populateWithSalaries(forecastRecap);
this.populateWithTimetables(forecastRecap);
this.populateWithForecasts(forecastRecap);
this.populateWithExpenses(forecastRecap);
forecastRecap.setEndingBalance(forecastRecap.getCurrentBalance());
}
public void populateWithOpportunities(ForecastRecap forecastRecap) throws AxelorException{
List<Opportunity> opportunityList = new ArrayList<Opportunity>();
if(forecastRecap.getBankDetails() != null){
opportunityList = Beans.get(OpportunityRepository.class).all().filter("self.company = ?1 AND self.bankDetails = ?2 AND self.expectedCloseDate BETWEEN ?3 AND ?4 AND self.saleOrder = null",
forecastRecap.getCompany(),forecastRecap.getBankDetails(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
else{
opportunityList = Beans.get(OpportunityRepository.class).all().filter("self.company = ?1 AND self.expectedCloseDate BETWEEN ?2 AND ?3 AND self.saleOrder = null",
forecastRecap.getCompany(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
for (Opportunity opportunity : opportunityList) {
BigDecimal amountCompanyCurr = BigDecimal.ZERO;
if(forecastRecap.getOpportunitiesTypeSelect() == ForecastRecapRepository.OPPORTUNITY_TYPE_BASE){
amountCompanyCurr = currencyService.getAmountCurrencyConverted(
opportunity.getCurrency(), opportunity.getCompany().getCurrency(), opportunity.getAmount().multiply(opportunity.getProbability()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(opportunity.getExpectedCloseDate(), 1, null,
amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
else if(forecastRecap.getOpportunitiesTypeSelect() == ForecastRecapRepository.OPPORTUNITY_TYPE_BEST){
amountCompanyCurr = currencyService.getAmountCurrencyConverted(
opportunity.getCurrency(), opportunity.getCompany().getCurrency(), new BigDecimal(opportunity.getBestCase()).multiply(opportunity.getProbability()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(opportunity.getExpectedCloseDate(), 1, null,
amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
else{
amountCompanyCurr = currencyService.getAmountCurrencyConverted(
opportunity.getCurrency(), opportunity.getCompany().getCurrency(), new BigDecimal(opportunity.getWorstCase()).multiply(opportunity.getProbability()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(opportunity.getExpectedCloseDate(), 1, null,
amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
}
}
public void getOpportunities(ForecastRecap forecastRecap, Map<LocalDate, BigDecimal> mapExpected, Map<LocalDate, BigDecimal> mapConfirmed) throws AxelorException{
List<Opportunity> opportunityList = new ArrayList<Opportunity>();
if(forecastRecap.getBankDetails() != null){
opportunityList = Beans.get(OpportunityRepository.class).all().filter("self.company = ?1 AND self.bankDetails = ?2 AND self.expectedCloseDate BETWEEN ?3 AND ?4 AND self.saleOrder = null",
forecastRecap.getCompany(),forecastRecap.getBankDetails(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
else{
opportunityList = Beans.get(OpportunityRepository.class).all().filter("self.company = ?1 AND self.expectedCloseDate BETWEEN ?2 AND ?3 AND self.saleOrder = null",
forecastRecap.getCompany(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
for (Opportunity opportunity : opportunityList) {
BigDecimal amountCompanyCurr = BigDecimal.ZERO;
if(forecastRecap.getOpportunitiesTypeSelect() == ForecastRecapRepository.OPPORTUNITY_TYPE_BASE){
amountCompanyCurr = currencyService.getAmountCurrencyConverted(
opportunity.getCurrency(), opportunity.getCompany().getCurrency(), opportunity.getAmount().multiply(opportunity.getProbability()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
}
else if(forecastRecap.getOpportunitiesTypeSelect() == ForecastRecapRepository.OPPORTUNITY_TYPE_BEST){
amountCompanyCurr = currencyService.getAmountCurrencyConverted(
opportunity.getCurrency(), opportunity.getCompany().getCurrency(), new BigDecimal(opportunity.getBestCase()).multiply(opportunity.getProbability()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
}
else{
amountCompanyCurr = currencyService.getAmountCurrencyConverted(
opportunity.getCurrency(), opportunity.getCompany().getCurrency(), new BigDecimal(opportunity.getWorstCase()).multiply(opportunity.getProbability()).divide(new BigDecimal(100), 2, RoundingMode.HALF_UP), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
}
if(opportunity.getSalesStageSelect() == 9){
if(mapExpected.containsKey(opportunity.getExpectedCloseDate())){
mapExpected.put(opportunity.getExpectedCloseDate(), mapExpected.get(opportunity.getExpectedCloseDate()).add(amountCompanyCurr));
}
else{
mapExpected.put(opportunity.getExpectedCloseDate(), amountCompanyCurr);
}
}
else{
if(mapConfirmed.containsKey(opportunity.getExpectedCloseDate())){
mapConfirmed.put(opportunity.getExpectedCloseDate(), mapConfirmed.get(opportunity.getExpectedCloseDate()).add(amountCompanyCurr));
}
else{
mapConfirmed.put(opportunity.getExpectedCloseDate(), amountCompanyCurr);
}
}
}
}
public void populateWithInvoices(ForecastRecap forecastRecap){
List<Invoice> invoiceList = new ArrayList<Invoice>();
if(forecastRecap.getBankDetails() != null){
invoiceList = Beans.get(InvoiceRepository.class).all().filter("self.company = ?1 AND self.companyBankDetails = ?2 AND self.statusSelect = 3 AND self.estimatedPaymentDate BETWEEN ?3 AND ?4 AND self.companyInTaxTotalRemaining != 0",
forecastRecap.getCompany(),forecastRecap.getBankDetails(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
else{
invoiceList = Beans.get(InvoiceRepository.class).all().filter("self.company = ?1 AND self.statusSelect = 3 AND self.estimatedPaymentDate BETWEEN ?2 AND ?3 AND self.companyInTaxTotalRemaining != 0",
forecastRecap.getCompany(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
for (Invoice invoice : invoiceList) {
BigDecimal amountPaidExTax = invoice.getAmountPaid().multiply(invoice.getCompanyExTaxTotal()).divide(invoice.getCompanyInTaxTotal(),2,RoundingMode.HALF_UP);
BigDecimal amount = invoice.getCompanyExTaxTotal().subtract(amountPaidExTax);
if(invoice.getOperationTypeSelect() == 2 || invoice.getOperationTypeSelect() == 3){
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amount));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(invoice.getEstimatedPaymentDate(), 1, null,
amount, forecastRecap.getCurrentBalance()));
}
if(invoice.getOperationTypeSelect() == 1 || invoice.getOperationTypeSelect() == 4){
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(amount));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(invoice.getEstimatedPaymentDate(), 2, null,
amount, forecastRecap.getCurrentBalance()));
}
}
}
public void getInvoices(ForecastRecap forecastRecap, Map<LocalDate, BigDecimal> mapExpected, Map<LocalDate, BigDecimal> mapConfirmed){
List<Invoice> invoiceList = new ArrayList<Invoice>();
if(forecastRecap.getBankDetails() != null){
invoiceList = Beans.get(InvoiceRepository.class).all().filter("self.company = ?1 AND self.companyBankDetails = ?2 AND self.statusSelect = 3 AND self.estimatedPaymentDate BETWEEN ?3 AND ?4 AND self.companyInTaxTotalRemaining != 0",
forecastRecap.getCompany(),forecastRecap.getBankDetails(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
else{
invoiceList = Beans.get(InvoiceRepository.class).all().filter("self.company = ?1 AND self.statusSelect = 3 AND self.estimatedPaymentDate BETWEEN ?2 AND ?3 AND self.companyInTaxTotalRemaining != 0",
forecastRecap.getCompany(), forecastRecap.getFromDate(), forecastRecap.getToDate()).fetch();
}
for (Invoice invoice : invoiceList) {
BigDecimal amountPaidExTax = invoice.getAmountPaid().multiply(invoice.getCompanyExTaxTotal()).divide(invoice.getCompanyInTaxTotal(),2,RoundingMode.HALF_UP);
BigDecimal amount = invoice.getCompanyExTaxTotal().subtract(amountPaidExTax);
if(invoice.getOperationTypeSelect() == 2 || invoice.getOperationTypeSelect() == 3){
if(mapConfirmed.containsKey(invoice.getEstimatedPaymentDate())){
mapConfirmed.put(invoice.getEstimatedPaymentDate(), mapConfirmed.get(invoice.getEstimatedPaymentDate()).add(amount));
}
else{
mapConfirmed.put(invoice.getEstimatedPaymentDate(), amount);
}
}
}
}
public void populateWithSalaries(ForecastRecap forecastRecap){
List<Employee> employeeList = new ArrayList<Employee>();
if(forecastRecap.getBankDetails() != null){
employeeList = Beans.get(EmployeeRepository.class).all().filter("self.user.activeCompany = ?1 AND self.bankDetails = ?2",forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
employeeList = Beans.get(EmployeeRepository.class).all().filter("self.user.activeCompany = ?1",forecastRecap.getCompany()).fetch();
}
LocalDate itDate = new LocalDate(forecastRecap.getFromDate());
while(!itDate.isAfter(forecastRecap.getToDate())){
if(itDate.isEqual(new LocalDate(itDate.getYear(), itDate.getMonthOfYear(), itDate.dayOfMonth().getMaximumValue()))){
for (Employee employee : employeeList) {
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(employee.getHourlyRate().multiply(employee.getWeeklyWorkHours().multiply(new BigDecimal(4)))));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(itDate, 2, null,
employee.getHourlyRate().multiply(employee.getWeeklyWorkHours().multiply(new BigDecimal(4))), forecastRecap.getCurrentBalance()));
}
itDate = itDate.plusMonths(1);
}
else{
itDate = new LocalDate(itDate.getYear(), itDate.getMonthOfYear(), itDate.dayOfMonth().getMaximumValue());
}
}
}
public void populateWithTimetables(ForecastRecap forecastRecap) throws AxelorException{
List<Timetable> timetableSaleOrderList = new ArrayList<Timetable>();
List<Timetable> timetablePurchaseOrderList = new ArrayList<Timetable>();
if(forecastRecap.getBankDetails() != null){
timetableSaleOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.saleOrder.company = ?3 AND"
+ " self.saleOrder.companyBankDetails = ?4 AND self.saleOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
timetablePurchaseOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.purchaseOrder.company = ?3 AND"
+ " self.purchaseOrder.companyBankDetails = ?4 AND self.purchaseOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
timetableSaleOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.saleOrder.company = ?3 AND"
+ " self.saleOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
timetablePurchaseOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.purchaseOrder.company = ?3 AND"
+ " self.purchaseOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (Timetable timetable : timetableSaleOrderList) {
timetableService.updateTimetable(timetable.getSaleOrder());
BigDecimal amountCompanyCurr = currencyService.getAmountCurrencyConverted(
timetable.getSaleOrder().getCurrency(), timetable.getSaleOrder().getCompany().getCurrency(), timetable.getAmountToInvoice(), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(timetable.getEstimatedDate(), 1, null, amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
for (Timetable timetable : timetablePurchaseOrderList) {
timetableService.updateTimetable(timetable.getPurchaseOrder());
BigDecimal amountCompanyCurr = currencyService.getAmountCurrencyConverted(
timetable.getPurchaseOrder().getCurrency(), timetable.getPurchaseOrder().getCompany().getCurrency(), timetable.getAmountToInvoice(), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(timetable.getEstimatedDate(), 2, null, amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
}
public void populateWithTimetablesOrOrders(ForecastRecap forecastRecap) throws AxelorException{
List<Timetable> timetableSaleOrderList = new ArrayList<Timetable>();
List<SaleOrder> saleOrderList = new ArrayList<SaleOrder>();
List<Timetable> timetablePurchaseOrderList = new ArrayList<Timetable>();
List<PurchaseOrder> purchaseOrderList = new ArrayList<PurchaseOrder>();
if(forecastRecap.getBankDetails() != null){
timetableSaleOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.saleOrder.company = ?3 AND"
+ " self.saleOrder.companyBankDetails = ?4 AND self.saleOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
timetablePurchaseOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.purchaseOrder.company = ?3 AND"
+ " self.purchaseOrder.companyBankDetails = ?4 AND self.purchaseOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
timetableSaleOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.saleOrder.company = ?3 AND"
+ " self.saleOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
timetablePurchaseOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.purchaseOrder.company = ?3 AND"
+ " self.purchaseOrder.statusSelect = 3 AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (Timetable timetable : timetableSaleOrderList) {
saleOrderList.add(timetable.getSaleOrder());
timetableService.updateTimetable(timetable.getSaleOrder());
BigDecimal amountCompanyCurr = currencyService.getAmountCurrencyConverted(
timetable.getSaleOrder().getCurrency(), timetable.getSaleOrder().getCompany().getCurrency(), timetable.getAmountToInvoice(), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(timetable.getEstimatedDate(), 1, null, amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
for (Timetable timetable : timetablePurchaseOrderList) {
purchaseOrderList.add(timetable.getPurchaseOrder());
timetableService.updateTimetable(timetable.getPurchaseOrder());
BigDecimal amountCompanyCurr = currencyService.getAmountCurrencyConverted(
timetable.getPurchaseOrder().getCurrency(), timetable.getPurchaseOrder().getCompany().getCurrency(), timetable.getAmountToInvoice(), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(timetable.getEstimatedDate(), 2, null, amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
List<SaleOrder> saleOrderNoTimeTableList = new ArrayList<SaleOrder>();
List<PurchaseOrder> purchaseOrderNoTimetableList = new ArrayList<PurchaseOrder>();
if(forecastRecap.getBankDetails() != null){
saleOrderNoTimeTableList = Beans.get(SaleOrderRepository.class).all().filter("self.expectedRealisationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.companyBankDetails = ?4 AND (self.statusSelect = 2 OR self.statusSelect = 3)", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
purchaseOrderNoTimetableList = Beans.get(PurchaseOrderRepository.class).all().filter("self.expectedRealisationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.companyBankDetails = ?4 AND self.statusSelect = 3", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
saleOrderNoTimeTableList = Beans.get(SaleOrderRepository.class).all().filter("self.expectedRealisationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " (self.statusSelect = 2 OR self.statusSelect = 3)", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
purchaseOrderNoTimetableList = Beans.get(PurchaseOrderRepository.class).all().filter("self.expectedRealisationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.statusSelect = 3", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (SaleOrder saleOrder : saleOrderNoTimeTableList) {
if(!saleOrderList.contains(saleOrder)){
BigDecimal amountCompanyCurr = saleOrder.getCompanyExTaxTotal().subtract(saleOrder.getAmountInvoiced());
if(amountCompanyCurr.compareTo(BigDecimal.ZERO) == 0){
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(saleOrder.getExpectedRealisationDate(), 1, null, amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
}
}
for (PurchaseOrder purchaseOrder : purchaseOrderNoTimetableList) {
if(!purchaseOrderList.contains(purchaseOrder)){
BigDecimal amountCompanyCurr = purchaseOrder.getCompanyExTaxTotal().subtract(purchaseOrder.getAmountInvoiced());
if(amountCompanyCurr.compareTo(BigDecimal.ZERO) == 0){
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(amountCompanyCurr));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(purchaseOrder.getExpectedRealisationDate(), 2, null, amountCompanyCurr, forecastRecap.getCurrentBalance()));
}
}
}
}
public void getTimetablesOrOrders(ForecastRecap forecastRecap, Map<LocalDate, BigDecimal> mapExpected, Map<LocalDate, BigDecimal> mapConfirmed) throws AxelorException{
List<Timetable> timetableSaleOrderList = new ArrayList<Timetable>();
List<SaleOrder> saleOrderList = new ArrayList<SaleOrder>();
if(forecastRecap.getBankDetails() != null){
timetableSaleOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.saleOrder.company = ?3 AND"
+ " self.saleOrder.companyBankDetails = ?4 AND (self.saleOrder.statusSelect = 2 OR self.saleOrder.statusSelect = 3) AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
timetableSaleOrderList = Beans.get(TimetableRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.saleOrder.company = ?3 AND"
+ " (self.saleOrder.statusSelect = 2 OR self.saleOrder.statusSelect = 3) AND self.amountToInvoice != 0", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (Timetable timetable : timetableSaleOrderList) {
saleOrderList.add(timetable.getSaleOrder());
timetableService.updateTimetable(timetable.getSaleOrder());
BigDecimal amountCompanyCurr = currencyService.getAmountCurrencyConverted(
timetable.getSaleOrder().getCurrency(), timetable.getSaleOrder().getCompany().getCurrency(), timetable.getAmountToInvoice(), generalService.getTodayDate())
.setScale(2, RoundingMode.HALF_UP);
if(timetable.getSaleOrder().getStatusSelect() == 2){
if(mapExpected.containsKey(timetable.getEstimatedDate())){
mapExpected.put(timetable.getEstimatedDate(), mapExpected.get(timetable.getEstimatedDate()).add(amountCompanyCurr));
}
else{
mapExpected.put(timetable.getEstimatedDate(), amountCompanyCurr);
}
}
else{
if(mapConfirmed.containsKey(timetable.getEstimatedDate())){
mapConfirmed.put(timetable.getEstimatedDate(), mapConfirmed.get(timetable.getEstimatedDate()).add(amountCompanyCurr));
}
else{
mapConfirmed.put(timetable.getEstimatedDate(), amountCompanyCurr);
}
}
}
List<SaleOrder> saleOrderNoTimeTableList = new ArrayList<SaleOrder>();
if(forecastRecap.getBankDetails() != null){
saleOrderNoTimeTableList = Beans.get(SaleOrderRepository.class).all().filter("self.expectedRealisationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.companyBankDetails = ?4 AND (self.statusSelect = 2 OR self.statusSelect = 3)", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
saleOrderNoTimeTableList = Beans.get(SaleOrderRepository.class).all().filter("self.expectedRealisationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " (self.statusSelect = 2 OR self.statusSelect = 3)", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (SaleOrder saleOrder : saleOrderNoTimeTableList) {
if(!saleOrderList.contains(saleOrder)){
BigDecimal amountCompanyCurr = saleOrder.getCompanyExTaxTotal().subtract(saleOrder.getAmountInvoiced());
if(amountCompanyCurr.compareTo(BigDecimal.ZERO) == 0){
if(saleOrder.getStatusSelect() == 2){
if(mapExpected.containsKey(saleOrder.getExpectedRealisationDate())){
mapExpected.put(saleOrder.getExpectedRealisationDate(), mapExpected.get(saleOrder.getExpectedRealisationDate()).add(amountCompanyCurr));
}
else{
mapExpected.put(saleOrder.getExpectedRealisationDate(), amountCompanyCurr);
}
}
else{
if(mapConfirmed.containsKey(saleOrder.getExpectedRealisationDate())){
mapConfirmed.put(saleOrder.getExpectedRealisationDate(), mapConfirmed.get(saleOrder.getExpectedRealisationDate()).add(amountCompanyCurr));
}
else{
mapConfirmed.put(saleOrder.getExpectedRealisationDate(), amountCompanyCurr);
}
}
}
}
}
}
@Transactional
public void populateWithForecasts(ForecastRecap forecastRecap){
List<Forecast> forecastList = new ArrayList<Forecast>();
if(forecastRecap.getBankDetails() != null){
forecastList = Beans.get(ForecastRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.bankDetails = ?4 AND (self.realizedSelect = 2 OR (self.realizedSelect = 3 AND self.estimatedDate <= ?5))", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails(), generalService.getTodayDate()).fetch();
}
else{
forecastList = Beans.get(ForecastRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " (self.realizedSelect = 2 OR (self.realizedSelect = 3 AND self.estimatedDate <= ?4))", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(), generalService.getTodayDate()).fetch();
}
for (Forecast forecast : forecastList) {
if(forecast.getTypeSelect() == 1){
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(forecast.getAmount()));
}
else{
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(forecast.getAmount()));
}
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(forecast.getEstimatedDate(), forecast.getTypeSelect(), forecast.getForecastReason(), forecast.getAmount(), forecastRecap.getCurrentBalance()));
forecast.setRealizedSelect(ForecastRepository.REALISED_SELECT_YES);
forecastRepo.save(forecast);
}
}
public void populateWithForecastsNoSave(ForecastRecap forecastRecap){
List<Forecast> forecastList = new ArrayList<Forecast>();
if(forecastRecap.getBankDetails() != null){
forecastList = Beans.get(ForecastRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.bankDetails = ?4 AND (self.realizedSelect = 2 OR (self.realizedSelect = 3 AND self.estimatedDate <= ?5))", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails(), generalService.getTodayDate()).fetch();
}
else{
forecastList = Beans.get(ForecastRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " (self.realizedSelect = 2 OR (self.realizedSelect = 3 AND self.estimatedDate <= ?4))", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(), generalService.getTodayDate()).fetch();
}
for (Forecast forecast : forecastList) {
if(forecast.getTypeSelect() == 1){
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().add(forecast.getAmount()));
}
else{
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(forecast.getAmount()));
}
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(forecast.getEstimatedDate(), forecast.getTypeSelect(), forecast.getForecastReason(), forecast.getAmount(), forecastRecap.getCurrentBalance()));
}
}
public void getForecasts(ForecastRecap forecastRecap, Map<LocalDate, BigDecimal> mapExpected, Map<LocalDate, BigDecimal> mapConfirmed){
List<Forecast> forecastList = new ArrayList<Forecast>();
if(forecastRecap.getBankDetails() != null){
forecastList = Beans.get(ForecastRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.bankDetails = ?4 AND (self.realizedSelect = 2 OR self.realizedSelect = 3)", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
forecastList = Beans.get(ForecastRepository.class).all().filter("self.estimatedDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " (self.realizedSelect = 2 OR self.realizedSelect = 3)", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (Forecast forecast : forecastList) {
if(forecast.getTypeSelect() == 1){
if(forecast.getRealizedSelect() == 2){
if(mapExpected.containsKey(forecast.getEstimatedDate())){
mapExpected.put(forecast.getEstimatedDate(), mapExpected.get(forecast.getEstimatedDate()).add(forecast.getAmount()));
}
else{
mapExpected.put(forecast.getEstimatedDate(), forecast.getAmount());
}
}
else{
if(mapConfirmed.containsKey(forecast.getEstimatedDate())){
mapConfirmed.put(forecast.getEstimatedDate(), mapConfirmed.get(forecast.getEstimatedDate()).add(forecast.getAmount()));
}
else{
mapConfirmed.put(forecast.getEstimatedDate(), forecast.getAmount());
}
}
}
}
}
public void populateWithExpenses(ForecastRecap forecastRecap){
List<Expense> expenseList = new ArrayList<Expense>();
if(forecastRecap.getBankDetails() != null){
expenseList = Beans.get(ExpenseRepository.class).all().filter("self.validationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.bankDetails = ?4 AND self.statusSelect = 3", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany(),forecastRecap.getBankDetails()).fetch();
}
else{
expenseList = Beans.get(ExpenseRepository.class).all().filter("self.validationDate BETWEEN ?1 AND ?2 AND self.company = ?3 AND"
+ " self.statusSelect = 3", forecastRecap.getFromDate(), forecastRecap.getToDate(), forecastRecap.getCompany()).fetch();
}
for (Expense expense : expenseList) {
forecastRecap.setCurrentBalance(forecastRecap.getCurrentBalance().subtract(expense.getExTaxTotal()));
forecastRecap.addForecastRecapLineListItem(this.createForecastRecapLine(expense.getValidationDate(), 2, null, expense.getExTaxTotal(), forecastRecap.getCurrentBalance()));
}
}
public ForecastRecapLine createForecastRecapLine(LocalDate date, int type, ForecastReason reason, BigDecimal amount, BigDecimal balance){
ForecastRecapLine forecastRecapLine = new ForecastRecapLine();
forecastRecapLine.setEstimatedDate(date);
forecastRecapLine.setTypeSelect(type);
forecastRecapLine.setForecastReason(reason);
forecastRecapLine.setAmount(amount);
forecastRecapLine.setBalance(balance);
return forecastRecapLine;
}
public String getURLForecastRecapPDF(ForecastRecap forecastRecap) throws AxelorException {
String language="";
try{
language = forecastRecap.getCompany().getPrintingSettings().getLanguageSelect() != null ? forecastRecap.getCompany().getPrintingSettings().getLanguageSelect() : "en" ;
}catch (NullPointerException e) {
language = "en";
}
language = language.equals("")? "en": language;
String title = I18n.get("ForecastRecap");
title += forecastRecap.getId();
return reportFactory.createReport(IReport.FORECAST_RECAP, title+"-${date}")
.addParam("ForecastRecapId", forecastRecap.getId().toString())
.addParam("Locale", language)
.generate()
.getFileLink();
}
}