/**
* 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.crm.service;
import java.math.BigDecimal;
import javax.persistence.Query;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import com.axelor.apps.base.db.ITarget;
import com.axelor.apps.base.db.Team;
import com.axelor.auth.db.User;
import com.axelor.apps.crm.db.IEvent;
import com.axelor.apps.crm.db.IOpportunity;
import com.axelor.apps.crm.db.Target;
import com.axelor.apps.crm.db.TargetConfiguration;
import com.axelor.apps.crm.db.repo.EventRepository;
import com.axelor.apps.crm.db.repo.OpportunityRepository;
import com.axelor.apps.crm.db.repo.TargetRepository;
import com.axelor.apps.crm.exception.IExceptionMessage;
import com.axelor.db.JPA;
import com.axelor.exception.AxelorException;
import com.axelor.exception.db.IException;
import com.axelor.i18n.I18n;
import com.google.inject.Inject;
import com.google.inject.persist.Transactional;
public class TargetService {
@Inject
private EventRepository eventRepo;
@Inject
private OpportunityRepository opportunityRepo;
@Inject
private TargetRepository targetRepo;
public void createsTargets(TargetConfiguration targetConfiguration) throws AxelorException {
if(targetConfiguration.getPeriodTypeSelect() == ITarget.NONE) {
Target target = this.createTarget(targetConfiguration, targetConfiguration.getFromDate(), targetConfiguration.getToDate());
this.update(target);
}
else {
LocalDate oldDate = targetConfiguration.getFromDate();
LocalDate date = oldDate ;
while(date.isBefore(targetConfiguration.getToDate()) || date.isEqual(targetConfiguration.getToDate())) {
date = this.getNextDate(targetConfiguration.getPeriodTypeSelect(), date);
Target target2 = targetRepo.all().filter("self.user = ?1 AND self.team = ?2 AND self.periodTypeSelect = ?3 AND self.fromDate >= ?4 AND self.toDate <= ?5 AND " +
"((self.callEmittedNumberTarget > 0 AND ?6 > 0) OR (self.meetingNumberTarget > 0 AND ?7 > 0) OR " +
"(self.opportunityAmountWonTarget > 0.00 AND ?8 > 0.00) OR (self.opportunityCreatedNumberTarget > 0 AND ?9 > 0) OR (self.opportunityCreatedWonTarget > 0 AND ?10 > 0))",
targetConfiguration.getUser(), targetConfiguration.getTeam(), targetConfiguration.getPeriodTypeSelect(), targetConfiguration.getFromDate(), targetConfiguration.getToDate(),
targetConfiguration.getCallEmittedNumber(), targetConfiguration.getMeetingNumber(),
targetConfiguration.getOpportunityAmountWon().doubleValue(), targetConfiguration.getOpportunityCreatedNumber(), targetConfiguration.getOpportunityCreatedWon()).fetchOne();
if(target2 == null) {
Target target = this.createTarget(targetConfiguration, oldDate, (date.isBefore(targetConfiguration.getToDate())) ? date.minusDays(1) : targetConfiguration.getToDate());
this.update(target);
oldDate = date;
}
else {
throw new AxelorException(String.format(I18n.get(IExceptionMessage.TARGET_1),
target2.getCode(), targetConfiguration.getCode()), IException.CONFIGURATION_ERROR);
}
}
}
}
public LocalDate getNextDate(int periodTypeSelect, LocalDate date) {
switch (periodTypeSelect) {
case ITarget.NONE:
return date;
case ITarget.MONTHLY:
return date.plusMonths(1);
case ITarget.WEEKLY:
return date.plusWeeks(1);
case ITarget.DAILY:
return date.plusDays(1);
default:
return date;
}
}
@Transactional(rollbackOn = {AxelorException.class, Exception.class})
public Target createTarget(TargetConfiguration targetConfiguration, LocalDate fromDate, LocalDate toDate) {
Target target = new Target();
target.setCallEmittedNumberTarget(targetConfiguration.getCallEmittedNumber());
target.setMeetingNumberTarget(targetConfiguration.getMeetingNumber());
target.setOpportunityAmountWonTarget(targetConfiguration.getOpportunityAmountWon());
target.setOpportunityCreatedNumberTarget(targetConfiguration.getOpportunityCreatedNumber());
target.setOpportunityCreatedWonTarget(targetConfiguration.getOpportunityCreatedWon());
// target.setSaleOrderAmountWonTarget(targetConfiguration.getSaleOrderAmountWon());
// target.setSaleOrderCreatedNumberTarget(targetConfiguration.getSaleOrderCreatedNumber());
// target.setSaleOrderCreatedWonTarget(targetConfiguration.getSaleOrderCreatedWon());
target.setPeriodTypeSelect(targetConfiguration.getPeriodTypeSelect());
target.setFromDate(fromDate);
target.setToDate(toDate);
target.setUser(targetConfiguration.getUser());
target.setTeam(targetConfiguration.getTeam());
target.setName(targetConfiguration.getName());
target.setCode(targetConfiguration.getCode());
return targetRepo.save(target);
}
@Transactional(rollbackOn = {AxelorException.class, Exception.class})
public void update(Target target) {
User user = target.getUser();
Team team = target.getTeam();
LocalDate fromDate = target.getFromDate();
LocalDate toDate = target.getToDate();
LocalDateTime fromDateTime = new LocalDateTime(fromDate.getYear(), fromDate.getMonthOfYear(), fromDate.getDayOfMonth(), 0, 0);
LocalDateTime toDateTime = new LocalDateTime(toDate.getYear(), toDate.getMonthOfYear(), toDate.getDayOfMonth(), 23, 59);
if(user != null) {
Query q = JPA.em().createQuery("select SUM(op.amount) FROM Opportunity as op WHERE op.user = ?1 AND op.salesStageSelect = ?2 AND op.createdOn >= ?3 AND op.createdOn <= ?4 ");
q.setParameter(1, user);
q.setParameter(2, IOpportunity.STAGE_CLOSED_WON);
q.setParameter(3, fromDateTime);
q.setParameter(4, toDateTime);
BigDecimal opportunityAmountWon = (BigDecimal) q.getSingleResult();
Long callEmittedNumber = eventRepo.all().filter("self.typeSelect = ?1 AND self.user = ?2 AND self.startDateTime >= ?3 AND self.endDateTime <= ?4 AND self.callTypeSelect = 2",
IEvent.CALL, user, fromDateTime, toDateTime).count();
target.setCallEmittedNumber(callEmittedNumber.intValue());
Long meetingNumber = eventRepo.all().filter("self.typeSelect = ?1 AND self.user = ?2 AND self.startDateTime >= ?3 AND self.endDateTime <= ?4",
IEvent.MEETING, user, fromDateTime, toDateTime).count();
target.setMeetingNumber(meetingNumber.intValue());
target.setOpportunityAmountWon(opportunityAmountWon);
Long opportunityCreatedNumber = opportunityRepo.all().filter("self.user = ?1 AND self.createdOn >= ?2 AND self.createdOn <= ?3",
user, fromDateTime, toDateTime).count();
target.setOpportunityCreatedNumber(opportunityCreatedNumber.intValue());
Long opportunityCreatedWon = opportunityRepo.all().filter("self.user = ?1 AND self.createdOn >= ?2 AND self.createdOn <= ?3 AND self.salesStageSelect = ?4",
user, fromDateTime, toDateTime, IOpportunity.STAGE_CLOSED_WON).count();
target.setOpportunityCreatedWon(opportunityCreatedWon.intValue());
}
else if(team != null) {
Query q = JPA.em().createQuery("select SUM(op.amount) FROM Opportunity as op WHERE op.team = ?1 AND op.salesStageSelect = ?2 AND op.createdOn >= ?3 AND op.createdOn <= ?4 ");
q.setParameter(1, team);
q.setParameter(2, IOpportunity.STAGE_CLOSED_WON);
q.setParameter(3, fromDateTime);
q.setParameter(4, toDateTime);
BigDecimal opportunityAmountWon = (BigDecimal) q.getSingleResult();
Long callEmittedNumber = eventRepo.all().filter("self.typeSelect = ?1 AND self.team = ?2 AND self.startDateTime >= ?3 AND self.endDateTime <= ?4 AND self.callTypeSelect = 2",
IEvent.CALL, team, fromDateTime, toDateTime).count();
target.setCallEmittedNumber(callEmittedNumber.intValue());
Long meetingNumber = eventRepo.all().filter("self.typeSelect = ?1 AND self.team = ?2 AND self.startDateTime >= ?3 AND self.endDateTime <= ?4",
IEvent.MEETING, team, fromDateTime, toDateTime).count();
target.setMeetingNumber(meetingNumber.intValue());
target.setOpportunityAmountWon(opportunityAmountWon);
Long opportunityCreatedNumber = opportunityRepo.all().filter("self.team = ?1 AND self.createdOn >= ?2 AND self.createdOn <= ?3",
team, fromDateTime, toDateTime).count();
target.setOpportunityCreatedNumber(opportunityCreatedNumber.intValue());
Long opportunityCreatedWon = opportunityRepo.all().filter("self.team = ?1 AND self.createdOn >= ?2 AND self.createdOn <= ?3 AND self.salesStageSelect = ?4",
team, fromDateTime, toDateTime, IOpportunity.STAGE_CLOSED_WON).count();
target.setOpportunityCreatedWon(opportunityCreatedWon.intValue());
}
targetRepo.save(target);
}
}