Ecosoft/Customization for Bicycle Manufacturer Case Study

From ADempiere
Jump to: navigation, search
This Wiki is read-only for reference purposes to avoid broken links.

This page is under construction --Kittiu 16:18, 20 September 2010 (UTC)


This page contain specific customization made for Bicycle Manufacturer Case Study by ecosoft. All customizations are made without touching the core application, using customization.jar techinque

Source code (compiled to customization.jar) of this project will be updated to @ Bicycle SVN

Enable Print & Print Preview Buttons With specific Logic


As of AD-360LTS, the Print and Print Preview Button is still not capable of enable/disable based on Document Status or other conditions, but only based on 1) report existence for that document type and 2) whether user has right to that report.

In our project, we have the need to prevent Document Forms (i.e., sales order, invoice, receipt) from being printed out when the document is not yet completed (or closed or voided) (DocStatus = CO, CL). There are some other alternative without touching the code, such as, have the status printout in big letters, so that people can spot it by their eye. But this is rejected by the client.

Requirement Summary

  • Use System Configurator window to control whether to use this feature.
  • Print and Print Preview button will be enabled only when the condition set is met. For example, we might want print buttons to enable only when document status is Complete/Closed/Voided, but except MM Shipment and AR Receipt Form that will be enabled in all DocStatus.


  • Modify isPrinted() function to also check for the ENABLE_PRINT_BUTTON_WITH_LOGIC’s logic
	public boolean isPrinted()
		// Start of Modification - Enable Print Buttons with some logics
		 * return m_vo.AD_Process_ID != 0; 
		if (m_vo.AD_Process_ID == 0) {
			return false;
		else { // Check if Status is on the Enable List
			String docstatuslist = MSysConfig.getValue("ENABLE_PRINT_BUTTON_WITH_LOGIC", null, Env.getAD_Client_ID(m_vo.ctx), Env.getAD_Org_ID(m_vo.ctx));
			if (docstatuslist != null && docstatuslist.toString().length() > 0)
				return Evaluator.evaluateLogic(this, docstatuslist);
			else // No logic defined, back to normal
				return true;
		// End of Modification - Enable Print Buttons with some logics
	}	//	isPrinted
  • Modify getTitle() function add 2 lines to also set enable the button,
    • aPrint.setEnabled(m_curTab.isPrinted());
    • aPrintPreview.setEnabled(m_curTab.isPrinted());
	public String getTitle()
		// Start of Modification (add) - Enable Print Buttons with some logics
		// End of Modification - Enable Print Buttons with some logics
3) Add new record in System Configurator window
  • Search Key: @C_DocType_ID@=120 | @C_DocType_ID@=119 | @DocStatus@='CO' | @DocStatus@='CL' | @DocStatus@='VO'
  • Note: 120, 119 is the c_doctype_id, many change from system to system. Check Document Type window for the current id.

Sysconfig enable print.jpg


  • Discussion about this feature in forum [1]
  • In tracker, but not trunkable, as there is another alternative using rule script (applicable but not same result) [2]
  • Sample of the rule script in Java [3]

Simple One Time Business Partner Credit Approval


Given a Business Partner with Credit Status = Credit Watch. In the existing functionality,

  • If user creates a Sales Order (SO) for this Business Partner with Sales Amount more than the credit available (remaining),
  • He/she will not be able to complete the document. Clicking on Complete button will give warning message Credit On Hold… and Document Status will be changed to Invalid

As per existing functionality, the supervisor / admin will have to login and make change to Credit Status of this BP in Business Partner window to “Credit OK” or to increase the Credit Limit amount, and then supervisee will be able to complete document.

Currently, there is no built-in way to do one time approval in ADempiere.

This enhancement is to create a simple way (by select a CheckBox) for Supervisor of the SO creator to review and if everything is ok, make approval directly to this specific SO by ticking a CheckBox. And as the checkbox is ticked, the approval process will be ignored.

Remarks: At first, we are looking at using standard Workflow, but eventually found some difficulties,

  • Doc Process WF: This type of workflow is not even fired yet, as AD already stop it when check on Credit Limit.
  • Doc Value WF: This type of workflow will always send message to the Invoker (which is the user himself, no use). There is no way to specify the target approver.
  • This enhancement is not submitted as FR, as it is quite specific to this customer

Requirement Summary

Following is the TO-BE process for SO Credit Approval.

  • User creates SO (Sales Order), select BP (Business Partner) and add SO Lines with the total amount exceed Credit Available for this BP.
  • User clicks Complete Button to try to complete the document. The system will not allow and give warning message. DocStaus changes to Invalid. Without changing of the amount of SO lines, he/she will not able to continue.
  • User will notify his/her supervisor (manually) to approve the underline SO number.
  • Supervisor, will login to ADempiere as normal, open up the problem SO number, review and make decision.
    • If Approve,
      • Supervisor will click on “Credit Approved?” checkbox at the bottom of page and Save this document.
      • Supervisor will either notify his/her supervisee to go back and complete it, or he/she will complete by him/herself.
      • With the “Credit Approved?” checkbox checked, ADempiere should not give any warning.
      • End of the completion process.
    • If not Approve,
      • Supervisor simply does not do anything, and either go back to his/her to void it. Or he/she could void it by him/herself.
      • Supervisor simply does not do anything, and either
        • Keep it as ‘Invalid’ status and approve it when BP settles payment and their credit is available.
        • Or void it by him/herself or even go back to his/her supervisee to do it.


  • Since we do not use the Workflow to track, but use a simple Credit Approved CheckBox. Do make sure that,


  • This checkbox is visible only when the document status is Invalid
  • This checkbox should be Editable only for the specified supervisor but show as Read Only for other users at all time.
  • When SO document is copied as new SO, this checkbox will always be unchecked (although the original is checked)
  • Even this SO is already approved, but if user change Business Partner or the Line Amount (so the credit available is changed), this checkbox should be cleared.


1) Use Application Dictionary to setup proper UI
  • Table and column widnow --> IsCreditApproved column in table C_Order set to editable.
update ad_column set isupdateable = 'Y' where ad_column_id = 2176;
  • Window Tab & Field window --> add Credit Approved field at the bottom of window.
update ad_field
set seqno = 540, issameline = 'Y', isdisplayed = 'Y', displaylogic = '@OrderType@=''SO''&@DocStatus@=''IN'''
where ad_field_id = 1088;
  • Use Table and Column window and set Readonly logic for Credit Approved field, Readonly for end users, and Editable for approving users.
update ad_column 
set readonlylogic = '@#AD_User_Name@!''nantachai'' & @#AD_User_Name@!''SuperUser''' 
where ad_column_id = 2176;
2) Setup Rules Scripts to ensure that if user change BP or total amount, Credit Approved will be unchecked
  • Rule: Reset_IsCreditApproved
import org.compiere.util.DB;
String sql = "update c_order set iscreditapproved = 'N' where c_order_id = "+ A_Tab.getValue("C_Order_ID");
int no = DB.executeUpdate(sql);
result = "";

  • Table and Column window --> Assign this rule to
    • C_Order.C_BPartner_ID: @script:beanshell:Reset_IsCreditApproved
    • C_OrderLine.LineNetAmt: @script:beanshell:Reset_IsCreditApproved
  • Modify method prepareIt() so that, if IsCreditApproved field is ‘Y’, then by pass the credit checking.
// -- if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(grandTotal)))
if (MBPartner.SOCREDITSTATUS_CreditHold.equals(bp.getSOCreditStatus(grandTotal)) && this.isCreditApproved() == false)

DocAction to show only Prepare when DocStatus = Draft


Each Document Type, there is a certain list of DocAction defined in ADempiere. Although we can use Role Security / Document Action to control list of action based on role, we can't restrict DocAction based on DocStatus. In our case, when document status is "Prepare" we don't want want end user to complete it immediately (double check routine). Carlos Ruiz have discuss it here.

Requirement Summary

For Order Window

  • When DocStatus = “Draft”
    • Click on DocAction button
    • Show only “Prepare” action
  • When DocStatus != “Draft”
    • Click on DocAction button
    • Show more actions, i.e., Prepare, Complete, Close, Void


  • Implement DocOption interface
public class MOrder extends X_C_Order implements DocAction, DocOptions
  • Add customizeValidActions() function to overwrite the existing list of action.
     * Customize Valid Actions
     * @param docStatus
     * @param processing
     * @param orderType
     * @param isSOTrx
     * @param AD_Table_ID
     * @param docAction
     * @param options
     * @return Number of valid options
    public int customizeValidActions (String docStatus, Object processing, 
                    String orderType, String isSOTrx, int AD_Table_ID, String[] docAction, String[] options, int index) {
    	// If status = Drafted, only show "Prepare" in the list
    	if (docStatus.equals(DocumentEngine.STATUS_Drafted)) {
    		// 1. Remove all
    		for (int i = 0; i < options.length; i++) {
    			options[i] = null;
    		// 2. Add Prepare
    		options[0] = DocumentEngine.ACTION_Prepare;
    		index = 1;
    	return index;

2) For Order windows, make sure default is set to "Prepare"

Overwriting UOM Conversion Rate for Purchase Cycle (workaround for Double UOM)


For some material (i.e., steel), purchased as one unit (i.e., KG) and receive in another unit (i.e., pieces). But when receiving, the conversion rate can vary slightly from what has been setup (in UOM Conversion Tab).

For example, purchase 1 Kg of steal = 101 pieces on average conversion rate. But when receive material it could be 99 pieces. As such, when receiving we need to overwrite the conversion rate and keep that overwriting rate to this receiving transaction.

In standard version of ADempeire, for the whole Purchase Cycle (Requisition to Invoice), ordering a product with UOM other than the smallest product UOM is not allowed. Selecting product will set default product UOM and it is unchangeable.

But with this enhancement, user will be able to set the needed UOM on PO --> Receipt --> Invoice (Vendor) and hence, we need to modify some internal logic to accommodate it as existing logic for Purchasing Cycle was written with smallest product UOM in mind.

(Note that, in Requisition window, user still need to use the smallest Product UOM as default)

Requirement Summary

For Purchase Order Line Window
  • In Purchase Onrder Line, either created manually, or using Create PO from Requisition Process, the PO Line will now allow user to select the needed UOM.
  • On changing UOM, i.e., from Piece to Kg, as oppose to the existing logic, which will calculate the new PO Quantity. Quantity will be recalculated to reflect the new UOM and PO Quantity will stay the same to reflect qty for smallest product UOM.
  • This make more sense as the Requisition window user must request the smallest unit, i.e. 1000 pieces. As such, in PO window, changing from piece to Kg should calculate the Quantity (i.e., in Kg), not the PO Quantity (i.e., in piece). All is based on the standard product UOM conversion rate.
  • The Line Amount = Price X Quantity (per selected UOM)
For Material Receipt Line window
  • Introduce new field, Overwrite Rate. User can now receive material in non-standard product UOM conversion rate.
  • When Receipt user is allowed to change either the Movement Quantity (smallest product UOM) or the Quantity (ordering UOM) or both. And the Overwrite Rate will be adjusted.
  • For example, in UOM conversion of a product, 1 Kg = 101 pieces, but in reality, user might receive only 99 pieces for this 1 Kg.
  • New Overwrite Rate will absorb that, and will be stored in this transaction for future reference.
  • Note that, if the Ordering UOM and Product UOM is the same, the Overwrite Rate will equal to 1 and it will be disabled.

Overwrite Conversion Rate.jpg

For Invoice (Vendor) window
  • In case, Invoice Line is copied from Receipt, the Quantity and Quantity Invoiced will be read-only. Note that, the standard conversion rate is not used, as it could be overwritten when on receipt of material in previous step.
  • In case, Invoice Line is created manually, the Quantity will be editable and Quantity Invoiced (smallest product UOM) will be calculated based on standard conversion rate.
  • User can adjust the Price (per selected UOM) and the Unit Price (per smallest product UOM) will be calculated based on the overwritten UOM rate (not from standard conversion rate).
  • The Line Amount = Price X Quantity (per selected UOM)

Note: Must test for Sales Cycle as well, as table Order and Inout is used for both cycles.


1) Create new TextBox "Conversion Rate Overwrite" in Receipt Line tab
  • Create Element OverwriteRate_Overwrite Rate
  • Create new Column OverwriteRate_Overwrite Rate under table M_InOutLine_Shipment/Receipt Line --> number (22), Default=1, Readonly Logic='@OverwriteRate@=1', Callout=org.compiere.model.CalloutInOut.qty
  • Create new field OverwriteRate_Overwrite Conversion Rate next to field Movement Quantity in Receipt Line_Material Receipt window
  • Mark this OverwriteRate and Movement Quantity to always displayed (no Display Logic)
  • All from running --> SQL Script [4]
2) Configure AD Fields
  • Set Movement Quantity field in Receipt Line tab to be editable (from readonly)
  • Set UOM field in PO Line tab to be editable (from readonly)
  • Set rule of Quantity field in Invoice Line tab to be readonly (from editable) if the it is has reference to PO or Receipt Document
  • All from running --> SQL Script [5]
3) Overwrite Java files in customization.jar
  • All on top of 360LTS before any patches --> Revision 14277

Test Steps

  1. Create Requisition for a product (stored in pieces, can convert to Kg) in UOM pieces
  2. Complete the Requisition
  3. Create PO from this Requisition --> PO and Lines is created in pieces
  4. On the PO Line, change UOM to Kg --> Quantity is recalculated (Kg), PO Quantity stay the same (pieces) --> Price is changed (Kg), Unit Price stays (pieces)
  5. On the PO Line, change Quantity to make it round number --> PO Quantity change (pieces) --> Price and Unit Price stays the same --> Line amount change (new Qty X Price)
  6. Complete the PO
  7. Create new Material Receipt,
  8. Click on Create Lines From button to Create Receipt Line from the PO
  9. On Receipt Line, change Movement Quantity (piece) to make it round number (as receipt from Vendor) --> Quantity stays the same (Kg) --> Overwrite Rate is changed to absorb the variant.
  10. Complete the MM Receipt
  11. Create new AP Invoice (Vendor)
  12. Click on Create Lines From button to Create Receipt Line from the Receipt or PO
  13. On Invoice Line, Quantity and Quantity Invoiced is not changeable. Note that the Unit Price (piece) is changed based on the new Overwrite Rate.
  14. Change Price (per Kg), the Unit Price (per piece) will be recalculated, follow the new Overwrite Rate (rather than standard UOM rate) --> Line amount change (Qty X new Price)
  15. Complete the Invoice

Note: Make sure that it is backward compatible with other cases, and the Sales Cycle.

Print Billing and Print Receipt in bulk


This feature is the request from customer, to print Payment Document (Billing & Receipt) in bulk. Currently, ADempiere already poscess the same for Print Invoices.

Requirement Summary

Process PrintBilling.jpg Process PrintReceipt.jpg

  • Generally, the function will be similar to Print Invoice process, but remove send Email PDF functionality (Payment document do not have User to send email to)
  • Separate into 2 processes, 1) Print Billings and 2) Print Receipt
  • Underlining there will be only one java process, which is, used for both.
  • If user choose Print Billing, only Billing document (Payment with docstatus = 'Draft') will be selected to print.
  • If user choose Print receipts, only Receipt document (Payment with docstatus = 'In Progress' / 'Complete' / 'Close') will be selected to print.

Note: Specific to this project, we use Payment window for both Billing and Receipt


1) Apply a printing bug fix [6]
  • This fix will ensure that JasperReport is used when do the bulk printing. Otherwise, it will use normal Print Format, although Jasper is in place.
2) [7]
  • New process class (initial copied from for printing Billing and Receipt in bulk.
  • It is similar to Invoice Print, but do note that this class will be used for both Billing and Receipt Forms.
3) Configuration in Report & Process window, to create 2 new processes window, Billing_Print and Receipt_Print.
4) Register these process in menu, and give access right.

Make-to-Order Enhancement


In standard manufacturing feature, if the Product's BOM type is Make-to-Order, we can complete the Sales Order in order to Launch the Manufacturing Order directly without having to go through the MRP process. The logic of getting the Product BOM and Workflow is as following,

  1. If there is product planning data for the product, it will get the BOM and Workflow from there and issue the Manufacturing Order.
  2. But if there is no Product Planning data, it will find the Workflow with exactly the same name (value) as the selected product to issue the MO.

However with this approach, we will need to have a new workflow per each of the new make-to-order product.

Requirement Summary

The enhancement is intended for reusabibility of BOM and Workflow. User can still use the existing approach, by creating new a new BOM and a new Workflow and relate them in Product Planning Data for each new make to order as usual. But in addition, user can also create more than 1 BOMs for the same product, and reuse the same workflow. And as such, during the Sales Order process, product has BOM of type Make-To-Order, the BOM and Workflow field will be displayed. User will have to specify BOM and Workflow right at each Sales Order Line.


  • Simply deploy the package using 2Pack.
  • Following objects are deployed
    • 2 fields in Sales Order Line, 1) BOM & Formulas 2) Workflow
    • A callout function, CalloutRaja.setMakeToOrderBOM() called from Product Field.

How to use?

  1. First, make sure the Manufacturing Order is active.
  2. Define product BOM Type = Make-to-Order and BOM Use = Manufacturing
  3. Define a new Manufacturing Workflow for this product
  4. Relate this BOM and Workflow in Product Planning data
  5. When new Make-to-Order arrive,
    1. User can define more BOMs using the existing BOM as template.
  6. On Sales Order / Sales Order Line, select product for make-to-order
    1. BOM and Workflow field will now be visible.
    2. User select BOM and Workflow
  7. Complete the Sales Order and the Manufacturing Order will be issued.