/* * Copyright (C) 2014 GG-Net GmbH - Oliver Günther * * 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 eu.ggnet.dwoss.redtape.workflow; import eu.ggnet.dwoss.rules.DocumentType; import eu.ggnet.dwoss.rules.PaymentMethod; import eu.ggnet.dwoss.customer.api.AddressService; import eu.ggnet.dwoss.customer.api.CustomerMetaData; import eu.ggnet.dwoss.rules.AddressType; import eu.ggnet.dwoss.rules.CustomerFlag; import eu.ggnet.dwoss.customer.api.CustomerService; import eu.ggnet.dwoss.redtape.entity.Dossier; import eu.ggnet.dwoss.redtape.entity.DocumentHistory; import eu.ggnet.dwoss.redtape.entity.Document; import java.text.*; import java.util.Set; import javax.inject.Inject; import javax.persistence.EntityManager; import org.slf4j.*; import eu.ggnet.dwoss.mandator.api.value.Mandator; import eu.ggnet.dwoss.mandator.api.value.SpecialSystemCustomers; import eu.ggnet.dwoss.redtape.assist.RedTapes; import eu.ggnet.dwoss.redtape.emo.AddressEmo; import eu.ggnet.dwoss.redtape.entity.Document.Directive; import eu.ggnet.dwoss.redtape.format.DossierFormater; import static eu.ggnet.dwoss.rules.CustomerFlag.*; import static eu.ggnet.dwoss.rules.DocumentType.BLOCK; /** * Workflow to create a Dossier with one document of the selected Type. * * @author oliver.guenther */ public class RedTapeCreateDossierWorkflow { protected final static Logger L = LoggerFactory.getLogger(RedTapeCreateDossierWorkflow.class); private final static NumberFormat _00000_ = new DecimalFormat("00000"); @Inject @RedTapes private EntityManager redTapeEm; @Inject private AddressService addressService; @Inject private CustomerService customerService; @Inject private Mandator mandator; @Inject private SpecialSystemCustomers specialSystemCustomers; /** * Returns the first Directive on a created Document. * See Implementation. Uses Dispatch. * * @param type the {@link DocumentType} * @param paymentMethod the payment method * @param flags the customerFlags * @param dispatch value specifying weither this is a dispatch process * @return the Directive. */ public static Document.Directive primeDirective(DocumentType type, PaymentMethod paymentMethod, Set<CustomerFlag> flags, boolean dispatch) { if ( paymentMethod == null ) throw new NullPointerException("PaymentMethod is Null"); if ( type == DocumentType.BLOCK ) return Directive.NONE; if ( type == DocumentType.CAPITAL_ASSET ) return Directive.HAND_OVER_GOODS; // Default für Block, Returns und Anlagevermögen. switch (paymentMethod) { case CASH_ON_DELIVERY: // Implies dispatch if ( !dispatch ) throw new IllegalArgumentException("A PickUp Order cannot be of PaymentMethod " + paymentMethod); if ( flags.contains(CONFIRMED_CASH_ON_DELIVERY) && flags.contains(CONFIRMS_DOSSIER) ) return Directive.SEND_ORDER; if ( flags.contains(CONFIRMED_CASH_ON_DELIVERY) ) return Directive.PREPARE_SHIPPING; return Directive.SEND_CASH_ON_DELIVERY_CONTRACT; case ADVANCE_PAYMENT: if ( dispatch ) return Directive.SEND_ORDER; return Directive.WAIT_FOR_MONEY; case DIRECT_DEBIT: case INVOICE: if ( dispatch && flags.contains(CONFIRMS_DOSSIER) ) return Directive.SEND_ORDER; if ( dispatch ) return Directive.PREPARE_SHIPPING; // This is also ok for Returns and Capital Asset return Directive.HAND_OVER_GOODS; default: } throw new IllegalArgumentException("A Prime Directive for " + paymentMethod + ", " + flags + "dispatch=" + dispatch + " not found"); } private PaymentMethod selectPaymentMethod(boolean dispatch, CustomerMetaData customer) { // A PickUp Order with Cash on Delivery is impossible. if ( !dispatch && customer.getPaymentMethod() == PaymentMethod.CASH_ON_DELIVERY ) return PaymentMethod.ADVANCE_PAYMENT; else return customer.getPaymentMethod(); } /** * Creates the Dossier. * * @param customer the customer * @return the Dossier. */ Dossier createDossier(long customerId, boolean dispatch, DocumentType type, PaymentMethod paymentMethod, Directive directive, String arranger) { if ( specialSystemCustomers.get(customerId).map(x -> x != type).orElse(false) ) { throw new IllegalStateException(type + " is not allowed for Customer " + customerId); } Dossier dos = new Dossier(); dos.setPaymentMethod(paymentMethod); dos.setDispatch(dispatch); dos.setCustomerId(customerId); Document doc = new Document(); doc.setType(type); doc.setActive(true); doc.setDirective(directive); doc.setHistory(new DocumentHistory(arranger, "Automatische Erstellung eines leeren Dokuments")); AddressEmo adEmo = new AddressEmo(redTapeEm); doc.setInvoiceAddress(adEmo.request(addressService.defaultAddressLabel(customerId, AddressType.INVOICE))); doc.setShippingAddress(adEmo.request(addressService.defaultAddressLabel(customerId, AddressType.SHIPPING))); dos.add(doc); redTapeEm.persist(dos); dos.setIdentifier(mandator.getDossierPrefix() + _00000_.format(dos.getId())); L.info("Created {} by {}", DossierFormater.toSimpleLine(dos), arranger); return dos; } /** * Executes the Workflow. * * @param customerId * @param dispatch * @param arranger * @return the Dossier. */ public Dossier execute(long customerId, boolean dispatch, String arranger) { DocumentType type = DocumentType.ORDER; CustomerMetaData customer = customerService.asCustomerMetaData(customerId); L.debug("Found Customer: {}", customer); if ( customer.getFlags().contains(SYSTEM_CUSTOMER) ) { type = specialSystemCustomers.get(customerId).orElse(BLOCK); L.debug("CustomerId {} is SystemCustomer, using DocumentType: {}, source {}", customerId, type, specialSystemCustomers); } PaymentMethod paymentMethod = selectPaymentMethod(dispatch, customer); Directive directive = primeDirective(type, paymentMethod, customer.getFlags(), dispatch); return createDossier(customerId, dispatch, type, paymentMethod, directive, arranger); } }