001package org.kuali.ole.service.impl;
002
003import org.apache.commons.lang.StringUtils;
004import org.kuali.ole.DocumentUniqueIDPrefix;
005import org.kuali.ole.docstore.common.document.Bib;
006import org.kuali.ole.fp.businessobject.SalesTax;
007import org.kuali.ole.module.purap.PurapParameterConstants;
008import org.kuali.ole.module.purap.businessobject.PurApItem;
009import org.kuali.ole.module.purap.document.OlePurchasingDocument;
010import org.kuali.ole.module.purap.document.PurchasingDocument;
011import org.kuali.ole.module.purap.document.service.PurapService;
012import org.kuali.ole.module.purap.document.service.PurchasingService;
013import org.kuali.ole.module.purap.document.validation.event.AttributedAddPurchasingAccountsPayableItemEvent;
014import org.kuali.ole.module.purap.service.PurapAccountingService;
015import org.kuali.ole.select.bo.OLEEditorResponse;
016import org.kuali.ole.select.businessobject.OleDocstoreResponse;
017import org.kuali.ole.select.businessobject.OleRequisitionItem;
018import org.kuali.ole.select.form.OLERequisitionForm;
019import org.kuali.ole.service.OLERequisitionService;
020import org.kuali.ole.sys.OLEConstants;
021import org.kuali.ole.sys.businessobject.AccountingLine;
022import org.kuali.ole.sys.context.SpringContext;
023import org.kuali.ole.sys.document.AccountingDocument;
024import org.kuali.ole.sys.document.validation.impl.AccountingDocumentRuleBaseConstants;
025import org.kuali.ole.sys.service.impl.OleParameterConstants;
026import org.kuali.rice.core.api.parameter.ParameterEvaluator;
027import org.kuali.rice.core.api.parameter.ParameterEvaluatorService;
028import org.kuali.rice.coreservice.framework.parameter.ParameterService;
029import org.kuali.rice.krad.service.BusinessObjectService;
030import org.kuali.rice.krad.service.DataDictionaryService;
031import org.kuali.rice.krad.service.KualiRuleService;
032import org.kuali.rice.krad.util.GlobalVariables;
033import org.kuali.rice.krad.util.ObjectUtils;
034
035import java.util.List;
036import java.util.Map;
037
038import static org.kuali.ole.sys.OLEKeyConstants.ERROR_DOCUMENT_ACCOUNTING_LINE_SALES_TAX_INVALID_ACCOUNT;
039import static org.kuali.ole.sys.OLEKeyConstants.ERROR_DOCUMENT_ACCOUNTING_LINE_SALES_TAX_REQUIRED;
040import static org.kuali.ole.sys.OLEKeyConstants.ERROR_REQUIRED;
041
042/**
043 * Created by chenchulakshmig on 9/3/14.
044 */
045public class OLERequisitionServiceImpl implements OLERequisitionService {
046
047    @Override
048    public void superCalculate(OLERequisitionForm oleRequisitionForm) {
049        OlePurchasingDocument purDoc = (OlePurchasingDocument) oleRequisitionForm.getDocument();
050        boolean defaultUseTaxIndicatorValue = SpringContext.getBean(PurchasingService.class).getDefaultUseTaxIndicatorValue(purDoc);
051        SpringContext.getBean(PurapService.class).updateUseTaxIndicator(purDoc, defaultUseTaxIndicatorValue);
052        SpringContext.getBean(PurapService.class).calculateTax(purDoc);
053        // call prorateDiscountTradeIn
054        SpringContext.getBean(PurapService.class).prorateForTradeInAndFullOrderDiscount(purDoc);
055        //recalculate the amounts and percents on the accounting line.
056        SpringContext.getBean(PurapAccountingService.class).updateAccountAmounts(purDoc);
057        //TODO
058        //customCalculate(purDoc);//need to verify
059        oleRequisitionForm.setInitialZipCode(purDoc.getDeliveryPostalCode());
060        oleRequisitionForm.setCalculated(true);
061        purDoc.setCalculated(true);
062        GlobalVariables.getMessageMap().clearErrorMessages();
063    }
064
065    @Override
066    public void superAddItem(OLERequisitionForm oleRequisitionForm) {
067        PurApItem item = oleRequisitionForm.getNewPurchasingItemLine();
068        OlePurchasingDocument purDocument = (OlePurchasingDocument) oleRequisitionForm.getDocument();
069        boolean rulePassed = SpringContext.getBean(KualiRuleService.class).applyRules(new AttributedAddPurchasingAccountsPayableItemEvent("", purDocument, item));
070        if (rulePassed) {
071            item = oleRequisitionForm.getAndResetNewPurchasingItemLine();
072            purDocument.addItem(item);
073        }
074    }
075
076    @Override
077    public void setItemDescription(OleRequisitionItem item, String fileName) throws Exception {
078        if (OleDocstoreResponse.getInstance().getEditorResponse() != null) {
079            Map<String, OLEEditorResponse> oleEditorResponses = OleDocstoreResponse.getInstance().getEditorResponse();
080            OLEEditorResponse oleEditorResponse = oleEditorResponses.get(fileName);
081            Bib bib = oleEditorResponse != null ? oleEditorResponse.getBib() : null;
082            if (bib != null) {
083                String title = (bib.getTitle() != null && !bib.getTitle().isEmpty()) ? bib.getTitle() + ", " : "";
084                String author = (bib.getAuthor() != null && !bib.getAuthor().isEmpty()) ? bib.getAuthor() + ", " : "";
085                String publisher = (bib.getPublisher() != null && !bib.getPublisher().isEmpty()) ? bib.getPublisher() + ", " : "";
086                String isbn = (bib.getIsbn() != null && !bib.getIsbn().isEmpty()) ? bib.getIsbn() + ", " : "";
087                String description = title + author + publisher + isbn;
088                item.setDocFormat(DocumentUniqueIDPrefix.getBibFormatType(bib.getId().toString()));
089                item.setItemDescription(description.substring(0, (description.lastIndexOf(","))));
090            }
091            if (bib != null) {
092                item.setBibUUID(bib.getId());
093                item.setItemTitleId(bib.getId());
094                item.setLinkToOrderOption(oleEditorResponse.getLinkToOrderOption());
095            }
096            OleDocstoreResponse.getInstance().getEditorResponse().remove(oleEditorResponse);
097        }
098    }
099
100    @Override
101    public boolean requiresCalculate(boolean isCalculated, boolean canUserCalculate) {
102        boolean requiresCalculate = true;
103        boolean salesTaxInd = SpringContext.getBean(ParameterService.class).getParameterValueAsBoolean(OleParameterConstants.PURCHASING_DOCUMENT.class, PurapParameterConstants.ENABLE_SALES_TAX_IND);
104        requiresCalculate = salesTaxInd && (!isCalculated && canUserCalculate);
105        return requiresCalculate;
106    }
107
108    @Override
109    public boolean checkSalesTaxRequiredAllLines(AccountingDocument accoutingDocument, List<AccountingLine> baselineAcctingLines) {
110        boolean passed = true;
111        int index = 0;
112        for (AccountingLine accountingLine : baselineAcctingLines) {
113            boolean source = false;
114            if (accountingLine.isSourceAccountingLine()) {
115                source = true;
116            }
117            passed &= checkSalesTax(accoutingDocument, accountingLine, source, false, index);
118            index++;
119        }
120        return passed;
121    }
122
123    private boolean checkSalesTax(AccountingDocument document, AccountingLine line, boolean source, boolean newLine, int index) {
124        boolean passed = true;
125        if (isSalesTaxRequired(document, line)) {
126            // then set the salesTaxRequired on the accountingLine
127            line.setSalesTaxRequired(true);
128            populateSalesTax(line);
129            // check to see if the sales tax info has been put in
130            passed &= isValidSalesTaxEntered(line, source, newLine, index);
131        } else {
132            //we do not need the saleTax bo for the line otherwise validations will fail.
133            line.setSalesTax(null);
134        }
135        return passed;
136    }
137
138    private boolean isValidSalesTaxEntered(AccountingLine accountingLine, boolean source, boolean newLine, int index) {
139        boolean valid = true;
140        BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class);
141        String objCd = accountingLine.getFinancialObjectCode();
142        String account = accountingLine.getAccountNumber();
143        SalesTax salesTax = accountingLine.getSalesTax();
144        String pathPrefix = "";
145        if (source && !newLine) {
146            pathPrefix = "document." + OLEConstants.EXISTING_SOURCE_ACCT_LINE_PROPERTY_NAME + "[" + index + "]";
147        } else if (!source && !newLine) {
148            pathPrefix = "document." + OLEConstants.EXISTING_TARGET_ACCT_LINE_PROPERTY_NAME + "[" + index + "]";
149        } else if (source && newLine) {
150            pathPrefix = OLEConstants.NEW_SOURCE_ACCT_LINE_PROPERTY_NAME;
151        } else if (!source && newLine) {
152            pathPrefix = OLEConstants.NEW_TARGET_ACCT_LINE_PROPERTY_NAME;
153        }
154        GlobalVariables.getMessageMap().addToErrorPath(pathPrefix);
155        if (ObjectUtils.isNull(salesTax)) {
156            valid &= false;
157            GlobalVariables.getMessageMap().putError("salesTax.chartOfAccountsCode", ERROR_DOCUMENT_ACCOUNTING_LINE_SALES_TAX_REQUIRED, account, objCd);
158        } else {
159            if (StringUtils.isBlank(salesTax.getChartOfAccountsCode())) {
160                valid &= false;
161                GlobalVariables.getMessageMap().putError("salesTax.chartOfAccountsCode", ERROR_REQUIRED, "Chart of Accounts");
162            }
163            if (StringUtils.isBlank(salesTax.getAccountNumber())) {
164                valid &= false;
165                GlobalVariables.getMessageMap().putError("salesTax.accountNumber", ERROR_REQUIRED, "Account Number");
166            }
167            if (salesTax.getFinancialDocumentGrossSalesAmount() == null) {
168                valid &= false;
169                GlobalVariables.getMessageMap().putError("salesTax.financialDocumentGrossSalesAmount", ERROR_REQUIRED, "Gross Sales Amount");
170            }
171            if (salesTax.getFinancialDocumentTaxableSalesAmount() == null) {
172                valid &= false;
173                GlobalVariables.getMessageMap().putError("salesTax.financialDocumentTaxableSalesAmount", ERROR_REQUIRED, "Taxable Sales Amount");
174            }
175            if (salesTax.getFinancialDocumentSaleDate() == null) {
176                valid &= false;
177                GlobalVariables.getMessageMap().putError("salesTax.financialDocumentSaleDate", ERROR_REQUIRED, "Sale Date");
178            }
179            if (StringUtils.isNotBlank(salesTax.getChartOfAccountsCode()) && StringUtils.isNotBlank(salesTax.getAccountNumber())) {
180
181                if (boService.getReferenceIfExists(salesTax, "account") == null) {
182                    valid &= false;
183                    GlobalVariables.getMessageMap().putError("salesTax.accountNumber", ERROR_DOCUMENT_ACCOUNTING_LINE_SALES_TAX_INVALID_ACCOUNT, salesTax.getChartOfAccountsCode(), salesTax.getAccountNumber());
184
185                }
186            }
187            if (!valid) {
188                GlobalVariables.getMessageMap().putError("salesTax.chartOfAccountsCode", ERROR_DOCUMENT_ACCOUNTING_LINE_SALES_TAX_REQUIRED, account, objCd);
189            }
190        }
191        GlobalVariables.getMessageMap().removeFromErrorPath(pathPrefix);
192        return valid;
193    }
194
195    private void populateSalesTax(AccountingLine line) {
196        SalesTax salesTax = line.getSalesTax();
197
198        if (ObjectUtils.isNotNull(salesTax)) {
199            salesTax.setDocumentNumber(line.getDocumentNumber());
200            salesTax.setFinancialDocumentLineTypeCode(line.getFinancialDocumentLineTypeCode());
201            salesTax.setFinancialDocumentLineNumber(line.getSequenceNumber());
202        }
203    }
204
205    private boolean isSalesTaxRequired(AccountingDocument financialDocument, AccountingLine accountingLine) {
206        boolean required = false;
207        String docType = SpringContext.getBean(DataDictionaryService.class).getDocumentTypeNameByClass(financialDocument.getClass());
208        // first we need to check just the doctype to see if it needs the sales tax check
209        ParameterService parameterService = SpringContext.getBean(ParameterService.class);
210        // apply the rule, see if it fails
211        ParameterEvaluator docTypeSalesTaxCheckEvaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(OleParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class, AccountingDocumentRuleBaseConstants.APPLICATION_PARAMETER.DOCTYPE_SALES_TAX_CHECK, docType);
212        if (docTypeSalesTaxCheckEvaluator.evaluationSucceeds()) {
213            required = true;
214        }
215        // second we need to check the account and object code combination to see if it needs sales tax
216        if (required) {
217            // get the object code and account
218            String objCd = accountingLine.getFinancialObjectCode();
219            String account = accountingLine.getAccountNumber();
220            if (!StringUtils.isEmpty(objCd) && !StringUtils.isEmpty(account)) {
221                String compare = account + ":" + objCd;
222                ParameterEvaluator salesTaxApplicableAcctAndObjectEvaluator = /*REFACTORME*/SpringContext.getBean(ParameterEvaluatorService.class).getParameterEvaluator(OleParameterConstants.FINANCIAL_PROCESSING_DOCUMENT.class, AccountingDocumentRuleBaseConstants.APPLICATION_PARAMETER.SALES_TAX_APPLICABLE_ACCOUNTS_AND_OBJECT_CODES, compare);
223                if (!salesTaxApplicableAcctAndObjectEvaluator.evaluationSucceeds()) {
224                    required = false;
225                }
226            } else {
227                // the two fields are currently empty and we don't need to check yet
228                required = false;
229            }
230        }
231        return required;
232    }
233
234}