/*
*
* Copyright (c) 2013 - 2014 INT - National Institute of Technology & COPPE - Alberto Luiz Coimbra Institute
- Graduate School and Research in Engineering.
* See the file license.txt for copyright permission.
*
*/
package service;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import comparator.PlPerModComparatorPorPerioPM;
import modelo.CadPlan;
import modelo.Excecao;
import modelo.ExcecaoMens;
import modelo.HP;
import modelo.PerioPM;
import modelo.PlPerMod;
import modelo.PlanoModelo;
import service.anotacao.Transacional;
import service.controleTransacao.FabricaDeAppService;
import service.exception.AplicacaoException;
import DAO.ExcecaoDAO;
import DAO.ExcecaoMensDAO;
import DAO.HPDAO;
import DAO.PerioPMDAO;
import DAO.PlPerModDAO;
import DAO.PlanoModeloDAO;
import DAO.Impl.ExcecaoDAOImpl;
import DAO.Impl.ExcecaoMensDAOImpl;
import DAO.Impl.HPDAOImpl;
import DAO.Impl.PerioPMDAOImpl;
import DAO.Impl.PlPerModDAOImpl;
import DAO.Impl.PlanoModeloDAOImpl;
import DAO.controle.FabricaDeDao;
import DAO.exception.ObjetoNaoEncontradoException;
/**
* classe responsavel pela geracao das mensagens de excecao por planoModelo.
* @author arruda
*
*/
public class ExcecaoMensAppService {
// DAOs
private static PerioPMDAO perioPMDAO;
private static ExcecaoDAO excecaoDAO;
private static HPDAO hpDAO;
private static PlPerModDAO plPerModDAO;
private static PlanoModeloDAO planoModeloDAO;
private static ExcecaoMensDAO excecaoMensDAO;
// Services
private static ExcecaoAppService excecaoService;
private static PlPerModAppService plPerModService;
@SuppressWarnings("unchecked")
public ExcecaoMensAppService() {
try {
// DAOs
perioPMDAO = FabricaDeDao.getDao(PerioPMDAOImpl.class);
excecaoDAO = FabricaDeDao.getDao(ExcecaoDAOImpl.class);
hpDAO = FabricaDeDao.getDao(HPDAOImpl.class);
plPerModDAO = FabricaDeDao.getDao(PlPerModDAOImpl.class);
planoModeloDAO = FabricaDeDao.getDao(PlanoModeloDAOImpl.class);
excecaoMensDAO = FabricaDeDao.getDao(ExcecaoMensDAOImpl.class);
// Service
excecaoService = FabricaDeAppService.getAppService(ExcecaoAppService.class);
plPerModService = FabricaDeAppService.getAppService(PlPerModAppService.class);
} catch (Exception e) {
e.printStackTrace();
System.exit(1);
}
}
/**
* Inclui uma excecaoMens
* Verifica se existe j� uma com as mesmas chavez, se existir nao inclui.
*
* Se o periodoOrigem for null, utiliza a query "recuperaListaDeExcecaoMensPorPlanoModeloEExcecao", para evitar buscar perioPM null.
* Caso n�o seja null, utiliza a query: "recuperaListaDeExcecaoMensPorPlanoModeloEExcecaoEPeriodoOrigem".
*
* @param excecaoMens
* @return
* @throws AplicacaoException
*/
@Transacional
public long inclui(ExcecaoMens excecaoMens) throws AplicacaoException {
long retorno = -1;
List<ExcecaoMens> listaExecaoMens=null;
if(excecaoMens.getPeriodoOrigem() == null){
listaExecaoMens = excecaoMensDAO.recuperaListaDeExcecaoMensPorPlanoModeloEExcecao
(excecaoMens.getPlanoModelo(),excecaoMens.getExcecao());
}
else{
listaExecaoMens = excecaoMensDAO.recuperaListaDeExcecaoMensPorPlanoModeloEExcecaoEPeriodoOrigem
(excecaoMens.getPlanoModelo(),excecaoMens.getExcecao(),
excecaoMens.getPeriodoOrigem());
}
if(listaExecaoMens.size()!= 0){
throw new AplicacaoException("excecaoMens.EXCECAOMENS_EXISTENTE");
}
retorno = excecaoMensDAO.inclui(excecaoMens).getId();
return retorno;
}
/**
* Altera uma ExcecaoMens
* @param excecao
*/
@Transacional
public void altera(ExcecaoMens excecaoMens) {
excecaoMensDAO.altera(excecaoMens);
}
/**
* Exclui uma ExcecaoMens
*
* @param excecao
* @throws AplicacaoException
*/
@Transacional
public void exclui(ExcecaoMens excecaoMens) throws AplicacaoException {
ExcecaoMens excecaoParaExcuir = null;
try {
excecaoParaExcuir = excecaoMensDAO.getPorIdComLock((excecaoMens.getId()));
} catch (ObjetoNaoEncontradoException e) {
throw new AplicacaoException("excecaoMens.NAO_ENCONTRADA");
}
excecaoMensDAO.exclui(excecaoParaExcuir);
}
public void gerarMensagensExcecao(CadPlan cadPlan) throws AplicacaoException {
deletarExcecoesDoPlano(cadPlan);
List<PlanoModelo>listaPlanoModeloCadPlan = new ArrayList(cadPlan.getPlanosModelo());
Collections.sort(listaPlanoModeloCadPlan); //ordenando
for(PlanoModelo planoModelo : listaPlanoModeloCadPlan){
// try {
// planoModelo = planoModeloDAO.recuperarPlPerModsPorPlanoModelo(planoModelo);
// } catch (ObjetoNaoEncontradoException e) {
// }
List<PlPerMod>listaDePlPerMods = plPerModDAO.recuperaListaDePlPerModPorPlanoModelo(planoModelo);
Collections.sort(listaDePlPerMods, new PlPerModComparatorPorPerioPM());
planoModelo.setPlPerModsList(listaDePlPerMods);
gerarMensagemDeExcecaoPorModelo(planoModelo);
}
}
@Transacional
public void deletarExcecoesDoPlano(CadPlan cadPlan) throws AplicacaoException {
List<ExcecaoMens> excecoesDoPlano = recuperaListaDeExcecaoMensPorCadPlan(cadPlan);
for (ExcecaoMens excecaoMens: excecoesDoPlano){
exclui(excecaoMens);
}
}
public ArrayList<Map> inicializaVetorRecebimentos(ArrayList<Map> vetorRecebimentos,PlanoModelo planoModelo){
//verificar se esta ordenado nesse momento.
for(PlPerMod plPerMod : planoModelo.getPlPerModsList()){
Map novoMap = new HashMap();
novoMap.put("periodo", plPerMod.getPerioPM());
novoMap.put("recebimentoVerificado", false);
novoMap.put("producao", plPerMod.getProducaoModel());
vetorRecebimentos.add(novoMap);
}
return vetorRecebimentos;
}
/**
* Cria uma mensagem de excecao usando os parametros passados.
* Caso o periodoDestino e o periodoOrigem n�o existam, entao cria usando null em ambos.
*
* @param planoModelo
* @param periodoOrigem
* @param periodoDestino
* @param excecao
* @param quantidade
* @return
* @throws AplicacaoException
*/
public ExcecaoMens criaMensagemExcecao(PlanoModelo planoModelo,
int periodoOrigem,int periodoDestino,Excecao excecao,Double quantidade) throws AplicacaoException{
ExcecaoMens novaMensagem = new ExcecaoMens();
novaMensagem.setPlanoModelo(planoModelo);
novaMensagem.setExcecao(excecao);
PerioPM perioOrigem=null;
PerioPM perioDestino=null;
try{
perioOrigem = perioPMDAO.recuperaPerioPMPorPeriodoPM(periodoOrigem);
}
catch(ObjetoNaoEncontradoException e){
}
try{
perioDestino = perioPMDAO.recuperaPerioPMPorPeriodoPM(periodoDestino);
}
catch(ObjetoNaoEncontradoException e){
}
novaMensagem.setPeriodoOrigem(perioOrigem);
novaMensagem.setPeriodoDestino(perioDestino);
novaMensagem.setQuantidade(quantidade);
inclui(novaMensagem);
return novaMensagem;
}
public void gerarMensagemDeExcecaoPorModelo(PlanoModelo planoModelo) {
ArrayList<Map> vetorRecebimentos = new ArrayList<Map>();
vetorRecebimentos = inicializaVetorRecebimentos(vetorRecebimentos,planoModelo);
List<Excecao> excecoes = excecaoService.inicializaVetorExcecao();
double demandaTotalDoHP = 0.0;
double estoqueInicModelCalc = planoModelo.getModelo().getEstqInicModel()
+ planoModelo.getModelo().getRecebimentoPendente()
- planoModelo.getModelo().getEstqEmFalta();
//representa a porcentagem permitida considerada toleravel no calculo do excesso da cobertura de estoque.
double limiteSuperior = planoModelo.getModelo().getCobertura()*1.25;
//msg sobre saldo inicial negativo
if(excecoes.get(1).getStatusExcecao()){
if(estoqueInicModelCalc < 0){
try {
criaMensagemExcecao(planoModelo,0,0,excecoes.get(1),estoqueInicModelCalc);
} catch (AplicacaoException e) {
}
}
}
//msg sobre recebimento pendente com prazo vencido
if(excecoes.get(5).getStatusExcecao()){
if(planoModelo.getModelo().getRecebimentoPendente() > 0){
try {
criaMensagemExcecao(planoModelo,0,0,excecoes.get(5),planoModelo.getModelo().getRecebimentoPendente());
} catch (AplicacaoException e) {
}
}
}
//msg sobre estoque em falta
if(excecoes.get(4).getStatusExcecao()){
if(planoModelo.getModelo().getEstqEmFalta() > 0){
try {
criaMensagemExcecao(planoModelo,0,0,excecoes.get(4),planoModelo.getModelo().getEstqEmFalta());
} catch (AplicacaoException e) {
}
}
}
//percorre todos os plpermods desse planoModelo
for(PlPerMod plPerMod : planoModelo.getPlPerModsList()){
//inicio do PMP antes do primeiro periodo do HP
if(excecoes.get(3).getStatusExcecao()){
if(plPerMod.getPeriodoPMInicioPMP() < 1){
try {
criaMensagemExcecao(planoModelo, plPerMod.getPerioPM().getPeriodoPM(), 0,
excecoes.get(3), null);
} catch (AplicacaoException e) {
}
}
}
if(plPerMod.getProducaoModel() != 0){
//ordem prestes a ser liberada
if(excecoes.get(4).getStatusExcecao()){
if(plPerMod.getPeriodoPMInicioPMP() == 1){
try {
criaMensagemExcecao(planoModelo, plPerMod.getPerioPM().getPeriodoPM(), 0,
excecoes.get(4), plPerMod.getProducaoModel());
} catch (AplicacaoException e) {
}
}
}
}
//mensagem : Estoque Excessivo no Periodo
//se tiver estoque excessivo no per�odo, al�m de 15% acima da cobertura de estoque desejada para o per�odo
//estou trabalhando com uma margem pois o proprio algoritmo de inclus�o, como faz muitos arredondamentos para cima
// devido ao tam lote acaba sempre trabalhando com um valor um pouco acima do desejado
if(excecoes.get(9).getStatusExcecao() &&
plPerMod.getCoberturaModel() > limiteSuperior){
try {
criaMensagemExcecao(planoModelo, plPerMod.getPerioPM().getPeriodoPM(), 0,
excecoes.get(9), plPerMod.getDispProjModel());
} catch (AplicacaoException e) {
}
}
demandaTotalDoHP = demandaTotalDoHP + Math.max(plPerMod.getPedidosModel(), plPerMod.getVendasModel());
}
//estoque inicial excessivo
if(excecoes.get(2).getStatusExcecao()){
if(estoqueInicModelCalc > demandaTotalDoHP){
try {
criaMensagemExcecao(planoModelo, 0, 0,excecoes.get(2),
(estoqueInicModelCalc - demandaTotalDoHP));
} catch (AplicacaoException e) {
}
}
}
//antecipar, postergar e cancelar recebimento de producao
if(excecoes.get(6).getStatusExcecao() ||
excecoes.get(7).getStatusExcecao() ||
excecoes.get(8).getStatusExcecao()){
double disponibilidade = estoqueInicModelCalc;
//para todos os periodos da lista fazer:
//percorre todos os periodos do plper mod do plano e do modelo
//at� atingir a disponibilidade desejada
//antecipa os recebimentos que ocorrem apos o momento necessario
//e posterga aqueles que ocorrem antes do AuxPeriodo necessario.
HP hp = hpDAO.recuperaListaDeHP().get(0);
List<PerioPM> periodosHP = perioPMDAO.recuperaIntervaloDePerioPMs(hp.getPerioPMInicPMP().getPeriodoPM(),
hp.getPerioPMFinalPMP().getPeriodoPM());
for (PerioPM perioPM : periodosHP){
PlPerMod plPerMod =null;
try {
plPerMod = plPerModDAO.recuperaPlPerModPorPlanoModeloEPerioPM(planoModelo, perioPM);
} catch (ObjetoNaoEncontradoException e) {
}
disponibilidade = disponibilidade - Math.max(plPerMod.getPedidosModel(), plPerMod.getVendasModel());
double demandaMaxProxPeriodo = plPerModService.obtemDemandaMaxProxPeriodo(plPerMod, hp);
double disponibilidadeDesejada = demandaMaxProxPeriodo * planoModelo.getModelo().getCobertura() / 100;
// double disponibilidadeDesejada = Math.max(plPerMod.getPedidosModel(), plPerMod.getVendasModel())
// * planoModelo.getModelo().getCobertura() / 100;
Map infosRecebimento = new HashMap();
boolean localizouRecebimento = true;
int numPeriodoRecebimento =0;//???
double proxRecebimento =0;//????
infosRecebimento.put("localizouRecebimento", localizouRecebimento);
infosRecebimento.put("numPeriodoRecebimento", 0);//???
infosRecebimento.put("proxRecebimento", proxRecebimento);
while(disponibilidade < disponibilidadeDesejada && localizouRecebimento){
//aparentemente vetorRecebimentos esta sendo alterado, mesmo sem retornar como parametro
infosRecebimento = localizaProxRecebimentoPMP(infosRecebimento, vetorRecebimentos, hp);
//recupera as infos do map
localizouRecebimento = (Boolean)infosRecebimento.get("localizouRecebimento");
numPeriodoRecebimento = (Integer)infosRecebimento.get("numPeriodoRecebimento");
proxRecebimento = (Double)infosRecebimento.get("proxRecebimento");
if(localizouRecebimento){
disponibilidade = disponibilidade + proxRecebimento;
//mensagem : antecipar recebimento
//vai antecipar mesmo que com esse recebimento
//a disponibilidade fique um pouco maior que a desejada naquele periodo,
//para evitar falta.
//� uma postura conservadora.
if(excecoes.get(6).getStatusExcecao() && numPeriodoRecebimento > perioPM.getPeriodoPM()){
try {
criaMensagemExcecao(planoModelo, numPeriodoRecebimento, perioPM.getPeriodoPM(),
excecoes.get(6), proxRecebimento);
} catch (AplicacaoException e) {
}
}
//mensagem: postergar recebimento
if(excecoes.get(7).getStatusExcecao() && numPeriodoRecebimento < perioPM.getPeriodoPM()){
try {
criaMensagemExcecao(planoModelo,numPeriodoRecebimento, perioPM.getPeriodoPM(),
excecoes.get(7), proxRecebimento);
} catch (AplicacaoException e) {
}
}
}
}
}
//mensagem de cancelamento de recebimento
/*se ja atingiu a disponibilidade desejada e saiu do loop
* antes de chegar a verificar todos os periodos
* e portanto ainda tiver recebimentos programados nao
* verificados, entao esses devem ser cancelados pois estao excedendo a quantidade
* necessaria
*/
if(excecoes.get(8).getStatusExcecao()){
Map infosRecebimento = new HashMap();
boolean localizouRecebimento = true;
int numPeriodoRecebimento =0;
double proxRecebimento =0;
infosRecebimento.put("localizouRecebimento", localizouRecebimento);
infosRecebimento.put("numPeriodoRecebimento", 0);
infosRecebimento.put("proxRecebimento", proxRecebimento);
while(localizouRecebimento){
//aparentemente vetorRecebimentos esta sendo alterado, mesmo sem retornar como parametro
infosRecebimento = localizaProxRecebimentoPMP(infosRecebimento, vetorRecebimentos, hp);
//recupera as infos do map
localizouRecebimento = (Boolean)infosRecebimento.get("localizouRecebimento");
numPeriodoRecebimento = (Integer)infosRecebimento.get("numPeriodoRecebimento");
proxRecebimento = (Double)infosRecebimento.get("proxRecebimento");
if(localizouRecebimento){
try {
criaMensagemExcecao(planoModelo, numPeriodoRecebimento, 0, excecoes.get(8), proxRecebimento);
} catch (AplicacaoException e) {
}
}
}
}
}
}
public Map localizaProxRecebimentoPMP(Map parametrosEntrada,ArrayList<Map> vetorRecebimentos, HP hp){
boolean localizouRecebimento = (Boolean)parametrosEntrada.get("localizouRecebimento");
int numPeriodoRecebimento = (Integer)parametrosEntrada.get("numPeriodoRecebimento");
double proxRecebimento = (Double)parametrosEntrada.get("proxRecebimento");
localizouRecebimento = false;
parametrosEntrada.put("localizouRecebimento", localizouRecebimento);
int perio = 1;
//percorre todos valores(maps) do vetor de recebimento(periodos basicamente)
for(Map mapPeriodoCorrenteVetorReceb : vetorRecebimentos){
//se localizar entao sai do loop
if(localizouRecebimento)
break;
//recupera as infos do map atual do vetorRecebimentos (recebimentoVerificado do periodo sendo analisado)
boolean recebimentoVerificado = (Boolean)mapPeriodoCorrenteVetorReceb.get("recebimentoVerificado");
double producao = (Double)mapPeriodoCorrenteVetorReceb.get("producao");
PerioPM periodo = (PerioPM)mapPeriodoCorrenteVetorReceb.get("periodo");
if(!recebimentoVerificado && producao != 0){
parametrosEntrada.put("localizouRecebimento", true);
parametrosEntrada.put("numPeriodoRecebimento", periodo.getPeriodoPM());
parametrosEntrada.put("proxRecebimento", producao);
mapPeriodoCorrenteVetorReceb.put("recebimentoVerificado", true);
localizouRecebimento=true;
}
}
return parametrosEntrada;
}
public List<ExcecaoMens> recuperaListaPaginadaDeExcecaoMens(){
return excecaoMensDAO.recuperaListaPaginadaDeExcecaoMens();
}
public List<ExcecaoMens> recuperaListaDeExcecaoMensPorPlanoModelo(PlanoModelo planoModelo){
return excecaoMensDAO.recuperaListaDeExcecaoMensPorPlanoModelo(planoModelo);
}
/**
* Percorre os planosModelos do cadPlan em questao e retorna a lista de
* ExcecaoMens de todos os planos.
* @param cadPlanCorrente
* @return
*/
@Transacional
public List<ExcecaoMens> recuperaListaDeExcecaoMensPorCadPlan(CadPlan cadPlanCorrente){
List<ExcecaoMens> listaExcecaoMens = new ArrayList<ExcecaoMens>();
for(PlanoModelo planoModelo : cadPlanCorrente.getPlanosModelo()){
listaExcecaoMens.addAll(excecaoMensDAO.recuperaListaDeExcecaoMensPorPlanoModelo(planoModelo));
}
return listaExcecaoMens;
}
}