FR [2857807] - Allow accounting posting in standalone user mode
https://sourceforge.net/tracker/?func=detail&atid=879335&aid=2857807&group_id=176962 Partial Fix [2857268] - Usability - Posting silently failing https://sourceforge.net/tracker/index.php?func=detail&aid=2857268&group_id=176962&atid=879332
This commit is contained in:
parent
7147bcda2d
commit
69920ace55
|
@ -33,6 +33,7 @@ import org.compiere.model.MAcctSchema;
|
|||
import org.compiere.model.MAllocationHdr;
|
||||
import org.compiere.model.MBankStatement;
|
||||
import org.compiere.model.MCash;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MConversionRate;
|
||||
import org.compiere.model.MDocType;
|
||||
import org.compiere.model.MInOut;
|
||||
|
@ -373,7 +374,7 @@ public abstract class Doc
|
|||
* @param defaultDocumentType default document type or null
|
||||
* @param trxName trx
|
||||
*/
|
||||
Doc (MAcctSchema[] ass, Class clazz, ResultSet rs, String defaultDocumentType, String trxName)
|
||||
Doc (MAcctSchema[] ass, Class<?> clazz, ResultSet rs, String defaultDocumentType, String trxName)
|
||||
{
|
||||
p_Status = STATUS_Error;
|
||||
m_ass = ass;
|
||||
|
@ -384,7 +385,7 @@ public abstract class Doc
|
|||
className = className.substring(className.lastIndexOf('.')+1);
|
||||
try
|
||||
{
|
||||
Constructor constructor = clazz.getConstructor(new Class[]{Properties.class, ResultSet.class, String.class});
|
||||
Constructor<?> constructor = clazz.getConstructor(new Class[]{Properties.class, ResultSet.class, String.class});
|
||||
p_po = (PO)constructor.newInstance(new Object[]{m_ctx, rs, trxName});
|
||||
}
|
||||
catch (Exception e)
|
||||
|
@ -556,6 +557,9 @@ public abstract class Doc
|
|||
}
|
||||
|
||||
// Lock Record ----
|
||||
String trxName = null; // outside trx if on server
|
||||
if (MClient.isClientAccounting())
|
||||
trxName = getTrxName(); // on trx if it's in client
|
||||
StringBuffer sql = new StringBuffer ("UPDATE ");
|
||||
sql.append(get_TableName()).append( " SET Processing='Y' WHERE ")
|
||||
.append(get_TableName()).append("_ID=").append(get_ID())
|
||||
|
@ -564,7 +568,7 @@ public abstract class Doc
|
|||
sql.append(" AND (Processing='N' OR Processing IS NULL)");
|
||||
if (!repost)
|
||||
sql.append(" AND Posted='N'");
|
||||
if (DB.executeUpdate(sql.toString(), null) == 1) // outside trx
|
||||
if (DB.executeUpdate(sql.toString(), trxName) == 1)
|
||||
log.info("Locked: " + get_TableName() + "_ID=" + get_ID());
|
||||
else
|
||||
{
|
||||
|
@ -646,7 +650,7 @@ public abstract class Doc
|
|||
|
||||
String validatorMsg = null;
|
||||
// Call validator on before post
|
||||
if (!p_Status.equals(STATUS_Error)) {
|
||||
if (p_Status.equals(STATUS_Posted)) {
|
||||
validatorMsg = ModelValidationEngine.get().fireDocValidate(getPO(), ModelValidator.TIMING_BEFORE_POST);
|
||||
if (validatorMsg != null) {
|
||||
p_Status = STATUS_Error;
|
||||
|
@ -658,7 +662,7 @@ public abstract class Doc
|
|||
// commitFact
|
||||
p_Status = postCommit (p_Status);
|
||||
|
||||
if (!p_Status.equals(STATUS_Error)) {
|
||||
if (p_Status.equals(STATUS_Posted)) {
|
||||
validatorMsg = ModelValidationEngine.get().fireDocValidate(getPO(), ModelValidator.TIMING_AFTER_POST);
|
||||
if (validatorMsg != null) {
|
||||
p_Status = STATUS_Error;
|
||||
|
@ -693,6 +697,7 @@ public abstract class Doc
|
|||
.append(", Balanced=").append(isBalanced());
|
||||
note.setTextMsg(Text.toString());
|
||||
note.save();
|
||||
p_Error = Text.toString();
|
||||
}
|
||||
|
||||
// dispose facts
|
||||
|
@ -1053,7 +1058,7 @@ public abstract class Doc
|
|||
Iterator<Integer> it = set.iterator();
|
||||
while (it.hasNext() && convertible)
|
||||
{
|
||||
int C_Currency_ID = ((Integer)it.next()).intValue();
|
||||
int C_Currency_ID = it.next().intValue();
|
||||
if (C_Currency_ID != acctSchema.getC_Currency_ID())
|
||||
{
|
||||
BigDecimal amt = MConversionRate.getRate (C_Currency_ID, acctSchema.getC_Currency_ID(),
|
||||
|
|
|
@ -56,8 +56,7 @@ public class MClient extends X_AD_Client
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = -295299248474003249L;
|
||||
|
||||
private static final long serialVersionUID = -6345228636481802120L;
|
||||
|
||||
/**
|
||||
* Get client
|
||||
|
@ -890,7 +889,7 @@ public class MClient extends X_AD_Client
|
|||
if (server != null)
|
||||
{ // See ServerBean
|
||||
if (html && message != null)
|
||||
message = email.HTML_MAIL_MARKER + message;
|
||||
message = EMail.HTML_MAIL_MARKER + message;
|
||||
email = server.createEMail(Env.getRemoteCallCtx(getCtx()), getAD_Client_ID(),
|
||||
from.getAD_User_ID(),
|
||||
to, subject, message);
|
||||
|
@ -914,4 +913,38 @@ public class MClient extends X_AD_Client
|
|||
return email;
|
||||
} // createEMail
|
||||
|
||||
/*
|
||||
* Is Client Accounting enabled?
|
||||
* CLIENT_ACCOUNTING parameter allow the next values
|
||||
* D - Disabled (default)
|
||||
* Q - Queue (enabled to post by hand - queue documents for posterior processing)
|
||||
* I - Immediate (immediate post - allow complete on errors)
|
||||
*
|
||||
* @return boolean representing if client accounting is enabled and it's on a client
|
||||
*/
|
||||
private static final String CLIENT_ACCOUNTING_DISABLED = "D";
|
||||
private static final String CLIENT_ACCOUNTING_QUEUE = "Q";
|
||||
private static final String CLIENT_ACCOUNTING_IMMEDIATE = "I";
|
||||
|
||||
public static boolean isClientAccounting() {
|
||||
String ca = MSysConfig.getValue("CLIENT_ACCOUNTING",
|
||||
CLIENT_ACCOUNTING_DISABLED, // default
|
||||
Env.getAD_Client_ID(Env.getCtx()));
|
||||
return (ca.equalsIgnoreCase(CLIENT_ACCOUNTING_IMMEDIATE) || ca.equalsIgnoreCase(CLIENT_ACCOUNTING_QUEUE));
|
||||
}
|
||||
|
||||
public static boolean isClientAccountingQueue() {
|
||||
String ca = MSysConfig.getValue("CLIENT_ACCOUNTING",
|
||||
CLIENT_ACCOUNTING_DISABLED, // default
|
||||
Env.getAD_Client_ID(Env.getCtx()));
|
||||
return ca.equalsIgnoreCase(CLIENT_ACCOUNTING_QUEUE);
|
||||
}
|
||||
|
||||
public static boolean isClientAccountingImmediate() {
|
||||
String ca = MSysConfig.getValue("CLIENT_ACCOUNTING",
|
||||
CLIENT_ACCOUNTING_DISABLED, // default
|
||||
Env.getAD_Client_ID(Env.getCtx()));
|
||||
return ca.equalsIgnoreCase(CLIENT_ACCOUNTING_IMMEDIATE);
|
||||
}
|
||||
|
||||
} // MClient
|
||||
|
|
|
@ -39,7 +39,7 @@ public class MFactAcct extends X_Fact_Acct
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 5251847162314796574L;
|
||||
private static final long serialVersionUID = 756203818233903671L;
|
||||
|
||||
/**
|
||||
* Delete Accounting
|
||||
|
@ -135,4 +135,19 @@ public class MFactAcct extends X_Fact_Acct
|
|||
return acct;
|
||||
} // getMAccount
|
||||
|
||||
/**
|
||||
* Check if a document is already posted
|
||||
* @param AD_Table_ID table
|
||||
* @param Record_ID record
|
||||
* @param trxName transaction
|
||||
* @return boolean indicating if the document has already accounting facts
|
||||
* @throws DBException on database exception
|
||||
*/
|
||||
public static boolean alreadyPosted(int AD_Table_ID, int Record_ID, String trxName) throws DBException
|
||||
{
|
||||
final String sql = "SELECT 1 FROM Fact_Acct WHERE AD_Table_ID=? AND Record_ID=?";
|
||||
int one = DB.getSQLValue(trxName, sql, new Object[]{AD_Table_ID, Record_ID}, trxName);
|
||||
return (one == 1);
|
||||
}
|
||||
|
||||
} // MFactAcct
|
||||
|
|
|
@ -26,8 +26,10 @@ import java.util.Properties;
|
|||
import java.util.Vector;
|
||||
import java.util.logging.Level;
|
||||
|
||||
import org.compiere.acct.Doc;
|
||||
import org.compiere.db.CConnection;
|
||||
import org.compiere.interfaces.Server;
|
||||
import org.compiere.model.MAcctSchema;
|
||||
import org.compiere.model.MAllocationHdr;
|
||||
import org.compiere.model.MBankStatement;
|
||||
import org.compiere.model.MCash;
|
||||
|
@ -458,25 +460,9 @@ public class DocumentEngine implements DocAction
|
|||
if (!isValidAction(ACTION_Post)
|
||||
|| m_document == null)
|
||||
return false;
|
||||
try
|
||||
{
|
||||
// Should work on Client and Server
|
||||
Server server = CConnection.get().getServer();
|
||||
if (server != null)
|
||||
{
|
||||
String error = server.postImmediate(Env.getRemoteCallCtx(Env.getCtx()),
|
||||
m_document.getAD_Client_ID(),
|
||||
m_document.get_Table_ID(), m_document.get_ID(),
|
||||
true, null);
|
||||
m_document.get_Logger().config("Server: " + error == null ? "OK" : error);
|
||||
return error == null;
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_document.get_Logger().config("(ex) " + e.getMessage());
|
||||
}
|
||||
return false;
|
||||
|
||||
String error = DocumentEngine.postImmediate(Env.getCtx(), m_document.getAD_Client_ID(), m_document.get_Table_ID(), m_document.get_ID(), true, m_document.get_TrxName());
|
||||
return (error == null);
|
||||
} // postIt
|
||||
|
||||
/**
|
||||
|
@ -1227,4 +1213,56 @@ public class DocumentEngine implements DocAction
|
|||
}
|
||||
return validOptions.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Post Immediate
|
||||
*
|
||||
* @param ctx Client Context
|
||||
* @param AD_Client_ID Client ID of Document
|
||||
* @param AD_Table_ID Table ID of Document
|
||||
* @param Record_ID Record ID of this document
|
||||
* @param force force posting
|
||||
* @param trxName ignore, retained for backward compatibility
|
||||
* @return null, if success or error message
|
||||
*/
|
||||
public static String postImmediate (Properties ctx,
|
||||
int AD_Client_ID, int AD_Table_ID, int Record_ID, boolean force, String trxName)
|
||||
{
|
||||
String error = null;
|
||||
if (MClient.isClientAccounting()) {
|
||||
log.info ("Table=" + AD_Table_ID + ", Record=" + Record_ID);
|
||||
MAcctSchema[] ass = MAcctSchema.getClientAcctSchema(ctx, AD_Client_ID);
|
||||
error = Doc.postImmediate(ass, AD_Table_ID, Record_ID, force, trxName);
|
||||
return error;
|
||||
}
|
||||
|
||||
// try to get from Server when enabled
|
||||
if (CConnection.get().isAppsServerOK(true))
|
||||
{
|
||||
log.config("trying server");
|
||||
try
|
||||
{
|
||||
Server server = CConnection.get().getServer();
|
||||
if (server != null)
|
||||
{
|
||||
Properties p = Env.getRemoteCallCtx(Env.getCtx());
|
||||
error = server.postImmediate(p, AD_Client_ID,
|
||||
AD_Table_ID, Record_ID, force, null); // don't pass transaction to server
|
||||
log.config("from Server: " + error== null ? "OK" : error);
|
||||
}
|
||||
else
|
||||
{
|
||||
error = "NoAppsServer";
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.WARNING, "(RE)", e);
|
||||
error = e.getMessage();
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
} // postImmediate
|
||||
|
||||
} // DocumentEnine
|
||||
|
|
|
@ -31,13 +31,12 @@ import java.util.StringTokenizer;
|
|||
import java.util.logging.Level;
|
||||
|
||||
import org.adempiere.exceptions.AdempiereException;
|
||||
import org.compiere.db.CConnection;
|
||||
import org.compiere.interfaces.Server;
|
||||
import org.compiere.model.MAttachment;
|
||||
import org.compiere.model.MBPartner;
|
||||
import org.compiere.model.MClient;
|
||||
import org.compiere.model.MColumn;
|
||||
import org.compiere.model.MConversionRate;
|
||||
import org.compiere.model.MFactAcct;
|
||||
import org.compiere.model.MMailText;
|
||||
import org.compiere.model.MNote;
|
||||
import org.compiere.model.MOrg;
|
||||
|
@ -55,9 +54,9 @@ import org.compiere.model.Query;
|
|||
import org.compiere.model.X_AD_WF_Activity;
|
||||
import org.compiere.print.ReportEngine;
|
||||
import org.compiere.process.DocAction;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
import org.compiere.process.ProcessInfo;
|
||||
import org.compiere.process.StateEngine;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DisplayType;
|
||||
import org.compiere.util.Env;
|
||||
import org.compiere.util.Msg;
|
||||
|
@ -78,8 +77,7 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable
|
|||
/**
|
||||
*
|
||||
*/
|
||||
private static final long serialVersionUID = 2104882570953130237L;
|
||||
|
||||
private static final long serialVersionUID = 1584816335412184476L;
|
||||
|
||||
/**
|
||||
* Get Activities for table/record
|
||||
|
@ -898,10 +896,10 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable
|
|||
throw e;
|
||||
}
|
||||
// Post Immediate
|
||||
if (success && DocAction.ACTION_Complete.equals(m_node.getDocAction()))
|
||||
if (success && DocAction.STATUS_Completed.equals(doc.getDocStatus()) && DocAction.ACTION_Complete.equals(m_node.getDocAction()))
|
||||
{
|
||||
MClient client = MClient.get(doc.getCtx(), doc.getAD_Client_ID());
|
||||
if (client.isPostImmediate())
|
||||
if (client.isPostImmediate() || MClient.isClientAccountingImmediate())
|
||||
m_postImmediate = doc;
|
||||
}
|
||||
//
|
||||
|
@ -1504,30 +1502,13 @@ public class MWFActivity extends X_AD_WF_Activity implements Runnable
|
|||
*/
|
||||
private void postImmediate()
|
||||
{
|
||||
if (CConnection.get().isAppsServerOK(false))
|
||||
{
|
||||
try
|
||||
{
|
||||
Server server = CConnection.get().getServer();
|
||||
if (server != null)
|
||||
{
|
||||
String error = server.postImmediate(Env.getRemoteCallCtx(Env.getCtx()),
|
||||
m_postImmediate.getAD_Client_ID(),
|
||||
m_postImmediate.get_Table_ID(), m_postImmediate.get_ID(),
|
||||
true, null);
|
||||
m_postImmediate.get_Logger().config("Server: " + error == null ? "OK" : error);
|
||||
if (MFactAcct.alreadyPosted(m_postImmediate.get_Table_ID(), m_postImmediate.get_ID(), m_postImmediate.get_TrxName()))
|
||||
return;
|
||||
}
|
||||
else
|
||||
m_postImmediate.get_Logger().config("NoAppsServer");
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
m_postImmediate.get_Logger().config("(RE) " + e.getMessage());
|
||||
}
|
||||
}
|
||||
} // PostImmediate
|
||||
|
||||
String error = DocumentEngine.postImmediate(m_postImmediate.getCtx(),
|
||||
m_postImmediate.getAD_Client_ID(), m_postImmediate.get_Table_ID(), m_postImmediate.get_ID(), true,
|
||||
m_postImmediate.get_TrxName());
|
||||
} // PostImmediate
|
||||
|
||||
/*********************************
|
||||
* Send EMail
|
||||
|
|
|
@ -51,6 +51,7 @@ import org.compiere.model.GridWindowVO;
|
|||
import org.compiere.model.MMenu;
|
||||
import org.compiere.model.MQuery;
|
||||
import org.compiere.model.MRole;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
import org.compiere.swing.CButton;
|
||||
import org.compiere.swing.CFrame;
|
||||
import org.compiere.swing.CMenuItem;
|
||||
|
@ -898,40 +899,8 @@ public final class AEnv
|
|||
+ ", AD_Table_ID=" + AD_Table_ID + "/" + Record_ID
|
||||
+ ", Force=" + force);
|
||||
|
||||
String error = null;
|
||||
// try to get from Server when enabled
|
||||
if (isServerActive())
|
||||
{
|
||||
log.config("trying server");
|
||||
try
|
||||
{
|
||||
s_server = CConnection.get().getServer();
|
||||
if (s_server != null)
|
||||
{
|
||||
error = s_server.postImmediate(Env.getCtx(), AD_Client_ID,
|
||||
AD_Table_ID, Record_ID, force, null);
|
||||
log.config("from Server: " + error== null ? "OK" : error);
|
||||
}
|
||||
else
|
||||
{
|
||||
ADialog.error(WindowNo, null, "NoAppsServer");
|
||||
return "NoAppsServer";
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.WARNING, "(RE)", e);
|
||||
error = e.getMessage();
|
||||
if (error == null)
|
||||
error = "Exception: " + e.toString();
|
||||
s_server = null;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ADialog.error(WindowNo, null, "NoAppsServer");
|
||||
return "NoAppsServer";
|
||||
}
|
||||
String error = DocumentEngine.postImmediate(Env.getCtx(), AD_Client_ID, AD_Table_ID, Record_ID, force, null);
|
||||
|
||||
return error;
|
||||
} // postImmediate
|
||||
|
||||
|
|
|
@ -0,0 +1,5 @@
|
|||
-- Sep 13, 2009 5:37:29 PM COT
|
||||
-- FR2857807-Allow accounting posting in standalone user mode
|
||||
INSERT INTO AD_SysConfig (AD_Client_ID,AD_Org_ID,AD_SysConfig_ID,ConfigurationLevel,Created,CreatedBy,Description,EntityType,IsActive,Name,Updated,UpdatedBy,Value) VALUES (0,0,50034,'C',TO_DATE('2009-09-13 17:37:28','YYYY-MM-DD HH24:MI:SS'),100,'Enable client Accounting -> D - Disabled (default) / Q - Queue (enabled to post by hand - queue documents for posterior processing) / I - Immediate (immediate post)','D','Y','CLIENT_ACCOUNTING',TO_DATE('2009-09-13 17:37:28','YYYY-MM-DD HH24:MI:SS'),100,'D')
|
||||
;
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
-- Sep 13, 2009 5:37:29 PM COT
|
||||
-- FR2857807-Allow accounting posting in standalone user mode
|
||||
INSERT INTO AD_SysConfig (AD_Client_ID,AD_Org_ID,AD_SysConfig_ID,ConfigurationLevel,Created,CreatedBy,Description,EntityType,IsActive,Name,Updated,UpdatedBy,Value) VALUES (0,0,50034,'C',TO_TIMESTAMP('2009-09-13 17:37:28','YYYY-MM-DD HH24:MI:SS'),100,'Enable client Accounting -> D - Disabled (default) / Q - Queue (enabled to post by hand - queue documents for posterior processing) / I - Immediate (immediate post)','D','Y','CLIENT_ACCOUNTING',TO_TIMESTAMP('2009-09-13 17:37:28','YYYY-MM-DD HH24:MI:SS'),100,'D')
|
||||
;
|
||||
|
|
@ -38,13 +38,13 @@ import javax.servlet.ServletRequest;
|
|||
|
||||
import org.adempiere.webui.component.Window;
|
||||
import org.adempiere.webui.session.SessionManager;
|
||||
import org.adempiere.webui.window.FDialog;
|
||||
import org.compiere.apps.ALogin;
|
||||
import org.compiere.db.CConnection;
|
||||
import org.compiere.interfaces.Server;
|
||||
import org.compiere.model.GridWindowVO;
|
||||
import org.compiere.model.Lookup;
|
||||
import org.compiere.model.MQuery;
|
||||
import org.compiere.process.DocumentEngine;
|
||||
import org.compiere.util.CCache;
|
||||
import org.compiere.util.CLogger;
|
||||
import org.compiere.util.DB;
|
||||
|
@ -340,40 +340,9 @@ public final class AEnv
|
|||
+ ", AD_Table_ID=" + AD_Table_ID + "/" + Record_ID
|
||||
+ ", Force=" + force);
|
||||
|
||||
String error = null;
|
||||
// try to get from Server when enabled
|
||||
if (isServerActive())
|
||||
{
|
||||
log.config("trying server");
|
||||
try
|
||||
{
|
||||
Server server = CConnection.get().getServer();
|
||||
if (server != null)
|
||||
{
|
||||
Properties p = Env.getRemoteCallCtx(Env.getCtx());
|
||||
error = server.postImmediate(p, AD_Client_ID,
|
||||
AD_Table_ID, Record_ID, force, null);
|
||||
log.config("from Server: " + error== null ? "OK" : error);
|
||||
}
|
||||
else
|
||||
{
|
||||
FDialog.error(WindowNo, "", "NoApps Server");
|
||||
return "NoAppsServer";
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
log.log(Level.WARNING, "(RE)", e);
|
||||
error = e.getMessage();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FDialog.error(WindowNo, "", "NoAppsServer");
|
||||
return "NoAppsServer";
|
||||
}
|
||||
return error;
|
||||
String error = DocumentEngine.postImmediate(Env.getCtx(), AD_Client_ID, AD_Table_ID, Record_ID, force, null);
|
||||
|
||||
return error;
|
||||
} // postImmediate
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue