hg merge release-5.1 (merge release5.1 into default)
This commit is contained in:
commit
ac0b824eee
|
@ -0,0 +1,15 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-3757
|
||||
-- Jul 24, 2018 9:30:27 AM CEST
|
||||
UPDATE AD_Table SET AccessLevel='4',Updated=TO_DATE('2018-07-24 09:30:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Table_ID=116
|
||||
;
|
||||
|
||||
DELETE FROM ad_window_access WHERE ad_window_id=105
|
||||
AND ad_role_id IN (SELECT ad_role_id FROM ad_role WHERE ismanual='N' AND userlevel NOT LIKE 'S%')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201807240936_IDEMPIERE-3757.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,14 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-3762 : Fix AD_Column_ID / AD_Field_ID : Loader - Too many records
|
||||
-- Jul 26, 2018 10:06:34 AM CEST
|
||||
UPDATE AD_Field SET AD_Reference_ID=30,Updated=TO_DATE('2018-07-26 10:06:34','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=0 WHERE AD_Field_ID=4599
|
||||
;
|
||||
|
||||
-- Jul 26, 2018 10:06:42 AM CEST
|
||||
UPDATE AD_Field SET AD_Reference_ID=30,Updated=TO_DATE('2018-07-26 10:06:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=0 WHERE AD_Field_ID=59576
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201807271000_IDEMPIERE-3762.sql') FROM dual
|
||||
;
|
|
@ -0,0 +1,10 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-3769 : IBAN : Invalid message is not translated - force to uppercase
|
||||
-- Aug 1, 2018 8:56:43 AM CEST
|
||||
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','IBAN is invalid',0,0,'Y',TO_DATE('2018-08-01 08:56:42','YYYY-MM-DD HH24:MI:SS'),0,TO_DATE('2018-08-01 08:56:42','YYYY-MM-DD HH24:MI:SS'),0,200480,'InvalidIBAN','D','4cc792d9-9af0-4e37-b90a-7dcc9f5e82ec')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201808010900_IDEMPIERE-3769.sql') FROM dual
|
||||
;
|
|
@ -0,0 +1,31 @@
|
|||
SET SQLBLANKLINES ON
|
||||
SET DEFINE OFF
|
||||
|
||||
-- IDEMPIERE-2442 Always using default conversion type in Order & Invoice window's amount summary information
|
||||
-- Aug 7, 2018 12:22:32 PM CEST
|
||||
UPDATE AD_StatusLine SET SQLStatement='SELECT COUNT(DISTINCT C_OrderLine_ID) AS Lines,o.TotalLines,o.GrandTotal,c.ISO_Code,
|
||||
currencyConvert(o.GrandTotal,o.C_Currency_ID,ac.C_Currency_ID,o.DateAcct,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) AS ConvAmt
|
||||
FROM C_Order o
|
||||
INNER JOIN C_Currency c ON (o.C_Currency_ID=c.C_Currency_ID)
|
||||
LEFT JOIN C_OrderLine l ON (o.C_Order_ID=l.C_Order_ID)
|
||||
LEFT JOIN AD_ClientInfo ci ON (ci.AD_Client_ID=o.AD_Client_ID)
|
||||
LEFT JOIN C_AcctSchema ac ON (ci.C_AcctSchema1_ID=ac.C_AcctSchema_ID)
|
||||
WHERE o.C_Order_ID=@C_Order_ID@
|
||||
GROUP BY o.C_Currency_ID, ac.C_Currency_ID, o.C_ConversionType_ID, c.ISO_Code, o.TotalLines, o.GrandTotal, o.DateAcct, o.AD_Client_ID, o.AD_Org_ID',Updated=TO_DATE('2018-08-07 12:22:32','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_StatusLine_ID=200000
|
||||
;
|
||||
|
||||
-- Aug 7, 2018 12:25:27 PM CEST
|
||||
UPDATE AD_StatusLine SET SQLStatement='SELECT COUNT(DISTINCT C_InvoiceLine_ID) AS Lines,o.TotalLines,o.GrandTotal,c.ISO_Code,
|
||||
currencyConvert(o.GrandTotal,o.C_Currency_ID,ac.C_Currency_ID,o.DateAcct,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) AS ConvAmt
|
||||
FROM C_Invoice o
|
||||
INNER JOIN C_Currency c ON (o.C_Currency_ID=c.C_Currency_ID)
|
||||
LEFT JOIN C_InvoiceLine l ON (o.C_Invoice_ID=l.C_Invoice_ID)
|
||||
LEFT JOIN AD_ClientInfo ci ON (ci.AD_Client_ID=o.AD_Client_ID)
|
||||
LEFT JOIN C_AcctSchema ac ON (ci.C_AcctSchema1_ID=ac.C_AcctSchema_ID)
|
||||
WHERE o.C_Invoice_ID=@C_Invoice_ID@
|
||||
GROUP BY o.C_Currency_ID, ac.C_Currency_ID, o.C_ConversionType_ID, c.ISO_Code, o.TotalLines, o.GrandTotal, o.DateAcct, o.AD_Client_ID, o.AD_Org_ID',Updated=TO_DATE('2018-08-07 12:25:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_StatusLine_ID=200002
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201808071226_IDEMPIERE-2442.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
-- IDEMPIERE-3757
|
||||
-- Jul 24, 2018 9:30:27 AM CEST
|
||||
UPDATE AD_Table SET AccessLevel='4',Updated=TO_TIMESTAMP('2018-07-24 09:30:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_Table_ID=116
|
||||
;
|
||||
|
||||
DELETE FROM ad_window_access WHERE ad_window_id=105
|
||||
AND ad_role_id IN (SELECT ad_role_id FROM ad_role WHERE ismanual='N' AND userlevel NOT LIKE 'S%')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201807240936_IDEMPIERE-3757.sql') FROM dual
|
||||
;
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
-- IDEMPIERE-3762 : Fix AD_Column_ID / AD_Field_ID : Loader - Too many records
|
||||
-- Jul 26, 2018 10:06:34 AM CEST
|
||||
UPDATE AD_Field SET AD_Reference_ID=30,Updated=TO_TIMESTAMP('2018-07-26 10:06:34','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=0 WHERE AD_Field_ID=4599
|
||||
;
|
||||
|
||||
-- Jul 26, 2018 10:06:42 AM CEST
|
||||
UPDATE AD_Field SET AD_Reference_ID=30,Updated=TO_TIMESTAMP('2018-07-26 10:06:42','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=0 WHERE AD_Field_ID=59576
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201807271000_IDEMPIERE-3762.sql') FROM dual
|
||||
;
|
|
@ -0,0 +1,7 @@
|
|||
-- IDEMPIERE-3769 : IBAN : Invalid message is not translated - force to uppercase
|
||||
-- Aug 1, 2018 8:56:43 AM CEST
|
||||
INSERT INTO AD_Message (MsgType,MsgText,AD_Client_ID,AD_Org_ID,IsActive,Created,CreatedBy,Updated,UpdatedBy,AD_Message_ID,Value,EntityType,AD_Message_UU) VALUES ('I','IBAN is invalid',0,0,'Y',TO_TIMESTAMP('2018-08-01 08:56:42','YYYY-MM-DD HH24:MI:SS'),0,TO_TIMESTAMP('2018-08-01 08:56:42','YYYY-MM-DD HH24:MI:SS'),0,200480,'InvalidIBAN','D','4cc792d9-9af0-4e37-b90a-7dcc9f5e82ec')
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201808010900_IDEMPIERE-3769.sql') FROM dual
|
||||
;
|
|
@ -0,0 +1,28 @@
|
|||
-- IDEMPIERE-2442 Always using default conversion type in Order & Invoice window's amount summary information
|
||||
-- Aug 7, 2018 12:22:32 PM CEST
|
||||
UPDATE AD_StatusLine SET SQLStatement='SELECT COUNT(DISTINCT C_OrderLine_ID) AS Lines,o.TotalLines,o.GrandTotal,c.ISO_Code,
|
||||
currencyConvert(o.GrandTotal,o.C_Currency_ID,ac.C_Currency_ID,o.DateAcct,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) AS ConvAmt
|
||||
FROM C_Order o
|
||||
INNER JOIN C_Currency c ON (o.C_Currency_ID=c.C_Currency_ID)
|
||||
LEFT JOIN C_OrderLine l ON (o.C_Order_ID=l.C_Order_ID)
|
||||
LEFT JOIN AD_ClientInfo ci ON (ci.AD_Client_ID=o.AD_Client_ID)
|
||||
LEFT JOIN C_AcctSchema ac ON (ci.C_AcctSchema1_ID=ac.C_AcctSchema_ID)
|
||||
WHERE o.C_Order_ID=@C_Order_ID@
|
||||
GROUP BY o.C_Currency_ID, ac.C_Currency_ID, o.C_ConversionType_ID, c.ISO_Code, o.TotalLines, o.GrandTotal, o.DateAcct, o.AD_Client_ID, o.AD_Org_ID',Updated=TO_TIMESTAMP('2018-08-07 12:22:32','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_StatusLine_ID=200000
|
||||
;
|
||||
|
||||
-- Aug 7, 2018 12:25:27 PM CEST
|
||||
UPDATE AD_StatusLine SET SQLStatement='SELECT COUNT(DISTINCT C_InvoiceLine_ID) AS Lines,o.TotalLines,o.GrandTotal,c.ISO_Code,
|
||||
currencyConvert(o.GrandTotal,o.C_Currency_ID,ac.C_Currency_ID,o.DateAcct,o.C_ConversionType_ID,o.AD_Client_ID,o.AD_Org_ID) AS ConvAmt
|
||||
FROM C_Invoice o
|
||||
INNER JOIN C_Currency c ON (o.C_Currency_ID=c.C_Currency_ID)
|
||||
LEFT JOIN C_InvoiceLine l ON (o.C_Invoice_ID=l.C_Invoice_ID)
|
||||
LEFT JOIN AD_ClientInfo ci ON (ci.AD_Client_ID=o.AD_Client_ID)
|
||||
LEFT JOIN C_AcctSchema ac ON (ci.C_AcctSchema1_ID=ac.C_AcctSchema_ID)
|
||||
WHERE o.C_Invoice_ID=@C_Invoice_ID@
|
||||
GROUP BY o.C_Currency_ID, ac.C_Currency_ID, o.C_ConversionType_ID, c.ISO_Code, o.TotalLines, o.GrandTotal, o.DateAcct, o.AD_Client_ID, o.AD_Org_ID',Updated=TO_TIMESTAMP('2018-08-07 12:25:27','YYYY-MM-DD HH24:MI:SS'),UpdatedBy=100 WHERE AD_StatusLine_ID=200002
|
||||
;
|
||||
|
||||
SELECT register_migration_script('201808071226_IDEMPIERE-2442.sql') FROM dual
|
||||
;
|
||||
|
|
@ -453,8 +453,6 @@ public class CalloutOrder extends CalloutEngine
|
|||
*/
|
||||
public String bPartnerBill (Properties ctx, int WindowNo, GridTab mTab, GridField mField, Object value)
|
||||
{
|
||||
if (isCalloutActive())
|
||||
return "";
|
||||
Integer bill_BPartner_ID = (Integer)value;
|
||||
if (bill_BPartner_ID == null || bill_BPartner_ID.intValue() == 0)
|
||||
return "";
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.compiere.model.MBPartner;
|
|||
import org.compiere.model.MDocType;
|
||||
import org.compiere.model.MInvoice;
|
||||
import org.compiere.model.MInvoiceLine;
|
||||
import org.compiere.model.MPriceList;
|
||||
import org.compiere.model.MTimeExpense;
|
||||
import org.compiere.model.MTimeExpenseLine;
|
||||
import org.compiere.util.DB;
|
||||
|
@ -136,6 +137,10 @@ public class ExpenseAPInvoice extends SvrProcess
|
|||
break;
|
||||
}
|
||||
invoice.setM_PriceList_ID(te.getM_PriceList_ID());
|
||||
|
||||
MPriceList pl = MPriceList.get(getCtx(), te.getM_PriceList_ID(), get_TrxName());
|
||||
invoice.setIsTaxIncluded(pl.isTaxIncluded());
|
||||
|
||||
invoice.setSalesRep_ID(te.getDoc_User_ID());
|
||||
StringBuilder descr = new StringBuilder().append(Msg.translate(getCtx(), "S_TimeExpense_ID"))
|
||||
.append(": ").append(te.getDocumentNo()).append(" " )
|
||||
|
@ -182,6 +187,7 @@ public class ExpenseAPInvoice extends SvrProcess
|
|||
//
|
||||
// il.setPrice(); // not really a list/limit price for reimbursements
|
||||
il.setPrice(line.getPriceReimbursed()); //
|
||||
|
||||
il.setTax();
|
||||
if (!il.save())
|
||||
throw new IllegalStateException("Cannot save Invoice Line");
|
||||
|
|
|
@ -19,7 +19,8 @@ package org.compiere.acct;
|
|||
import java.math.BigDecimal;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.model.MAccount;
|
||||
|
@ -28,7 +29,8 @@ import org.compiere.model.MAcctSchemaElement;
|
|||
import org.compiere.model.MAllocationHdr;
|
||||
import org.compiere.model.MAllocationLine;
|
||||
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.MInvoice;
|
||||
import org.compiere.model.MInvoiceLine;
|
||||
|
@ -197,6 +199,7 @@ public class Doc_AllocationHdr extends Doc
|
|||
FactLine fl = null;
|
||||
FactLine flForRGL = null;
|
||||
MAccount bpAcct = null; // Liability/Receivables
|
||||
MAccount payAcct = null; // Payment Selection
|
||||
//
|
||||
MPayment payment = null;
|
||||
if (line.getC_Payment_ID() != 0)
|
||||
|
@ -258,8 +261,9 @@ public class Doc_AllocationHdr extends Doc
|
|||
|
||||
// Payment/Cash DR
|
||||
if (line.getC_Payment_ID() != 0)
|
||||
{
|
||||
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
|
||||
{
|
||||
payAcct = getPaymentAcct(as, line.getC_Payment_ID());
|
||||
fl = fact.createLine (line, payAcct,
|
||||
getC_Currency_ID(), line.getAmtSource(), null);
|
||||
if (fl != null && payment != null)
|
||||
fl.setAD_Org_ID(payment.getAD_Org_ID());
|
||||
|
@ -388,8 +392,9 @@ public class Doc_AllocationHdr extends Doc
|
|||
}
|
||||
// Payment/Cash CR
|
||||
if (isUsingClearing && line.getC_Payment_ID() != 0) // Avoid usage of clearing accounts
|
||||
{
|
||||
fl = fact.createLine (line, getPaymentAcct(as, line.getC_Payment_ID()),
|
||||
{
|
||||
payAcct = getPaymentAcct(as, line.getC_Payment_ID());
|
||||
fl = fact.createLine (line, payAcct,
|
||||
getC_Currency_ID(), null, line.getAmtSource().negate());
|
||||
if (fl != null && payment != null)
|
||||
fl.setAD_Org_ID(payment.getAD_Org_ID());
|
||||
|
@ -430,7 +435,7 @@ public class Doc_AllocationHdr extends Doc
|
|||
&& (getC_Currency_ID() != as.getC_Currency_ID() // payment allocation in foreign currency
|
||||
|| getC_Currency_ID() != line.getInvoiceC_Currency_ID())) // allocation <> invoice currency
|
||||
{
|
||||
p_Error = createRealizedGainLoss (line, as, fact, bpAcct, invoice,
|
||||
p_Error = createRealizedGainLoss (line, as, fact, bpAcct, invoice, payAcct, payment,
|
||||
allocationSource, allocationAccounted);
|
||||
if (p_Error != null)
|
||||
return null;
|
||||
|
@ -692,102 +697,164 @@ public class Doc_AllocationHdr extends Doc
|
|||
* Accounted Amount of the Allocation
|
||||
* @param as accounting schema
|
||||
* @param fact fact
|
||||
* @param acct account
|
||||
* @param invAcct invoice account
|
||||
* @param invoice invoice
|
||||
* @param payAcct payment account
|
||||
* @param payment payment
|
||||
* @param allocationSource source amt
|
||||
* @param allocationAccounted acct amt
|
||||
* @return Error Message or null if OK
|
||||
*/
|
||||
private String createRealizedGainLoss (DocLine line, MAcctSchema as, Fact fact, MAccount acct,
|
||||
MInvoice invoice, BigDecimal allocationSource, BigDecimal allocationAccounted)
|
||||
private String createRealizedGainLoss (DocLine line, MAcctSchema as, Fact fact, MAccount invAcct,
|
||||
MInvoice invoice, MAccount payAcct, MPayment payment, BigDecimal allocationSource, BigDecimal allocationAccounted)
|
||||
{
|
||||
BigDecimal invoiceSource = null;
|
||||
BigDecimal invoiceAccounted = null;
|
||||
BigDecimal paymentSource = null;
|
||||
BigDecimal paymentAccounted = null;
|
||||
//
|
||||
StringBuilder sql = new StringBuilder("SELECT ")
|
||||
.append(invoice.isSOTrx()
|
||||
? "SUM(AmtSourceDr), SUM(AmtAcctDr)" // so
|
||||
: "SUM(AmtSourceCr), SUM(AmtAcctCr)") // po
|
||||
StringBuilder sql = new StringBuilder()
|
||||
.append("SELECT SUM(AmtSourceDr), SUM(AmtAcctDr), SUM(AmtSourceCr), SUM(AmtAcctCr)")
|
||||
.append(" FROM Fact_Acct ")
|
||||
.append("WHERE AD_Table_ID=318 AND Record_ID=?") // Invoice
|
||||
.append("WHERE AD_Table_ID=? AND Record_ID=?")
|
||||
.append(" AND C_AcctSchema_ID=?")
|
||||
.append(" AND PostingType='A'");
|
||||
//AND C_Currency_ID=102
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try
|
||||
{
|
||||
pstmt = DB.prepareStatement(sql.toString(), getTrxName());
|
||||
pstmt.setInt(1, invoice.getC_Invoice_ID());
|
||||
pstmt.setInt(2, as.getC_AcctSchema_ID());
|
||||
rs = pstmt.executeQuery();
|
||||
if (rs.next())
|
||||
{
|
||||
invoiceSource = rs.getBigDecimal(1);
|
||||
invoiceAccounted = rs.getBigDecimal(2);
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.SEVERE, sql.toString(), e);
|
||||
}
|
||||
finally {
|
||||
DB.close(rs, pstmt);
|
||||
rs = null; pstmt = null;
|
||||
.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());
|
||||
if (valuesInv != null) {
|
||||
if (invoice.isSOTrx()) {
|
||||
invoiceSource = (BigDecimal) valuesInv.get(0); // AmtSourceDr
|
||||
invoiceAccounted = (BigDecimal) valuesInv.get(1); // AmtAcctDr
|
||||
} else {
|
||||
invoiceSource = (BigDecimal) valuesInv.get(2); // AmtSourceCr
|
||||
invoiceAccounted = (BigDecimal) valuesInv.get(3); // AmtAcctCr
|
||||
}
|
||||
}
|
||||
// Requires that Invoice is Posted
|
||||
if (invoiceSource == null || invoiceAccounted == null)
|
||||
return "Gain/Loss - Invoice not posted yet";
|
||||
//
|
||||
StringBuilder description = new StringBuilder("Invoice=(").append(invoice.getC_Currency_ID()).append(")").append(invoiceSource).append("/").append(invoiceAccounted)
|
||||
.append(" - Allocation=(").append(getC_Currency_ID()).append(")").append(allocationSource).append("/").append(allocationAccounted);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(description.toString());
|
||||
// Allocation not Invoice Currency
|
||||
//
|
||||
String invoiceCur = MCurrency.get(getCtx(), invoice.getC_Currency_ID()).getISO_Code();
|
||||
String allocCur = MCurrency.get(getCtx(), getC_Currency_ID()).getISO_Code();
|
||||
StringBuilder descriptionInv = new StringBuilder("Invoice=(").append(invoiceCur).append(")").append(invoiceSource).append("/").append(invoiceAccounted)
|
||||
.append(" - Allocation=(").append(allocCur).append(")").append(allocationSource).append("/").append(allocationAccounted);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(descriptionInv.toString());
|
||||
// Allocation not Invoice Currency
|
||||
BigDecimal allocationInvoiceSource = allocationSource;
|
||||
if (getC_Currency_ID() != invoice.getC_Currency_ID())
|
||||
{
|
||||
BigDecimal allocationSourceNew = MConversionRate.convert(getCtx(),
|
||||
allocationInvoiceSource = MConversionRate.convert(getCtx(),
|
||||
allocationSource, getC_Currency_ID(),
|
||||
invoice.getC_Currency_ID(), getDateAcct(),
|
||||
invoice.getC_ConversionType_ID(), invoice.getAD_Client_ID(), invoice.getAD_Org_ID());
|
||||
if (allocationSourceNew == null)
|
||||
if (allocationInvoiceSource == null)
|
||||
return "Gain/Loss - No Conversion from Allocation->Invoice";
|
||||
StringBuilder d2 = new StringBuilder("Allocation=(").append(getC_Currency_ID()).append(")").append(allocationSource)
|
||||
.append("->(").append(invoice.getC_Currency_ID()).append(")").append(allocationSourceNew);
|
||||
StringBuilder d2 = new StringBuilder("Allocation=(").append(allocCur).append(")").append(allocationSource)
|
||||
.append("->(").append(invoiceCur).append(")").append(allocationInvoiceSource);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||
description.append(" - ").append(d2);
|
||||
allocationSource = allocationSourceNew;
|
||||
descriptionInv.append(" - ").append(d2);
|
||||
}
|
||||
|
||||
BigDecimal acctDifference = null; // gain is negative
|
||||
// Full Payment in currency
|
||||
if (allocationSource.compareTo(invoiceSource) == 0)
|
||||
{
|
||||
acctDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
||||
StringBuilder d2 = new StringBuilder("(full) = ").append(acctDifference);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||
description.append(" - ").append(d2);
|
||||
}
|
||||
else // partial or MC
|
||||
{
|
||||
// percent of total payment
|
||||
double multiplier = allocationSource.doubleValue() / invoiceSource.doubleValue();
|
||||
// Reduce Orig Invoice Accounted
|
||||
invoiceAccounted = invoiceAccounted.multiply(BigDecimal.valueOf(multiplier));
|
||||
// Difference based on percentage of Orig Invoice
|
||||
acctDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
||||
// ignore Tolerance
|
||||
if (acctDifference.abs().compareTo(TOLERANCE) < 0)
|
||||
acctDifference = Env.ZERO;
|
||||
// Round
|
||||
int precision = as.getStdPrecision();
|
||||
if (acctDifference.scale() > precision)
|
||||
acctDifference = acctDifference.setScale(precision, BigDecimal.ROUND_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)
|
||||
BigDecimal invoiceDifference = null; // gain is negative
|
||||
// Full Invoice in currency
|
||||
if (allocationInvoiceSource.compareTo(invoiceSource) == 0)
|
||||
{
|
||||
invoiceDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
||||
StringBuilder d2 = new StringBuilder("(full) = ").append(invoiceDifference);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||
descriptionInv.append(" - ").append(d2);
|
||||
}
|
||||
else // partial or MC
|
||||
{
|
||||
// percent of total payment
|
||||
double multiplier = allocationInvoiceSource.doubleValue() / invoiceSource.doubleValue();
|
||||
// Reduce Orig Invoice Accounted
|
||||
invoiceAccounted = invoiceAccounted.multiply(BigDecimal.valueOf(multiplier));
|
||||
// Difference based on percentage of Orig Invoice
|
||||
invoiceDifference = invoiceAccounted.subtract(allocationAccounted); // gain is negative
|
||||
// ignore Tolerance
|
||||
if (invoiceDifference.abs().compareTo(TOLERANCE) < 0)
|
||||
invoiceDifference = Env.ZERO;
|
||||
// Round
|
||||
int precision = as.getStdPrecision();
|
||||
if (invoiceDifference.scale() > precision)
|
||||
invoiceDifference = invoiceDifference.setScale(precision, BigDecimal.ROUND_HALF_UP);
|
||||
StringBuilder d2 = new StringBuilder("(partial) = ").append(invoiceDifference).append(" - Multiplier=").append(multiplier);
|
||||
if (log.isLoggable(Level.FINE)) log.fine(d2.toString());
|
||||
descriptionInv.append(" - ").append(d2);
|
||||
}
|
||||
|
||||
// For Payment
|
||||
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, BigDecimal.ROUND_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");
|
||||
return null;
|
||||
|
@ -795,23 +862,45 @@ public class Doc_AllocationHdr extends Doc
|
|||
|
||||
MAccount gain = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedGain_Acct());
|
||||
MAccount loss = MAccount.get (as.getCtx(), as.getAcctSchemaDefault().getRealizedLoss_Acct());
|
||||
//
|
||||
//
|
||||
BigDecimal acctDifference = invoiceDifference.subtract(paymentDifference);
|
||||
if (invoice.isSOTrx())
|
||||
{
|
||||
FactLine fl = fact.createLine (line, loss, gain,
|
||||
as.getC_Currency_ID(), acctDifference);
|
||||
fl.setDescription(description.toString());
|
||||
fact.createLine (line, acct,
|
||||
as.getC_Currency_ID(), acctDifference.negate());
|
||||
fl.setDescription(description.toString());
|
||||
{
|
||||
if (acctDifference.signum() != 0) {
|
||||
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());
|
||||
}
|
||||
if (invoiceDifference.signum() != 0) {
|
||||
FactLine fl = fact.createLine (line, invAcct, as.getC_Currency_ID(), invoiceDifference.negate());
|
||||
fl.setDescription(descriptionInv.toString());
|
||||
}
|
||||
if (paymentDifference.signum() != 0) {
|
||||
FactLine fl = fact.createLine (line, payAcct, as.getC_Currency_ID(), paymentDifference);
|
||||
fl.setDescription(descriptionPay.toString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fact.createLine (line, acct,
|
||||
as.getC_Currency_ID(), acctDifference);
|
||||
@SuppressWarnings("unused")
|
||||
FactLine fl = fact.createLine (line, loss, gain,
|
||||
as.getC_Currency_ID(), acctDifference.negate());
|
||||
if (invoiceDifference.signum() != 0) {
|
||||
FactLine fl = fact.createLine (line, invAcct, as.getC_Currency_ID(), invoiceDifference);
|
||||
fl.setDescription(descriptionInv.toString());
|
||||
}
|
||||
if (paymentDifference.signum() != 0) {
|
||||
FactLine fl = fact.createLine (line, payAcct, as.getC_Currency_ID(), paymentDifference.negate());
|
||||
fl.setDescription(descriptionPay.toString());
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
return null;
|
||||
} // createRealizedGainLoss
|
||||
|
@ -1040,49 +1129,49 @@ class Doc_AllocationTax
|
|||
} // Discount
|
||||
|
||||
// WriteOff Amount
|
||||
if (m_WriteOffAmt.signum() != 0)
|
||||
{
|
||||
// Original Tax is DR - need to correct it CR
|
||||
if (Env.ZERO.compareTo(factAcct.getAmtSourceDr()) != 0)
|
||||
{
|
||||
BigDecimal amount = calcAmount(factAcct.getAmtSourceDr(),
|
||||
total, m_WriteOffAmt, precision);
|
||||
if (amount.signum() != 0)
|
||||
{
|
||||
if (m_IsSOTrx) {
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), amount, null);
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), null, amount);
|
||||
} else {
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), amount.negate(), null);
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), null, amount.negate());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Original Tax is CR - need to correct it DR
|
||||
else
|
||||
{
|
||||
BigDecimal amount = calcAmount(factAcct.getAmtSourceCr(),
|
||||
total, m_WriteOffAmt, precision);
|
||||
if (amount.signum() != 0)
|
||||
{
|
||||
if(m_IsSOTrx) {
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), amount, null);
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), null, amount);
|
||||
} else {
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), amount.negate(), null);
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), null, amount.negate());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // WriteOff
|
||||
if (m_WriteOffAmt.signum() != 0)
|
||||
{
|
||||
// Original Tax is DR - need to correct it CR
|
||||
if (Env.ZERO.compareTo(factAcct.getAmtSourceDr()) != 0)
|
||||
{
|
||||
BigDecimal amount = calcAmount(factAcct.getAmtSourceDr(),
|
||||
total, m_WriteOffAmt, precision);
|
||||
if (amount.signum() != 0)
|
||||
{
|
||||
if (m_IsSOTrx) {
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), amount, null);
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), null, amount);
|
||||
} else {
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), amount.negate(), null);
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), null, amount.negate());
|
||||
}
|
||||
}
|
||||
}
|
||||
// Original Tax is CR - need to correct it DR
|
||||
else
|
||||
{
|
||||
BigDecimal amount = calcAmount(factAcct.getAmtSourceCr(),
|
||||
total, m_WriteOffAmt, precision);
|
||||
if (amount.signum() != 0)
|
||||
{
|
||||
if(m_IsSOTrx) {
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), amount, null);
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), null, amount);
|
||||
} else {
|
||||
fact.createLine (line, taxAcct,
|
||||
as.getC_Currency_ID(), amount.negate(), null);
|
||||
fact.createLine (line, m_WriteOffAccount,
|
||||
as.getC_Currency_ID(), null, amount.negate());
|
||||
}
|
||||
}
|
||||
}
|
||||
} // WriteOff
|
||||
|
||||
} // for all lines
|
||||
return true;
|
||||
|
|
|
@ -93,7 +93,10 @@ public class Doc_GLJournal extends Doc
|
|||
MAccount account = line.getAccount_Combi();
|
||||
docLine.setAccount (account);
|
||||
// -- Organization of Line was set to Org of Account
|
||||
list.add(docLine);
|
||||
list.add(docLine);
|
||||
|
||||
if (docLine.getC_Currency_ID() != getC_Currency_ID())
|
||||
setIsMultiCurrency(true);
|
||||
}
|
||||
// Return Array
|
||||
int size = list.size();
|
||||
|
@ -154,7 +157,7 @@ public class Doc_GLJournal extends Doc
|
|||
@SuppressWarnings("unused")
|
||||
FactLine line = fact.createLine (p_lines[i],
|
||||
p_lines[i].getAccount (),
|
||||
getC_Currency_ID(),
|
||||
p_lines[i].getC_Currency_ID(),
|
||||
p_lines[i].getAmtSourceDr (),
|
||||
p_lines[i].getAmtSourceCr ());
|
||||
}
|
||||
|
|
|
@ -445,14 +445,41 @@ public class Doc_MatchPO extends Doc
|
|||
&& mPO[i].getM_MatchPO_ID() != mMatchPO.getM_MatchPO_ID())
|
||||
{
|
||||
BigDecimal qty = (isReturnTrx ? mPO[i].getQty().negate() : mPO[i].getQty());
|
||||
BigDecimal orderCost = BigDecimal.ZERO;
|
||||
if (mPO[i].getM_InOutLine_ID() > 0)
|
||||
{
|
||||
tQty = tQty.add(qty);
|
||||
tAmt = tAmt.add(poCost.multiply(qty));
|
||||
//IDEMPIERE-3742 Wrong product cost for partial MR
|
||||
if (m_oLine.getC_Currency_ID() != as.getC_Currency_ID())
|
||||
{
|
||||
MOrder order = m_oLine.getParent();
|
||||
if(MAcctSchema.COSTINGMETHOD_AveragePO.equals(as.getCostingMethod()))
|
||||
{
|
||||
orderCost = mPO[i].getM_InOutLine().getC_OrderLine().getPriceActual();
|
||||
Timestamp dateAcct = mPO[i].getM_InOutLine().getM_InOut().getDateAcct();
|
||||
BigDecimal rate = MConversionRate.getRate(
|
||||
order.getC_Currency_ID(), as.getC_Currency_ID(),
|
||||
dateAcct, order.getC_ConversionType_ID(),
|
||||
m_oLine.getAD_Client_ID(), m_oLine.getAD_Org_ID());
|
||||
|
||||
if (rate == null)
|
||||
{
|
||||
p_Error = "Purchase Order not convertible - " + as.getName();
|
||||
return null;
|
||||
}
|
||||
orderCost = orderCost.multiply(rate);
|
||||
tAmt = tAmt.add(orderCost.multiply(qty));
|
||||
|
||||
} else {
|
||||
tAmt = tAmt.add(poCost.multiply(qty));
|
||||
}
|
||||
} //IDEMPIERE-3742 Wrong product cost for partial MR
|
||||
else {
|
||||
tAmt = tAmt.add(poCost.multiply(qty));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
poCost = poCost.multiply(getQty()); // Delivered so far
|
||||
tAmt = tAmt.add(isReturnTrx ? poCost.negate() : poCost);
|
||||
tQty = tQty.add(isReturnTrx ? getQty().negate() : getQty());
|
||||
|
|
|
@ -728,7 +728,7 @@ public final class FactLine extends X_Fact_Acct
|
|||
|
||||
Timestamp convDate = getDateAcct();
|
||||
|
||||
if ( m_docLine != null && ( m_doc instanceof Doc_BankStatement || m_doc instanceof Doc_AllocationHdr ) )
|
||||
if (m_docLine != null && m_doc instanceof Doc_BankStatement)
|
||||
convDate = m_docLine.getDateConv();
|
||||
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.adempiere.util.PaymentUtil;
|
|||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.IBAN;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
/**
|
||||
|
@ -214,7 +215,7 @@ public class MBPBankAccount extends X_C_BP_BankAccount
|
|||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
log.saveError("Error", Msg.getMsg(getCtx(), "InvalidIBAN"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,6 +22,7 @@ import java.util.Properties;
|
|||
import org.compiere.util.CCache;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.IBAN;
|
||||
import org.compiere.util.Msg;
|
||||
import org.compiere.util.Util;
|
||||
|
||||
|
||||
|
@ -136,7 +137,7 @@ public class MBankAccount extends X_C_BankAccount
|
|||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
log.saveError("Error", Msg.getMsg(getCtx(), "InvalidIBAN"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1035,7 +1035,7 @@ public class MInvoiceLine extends X_C_InvoiceLine
|
|||
{
|
||||
double result = getLineNetAmt().multiply(base).doubleValue();
|
||||
result /= total.doubleValue();
|
||||
lca.setAmt(result, getParent().getC_Currency().getCostingPrecision());
|
||||
lca.setAmt(result, getParent().getC_Currency().getStdPrecision());
|
||||
}
|
||||
if (!lca.save()){
|
||||
msgreturn = new StringBuilder("Cannot save line Allocation = ").append(lca);
|
||||
|
@ -1170,7 +1170,7 @@ public class MInvoiceLine extends X_C_InvoiceLine
|
|||
{
|
||||
double result = getLineNetAmt().multiply(base).doubleValue();
|
||||
result /= total.doubleValue();
|
||||
lca.setAmt(result, getParent().getC_Currency().getCostingPrecision());
|
||||
lca.setAmt(result, getParent().getC_Currency().getStdPrecision());
|
||||
}
|
||||
if (!lca.save()){
|
||||
msgreturn = new StringBuilder("Cannot save line Allocation = ").append(lca);
|
||||
|
|
|
@ -527,8 +527,8 @@ public class MJournal extends X_GL_Journal implements DocAction
|
|||
}
|
||||
// end BF [2789319] No check of Actual, Budget, Statistical attribute
|
||||
|
||||
AmtSourceDr = AmtSourceDr.add(line.getAmtSourceDr());
|
||||
AmtSourceCr = AmtSourceCr.add(line.getAmtSourceCr());
|
||||
AmtSourceDr = AmtSourceDr.add(line.getAmtAcctDr()); // multi-currency
|
||||
AmtSourceCr = AmtSourceCr.add(line.getAmtAcctCr());
|
||||
}
|
||||
setTotalDr(AmtSourceDr);
|
||||
setTotalCr(AmtSourceCr);
|
||||
|
|
|
@ -804,7 +804,7 @@ public class MPayment extends X_C_Payment
|
|||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
log.saveError("Error", Msg.getMsg(getCtx(), "InvalidIBAN"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public class MPaymentTransaction extends X_C_PaymentTransaction implements Proce
|
|||
if (!Util.isEmpty(getIBAN())) {
|
||||
setIBAN(IBAN.normalizeIBAN(getIBAN()));
|
||||
if (!IBAN.isValid(getIBAN())) {
|
||||
log.saveError("Error", "IBAN is invalid");
|
||||
log.saveError("Error", Msg.getMsg(getCtx(), "InvalidIBAN"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -282,7 +282,8 @@ public class MPeriod extends X_C_Period
|
|||
int idxdate = -1;
|
||||
if ( tableID == MInventory.Table_ID
|
||||
|| tableID == MMovement.Table_ID
|
||||
|| tableID == MProduction.Table_ID) {
|
||||
|| tableID == MProduction.Table_ID
|
||||
|| tableID == MProjectIssue.Table_ID) {
|
||||
idxdate = po.get_ColumnIndex("MovementDate");
|
||||
} else if ( tableID == MRequisition.Table_ID) {
|
||||
idxdate = po.get_ColumnIndex("DateDoc");
|
||||
|
@ -333,6 +334,8 @@ public class MPeriod extends X_C_Period
|
|||
} else if ( tableID == MAssetDisposed.Table_ID
|
||||
|| tableID == MDepreciationExp.Table_ID) {
|
||||
docBaseType = MDocType.DOCBASETYPE_GLDocument; // seems like a bug of fixed assets - must use GLJournal instead of GLDocument?
|
||||
} else if (tableID == MProjectIssue.Table_ID) {
|
||||
docBaseType = MDocType.DOCBASETYPE_ProjectIssue;
|
||||
} else {
|
||||
s_log.warning("Could not find C_DocType_ID for " + table.getTableName());
|
||||
return true;
|
||||
|
|
|
@ -288,7 +288,7 @@ public class MRequisitionLine extends X_M_RequisitionLine
|
|||
* IDEMPIERE-178 Orders and Invoices must disallow amount lines without product/charge
|
||||
*/
|
||||
if (getParent().getC_DocType().isChargeOrProductMandatory()) {
|
||||
if (getC_Charge_ID() == 0 && getM_Product_ID() == 0 && getPriceActual().signum() != 0) {
|
||||
if (getC_Charge_ID() == 0 && getM_Product_ID() == 0 && (getPriceActual().signum() != 0 || getQty().signum() != 0)) {
|
||||
log.saveError("FillMandatory", Msg.translate(getCtx(), "ChargeOrProductMandatory"));
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -871,14 +871,8 @@ public final class Env
|
|||
throw new IllegalArgumentException ("Require Context");
|
||||
String s = getContext(ctx, WindowNo, context, false);
|
||||
// JDBC Format YYYY-MM-DD example 2000-09-11 00:00:00.0
|
||||
if (s == null || s.equals(""))
|
||||
{
|
||||
if (!"#date".equalsIgnoreCase(context))
|
||||
{
|
||||
log.log(Level.WARNING, "No value for: " + context);
|
||||
}
|
||||
if (Util.isEmpty(s))
|
||||
return new Timestamp(System.currentTimeMillis());
|
||||
}
|
||||
|
||||
// BUG:3075946 KTU - Fix Thai Date
|
||||
/*
|
||||
|
|
|
@ -26,7 +26,7 @@ public class IBAN {
|
|||
{
|
||||
if (iban!=null)
|
||||
{
|
||||
return iban.trim().replace(" ", "") ;
|
||||
return iban.trim().replace(" ", "").toUpperCase() ;
|
||||
}
|
||||
return null ;
|
||||
}
|
||||
|
|
|
@ -1353,7 +1353,7 @@ public class ReportStarter implements ProcessCall, ClientProcess
|
|||
jasperFile.setLastModified( reportFile.lastModified()); //Synchronize Dates
|
||||
compiledJasperReport = (JasperReport)JRLoader.loadObject(jasperFile);
|
||||
} catch (JRException e) {
|
||||
log.log(Level.SEVERE, "Error", e);
|
||||
throw new AdempiereException(e);
|
||||
}
|
||||
return compiledJasperReport;
|
||||
}
|
||||
|
|
|
@ -533,7 +533,7 @@ public class WAllocation extends Allocation
|
|||
allocateButton.setEnabled(true);
|
||||
if (allocation != null)
|
||||
{
|
||||
DocumentLink link = new DocumentLink(allocation.getDocumentNo(), allocation.get_Table_ID(), allocation.get_ID());
|
||||
DocumentLink link = new DocumentLink(Msg.getElement(Env.getCtx(), MAllocationHdr.COLUMNNAME_C_AllocationHdr_ID) + ": " + allocation.getDocumentNo(), allocation.get_Table_ID(), allocation.get_ID());
|
||||
statusBar.appendChild(link);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -118,7 +118,7 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene
|
|||
{
|
||||
log.log(Level.SEVERE, "", e);
|
||||
}
|
||||
} // init
|
||||
} // WPayPrint
|
||||
|
||||
// Static Variables
|
||||
protected Panel centerPanel = new Panel();
|
||||
|
@ -234,8 +234,7 @@ public class WPayPrint extends PayPrint implements IFormController, EventListene
|
|||
bExport.setDisabled(true);
|
||||
bPrint.setDisabled(true);
|
||||
fDepositBatch.setReadWrite(false);
|
||||
fDocumentNo.setReadWrite(false);
|
||||
} // VPayPrint
|
||||
} // zkInit
|
||||
|
||||
/**
|
||||
* Dynamic Init
|
||||
|
|
|
@ -85,8 +85,8 @@ public class WAccountEditor extends WEditor implements ContextMenuListener
|
|||
@Override
|
||||
public Object getValue()
|
||||
{
|
||||
//if (m_mAccount.C_ValidCombination_ID == 0)
|
||||
// return null;
|
||||
if (m_mAccount.C_ValidCombination_ID == 0)
|
||||
return null;
|
||||
return new Integer (m_mAccount.C_ValidCombination_ID);
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,11 @@ public class WAccountEditor extends WEditor implements ContextMenuListener
|
|||
*/
|
||||
public void cmd_button()
|
||||
{
|
||||
int C_AcctSchema_ID = Env.getContextAsInt(Env.getCtx(), gridField.getWindowNo(), "C_AcctSchema_ID");
|
||||
int C_AcctSchema_ID;
|
||||
if (gridField.getGridTab() != null)
|
||||
C_AcctSchema_ID = Env.getContextAsInt(Env.getCtx(), gridField.getWindowNo(), gridField.getGridTab().getTabNo(), "C_AcctSchema_ID");
|
||||
else
|
||||
C_AcctSchema_ID = Env.getContextAsInt(Env.getCtx(), gridField.getWindowNo(), "C_AcctSchema_ID");
|
||||
// Try to get C_AcctSchema_ID from global context - teo_sarca BF [ 1830531 ]
|
||||
if (C_AcctSchema_ID <= 0)
|
||||
{
|
||||
|
|
|
@ -2649,7 +2649,7 @@ public class FindWindow extends Window implements EventListener<Event>, ValueCha
|
|||
*/
|
||||
private void setStatusDB (int currentCount)
|
||||
{
|
||||
StringBuilder text = new StringBuilder(" ").append(currentCount).append(" / ").append(m_total).append(" ");
|
||||
StringBuilder text = new StringBuilder(" ").append(Msg.getMsg(Env.getCtx(), "Records")).append(" = ").append(m_total).append(" ");
|
||||
statusBar.setStatusDB(text.toString());
|
||||
} // setDtatusDB
|
||||
/** END DEVCOFFEE **/
|
||||
|
|
|
@ -2,6 +2,9 @@ CKEDITOR.editorConfig = function(config) {
|
|||
config.resize_enabled = false;
|
||||
config.toolbarCanCollapse = true;
|
||||
config.toolbar = 'MyToolbar';
|
||||
config.coreStyles_bold = { element: 'b', overrides: 'strong' };
|
||||
config.coreStyles_italic = { element: 'i', overrides: 'em' };
|
||||
config.coreStyles_strike = { element: 'strike', overrides: 's' };
|
||||
config.toolbar_MyToolbar =
|
||||
[
|
||||
{ name: 'styles', items : [ 'Styles','Format','Font','FontSize' ] },
|
||||
|
|
|
@ -2,6 +2,9 @@ CKEDITOR.editorConfig = function(config) {
|
|||
config.resize_enabled = false;
|
||||
config.toolbarCanCollapse = true;
|
||||
config.toolbar = 'MyToolbar';
|
||||
config.coreStyles_bold = { element: 'b', overrides: 'strong' };
|
||||
config.coreStyles_italic = { element: 'i', overrides: 'em' };
|
||||
config.coreStyles_strike = { element: 'strike', overrides: 's' };
|
||||
config.toolbar_MyToolbar =
|
||||
[
|
||||
{ name: 'styles', items : [ 'Styles','Format','Font','FontSize' ] },
|
||||
|
|
|
@ -65,11 +65,8 @@ public class CompositeServiceImpl extends AbstractService implements CompositeSe
|
|||
*/
|
||||
@Override
|
||||
public CompositeResponsesDocument compositeOperation(CompositeRequestDocument reqs) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
CompositeResponsesDocument ret = CompositeResponsesDocument.Factory.newInstance();
|
||||
CompositeResponses resps = ret.addNewCompositeResponses();
|
||||
|
@ -124,8 +121,7 @@ public class CompositeServiceImpl extends AbstractService implements CompositeSe
|
|||
|
||||
return ret;
|
||||
} finally {
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ public class MWebService extends X_WS_WebService
|
|||
* @param webServiceValue
|
||||
* @return Table
|
||||
*/
|
||||
public static MWebService get (Properties ctx, String webServiceValue)
|
||||
public static synchronized MWebService get (Properties ctx, String webServiceValue)
|
||||
{
|
||||
if (webServiceValue == null)
|
||||
return null;
|
||||
|
|
|
@ -79,13 +79,13 @@ public class CompiereService {
|
|||
|
||||
public final String dateFormatOnlyForCtx = "yyyy-MM-dd";
|
||||
|
||||
private boolean m_connected;
|
||||
private int m_connectCount;
|
||||
|
||||
/**
|
||||
*
|
||||
* @return AD_Client_ID of current request
|
||||
*/
|
||||
public int getAD_Client_ID() {
|
||||
public synchronized int getAD_Client_ID() {
|
||||
return m_AD_Client_ID;
|
||||
}
|
||||
|
||||
|
@ -93,7 +93,7 @@ public class CompiereService {
|
|||
*
|
||||
* @return AD_Org_ID of current request
|
||||
*/
|
||||
public int getAD_Org_ID() {
|
||||
public synchronized int getAD_Org_ID() {
|
||||
return m_AD_Org_ID;
|
||||
}
|
||||
|
||||
|
@ -101,7 +101,7 @@ public class CompiereService {
|
|||
*
|
||||
* @return context of current request
|
||||
*/
|
||||
public Properties getCtx() {
|
||||
public synchronized Properties getCtx() {
|
||||
return Env.getCtx();
|
||||
}
|
||||
|
||||
|
@ -111,7 +111,7 @@ public class CompiereService {
|
|||
public CompiereService()
|
||||
{
|
||||
m_loggedin = false;
|
||||
m_connected = false;
|
||||
m_connectCount = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -119,70 +119,51 @@ public class CompiereService {
|
|||
*/
|
||||
public void connect()
|
||||
{
|
||||
if (!m_connected)
|
||||
{
|
||||
CompiereUtil.initWeb();
|
||||
|
||||
m_connected = true;
|
||||
|
||||
ServerContext.setCurrentInstance(new Properties());
|
||||
Env.setContext(getCtx(), "#AD_Language", "en_US" );
|
||||
m_language = Language.getLanguage("en_US");
|
||||
|
||||
dateFormat = DisplayType.getDateFormat(DisplayType.Date, m_language);
|
||||
dateTimeFormat = DisplayType.getDateFormat(DisplayType.DateTime, m_language);
|
||||
timeFormat = DisplayType.getDateFormat(DisplayType.Time, m_language);
|
||||
dateFormatJDBC = DisplayType.getDateFormat_JDBC();
|
||||
dateTimeFormatJDBC = DisplayType.getTimestampFormat_Default();
|
||||
timeFormatJDBC = DisplayType.getTimeFormat_Default();
|
||||
}
|
||||
CompiereUtil.initWeb();
|
||||
|
||||
ServerContext.setCurrentInstance(new Properties());
|
||||
Env.setContext(getCtx(), "#AD_Language", "en_US" );
|
||||
m_language = Language.getLanguage("en_US");
|
||||
|
||||
dateFormat = DisplayType.getDateFormat(DisplayType.Date, m_language);
|
||||
dateTimeFormat = DisplayType.getDateFormat(DisplayType.DateTime, m_language);
|
||||
timeFormat = DisplayType.getDateFormat(DisplayType.Time, m_language);
|
||||
dateFormatJDBC = DisplayType.getDateFormat_JDBC();
|
||||
dateTimeFormatJDBC = DisplayType.getTimestampFormat_Default();
|
||||
timeFormatJDBC = DisplayType.getTimeFormat_Default();
|
||||
|
||||
m_connectCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increase connect count
|
||||
*/
|
||||
public synchronized void connectCacheInstance()
|
||||
{
|
||||
m_connectCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* cleanup request
|
||||
*/
|
||||
public void disconnect()
|
||||
public synchronized void disconnect()
|
||||
{
|
||||
m_connectCount--;
|
||||
// TODO: create a thread that checks expired connected compiereservices and log them out
|
||||
if (! isExpired()) {
|
||||
// do not close, save session in cache
|
||||
if (! csMap.containsValue(this)) {
|
||||
String key = getKey(m_AD_Client_ID,
|
||||
m_AD_Org_ID,
|
||||
m_userName,
|
||||
m_AD_Role_ID,
|
||||
m_M_Warehouse_ID,
|
||||
m_locale,
|
||||
m_password,
|
||||
m_IPAddress);
|
||||
csMap.put(key.toString(), this);
|
||||
Properties savedCache = new Properties();
|
||||
savedCache.putAll(Env.getCtx());
|
||||
ctxMap.put(key.toString(), savedCache);
|
||||
if (log.isLoggable(Level.INFO)) log.info("Saving " + this + " in cache");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if started
|
||||
*/
|
||||
public boolean isConnected()
|
||||
{
|
||||
return m_connected;
|
||||
expungeIfExpire();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Language of current request
|
||||
*/
|
||||
public Language getLanguage() {
|
||||
public synchronized Language getLanguage() {
|
||||
return m_language;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if already logged in
|
||||
*/
|
||||
public boolean isLoggedIn() {
|
||||
public synchronized boolean isLoggedIn() {
|
||||
return m_loggedin;
|
||||
}
|
||||
|
||||
|
@ -196,7 +177,7 @@ public class CompiereService {
|
|||
* @param AD_Org_ID org
|
||||
* @param M_Warehouse_ID warehouse
|
||||
*/
|
||||
private String checkLogin (Properties ctx, int AD_User_ID, int AD_Role_ID, int AD_Client_ID, int AD_Org_ID, int M_Warehouse_ID)
|
||||
private synchronized String checkLogin (Properties ctx, int AD_User_ID, int AD_Role_ID, int AD_Client_ID, int AD_Org_ID, int M_Warehouse_ID)
|
||||
{
|
||||
// Get Login Info
|
||||
String loginInfo = null;
|
||||
|
@ -262,7 +243,7 @@ public class CompiereService {
|
|||
* @param Lang
|
||||
* @return true if login is successful
|
||||
*/
|
||||
public boolean login( int AD_User_ID, int AD_Role_ID, int AD_Client_ID, int AD_Org_ID, int M_Warehouse_ID, String Lang ) {
|
||||
public synchronized boolean login( int AD_User_ID, int AD_Role_ID, int AD_Client_ID, int AD_Org_ID, int M_Warehouse_ID, String Lang ) {
|
||||
m_loggedin = false;
|
||||
String loginInfo = checkLogin (getCtx(), AD_User_ID, AD_Role_ID, AD_Client_ID, AD_Org_ID, M_Warehouse_ID );
|
||||
if (loginInfo == null)
|
||||
|
@ -315,6 +296,26 @@ public class CompiereService {
|
|||
session.saveEx();
|
||||
|
||||
m_loggedin = true;
|
||||
|
||||
synchronized (csMap) {
|
||||
//save session in cache
|
||||
String key = getKey(m_AD_Client_ID,
|
||||
m_AD_Org_ID,
|
||||
m_userName,
|
||||
m_AD_Role_ID,
|
||||
m_M_Warehouse_ID,
|
||||
m_locale,
|
||||
m_password,
|
||||
m_IPAddress);
|
||||
if (! csMap.containsKey(key)) {
|
||||
csMap.put(key.toString(), this);
|
||||
Properties savedCache = new Properties();
|
||||
savedCache.putAll(Env.getCtx());
|
||||
ctxMap.put(key.toString(), savedCache);
|
||||
if (log.isLoggable(Level.INFO)) log.info("Saving " + this + " in cache");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -322,7 +323,7 @@ public class CompiereService {
|
|||
*
|
||||
* @return AD_User_ID of current request
|
||||
*/
|
||||
public int getAD_User_ID() {
|
||||
public synchronized int getAD_User_ID() {
|
||||
return m_AD_User_ID;
|
||||
}
|
||||
|
||||
|
@ -330,7 +331,7 @@ public class CompiereService {
|
|||
*
|
||||
* @return AD_Role_ID of current request
|
||||
*/
|
||||
public int getAD_Role_ID() {
|
||||
public synchronized int getAD_Role_ID() {
|
||||
return m_AD_Role_ID;
|
||||
}
|
||||
|
||||
|
@ -338,7 +339,7 @@ public class CompiereService {
|
|||
*
|
||||
* @return locale code of current request
|
||||
*/
|
||||
public String getLocale() {
|
||||
public synchronized String getLocale() {
|
||||
return m_locale;
|
||||
}
|
||||
|
||||
|
@ -346,7 +347,7 @@ public class CompiereService {
|
|||
*
|
||||
* @return M_Warehouse_ID of current request
|
||||
*/
|
||||
public int getM_Warehouse_ID() {
|
||||
public synchronized int getM_Warehouse_ID() {
|
||||
return m_M_Warehouse_ID;
|
||||
}
|
||||
|
||||
|
@ -354,43 +355,43 @@ public class CompiereService {
|
|||
*
|
||||
* @return logged in user name of current request
|
||||
*/
|
||||
public String getUserName() {
|
||||
public synchronized String getUserName() {
|
||||
return m_userName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return set password
|
||||
*/
|
||||
public void setPassword(String pass) {
|
||||
public synchronized void setPassword(String pass) {
|
||||
m_password = pass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return logged in password of current request
|
||||
*/
|
||||
public String getPassword() {
|
||||
public synchronized String getPassword() {
|
||||
return m_password;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return set expiry minutes
|
||||
*/
|
||||
public void setExpiryMinutes(int expiryMinutes) {
|
||||
public synchronized void setExpiryMinutes(int expiryMinutes) {
|
||||
m_expiryMinutes = expiryMinutes;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return logged in expiry minutes of current request
|
||||
*/
|
||||
public int getExpiryMinutes() {
|
||||
public synchronized int getExpiryMinutes() {
|
||||
return m_expiryMinutes;
|
||||
}
|
||||
|
||||
public void refreshLastAuthorizationTime() {
|
||||
public synchronized void refreshLastAuthorizationTime() {
|
||||
m_lastAuthorizationTime = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
public void setIPAddress(String remoteAddr) {
|
||||
public synchronized void setIPAddress(String remoteAddr) {
|
||||
m_IPAddress = remoteAddr;
|
||||
}
|
||||
|
||||
|
@ -404,17 +405,17 @@ public class CompiereService {
|
|||
loginRequest.getPass(),
|
||||
req.getRemoteAddr());
|
||||
CompiereService l_cs = null;
|
||||
if (csMap.containsKey(key)) {
|
||||
l_cs = csMap.get(key);
|
||||
if (l_cs != null) {
|
||||
if (l_cs.isExpired()) {
|
||||
csMap.remove(key);
|
||||
ctxMap.remove(key);
|
||||
l_cs = null;
|
||||
} else {
|
||||
Properties cachedCtx = ctxMap.get(key);
|
||||
Env.getCtx().putAll(cachedCtx);
|
||||
if (log.isLoggable(Level.INFO)) log.info("Reusing " + l_cs);
|
||||
synchronized (csMap) {
|
||||
if (csMap.containsKey(key)) {
|
||||
l_cs = csMap.get(key);
|
||||
if (l_cs != null) {
|
||||
if (l_cs.expungeIfExpire()) {
|
||||
l_cs = null;
|
||||
} else {
|
||||
Properties cachedCtx = ctxMap.get(key);
|
||||
Env.getCtx().putAll(cachedCtx);
|
||||
if (log.isLoggable(Level.INFO)) log.info("Reusing " + l_cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -442,19 +443,43 @@ public class CompiereService {
|
|||
return key.toString();
|
||||
}
|
||||
|
||||
private boolean isExpired() {
|
||||
private synchronized boolean expungeIfExpire() {
|
||||
boolean expired =
|
||||
(
|
||||
(getExpiryMinutes() <= 0)
|
||||
|| (m_lastAuthorizationTime + (getExpiryMinutes() * 60000) <= System.currentTimeMillis())
|
||||
);
|
||||
if (m_connected && expired)
|
||||
if (m_connectCount==0 && expired)
|
||||
{
|
||||
if (log.isLoggable(Level.INFO)) log.info("Closing expired/invalid " + this);
|
||||
Env.logout();
|
||||
ServerContext.dispose();
|
||||
m_loggedin = false;
|
||||
m_connected = false;
|
||||
synchronized (csMap) {
|
||||
String key = getKey(m_AD_Client_ID,
|
||||
m_AD_Org_ID,
|
||||
m_userName,
|
||||
m_AD_Role_ID,
|
||||
m_M_Warehouse_ID,
|
||||
m_locale,
|
||||
m_password,
|
||||
m_IPAddress);
|
||||
if (csMap.containsKey(key)) {
|
||||
csMap.remove(key);
|
||||
}
|
||||
if (ctxMap.containsKey(key)) {
|
||||
Properties cachedCtx = ctxMap.remove(key);
|
||||
Properties currentCtx = ServerContext.getCurrentInstance();
|
||||
try {
|
||||
ServerContext.setCurrentInstance(cachedCtx);
|
||||
if (log.isLoggable(Level.INFO)) log.info("Closing expired/invalid " + this);
|
||||
Env.logout();
|
||||
} finally {
|
||||
if (currentCtx == cachedCtx) {
|
||||
ServerContext.dispose();
|
||||
} else {
|
||||
ServerContext.setCurrentInstance(currentCtx);
|
||||
}
|
||||
}
|
||||
}
|
||||
m_loggedin = false;
|
||||
}
|
||||
}
|
||||
return expired;
|
||||
}
|
||||
|
|
|
@ -168,13 +168,9 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
* use the runProcess web service
|
||||
*/
|
||||
public StandardResponseDocument setDocAction(ModelSetDocActionRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
boolean manageTrx = this.manageTrx;
|
||||
Trx trx=null;
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
StandardResponseDocument ret = StandardResponseDocument.Factory.newInstance();
|
||||
StandardResponse resp = ret.addNewStandardResponse();
|
||||
|
@ -289,9 +285,6 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
if (manageTrx && !trx.commit())
|
||||
return rollbackAndSetError(trx, resp, ret, true, "Cannot commit after docAction");
|
||||
|
||||
if (manageTrx)
|
||||
trx.close();
|
||||
|
||||
// resp.setError("");
|
||||
resp.setIsError(false);
|
||||
|
||||
|
@ -304,9 +297,8 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
} finally {
|
||||
if (manageTrx && trx != null)
|
||||
trx.close();
|
||||
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -390,11 +382,8 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
|
||||
|
||||
public RunProcessResponseDocument runProcess(ModelRunProcessRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
RunProcessResponseDocument resbadlogin = RunProcessResponseDocument.Factory.newInstance();
|
||||
RunProcessResponse rbadlogin = resbadlogin.addNewRunProcessResponse();
|
||||
|
@ -430,17 +419,13 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
requestCtx.put(serviceType+"_Summary", response.getRunProcessResponse().getSummary());
|
||||
return response;
|
||||
} finally {
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public WindowTabDataDocument getList(ModelGetListRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
WindowTabDataDocument resdoc = WindowTabDataDocument.Factory.newInstance();
|
||||
WindowTabData res = resdoc.addNewWindowTabData();
|
||||
|
@ -649,20 +634,14 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
|
||||
return resdoc;
|
||||
} finally {
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
} // getList
|
||||
|
||||
public StandardResponseDocument deleteData(ModelCRUDRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
Trx trx = null;
|
||||
boolean manageTrx = this.manageTrx;
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
StandardResponseDocument ret = StandardResponseDocument.Factory.newInstance();
|
||||
StandardResponse resp = ret.addNewStandardResponse();
|
||||
|
@ -727,8 +706,7 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
if (manageTrx && trx != null)
|
||||
trx.close();
|
||||
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -740,15 +718,9 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
}
|
||||
|
||||
public StandardResponseDocument createData(ModelCRUDRequestDocument req) {
|
||||
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
Trx trx = null;
|
||||
boolean manageTrx = this.manageTrx;
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
StandardResponseDocument ret = StandardResponseDocument.Factory.newInstance();
|
||||
StandardResponse resp = ret.addNewStandardResponse();
|
||||
|
@ -849,21 +821,15 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
if (manageTrx && trx != null)
|
||||
trx.close();
|
||||
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
|
||||
}
|
||||
} // createData
|
||||
|
||||
public StandardResponseDocument createUpdateData(ModelCRUDRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
Trx trx = null;
|
||||
boolean manageTrx = this.manageTrx;
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
StandardResponseDocument ret = StandardResponseDocument.Factory.newInstance();
|
||||
StandardResponse resp = ret.addNewStandardResponse();
|
||||
|
@ -1058,8 +1024,7 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
if (manageTrx && trx != null)
|
||||
trx.close();
|
||||
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
} // createUpdateData
|
||||
|
||||
|
@ -1234,14 +1199,9 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
}
|
||||
|
||||
public StandardResponseDocument updateData(ModelCRUDRequestDocument req){
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
Trx trx = null;
|
||||
boolean manageTrx = this.manageTrx;
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
StandardResponseDocument ret = StandardResponseDocument.Factory.newInstance();
|
||||
StandardResponse resp = ret.addNewStandardResponse();
|
||||
|
@ -1323,17 +1283,13 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
if (manageTrx && trx != null)
|
||||
trx.close();
|
||||
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
} // updateData
|
||||
|
||||
public WindowTabDataDocument readData(ModelCRUDRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
WindowTabDataDocument ret = WindowTabDataDocument.Factory.newInstance();
|
||||
WindowTabData resp = ret.addNewWindowTabData();
|
||||
|
@ -1423,19 +1379,14 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
|
||||
return ret;
|
||||
} finally {
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
public WindowTabDataDocument queryData(ModelCRUDRequestDocument req) {
|
||||
boolean connected = getCompiereService().isConnected();
|
||||
|
||||
boolean manageTrx = this.manageTrx;
|
||||
Trx trx=null;
|
||||
try {
|
||||
if (!connected)
|
||||
getCompiereService().connect();
|
||||
getCompiereService().connect();
|
||||
|
||||
CompiereService m_cs = getCompiereService();
|
||||
WindowTabDataDocument ret = WindowTabDataDocument.Factory.newInstance();
|
||||
|
@ -1589,8 +1540,7 @@ public class ModelADServiceImpl extends AbstractService implements ModelADServic
|
|||
if (manageTrx && trx != null)
|
||||
trx.close();
|
||||
|
||||
if (!connected)
|
||||
getCompiereService().disconnect();
|
||||
getCompiereService().disconnect();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -14,6 +14,8 @@
|
|||
package org.idempiere.webservices;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.Timestamp;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
|
@ -38,8 +40,9 @@ import org.compiere.model.MWebService;
|
|||
import org.compiere.model.MWebServiceType;
|
||||
import org.compiere.model.PO;
|
||||
import org.compiere.model.POInfo;
|
||||
import org.compiere.model.Query;
|
||||
import org.compiere.model.X_WS_WebServiceMethod;
|
||||
import org.compiere.model.X_WS_WebServiceTypeAccess;
|
||||
import org.compiere.util.CCache;
|
||||
import org.compiere.util.DB;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.KeyNamePair;
|
||||
|
@ -64,7 +67,9 @@ import org.idempiere.webservices.fault.IdempiereServiceFault;
|
|||
*/
|
||||
public class AbstractService {
|
||||
|
||||
private static final String ROLE_ACCESS_SQL = "SELECT IsActive FROM WS_WebServiceTypeAccess WHERE AD_Role_ID=? "
|
||||
private static final String ROLE_ACCESS_SQL = "SELECT IsActive FROM WS_WebServiceTypeAccess WHERE AD_Role_ID IN ("
|
||||
+ "SELECT AD_Role_ID FROM AD_Role WHERE AD_Role_ID=? UNION "
|
||||
+ "SELECT Included_Role_ID as AD_Role_ID FROM AD_Role_Included WHERE AD_Role_ID=?) "
|
||||
+ "AND WS_WebServiceType_ID=?";
|
||||
private static final String COMPIERE_SERVICE = "CompiereService";
|
||||
@Resource
|
||||
|
@ -91,6 +96,7 @@ public class AbstractService {
|
|||
if (cachedCs != null) {
|
||||
m_cs = cachedCs;
|
||||
req.setAttribute(COMPIERE_SERVICE, cachedCs);
|
||||
m_cs.connectCacheInstance();
|
||||
return authenticate(webService, method, serviceType, cachedCs); // already logged with same data
|
||||
}
|
||||
}
|
||||
|
@ -201,6 +207,9 @@ public class AbstractService {
|
|||
return authenticate(webService, method, serviceType, m_cs);
|
||||
}
|
||||
|
||||
private static CCache<String,MWebServiceType> s_WebServiceTypeCache = new CCache<String,MWebServiceType>(MWebServiceType.Table_Name, 10, 60); //60 minutes
|
||||
private static CCache<String,Boolean> s_RoleAccessCache = new CCache<>(X_WS_WebServiceTypeAccess.Table_Name, 60, 60);
|
||||
|
||||
/**
|
||||
* Authenticate user for requested service type
|
||||
* @param webServiceValue
|
||||
|
@ -219,28 +228,59 @@ public class AbstractService {
|
|||
if (m_webservicemethod == null || !m_webservicemethod.isActive())
|
||||
return "Method " + methodValue + " not registered";
|
||||
|
||||
MWebServiceType m_webservicetype = new Query(m_cs.getCtx(), MWebServiceType.Table_Name,
|
||||
"AD_Client_ID IN (0,?) AND WS_WebService_ID=? AND WS_WebServiceMethod_ID=? AND Value=?",
|
||||
null)
|
||||
.setOnlyActiveRecords(true)
|
||||
.setParameters(m_cs.getAD_Client_ID(), m_webservice.getWS_WebService_ID(), m_webservicemethod.getWS_WebServiceMethod_ID(), serviceTypeValue)
|
||||
.setOrderBy("AD_Client_ID DESC") // IDEMPIERE-3394 give precedence to tenant defined if there are system+tenant
|
||||
.first();
|
||||
MWebServiceType m_webservicetype = null;
|
||||
String key = m_cs.getAD_Client_ID() + "|" + m_webservice.getWS_WebService_ID() + "|"
|
||||
+ m_webservicemethod.getWS_WebServiceMethod_ID() + "|" + serviceTypeValue;
|
||||
synchronized (s_WebServiceTypeCache) {
|
||||
m_webservicetype = s_WebServiceTypeCache.get(key);
|
||||
if (m_webservicetype == null) {
|
||||
final String sql = "SELECT * FROM WS_WebServiceType " + "WHERE AD_Client_ID=? " + "AND WS_WebService_ID=? "
|
||||
+ "AND WS_WebServiceMethod_ID=? " + "AND Value=? " + "AND IsActive='Y'";
|
||||
PreparedStatement pstmt = null;
|
||||
ResultSet rs = null;
|
||||
try {
|
||||
pstmt = DB.prepareStatement(sql, null);
|
||||
pstmt.setInt(1, m_cs.getAD_Client_ID());
|
||||
pstmt.setInt(2, m_webservice.getWS_WebService_ID());
|
||||
pstmt.setInt(3, m_webservicemethod.getWS_WebServiceMethod_ID());
|
||||
pstmt.setString(4, serviceTypeValue);
|
||||
rs = pstmt.executeQuery();
|
||||
if (rs.next()) {
|
||||
m_webservicetype = new MWebServiceType(m_cs.getCtx(), rs, null);
|
||||
s_WebServiceTypeCache.put(key, m_webservicetype);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new IdempiereServiceFault(e.getClass().toString() + " " + e.getMessage() + " sql=" + sql, e.getCause(), new QName(
|
||||
"authenticate"));
|
||||
} finally {
|
||||
DB.close(rs, pstmt);
|
||||
rs = null;
|
||||
pstmt = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_webservicetype == null)
|
||||
return "Service type " + serviceTypeValue + " not configured";
|
||||
|
||||
getHttpServletRequest().setAttribute("MWebServiceType", m_webservicetype);
|
||||
|
||||
// Check if role has access on web-service
|
||||
String hasAccess = DB.getSQLValueStringEx(null, ROLE_ACCESS_SQL,
|
||||
Env.getAD_Role_ID( m_cs.getCtx()),
|
||||
m_webservicetype.get_ID());
|
||||
|
||||
if (!"Y".equals(hasAccess))
|
||||
{
|
||||
return "Web Service Error: Login role does not have access to the service type";
|
||||
}
|
||||
int AD_Role_ID = Env.getAD_Role_ID( m_cs.getCtx());
|
||||
key = AD_Role_ID + "|" + m_webservicetype.get_ID();
|
||||
synchronized (s_RoleAccessCache) {
|
||||
Boolean bAccess = s_RoleAccessCache.get(key);
|
||||
if (bAccess == null) {
|
||||
// Check if role has access on web-service
|
||||
String hasAccess = DB.getSQLValueStringEx(null, ROLE_ACCESS_SQL,
|
||||
AD_Role_ID, AD_Role_ID, m_webservicetype.get_ID());
|
||||
bAccess = "Y".equals(hasAccess);
|
||||
s_RoleAccessCache.put(key, bAccess);
|
||||
}
|
||||
if (!bAccess.booleanValue())
|
||||
{
|
||||
return "Web Service Error: Login role does not have access to the service type";
|
||||
}
|
||||
}
|
||||
|
||||
String ret=invokeLoginValidator(null, m_cs.getCtx(), m_webservicetype, IWSValidator.TIMING_ON_AUTHORIZATION);
|
||||
if(ret!=null && ret.length()>0)
|
||||
|
|
Loading…
Reference in New Issue