/* * Copyright (C) 2015 Arthur Gregorio, AG.Software * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package br.com.webbudget.application.controller.financial; import br.com.webbudget.application.controller.AbstractBean; import br.com.webbudget.domain.model.entity.entries.Card; import br.com.webbudget.domain.model.entity.entries.Contact; import br.com.webbudget.domain.model.entity.financial.Apportionment; import br.com.webbudget.domain.model.entity.entries.CostCenter; import br.com.webbudget.domain.model.entity.miscellany.FinancialPeriod; import br.com.webbudget.domain.model.entity.financial.Movement; import br.com.webbudget.domain.model.entity.entries.MovementClass; import br.com.webbudget.domain.model.entity.entries.MovementClassType; import br.com.webbudget.domain.model.entity.financial.MovementStateType; import br.com.webbudget.domain.model.entity.financial.MovementType; import br.com.webbudget.domain.model.entity.financial.Payment; import br.com.webbudget.domain.model.entity.entries.Wallet; import br.com.webbudget.domain.misc.filter.MovementFilter; import br.com.webbudget.application.component.table.AbstractLazyModel; import br.com.webbudget.application.component.table.MovementsListModel; import br.com.webbudget.domain.misc.ex.InternalServiceError; import br.com.webbudget.domain.model.entity.financial.PaymentMethodType; import br.com.webbudget.domain.model.service.CardService; import br.com.webbudget.domain.model.service.ContactService; import br.com.webbudget.domain.model.service.FinancialPeriodService; import br.com.webbudget.domain.model.service.MovementService; import br.com.webbudget.domain.model.service.WalletService; import java.util.ArrayList; import java.util.List; import java.util.stream.Collectors; import javax.annotation.PostConstruct; import javax.faces.view.ViewScoped; import javax.inject.Inject; import javax.inject.Named; import lombok.Getter; import lombok.Setter; import org.primefaces.model.DualListModel; /** * Controller da tela de movimentos do periodo * * @author Arthur Gregorio * * @version 2.0.0 * @since 1.0.0, 18/03/2014 */ @Named @ViewScoped public class MovementBean extends AbstractBean { @Getter @Setter private String contactFilter; @Getter @Setter private MovementFilter filter; @Getter @Setter private Movement movement; @Getter @Setter private Apportionment apportionment; @Getter private List<Wallet> wallets; @Getter private List<Card> debitCards; @Getter private List<Card> creditCards; @Getter private List<Contact> contacts; @Getter private List<CostCenter> costCenters; @Getter private List<FinancialPeriod> periods; @Getter private List<MovementClass> movementClasses; @Inject private CardService cardService; @Inject private WalletService walletService; @Inject private ContactService contactService; @Inject private MovementService movementService; @Inject private FinancialPeriodService financialPeriodService; @Getter private AbstractLazyModel<Movement> movementsModel; @Getter @Setter private DualListModel<FinancialPeriod> periodsModel; /** * Inicializamos os objetos necessarios */ @PostConstruct protected void initialize() { // inicializa o model customizado this.movementsModel = new MovementsListModel( this.movementService, () -> this.getFilter()); // inicializa o filtro this.filter = new MovementFilter(); } /** * Inicializa a tela de listagem de movimentos */ public void initializeListing() { this.viewState = ViewState.LISTING; // inicializa o filtro this.filter = new MovementFilter(); // cria o filtro por periodo this.periods = this.financialPeriodService.listFinancialPeriods(null); this.periodsModel = new DualListModel<>(this.periods, new ArrayList<>()); // seta a primeira busca sendo pelos periodos em aberto this.filter.setPeriods(this.getOpenPeriods()); } /** * Inicializa o form de cadastro, edicao ou visualizacao dos movimentos * * @param movementId o id do movimento a ser visualizado ou editado * @param viewState o estado da tela a ser aplicado */ public void initializeForm(long movementId, String viewState) { this.viewState = ViewState.valueOf(viewState); // lista as formas de pagamento this.wallets = this.walletService.listWallets(Boolean.FALSE); this.debitCards = this.cardService.listDebitCards(Boolean.FALSE); this.creditCards = this.cardService.listCreditCards(Boolean.FALSE); // carrega os centros de custo e os periodos validos this.costCenters = this.movementService.listCostCenters(false); this.periods = this.financialPeriodService.listFinancialPeriods(false); // inicializa o movimento if (this.viewState == ViewState.ADDING) { this.movement = new Movement(); } else { this.movement = this.movementService.findMovementById(movementId); } } /** * Inicializa o formulario de pagamento de movimentos * * @param movementId o id do movimento a ser pago */ public void initializePayment(long movementId) { // inicializa o movimento this.movement = this.movementService.findMovementById(movementId); final Payment payment = new Payment(); // se for um lancamento, pega a data de incio como data de pagamento if (this.movement.getLaunch() != null) { payment.setPaymentDate(this.movement.getLaunch().getStartDate()); } this.movement.setPayment(payment); // inicializa carteiras e afins this.wallets = this.walletService.listWallets(Boolean.FALSE); this.debitCards = this.cardService.listDebitCards(Boolean.FALSE); this.creditCards = this.cardService.listCreditCards(Boolean.FALSE); } /** * Salva o movimento */ public void doSave() { try { this.movementService.saveMovement(this.movement); this.movement = new Movement(); this.addInfo(true, "movement.saved"); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } } /** * Atualiza o movimento */ public void doUpdate() { try { this.movement = this.movementService.updateMovement(this.movement); this.movement = this.movementService .findMovementById(this.movement.getId()); this.addInfo(true, "movement.updated"); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } } /** * Salva e paga o movimento */ public void doSaveAndPayment() { try { this.movementService.payMovement(this.movement); this.movement = new Movement(); this.closeDialog("dialogPayment"); this.addInfo(false, "movement.saved-paid"); this.updateComponent("movementForm"); this.temporizeHiding("messages"); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } } /** * */ public void doUpdateAndPayment() { try { this.movementService.payMovement(this.movement); this.changeToDetail(this.movement.getId()); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } } /** * Aepnas paga o movimento */ public void doPayment() { try { this.movementService.payMovement(this.movement); this.updateAndOpenDialog("confirmPaymentDialog", "dialogConfirmPayment"); } catch (InternalServiceError ex) { this.addError(true, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(true, "error.undefined-error", ex.getMessage()); } } /** * Deleta o movimento */ public void doDelete() { try { final MovementType movementType = this.movement.getMovementType(); // fazemos a selecao do tipo de delecao a ser executado if (movementType == MovementType.MOVEMENT) { this.movementService.deleteMovement(this.movement); } else if (movementType == MovementType.CARD_INVOICE) { this.movementService.deleteCardInvoiceMovement(this.movement); } this.addInfo(true, "movement.deleted"); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } finally { this.updateComponent("movementsList"); this.closeDialog("dialogDeleteMovement"); } } /** * Exibe a telinha de pagamento */ public void showPaymentDialog() { final Payment payment = new Payment(); if (!this.movement.hasValueToDivide()) { this.addError(true, "error.movement.no-apportionment"); return; } // se for um lancamento, pega a data de incio como data de pagamento if (this.movement.getLaunch() != null) { payment.setPaymentDate(this.movement.getLaunch().getStartDate()); } this.movement.setPayment(payment); this.updateAndOpenDialog("paymentDialog", "dialogPayment"); } /** * @return volta para a tela de listagem */ public String changeToList() { return "listMovements.xhtml?faces-redirect=true"; } /** * @return envia o usuario para a tela de cadastro */ public String changeToAdd() { return "formMovement.xhtml?faces-redirect=true&viewState=" + ViewState.ADDING; } /** * @param movementId o id do movimento a ser editado * @return a tela de edicao */ public String changeToEdit(long movementId) { return "formMovement.xhtml?faces-redirect=true&movementId=" + movementId + "&viewState=" + ViewState.EDITING; } /** * @param movementId o id do movimento a ser excluido */ public void changeToDelete(long movementId) { this.movement = this.movementService.findMovementById(movementId); this.updateAndOpenDialog("deleteMovementDialog", "dialogDeleteMovement"); } /** * Da um redirect para os detalhes do movimento */ public void changeToDetail() { this.redirectTo("formMovement.xhtml?faces-redirect=true&movementId=" + this.movement.getId() + "&viewState=" + ViewState.DETAILING); } /** * Da um redirect para os detalhes do movimento * * @param movementId qual o movimento que vamos ver os detalhes */ public void changeToDetail(long movementId) { this.redirectTo("formMovement.xhtml?faces-redirect=true&movementId=" + movementId + "&viewState=" + ViewState.DETAILING); } /** * @param movementId o id do movimento a ser pago * @return a tela de pagamento de movimentos */ public String changeToPay(long movementId) { return "formPayment.xhtml?faces-redirect=true&movementId=" + movementId; } /** * */ public void showPaymentDetails() { this.updateAndOpenDialog("paymentDetailsDialog", "dialogPaymentDetails"); } /** * Abre a dialog de busca de contatos */ public void showContactDialog() { this.contactFilter = null; this.contacts = new ArrayList<>(); this.updateAndOpenDialog("contactDialog", "dialogContact"); } /** * Busca o contato de acordo com o filtro */ public void filterContactsList() { try { this.contacts = this.contactService .listContactsByFilter(this.contactFilter, false); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } finally { this.updateComponent("contactForm"); } } /** * Apos selecionar um contato este metodo fechara a dialog e atualizara a * view */ public void onContactSelect() { this.updateComponent("contactBox"); this.closeDialog("dialogContact"); } /** * Remove o contato que foi vinculado ao movimento */ public void removeContact() { this.movement.setContact(null); this.updateComponent("contactBox"); } /** * */ public void showApportionmentDialog() { // se o valor do rateio for igual ao total do movimento nem deixa exibir // a tela de rateios para que nao seja feito cagada if (this.movement.hasValueToDivide()) { this.addError(true, "error.fixed-movement.no-value-divide"); return; } this.apportionment = new Apportionment(); this.apportionment.setValue(this.movement.getValueToDivide()); this.updateAndOpenDialog("apportionmentDialog", "dialogApportionment"); } /** * */ public void addApportionment() { try { this.movement.addApportionment(this.apportionment); this.updateComponent("inValue"); this.updateComponent("apportionmentBox:container"); this.closeDialog("dialogApportionment"); } catch (InternalServiceError ex) { this.addError(false, ex.getMessage(), ex.getParameters()); } catch (Exception ex) { this.logger.error(ex.getMessage(), ex); this.addError(false, "error.undefined-error", ex.getMessage()); } finally { this.updateComponent("apportionmentMessages"); } } /** * * @param code */ public void deleteApportionment(String code) { this.movement.removeApportionment(code); this.updateComponent("inValue"); this.updateComponent("apportionmentBox:container"); } /** * Atualiza o combo de classes quando o usuario selecionar o centro de custo */ public void loadMovementClasses() { this.movementClasses = this.movementService.listMovementClassesByCostCenterAndType( this.apportionment.getCostCenter(), null); } /** * Exibe a tela de customizacao dos filros avancados */ public void showFilterConfigDialog() { this.updateAndOpenDialog("configFilterDialog", "dialogConfigFilter"); } /** * Aplica os filtros customizados selecionados na listagem de movimentos */ public void applyCustomFilters() { this.filter.setPeriods(this.periodsModel.getTarget()); this.updateComponent("movementsList"); this.closeDialog("dialogConfigFilter"); } /** * Limpa todos os filtro ja realizados */ public void clearFilters() { this.filter.setCriteria(null); this.filter.setPeriods(this.getOpenPeriods()); this.updateComponent("movementsList"); this.updateComponent("controlsForm"); } /** * @return da lista de periodos, retorna apenas o que estiver ativo */ public FinancialPeriod getActivePeriod() { return this.periods.stream() .filter(FinancialPeriod::isActive) .findFirst() .orElse(null); } /** * @return os periodos financeiros em aberto no sistema */ public List<FinancialPeriod> getOpenPeriods() { if (this.viewState == ViewState.DETAILING) { return this.periods; } else { return this.periods.stream() .filter(period -> !period.isClosed()) .collect(Collectors.toList()); } } /** * @return os estados possiveis dos movimentos */ public MovementStateType[] getMovementStateTypes() { return MovementStateType.values(); } /** * @return as possiveis direcoes de um movimento */ public MovementClassType[] getMovementClassTypes() { return MovementClassType.values(); } /** * @return os possiveis tipos de um movimento */ public MovementType[] getMovementTypes() { return MovementType.values(); } /** * @return os possiveis metodos de pagamento */ public PaymentMethodType[] getPaymentMethodTypes() { return PaymentMethodType.values(); } }