package com.fp.general.rules.save; import java.sql.Date; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.HashMap; import java.util.List; import java.util.Map; import javax.persistence.Query; import com.fp.common.helper.CalculationBase; import com.fp.common.helper.Constant; import com.fp.dto.rules.TransactionRule; import com.fp.dto.save.SaveRequest; import com.fp.general.exception.GeneralException; import com.fp.persistence.commondb.PersistenceHelper; import com.fp.persistence.commondb.db.DataHelper; import com.fp.persistence.commondb.helper.APPDates; import com.fp.persistence.pgeneral.date.TgeneAccountingDate; import com.fp.persistence.pgeneral.date.TgeneAccountingDateBranch; import com.fp.persistence.pgeneral.date.TgeneAccountingDateKey; import com.fp.persistence.pgeneral.date.TgeneNotAccountingDay; import com.fp.persistence.pgeneral.gene.TgeneBranch; import com.fp.persistence.pgeneral.gene.TgeneBranchKey; /** * Clase que se encarga de generar las fechas contables para un tiempo * determinado * * @author scastillo * @version 2.1 */ public class GenerateAccountingDate extends TransactionRule { /** * Map que contiene los datos del request de los dias contables y no * contables */ private Map> mdays = new HashMap>(); /** * Lista de dias no contables por mes. */ private List lnotaccountingdays; /** * Fecha de inicio de generacion del calendario. */ private Date initdatedate; /** * Fecha de finalizacion de genercion del calendario. */ private Date enddate; /** * Metodo que genra las fechas contables * * @param saveRequest Datos del request original. * @return SaveRequest * @throws Exception */ public SaveRequest normalProcess(SaveRequest saveRequest) throws Exception { this.fillMapDay(saveRequest); lnotaccountingdays = TgeneNotAccountingDay.findAll(PersistenceHelper.getEntityManager()); enddate = (Date) saveRequest.get("enddate"); this.processBranches(saveRequest); return saveRequest; } /** * Metodo que genera fechas contables para la sucursal oficina de proceso. * * @param saveRequest Datos del request original. * @throws Exception */ private void processBranches(SaveRequest saveRequest) throws Exception { Integer init = Integer.parseInt(saveRequest.get("branchcodemin").toString()); Integer end = Integer.parseInt(saveRequest.get("branchcodemax").toString()); while (init <= end) { TgeneBranchKey tgeneBranchKey = new TgeneBranchKey(init, saveRequest.getCompany()); TgeneBranch tgeneBranch = TgeneBranch.find(PersistenceHelper.getEntityManager(), tgeneBranchKey); if (tgeneBranch != null) { //Obtiene la fecha de inicio por cada sucursal initdatedate = (Date) saveRequest.get("initdate"); this.delete(init, saveRequest.getCompany()); this.validateDatesByBranch(init, saveRequest.getCompany()); this.processByDate(saveRequest, init); } init++; } } private void processByDate(SaveRequest saveRequest, Integer pBranch) throws Exception { APPDates d = new APPDates(initdatedate, CalculationBase.B365365); while (initdatedate.compareTo(enddate) <= 0) { this.generateCalendar(saveRequest, pBranch, d); d.addField(Calendar.DAY_OF_YEAR, 1); initdatedate = d.getDate(); } } /** * * @param saveRequest Datos del request original. * @param pBranch Codigo de sucursal a generar la fecha contable. * @param d Fecha real con la cual se obtiene la fecha de trabajo y la * contable. * @throws Exception */ private void generateCalendar(SaveRequest saveRequest, Integer pBranch, APPDates d) throws Exception { Map m = this.mdays.get(d.getField(Calendar.DAY_OF_WEEK)); TgeneAccountingDateKey key = new TgeneAccountingDateKey(); key.setCompanycode(saveRequest.getCompany()); key.setBranchcode(pBranch); key.setRealdate(d.getDate()); TgeneAccountingDate obj = new TgeneAccountingDate(); obj.setPk(key); obj.setAccountingdate(this.getDate(d, "accounting", m)); obj.setWorkingdate(this.getDate(d, "working", m)); PersistenceHelper.save(obj); } /** * Entrega la fecha contable para una fecha real. * * @param d Fecha real con la cual se obtien la fecha de trabajo y la fecha * contable. * @param fieldname Nombre del campo, working o accounting * @param m Map que contien indica si la fecha es laborable y/o contable. * @return Date * @throws Exception */ private Date getDate(APPDates d, String fieldname, Map m) throws Exception { if (m.get(fieldname)) { if (fieldname.compareTo("working") == 0) { return d.getDate(); } else if (this.validateDayOfTheMonth(d)) { //Si es fecha contable verifica que el dia dentro del mes sea contable. return d.getDate(); } } APPDates daux = new APPDates(d.getDate(), CalculationBase.B365365); int day = d.getField(Calendar.DAY_OF_WEEK); boolean cont = true; while (cont) { day++; if (day == 8) { day = 1; } daux.addField(Calendar.DAY_OF_YEAR, 1); if (fieldname.compareTo("accounting") == 0 && !this.validateDayOfTheMonth(daux)) { //Si el dia es no contable continua continue; } if (this.mdays.get(day).get(fieldname)) { cont = false; } } return daux.getDate(); } /** * Valida si el dia es contable dentro del mes, ejemplo 1 de enero no es * contable. * * @param d Fecha verificar si el dia es contable. * @return boolean * @throws Exception */ private boolean validateDayOfTheMonth(APPDates d) throws Exception { boolean isaccounting = true; String mes = String.valueOf(d.getField(Calendar.MONTH)); if (mes.length() == 1) { mes = "0" + mes; } for (TgeneNotAccountingDay obj : lnotaccountingdays) { if (obj.getPk().getCatalog().compareTo(mes) != 0) { continue; } int day = d.getField(Calendar.DAY_OF_MONTH); if (obj.getPk().getDay().compareTo(day) == 0) { isaccounting = false; break; } } return isaccounting; } @SuppressWarnings("unchecked") private void fillMapDay(SaveRequest saveRequest) throws Exception { List lobj = saveRequest.getSaveBeanModifiedRecords("LISTACCOUNTINDATE"); if(lobj == null || lobj.isEmpty()){ lobj = (List)saveRequest.get("LISTACCOUNTINDATE"); } boolean isworking = false; boolean isaccounting = false; for (Object object : lobj) { Map m = (Map) object; Integer day = Integer.parseInt(m.get("day").toString()); String working = m.get("teller").toString(); String accounting = m.get("accounting").toString(); Map maux = new HashMap(); maux.put("working", Constant.ifYes(working)); maux.put("accounting", Constant.ifYes(accounting)); mdays.put(day, maux); if(!isworking){ isworking = Constant.ifYes(working); } if(!isaccounting){ isaccounting = Constant.ifYes(accounting); } } if(!isaccounting || !isworking){ throw new GeneralException("GENE-0052", "INGRESE AL MENOS UN DÍA CONATBLE Y DE TRABAJO PARA GENERAR EL CALENDARIO"); } } /** * Sentencia que se encarga de eliminar el calendario de fechas por sucursal */ private static String DEL = "delete from TgeneAccountingDate t " + " where t.pk.branchcode = :branch " + " and t.pk.companycode = :company " + " and t.pk.realdate >= :datefrom "; /** * Elimna fechas del calendario por sucursal y mayor a la fecha a regenerar * el calendario. * * @param pBracnch Codigo de sucursal. * @param pCompany Codigo de compania. * @throws Exception */ private void delete(Integer pBracnch, Integer pCompany) throws Exception { Query qry = PersistenceHelper.getEntityManager().createQuery(DEL); qry.setParameter("branch", pBracnch); qry.setParameter("company", pCompany); qry.setParameter("datefrom", this.initdatedate); qry.executeUpdate(); } /** * Sentencia que se encarga de eliminar el calendario de fechas por sucursal */ private static String SQL_VAL = "select max(t.pk.realdate) from TgeneAccountingDate t " + " where t.pk.branchcode = :branch " + " and t.pk.companycode = :company " + " and t.pk.realdate < :datefrom "; /** * Valida que en la generacion de del calendario no exista huecos de fechas * realres. * * @param pBracnch Codigo de sucursal. * @param pCompany Codigo de compania. * @throws Exception */ private void validateDatesByBranch(Integer pBracnch, Integer pCompany) throws Exception { Query qry = PersistenceHelper.getEntityManager().createQuery(SQL_VAL); qry.setParameter("branch", pBracnch); qry.setParameter("company", pCompany); qry.setParameter("datefrom", this.initdatedate); Date d = (Date) qry.getSingleResult(); if (d == null) { return; } APPDates appd = new APPDates(d, CalculationBase.B365365); appd.addField(Calendar.DAY_OF_YEAR, 1); if (appd.getDate().compareTo(initdatedate) < 0) { SimpleDateFormat fd = new SimpleDateFormat("dd-MM-yyyy"); throw new GeneralException("GENE-0019", "EL CALENDARIO NO PUEDE DEJAR HUECOS PARA LA SUCURSAL: {0} FCONTABLE ANTERIOR: {1}", pBracnch, fd.format(d)); } TgeneAccountingDateBranch ad = DataHelper.getInstance().getTgeneAccountingDateBranch(pCompany, 0); if (ad.getRealdate().compareTo(initdatedate) > 0) { throw new GeneralException("GENE-0020", "FECHA DE INICIO PARA GENERAR CALENDARIO NO PUEDE SER MENOR A: {0}", ad.getRealdate()); } } /** * Metodo que se ejecuta en modo reverso * * @param saveRequest * @return SaveRequest * @throws Exception */ public SaveRequest reverseProcess(SaveRequest saveRequest) throws Exception { //En este caso no hacer nada no existen reversos. return saveRequest; } }