/**
*
*/
package net.conselldemallorca.helium.core.helper;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import javax.annotation.Resource;
import net.conselldemallorca.helium.core.model.hibernate.DefinicioProces;
import net.conselldemallorca.helium.core.model.hibernate.Festiu;
import net.conselldemallorca.helium.core.model.hibernate.Termini;
import net.conselldemallorca.helium.core.model.hibernate.TerminiIniciat;
import net.conselldemallorca.helium.core.util.GlobalProperties;
import net.conselldemallorca.helium.jbpm3.integracio.JbpmHelper;
import net.conselldemallorca.helium.v3.core.api.dto.TerminiIniciatDto;
import net.conselldemallorca.helium.v3.core.api.exception.NoTrobatException;
import net.conselldemallorca.helium.v3.core.repository.FestiuRepository;
import net.conselldemallorca.helium.v3.core.repository.TerminiIniciatRepository;
import net.conselldemallorca.helium.v3.core.repository.TerminiRepository;
import org.springframework.stereotype.Component;
/**
* Helper per a enviament de correus
*
* @author Limit Tecnologies <limit@limit.es>
*/
@Component("TerminiHelperV3")
public class TerminiHelper {
@Resource
private TerminiRepository terminiRepository;
@Resource
private TerminiIniciatRepository terminiIniciatRepository;
@Resource
private FestiuRepository festiuRepository;
@Resource
private JbpmHelper jbpmHelper;
@Resource
private ConversioTipusHelper conversioTipusHelper;
@Resource
private MessageHelper messageHelper;
public TerminiIniciatDto iniciar(
Long terminiId,
String processInstanceId,
Date data,
boolean esDataFi) {
Termini termini = terminiRepository.findOne(terminiId);
if (termini == null)
throw new NoTrobatException(Termini.class, terminiId);
TerminiIniciat terminiIniciat = terminiIniciatRepository.findByTerminiAndProcessInstanceId(
termini,
processInstanceId);
if (terminiIniciat == null) {
return iniciar(
terminiId,
processInstanceId,
data,
termini.getAnys(),
termini.getMesos(),
termini.getDies(),
esDataFi);
} else {
return iniciar(
terminiId,
processInstanceId,
data,
terminiIniciat.getAnys(),
terminiIniciat.getMesos(),
terminiIniciat.getDies(),
esDataFi);
}
}
public TerminiIniciatDto iniciar(
Long terminiId,
String processInstanceId,
Date data,
int anys,
int mesos,
int dies,
boolean esDataFi) {
Termini termini = terminiRepository.findOne(terminiId);
if (termini == null)
throw new NoTrobatException(Termini.class, terminiId);
TerminiIniciat terminiIniciat = terminiIniciatRepository.findByTerminiAndProcessInstanceId(
termini,
processInstanceId);
if (terminiIniciat == null) {
if (esDataFi) {
Date dataInici = getDataIniciTermini(
data,
anys,
mesos,
dies,
termini.isLaborable());
terminiIniciat = new TerminiIniciat(
termini,
anys,
mesos,
dies,
processInstanceId,
dataInici,
data);
} else {
Date dataFi = getDataFiTermini(
data,
anys,
mesos,
dies,
termini.isLaborable());
terminiIniciat = new TerminiIniciat(
termini,
anys,
mesos,
dies,
processInstanceId,
data,
dataFi);
}
} else {
if (esDataFi) {
Date dataInici = getDataIniciTermini(
data,
anys,
mesos,
dies,
termini.isLaborable());
terminiIniciat.setDataInici(dataInici);
terminiIniciat.setDataFi(data);
} else {
Date dataFi = getDataFiTermini(
data,
anys,
mesos,
dies,
termini.isLaborable());
terminiIniciat.setDataInici(data);
terminiIniciat.setDataFi(dataFi);
}
terminiIniciat.setDataAturada(null);
terminiIniciat.setDataCancelacio(null);
resumeTimers(terminiIniciat);
}
terminiIniciatRepository.save(terminiIniciat);
return conversioTipusHelper.convertir(
terminiIniciat,
TerminiIniciatDto.class);
}
public void pausar(Long terminiIniciatId, Date data) {
TerminiIniciat terminiIniciat = terminiIniciatRepository.findOne(terminiIniciatId);
if (terminiIniciat.getDataInici() == null)
throw new IllegalStateException(
messageHelper.getMessage("error.terminiService.noIniciat"));
terminiIniciat.setDataAturada(data);
suspendTimers(terminiIniciat);
}
public void continuar(Long terminiIniciatId, Date data) {
TerminiIniciat terminiIniciat = terminiIniciatRepository.findOne(terminiIniciatId);
if (terminiIniciat.getDataAturada() == null)
throw new IllegalStateException(
messageHelper.getMessage("error.terminiService.noPausat"));
int diesAturat = terminiIniciat.getNumDiesAturadaActual(data);
terminiIniciat.setDiesAturat(terminiIniciat.getDiesAturat() + diesAturat);
terminiIniciat.setDataAturada(null);
resumeTimers(terminiIniciat);
}
public void cancelar(Long terminiIniciatId, Date data) {
TerminiIniciat terminiIniciat = terminiIniciatRepository.findOne(terminiIniciatId);
if (terminiIniciat.getDataInici() == null)
throw new IllegalStateException(
messageHelper.getMessage("error.terminiService.noIniciat"));
terminiIniciat.setDataCancelacio(data);
suspendTimers(terminiIniciat);
}
public Date getDataFiTermini(
Date inici,
int anys,
int mesos,
int dies,
boolean laborable) {
Calendar dataFi = Calendar.getInstance();
dataFi.setTime(inici); //inicialitzam la data final amb la data d'inici
// Afegim els anys i mesos
if (anys > 0) {
dataFi.add(Calendar.YEAR, anys);
dataFi.add(Calendar.DAY_OF_YEAR, -1);
}
if (mesos > 0) {
dataFi.add(Calendar.MONTH, mesos);
dataFi.add(Calendar.DAY_OF_YEAR, -1);
}
if (dies > 0) {
// Depenent de si el termini és laborable o no s'afegiran més o manco dies
if (laborable) {
sumarDies(dataFi, dies);
} else {
dataFi.add(Calendar.DATE, dies - 1);
// Si el darrer dia cau en festiu es passa al dia laborable següent
sumarDies(dataFi, 1);
}
// El termini en realitat acaba a les 23:59 del darrer dia
dataFi.set(Calendar.HOUR_OF_DAY, 23);
dataFi.set(Calendar.MINUTE, 59);
dataFi.set(Calendar.SECOND, 59);
dataFi.set(Calendar.MILLISECOND, 999);
}
return dataFi.getTime();
}
public Date getDataIniciTermini(
Date fi,
int anys,
int mesos,
int dies,
boolean laborable) {
Calendar dataInici = Calendar.getInstance();
dataInici.setTime(fi); //inicialitzam la data final amb la data d'inici
// Afegim els anys i mesos
if (anys > 0) {
dataInici.add(Calendar.YEAR, -anys);
dataInici.add(Calendar.DAY_OF_YEAR, -1);
}
if (mesos > 0) {
dataInici.add(Calendar.MONTH, -mesos);
dataInici.add(Calendar.DAY_OF_YEAR, -1);
}
if (dies > 0) {
// Depenent de si el termini és laborable o no s'afegiran més o manco dies
if (laborable) {
sumarDies(dataInici, -dies);
} else {
dataInici.add(Calendar.DATE, -dies + 1);
// Si el darrer dia cau en festiu es passa al dia laborable següent
sumarDies(dataInici, -1);
}
// El termini en realitat s'inicia a les 00:00h
dataInici.set(Calendar.HOUR_OF_DAY, 0);
dataInici.set(Calendar.MINUTE, 0);
dataInici.set(Calendar.SECOND, 0);
dataInici.set(Calendar.MILLISECOND, 0);
}
return dataInici.getTime();
}
public Termini findTerminiById(Long terminiId) {
return terminiRepository.findOne(terminiId);
}
public TerminiIniciat findTerminiIniciatById(Long terminiIniciatId) {
return terminiIniciatRepository.findOne(terminiIniciatId);
}
public Termini findAmbDefinicioProcesICodi(
DefinicioProces definicioProces,
String terminiCodi) {
return terminiRepository.findByDefinicioProcesAndCodi(
definicioProces,
terminiCodi);
}
public TerminiIniciat findIniciatAmbDefinicioProcesICodi(
DefinicioProces definicioProces,
String processInstanceId,
String terminiCodi) {
Termini termini = terminiRepository.findByDefinicioProcesAndCodi(
definicioProces,
terminiCodi);
if (termini == null)
return null;
return terminiIniciatRepository.findByTerminiAndProcessInstanceId(
termini,
processInstanceId);
}
private void sumarDies(Calendar cal, int numDies) {
int signe = (numDies < 0) ? -1 : 1;
int nd = (numDies < 0) ? -numDies : numDies;
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.set(Calendar.MINUTE, 0);
cal.set(Calendar.SECOND, 0);
cal.set(Calendar.MILLISECOND, 0);
List<Festiu> festius = festiuRepository.findAll();
int diesLabs = 0;
while (diesLabs < nd) {
if (!esFestiu(cal, festius))
diesLabs ++;
cal.add(Calendar.DATE, signe);
}
cal.add(Calendar.DATE, -signe);
}
private boolean esFestiu(
Calendar cal,
List<Festiu> festius) {
int diasem = cal.get(Calendar.DAY_OF_WEEK);
for (int nolab: getDiesNoLaborables()) {
if (diasem == nolab)
return true;
}
for (Festiu festiu: festius) {
if (cal.getTime().compareTo(festiu.getData()) == 0)
return true;
}
return false;
}
private int[] getDiesNoLaborables() {
String nolabs = GlobalProperties.getInstance().getProperty("app.calendari.nolabs");
if (nolabs != null) {
String[] dies = nolabs.split(",");
int[] resposta = new int[dies.length];
for (int i = 0; i < dies.length; i++) {
resposta[i] = (Integer.parseInt(dies[i]) % 7) + 1;
}
return resposta;
}
return new int[0];
}
private void suspendTimers(TerminiIniciat terminiIniciat) {
long[] timerIds = terminiIniciat.getTimerIdsArray();
for (int i = 0; i < timerIds.length; i++)
jbpmHelper.suspendTimer(
timerIds[i],
new Date(Long.MAX_VALUE));
}
private void resumeTimers(TerminiIniciat terminiIniciat) {
long[] timerIds = terminiIniciat.getTimerIdsArray();
for (int i = 0; i < timerIds.length; i++)
jbpmHelper.resumeTimer(
timerIds[i],
terminiIniciat.getDataFi());
}
}