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:
Carlos Ruiz 2009-09-13 22:41:51 +00:00
parent 7147bcda2d
commit 69920ace55
9 changed files with 150 additions and 130 deletions

View File

@ -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)
@ -539,7 +540,7 @@ public abstract class Doc
{
if (m_DocStatus == null)
; // return "No DocStatus for DocumentNo=" + getDocumentNo();
else if (m_DocStatus.equals(DocumentEngine.STATUS_Completed)
else if (m_DocStatus.equals(DocumentEngine.STATUS_Completed)
|| m_DocStatus.equals(DocumentEngine.STATUS_Closed)
|| m_DocStatus.equals(DocumentEngine.STATUS_Voided)
|| m_DocStatus.equals(DocumentEngine.STATUS_Reversed))
@ -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(),

View File

@ -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);
@ -912,6 +911,40 @@ public class MClient extends X_AD_Client
if (isSmtpAuthorization())
email.createAuthenticator (from.getEMailUser(), from.getEMailUserPW());
return email;
} // createEMail
} // 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

View File

@ -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
@ -134,5 +134,20 @@ public class MFactAcct extends X_Fact_Acct
acct.save();
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

View File

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

View File

@ -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,31 +1502,14 @@ 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);
return;
}
else
m_postImmediate.get_Logger().config("NoAppsServer");
}
catch (Exception e)
{
m_postImmediate.get_Logger().config("(RE) " + e.getMessage());
}
}
if (MFactAcct.alreadyPosted(m_postImmediate.get_Table_ID(), m_postImmediate.get_ID(), m_postImmediate.get_TrxName()))
return;
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
*/

View File

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

View File

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

View File

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

View File

@ -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;
@ -339,41 +339,10 @@ public final class AEnv
log.config("Window=" + WindowNo
+ ", AD_Table_ID=" + AD_Table_ID + "/" + Record_ID
+ ", Force=" + force);
String error = DocumentEngine.postImmediate(Env.getCtx(), AD_Client_ID, AD_Table_ID, Record_ID, force, null);
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;
} // postImmediate
/**