/**
   * Reverse current allocation (another allocation is produced) NOTE: this method is not saving
   * current object's modifications
   *
   * @see
   *     http://dewiki908/mediawiki/index.php/02181:_Verbuchungsfehler_bei_Zuordnungen_%282011092910000015%29
   */
  private void reverseCorrectIt0() {
    MAllocationHdr reversal = new MAllocationHdr(getCtx(), 0, get_TrxName());
    copyValues(this, reversal);

    //
    // 07570: Keep AD_Org of original document
    reversal.setAD_Org_ID(this.getAD_Org_ID());

    reversal.setDocumentNo(""); // let it generate a new document#
    reversal.setProcessing(false);
    reversal.setProcessed(false);
    reversal.setDocStatus(DOCSTATUS_Drafted);
    reversal.setDocAction(DOCACTION_Complete);
    reversal.setPosted(false);
    reversal.setReversal_ID(this.getC_AllocationHdr_ID());
    reversal.saveEx();

    this.setReversal_ID(reversal.getC_AllocationHdr_ID());
    saveEx();

    for (MAllocationLine line : this.getLines(true)) {
      MAllocationLine reversalLine = new MAllocationLine(reversal);
      MAllocationLine.copyValues(line, reversalLine);

      //
      // 07570: Keep AD_Org of original document
      reversalLine.setAD_Org_ID(line.getAD_Org_ID());

      reversalLine.setC_AllocationHdr_ID(reversal.getC_AllocationHdr_ID());
      reversalLine.setAmount(reversalLine.getAmount().negate());
      reversalLine.setDiscountAmt(reversalLine.getDiscountAmt().negate());
      reversalLine.setOverUnderAmt(reversalLine.getOverUnderAmt().negate());
      reversalLine.setWriteOffAmt(reversalLine.getWriteOffAmt().negate());
      reversalLine.setReversalLine_ID(line.getC_AllocationLine_ID());
      reversalLine.saveEx();

      line.setReversalLine_ID(reversalLine.getC_AllocationLine_ID());
      line.saveEx();
    }

    if (!reversal.processIt(DOCACTION_Complete)) {
      throw new AdempiereException(reversal.getProcessMsg());
    }
    reversal.setDocStatus(DOCSTATUS_Reversed);
    reversal.setDocAction(DOCACTION_None);
    reversal.saveEx();

    this.setDocStatus(DOCSTATUS_Reversed);
    this.setDocAction(DOCACTION_None);
  }
  /**
   * Prepare Document
   *
   * @return new status (In Progress or Invalid)
   */
  @Override
  public String prepareIt() {
    log.log(Level.INFO, "{0}", this);
    m_processMsg =
        ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_BEFORE_PREPARE);
    if (m_processMsg != null) return DocAction.STATUS_Invalid;

    //	Std Period open?
    MPeriod.testPeriodOpen(
        getCtx(), getDateAcct(), MDocType.DOCBASETYPE_PaymentAllocation, getAD_Org_ID());
    getLines(false);
    if (m_lines.length == 0) {
      m_processMsg = "@NoLines@";
      return DocAction.STATUS_Invalid;
    }

    // Stop the Document Workflow if invoice to allocate is as paid
    // @formatter:off
    // 04627: metas.ts: commenting out, because:
    // we want to allocate, even if the invoice is paid (in that case with amout=0), because a
    // customer might
    // inadvertedly overpay an invoice, but still this shall also be documented in the allocation
    //		if (this.getReversal_ID() <= 0) { // metas: tsa: 02181: check only if is not a reversal
    //		for (MAllocationLine line :m_lines)
    //		{
    //			if (line.getC_Invoice_ID() != 0)
    //			{
    //				final String whereClause = I_C_Invoice.COLUMNNAME_C_Invoice_ID + "=? AND "
    //								   + I_C_Invoice.COLUMNNAME_IsPaid + "=? AND "
    //								   + I_C_Invoice.COLUMNNAME_DocStatus + " NOT IN (?,?)";
    //				boolean InvoiceIsPaid = new Query(getCtx(), I_C_Invoice.Table_Name, whereClause,
    // get_TrxName())
    //				.setClient_ID()
    //				.setParameters(new Object[]{line.getC_Invoice_ID(), "Y", MInvoice.DOCSTATUS_Voided,
    // MInvoice.DOCSTATUS_Reversed})
    //				.match();
    //				if(InvoiceIsPaid)
    //					throw new  AdempiereException("@ValidationError@ @C_Invoice_ID@ @IsPaid@");
    //			}
    //		}
    //		}  // metas: tsa: 02181: check only if is not a reversal
    // @formatter:on
    //	Add up Amounts & validate
    BigDecimal approval = Env.ZERO;
    for (int i = 0; i < m_lines.length; i++) {
      MAllocationLine line = m_lines[i];
      approval = approval.add(line.getWriteOffAmt()).add(line.getDiscountAmt());
      //	Make sure there is BP
      if (line.getC_BPartner_ID() <= 0) {
        m_processMsg = "No Business Partner";
        return DocAction.STATUS_Invalid;
      }
    }
    setApprovalAmt(approval);
    //
    m_processMsg =
        ModelValidationEngine.get().fireDocValidate(this, ModelValidator.TIMING_AFTER_PREPARE);
    if (m_processMsg != null) return DocAction.STATUS_Invalid;

    m_justPrepared = true;
    if (!DOCACTION_Complete.equals(getDocAction())) setDocAction(DOCACTION_Complete);

    return DocAction.STATUS_InProgress;
  } //	prepareIt