/**
  * Used by tests of generateAccountDistributionForProration and related methods to make
  * comparisons between the percentages given by the resulting distributed accounts and the
  * percentages that we think should be correct for those lines.
  *
  * @param distributedAccounts A List of the PurApAccountingLines that result from the distribution
  *     to be tested.
  * @param correctPercents A List of percents we think should be correct, in BigDecimal format
  */
 private void comparePercentages(
     List<PurApAccountingLine> distributedAccounts, List<BigDecimal> correctPercents) {
   for (int i = 0; i < distributedAccounts.size(); i++) {
     PurApAccountingLine line = distributedAccounts.get(i);
     BigDecimal percent = line.getAccountLinePercent();
     assertTrue(percent.floatValue() == correctPercents.get(i).floatValue());
   }
 }
 @ConfigureContext(session = parke)
 public void testUpdateItemAccountAmounts_ThreeAccounts() {
   PurapAccountingServiceFixture fixture = PurapAccountingServiceFixture.REQ_PRORATION_THIRDS;
   RequisitionDocument req = fixture.generateRequisitionDocument_OneItem();
   RequisitionItem item = (RequisitionItem) req.getItems().get(0);
   KualiDecimal total = item.getTotalAmount();
   purapAccountingService.updateItemAccountAmounts(item);
   PurApAccountingLine line1 = item.getSourceAccountingLines().get(0);
   assertTrue(line1.getAmount().compareTo(total.divide(new KualiDecimal(3))) == 0);
 }
 @ConfigureContext(session = appleton)
 public void testUpdateAccountAmounts_AfterFullEntry_AmountToPercent() {
   PurapAccountingServiceFixture fixture = PurapAccountingServiceFixture.PREQ_PRORATION_THIRDS;
   PurchasingAccountsPayableDocument preq = fixture.generatePaymentRequestDocument_OneItem();
   preq.setApplicationDocumentStatus(
       PurapConstants.PaymentRequestStatuses.APPDOC_DEPARTMENT_APPROVED);
   purapAccountingService.updateAccountAmounts(preq);
   PurApItem item = preq.getItems().get(0);
   int i = 0;
   for (PurApAccountingLine correctLine : fixture.getPurApAccountingLineList()) {
     PurApAccountingLine line = item.getSourceAccountingLines().get(i++);
     assertTrue(line.getAccountLinePercent().equals(correctLine.getAccountLinePercent()));
   }
 }
 @ConfigureContext(session = appleton)
 public void testUpdateAccountAmounts_BeforeFullEntry_AmountNotToPercent() {
   PurapAccountingServiceFixture fixture = PurapAccountingServiceFixture.PREQ_PRORATION_THIRDS;
   PurchasingAccountsPayableDocument preq = fixture.generatePaymentRequestDocument_OneItem();
   purapAccountingService.updateAccountAmounts(preq);
   PurApItem item = preq.getItems().get(0);
   int i = 0;
   boolean orResult = false;
   for (PurApAccountingLine correctLine : fixture.getPurApAccountingLineList()) {
     PurApAccountingLine line = item.getSourceAccountingLines().get(i++);
     if (!line.getAccountLinePercent().equals(correctLine.getAccountLinePercent())) {
       orResult = true;
       break;
     }
   }
   assertFalse(orResult);
 }
  public boolean validate(AttributedDocumentEvent event) {
    boolean valid = true;
    PurApAccountingLine account =
        (PurApAccountingLine) ((AddAccountingLineEvent) event).getAccountingLine();
    ObjectCode objectCode = account.getObjectCode();

    ParameterEvaluator parameterEvaluator = /*REFACTORME*/
        SpringContext.getBean(ParameterEvaluatorService.class)
            .getParameterEvaluator(
                VendorCreditMemoDocument.class,
                PurapRuleConstants.VALID_OBJECT_LEVELS_BY_OBJECT_TYPE_PARM_NM,
                PurapRuleConstants.INVALID_OBJECT_LEVELS_BY_OBJECT_TYPE_PARM_NM,
                objectCode.getFinancialObjectTypeCode(),
                objectCode.getFinancialObjectLevelCode());
    return parameterEvaluator.evaluateAndAddError(
        SourceAccountingLine.class,
        "objectCode.financialObjectLevelCode",
        KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
  }
  public boolean validate(AttributedDocumentEvent event) {
    boolean valid = true;
    double pct = accountingLine.getAccountLinePercent().doubleValue();

    if (pct <= 0 || pct > 100) {
      GlobalVariables.getMessageMap()
          .putError(errorPropertyName, PurapKeyConstants.ERROR_ITEM_PERCENT, "%", itemIdentifier);

      valid = false;
    }

    return valid;
  }
 /**
  * finds the line with matching sequence number, chart code, account number, financial object code
  * and updates amount/percent on the account line.
  *
  * @param pOItem
  * @param lineAcct
  */
 protected void updateItemAccountLine(PurApItem pOItem, PurApAccountingLine lineAcct) {
   List<PurApAccountingLine> pOAccountingLines = pOItem.getSourceAccountingLines();
   for (PurApAccountingLine pOLineAcct : pOAccountingLines) {
     if (lineAcct.getChartOfAccountsCode().equalsIgnoreCase(pOLineAcct.getChartOfAccountsCode())
         && lineAcct.getAccountNumber().equalsIgnoreCase(pOLineAcct.getAccountNumber())
         && lineAcct
             .getFinancialObjectCode()
             .equalsIgnoreCase(pOLineAcct.getFinancialObjectCode())) {
       lineAcct.setAmount(pOLineAcct.getAmount());
       lineAcct.setAccountLinePercent(pOLineAcct.getAccountLinePercent());
     }
   }
 }
  /**
   * gets the item from preq and restores the values from the original PO and then redistributes the
   * amounts based on extended cost and quantity
   *
   * @param mapping
   * @param form
   * @param request
   * @param response
   * @return actionForward
   * @throws Exception
   */
  public ActionForward recalculateItemAccountsAmounts(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    AccountsPayableFormBase payableForm = (AccountsPayableFormBase) form;
    AccountsPayableDocument apDoc = (AccountsPayableDocument) payableForm.getDocument();

    PurapAccountingService purapAccountingService =
        SpringContext.getBean(PurapAccountingService.class);

    String[] indexes = getSelectedItemNumber(request);
    int itemIndex = Integer.parseInt(indexes[0]);

    PurApItem item = apDoc.getItem((itemIndex));

    // first reset the the corresponding po items accounts amounts to this item
    restoreItemAccountsAmounts(apDoc, item);

    item.refreshReferenceObject(PurapPropertyConstants.ITEM_TYPE);

    final KualiDecimal itemExtendedPrice =
        (item.getExtendedPrice() == null) ? KualiDecimal.ZERO : item.getExtendedPrice();
    ;
    if (item.getItemType().isQuantityBasedGeneralLedgerIndicator()) {
      KualiDecimal newExtendedPrice = item.calculateExtendedPrice();
      item.setExtendedPrice(newExtendedPrice);
    }

    PaymentRequestDocument preqDoc = (PaymentRequestDocument) apDoc;

    // set amounts on any empty
    preqDoc.updateExtendedPriceOnItems();

    // calculation just for the tax area, only at tax review stage
    // by now, the general calculation shall have been done.
    if (preqDoc
        .getApplicationDocumentStatus()
        .equals(PaymentRequestStatuses.APPDOC_AWAITING_TAX_REVIEW)) {
      SpringContext.getBean(PaymentRequestService.class).calculateTaxArea(preqDoc);
    }

    // notice we're ignoring whether the boolean, because these are just warnings they shouldn't
    // halt anything
    // Calculate Payment request before rules since the rule check totalAmount.
    SpringContext.getBean(PaymentRequestService.class).calculatePaymentRequest(preqDoc, true);
    SpringContext.getBean(KualiRuleService.class)
        .applyRules(new AttributedCalculateAccountsPayableEvent(preqDoc));

    PurchasingAccountsPayableDocumentBase document = (PurchasingAccountsPayableDocumentBase) apDoc;
    String accountDistributionMethod = document.getAccountDistributionMethod();

    if (PurapConstants.AccountDistributionMethodCodes.SEQUENTIAL_CODE.equalsIgnoreCase(
        accountDistributionMethod)) {
      // update the accounts amounts for PREQ and distribution method = sequential
      purapAccountingService.updatePreqItemAccountAmounts(item);
    } else {
      List<PurApAccountingLine> sourceAccountingLines = item.getSourceAccountingLines();
      for (PurApAccountingLine acctLine : sourceAccountingLines) {
        acctLine.setAmount(KualiDecimal.ZERO);
      }

      purapAccountingService.updatePreqProportionalItemAccountAmounts(item);
    }

    return mapping.findForward(KFSConstants.MAPPING_BASIC);
  }
  /**
   * Handles continue request. This request comes from the initial screen which gives indicates
   * whether the type is payment request, purchase order, or vendor. Based on that, the credit memo
   * is initially populated and the remaining tabs shown.
   *
   * @param mapping An ActionMapping
   * @param form An ActionForm
   * @param request The HttpServletRequest
   * @param response The HttpServletResponse
   * @throws Exception
   * @return An ActionForward
   */
  public ActionForward continueCreditMemo(
      ActionMapping mapping,
      ActionForm form,
      HttpServletRequest request,
      HttpServletResponse response)
      throws Exception {
    VendorCreditMemoForm cmForm = (VendorCreditMemoForm) form;
    VendorCreditMemoDocument creditMemoDocument = (VendorCreditMemoDocument) cmForm.getDocument();

    String defaultDistributionMethod =
        SpringContext.getBean(ParameterService.class)
            .getParameterValueAsString(
                PurapConstants.PURAP_NAMESPACE,
                "Document",
                PurapParameterConstants.DISTRIBUTION_METHOD_FOR_ACCOUNTING_LINES);

    String preqId = request.getParameter("document.paymentRequestIdentifier");
    if (!StringUtils.isEmpty(preqId)) {
      // get the po document and get the account distribution method code....
      String distributionCode = getDistributionMethodFromPReq(preqId);
      if (ObjectUtils.isNotNull(distributionCode)) {
        defaultDistributionMethod = distributionCode;
      }
    } else {
      String poId = request.getParameter("document.purchaseOrderIdentifier");
      if (!StringUtils.isEmpty(poId)) {
        // get the po document and get the account distribution method code....
        String distributionCode = getDistributionMethodFromPO(poId);
        if (ObjectUtils.isNotNull(distributionCode)) {
          defaultDistributionMethod = distributionCode;
        }
      }
    }

    // set the account distribution method code on the document.
    creditMemoDocument.setAccountDistributionMethod(defaultDistributionMethod);

    boolean rulePassed =
        SpringContext.getBean(KualiRuleService.class)
            .applyRules(new AttributedContinuePurapEvent(creditMemoDocument));
    if (!rulePassed) {
      return mapping.findForward(KFSConstants.MAPPING_BASIC);
    }

    if (creditMemoDocument.isSourceDocumentPaymentRequest()) {
      PaymentRequestDocument preq =
          SpringContext.getBean(PaymentRequestService.class)
              .getPaymentRequestById(creditMemoDocument.getPaymentRequestIdentifier());
      if (ObjectUtils.isNotNull(preq)) {
        // TODO figure out a more straightforward way to do this.  ailish put this in so the link id
        // would be set and the perm check would work
        creditMemoDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(
            preq.getAccountsPayablePurchasingDocumentLinkIdentifier());

        if (!SpringContext.getBean(DocumentHelperService.class)
            .getDocumentAuthorizer(creditMemoDocument)
            .isAuthorizedByTemplate(
                creditMemoDocument,
                KRADConstants.KNS_NAMESPACE,
                KimConstants.PermissionTemplateNames.OPEN_DOCUMENT,
                GlobalVariables.getUserSession().getPrincipalId())) {
          throw buildAuthorizationException("initiate document", creditMemoDocument);
        }
      }
    } else if (creditMemoDocument.isSourceDocumentPurchaseOrder()) {
      PurchaseOrderDocument po =
          SpringContext.getBean(PurchaseOrderService.class)
              .getCurrentPurchaseOrder(creditMemoDocument.getPurchaseOrderIdentifier());
      if (ObjectUtils.isNotNull(po)) {
        // TODO figure out a more straightforward way to do this.  ailish put this in so the link id
        // would be set and the perm check would work
        creditMemoDocument.setAccountsPayablePurchasingDocumentLinkIdentifier(
            po.getAccountsPayablePurchasingDocumentLinkIdentifier());

        if (!SpringContext.getBean(DocumentHelperService.class)
            .getDocumentAuthorizer(creditMemoDocument)
            .isAuthorizedByTemplate(
                creditMemoDocument,
                KRADConstants.KNS_NAMESPACE,
                KimConstants.PermissionTemplateNames.OPEN_DOCUMENT,
                GlobalVariables.getUserSession().getPrincipalId())) {
          throw buildAuthorizationException("initiate document", creditMemoDocument);
        }
      }
    } else {
      // do nothing for credit memos against a vendor; no link to PO means no need to hide doc based
      // on sensitive data
    }

    // preform duplicate check which will forward to a question prompt if one is found
    ActionForward forward =
        performDuplicateCreditMemoCheck(mapping, form, request, response, creditMemoDocument);
    if (forward != null) {
      return forward;
    }

    // perform validation of init tab
    SpringContext.getBean(CreditMemoService.class).populateAndSaveCreditMemo(creditMemoDocument);

    // sort below the line (doesn't really need to be done on CM, but will help if we ever bring btl
    // from other docs)
    SpringContext.getBean(PurapService.class).sortBelowTheLine(creditMemoDocument);

    // update the counts on the form
    cmForm.updateItemCounts();

    // if source is (PREQ or PO) and the PO status is CLOSED, automatically reopen the PO
    PurchaseOrderDocument po = creditMemoDocument.getPurchaseOrderDocument();
    if ((creditMemoDocument.isSourceDocumentPaymentRequest()
            || creditMemoDocument.isSourceDocumentPurchaseOrder())
        && PurapConstants.PurchaseOrderStatuses.APPDOC_CLOSED.equals(
            po.getApplicationDocumentStatus())) {
      initiateReopenPurchaseOrder(po, cmForm.getAnnotation());
    }

    // update the accounts amounts to zero.  The recalculate will calculate the totals...
    List<PurApItem> items = creditMemoDocument.getItems();

    for (PurApItem item : items) {
      for (PurApAccountingLine accountLine : item.getSourceAccountingLines()) {
        accountLine.setAmount(KualiDecimal.ZERO);
      }
    }

    return mapping.findForward(KFSConstants.MAPPING_BASIC);
  }