/*
* @(#)EmailDigesterUtil.java
*
* Copyright 2010 Instituto Superior Tecnico
* Founding Authors: Luis Cruz
*
* https://fenix-ashes.ist.utl.pt/
*
* This file is part of the Working Capital Module.
*
* The Working Capital Module is free software: you can
* redistribute it and/or modify it under the terms of the GNU Lesser General
* Public License as published by the Free Software Foundation, either version
* 3 of the License, or (at your option) any later version.
*
* The Working Capital Module 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Working Capital Module. If not, see <http://www.gnu.org/licenses/>.
*
*/
package module.workingCapital.domain;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.fenixedu.bennu.core.domain.Bennu;
import org.fenixedu.bennu.core.domain.User;
import org.fenixedu.bennu.core.groups.Group;
import org.fenixedu.bennu.core.i18n.BundleUtil;
import org.fenixedu.bennu.core.security.Authenticate;
import org.fenixedu.bennu.core.util.CoreConfiguration;
import org.fenixedu.commons.i18n.I18N;
import org.fenixedu.commons.i18n.LocalizedString;
import org.fenixedu.messaging.core.domain.Message;
import org.fenixedu.messaging.core.template.DeclareMessageTemplate;
import org.fenixedu.messaging.core.template.TemplateParameter;
import org.jfree.data.time.Month;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import module.workflow.util.PresentableProcessState;
import module.workingCapital.util.Bundle;
import pt.ist.expenditureTrackingSystem.domain.ExpenditureTrackingSystem;
import pt.ist.expenditureTrackingSystem.domain.RoleType;
import pt.ist.expenditureTrackingSystem.domain.authorizations.Authorization;
import pt.ist.expenditureTrackingSystem.domain.organization.AccountingUnit;
import pt.ist.expenditureTrackingSystem.domain.organization.Person;
/**
*
* @author Luis Cruz
*
*/
@DeclareMessageTemplate(id = "expenditures.capital.pending", bundle = Bundle.WORKING_CAPITAL,
description = "template.capital.pending", subject = "template.capital.pending.subject",
text = "template.capital.pending.text", parameters = {
@TemplateParameter(id = "applicationTitle", description = "template.parameter.application.subtitle"),
@TemplateParameter(id = "applicationUrl", description = "template.parameter.application.url"),
@TemplateParameter(id = "processesByType", description = "template.parameter.processes.by.type"),
@TemplateParameter(id = "processesTotal", description = "template.parameter.processes.total") })
@DeclareMessageTemplate(id = "expenditures.capital.pending.termination", bundle = Bundle.WORKING_CAPITAL,
description = "template.capital.pending.termination", subject = "template.capital.pending.termination.subject",
text = "template.capital.pending.termination.text", parameters = {
@TemplateParameter(id = "applicationTitle", description = "template.parameter.application.subtitle"),
@TemplateParameter(id = "applicationUrl", description = "template.parameter.application.url"),
@TemplateParameter(id = "unit", description = "template.parameter.unit"),
@TemplateParameter(id = "year", description = "template.parameter.year") })
public class EmailDigesterUtil {
public static final String BUNDLE = "resources.MissionResources", TAKEN = "taken", PENDING_APPROVAL = "approval",
PENDING_VERIFICATION = "verification", PENDING_AUTHORIZATION = "authorization", PENDING_PAYMENT = "payment",
PENDING_PROCESSING = "processing";
public static class WorkingCapitalProcessBean implements Comparable<WorkingCapitalProcessBean> {
private String unit;
private Integer year;
public String getUnit() {
return unit;
}
public Integer getYear() {
return year;
}
public WorkingCapitalProcessBean(WorkingCapital capital) {
this.unit = capital.getUnit().getPresentationName();
this.year = capital.getWorkingCapitalYear().getYear();
}
@Override
public int compareTo(WorkingCapitalProcessBean b) {
return unit.compareTo(b.getUnit());
}
}
private static List<WorkingCapitalProcessBean> getMissionProcessBeans(Set<WorkingCapitalProcess> processes) {
return processes.stream().map(p -> new WorkingCapitalProcessBean(p.getWorkingCapital())).sorted()
.collect(Collectors.toList());
}
public static void executeTask() {
final DateTime now = new DateTime();
I18N.setLocale(new Locale(CoreConfiguration.getConfiguration().defaultLocale()));
for (Person person : getPeopleToProcess()) {
final User user = person.getUser();
if (user.getPerson() != null && user.getExpenditurePerson() != null) {
Authenticate.mock(user);
try {
final LocalizedString applicationTitle = Bennu.getInstance().getConfiguration().getApplicationSubTitle();
final String applicationUrl = CoreConfiguration.getConfiguration().applicationUrl();
final WorkingCapitalYear workingCapitalYear = WorkingCapitalYear.getCurrentYear();
final LocalDate today = new LocalDate();
final WorkingCapitalYear previousYear =
today.getMonthOfYear() == Month.JANUARY ? WorkingCapitalYear.findOrCreate(today.getYear() - 1) : null;
Map<String, List<WorkingCapitalProcessBean>> processesTypeMap = new LinkedHashMap<>();
if (previousYear == null) {
processesTypeMap.put(TAKEN, getMissionProcessBeans(workingCapitalYear.getTaken()));
processesTypeMap.put(PENDING_APPROVAL, getMissionProcessBeans(workingCapitalYear.getPendingAproval()));
processesTypeMap.put(PENDING_VERIFICATION,
getMissionProcessBeans(workingCapitalYear.getPendingVerification()));
processesTypeMap.put(PENDING_PROCESSING,
getMissionProcessBeans(workingCapitalYear.getPendingProcessing()));
processesTypeMap.put(PENDING_AUTHORIZATION,
getMissionProcessBeans(workingCapitalYear.getPendingAuthorization()));
processesTypeMap.put(PENDING_PAYMENT, getMissionProcessBeans(workingCapitalYear.getPendingPayment()));
} else {
processesTypeMap.put(TAKEN, getMissionProcessBeans(previousYear.getTaken(workingCapitalYear.getTaken())));
processesTypeMap.put(PENDING_APPROVAL,
getMissionProcessBeans(previousYear.getPendingAproval(workingCapitalYear.getPendingAproval())));
processesTypeMap.put(PENDING_VERIFICATION, getMissionProcessBeans(previousYear
.getPendingVerification(workingCapitalYear.getPendingVerification())));
processesTypeMap.put(PENDING_PROCESSING, getMissionProcessBeans(previousYear
.getPendingProcessing(workingCapitalYear.getPendingProcessing())));
processesTypeMap.put(PENDING_AUTHORIZATION, getMissionProcessBeans(previousYear
.getPendingAuthorization(workingCapitalYear.getPendingAuthorization())));
processesTypeMap.put(PENDING_PAYMENT,
getMissionProcessBeans(previousYear.getPendingPayment(workingCapitalYear.getPendingPayment())));
}
final int totalPending = processesTypeMap.values().stream().map(Collection::size).reduce(0, Integer::sum);
if (totalPending > 0) {
Message.fromSystem().to(Group.users(user)).template("expenditures.capital.pending")
.parameter("applicationTitle", applicationTitle).parameter("applicationUrl", applicationUrl)
.parameter("processesByType", processesTypeMap).parameter("processesTotal", totalPending).and()
.send();
}
for (final WorkingCapital workingCapital : user.getPerson().getMovementResponsibleWorkingCapitalsSet()) {
final Integer year = workingCapital.getWorkingCapitalYear().getYear();
if (year.intValue() < now.getYear() || (year.intValue() == now.getYear() && now.getMonthOfYear() == 12)
&& now.getDayOfMonth() > 15) {
final PresentableProcessState state = workingCapital.getPresentableAcquisitionProcessState();
if (state == WorkingCapitalProcessState.WORKING_CAPITAL_AVAILABLE) {
Message.fromSystem().to(Group.users(user)).template("expenditures.capital.pending.termination")
.parameter("applicationTitle", applicationTitle)
.parameter("applicationUrl", applicationUrl)
.parameter("unit", workingCapital.getUnit().getPresentationName())
.parameter("year", workingCapital.getWorkingCapitalYear().getYear()).and().send();
}
}
}
} finally {
Authenticate.unmock();
}
}
}
}
protected String getBundle() {
return "resources.ContentResources";
}
protected String getMessage(final String key) {
return BundleUtil.getString(getBundle(), key);
}
private static Collection<Person> getPeopleToProcess() {
final Set<Person> people = new HashSet<Person>();
final LocalDate today = new LocalDate();
final ExpenditureTrackingSystem instance = ExpenditureTrackingSystem.getInstance();
for (final Authorization authorization : instance.getAuthorizationsSet()) {
if (authorization.isValidFor(today)) {
final Person person = authorization.getPerson();
if (person.getOptions().getReceiveNotificationsByEmail()) {
people.add(person);
}
}
}
for (final RoleType roleType : RoleType.values()) {
addPeopleWithRole(people, roleType);
}
for (final AccountingUnit accountingUnit : instance.getAccountingUnitsSet()) {
addPeople(people, accountingUnit.getPeopleSet());
addPeople(people, accountingUnit.getProjectAccountantsSet());
addPeople(people, accountingUnit.getResponsiblePeopleSet());
addPeople(people, accountingUnit.getResponsibleProjectAccountantsSet());
addPeople(people, accountingUnit.getTreasuryMembersSet());
}
final WorkingCapitalYear workingCapitalYear = WorkingCapitalYear.getCurrentYear();
addMovementResponsibles(people, workingCapitalYear);
if (today.getMonthOfYear() == Month.JANUARY) {
final WorkingCapitalYear previousYear = WorkingCapitalYear.findOrCreate(today.getYear() - 1);
addMovementResponsibles(people, previousYear);
}
return people;
}
private static void addMovementResponsibles(final Set<Person> people, final WorkingCapitalYear workingCapitalYear) {
for (final WorkingCapital workingCapital : workingCapitalYear.getWorkingCapitalsSet()) {
final module.organization.domain.Person movementResponsible = workingCapital.getMovementResponsible();
if (movementResponsible.getUser() != null) {
final User user = movementResponsible.getUser();
if (user.getExpenditurePerson() != null) {
final Person person = user.getExpenditurePerson();
if (person.getOptions().getReceiveNotificationsByEmail()) {
people.add(person);
}
}
}
}
}
private static void addPeopleWithRole(final Set<Person> people, final RoleType roleType) {
addUsers(people, roleType.group().getMembers());
}
private static void addUsers(Set<Person> people, Stream<User> members) {
members.forEach(u -> addPerson(people, u.getExpenditurePerson()));
}
private static void addPerson(Set<Person> people, Person person) {
if (person.getOptions().getReceiveNotificationsByEmail()) {
people.add(person);
}
}
private static void addPeople(final Set<Person> people, Collection<Person> unverified) {
for (final Person person : unverified) {
addPerson(people, person);
}
}
}