Merge release-7.1 into master

This commit is contained in:
Carlos Ruiz 2020-02-13 01:00:46 +01:00
commit 15707d9aac
17 changed files with 1043 additions and 207 deletions

View File

@ -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
;

View File

@ -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
;

View File

@ -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,14 +445,31 @@ 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) if (p_Error != null)
return null; return null;
} }
totalAllocationSource = totalAllocationSource.add(line.getAmtSource());
lineID = line.get_ID();
} // for all lines } // 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)
return null;
}
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)) {
boolean allEquals = true; boolean allEquals = true;
@ -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); fl.setDescription(description.toString());
StringBuilder description = new StringBuilder(descriptionInv); fl = fact.createLine (line, acct, as.getC_Currency_ID(), acctDifference.negate());
if (paymentDifference.signum() != 0 && descriptionPay != null) { gainLossFactList.add(fl);
description.append(" / ").append(descriptionPay);
}
fl.setDescription(description.toString());
fl.setAD_Org_ID(invoice.getAD_Org_ID());
}
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) { fl.setDescription(description.toString());
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.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
/** /**

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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"))
setIsPrepayment (getC_Charge_ID() == 0 {
&& getC_BPartner_ID() != 0 if (getReversal_ID() > 0)
&& (getC_Order_ID() != 0 {
|| (getC_Project_ID() != 0 && getC_Invoice_ID() == 0))); setIsPrepayment(getReversal().isPrepayment());
}
else
{
setIsPrepayment (getC_Charge_ID() == 0
&& getC_BPartner_ID() != 0
&& (getC_Order_ID() != 0
|| (getC_Project_ID() != 0 && getC_Invoice_ID() == 0)));
}
}
if (isPrepayment()) if (isPrepayment())
{ {
if (newRecord if (newRecord

View File

@ -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

View File

@ -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;
} }

View File

@ -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);

View File

@ -2017,15 +2017,19 @@ public abstract class AbstractADWindowContent extends AbstractUIPart implements
clearTitleRelatedContext(); clearTitleRelatedContext();
onSave(false, false, new Callback<Boolean>() { // The record was not changed locally
if (adTabbox.getDirtyADTabpanel() == null) {
@Override doOnFind();
public void onCallback(Boolean result) { } else {
if (result) { onSave(false, false, new Callback<Boolean>() {
doOnFind(); @Override
} public void onCallback(Boolean result) {
} if (result) {
}); doOnFind();
}
}
});
}
} }
private void doOnFind() { private void doOnFind() {
@ -2156,11 +2160,15 @@ 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
RowRenderer<Object[]> renderer = dirtyTabpanel.getGridView().getListbox().getRowRenderer(); if (dirtyTabpanel.getGridView() != null &&
GridTabRowRenderer gtr = (GridTabRowRenderer)renderer; dirtyTabpanel.getGridView().getListbox() != null &&
org.zkoss.zul.Row row = gtr.getCurrentRow(); dirtyTabpanel.getGridView().getListbox().getRowRenderer() != null) {
if (row != null) RowRenderer<Object[]> renderer = dirtyTabpanel.getGridView().getListbox().getRowRenderer();
gtr.setCurrentRow(row); GridTabRowRenderer gtr = (GridTabRowRenderer)renderer;
org.zkoss.zul.Row row = gtr.getCurrentRow();
if (row != null)
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();

View File

@ -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();
} }
/** /**

View File

@ -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();

View File

@ -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);
} }

View File

@ -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()))
{ {

View File

@ -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,12 +604,13 @@ 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());

View File

@ -507,6 +507,8 @@ ContextMenuListener, IZoomableEditor
gridField.setLookupEditorSettingValue(false); gridField.setLookupEditorSettingValue(false);
} }
} }
if (newValue != null)
focusNext();
} finally { } finally {
onselecting = false; onselecting = false;
} }