Difference between revisions of "User:Trifonnt/Howtos Hints"
(Created page with '==== Show where products are located ==== Submitted By: Jan Kantert (jab_doa) Summary: Show where products are located sf.net tracker: [https://sourceforge.net/tracker/?func=de…') |
(No difference)
|
Revision as of 06:09, 20 July 2010
Contents
- 1 Show where products are located
- 2 Security
- 3 Bank Transfer tips
- 4 Listing a BOM within a BOM
- 5 User authentication in Adempiere using LDAP
- 6 Add OnHandQty In Product window
- 7 How to setup Workflow for PO Approval?
- 8 Workflow Simple approval
- 9 Workflow Dynamic approval
- 10 Changelog functionality
- 11 Securing JBoss JMX Console and Web Console
- 12 SECURE SCENARIO to use Adempiere
- 13 Product Attribute Instance - Color/Size/Serial number
- 14 Material transaction between two organizations
- 15 Maintain multiple environments(Postgre multiple schema managing)
- 16 PostgreSQL Materialized Views
- 17 Report sales figures by product
- 18 How to monitor Oracle sessions?
- 19 How to get Oracle Character set?
- 20 How to change document numbers?
- 21 Where to place JasperReport files?
- 22 How to handle imprests?
- 23 How to process credit card payments from Java GUI?
- 24 How to add comment on printed Invoice?
- 25 BOM price explained.
- 26 How to enable Multilingual documents?
- 27 How Cost centers are implemented in Adempiere?
- 28 How to setup Extended Document Number Formatting?
- 29 How to list General Ledger Transactions?
- 30 How to setup Manufacturing process
- 31 How to Merge Business Partner entities?
- 32 How to display Key and Name?
- 33 How to Delete Client/Tenant
- 34 init.d for centOS
- 35 Sql which set QtyInvoice = QtyOrdered for given Organization.
- 36 How to translate root menu in Ademepire Swing GUI?
- 37 How to translate root menu in Ademepire Zk Web UI?
- 38 How to fix issue: Active workflow for this record exists?
- 39 How to setup embedded tab?
- 40 How to enter Payment from BP to another BP?
- 41 Location of Documantation Chapters?
- 42 Description of Dunning in ADempiere
- 43 Developer hints
- 43.1 Hint-1; UPDATE columns which must have default value or have checked constraint
- 43.2 Hint-2; Be carefull when creating VIEWS
- 43.3 Hint-3; Java on Ubuntu
- 43.4 Hint-4; How to truncate timestamp
- 43.5 Hint-5; How to use MTable.get(..) and MTable.getPO(..)
- 43.6 Subversion Access
- 43.7 MFG
- 43.8 Template Process and steps to create a process
- 43.9 Migration with SQL statements - Oracle - AD_Element
- 43.10 Migration with SQL statements - Oracle - AD_Table
- 43.11 Migration with SQL statements - Oracle - AD_Column
- 43.12 Migration with SQL statements - Oracle - AD_Window
- 43.13 Migration with SQL statements - Oracle - AD_Tab
- 43.14 Migration with SQL statements - Oracle - AD_Field
- 43.15 Migration with SQL statements - Oracle - AD_Menu
- 43.16 Migration with SQL statements - Oracle - AD_TreeNodeMM
- 43.17 Migration with SQL statements - AD_Message
- 43.18 Migration with SQL statements - AD_Process_Para
- 43.19 Migration with SQL statements - AD_Ref_List - Postgre
- 43.20 Session_IsChangeLog, AD_Table.IsChangeLog, AD_Column.IsChangeLog combination
- 43.21 How to use Transactions and Save points in Adempiere
- 43.22 How to build Adempiere customization.jar
- 43.23 How to Open Window from source code?
- 43.24 How to keep parameter window open after view report?
- 43.25 How to create confirmation for inventory move?
- 43.26 How to make Adempiere LDAP username registration compatible with OpenLDAP
- 43.27 How to use JSR 223: Scripting callouts in Adempiere?
- 43.28 How to get Adempiere/Compiere Home from java class?
- 43.29 How to set/update column ModelValidationClasses
- 43.30 How to use Adempiere sequence from java code?
- 43.31 How to setup Adempiere ZK Development Environment
- 43.32 How to add new tab to Info Window
- 43.33 How to copy print format and how to invoke print preview from java?
- 43.34 Some views
- 43.35 How to call stored procedure from java?
- 43.36 How to add Value column to Existing Adempiere table?
- 43.37 How to speedup Record Change Log?
- 43.38 Log management in Adempiere?
- 43.39 Adempiere initiative: Remove SQL code and Replace with Query class!
- 43.40 How to use Adempiere Query class?
- 43.41 How to use Adempiere MQuery class?
- 43.42 Adempiere utility classes?
- 43.43 Base Language functionality
- 43.44 Differences in source code between Adempiere 3.5.0 and Compiere 3.0.0
- 43.45 Keeping sources compatible with Adempiere 3.5.0 and Compiere 3.0.0
- 43.46 How to Validate conditional mandatory field?
- 43.47 How to enable Query TimeOut in Adempiere?
- 43.48 How to decrease number of log files created by Java WebStart?
- 43.49 How to post accounting transactions without Application Server?
- 44 License to use for new classes
- 45 How to add new Actions to Document Engine
- 46 Adempiere Export/Import Tools
- 47 Ideas for extensions
- 48 Recent Adempiere changes
- 49 Reorganization of Adempiere menu
- 50 How to add chache suport for persistent class?
- 51 Hint for Defining Oracle View
Show where products are located
Submitted By: Jan Kantert (jab_doa)
Summary: Show where products are located
sf.net tracker: here
Initial Comment:
Log in as System Administrator. Select "Application Dictionary" -> "Window, Tab & Field" -> Name = Product
Click on "Tab". Go to the end of the list and add a new row. Zoom in and set Table to "M_Storage_M_Storage", Name to "Located at", Description to "Where are my units located?", Tab Level to "2" and check "read only". Now save and click on "Create Fields". Thats it. Now you can see where your units are when zooming into a product.
Security
Submitted By: Armen (armenrz)
Summary: Security
sf.net tracker: here
1) ADempiere support role based security - Role window.
2) Role Data Access. You can also play around with SQLWhere in Window, Tab & Field.
Example: (instr('@#User_Level@','C')<>0 OR C_BPartner.CreatedBy=@#AD_user_ID@ OR C_BPartner.SalesRep_ID=@#AD_User_ID@)
For pricelist, there's one place you can't hide price from user, which is Product Info. You need to modify some codes to do this. What I did is add IsCanViewPrice option in Role so now each role can be set either they can view price or not.
Bank Transfer tips
Submitted By: usman88
Summary: Bank Transfer tips
sf.net tracker: here
Small tips to handle 1 source Bank to 1 recipient Bank transfer transaction.
1. Create new cash journal.
2. Select appropriate cash book ( in my case i use dummy cash book to serve this transaction)
3. Next go to cash line and create a new line and select cash type as bank transfer.
4. Then select source bank account and type in transfer amount
5. Create 2nd line as in step 3.
6. This time select recipient bank account and type in transfer amount but in negative sign.
7. Back to cash journal tab, complete and post it.
8. To finalize it create, complete and post Bank statement for each bank account.
PS. Above tips can be use for more complex scenario such as transfer from 2 bank to 1 recipient.
Listing a BOM within a BOM
Submitted By: stingreye
Summary: Listing a BOM within a BOM
sf.net tracker: here
Here is the view in Oracle... Because we have so many parts we ended up doing a materialized view that we update with a process in Compiere everytime we
change
a BOM. We did that so we could report off of this view faster.
I am sure someone out here could write a much better query than this but here is what I did. Basically, created a view on top of itself so that the parent records would null. Then used the connect by clause to generate the hierarchy. You will also notice the use of connect_by_root = Top level of bill. Connect_by_ISLEAF = bottom level of bill. Level = what level of the hierarchy.
CREATE OR REPLACE VIEW BOM_INDENTED (TOPLEVELID, TOPLEVEL, TOPLEVEL_DESC, PRODUCTNUM, PRODDEC, M_PRODUCTBOM_ID, BOM_LEVEL, BOMQTY, DESCRIPTION, AD_CLIENT_ID, AD_ORG_ID, ROWNUMBER, BOM_LEVEL_NUM, BOTTOMCOMPONENT) AS SELECT CONNECT_BY_ROOT M_ProductBom_ID AS TOPLEVELID,CONNECT_BY_ROOT Value AS TOPLEVEL,CONNECT_BY_ROOT b.DESCRIPTION AS TOPLEVEL_DESC, Value AS ProductNum, b.DESCRIPTION AS ProdDesc, M_PRODUCTBOM_ID,LPAD(' ',2*(LEVEL-1)) || TO_CHAR(LEVEL) BOM_Level, BOMQTY, a.DESCRIPTION,a.AD_CLIENT_ID, a.AD_ORG_ID, ROWNUM, LEVEL, Connect_By_ISLEAF FROM -- part 2 subquerry combining top level and bom to create null to start from ( SELECT "M_PRODUCT_BOM_ID","AD_CLIENT_ID","AD_ORG_ID","ISACTIVE",--"CREATED","C REATEDBY","UPDATED","UPDATEDBY", (remove becuase unnnecessarry) "LINE","M_PRODUCT_ID","M_PRODUCTBOM_ID","BOMQTY","DESCRIPTION","BOMTYPE" FROM M_PRODUCT_BOM UNION -- part 1 the tope level querry creating the nulls that is combined in part 2 SELECT M_PRODUCT_BOM_1.M_PRODUCT_BOM_ID, M_PRODUCT_BOM.AD_CLIENT_ID, M_PRODUCT_BOM.AD_ORG_ID, M_PRODUCT_BOM_1.ISACTIVE,-- M_PRODUCT_BOM_1.CREATED, M_PRODUCT_BOM_1.CREATEDBY, M_PRODUCT_BOM_1.UPDATED, M_PRODUCT_BOM_1.UPDATEDBY, (removed unnecessary) M_PRODUCT_BOM_1.LINE,M_PRODUCT_BOM_1.M_PRODUCTBOM_ID AS M_PRODUCT_ID, M_PRODUCT_BOM.M_PRODUCT_ID AS M_PRODUCTBOM_ID, M_PRODUCT_BOM_1.BOMQTY, M_PRODUCT_BOM_1.DESCRIPTION, M_PRODUCT_BOM_1.BOMTYPE FROM M_PRODUCT_BOM LEFT JOIN M_PRODUCT_BOM M_PRODUCT_BOM_1 ON M_PRODUCT_BOM.M_PRODUCT_ID = M_PRODUCT_BOM_1.M_PRODUCTBOM_ID GROUP BY M_PRODUCT_BOM_1.M_PRODUCT_BOM_ID, M_PRODUCT_BOM.AD_CLIENT_ID, M_PRODUCT_BOM.AD_ORG_ID, M_PRODUCT_BOM_1.ISACTIVE, M_PRODUCT_BOM_1.CREATED, M_PRODUCT_BOM_1.CREATEDBY, M_PRODUCT_BOM_1.UPDATED, M_PRODUCT_BOM_1.UPDATEDBY, M_PRODUCT_BOM_1.LINE, M_PRODUCT_BOM.M_PRODUCT_ID, M_PRODUCT_BOM_1.M_PRODUCTBOM_ID, M_PRODUCT_BOM_1.BOMQTY, M_PRODUCT_BOM_1.DESCRIPTION, M_PRODUCT_BOM_1.BOMTYPE HAVING (((M_PRODUCT_BOM_1.M_PRODUCTBOM_ID) IS NULL))) a -- part 3 continued INNER JOIN M_PRODUCT b ON a.M_PRODUCTBOM_ID = b.M_PRODUCT_ID START WITH a.M_PRODUCT_ID IS NULL CONNECT BY PRIOR M_PRODUCTBOM_ID = a.M_PRODUCT_ID ORDER SIBLINGS BY b.Value /
If you want to use materialized views... we did it the following way (I really know very little about them, so if someone has a better idea of how to use them for this, it would be appreciated) The materialized view would be
CREATE MATERIALIZED VIEW BOM_INDENTED_MV (PTX_Path,TOPLEVELID, TOPLEVEL, TOPLEVEL_DESC, PRODUCTNUM, PRODDEC, M_PRODUCTBOM_ID, BOM_LEVEL, BOMQTY, DESCRIPTION, AD_CLIENT_ID, AD_ORG_ID, BOM_LEVEL_NUM, BOTTOMCOMPONENT,TOPLEVEL_ISACTIVE, COMP_ISACTIVE, TOP_Client) Build IMMEDIATE REFRESH ON DEMAND DISABLE QUERY REWRITE AS SELECT Path, TOPLEVELID,TOPLEVEL,TOPLEVEL_DESC, ProductNum, ProdDesc, M_PRODUCTBOM_ID, BOM_Level, BOMQTY, f1.DESCRIPTION,mp2.AD_CLIENT_ID, mp2.AD_ORG_ID, BomLevelNum, BottomComponent, MP.ISACTIVE AS TOPLEV_ISACTIVE, MP2.ISACTIVE AS COMP_ISACTIVE, mp.AD_CLIENT_ID AS TOPLEVEL_Client FROM ( SELECT DISTINCT SYS_CONNECT_BY_PATH (M_PRODUCTBOM_ID,'/') AS Path, CONNECT_BY_ROOT M_ProductBom_ID AS TOPLEVELID,CONNECT_BY_ROOT Value AS TOPLEVEL,CONNECT_BY_ROOT b.DESCRIPTION AS TOPLEVEL_DESC, Value AS ProductNum, b.DESCRIPTION AS ProdDesc, M_PRODUCTBOM_ID,LPAD(' ',2*(LEVEL-1)) || TO_CHAR(LEVEL) BOM_Level, BOMQTY, a.DESCRIPTION,a.AD_CLIENT_ID, a.AD_ORG_ID, LEVEL AS BomLevelNum, Connect_By_ISLEAF AS BottomComponent FROM -- part 2 subquerry combining top level and bom to create null to start from ( SELECT "M_PRODUCT_BOM_ID","AD_CLIENT_ID","AD_ORG_ID","ISACTIVE",--"CREATED","C REATEDBY","UPDATED","UPDATEDBY", (remove becuase unnnecessarry) "LINE","M_PRODUCT_ID","M_PRODUCTBOM_ID","BOMQTY","DESCRIPTION","BOMTYPE" FROM M_PRODUCT_BOM UNION -- part 1 the tope level querry creating the nulls that is combined in part 2 SELECT M_PRODUCT_BOM_1.M_PRODUCT_BOM_ID, M_PRODUCT_BOM.AD_CLIENT_ID, M_PRODUCT_BOM.AD_ORG_ID, M_PRODUCT_BOM_1.ISACTIVE,-- M_PRODUCT_BOM_1.CREATED, M_PRODUCT_BOM_1.CREATEDBY, M_PRODUCT_BOM_1.UPDATED, M_PRODUCT_BOM_1.UPDATEDBY, (removed unnecessary) M_PRODUCT_BOM_1.LINE,M_PRODUCT_BOM_1.M_PRODUCTBOM_ID AS M_PRODUCT_ID, M_PRODUCT_BOM.M_PRODUCT_ID AS M_PRODUCTBOM_ID, M_PRODUCT_BOM_1.BOMQTY, M_PRODUCT_BOM_1.DESCRIPTION, M_PRODUCT_BOM_1.BOMTYPE FROM M_PRODUCT_BOM LEFT JOIN M_PRODUCT_BOM M_PRODUCT_BOM_1 ON M_PRODUCT_BOM.M_PRODUCT_ID = M_PRODUCT_BOM_1.M_PRODUCTBOM_ID GROUP BY M_PRODUCT_BOM_1.M_PRODUCT_BOM_ID, M_PRODUCT_BOM.AD_CLIENT_ID, M_PRODUCT_BOM.AD_ORG_ID, M_PRODUCT_BOM_1.ISACTIVE, M_PRODUCT_BOM_1.CREATED, M_PRODUCT_BOM_1.CREATEDBY, M_PRODUCT_BOM_1.UPDATED, M_PRODUCT_BOM_1.UPDATEDBY, M_PRODUCT_BOM_1.LINE, M_PRODUCT_BOM.M_PRODUCT_ID, M_PRODUCT_BOM_1.M_PRODUCTBOM_ID, M_PRODUCT_BOM_1.BOMQTY, M_PRODUCT_BOM_1.DESCRIPTION, M_PRODUCT_BOM_1.BOMTYPE HAVING (((M_PRODUCT_BOM_1.M_PRODUCTBOM_ID) IS NULL))) a -- part 3 continued INNER JOIN M_PRODUCT b ON a.M_PRODUCTBOM_ID = b.M_PRODUCT_ID START WITH a.M_PRODUCT_ID IS NULL CONNECT BY PRIOR M_PRODUCTBOM_ID = a.M_PRODUCT_ID ORDER SIBLINGS BY b.Value ) f1 INNER JOIN M_PRODUCT mp ON TOPLEVELID=mp.M_PRODUCT_ID INNER JOIN M_PRODUCT mp2 ON M_PRODUCTBOM_ID = mp2.M_PRODUCT_ID ORDER BY Path /
Then to refresh the materialize view we used the following database procedure where we used a parameter in the "report process" window to identify which MV to refresh:
CREATE OR REPLACE PROCEDURE Indented_Bom_Mv_Refresh ( PInstance_ID IN NUMBER ) AS -- Logistice ResultStr VARCHAR2(2000); Message VARCHAR2(2000); Record_ID NUMBER; -- Parameter CURSOR Cur_Parameter (PInstance NUMBER) IS SELECT i.Record_ID, p.ParameterName, p.P_String, p.P_Number, p.P_Date FROM AD_PINSTANCE i, AD_PINSTANCE_PARA p WHERE i.AD_PInstance_ID=PInstance AND i.AD_PInstance_ID=p.AD_PInstance_ID(+) ORDER BY p.SeqNo; -- Parameter Variables p_MVIEW VARCHAR2(2000); BEGIN DBMS_OUTPUT.PUT_LINE('Updating PInstance - Processing ' || PInstance_ID); ResultStr := 'PInstanceNotFound'; UPDATE AD_PINSTANCE SET Created = SYSDATE, IsProcessing = 'Y' WHERE AD_PInstance_ID=PInstance_ID; COMMIT; -- Get Parameters ResultStr := 'ReadingParameters'; FOR p IN Cur_Parameter (PInstance_ID) LOOP Record_ID := p.Record_ID; IF (p.ParameterName = 'MVIEW') THEN P_PTX_MVIEW := p.P_String; DBMS_OUTPUT.PUT_LINE(' MVIEW=' || p_MVIEW); ELSE DBMS_OUTPUT.PUT_LINE('*** Unknown Parameter=' || p.ParameterName); END IF; END LOOP; -- Get Parameter DBMS_OUTPUT.PUT_LINE(' Record_ID=' || Record_ID); DBMS_MVIEW.REFRESH (p_PTX_MVIEW, 'c'); <<FINISH_PROCESS>> -- Update AD_PInstance DBMS_OUTPUT.PUT_LINE('Updating PInstance - Finished ' || Message); UPDATE AD_PINSTANCE SET Updated = SYSDATE, IsProcessing = 'N', Result = 1, -- success ErrorMsg = Message WHERE AD_PInstance_ID=PInstance_ID; COMMIT; RETURN; EXCEPTION WHEN OTHERS THEN ResultStr := ResultStr || ': ' || SQLERRM || ' - ' || Message; DBMS_OUTPUT.PUT_LINE(ResultStr); UPDATE AD_PINSTANCE SET Updated = SYSDATE, IsProcessing = 'N', Result = 0, -- failure ErrorMsg = ResultStr WHERE AD_PInstance_ID=PInstance_ID; COMMIT; RETURN; END ; /
User authentication in Adempiere using LDAP
Submitted By: gemmiti
Summary: User authentication in Adempiere using LDAP
sf.net tracker: here
Enabling LDAP Functionality:
1. Log in as SysAdmin
2. Go to Menu > System Admin > System
3. In Field "Ldap URL" fill in your LDAP URL, i.e. "LDAP://YourLdapServer.com"
4. In field "LDAP Domain" Your Domain, i.e., "YourLdapServer.com"
5. Log Out as SysAdmin
6. Log In as SuperUser/Admin
7. GoTo Menu > General Rules > Security>User
8. In tab "User Contact" and "Internal" you will find a field for LDAP User Name -- Here (for a particular user) fill in the LDAP use name.
Upon logging in -- the user can enter his/her LDAP user name and password and it will associate the correct credentials to the user you have set up in Compiere.
Add OnHandQty In Product window
Submitted By: stingreye
Summary: Add OnHandQty In Product window
sf.net tracker: here
First the SQL 1) You want On Hand Qty - Product can be stored in multiple locators in M_Storage table. I assume you want total of all locators 2) So SQL = SELECT SUM (QTYONHAND) FROM M_STORAGE s 3) Now you want to sync with product table, so we add WHERE s.M_PRODUCT_ID = M_PRODUCT.M_PRODUCT_ID 4) So the final SQL we need is (SELECT SUM(QTYONHAND) FROM M_STORAGE s WHERE s.M_PRODUCT_ID = M_PRODUCT.M_PRODUCT_ID) Now lets add it to compiere: 1) Log in as SuperUser or System 2) Role = System Administrator 3) Open Table window 4) Select Column tab 5) Create new record 6) Insert a name for DB Column Name 7) Choose a system element in this case most likely Qty_OnHand 8) Reference = String 9) Length = 20 should be plenty 10) Click Save 11) Click synchronize column, cross fingers 12) Look on bottom left of window for alter table M_PRODUCTADD name of the field you just made Lets add it to the M_Product window. 1) Go to Window Tab Field 2) Choose Product Table 3) Goto Tab 4) Choose the “tab†we want which is Product (it is for the M_PRODUCT table) 5) Choose Field Tab 6) New Record 7) Name your Field (Qty on Hand) 8) Column – Choose the new column you created. 9) Save Now open the Product window and it should work!
How to setup Workflow for PO Approval?
Workflow Simple approval
Workflow Dynamic approval
Changelog functionality
changelog functionality consists of two parts: who & what.
- Via tables user can identify "what" wish to log.
- Via roles "who".
By this way is possible to finely control the auditing. This means more tables to be flagged if user wish to log all tables.
Securing JBoss JMX Console and Web Console
SECURE SCENARIO to use Adempiere
- sf.net post by Carlos
Possible SECURE SCENARIO to use Adempiere (applicable Compiere installations also)
CLIENTS
- 1 - Don't install clients
- 2 - Install two servers - one for NX (call it NXServer), and the other for oracle and JBoss (call it ADServer)
- 3 - Allow clients just run through NX connection (you'll have total control of the ADempiere.properties in a linux box)
- 4 - Configure the ADServer to only accept connections from NXServer
- 5 - Configure the Oracle in ADServer to only accept connections from the same ADServer and from NXServer
SERVICES ON WEB
- 1 - Don't expose web services from jboss directly
- 2 - Install an apache server to expose in a controlled way just the needed services and pages from jboss adempiere
In this scenario NX can be replaced with any terminal server software (Microsoft TS, Citrix, Sun Global Secure Desktop, etc).
And you must incur in costs of terminal server software licensing - but security is not free.
And you must ensure all those servers - ensure NX, ensure oracle, ensure jboss, ensure apache, ensure linux, etc.
Product Attribute Instance - Color/Size/Serial number
- Color/Size in Product Attribute per Instance Very good explanation from Colin
Material transaction between two organizations
- sf.net post another good description from Colin
Maintain multiple environments(Postgre multiple schema managing)
- wiki pageGood description from Fernando
PostgreSQL Materialized Views
Report sales figures by product
1. Create a Report Line Set called All Products. 2. Create a Report Line under it called Product with a Line Type of Segment Value (leave Posting and Amount Types blank) 3. Create a Report Source under it with Type=Product and leave the Product field blank 4. Create a Report Column Set called Current Period and YTD 5. Create 2 report columns under it, one for Current Period and YTD. The first one should have Posting Type=Actual, Amount Type=Period Balance, Column Type=Relative Period, Relative Period=0. The second one should be the same except Amount Type=Year Balance. 6. Then create a Financial report using these Report Line and Columns Sets. Make sure to check List Sources when you run to see all the products. Warning, If there are more than 1000 products it won't work (we're obviously aware of this limitation and working on removing it).
You can easily produce a similar report for Sales by Business Partner by just substituting Type=Business Parter in Step 3.
How to monitor Oracle sessions?
SELECT SID, SERIAL#, STATUS, SERVER FROM V$SESSION WHERE USERNAME = 'ADEMPIERE';
How to get Oracle Character set?
SELECT * FROM nls_database_parameters WHERE parameter = any('NLS_CHARACTERSET','NLS_NCHAR_CHARACTERSET');
How to change document numbers?
Go to Performance
Analysis -> Accounting Rules -> Document Type
Here you can see all existing document types like Purchase Order etc. If the 'Document is Number Controlled' checkbox is checked then you will have a Document Sequence field (a drop down). Right click and zoom to the Document Sequence window
Performance Analysis -> Accounting Rules -> Document Sequence
Here you can change the current next value, the increment and you can add prefix and or suffix for your order/invoice numbers.
Where to place JasperReport files?
JasperReport can be defined as:
http:// https:// attachment: file:/ or a direct file_directory path
An easier way to deploy jasper reports could be putting the .jasper in the customization.jar
For that we could add a new prefix like:
resource:org/adempiere/jasper/MyReport.jasper
How to handle imprests?
How to process credit card payments from Java GUI?
How a user could create a payment in the client (not the webstore) that will get passed to the payment processor?
Window 'Invoice (Customer)'.
Complete 'Invoice (Customer)'.
Set Payment Type - Press Button which by default has value 'On Credit'.
A new window open and user can change payment Type from 'On Credit' to 'Credit Card'.
Enter Credit Card data.
How to add comment on printed Invoice?
A line without product, charge and qty = 0 will be printed as a comment on invoice.
BOM price explained.
https://sourceforge.net/forum/message.php?msg_id=4740301
BOM Product price is depend of the price of the products which built it.
For example Product A consist of 1 product B and 1 product C. Product B and C are being priced at USD 5 and USD 6 respectively. The price of Product A would be USD 11. You cannot change it.
Meanwhile we often find a case where the price of Product A IS NOT the price of product B or C combined. It can be higher or lower. I try to add price to product A, which not the combined price but it doesn't work. This is what happen.
I put price of USD 15 for product A. When I created Sales Order, and I chose product A the price was still USD 15. Everything felt right. And then the disaster came. When I click Complete button suddenly the price change to USD 11!
If the BOM is not stocked it is considered a 'basket; and will compute the price based on the component prices.
If you want to assign a price change it to 'stocked'
How to enable Multilingual documents?
Client Window -> Multilingual Documents
Language Window Language Maintenance -> Add missing translations
How Cost centers are implemented in Adempiere?
sf.net post Adempiere support cost center using organization setup( have a look at the organization and organization type setup). Also, the transact organization element could be turned on in accounting schema to handle this.
How to setup Extended Document Number Formatting?
Enhance Document No Formatting
@AD_Org_ID<Value>@ is replace by 'HQ' ( AD_Org.Value )
<Value> can be replaced by any other column from AD_Org table.
How to list General Ledger Transactions?
How to setup Manufacturing process
01. Define a Resource as Plant 02. Create your resource Type this will determinate the capacity for your resource 03. Create your resource (Production Line , Work Center , Work Station) 03. Create a Manufacturing workflow (routing) where you define the process to manufacturing your product, so you need define each step the process and assign the resource where will execute the work. 04. Create the BOM to manufacturing your product, you need define if will use BOM or Formulas. 05. Create Manufacturing Document . 06. Use the BOM and workflow to create a new Manufacturing order 07. Change the Document status from draft to in process 08. Use Component check 09. if your component are available then use Print & Release Order 10. use Order Receipt & issue to report the component and finish good.
How to Merge Business Partner entities?
If you merge Business Partners you may need to run: Partner Relations -> Business Partner Rules -> Validate Business Partner
to get the correct open amounts, Life time value, etc...
If you merge Products, first move any inventory out of the product you will be deleting as that is not done in the merge process.
Costing records are not merged!
How to display Key and Name?
How to Delete Client/Tenant
Both scripts are in svn:
http://adempiere.svn.sourceforge.net/viewvc/adempiere/contributions/stuff/ DeleteAdempiereClient.SQL (for oracle) DeleteAdempiereClient_pg.SQL (for postgresql)
init.d for centOS
Sql which set QtyInvoice = QtyOrdered for given Organization.
update c_orderline ol set ol.QTYINVOICED=ol.QTYORDERED where C_ORDER_ID in (SELECT C_ORDER_ID FROM C_Order o WHERE DocStatus IN('CO','CL') AND IsSOTrx='Y' AND AD_Org_ID=1000001 AND EXISTS (SELECT * FROM C_OrderLine ol WHERE o.C_Order_ID=ol.C_Order_ID AND ol.QtyOrdered<>ol.QtyInvoiced) ); commit;
change class: org.compiere.grid.tree.VTreePanel.java
change method: public boolean initTree (int AD_Tree_ID)
add lines:
m_root = vTree.getRoot(); m_root.setName(Msg.getMsg(Env.getCtx(), vTree.getName() ) ); // translate name of menu. // m_root.setName(Msg.getMsg(Env.getCtx(), "Menu") ); // @Trifon; this is the hardcoded way.
change class: webui.desktop.java
change method: doCreatePart()
West w = new West(); layout.appendChild(w); w.setWidth("300px"); w.setCollapsible(true); w.setSplittable(true); w.setTitle("Menu"); w.setTooltiptext("Application Menu");
How to fix issue: Active workflow for this record exists?
Sometimes Adempiere crashes while processing a document. This usually leaves the document jammed in between two states. If you try to reverse it and rather unhelpful error message says there is an active workflow which must be completed first. To complete the work flow go to Workflow -> Workflow process then in the grid view find the work flow process with who's record_ID is the same as the document in question. Switch to the tab view and click Manage Process -> then check 'Abort' -> click okay. Go back to the document, requery (blue arrows), and you should now be able to reverse the document.
How to setup embedded tab?
Example how to setup UOM Conversion tab as embedded in UOM tab.
Steps:
- 1
Window: "Unit of Measure"
Tab: "Unit of Measure"
Field: "C_UOM_ID" make it visible.
Field: "Included Tab" set value to: "Conversion"
- 2
Tab: "Conversion"
Set "Sql Where":
C_UOM_Conversion.C_UOM_ID=@C_UOM_ID@
How to enter Payment from BP to another BP?
easiest - reverse correct the payment and re-enter as if coming from the the BP with the invoices and enter notes/descriptions to show what happened. less easy - create an invoice to the BP who paid and put to a Charge pointing to a suspense account. enter a credit note to the BP with invoices and put to same charge then allocate the credit note against the invoices.
Location of Documantation Chapters?
Chapter 3: http://grovers.us/media/Ch_3_BPG_SetUp.pdf Chapter 4A: http://grovers.us/media/Ch4Sales&MarketingPrt1.pdf Chapter 4B: http://grovers.us/media/Ch4SalesOrderPrt2.pdf Chapter 5: http://grovers.us/media/finished.zip Chapter 6: http://grovers.us/media/ch6open_items.pdf
Description of Dunning in ADempiere
ADempiere Dunning
Developer hints
- class dbPort/org.compiere.process.DocActionTemplate shows a template for DocAction, i think that it must be updated.
- Video created by Tim; part 1
- Video created by Tim; part 2
- Open Window and Tab programmatically, sf.net post
Hint-1; UPDATE columns which must have default value or have checked constraint
When developer add new column which is NOT NULL or which has checked constraint, please do not forget to execute proper UPDATE TABLE sql statements.
Example:
ALTER TABLE EXP_FormatLine ADD IsPartUniqueIndex CHAR(1) CHECK(IsPartUniqueIndex IN ('Y', 'N')); UPDATE EXP_FormatLine SET IsPartUniqueIndex = 'N' WHERE IsPartUniqueIndex IS NULL;
Hint-2; Be carefull when creating VIEWS
Use LEFT/RIGHT OUTER JOINS, because in many cases fields do not have values and INNER JOIN will not show all records. In this example C_Invoice.C_Order_ID is not manadatory so view will not show records which do not have Order associated with Invoice!
FROM C_Invoice i INNER JOIN C_DocType d ON (i.C_DocType_ID=d.C_DocType_ID) LEFT OUTER JOIN C_Order o ON (i.C_Order_ID=o.C_Order_ID)
Hint-3; Java on Ubuntu
Ubuntu came with default version of java 1.4.2 and installing 1.5.0 didn't change that. So developer have to change it. Exporting the path to your newer java to the .bashrc config file of your environment is a standadrd decision but is not system wide and in some cases is not enough. The decision is. When you type at the prompt:
$ sudo update-java-alternatives -l
will see the versions of all javas installed into your system. In order to make the latest one default for the whole system type:
$ sudo update-java-alternatives -s java-newer-ver
Hint-4; How to truncate timestamp
Timestamp today = TimeUtil.trunc(new Timestamp (System.currentTimeMillis() ), TimeUtil.TRUNC_DAY);
Hint-5; How to use MTable.get(..) and MTable.getPO(..)
Class: base/src/org/compiere/model/MProduct.java
public MAttributeInstance getAttributeInstance(String name, String trxName) { MAttributeInstance instance = null; MTable table = MTable.get(Env.getCtx(), MAttribute.Table_ID); MAttribute attribute = (MAttribute)table.getPO("Name = ?", new Object[]{name}, trxName); if ( attribute == null ) return null; table = MTable.get(Env.getCtx(), MAttributeInstance.Table_ID); instance = (MAttributeInstance)table.getPO( MAttributeInstance.COLUMNNAME_M_AttributeSetInstance_ID + "=?" + " and " + MAttributeInstance.COLUMNNAME_M_Attribute_ID + "=?" , new Object[]{getM_AttributeSetInstance_ID(), attribute.getM_Attribute_ID()}, trxName); return instance; }
Subversion Access
Subversion Plugin for Eclipse Subversive
Adempiere project's SourceForge.net Subversion repository can be checked out through SVN with the following instruction set: svn co https://adempiere.svn.sourceforge.net/svnroot/adempiere adempiere
- SVN Browse: here
MFG
Important Steps:
1. Apply the following patches: buildbase.patch.tim buildclient.patch.tim buildutils_dev.patch.tim X_AD_WF_Node.patch X_C_DocType.patch X_S_Resource.patch X_AD_Workflow.patch X_M_Cost.patch X_M_Transaction.patch X_M_Product.patch 2. I copied adempiere/libero/build.xml.tim to adempiere/libero/build.xml Build your Adempiere and run it. 3. Create a new client and import accounting etc... (If you don't do this you won't see all the menus, you can't just login under GardenAdmin/GardenAdmin that is not enough) It looks that 2pack file do not contains proper access records. Must research!!! 4. Login with your new client Admin login you created in step3 and Libero away!!!
Compiling adempiere + libero from SVN head
Libero Manufacturing functionality is in branch/stable and is not necessary to perform below steps!
1. Check out the head version of both libero and adempiere 2. Build adempiere 3. Build libero 4. Rebuild adempiere (to get the libero.jar into the install) 5. Set up the database. (Create database, run the pljava deployer, drop the sqlj schema, import the dump file) 6. Run the 330-trunk database migrations 7. Copy EE01.zip into the packages directory 8. Run silent setup and start the app server. 9. Launch the Adempiere client 10. Add the EE01 entity type 11. Pack in the EE01.zip 12. Copy libero.jar into the packages/packages/EE01/lib directory. 13. Re-run silentsetup and start the server.
Template Process and steps to create a process
1)create a java class extends org.compiere.process.SvrProcess
2)Implements two methods void doIt() String prepare()
In Prepare method you can get different parameters ProcessInfoParameter[] para = getParameter(); for (int i = 0; i < para.length; i++) { String name = para[i].getParameterName(); if (para[i].getParameter() == null)
else System.out.println(name); } and in doIt method you try to insert this parameters into your table after you create this class Login with system administrator role
3) 'Report and Process' window define your process with parameter 4) 'Table and Column' window choose your table and create a column with Button Reference
5) Choose your process for this Button
package org.adempiere.process; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.logging.Level; import org.compiere.model.MClient; import org.compiere.model.MDocType; import org.compiere.model.X_C_BPartner_EDI; import org.compiere.model.X_C_EDIFormat; import org.compiere.model.X_C_EDIProcessor; import org.compiere.process.ProcessInfoParameter; import org.compiere.process.SvrProcess; import org.compiere.util.DB; import org.compiere.util.Env; import org.compiere.util.Msg; /** * @author Trifon Trifonov * @version $Id:$ */ public class ModelImporter extends SvrProcess { /** Client Parameter */ protected int p_AD_Client_ID = 0; /** Business Partner Parameter */ protected int p_C_BPartner_ID = 0; /** Document Type Parameter */ protected int p_C_DocType_ID = 0; /** Record ID */ protected int p_Record_ID = 0; /** Table ID */ int AD_Table_ID = 0; /** * Get Parameters */ protected void prepare () { p_Record_ID = getRecord_ID(); if (p_AD_Client_ID == 0) p_AD_Client_ID = Env.getAD_Client_ID(getCtx()); AD_Table_ID = getTable_ID(); StringBuffer sb = new StringBuffer ("AD_Table_ID=").append(AD_Table_ID); sb.append("; Record_ID=").append(getRecord_ID()); // Parameter ProcessInfoParameter[] para = getParameter(); for (int i = 0; i < para.length; i++) { String name = para[i].getParameterName(); if (para[i].getParameter() == null) ; else if (name.equals("C_BPartner_ID")) p_C_BPartner_ID = para[i].getParameterAsInt(); else log.log(Level.SEVERE, "Unknown Parameter: " + name); } log.info(sb.toString()); } /** * Process * @return info */ protected String doIt () throws Exception { StringBuffer result = new StringBuffer(""); MClient client = MClient.get (getCtx(), p_AD_Client_ID); log.info(client.toString()); // get proper EDI Format from Document Type MDocType docType = MDocType.get(getCtx(), p_C_DocType_ID); int C_EDIFormat_ID = 0; int C_EDIProcessor_ID = 0; String sql1 = "SELECT C_EDIFormat_ID, C_EDIProcessor_ID " + "FROM " + X_C_BPartner_EDI.Table_Name + " " + "WHERE AD_Client_ID = ? " + " AND C_BPartner_ID = ? " + " AND C_DocType_ID = ? " + " AND Inbound = 'N' " ; ResultSet rs1 = null; PreparedStatement pstmt1 = null; try { pstmt1 = DB.prepareStatement(sql1, get_TrxName()); pstmt1.setInt(1, p_AD_Client_ID); pstmt1.setInt(2, p_C_BPartner_ID); pstmt1.setInt(3, p_C_DocType_ID); rs1 = pstmt1.executeQuery(); if (rs1.next()) { // Found specific C_EDIFormat for given BPartner and C_DocType_ID C_EDIFormat_ID = rs1.getInt(X_C_EDIFormat.COLUMNNAME_C_EDIFormat_ID); C_EDIProcessor_ID = rs1.getInt(X_C_EDIProcessor.COLUMNNAME_C_EDIProcessor_ID); } else { // Get C_EDIFormat_ID from Document Type C_EDIFormat_ID = docType.getC_EDIFormat_ID(); } } finally { try { if (rs1 != null) rs1.close(); if (pstmt1 != null) pstmt1.close(); } catch (SQLException ex) {/*ignored*/} rs1 = null; pstmt1 = null; } if (C_EDIFormat_ID == 0) { throw new Exception("EDI Format is not set for C_DocType_ID = [" + p_C_DocType_ID + "]"); } if (C_EDIProcessor_ID == 0) { throw new Exception("EDI Processor is not set for C_DocType_ID = [" + p_C_DocType_ID + "]"); } addLog(0, null, null, Msg.getMsg (getCtx(), "EDISubmitProcessResult") + "\n" + result.toString()); return result.toString(); } }
Migration with SQL statements - Oracle - AD_Element
INSERT INTO AD_Element (AD_Element_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Cpdated, UpdatedBy, ColumnName, EntityType, Name, PrintName ) VALUES (500XX, 0, 0, 'Y', TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, '[ColumnNameHere]', 'D', '[NameHere]', '[PrintNameHere]' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Element_ID) + 1 FROM AD_Element WHERE AD_Element_ID < 1000000) WHERE NAME = 'AD_Element';
Migration with SQL statements - Oracle - AD_Table
INSERT INTO AD_Table (AD_Table_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Name, Description, Help, TableName, IsView, AccessLevel, EntityType, AD_Window_ID, AD_Val_Rule_ID, LoadSeq, IsSecurityEnabled, IsDeleteable, IsHighVolume, ImportTable, IsChangelog, ReplicationType, PO_Window_ID, CopyColumnsFromTable ) VALUES (53014, 0, 0, 'Y', TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, '[NameHere]', '[DescriptionHere]', '[HelpHere]', '[TableNameHere]', 'N', '4', 'D', null, null, 0, 'N', 'Y', 'N', 'N', 'N', 'L', null, 'N' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Table_ID) + 1 FROM AD_Table WHERE AD_Table_ID < 1000000) WHERE NAME = 'AD_Table';
Migration with SQL statements - Oracle - AD_Column
INSERT INTO AD_Column (AD_Column_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, Updated, CreatedBy, UpdatedBy, Name, Description, Version, EntityType, ColumnName, AD_Table_ID, AD_Reference_ID, FieldLength, IsKey, IsParent, IsMandatory, IsUpdateable, IsIdentifier, SeqNo, IsTranslated, IsEncrypted, IsSelectionColumn, AD_Element_ID, Callout, IsSyncDatabase, IsAlwaysUpdateable ) VALUES (502XX, 0, 0, 'Y', TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, 100, '[NameHere]', '[DescriptionHere]', 1, 'D', '[ColumnNameHere]', AD_Table_IDHERE, AD_Reference_IDHere, 1, 'N', 'N', 'Y', 'Y', 'N', 0, 'N', 'N', 'N', 50071, '[CalloutHere]', 'N', 'N' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Column_ID) + 1 FROM AD_Column WHERE AD_Column_ID < 1000000) WHERE NAME = 'AD_Column';
Migration with SQL statements - Oracle - AD_Window
INSERT INTO AD_Window (AD_Window_ID,AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Name, Description, Help, WindowType, IsSoTrx, EntityType, Processing, AD_Image_ID, AD_Color_ID, IsDefault, WinHeight, WinWidth, IsBetaFunctionality ) VALUES (53003, 0, 0, 'Y', TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, '[NameHere]', null, null, 'M', 'N', 'D', 'N', null, null, 'N', 0, 0, 'N' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Window_ID) + 1 FROM AD_Window WHERE AD_Window_ID < 1000000) WHERE Name = 'AD_Window';
Migration with SQL statements - Oracle - AD_Tab
INSERT INTO AD_Tab (AD_Tab_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Name, Description, Help, AD_Table_ID, AD_Window_ID, SeqNo, TabLevel, IsSingleRow, IsInfoTab, IsTranslationTab, IsReadOnly, AD_Column_ID, HasTree, WhereClause, OrderByClause, CommitWarning, AD_Process_ID, Processing, AD_Image_ID, ImportFields, AD_ColumnSortOrder_ID, AD_ColumnSortYesNo_ID, IsSortTab, EntityType, Included_Tab_ID, ReadOnlyLogic, DisplayLogic, IsInsertRecord, IsAdvancedTab ) VALUES (53014, 0, 0, 'Y', TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, '[NameHere]', null, null, [AD_TableIDHERE], [AD_Window_IDHERE], [SeqNoHERE], 0, 'N', 'N', 'N', 'N', null, 'N', null, null, null, null, 'N', null, 'N', null, null, 'N', 'D', null, null, null, 'Y', 'N' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Tab_ID) + 1 FROM AD_Tab WHERE AD_Tab_ID < 1000000) WHERE Name = 'AD_Tab';
Migration with SQL statements - Oracle - AD_Field
INSERT INTO AD_Field (AD_Field_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Name, Description, IsCentrallyMaintained, SeqNo, AD_Tab_ID, AD_Column_ID, IsDisplayed, DisplayLength, IsReadonly, IsSameLine, IsHeading, IsFieldOnly, IsEncrypted, EntityType ) VALUES (50184, 0, 0, 'Y', TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, 'Store Archive On File System', 'Store Archive On File System', 'Y', 250, 145, 50214, 'Y', 1, 'N', 'N', 'N', 'N', 'N', 'D' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Field_ID) + 1 FROM AD_Field WHERE AD_Field_ID < 1000000) WHERE Name = 'AD_Field';
Migration with SQL statements - Oracle - AD_Menu
INSERT INTO AD_Menu (AD_Menu_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Name, Description, IsSummary, IsSoTrx, IsReadOnly, Action, AD_Window_ID, AD_Workflow_ID, AD_Task_ID, AD_Process_ID, AD_Form_ID, AD_Workbench_ID, EntityType ) VALUES( 53012, 0, 0, 'Y', TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, '[NameHERE]', NULL, 'N', 'N', 'N', 'W', [AD_Window_IDHERE], NULL, NULL, NULL, NULL, NULL, 'D' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Menu_ID) + 1 FROM AD_Menu WHERE AD_Menu_ID < 1000000) WHERE Name = 'AD_Menu';
Migration with SQL statements - Oracle - AD_TreeNodeMM
INSERT INTO AD_TreeNodeMM (AD_Tree_ID, Node_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, Createdby, Updated, UpdatedBy, Parent_ID, SeqNo ) VALUES (10, [Node_IDHERE], 0, 0, 'Y', TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 0, TO_DATE ('10/22/2007 09:30:00', 'MM/DD/YYYY HH24:MI:SS'), 0, [Parent_IDHERE], [SeqNoHERE] ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Menu_ID) + 1 FROM AD_Menu WHERE AD_Menu_ID < 1000000) WHERE Name = 'AD_Menu';
Migration with SQL statements - AD_Message
INSERT INTO AD_Message (AD_Message_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Value, MsgText, MsgType ) VALUES (500XX, 0, 0, 'Y', TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, TO_DATE ('02/26/2007 12:30:00', 'MM/DD/YYYY HH24:MI:SS'), 100, '[VaueHere]','[MSG Text Here]','I' ); COMMIT; UPDATE AD_Sequence SET CurrentNextSys = (SELECT MAX (AD_Message_ID) + 1 FROM AD_Message WHERE AD_message_ID < 1000000) WHERE NAME = 'AD_Message';
Migration with SQL statements - AD_Process_Para
INSERT INTO AD_Process_Para (AD_Process_Para_ID, AD_Client_ID, AD_Org_ID, IsActive, Created, CreatedBy, Updated, UpdatedBy, Name, Description, Help, AD_Process_ID, SeqNo, AD_Reference_ID, AD_Reference_Value_ID, AD_Val_Rule_ID, ColumnName, IsCentrallyMaintained, FieldLength, IsMandatory, IsRange, AD_Element_ID, EntityType ) VALUES (50019, 0, 0, 'Y', TO_DATE ('2007-03-03', 'YYYY-MM-DD'), 100, TO_DATE ('2007-03-03', 'YYYY-MM-DD'), 100, 'Shipment Date', 'Date printed on shipment', 'The Shipment Date indicates the date printed on the shipment.', 118, 15, 15, NULL, NULL, 'MovementDate', 'N', 0, 'Y', 'N', 1037, 'D' ); COMMIT; UPDATE AD_SEQUENCE SET currentnextsys = (SELECT MAX (ad_process_para_id) + 1 FROM AD_Process_Para WHERE AD_Process_Para_ID < 1000000) WHERE NAME = 'AD_Process_Para';
Migration with SQL statements - AD_Ref_List - Postgre
INSERT INTO AD_Ref_List ( Created, CreatedBy, Updated, UpdatedBy, AD_Org_ID, AD_Ref_List_ID, AD_Reference_ID, Value, Name, IsActive, AD_Client_ID, EntityType ) VALUES ( TO_TIMESTAMP('2008-01-19 22:45:00','YYYY-MM-DD HH24:MI:SS'), 0, TO_TIMESTAMP('2008-01-19 22:45:00','YYYY-MM-DD HH24:MI:SS'), 0, 0, 53287, 329, 'DOO', 'Distribution Order', 'Y',0,'EE01' );
Session_IsChangeLog, AD_Table.IsChangeLog, AD_Column.IsChangeLog combination
1. Session_IsChangeLog=no, AD_Table.IsChangeLog=no, AD_Column.IsChangeLog=no =>is column logged: no 2. Session_IsChangeLog=no, AD_Table.IsChangeLog=no, AD_Column.IsChangeLog=yes =>is column logged: no 3. Session_IsChangeLog=no, AD_Table.IsChangeLog=yes, AD_Column.IsChangeLog=no =>is column logged: no 4. Session_IsChangeLog=no, AD_Table.IsChangeLog=yes, AD_Column.IsChangeLog=yes =>is column logged: yes 5. Session_IsChangeLog=yes, AD_Table.IsChangeLog=no, AD_Column.IsChangeLog=no =>is column logged: no 6. Session_IsChangeLog=yes, AD_Table.IsChangeLog=no, AD_Column.IsChangeLog=yes =>is column logged: yes 7. Session_IsChangeLog=yes, AD_Table.IsChangeLog=yes, AD_Column.IsChangeLog=no =>is column logged: no 8. Session_IsChangeLog=yes, AD_Table.IsChangeLog=yes, AD_Column.IsChangeLog=yes =>is column logged: yes Note: Session_IsChangeLog means: AD_Role.IsChangeLog or is a webstore session. Observation1: as you see, AD_Column.IsChangeLog=Y means inherit policy from parent (AD_Table) and AD_Column.IsChangeLog=N means never log this record. PS: in future, i think we can move from IsChangeLog flag to some ChangeLogPolicy=(Always, Never, Inherit from parent).
How to use Transactions and Save points in Adempiere
String trxName = Trx.createTrxName("test"); Trx trx = Trx.get(trxName, true); Savepoint save1 = trx.setSavepoint("save1"); location = new MLocation(m_Ctx, 0, trxName); ... trx.rollback(save1); trx.commit(); trx.close();
How to build Adempiere customization.jar
Customization.jar is in the lib directory of trunk. (ie /trunk/lib ) Go to that directory and execute following commands:
jar uvf customization.jar -C ../libero/build/ ./org/compiere/model/ jar uvf customization.jar -C ../libero/build/ ./org/compiere/acct/ jar uvf customization.jar -C ../libero/build/ ./org/compiere/process/
Then goto utils_dev directory and ./RUN_build.sh
After the build has completed the new customized.jar will be in $ADEMPIERE_HOME/lib Adempiere should now use the customized classes.
How to Open Window from source code?
MQuery aQuery = new MQuery ("C_Invoice"); aQuery.setRecordCount(1); aQuery.addRestriction("C_Invoice_ID", "=", C_Invoice_ID ); AWindow frame = new AWindow(); frame.initWindow(183, aQuery); // 183=window "Invoice (Vendor)" frame.validate(); AEnv.showCenterScreen(frame);
How to keep parameter window open after view report?
How to create confirmation for inventory move?
How to make Adempiere LDAP username registration compatible with OpenLDAP
- StringBuffer principal = new StringBuffer (userName).append("@").append(domain); + // For OpenLDAP uncomment the next line + // StringBuffer principal = new StringBuffer("uid=").append(userName).append(",").append(domain); + StringBuffer principal = new StringBuffer(userName).append("@").append(domain); env.put(Context.SECURITY_PRINCIPAL, principal.toString()); env.put(Context.SECURITY_CREDENTIALS, password);
How to use JSR 223: Scripting callouts in Adempiere?
Integer order_id = (Integer) mTab.getValue("C_ORDER_ID"); MOrder obj = new MOrder(Env.getCtx(),order_id.intValue(),null); if (obj.getC_DocType_ID()==1000025 ) { your code here... }
How to get Adempiere/Compiere Home from java class?
org.compiere.util.Ini.findAdempiereHome()
How to set/update column ModelValidationClasses
Nice code from Carlos! Have to check if it works for Oracle and Postgre.
UPDATE AD_Client SET ModelValidationClasses = CASE WHEN ModelValidationClasses LIKE '%org.adempiere.model.LCO_Validator%' THEN ModelValidationClasses WHEN LENGTH (TRIM (ModelValidationClasses)) = 0 OR ModelValidationClasses IS NULL THEN TO_NCHAR ('org.adempiere.model.LCO_Validator') ELSE ModelValidationClasses || ';org.adempiere.model.LCO_Validator' END WHERE AD_Client_ID != 0
How to use Adempiere sequence from java code?
MSequence sequence = new MSequence(getCtx(), sequenceId, get_TrxName()); int nextId = sequence.getNextID(); sequence.save();
How to setup Adempiere ZK Development Environment
How to add new tab to Info Window
How to copy print format and how to invoke print preview from java?
Language language = Language.getLoginLanguage(); // Base Language MPrintFormat pf = null; int pfid = 0; // get print format for client, else copy system to client RowSet pfrs = MPrintFormat.getAccessiblePrintFormats(X_RV_PP_Product_BOMLine.Table_ID, -1, null); pfrs.next(); pfid = pfrs.getInt("AD_PrintFormat_ID"); if(pfrs.getInt("AD_Client_ID") != 0) pf = MPrintFormat.get(getCtx(), pfid, false); else pf = MPrintFormat.copyToClient(getCtx(), pfid, getAD_Client_ID()); pfrs.close(); if (pf == null) raiseError("Error: ","No Print Format"); pf.setLanguage(language); pf.setTranslationLanguage(language); // query MQuery query = MQuery.get(getCtx(), AD_PInstance_ID, X_RV_PP_Product_BOMLine.Table_Name); query.addRestriction("AD_PInstance_ID", MQuery.EQUAL, AD_PInstance_ID); PrintInfo info = new PrintInfo(X_RV_PP_Product_BOMLine.Table_Name, X_RV_PP_Product_BOMLine.Table_ID, getRecord_ID()); ReportEngine re = new ReportEngine(getCtx(), pf, query, info); ReportCtl.preview(re); // wait for report window to be closed as t_bomline // records are deleted when process ends while (re.getView().isDisplayable()) { Env.sleep(1); }
Some views
CREATE VIEW RV_OpenItemAcct AS SELECT item.AD_Client_ID , item.AD_Org_ID , item.DocumentNo , item.C_Invoice_ID , item.C_Order_ID , item.C_BPartner_ID , item.IsSOTrx , item.DateInvoiced , item.DateAcct , item.NetDays , item.DueDate , item.DaysDue , item.DiscountDate , item.DiscountAmt , item.GrandTotal , item.PaidAmt , item.OpenAmt , item.C_Currency_ID , item.C_ConversionType_ID , item.C_PaymentTerm_ID , item.IsPayScheduleValid , item.C_InvoicePaySchedule_ID , item.InvoiceCollectionType , item.C_Campaign_ID , item.C_Project_ID , item.C_Activity_ID , combCust.Combination AS custCombComination , combCust.Description AS custCombDescription , combVend.Combination AS custVendComination , combVend.Description AS custVendDescription FROM RV_OpenItem item LEFT OUTER JOIN C_BP_Customer_Acct custAcct ON (item.IsSoTrx= 'Y' AND item.C_BPartner_ID = custAcct.C_BPartner_ID AND custAcct.C_AcctSchema_ID=101) LEFT OUTER JOIN C_ValidCombination combCust ON (custAcct.C_Receivable_Acct = combCust.C_ValidCombination_ID) LEFT OUTER JOIN C_BP_Vendor_Acct vendAcct ON (item.IsSoTrx= 'N' AND item.C_BPartner_ID = vendAcct.C_BPartner_ID AND vendAcct.C_AcctSchema_ID=101) LEFT OUTER JOIN C_ValidCombination combVend ON (vendAcct.V_Liability_Acct = combVend.C_ValidCombination_ID)
How to call stored procedure from java?
CallableStatement cs = null; cs = DB.prepareCall("{call AD_Sequence_Next(?,?,?)}"); cs.setString(1, "A_Asset_Change"); cs.setInt(2,imp.getAD_Client_ID()); cs.registerOutParameter(3, java.sql.Types.INTEGER); cs.execute(); int value = cs.getInt(3);
How to add Value column to Existing Adempiere table?
- Parameters:
- TableName = 'M_Attribute'
- AD_Client_ID = 11
- Add Value column
ALTER TABLE M_Attribute ADD Value NVARCHAR2(40)
- Make values unique
- Make values unique - version 1
UPDATE M_Attribute Set Value = nextidfunc( (SELECT AD_Sequence_ID FROM AD_Sequence WHERE AD_Client_ID = 0 AND Name = 'M_Attribute')::integer, 'N'::varchar) WHERE M_Attribute.Value IS NULL AND M_Attribute.AD_Client_ID = 11
- Make values unique - version 2
UPDATE M_Attribute Set Value = nextidfunc(691, 'N'::varchar) WHERE M_Attribute.Value IS NULL AND M_Attribute.AD_Client_ID = 11
- Add Unique contraint
- Add Unique contraint - version 1
ALTER TABLE M_Attribute ADD Constraint M_Attribute_Value UNIQUE(AD_Client_ID, Value)
- Add Unique contraint - version 2
CREATE UNIQUE INDEX M_Attribute_Value ON M_Attribute(AD_Client_ID, Value)
How to speedup Record Change Log?
- sf.net post
- Oracle
create index ad_changelog_speed on ad_changelog (ad_table_id, record_id);
- Postgre
create index ad_changelog_speed on ad_changelog (ad_table_id, record_id);
Log management in Adempiere?
Adempiere uses Java logging capabilities. Responsible classes are:
base/src/org.compiere.util.CLogMgt
Configuration files:
base/src/org/compiere/util/logClient.properties base/src/org/compiere/util/logServer.properties
Adempiere initiative: Remove SQL code and Replace with Query class!
- Description to use in svn commits:
One class per day initiative. FR: [ 2214883 ] Remove SQL code and Replace for Query https://sourceforge.net/tracker/?func=detail&atid=879335&aid=2214883&group_id=176962
How to use Adempiere Query class?
How to return only ONE object?
StringBuffer whereClause = null; whereClause = new StringBuffer("AD_Client_ID=?" // #1 + " AND AD_Org_ID=?" // #2 + " AND C_AcctSchema_ID=?" // #3 + " AND Account_ID=?"); // #4 ArrayList<Object> params = new ArrayList<Object>(); params.add(AD_Client_ID); params.add(AD_Org_ID); params.add(C_AcctSchema_ID); params.add(Account_ID); Account existingAccount = new Query(ctx, MAccount.Table_Name, whereClause.toString(), null) .setParameters( params ) .first();
How to return ARRAY of objects?
public static MAchievement[] getOfMeasure (Properties ctx, int PA_Measure_ID) { String whereClause = "PA_Measure_ID=? AND IsAchieved='Y'"; List<MAchievement> list = new Query(ctx, MAchievement.Table_Name, whereClause, null) .setParameters(new Object[]{PA_Measure_ID}) .setOrderBy("SeqNo, DateDoc") .list() ; MAchievement[] retValue = new MAchievement[ list.size() ]; retValue = list.toArray (retValue); return retValue; }
How to return ARRAY of objects and process elements?
public static MAchievement[] getOfMeasure (Properties ctx, int PA_Measure_ID) { String whereClause = "PA_Measure_ID=? AND IsAchieved='Y'"; List<MAchievement> list = new Query(ctx, MAchievement.Table_Name, whereClause, null) .setParameters(new Object[]{PA_Measure_ID}) .setOrderBy("SeqNo, DateDoc") .list() ; for(MAchievement achievement : list) { s_log.fine(" - " + achievement); } MAchievement[] retValue = new MAchievement[ list.size() ]; retValue = list.toArray (retValue); return retValue; }
How to pass Timestamp parameter?
Timestamp dateAcct = ...; String trxName = ...; String whereClause = "c.C_CashBook_ID=?" // #1 + " AND TRUNC(c.StatementDate)=?" // #2 + " AND c.Processed='N'"; MCash retValue = new Query(ctx, MCash.Table_Name, whereClause, trxName) .setParameters(new Object[]{C_CashBook_ID, TimeUtil.getDay(dateAcct)}) .first() ;
How to use Query class with complex where clause: EXISTS?
String whereClause = "C_Cash.AD_Org_ID=?" // #1 + " AND TRUNC(C_Cash.StatementDate)=?" // #2 + " AND C_Cash.Processed='N'" + " AND EXISTS (SELECT * FROM C_CashBook cb " + "WHERE C_Cash.C_CashBook_ID=cb.C_CashBook_ID AND cb.AD_Org_ID=C_Cash.AD_Org_ID" + " AND cb.C_Currency_ID=?)" // #3 ; MCash retValue = new Query(ctx, MCash.Table_Name, whereClause, trxName) .setParameters(new Object[]{AD_Org_ID,TimeUtil.getDay(dateAcct),C_Currency_ID}) .first() ;
How to use Adempiere MQuery class?
- example 1
MQuery aQuery = new MQuery(X_C_Invoice.Table_Name); aQuery.setRecordCount( 1 ); aQuery.addRestriction("C_Invoice_ID", "=", C_Invoice_ID );
- Example 2
MQuery query = MQuery.get(getCtx(), AD_PInstance_ID, X_RV_PP_Product_BOMLine.Table_Name); query.addRestriction("AD_PInstance_ID", MQuery.EQUAL, AD_PInstance_ID);
Adempiere utility classes?
- base/org.compiere.util.TimeUtil
Base Language functionality
Revision: 6839 http://adempiere.svn.sourceforge.net/adempiere/?rev=6839&view=rev Revision: 6810 http://adempiere.svn.sourceforge.net/adempiere/?rev=6810&view=rev contributions/Localizations/Germany/src/migration/postgresql/baselanguage/baselanguage.sql contributions/Localizations/Germany/src/migration/postgresql/baselanguage/baselanguage_views.sql Revision: 6809 http://adempiere.svn.sourceforge.net/adempiere/?rev=6809&view=rev contributions/Localizations/Germany/src/java/org/compiere/apps/ALogin.java contributions/Localizations/Germany/src/java/org/compiere/cm/utils/CMEnv.java contributions/Localizations/Germany/src/java/org/compiere/util/Language.java contributions/Localizations/Germany/src/java/org/compiere/wstore/PriceListTag.java contributions/Localizations/Germany/src/java/org/posterita/core/businesslogic/ElementManager.java
Differences in source code between Adempiere 3.5.0 and Compiere 3.0.0
Context
- Adempiere
Env.setContext(Env.getCtx(), "#AD_User_ID", CreatedBy_ID);
- Compiere
Env.getCtx().setContext("#AD_User_ID", CreatedBy_ID);
Build, Imports
- Compiere
import org.compiere.util.Ctx; import org.compiere.framework.PO;
add projects 'ad' and 'common' to build path.
Keeping sources compatible with Adempiere 3.5.0 and Compiere 3.0.0
Context
/* $if isAdempiere $ Env.setContext(Env.getCtx(), "#AD_Org_ID", AD_Org_ID); // Adempiere $else$ */ Env.getCtx().setContext("#AD_Org_ID", AD_Org_ID); // Compiere /* $endif$ */
Example
// ================= /* $if isAdempiere $ Env.setContext(Env.getCtx(), "#AD_User_ID", CreatedBy_ID); // Adempiere $else$ */ Env.getCtx().setContext("#AD_User_ID", CreatedBy_ID); // Compiere /* $endif$ */ } // ================= /* $if isAdempiere $ Env.setContext(Env.getCtx(), "#AD_Client_ID", AD_Client_ID); // Adempiere $else$ */ Env.getCtx().setContext("#AD_Client_ID", AD_Client_ID); // Compiere /* $endif$ */ // ================= /* $if isAdempiere $ Env.setContext(Env.getCtx(), "#AD_Org_ID", AD_Org_ID); // Adempiere $else$ */ Env.getCtx().setContext("#AD_Org_ID", AD_Org_ID); // Compiere /* $endif$ */
How to Validate conditional mandatory field?
Timestamp start = getTimeSlotStart(); if (start == null) throw new FillMandatoryException(COLUMNNAME_TimeSlotStart);
How to enable Query TimeOut in Adempiere?
Specify JVM parameter
-Dorg.adempiere.po.useTimeoutForUpdate=true
How to decrease number of log files created by Java WebStart?
Problem is missing ADEMPIERE_HOME on the machine. Webstart works fine without environment variable set, only resulting in many many logfiles. After setting the variable to c:\adempiere it created the log folder and used just one file per session as expected.
How to post accounting transactions without Application Server?
Add new jvm system property:
org.adempiere.server.embedded
License to use for new classes
/********************************************************************** * This file is part of ADempiere Business Suite * * http://www.adempiere.org * * * * Copyright (C) Trifon Trifonov. * * Copyright (C) Contributors * * * * This program is free software; you can redistribute it and/or * * modify it under the terms of the GNU General Public License * * as published by the Free Software Foundation; either version 2 * * of the License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program; if not, write to the Free Software * * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * * MA 02110-1301, USA. * * * * Contributors: * * - Trifon Trifonov (trifonnt@users.sourceforge.net) * * * * Sponsors: * * - Company (http://www.site.com) * ***********************************************************************/ ... ... /** * @author Trifon Trifonov * @version $Id$ */
How to add new Actions to Document Engine
Edit class
base/src/org/compiere/process/DocumentEngine.java
Add new if statements:
+ /******************** + * Manufacturing Order + */ + else if (AD_Table_ID == MPPOrder.Table_ID) + { + if (docStatus.equals(DocumentEngine.STATUS_Drafted) + || docStatus.equals(DocumentEngine.STATUS_InProgress) + || docStatus.equals(DocumentEngine.STATUS_Invalid)) + { + options[index++] = DocumentEngine.ACTION_Prepare; + options[index++] = DocumentEngine.ACTION_Close; + } + // Complete ... CO + else if (docStatus.equals(DocumentEngine.STATUS_Completed)) + { + options[index++] = DocumentEngine.ACTION_Void; + options[index++] = DocumentEngine.ACTION_ReActivate; + } + }
Adempiere Export/Import Tools
- ADCK can be used in two modes.
- As Development tool. To model DB design and create/modify tables.
As Development tool ADCK uses Druid which allows developer to generate CREATE TABLE and ALTER table SQL statement for various DBs: Oracle, Postgres, MySQL, ... As Development tool ADCK can generate xml files for various tools and frameworks like: hibernate, torque.
- As transfer tool for only migrating AD changes from Adempiere instance to instance or from version to version.
As transfer tool ADCK require initial just setting of proper settings in properties files.
2Pack vs. ADCK comparison table.
This table is made with the sole purpose to help me to organize information regarding import/export tools in Adempiere. I do not have any idea to push any of the tools mentiod here. It is user's choice to use or not to use any of them and also users choice to have headache after thier usage.
WARNING: !!!MAKE A BACKUP BEFORE ANY USAGE OF ANY OF THE TOOLS!!!
2Pack | ADCK |
menu | menu |
window | window |
tab | tab |
field | field |
process | process |
processpara | processpara |
table | table |
column | column |
impformat | AD_ImpFormat |
impformatrow | AD_ImpFormat_Row |
printformat | AD_PrintFormat |
printformatitem | AD_PrintFormatItem |
reference | ADCK |
referencelist | ADCK |
referencetable | ADCK |
reportview | ADCK |
reportviewcol | ADCK |
task | ADCK |
form | ADCK |
workbench | ADCK |
preference | ADCK |
role | AD_Role |
??? | AD_User |
userrole | AD_User_Roles |
orgrole | AD_Role_OrgAccess |
windowaccess | AD_Window_Access |
processaccess | AD_Process_Access |
formaccess | AD_Form_Access |
workflowaccess | AD_Workflow_Access |
taskaccess | ADCK |
??? | AD_Column_Access |
??? | AD_Language |
??? | AD_Message |
??? | AD_PrintTableFormat |
??? | AD_Scheduler |
??? | C_BP_Group |
??? | M_Product_Category |
??? | PA_ReportColumnSet |
??? | PA_ReportColumn |
??? | PA_Report |
??? | PA_ReportLineSet |
??? | PA_ReportLine |
??? | PA_ReportSource |
??? | AD_Client |
2Pack Any Table | ADCK Any Table |
??? | TEMPLATE |
Weak sides of 2pack according me
- Require integration at source code level with Adempiere, which means that if i need to customize any import functionality i must rebuild whole application or patch it.
- Carlos pointed that 2Pack can import records into any table, even customized.
- My comment is regarding main xml elements like: menu, window, tab, field, process, ... First time when i understood that i need to modify main xml elements was for JasperReports integration when i had to add new column into AD_Process table.
- I think that GenericPO which is responsible to import records into Any Table had one issue (I have to remember the exact reason. It was regarding Sequences or something related. ).
- Format of general imports is complicated.
- Main class(org.adempiere.pipo.PackInHandler) which handle import is very big(3800 lines) and complex, which require lot of time for developer to study it and makes modifications hard task.
- Since version 3.3.0 Low Heng Sin refactored org.adempiere.pipo.PackInHandler and now it is split into multiple classes.
- 2Pack uses SAX Parser which makes developer job harder as developer can't look forward or backward in XML tree.
Weak sides of ADCK according me
- It is external program, so user do not have such detailed control over security.
- It is harder for developer to work with it as do not have automatic changes extraction like 2Pack.
Ideas for extensions
SOUNDX support
Computerized Maintenance Management System
sf.net post CMMS is Computerized Maintenance Management System that designed specially for preventive maintenance for assets such as light vehicle, heavy equipment etc. so that company can create budgeting for repair and maintenance for their assets. Technicaly the module give alert to user when an asset have to get action such as replace fuel filter, oil filter or other item spareparts. Therefore these module related with inventory (internal use). Inventory will decrease its stock when user CMMS request for repair and maintenance their an asset.
Additional fields in I_Xxx tables
By: Carlos (globalqss)
Hi, every time I customize tables for a customer (almost all projects) I need to change the importers and/or make some tricks with not used fields on import. [Struggling today with this case]
Idea!
Not tested, but I think I could make a ModelValidator on udpate of I_ table (i.e. I_BPartner) and process the corresponding fields.
The other thing we could do is to add some free fields to every I_ table as wildcards to save customized or non considered fields and process them properly with the ModelValidator. Maybe just adding i.e. 10 fields FreeField01 through FreeField10 on the tables can make the trick.
Recent Adempiere changes
Avoid usage of clearing accounts
Tracker also contains a .doc file which show the effect of the change and he scripts to test it with GardenWorld.
Add more query method to MTable
Date: 2007-08-21
MTable has new method:
public Query createQuery(String whereClause, String trxName) { return new Query(this, whereClause, trxName); }
Jar file in 2pack/lib will be packed into Adempiere.jar
Starting from revision 3261 of trunk, any jar file that is pack of the lib folder of a 2pack package will be packed into the Adempiere.jar by the run_setup process. What this mean is, you just need to compile all libero specific code, pack it in a jar file and place it under the lib folder of the libero 2pack archive. Please look at the latest FAPack006.zip in the svn packages folder for an example.
<menu name="" > <menu name="Export Format" > <window name="Export Format" /> </menu> </menu>
Suggested menu:
<menu name="Quote-to-Invoice" > <menu name="Sales Orders" > <menu name="Rules" > <window name="" /> ... </menu> <menu name="Transact" > <window name="" /> ... </menu> <menu name="Report and Inquire" > <window name="" /> ... </menu> <menu name="Processes" > <window name="" /> ... </menu> </menu> <menu name="Shipments" > <menu name="Rules" > <window name="" /> ... </menu> <menu name="Transact" > <window name="" /> ... </menu> <menu name="Report and Inquire" > <window name="" /> ... </menu> <menu name="Processes" > <window name="" /> ... </menu> </menu> </menu>
How to add chache suport for persistent class?
Add class variable to hold reference to Cache.
public class MActivity extends X_C_Activity { /** Static Cache */ private static CCache<Integer, MActivity> s_cache = new CCache<Integer, MActivity>(Table_Name, 30);
Change getXxxx method
public static MActivity get(Properties ctx, int C_Activity_ID) { if (C_Activity_ID <= 0) { return null; } // Try cache MActivity activity = s_cache.get(C_Activity_ID); if (activity != null) { return activity; } // Load from DB activity = new MActivity(ctx, C_Activity_ID, null); if (activity.get_ID() == C_Activity_ID) { s_cache.put(C_Activity_ID, activity); } else { activity = null; } return activity; }
Hint for Defining Oracle View
* [sf.net post http://adempiere.svn.sourceforge.net/adempiere/?rev=11270&view=rev]
-'CO', --mrp.docstatus, +CAST('CO' AS nvarchar2(2)), --mrp.docstatus,