Merge release-7.1 into master
This commit is contained in:
commit
15707d9aac
|
@ -0,0 +1,19 @@
|
||||||
|
SET SQLBLANKLINES ON
|
||||||
|
SET DEFINE OFF
|
||||||
|
|
||||||
|
-- IDEMPIERE-3215 Sales Order/Proposal BP shipper, cause inability to complete
|
||||||
|
-- Feb 12, 2020, 11:14:32 PM CET
|
||||||
|
UPDATE AD_Field SET DisplayLogic='@OrderType@=''SO'' | @DeliveryViaRule@=''S'' | @DeliveryViaRule@=''''', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2020-02-12 23:14:32','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1108
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Feb 12, 2020, 8:59:02 PM CET
|
||||||
|
UPDATE AD_Field SET DisplayLogic='@DeliveryViaRule@=''S''', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2020-02-12 20:59:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1109
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Feb 12, 2020, 8:59:28 PM CET
|
||||||
|
UPDATE AD_Field SET DisplayLogic='@DeliveryViaRule@=''S''', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_DATE('2020-02-12 20:59:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=56446
|
||||||
|
;
|
||||||
|
|
||||||
|
SELECT register_migration_script('202002122100_IDEMPIERE-3215.sql') FROM dual
|
||||||
|
;
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
-- IDEMPIERE-3215 Sales Order/Proposal BP shipper, cause inability to complete
|
||||||
|
-- Feb 12, 2020, 8:58:51 PM CET
|
||||||
|
-- Feb 12, 2020, 11:14:32 PM CET
|
||||||
|
UPDATE AD_Field SET DisplayLogic='@OrderType@=''SO'' | @DeliveryViaRule@=''S'' | @DeliveryViaRule@=''''', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2020-02-12 23:14:32','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1108
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Feb 12, 2020, 8:59:02 PM CET
|
||||||
|
UPDATE AD_Field SET DisplayLogic='@DeliveryViaRule@=''S''', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2020-02-12 20:59:02','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=1109
|
||||||
|
;
|
||||||
|
|
||||||
|
-- Feb 12, 2020, 8:59:28 PM CET
|
||||||
|
UPDATE AD_Field SET DisplayLogic='@DeliveryViaRule@=''S''', AD_Reference_Value_ID=NULL, AD_Val_Rule_ID=NULL, IsToolbarButton=NULL,Updated=TO_TIMESTAMP('2020-02-12 20:59:28','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Field_ID=56446
|
||||||
|
;
|
||||||
|
|
||||||
|
SELECT register_migration_script('202002122100_IDEMPIERE-3215.sql') FROM dual
|
||||||
|
;
|
||||||
|
|
|
@ -31,12 +31,12 @@ import org.compiere.model.MAllocationHdr;
|
||||||
import org.compiere.model.MAllocationLine;
|
import org.compiere.model.MAllocationLine;
|
||||||
import org.compiere.model.MCashLine;
|
import org.compiere.model.MCashLine;
|
||||||
import org.compiere.model.MConversionRate;
|
import org.compiere.model.MConversionRate;
|
||||||
import org.compiere.model.MCurrency;
|
|
||||||
import org.compiere.model.MFactAcct;
|
import org.compiere.model.MFactAcct;
|
||||||
import org.compiere.model.MInvoice;
|
import org.compiere.model.MInvoice;
|
||||||
import org.compiere.model.MInvoiceLine;
|
import org.compiere.model.MInvoiceLine;
|
||||||
import org.compiere.model.MOrder;
|
import org.compiere.model.MOrder;
|
||||||
import org.compiere.model.MPayment;
|
import org.compiere.model.MPayment;
|
||||||
|
import org.compiere.model.MPeriod;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
import org.compiere.util.DB;
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
|
@ -75,6 +75,9 @@ public class Doc_AllocationHdr extends Doc
|
||||||
private static final BigDecimal TOLERANCE = BigDecimal.valueOf(0.02);
|
private static final BigDecimal TOLERANCE = BigDecimal.valueOf(0.02);
|
||||||
/** Facts */
|
/** Facts */
|
||||||
private ArrayList<Fact> m_facts = null;
|
private ArrayList<Fact> m_facts = null;
|
||||||
|
BigDecimal gainLossAmt =Env.ZERO;
|
||||||
|
private BigDecimal cmGainLossAmt=Env.ZERO;
|
||||||
|
private ArrayList<FactLine> gainLossFactList;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -174,6 +177,12 @@ public class Doc_AllocationHdr extends Doc
|
||||||
Fact fact = new Fact(this, as, Fact.POST_Actual);
|
Fact fact = new Fact(this, as, Fact.POST_Actual);
|
||||||
Fact factForRGL = new Fact(this, as, Fact.POST_Actual); // dummy fact (not posted) to calculate Realized Gain & Loss
|
Fact factForRGL = new Fact(this, as, Fact.POST_Actual); // dummy fact (not posted) to calculate Realized Gain & Loss
|
||||||
boolean isInterOrg = isInterOrg(as);
|
boolean isInterOrg = isInterOrg(as);
|
||||||
|
BigDecimal paymentSelectAmt = Env.ZERO;
|
||||||
|
BigDecimal totalAllocationSource = Env.ZERO;
|
||||||
|
MPayment payment = null;
|
||||||
|
int lineID = 0;
|
||||||
|
MAccount bpAcct = null; // Liability/Receivables
|
||||||
|
gainLossFactList = new ArrayList<FactLine>();
|
||||||
|
|
||||||
for (int i = 0; i < p_lines.length; i++)
|
for (int i = 0; i < p_lines.length; i++)
|
||||||
{
|
{
|
||||||
|
@ -199,10 +208,7 @@ public class Doc_AllocationHdr extends Doc
|
||||||
|
|
||||||
FactLine fl = null;
|
FactLine fl = null;
|
||||||
FactLine flForRGL = null;
|
FactLine flForRGL = null;
|
||||||
MAccount bpAcct = null; // Liability/Receivables
|
|
||||||
MAccount payAcct = null; // Payment Selection
|
|
||||||
//
|
//
|
||||||
MPayment payment = null;
|
|
||||||
if (line.getC_Payment_ID() != 0)
|
if (line.getC_Payment_ID() != 0)
|
||||||
payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
|
payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
|
||||||
MInvoice invoice = null;
|
MInvoice invoice = null;
|
||||||
|
@ -254,7 +260,8 @@ public class Doc_AllocationHdr extends Doc
|
||||||
// if not using clearing accounts, then don't post amtsource
|
// if not using clearing accounts, then don't post amtsource
|
||||||
// change the allocationsource to be writeoff + discount
|
// change the allocationsource to be writeoff + discount
|
||||||
allocationSource = line.getDiscountAmt().add(line.getWriteOffAmt());
|
allocationSource = line.getDiscountAmt().add(line.getWriteOffAmt());
|
||||||
payAcct = getPaymentAcct(as, line.getC_Payment_ID());
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Normal behavior -- unchanged if using clearing accounts
|
// Normal behavior -- unchanged if using clearing accounts
|
||||||
|
@ -262,11 +269,14 @@ public class Doc_AllocationHdr extends Doc
|
||||||
// Payment/Cash DR
|
// Payment/Cash DR
|
||||||
if (line.getC_Payment_ID() != 0)
|
if (line.getC_Payment_ID() != 0)
|
||||||
{
|
{
|
||||||
payAcct = getPaymentAcct(as, line.getC_Payment_ID());
|
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
|
||||||
fl = fact.createLine (line, payAcct,
|
|
||||||
getC_Currency_ID(), line.getAmtSource(), null);
|
getC_Currency_ID(), line.getAmtSource(), null);
|
||||||
if (fl != null && payment != null)
|
if (fl != null && payment != null)
|
||||||
fl.setAD_Org_ID(payment.getAD_Org_ID());
|
fl.setAD_Org_ID(payment.getAD_Org_ID());
|
||||||
|
if (payment.getReversal_ID() > 0 )
|
||||||
|
paymentSelectAmt= paymentSelectAmt.add(fl.getAcctBalance().negate());
|
||||||
|
else
|
||||||
|
paymentSelectAmt= paymentSelectAmt.add(fl.getAcctBalance());
|
||||||
}
|
}
|
||||||
else if (line.getC_CashLine_ID() != 0)
|
else if (line.getC_CashLine_ID() != 0)
|
||||||
{
|
{
|
||||||
|
@ -393,11 +403,11 @@ public class Doc_AllocationHdr extends Doc
|
||||||
// Payment/Cash CR
|
// Payment/Cash CR
|
||||||
if (isUsingClearing && line.getC_Payment_ID() != 0) // Avoid usage of clearing accounts
|
if (isUsingClearing && line.getC_Payment_ID() != 0) // Avoid usage of clearing accounts
|
||||||
{
|
{
|
||||||
payAcct = getPaymentAcct(as, line.getC_Payment_ID());
|
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
|
||||||
fl = fact.createLine (line, payAcct,
|
|
||||||
getC_Currency_ID(), null, line.getAmtSource().negate());
|
getC_Currency_ID(), null, line.getAmtSource().negate());
|
||||||
if (fl != null && payment != null)
|
if (fl != null && payment != null)
|
||||||
fl.setAD_Org_ID(payment.getAD_Org_ID());
|
fl.setAD_Org_ID(payment.getAD_Org_ID());
|
||||||
|
paymentSelectAmt= paymentSelectAmt.add(fl.getAcctBalance().negate());
|
||||||
}
|
}
|
||||||
else if (isUsingClearing && line.getC_CashLine_ID() != 0) // Avoid usage of clearing accounts
|
else if (isUsingClearing && line.getC_CashLine_ID() != 0) // Avoid usage of clearing accounts
|
||||||
{
|
{
|
||||||
|
@ -435,13 +445,30 @@ public class Doc_AllocationHdr extends Doc
|
||||||
&& (getC_Currency_ID() != as.getC_Currency_ID() // payment allocation in foreign currency
|
&& (getC_Currency_ID() != as.getC_Currency_ID() // payment allocation in foreign currency
|
||||||
|| getC_Currency_ID() != line.getInvoiceC_Currency_ID())) // allocation <> invoice currency
|
|| getC_Currency_ID() != line.getInvoiceC_Currency_ID())) // allocation <> invoice currency
|
||||||
{
|
{
|
||||||
p_Error = createRealizedGainLoss (line, as, fact, bpAcct, invoice, payAcct, payment,
|
p_Error = createRealizedGainLoss (line, as, fact, bpAcct, invoice,
|
||||||
allocationSourceForRGL, allocationAccounted);
|
allocationSource, allocationAccounted);
|
||||||
|
if (p_Error != null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
totalAllocationSource = totalAllocationSource.add(line.getAmtSource());
|
||||||
|
lineID = line.get_ID();
|
||||||
|
} // for all lines
|
||||||
|
|
||||||
|
// rounding correction
|
||||||
|
if (payment != null && getC_Currency_ID() != as.getC_Currency_ID() ) // payment allocation in foreign currency
|
||||||
|
{
|
||||||
|
p_Error = createPaymentGainLoss (as, fact, getPaymentAcct(as, payment.get_ID()), payment,
|
||||||
|
totalAllocationSource, paymentSelectAmt, lineID);
|
||||||
if (p_Error != null)
|
if (p_Error != null)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // for all lines
|
if (getC_Currency_ID() != as.getC_Currency_ID())
|
||||||
|
{
|
||||||
|
p_Error = createInvoiceRounding (as, fact, bpAcct);
|
||||||
|
if (p_Error != null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
// FR [ 1840016 ] Avoid usage of clearing accounts - subject to C_AcctSchema.IsPostIfClearingEqual
|
// FR [ 1840016 ] Avoid usage of clearing accounts - subject to C_AcctSchema.IsPostIfClearingEqual
|
||||||
if ( (!as.isPostIfClearingEqual()) && p_lines.length > 0 && (!isInterOrg)) {
|
if ( (!as.isPostIfClearingEqual()) && p_lines.length > 0 && (!isInterOrg)) {
|
||||||
|
@ -652,7 +679,7 @@ public class Doc_AllocationHdr extends Doc
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.log(Level.SEVERE, sql, e);
|
throw new RuntimeException(e.getLocalizedMessage(), e);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
@ -697,21 +724,17 @@ public class Doc_AllocationHdr extends Doc
|
||||||
* Accounted Amount of the Allocation
|
* Accounted Amount of the Allocation
|
||||||
* @param as accounting schema
|
* @param as accounting schema
|
||||||
* @param fact fact
|
* @param fact fact
|
||||||
* @param invAcct invoice account
|
* @param acct account
|
||||||
* @param invoice invoice
|
* @param invoice invoice
|
||||||
* @param payAcct payment account
|
|
||||||
* @param payment payment
|
|
||||||
* @param allocationSource source amt
|
* @param allocationSource source amt
|
||||||
* @param allocationAccounted acct amt
|
* @param allocationAccounted acct amt
|
||||||
* @return Error Message or null if OK
|
* @return Error Message or null if OK
|
||||||
*/
|
*/
|
||||||
private String createRealizedGainLoss (DocLine line, MAcctSchema as, Fact fact, MAccount invAcct,
|
private String createRealizedGainLoss (DocLine line, MAcctSchema as, Fact fact, MAccount acct,
|
||||||
MInvoice invoice, MAccount payAcct, MPayment payment, BigDecimal allocationSource, BigDecimal allocationAccounted)
|
MInvoice invoice, BigDecimal allocationSource, BigDecimal allocationAccounted)
|
||||||
{
|
{
|
||||||
BigDecimal invoiceSource = null;
|
BigDecimal invoiceSource = null;
|
||||||
BigDecimal invoiceAccounted = null;
|
BigDecimal invoiceAccounted = null;
|
||||||
BigDecimal paymentSource = null;
|
|
||||||
BigDecimal paymentAccounted = null;
|
|
||||||
//
|
//
|
||||||
StringBuilder sql = new StringBuilder()
|
StringBuilder sql = new StringBuilder()
|
||||||
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
@ -732,129 +755,66 @@ public class Doc_AllocationHdr extends Doc
|
||||||
invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
|
invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Requires that Invoice is Posted
|
// Requires that Invoice is Posted
|
||||||
if (invoiceSource == null || invoiceAccounted == null)
|
if (invoiceSource == null || invoiceAccounted == null)
|
||||||
return "Gain/Loss - Invoice not posted yet";
|
return "Gain/Loss - Invoice not posted yet";
|
||||||
//
|
//
|
||||||
String invoiceCur = MCurrency.get(getCtx(), invoice.getC_Currency_ID()).getISO_Code();
|
StringBuilder description = new StringBuilder("Invoice=(").append(invoice.getC_Currency_ID()).append(")").append(invoiceSource).append("/").append(invoiceAccounted)
|
||||||
String allocCur = MCurrency.get(getCtx(), getC_Currency_ID()).getISO_Code();
|
.append(" - Allocation=(").append(getC_Currency_ID()).append(")").append(allocationSource).append("/").append(allocationAccounted);
|
||||||
StringBuilder descriptionInv = new StringBuilder("Invoice=(").append(invoiceCur).append(")").append(invoiceSource).append("/").append(invoiceAccounted)
|
if (log.isLoggable(Level.FINE)) log.fine(description.toString());
|
||||||
.append(" - Allocation=(").append(allocCur).append(")").append(allocationSource).append("/").append(allocationAccounted);
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(descriptionInv.toString());
|
|
||||||
// Allocation not Invoice Currency
|
// Allocation not Invoice Currency
|
||||||
BigDecimal allocationInvoiceSource = allocationSource;
|
|
||||||
if (getC_Currency_ID() != invoice.getC_Currency_ID())
|
if (getC_Currency_ID() != invoice.getC_Currency_ID())
|
||||||
{
|
{
|
||||||
allocationInvoiceSource = MConversionRate.convert(getCtx(),
|
BigDecimal allocationSourceNew = MConversionRate.convert(getCtx(),
|
||||||
allocationSource, getC_Currency_ID(),
|
allocationSource, getC_Currency_ID(),
|
||||||
invoice.getC_Currency_ID(), getDateAcct(),
|
invoice.getC_Currency_ID(), getDateAcct(),
|
||||||
invoice.getC_ConversionType_ID(), invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
invoice.getC_ConversionType_ID(), invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||||
if (allocationInvoiceSource == null)
|
if (allocationSourceNew == null)
|
||||||
return "Gain/Loss - No Conversion from Allocation->Invoice";
|
return "Gain/Loss - No Conversion from Allocation->Invoice";
|
||||||
StringBuilder d2 = new StringBuilder("Allocation=(").append(allocCur).append(")").append(allocationSource)
|
StringBuilder d2 = new StringBuilder("Allocation=(").append(getC_Currency_ID()).append(")").append(allocationSource)
|
||||||
.append("->(").append(invoiceCur).append(")").append(allocationInvoiceSource);
|
.append("->(").append(invoice.getC_Currency_ID()).append(")").append(allocationSourceNew);
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
descriptionInv.append(" - ").append(d2);
|
description.append(" - ").append(d2);
|
||||||
|
allocationSource = allocationSourceNew;
|
||||||
}
|
}
|
||||||
|
|
||||||
BigDecimal invoiceDifference = null; // gain is negative
|
BigDecimal acctDifference = null; // gain is negative
|
||||||
// Full Invoice in currency
|
//reversal entry
|
||||||
if (allocationInvoiceSource.compareTo(invoiceSource) == 0)
|
if (allocationSource.signum() > 0 )
|
||||||
{
|
{
|
||||||
invoiceDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
acctDifference = invoiceAccounted.subtract(allocationAccounted.abs());
|
||||||
StringBuilder d2 = new StringBuilder("(full) = ").append(invoiceDifference);
|
}
|
||||||
|
// Full Payment in currency
|
||||||
|
if (allocationSource.compareTo(invoiceSource) == 0)
|
||||||
|
{
|
||||||
|
acctDifference = invoiceAccounted.subtract(allocationAccounted.abs()); // gain is negative
|
||||||
|
|
||||||
|
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
descriptionInv.append(" - ").append(d2);
|
description.append(" - ").append(d2);
|
||||||
}
|
}
|
||||||
else // partial or MC
|
else // partial or MC
|
||||||
{
|
{
|
||||||
// percent of total payment
|
// percent of total payment
|
||||||
double multiplier = allocationInvoiceSource.doubleValue() / invoiceSource.doubleValue();
|
double multiplier = allocationSource.doubleValue() / invoiceSource.doubleValue();
|
||||||
// Reduce Orig Invoice Accounted
|
// Reduce Orig Invoice Accounted
|
||||||
invoiceAccounted = invoiceAccounted.multiply(BigDecimal.valueOf(multiplier));
|
invoiceAccounted = invoiceAccounted.multiply(BigDecimal.valueOf(multiplier));
|
||||||
// Difference based on percentage of Orig Invoice
|
// Difference based on percentage of Orig Invoice
|
||||||
invoiceDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
acctDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
||||||
// ignore Tolerance
|
// ignore Tolerance
|
||||||
if (invoiceDifference.abs().compareTo(TOLERANCE) < 0)
|
if (acctDifference.abs().compareTo(TOLERANCE) < 0)
|
||||||
invoiceDifference = Env.ZERO;
|
acctDifference = Env.ZERO;
|
||||||
// Round
|
// Round
|
||||||
int precision = as.getStdPrecision();
|
int precision = as.getStdPrecision();
|
||||||
if (invoiceDifference.scale() > precision)
|
if (acctDifference.scale() > precision)
|
||||||
invoiceDifference = invoiceDifference.setScale(precision, RoundingMode.HALF_UP);
|
acctDifference = acctDifference.setScale(precision, RoundingMode.HALF_UP);
|
||||||
StringBuilder d2 = new StringBuilder("(partial) = ").append(invoiceDifference).append(" - Multiplier=").append(multiplier);
|
StringBuilder d2 = new StringBuilder("(partial) = ").append(acctDifference).append(" - Multiplier=").append(multiplier);
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
descriptionInv.append(" - ").append(d2);
|
description.append(" - ").append(d2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For Payment
|
if (acctDifference.signum() == 0)
|
||||||
BigDecimal paymentDifference = Env.ZERO;
|
|
||||||
StringBuilder descriptionPay = null;
|
|
||||||
if (payment != null && payment.getC_Payment_ID() > 0) {
|
|
||||||
List<Object> valuesPay = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
|
|
||||||
MPayment.Table_ID, payment.getC_Payment_ID(), as.getC_AcctSchema_ID());
|
|
||||||
if (valuesPay != null) {
|
|
||||||
if (invoice.isSOTrx()) {
|
|
||||||
paymentSource = (BigDecimal) valuesPay.get(2); // AmtSourceCr
|
|
||||||
paymentAccounted = (BigDecimal) valuesPay.get(3); // AmtAcctCr
|
|
||||||
} else {
|
|
||||||
paymentSource = (BigDecimal) valuesPay.get(0); // AmtSourceDr
|
|
||||||
paymentAccounted = (BigDecimal) valuesPay.get(1); // AmtAcctDr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Requires that Payment is Posted
|
|
||||||
if (paymentSource == null || paymentAccounted == null)
|
|
||||||
return "Gain/Loss - Payment not posted yet";
|
|
||||||
//
|
|
||||||
String paymentCur = MCurrency.get(getCtx(), payment.getC_Currency_ID()).getISO_Code();
|
|
||||||
descriptionPay = new StringBuilder("Payment=(").append(paymentCur).append(")").append(paymentSource).append("/").append(paymentAccounted)
|
|
||||||
.append(" - Allocation=(").append(allocCur).append(")").append(allocationSource).append("/").append(allocationAccounted);
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(descriptionPay.toString());
|
|
||||||
// Allocation not Payment Currency
|
|
||||||
BigDecimal allocationPaymentSource = allocationSource;
|
|
||||||
if (getC_Currency_ID() != payment.getC_Currency_ID())
|
|
||||||
{
|
|
||||||
allocationPaymentSource = MConversionRate.convert(getCtx(),
|
|
||||||
allocationSource, getC_Currency_ID(),
|
|
||||||
payment.getC_Currency_ID(), getDateAcct(),
|
|
||||||
payment.getC_ConversionType_ID(), payment.getAD_Client_ID(), payment.getAD_Org_ID());
|
|
||||||
if (allocationPaymentSource == null)
|
|
||||||
return "Gain/Loss - No Conversion from Allocation->Payment";
|
|
||||||
StringBuilder d2 = new StringBuilder("Allocation=(").append(allocCur).append(")").append(allocationSource)
|
|
||||||
.append("->(").append(paymentCur).append(")").append(allocationPaymentSource);
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
|
||||||
descriptionPay.append(" - ").append(d2);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Full Payment in currency
|
|
||||||
if (allocationPaymentSource.compareTo(paymentSource) == 0)
|
|
||||||
{
|
|
||||||
paymentDifference = paymentAccounted.subtract(allocationAccounted); // gain is negative
|
|
||||||
StringBuilder d2 = new StringBuilder("(full) = ").append(paymentDifference);
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
|
||||||
descriptionPay.append(" - ").append(d2);
|
|
||||||
}
|
|
||||||
else // partial or MC
|
|
||||||
{
|
|
||||||
// percent of total payment
|
|
||||||
double multiplier = allocationPaymentSource.doubleValue() / paymentSource.doubleValue();
|
|
||||||
// Reduce Orig Payment Accounted
|
|
||||||
paymentAccounted = paymentAccounted.multiply(BigDecimal.valueOf(multiplier));
|
|
||||||
// Difference based on percentage of Orig Payment
|
|
||||||
paymentDifference = paymentAccounted.subtract(allocationAccounted); // gain is negative
|
|
||||||
// ignore Tolerance
|
|
||||||
if (paymentDifference.abs().compareTo(TOLERANCE) < 0)
|
|
||||||
paymentDifference = Env.ZERO;
|
|
||||||
// Round
|
|
||||||
int precision = as.getStdPrecision();
|
|
||||||
if (paymentDifference.scale() > precision)
|
|
||||||
paymentDifference = paymentDifference.setScale(precision, RoundingMode.HALF_UP);
|
|
||||||
StringBuilder d2 = new StringBuilder("(partial) = ").append(paymentDifference).append(" - Multiplier=").append(multiplier);
|
|
||||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
|
||||||
descriptionPay.append(" - ").append(d2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (invoiceDifference.signum() == 0 && paymentDifference.signum() == 0)
|
|
||||||
{
|
{
|
||||||
log.fine("No Difference");
|
log.fine("No Difference");
|
||||||
return null;
|
return null;
|
||||||
|
@ -862,51 +822,28 @@ public class Doc_AllocationHdr extends Doc
|
||||||
|
|
||||||
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||||
|
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0)
|
||||||
|
cmGainLossAmt = cmGainLossAmt.add(acctDifference);
|
||||||
|
else
|
||||||
|
gainLossAmt = gainLossAmt.add(acctDifference);
|
||||||
//
|
//
|
||||||
BigDecimal acctDifference = invoiceDifference.subtract(paymentDifference);
|
|
||||||
if (invoice.isSOTrx())
|
if (invoice.isSOTrx())
|
||||||
{
|
{
|
||||||
if (acctDifference.signum() != 0) {
|
|
||||||
FactLine fl = fact.createLine (line, loss, gain, as.getC_Currency_ID(), acctDifference);
|
FactLine fl = fact.createLine (line, loss, gain, as.getC_Currency_ID(), acctDifference);
|
||||||
StringBuilder description = new StringBuilder(descriptionInv);
|
|
||||||
if (paymentDifference.signum() != 0 && descriptionPay != null) {
|
|
||||||
description.append(" / ").append(descriptionPay);
|
|
||||||
}
|
|
||||||
fl.setDescription(description.toString());
|
fl.setDescription(description.toString());
|
||||||
fl.setAD_Org_ID(invoice.getAD_Org_ID());
|
fl = fact.createLine (line, acct, as.getC_Currency_ID(), acctDifference.negate());
|
||||||
}
|
gainLossFactList.add(fl);
|
||||||
if (invoiceDifference.signum() != 0) {
|
|
||||||
FactLine fl = fact.createLine (line, invAcct, as.getC_Currency_ID(), invoiceDifference.negate());
|
|
||||||
fl.setDescription(descriptionInv.toString());
|
|
||||||
fl.setAD_Org_ID(invoice.getAD_Org_ID());
|
|
||||||
}
|
|
||||||
if (paymentDifference.signum() != 0) {
|
|
||||||
FactLine fl = fact.createLine (line, payAcct, as.getC_Currency_ID(), paymentDifference);
|
|
||||||
fl.setDescription(descriptionPay.toString());
|
|
||||||
fl.setAD_Org_ID(invoice.getAD_Org_ID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (invoiceDifference.signum() != 0) {
|
FactLine fl = fact.createLine (line, acct,
|
||||||
FactLine fl = fact.createLine (line, invAcct, as.getC_Currency_ID(), invoiceDifference);
|
as.getC_Currency_ID(), acctDifference);
|
||||||
fl.setDescription(descriptionInv.toString());
|
gainLossFactList.add(fl);
|
||||||
fl.setAD_Org_ID(invoice.getAD_Org_ID());
|
fl = fact.createLine (line, loss, gain,
|
||||||
}
|
as.getC_Currency_ID(), acctDifference.negate());
|
||||||
if (paymentDifference.signum() != 0) {
|
|
||||||
FactLine fl = fact.createLine (line, payAcct, as.getC_Currency_ID(), paymentDifference.negate());
|
|
||||||
fl.setDescription(descriptionPay.toString());
|
|
||||||
fl.setAD_Org_ID(invoice.getAD_Org_ID());
|
|
||||||
}
|
|
||||||
if (acctDifference.signum() != 0) {
|
|
||||||
FactLine fl = fact.createLine (line, loss, gain, as.getC_Currency_ID(), acctDifference.negate());
|
|
||||||
StringBuilder description = new StringBuilder(descriptionInv);
|
|
||||||
if (paymentDifference.signum() != 0 && descriptionPay != null) {
|
|
||||||
description.append(" / ").append(descriptionPay);
|
|
||||||
}
|
|
||||||
fl.setDescription(description.toString());
|
fl.setDescription(description.toString());
|
||||||
fl.setAD_Org_ID(invoice.getAD_Org_ID());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
} // createRealizedGainLoss
|
} // createRealizedGainLoss
|
||||||
|
@ -947,7 +884,7 @@ public class Doc_AllocationHdr extends Doc
|
||||||
// Get Source Amounts with account
|
// Get Source Amounts with account
|
||||||
String sql = "SELECT * "
|
String sql = "SELECT * "
|
||||||
+ "FROM Fact_Acct "
|
+ "FROM Fact_Acct "
|
||||||
+ "WHERE AD_Table_ID=318 AND Record_ID=?" // Invoice
|
+ "WHERE AD_Table_ID=? AND Record_ID=?" // Invoice
|
||||||
+ " AND C_AcctSchema_ID=?"
|
+ " AND C_AcctSchema_ID=?"
|
||||||
+ " AND Line_ID IS NULL"; // header lines like tax or total
|
+ " AND Line_ID IS NULL"; // header lines like tax or total
|
||||||
PreparedStatement pstmt = null;
|
PreparedStatement pstmt = null;
|
||||||
|
@ -955,15 +892,16 @@ public class Doc_AllocationHdr extends Doc
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pstmt = DB.prepareStatement(sql, getTrxName());
|
pstmt = DB.prepareStatement(sql, getTrxName());
|
||||||
pstmt.setInt(1, line.getC_Invoice_ID());
|
pstmt.setInt(1, MInvoice.Table_ID);
|
||||||
pstmt.setInt(2, as.getC_AcctSchema_ID());
|
pstmt.setInt(2, line.getC_Invoice_ID());
|
||||||
|
pstmt.setInt(3, as.getC_AcctSchema_ID());
|
||||||
rs = pstmt.executeQuery();
|
rs = pstmt.executeQuery();
|
||||||
while (rs.next())
|
while (rs.next())
|
||||||
tax.addInvoiceFact (new MFactAcct(getCtx(), rs, fact.get_TrxName()));
|
tax.addInvoiceFact (new MFactAcct(getCtx(), rs, fact.get_TrxName()));
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
log.log(Level.SEVERE, sql, e);
|
throw new RuntimeException(e.getLocalizedMessage(), e);
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
DB.close(rs, pstmt);
|
DB.close(rs, pstmt);
|
||||||
|
@ -982,6 +920,430 @@ public class Doc_AllocationHdr extends Doc
|
||||||
|
|
||||||
} // createTaxCorrection
|
} // createTaxCorrection
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Create Rounding Correction.
|
||||||
|
* Compares the Accounted Amount of the Payment to the
|
||||||
|
* Accounted Amount of the Allocation
|
||||||
|
* @param as accounting schema
|
||||||
|
* @param fact fact
|
||||||
|
* @param acct account
|
||||||
|
* @param payment payment
|
||||||
|
* @param paymentSource source amt
|
||||||
|
* @param paymentAccounted acct amt
|
||||||
|
* @return Error Message or null if OK
|
||||||
|
*/
|
||||||
|
private String createPaymentGainLoss (MAcctSchema as, Fact fact, MAccount acct,
|
||||||
|
MPayment payment, BigDecimal allocationSource, BigDecimal totalAllocationAccounted, int lineID)
|
||||||
|
{
|
||||||
|
BigDecimal paymentSource = null;
|
||||||
|
BigDecimal paymentAccounted = null;
|
||||||
|
//
|
||||||
|
StringBuilder sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID=?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID = ? ")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
|
||||||
|
// For Payment
|
||||||
|
List<Object> valuesPay = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
|
||||||
|
MPayment.Table_ID, payment.getC_Payment_ID(), as.getC_AcctSchema_ID(), acct.getAccount_ID());
|
||||||
|
if (valuesPay != null) {
|
||||||
|
if (payment.isReceipt()) {
|
||||||
|
paymentSource = (BigDecimal) valuesPay.get(2); // AmtSourceCr
|
||||||
|
paymentAccounted = (BigDecimal) valuesPay.get(3); // AmtAcctCr
|
||||||
|
} else {
|
||||||
|
paymentSource = (BigDecimal) valuesPay.get(0); // AmtSourceDr
|
||||||
|
paymentAccounted = (BigDecimal) valuesPay.get(1); // AmtAcctDr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires that Allocation is Posted
|
||||||
|
if (paymentSource == null || paymentAccounted == null)
|
||||||
|
return null; //"Gain/Loss - Payment not posted yet";
|
||||||
|
//
|
||||||
|
StringBuilder description = new StringBuilder("Payment=(").append(payment.getC_Currency_ID()).append(")").append(paymentSource).append("/").append(paymentAccounted)
|
||||||
|
.append(" - Allocation=(").append(getC_Currency_ID()).append(")").append(allocationSource).append("/").append(totalAllocationAccounted);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(description.toString());
|
||||||
|
|
||||||
|
boolean isSameSourceDiffPeriod = false;
|
||||||
|
BigDecimal acctDifference = null; // gain is negative
|
||||||
|
// Full Payment in currency
|
||||||
|
if (allocationSource.abs().compareTo(paymentSource.abs()) == 0)
|
||||||
|
{
|
||||||
|
acctDifference = totalAllocationAccounted.subtract(paymentAccounted.abs()); // gain is negative
|
||||||
|
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
|
description.append(" - ").append(d2);
|
||||||
|
|
||||||
|
// Different period
|
||||||
|
if (MPeriod.getC_Period_ID(getCtx(), payment.getDateAcct(), payment.getAD_Org_ID()) !=
|
||||||
|
MPeriod.getC_Period_ID(getCtx(), getDateAcct(), getAD_Org_ID()))
|
||||||
|
{
|
||||||
|
BigDecimal allocationAccounted0 = MConversionRate.convert(getCtx(),
|
||||||
|
allocationSource, getC_Currency_ID(),
|
||||||
|
as.getC_Currency_ID(), payment.getDateAcct(),
|
||||||
|
payment.getC_ConversionType_ID(), payment.getAD_Client_ID(), payment.getAD_Org_ID());
|
||||||
|
BigDecimal paymentAccounted0 = MConversionRate.convert(getCtx(),
|
||||||
|
paymentSource, getC_Currency_ID(),
|
||||||
|
as.getC_Currency_ID(), getDateAcct(),
|
||||||
|
getC_ConversionType_ID(), getAD_Client_ID(), getAD_Org_ID());
|
||||||
|
isSameSourceDiffPeriod = allocationAccounted0.abs().compareTo(paymentAccounted.abs()) == 0 &&
|
||||||
|
paymentAccounted0.abs().compareTo(totalAllocationAccounted.abs()) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acctDifference == null || acctDifference.signum() == 0)
|
||||||
|
{
|
||||||
|
log.fine("No Difference");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||||
|
//
|
||||||
|
if (payment.isReceipt())
|
||||||
|
{
|
||||||
|
FactLine fl = fact.createLine (null, acct,as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
fl.setLine_ID(lineID);
|
||||||
|
if (!fact.isAcctBalanced())
|
||||||
|
{
|
||||||
|
if (!isSameSourceDiffPeriod && as.isCurrencyBalancing() && as.getC_Currency_ID() != payment.getC_Currency_ID() )
|
||||||
|
{
|
||||||
|
fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference);
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
fl = fact.createLine (null, loss, gain,as.getC_Currency_ID(), acctDifference);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FactLine fl = fact.createLine (null, acct,as.getC_Currency_ID(), acctDifference);
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
fl.setLine_ID(lineID);
|
||||||
|
if (!fact.isAcctBalanced())
|
||||||
|
{
|
||||||
|
if (!isSameSourceDiffPeriod && as.isCurrencyBalancing() && as.getC_Currency_ID() != payment.getC_Currency_ID() )
|
||||||
|
{
|
||||||
|
fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
} else {
|
||||||
|
fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************
|
||||||
|
* Create Rounding Correction.
|
||||||
|
* Compares the Accounted Amount of the AR/AP Invoice to the
|
||||||
|
* Accounted Amount of the AR/AP Allocation
|
||||||
|
* @param as accounting schema
|
||||||
|
* @param fact fact
|
||||||
|
* @param bpAcct account
|
||||||
|
* @param payment payment
|
||||||
|
* @return Error Message or null if OK
|
||||||
|
*/
|
||||||
|
private String createInvoiceRounding(MAcctSchema as, Fact fact, MAccount bpAcct) {
|
||||||
|
PreparedStatement pstmt = null;
|
||||||
|
ResultSet rs = null;
|
||||||
|
// Invoice AR/AP
|
||||||
|
BigDecimal totalInvoiceSource = BigDecimal.ZERO;
|
||||||
|
BigDecimal totalInvoiceAccounted = BigDecimal.ZERO;
|
||||||
|
boolean isCMReversal =false ;
|
||||||
|
MInvoice invoice = null;
|
||||||
|
MPayment payment = null;
|
||||||
|
ArrayList<MInvoice> invList = new ArrayList<MInvoice>();
|
||||||
|
for (int i = 0; i < p_lines.length; i++)
|
||||||
|
{
|
||||||
|
DocLine_Allocation line = (DocLine_Allocation)p_lines[i];
|
||||||
|
if (line.getC_Invoice_ID() != 0)
|
||||||
|
invoice = new MInvoice (getCtx(), line.getC_Invoice_ID(), getTrxName());
|
||||||
|
if (line.getC_Payment_ID() != 0)
|
||||||
|
payment = new MPayment (getCtx(), line.getC_Payment_ID(), getTrxName());
|
||||||
|
|
||||||
|
if (invoice != null )
|
||||||
|
{
|
||||||
|
boolean isDebit = false;
|
||||||
|
// to cater for invoice reverse-accrual.
|
||||||
|
if (invoice.isSOTrx() && !invoice.isCreditMemo())
|
||||||
|
isDebit = true;
|
||||||
|
else if (!invoice.isSOTrx() && invoice.isCreditMemo() && invoice.getReversal_ID() > 0 )
|
||||||
|
isDebit = true;
|
||||||
|
else if (invoice.isSOTrx() && invoice.isCreditMemo() && invoice.getReversal_ID() == 0)
|
||||||
|
isDebit = true;
|
||||||
|
//
|
||||||
|
StringBuilder sql = new StringBuilder("SELECT ")
|
||||||
|
.append((isDebit )
|
||||||
|
? "SUM(AmtSourceDr), SUM(AmtAcctDr)" // so
|
||||||
|
: "SUM(AmtSourceCr), SUM(AmtAcctCr)") // po
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID=?") // Invoice
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND PostingType='A'")
|
||||||
|
.append(" AND Account_ID= ? ");
|
||||||
|
pstmt = null;
|
||||||
|
rs = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pstmt = DB.prepareStatement(sql.toString(), getTrxName());
|
||||||
|
pstmt.setInt(1, MInvoice.Table_ID);
|
||||||
|
pstmt.setInt(2, invoice.getC_Invoice_ID());
|
||||||
|
pstmt.setInt(3, as.getC_AcctSchema_ID());
|
||||||
|
pstmt.setInt(4, bpAcct.getAccount_ID());
|
||||||
|
rs = pstmt.executeQuery();
|
||||||
|
if (rs.next())
|
||||||
|
{
|
||||||
|
BigDecimal invoiceSource = rs.getBigDecimal(1);
|
||||||
|
BigDecimal invoiceAccounted = rs.getBigDecimal(2);
|
||||||
|
if ( !invList.contains(invoice))
|
||||||
|
{
|
||||||
|
totalInvoiceSource =totalInvoiceSource.add(invoiceSource);
|
||||||
|
totalInvoiceAccounted =totalInvoiceAccounted.add(invoiceAccounted);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
invList.add(invoice);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
DB.close(rs, pstmt);
|
||||||
|
rs = null; pstmt = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BigDecimal allocInvoiceSource = BigDecimal.ZERO;
|
||||||
|
BigDecimal allocInvoiceAccounted = BigDecimal.ZERO;
|
||||||
|
MAllocationLine allocationLine = null;
|
||||||
|
FactLine[] factlines = fact.getLines();
|
||||||
|
boolean isExcludeCMGainLoss = false;
|
||||||
|
for (FactLine factLine : factlines) {
|
||||||
|
if (bpAcct != null) {
|
||||||
|
if (factLine.getAccount_ID() == bpAcct.getAccount_ID() )
|
||||||
|
{
|
||||||
|
if (factLine.getLine_ID() != 0 )
|
||||||
|
allocationLine = new MAllocationLine(getCtx(), factLine.getLine_ID(), getTrxName());
|
||||||
|
|
||||||
|
if (allocationLine != null)
|
||||||
|
invoice = allocationLine.getInvoice();
|
||||||
|
|
||||||
|
if (invoice.isSOTrx())
|
||||||
|
{
|
||||||
|
if (factLine.getC_Currency_ID() != as.getC_Currency_ID())
|
||||||
|
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceCr());
|
||||||
|
if (!gainLossFactList.contains(factLine) && !invoice.isCreditMemo())
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctCr());
|
||||||
|
|
||||||
|
if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo() && invoice.getReversal_ID() > 0 ) {
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
|
||||||
|
if (!invoice.getDateAcct().equals(getDateAcct()))
|
||||||
|
isCMReversal =true;
|
||||||
|
}
|
||||||
|
if (invoice!=null)
|
||||||
|
{
|
||||||
|
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0 ) {
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt.abs());
|
||||||
|
cmGainLossAmt = Env.ZERO;
|
||||||
|
}
|
||||||
|
if (gainLossFactList.contains(factLine)) {
|
||||||
|
isExcludeCMGainLoss = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (payment != null && payment.getReversal_ID() > 0 && !gainLossFactList.contains(factLine))
|
||||||
|
{
|
||||||
|
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr());
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
|
||||||
|
}
|
||||||
|
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
if (as.getC_Currency_ID() != factLine.getC_Currency_ID())
|
||||||
|
allocInvoiceSource = allocInvoiceSource.add(factLine.getAmtSourceDr());
|
||||||
|
|
||||||
|
if (!gainLossFactList.contains(factLine) && !invoice.isCreditMemo())
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctDr());
|
||||||
|
|
||||||
|
if (!gainLossFactList.contains(factLine) && invoice.isCreditMemo() && invoice.getReversal_ID() > 0 ) {
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(factLine.getAmtAcctCr());
|
||||||
|
// this is to cater for reverse-accrual.
|
||||||
|
if (!invoice.getDateAcct().equals(getDateAcct()))
|
||||||
|
isCMReversal =true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (invoice!=null )
|
||||||
|
{
|
||||||
|
if (invoice.isCreditMemo() || invoice.getReversal_ID() > 0 ) {
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt.abs());
|
||||||
|
cmGainLossAmt = Env.ZERO;
|
||||||
|
}
|
||||||
|
if (gainLossFactList.contains(factLine)) {
|
||||||
|
isExcludeCMGainLoss = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
BigDecimal acctDifference = null; // gain is negative
|
||||||
|
//
|
||||||
|
StringBuilder description = new StringBuilder("Invoice=(").append(getC_Currency_ID()).append(")").append(allocInvoiceSource).append("/").append(allocInvoiceAccounted);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(description.toString());
|
||||||
|
boolean isBPartnerAdjust = true;
|
||||||
|
if (allocInvoiceSource.abs().compareTo(totalInvoiceSource.abs()) == 0)
|
||||||
|
{
|
||||||
|
if (isExcludeCMGainLoss)
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt);
|
||||||
|
if (payment != null && payment.getReversal_ID() > 0 )
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.subtract(gainLossAmt);
|
||||||
|
else
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(gainLossAmt);
|
||||||
|
if (isCMReversal)
|
||||||
|
acctDifference = totalInvoiceAccounted.subtract(allocInvoiceAccounted.abs());
|
||||||
|
else
|
||||||
|
acctDifference = allocInvoiceAccounted.subtract(totalInvoiceAccounted.abs()); // gain is positive for receipt
|
||||||
|
|
||||||
|
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
|
description.append(" - ").append(d2);
|
||||||
|
} else{
|
||||||
|
MAllocationHdr[] allocations = MAllocationHdr.getOfInvoice(getCtx(), invoice.get_ID(), getTrxName());
|
||||||
|
for (MAllocationHdr alloc : allocations)
|
||||||
|
{
|
||||||
|
StringBuilder sql = new StringBuilder("SELECT ")
|
||||||
|
.append(invoice.isSOTrx()
|
||||||
|
? "SUM(AmtSourceCr), SUM(AmtAcctCr), SUM(AmtAcctDr)" // so
|
||||||
|
: "SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtAcctCr)") // po
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID=?") // allocation
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND PostingType='A'")
|
||||||
|
.append(" AND Account_ID= ? ");
|
||||||
|
pstmt = null;
|
||||||
|
rs = null;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
pstmt = DB.prepareStatement(sql.toString(), getTrxName());
|
||||||
|
pstmt.setInt(1, MAllocationHdr.Table_ID);
|
||||||
|
pstmt.setInt(2, alloc.get_ID());
|
||||||
|
pstmt.setInt(3, as.getC_AcctSchema_ID());
|
||||||
|
pstmt.setInt(4, bpAcct.getAccount_ID());
|
||||||
|
rs = pstmt.executeQuery();
|
||||||
|
if (rs.next())
|
||||||
|
{
|
||||||
|
BigDecimal allocateSource = rs.getBigDecimal(1);
|
||||||
|
BigDecimal allocateAccounted = rs.getBigDecimal(2);
|
||||||
|
BigDecimal allocateCredit = rs.getBigDecimal(3);
|
||||||
|
allocInvoiceSource =allocInvoiceSource.add(allocateSource != null ? allocateSource: BigDecimal.ZERO);
|
||||||
|
allocInvoiceAccounted =allocInvoiceAccounted.add(allocateAccounted != null ? allocateAccounted : BigDecimal.ZERO);
|
||||||
|
allocInvoiceAccounted= allocInvoiceAccounted.subtract(allocateCredit != null ? allocateCredit : BigDecimal.ZERO);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
throw new RuntimeException(e.getLocalizedMessage(), e);
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
DB.close(rs, pstmt);
|
||||||
|
rs = null; pstmt = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
double multiplier = allocInvoiceSource.doubleValue() / totalInvoiceSource.doubleValue();
|
||||||
|
|
||||||
|
// Reduce Orig Invoice Accounted
|
||||||
|
BigDecimal reduceOrigAccounted = totalInvoiceAccounted.multiply(BigDecimal.valueOf(multiplier));
|
||||||
|
if (reduceOrigAccounted.compareTo(totalInvoiceAccounted) < 0 )
|
||||||
|
totalInvoiceAccounted = reduceOrigAccounted;
|
||||||
|
if (isExcludeCMGainLoss)
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(cmGainLossAmt);
|
||||||
|
|
||||||
|
allocInvoiceAccounted = allocInvoiceAccounted.add(gainLossAmt);
|
||||||
|
|
||||||
|
// Difference based on percentage of Orig Invoice
|
||||||
|
acctDifference = allocInvoiceAccounted.subtract(totalInvoiceAccounted);
|
||||||
|
// ignore Tolerance
|
||||||
|
if (acctDifference.abs().compareTo(BigDecimal.valueOf(0.01)) < 0)
|
||||||
|
acctDifference = Env.ZERO;
|
||||||
|
|
||||||
|
// Round
|
||||||
|
int precision = as.getStdPrecision();
|
||||||
|
if (acctDifference.scale() > precision)
|
||||||
|
acctDifference = acctDifference.setScale(precision, RoundingMode.HALF_UP);
|
||||||
|
StringBuilder d2 = new StringBuilder("(partial) = ").append(acctDifference).append(" - Multiplier=").append(multiplier);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
|
description.append(" - ").append(d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acctDifference.signum() == 0)
|
||||||
|
{
|
||||||
|
log.fine("No Difference");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||||
|
//
|
||||||
|
if (acctDifference.abs().compareTo(TOLERANCE) <= 0)
|
||||||
|
{
|
||||||
|
if (invoice.isSOTrx())
|
||||||
|
{
|
||||||
|
FactLine fl = null;
|
||||||
|
if (!isBPartnerAdjust)
|
||||||
|
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference);
|
||||||
|
else
|
||||||
|
fl = fact.createLine (null, bpAcct,as.getC_Currency_ID(), acctDifference);
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
|
||||||
|
if (!fact.isAcctBalanced())
|
||||||
|
{
|
||||||
|
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID() )
|
||||||
|
{
|
||||||
|
fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
} else
|
||||||
|
{
|
||||||
|
fl = fact.createLine (null, loss, gain,as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}else
|
||||||
|
{
|
||||||
|
FactLine fl = null;
|
||||||
|
if (!isBPartnerAdjust)
|
||||||
|
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
else
|
||||||
|
fl = fact.createLine (null, bpAcct,as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
if (!fact.isAcctBalanced())
|
||||||
|
{
|
||||||
|
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID() )
|
||||||
|
{
|
||||||
|
fact.createLine (null, as.getCurrencyBalancing_Acct(),as.getC_Currency_ID(), acctDifference);
|
||||||
|
} else {
|
||||||
|
fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
|
||||||
|
} // createInvoiceRounding
|
||||||
|
|
||||||
} // Doc_Allocation
|
} // Doc_Allocation
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -24,6 +24,7 @@ import java.sql.Savepoint;
|
||||||
import java.sql.Timestamp;
|
import java.sql.Timestamp;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
@ -43,6 +44,7 @@ import org.compiere.model.MMatchInv;
|
||||||
import org.compiere.model.MOrderLandedCostAllocation;
|
import org.compiere.model.MOrderLandedCostAllocation;
|
||||||
import org.compiere.model.ProductCost;
|
import org.compiere.model.ProductCost;
|
||||||
import org.compiere.model.X_M_Cost;
|
import org.compiere.model.X_M_Cost;
|
||||||
|
import org.compiere.util.DB;
|
||||||
import org.compiere.util.Env;
|
import org.compiere.util.Env;
|
||||||
import org.compiere.util.Trx;
|
import org.compiere.util.Trx;
|
||||||
|
|
||||||
|
@ -286,6 +288,21 @@ public class Doc_MatchInv extends Doc
|
||||||
cr.setQty(getQty().multiply(multiplier).negate());
|
cr.setQty(getQty().multiply(multiplier).negate());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rounding correction
|
||||||
|
if (m_receiptLine != null && m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID()) // in foreign currency
|
||||||
|
{
|
||||||
|
p_Error = createReceiptGainLoss(as, fact, getAccount(Doc.ACCTTYPE_NotInvoicedReceipts, as), m_receiptLine.getParent(), dr.getAmtSourceDr(), dr.getAmtAcctDr());
|
||||||
|
if (p_Error != null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (m_invoiceLine != null && m_invoiceLine.getParent().getC_Currency_ID() != as.getC_Currency_ID()) // in foreign currency
|
||||||
|
{
|
||||||
|
p_Error = createInvoiceGainLoss(as, fact, expense, m_invoiceLine.getParent(), cr.getAmtSourceCr(), cr.getAmtAcctCr());
|
||||||
|
if (p_Error != null)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_matchInv.getReversal_ID() == 0)
|
if (m_matchInv.getReversal_ID() == 0)
|
||||||
{
|
{
|
||||||
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
cr.setC_Activity_ID(m_invoiceLine.getC_Activity_ID());
|
||||||
|
@ -831,4 +848,361 @@ public class Doc_MatchInv extends Doc
|
||||||
factLine.setM_Product_ID(m_invoiceLine.getM_Product_ID());
|
factLine.setM_Product_ID(m_invoiceLine.getM_Product_ID());
|
||||||
factLine.setQty(getQty());
|
factLine.setQty(getQty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String createInvoiceGainLoss(MAcctSchema as, Fact fact, MAccount acct,
|
||||||
|
MInvoice invoice, BigDecimal matchInvSource, BigDecimal matchInvAccounted)
|
||||||
|
{
|
||||||
|
BigDecimal invoiceSource = null;
|
||||||
|
BigDecimal invoiceAccounted = null;
|
||||||
|
//
|
||||||
|
StringBuilder sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID=?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID=?")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
|
||||||
|
// For Invoice
|
||||||
|
List<Object> valuesInv = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
|
||||||
|
MInvoice.Table_ID, invoice.getC_Invoice_ID(), as.getC_AcctSchema_ID(), acct.getAccount_ID());
|
||||||
|
if (valuesInv != null) {
|
||||||
|
invoiceSource = (BigDecimal) valuesInv.get(0); // AmtSourceDr
|
||||||
|
invoiceAccounted = (BigDecimal) valuesInv.get(1); // AmtAcctDr
|
||||||
|
if (invoiceSource.signum() == 0 && invoiceAccounted.signum() == 0) {
|
||||||
|
invoiceSource = (BigDecimal) valuesInv.get(2); // AmtSourceCr
|
||||||
|
invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires that Invoice is Posted
|
||||||
|
if (invoiceSource == null || invoiceAccounted == null)
|
||||||
|
return null;
|
||||||
|
//
|
||||||
|
|
||||||
|
if (m_matchInv.getReversal_ID() == 0 || m_matchInv.get_ID() < m_matchInv.getReversal_ID())
|
||||||
|
{
|
||||||
|
String matchInvLineSql = "SELECT M_MatchInv_ID FROM M_MatchInv "
|
||||||
|
+ "WHERE C_InvoiceLine_ID IN (SELECT C_InvoiceLine_ID FROM C_InvoiceLine WHERE C_Invoice_ID=?) "
|
||||||
|
+ "AND COALESCE(Reversal_ID,0)=0";
|
||||||
|
List<List<Object>> list = DB.getSQLArrayObjectsEx(getTrxName(), matchInvLineSql, invoice.get_ID());
|
||||||
|
StringBuffer s = new StringBuffer();
|
||||||
|
|
||||||
|
if (list == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (int index=0; index < list.size(); index++)
|
||||||
|
{
|
||||||
|
List<Object> l = list.get(index);
|
||||||
|
s.append(l.get(0));
|
||||||
|
if (index != list.size()-1)
|
||||||
|
s.append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID IN (").append(s).append(")")
|
||||||
|
.append(" AND Record_ID <> ?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID=?")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID IN (").append(m_matchInv.getReversal_ID()).append(")")
|
||||||
|
.append(" AND Record_ID <> ?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID=?")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal acctDifference = null; // gain is negative
|
||||||
|
// For Match Invoice
|
||||||
|
valuesInv = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
|
||||||
|
MMatchInv.Table_ID, get_ID(), as.getC_AcctSchema_ID(), acct.getAccount_ID());
|
||||||
|
if (valuesInv != null)
|
||||||
|
{
|
||||||
|
BigDecimal totalAmtSourceDr = (BigDecimal) valuesInv.get(0);
|
||||||
|
if (totalAmtSourceDr == null)
|
||||||
|
totalAmtSourceDr = Env.ZERO;
|
||||||
|
BigDecimal totalAmtAcctDr = (BigDecimal) valuesInv.get(1);
|
||||||
|
if (totalAmtAcctDr == null)
|
||||||
|
totalAmtAcctDr = Env.ZERO;
|
||||||
|
BigDecimal totalAmtSourceCr = (BigDecimal) valuesInv.get(2);
|
||||||
|
if (totalAmtSourceCr == null)
|
||||||
|
totalAmtSourceCr = Env.ZERO;
|
||||||
|
BigDecimal totalAmtAcctCr = (BigDecimal) valuesInv.get(3);
|
||||||
|
if (totalAmtAcctCr == null)
|
||||||
|
totalAmtAcctCr = Env.ZERO;
|
||||||
|
|
||||||
|
if (totalAmtSourceDr.signum() == 0 && totalAmtAcctDr.signum() == 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceCr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr);
|
||||||
|
}
|
||||||
|
else if (totalAmtSourceCr.signum() == 0 && totalAmtAcctCr.signum() == 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceDr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceDr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
|
||||||
|
acctDifference = totalAmtAcctCr.negate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceCr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr);
|
||||||
|
acctDifference = totalAmtSourceDr.negate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder description = new StringBuilder("Invoice=(").append(invoice.getC_Currency_ID()).append(")").append(invoiceSource).append("/").append(invoiceAccounted)
|
||||||
|
.append(" - MatchInv=(").append(getC_Currency_ID()).append(")").append(matchInvSource).append("/").append(matchInvAccounted);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(description.toString());
|
||||||
|
//
|
||||||
|
|
||||||
|
// Full Payment in currency
|
||||||
|
if (acctDifference == null && matchInvSource.compareTo(invoiceSource) == 0)
|
||||||
|
{
|
||||||
|
acctDifference = matchInvAccounted.subtract(invoiceAccounted.abs()); // gain is negative
|
||||||
|
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
|
description.append(" - ").append(d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acctDifference == null || acctDifference.signum() == 0)
|
||||||
|
{
|
||||||
|
log.fine("No Difference");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||||
|
//
|
||||||
|
if (invoice.isSOTrx())
|
||||||
|
{
|
||||||
|
FactLine fl = fact.createLine (null, acct, as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
|
||||||
|
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID()) {
|
||||||
|
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(), as.getC_Currency_ID(), acctDifference);
|
||||||
|
} else {
|
||||||
|
fl = fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference);
|
||||||
|
}
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FactLine fl = fact.createLine (null, acct, as.getC_Currency_ID(), acctDifference);
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
|
||||||
|
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != invoice.getC_Currency_ID()) {
|
||||||
|
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(), as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
} else {
|
||||||
|
fl = fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
}
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} // createInvoiceGainLoss
|
||||||
|
|
||||||
|
private String createReceiptGainLoss(MAcctSchema as, Fact fact, MAccount acct,
|
||||||
|
MInOut receipt, BigDecimal matchInvSource, BigDecimal matchInvAccounted)
|
||||||
|
{
|
||||||
|
BigDecimal receiptSource = null;
|
||||||
|
BigDecimal receiptAccounted = null;
|
||||||
|
//
|
||||||
|
StringBuilder sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID=?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID=?")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
|
||||||
|
// For Receipt
|
||||||
|
List<Object> valuesInv = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
|
||||||
|
MInOut.Table_ID, receipt.getM_InOut_ID(), as.getC_AcctSchema_ID(), acct.getAccount_ID());
|
||||||
|
if (valuesInv != null) {
|
||||||
|
receiptSource = (BigDecimal) valuesInv.get(0); // AmtSourceDr
|
||||||
|
receiptAccounted = (BigDecimal) valuesInv.get(1); // AmtAcctDr
|
||||||
|
if (receiptSource.signum() == 0 && receiptAccounted.signum() == 0) {
|
||||||
|
receiptSource = (BigDecimal) valuesInv.get(2); // AmtSourceCr
|
||||||
|
receiptAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Requires that Receipt is Posted
|
||||||
|
if (receiptSource == null || receiptAccounted == null)
|
||||||
|
return null;
|
||||||
|
//
|
||||||
|
if (m_matchInv.getReversal_ID() == 0 || m_matchInv.get_ID() < m_matchInv.getReversal_ID())
|
||||||
|
{
|
||||||
|
String matchInvLineSql = "SELECT M_MatchInv_ID FROM M_MatchInv "
|
||||||
|
+ "WHERE M_InOutLine_ID IN (SELECT M_InOutLine_ID FROM M_InOutLine WHERE M_InOut_ID=?) "
|
||||||
|
+ "AND COALESCE(Reversal_ID,0)=0";
|
||||||
|
List<List<Object>> list = DB.getSQLArrayObjectsEx(getTrxName(), matchInvLineSql, receipt.get_ID());
|
||||||
|
StringBuffer s = new StringBuffer();
|
||||||
|
|
||||||
|
if (list == null)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
for (int index=0; index < list.size(); index++)
|
||||||
|
{
|
||||||
|
List<Object> l = list.get(index);
|
||||||
|
s.append(l.get(0));
|
||||||
|
if (index != list.size()-1)
|
||||||
|
s.append(",");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID IN (").append(s).append(")")
|
||||||
|
.append(" AND Record_ID <> ?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID=?")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sql = new StringBuilder()
|
||||||
|
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||||
|
.append(" FROM Fact_Acct ")
|
||||||
|
.append("WHERE AD_Table_ID=? AND Record_ID IN (").append(m_matchInv.getReversal_ID()).append(")")
|
||||||
|
.append(" AND Record_ID <> ?")
|
||||||
|
.append(" AND C_AcctSchema_ID=?")
|
||||||
|
.append(" AND Account_ID=?")
|
||||||
|
.append(" AND PostingType='A'");
|
||||||
|
}
|
||||||
|
|
||||||
|
BigDecimal acctDifference = null; // gain is negative
|
||||||
|
// For Match Invoice
|
||||||
|
valuesInv = DB.getSQLValueObjectsEx(getTrxName(), sql.toString(),
|
||||||
|
MMatchInv.Table_ID, get_ID(), as.getC_AcctSchema_ID(), acct.getAccount_ID());
|
||||||
|
if (valuesInv != null)
|
||||||
|
{
|
||||||
|
BigDecimal totalAmtSourceDr = (BigDecimal) valuesInv.get(0);
|
||||||
|
if (totalAmtSourceDr == null)
|
||||||
|
totalAmtSourceDr = Env.ZERO;
|
||||||
|
BigDecimal totalAmtAcctDr = (BigDecimal) valuesInv.get(1);
|
||||||
|
if (totalAmtAcctDr == null)
|
||||||
|
totalAmtAcctDr = Env.ZERO;
|
||||||
|
BigDecimal totalAmtSourceCr = (BigDecimal) valuesInv.get(2);
|
||||||
|
if (totalAmtSourceCr == null)
|
||||||
|
totalAmtSourceCr = Env.ZERO;
|
||||||
|
BigDecimal totalAmtAcctCr = (BigDecimal) valuesInv.get(3);
|
||||||
|
if (totalAmtAcctCr == null)
|
||||||
|
totalAmtAcctCr = Env.ZERO;
|
||||||
|
|
||||||
|
if (totalAmtSourceDr.signum() == 0 && totalAmtAcctDr.signum() == 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceCr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr);
|
||||||
|
}
|
||||||
|
else if (totalAmtSourceCr.signum() == 0 && totalAmtAcctCr.signum() == 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceDr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_matchInv.getReversal_ID() == 0 || m_matchInv.get_ID() < m_matchInv.getReversal_ID())
|
||||||
|
{
|
||||||
|
if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceDr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr).subtract(totalAmtAcctCr);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceCr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr).subtract(totalAmtAcctDr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (totalAmtAcctDr.compareTo(totalAmtAcctCr) > 0)
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceDr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctDr);
|
||||||
|
acctDifference = totalAmtAcctCr.negate();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
matchInvSource = matchInvSource.add(totalAmtSourceCr);
|
||||||
|
matchInvAccounted = matchInvAccounted.add(totalAmtAcctCr);
|
||||||
|
acctDifference = totalAmtAcctDr.negate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder description = new StringBuilder("InOut=(").append(m_invoiceLine.getParent().getC_Currency_ID()).append(")").append(receiptSource).append("/").append(receiptAccounted)
|
||||||
|
.append(" - MatchInv=(").append(getC_Currency_ID()).append(")").append(matchInvSource).append("/").append(matchInvAccounted);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(description.toString());
|
||||||
|
|
||||||
|
// Full Payment in currency
|
||||||
|
if (acctDifference == null && matchInvSource.compareTo(receiptSource) == 0)
|
||||||
|
{
|
||||||
|
acctDifference = matchInvAccounted.subtract(receiptAccounted.abs()); // gain is negative
|
||||||
|
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
|
||||||
|
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||||
|
description.append(" - ").append(d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (acctDifference == null || acctDifference.signum() == 0)
|
||||||
|
{
|
||||||
|
log.fine("No Difference");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||||
|
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||||
|
//
|
||||||
|
if (!receipt.isSOTrx())
|
||||||
|
{
|
||||||
|
FactLine fl = fact.createLine (null, acct, as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
|
||||||
|
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != m_invoiceLine.getParent().getC_Currency_ID()) {
|
||||||
|
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(), as.getC_Currency_ID(), acctDifference);
|
||||||
|
} else {
|
||||||
|
fl = fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference);
|
||||||
|
}
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FactLine fl = fact.createLine (null, acct, as.getC_Currency_ID(), acctDifference);
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
|
||||||
|
if (as.isCurrencyBalancing() && as.getC_Currency_ID() != m_invoiceLine.getParent().getC_Currency_ID()) {
|
||||||
|
fl = fact.createLine (null, as.getCurrencyBalancing_Acct(), as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
} else {
|
||||||
|
fl = fact.createLine (null, loss, gain, as.getC_Currency_ID(), acctDifference.negate());
|
||||||
|
}
|
||||||
|
fl.setDescription(description.toString());
|
||||||
|
updateFactLine(fl);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} // createReceiptGainLoss
|
||||||
} // Doc_MatchInv
|
} // Doc_MatchInv
|
||||||
|
|
|
@ -1124,6 +1124,8 @@ public final class FactLine extends X_Fact_Acct
|
||||||
if (MMovement.Table_ID == AD_Table_ID)
|
if (MMovement.Table_ID == AD_Table_ID)
|
||||||
sql.append(" AND M_Locator_ID=?");
|
sql.append(" AND M_Locator_ID=?");
|
||||||
// end MZ
|
// end MZ
|
||||||
|
sql.append(" ORDER BY Fact_Acct_ID ");
|
||||||
|
|
||||||
PreparedStatement pstmt = null;
|
PreparedStatement pstmt = null;
|
||||||
ResultSet rs = null;
|
ResultSet rs = null;
|
||||||
try
|
try
|
||||||
|
|
|
@ -104,7 +104,7 @@ public class GridTable extends AbstractTableModel
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -2741647620577906242L;
|
private static final long serialVersionUID = 817894725729408648L;
|
||||||
|
|
||||||
public static final String DATA_REFRESH_MESSAGE = "Refreshed";
|
public static final String DATA_REFRESH_MESSAGE = "Refreshed";
|
||||||
public static final String DATA_UPDATE_COPIED_MESSAGE = "UpdateCopied";
|
public static final String DATA_UPDATE_COPIED_MESSAGE = "UpdateCopied";
|
||||||
|
@ -3499,7 +3499,7 @@ public class GridTable extends AbstractTableModel
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -8735217685095696892L;
|
private static final long serialVersionUID = -6866671239509705988L;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct Loader
|
* Construct Loader
|
||||||
|
|
|
@ -726,10 +726,20 @@ public class MPayment extends X_C_Payment
|
||||||
if (newRecord
|
if (newRecord
|
||||||
|| is_ValueChanged("C_Charge_ID") || is_ValueChanged("C_Invoice_ID")
|
|| is_ValueChanged("C_Charge_ID") || is_ValueChanged("C_Invoice_ID")
|
||||||
|| is_ValueChanged("C_Order_ID") || is_ValueChanged("C_Project_ID"))
|
|| is_ValueChanged("C_Order_ID") || is_ValueChanged("C_Project_ID"))
|
||||||
|
{
|
||||||
|
if (getReversal_ID() > 0)
|
||||||
|
{
|
||||||
|
setIsPrepayment(getReversal().isPrepayment());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
setIsPrepayment (getC_Charge_ID() == 0
|
setIsPrepayment (getC_Charge_ID() == 0
|
||||||
&& getC_BPartner_ID() != 0
|
&& getC_BPartner_ID() != 0
|
||||||
&& (getC_Order_ID() != 0
|
&& (getC_Order_ID() != 0
|
||||||
|| (getC_Project_ID() != 0 && getC_Invoice_ID() == 0)));
|
|| (getC_Project_ID() != 0 && getC_Invoice_ID() == 0)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (isPrepayment())
|
if (isPrepayment())
|
||||||
{
|
{
|
||||||
if (newRecord
|
if (newRecord
|
||||||
|
|
|
@ -241,6 +241,19 @@ public class CLogger extends Logger
|
||||||
return true;
|
return true;
|
||||||
} // saveWarning
|
} // saveWarning
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get Warning message from stack
|
||||||
|
* @param defaultMsg default message (used when there are no warnings on stack)
|
||||||
|
* @return error message, or defaultMsg if there is not error message saved
|
||||||
|
* @see #retrieveError()
|
||||||
|
*/
|
||||||
|
public static String retrieveWarningString(String defaultMsg) {
|
||||||
|
ValueNamePair vp = retrieveWarning();
|
||||||
|
if (vp == null)
|
||||||
|
return defaultMsg;
|
||||||
|
return vp.getName();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Warning from Stack
|
* Get Warning from Stack
|
||||||
* @return AD_Message as Value and Message as String
|
* @return AD_Message as Value and Message as String
|
||||||
|
|
|
@ -1653,7 +1653,7 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
|
||||||
if (listPanel.isVisible()) {
|
if (listPanel.isVisible()) {
|
||||||
listPanel.refresh(gridTab);
|
listPanel.refresh(gridTab);
|
||||||
listPanel.scrollToCurrentRow();
|
listPanel.scrollToCurrentRow();
|
||||||
Clients.resize(listPanel.getListbox());
|
listPanel.getListbox().invalidate();
|
||||||
} else {
|
} else {
|
||||||
listPanel.deactivate();
|
listPanel.deactivate();
|
||||||
}
|
}
|
||||||
|
@ -1880,7 +1880,11 @@ DataStatusListener, IADTabpanel, IdSpace, IFieldEditorContainer
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (found) {
|
if (found) {
|
||||||
if (editor.isVisible() && editor.isReadWrite()) {
|
if (editor.isVisible() && editor.isReadWrite()
|
||||||
|
// note, no auto focus on next button - if interested in
|
||||||
|
// focusing next button must implement to check if the button
|
||||||
|
// is just showin in toolbar, just focus on window fields must be auto focused
|
||||||
|
&& ! (editor instanceof WButtonEditor)) {
|
||||||
focusToEditor(editor, false);
|
focusToEditor(editor, false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,10 +83,12 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
private static final long serialVersionUID = -9183846974546235806L;
|
private static final long serialVersionUID = 2945672260455902597L;
|
||||||
|
|
||||||
public static final String BTNPREFIX = "Btn";
|
public static final String BTNPREFIX = "Btn";
|
||||||
|
|
||||||
|
public static final String MNITMPREFIX = "Mnitm";
|
||||||
|
|
||||||
private static final CLogger log = CLogger.getCLogger(ADWindowToolbar.class);
|
private static final CLogger log = CLogger.getCLogger(ADWindowToolbar.class);
|
||||||
|
|
||||||
private ToolBarButton btnIgnore;
|
private ToolBarButton btnIgnore;
|
||||||
|
@ -274,7 +276,6 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
|
||||||
tooltipKey = null;
|
tooltipKey = null;
|
||||||
}
|
}
|
||||||
ToolBarButton btn = createButton(button.getComponentName(), null, tooltipKey);
|
ToolBarButton btn = createButton(button.getComponentName(), null, tooltipKey);
|
||||||
this.appendChild(btn);
|
|
||||||
btn.removeEventListener(Events.ON_CLICK, this);
|
btn.removeEventListener(Events.ON_CLICK, this);
|
||||||
btn.setId(button.getName());
|
btn.setId(button.getName());
|
||||||
btn.setDisabled(false);
|
btn.setDisabled(false);
|
||||||
|
@ -291,9 +292,7 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
|
||||||
|
|
||||||
if (ClientInfo.isMobile() && button.isShowMore())
|
if (ClientInfo.isMobile() && button.isShowMore())
|
||||||
mobileShowMoreButtons.add(btn);
|
mobileShowMoreButtons.add(btn);
|
||||||
else if (button.isShowMore())
|
else if (!button.isShowMore()) {
|
||||||
createMenuitem(btn);
|
|
||||||
else {
|
|
||||||
this.appendChild(btn);
|
this.appendChild(btn);
|
||||||
action.decorate(btn);
|
action.decorate(btn);
|
||||||
}
|
}
|
||||||
|
@ -371,12 +370,15 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
|
||||||
Menuitem item = new Menuitem(button.getTooltiptext());
|
Menuitem item = new Menuitem(button.getTooltiptext());
|
||||||
if (button.getImage() != null)
|
if (button.getImage() != null)
|
||||||
item.setImage(button.getImage());
|
item.setImage(button.getImage());
|
||||||
|
else if (button.getImageContent() != null)
|
||||||
|
item.setImageContent(button.getImageContent());
|
||||||
else if (ThemeManager.isUseFontIconForImage()) {
|
else if (ThemeManager.isUseFontIconForImage()) {
|
||||||
item.setIconSclass(button.getIconSclass());
|
item.setIconSclass(button.getIconSclass());
|
||||||
LayoutUtils.addSclass("font-icon-toolbar-button", item);
|
LayoutUtils.addSclass("font-icon-toolbar-button", item);
|
||||||
}
|
}
|
||||||
|
item.setId(MNITMPREFIX+button.getName());
|
||||||
item.setValue(button.getName());
|
item.setValue(button.getName());
|
||||||
item.addEventListener(Events.ON_CLICK, evt -> doOnClick(new Event(Events.ON_CLICK, button)));
|
item.addEventListener(Events.ON_CLICK, evt -> Events.sendEvent(new Event(Events.ON_CLICK, button)));
|
||||||
menupopup.appendChild(item);
|
menupopup.appendChild(item);
|
||||||
menuItems.put(button, item);
|
menuItems.put(button, item);
|
||||||
return item;
|
return item;
|
||||||
|
@ -905,8 +907,10 @@ public class ADWindowToolbar extends FToolbar implements EventListener<Event>
|
||||||
public void dynamicDisplay() {
|
public void dynamicDisplay() {
|
||||||
List<Toolbarbutton> customButtons = new ArrayList<Toolbarbutton>();
|
List<Toolbarbutton> customButtons = new ArrayList<Toolbarbutton>();
|
||||||
for(ToolbarCustomButton toolbarCustomBtn : toolbarCustomButtons) {
|
for(ToolbarCustomButton toolbarCustomBtn : toolbarCustomButtons) {
|
||||||
toolbarCustomBtn.dynamicDisplay();
|
toolbarCustomBtn.dynamicDisplay(menuItems.get(toolbarCustomBtn.getToolbarbutton()) != null);
|
||||||
customButtons.add(toolbarCustomBtn.getToolbarbutton());
|
customButtons.add(toolbarCustomBtn.getToolbarbutton());
|
||||||
|
if (menuItems.get(toolbarCustomBtn.getToolbarbutton()) != null)
|
||||||
|
menuItems.get(toolbarCustomBtn.getToolbarbutton()).setVisible(toolbarCustomBtn.getToolbarbutton().isVisible());
|
||||||
}
|
}
|
||||||
|
|
||||||
ADWindow adwindow = ADWindow.findADWindow(this);
|
ADWindow adwindow = ADWindow.findADWindow(this);
|
||||||
|
|
|
@ -2017,8 +2017,11 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
||||||
|
|
||||||
clearTitleRelatedContext();
|
clearTitleRelatedContext();
|
||||||
|
|
||||||
|
// The record was not changed locally
|
||||||
|
if (adTabbox.getDirtyADTabpanel() == null) {
|
||||||
|
doOnFind();
|
||||||
|
} else {
|
||||||
onSave(false, false, new Callback<Boolean>() {
|
onSave(false, false, new Callback<Boolean>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCallback(Boolean result) {
|
public void onCallback(Boolean result) {
|
||||||
if (result) {
|
if (result) {
|
||||||
|
@ -2027,6 +2030,7 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void doOnFind() {
|
private void doOnFind() {
|
||||||
// Gets Fields from AD_Field_v
|
// Gets Fields from AD_Field_v
|
||||||
|
@ -2156,12 +2160,16 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
||||||
if (dirtyTabpanel != null) {
|
if (dirtyTabpanel != null) {
|
||||||
focusToTabpanel(dirtyTabpanel);
|
focusToTabpanel(dirtyTabpanel);
|
||||||
//ensure row indicator is not lost
|
//ensure row indicator is not lost
|
||||||
|
if (dirtyTabpanel.getGridView() != null &&
|
||||||
|
dirtyTabpanel.getGridView().getListbox() != null &&
|
||||||
|
dirtyTabpanel.getGridView().getListbox().getRowRenderer() != null) {
|
||||||
RowRenderer<Object[]> renderer = dirtyTabpanel.getGridView().getListbox().getRowRenderer();
|
RowRenderer<Object[]> renderer = dirtyTabpanel.getGridView().getListbox().getRowRenderer();
|
||||||
GridTabRowRenderer gtr = (GridTabRowRenderer)renderer;
|
GridTabRowRenderer gtr = (GridTabRowRenderer)renderer;
|
||||||
org.zkoss.zul.Row row = gtr.getCurrentRow();
|
org.zkoss.zul.Row row = gtr.getCurrentRow();
|
||||||
if (row != null)
|
if (row != null)
|
||||||
gtr.setCurrentRow(row);
|
gtr.setCurrentRow(row);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
focusToActivePanel();
|
focusToActivePanel();
|
||||||
|
|
||||||
|
@ -2379,6 +2387,14 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
||||||
//other error will be catch in the dataStatusChanged event
|
//other error will be catch in the dataStatusChanged event
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void showLastWarning() {
|
||||||
|
String msg = CLogger.retrieveWarningString(null);
|
||||||
|
if (msg != null)
|
||||||
|
{
|
||||||
|
statusBar.setStatusLine(Msg.getMsg(Env.getCtx(), msg), true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see ToolbarListener#onSaveCreate()
|
* @see ToolbarListener#onSaveCreate()
|
||||||
*/
|
*/
|
||||||
|
@ -2458,9 +2474,11 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
|
||||||
if (result)
|
if (result)
|
||||||
{
|
{
|
||||||
//error will be catch in the dataStatusChanged event
|
//error will be catch in the dataStatusChanged event
|
||||||
adTabbox.getSelectedGridTab().dataDelete();
|
boolean success = adTabbox.getSelectedGridTab().dataDelete();
|
||||||
adTabbox.getSelectedGridTab().dataRefreshAll(true, true);
|
adTabbox.getSelectedGridTab().dataRefreshAll(true, true);
|
||||||
adTabbox.getSelectedGridTab().refreshParentTabs();
|
adTabbox.getSelectedGridTab().refreshParentTabs();
|
||||||
|
if (!success)
|
||||||
|
showLastWarning();
|
||||||
|
|
||||||
adTabbox.getSelectedTabpanel().dynamicDisplay(0);
|
adTabbox.getSelectedTabpanel().dynamicDisplay(0);
|
||||||
focusToActivePanel();
|
focusToActivePanel();
|
||||||
|
|
|
@ -356,7 +356,7 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
|
||||||
showRecordsCount();
|
showRecordsCount();
|
||||||
}
|
}
|
||||||
if (this.isVisible())
|
if (this.isVisible())
|
||||||
Clients.resize(listbox);
|
listbox.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -729,7 +729,7 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
|
||||||
listModel.setPage(pgNo);
|
listModel.setPage(pgNo);
|
||||||
onSelectedRowChange(0);
|
onSelectedRowChange(0);
|
||||||
gridTab.clearSelection();
|
gridTab.clearSelection();
|
||||||
Clients.resize(listbox);
|
listbox.invalidate();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (event.getTarget() == selectAll)
|
else if (event.getTarget() == selectAll)
|
||||||
|
@ -1121,7 +1121,7 @@ public class GridView extends Vlayout implements EventListener<Event>, IdSpace,
|
||||||
|
|
||||||
refresh(gridTab);
|
refresh(gridTab);
|
||||||
scrollToCurrentRow();
|
scrollToCurrentRow();
|
||||||
Clients.resize(listbox);
|
listbox.invalidate();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -70,7 +70,11 @@ public class ToolbarCustomButton implements EventListener<Event>, Evaluatee {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dynamicDisplay() {
|
public void dynamicDisplay() {
|
||||||
if (toolbarButton.getParent() == null)
|
dynamicDisplay(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void dynamicDisplay(boolean forceValidation) {
|
||||||
|
if (toolbarButton.getParent() == null && !forceValidation)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
String displayLogic = mToolbarButton.getDisplayLogic();
|
String displayLogic = mToolbarButton.getDisplayLogic();
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Properties;
|
||||||
import org.adempiere.webui.AdempiereWebUI;
|
import org.adempiere.webui.AdempiereWebUI;
|
||||||
import org.adempiere.webui.ClientInfo;
|
import org.adempiere.webui.ClientInfo;
|
||||||
import org.adempiere.webui.LayoutUtils;
|
import org.adempiere.webui.LayoutUtils;
|
||||||
|
import org.adempiere.webui.adwindow.IFieldEditorContainer;
|
||||||
import org.adempiere.webui.component.Bandbox;
|
import org.adempiere.webui.component.Bandbox;
|
||||||
import org.adempiere.webui.component.Button;
|
import org.adempiere.webui.component.Button;
|
||||||
import org.adempiere.webui.component.Datebox;
|
import org.adempiere.webui.component.Datebox;
|
||||||
|
@ -813,6 +814,18 @@ public abstract class WEditor implements EventListener<Event>, PropertyChangeLis
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected void focusNext() {
|
||||||
|
Component comp = getComponent();
|
||||||
|
Component parent = comp.getParent();
|
||||||
|
while (parent != null) {
|
||||||
|
if (parent instanceof IFieldEditorContainer) {
|
||||||
|
((IFieldEditorContainer) parent).focusToNextEditor(this);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
parent = parent.getParent();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected Evaluatee getStyleEvaluatee() {
|
protected Evaluatee getStyleEvaluatee() {
|
||||||
return new EvaluateeWrapper(this, gridField, tableEditor);
|
return new EvaluateeWrapper(this, gridField, tableEditor);
|
||||||
}
|
}
|
||||||
|
|
|
@ -278,6 +278,8 @@ public class WPaymentEditor extends WEditor implements ListDataListener, Context
|
||||||
super.fireValueChange(changeEvent);
|
super.fireValueChange(changeEvent);
|
||||||
oldValue = newValue;
|
oldValue = newValue;
|
||||||
}
|
}
|
||||||
|
if (newValue != null)
|
||||||
|
focusNext();
|
||||||
}
|
}
|
||||||
else if (Events.ON_BLUR.equalsIgnoreCase(event.getName()))
|
else if (Events.ON_BLUR.equalsIgnoreCase(event.getName()))
|
||||||
{
|
{
|
||||||
|
|
|
@ -29,7 +29,6 @@ import org.adempiere.webui.LayoutUtils;
|
||||||
import org.adempiere.webui.ValuePreference;
|
import org.adempiere.webui.ValuePreference;
|
||||||
import org.adempiere.webui.adwindow.ADWindow;
|
import org.adempiere.webui.adwindow.ADWindow;
|
||||||
import org.adempiere.webui.adwindow.ADWindowContent;
|
import org.adempiere.webui.adwindow.ADWindowContent;
|
||||||
import org.adempiere.webui.adwindow.IFieldEditorContainer;
|
|
||||||
import org.adempiere.webui.apps.AEnv;
|
import org.adempiere.webui.apps.AEnv;
|
||||||
import org.adempiere.webui.component.Searchbox;
|
import org.adempiere.webui.component.Searchbox;
|
||||||
import org.adempiere.webui.event.ContextMenuEvent;
|
import org.adempiere.webui.event.ContextMenuEvent;
|
||||||
|
@ -390,16 +389,7 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value
|
||||||
log.fine(getColumnName() + " - Unique ID=" + id);
|
log.fine(getColumnName() + " - Unique ID=" + id);
|
||||||
|
|
||||||
actionCombo(Integer.valueOf(id)); // data binding
|
actionCombo(Integer.valueOf(id)); // data binding
|
||||||
|
focusNext();
|
||||||
Searchbox comp = getComponent();
|
|
||||||
Component parent = comp.getParent();
|
|
||||||
while (parent != null) {
|
|
||||||
if (parent instanceof IFieldEditorContainer) {
|
|
||||||
((IFieldEditorContainer) parent).focusToNextEditor(this);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
parent = parent.getParent();
|
|
||||||
}
|
|
||||||
|
|
||||||
//safety check: if focus is going no where, focus back to self
|
//safety check: if focus is going no where, focus back to self
|
||||||
String uid = getComponent().getTextbox().getUuid();
|
String uid = getComponent().getTextbox().getUuid();
|
||||||
|
@ -599,6 +589,7 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value
|
||||||
actionCombo (result);
|
actionCombo (result);
|
||||||
else
|
else
|
||||||
actionCombo (result[0]);
|
actionCombo (result[0]);
|
||||||
|
focusNext();
|
||||||
}
|
}
|
||||||
else if (cancelled)
|
else if (cancelled)
|
||||||
{
|
{
|
||||||
|
@ -613,13 +604,14 @@ public class WSearchEditor extends WEditor implements ContextMenuListener, Value
|
||||||
getComponent().setText("");
|
getComponent().setText("");
|
||||||
actionCombo(null);
|
actionCombo(null);
|
||||||
}
|
}
|
||||||
|
getComponent().getTextbox().focus();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (log.isLoggable(Level.CONFIG)) log.config(getColumnName() + " - Result = null (not cancelled)");
|
if (log.isLoggable(Level.CONFIG)) log.config(getColumnName() + " - Result = null (not cancelled)");
|
||||||
}
|
|
||||||
getComponent().getTextbox().focus();
|
getComponent().getTextbox().focus();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
ip.setId(ip.getTitle()+"_"+ip.getWindowNo());
|
ip.setId(ip.getTitle()+"_"+ip.getWindowNo());
|
||||||
AEnv.showWindow(ip);
|
AEnv.showWindow(ip);
|
||||||
|
|
|
@ -507,6 +507,8 @@ ContextMenuListener, IZoomableEditor
|
||||||
gridField.setLookupEditorSettingValue(false);
|
gridField.setLookupEditorSettingValue(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (newValue != null)
|
||||||
|
focusNext();
|
||||||
} finally {
|
} finally {
|
||||||
onselecting = false;
|
onselecting = false;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue