For example, add the Positions panel to the Opportunity module.
Important note, this guide is an example and does not provide a safe update as changes are made directly to the Opportunity module.
Developer mode must be enabled.
1 Step. In the Opportunity module, we create a one-to-many relationship (Main Opportunity module) with a subordinate Positions module.
Example picture below:
Relation:
Result:
Let’s remember that our relation has the name:
opportunities_aos_products_quotes_1
this name was generated automatically in the Studio.
Opportunity module name: Opportunities
Table in the database: opportunities
'relationship' => 'opportunities_aos_products_quotes_1',
'lhs_module' => 'Opportunities',
'lhs_table' => 'opportunities',
This is necessary for proper installation in /custom/modules/Opportunities/Ext/Vardefs/vardefs.ext.php
This will be discussed later.
Repair and Rebuild.
Step 2. Add fields related to the Positions module (LBL_CURRENCY,….LBL_GRAND_TOTAL
) to the panel of the Deals module in /custom/modules/Opportunities/metadata/editviewdefs.php
and /custom/modules/Opportunities/metadata/detailviewdefs.php
'lbl_editview_panel1' =>
array (
0 =>
array (
0 =>
array (
'name' => 'currency_id',
'studio' => 'visible',
'label' => 'LBL_CURRENCY',
),
),
1 =>
array (
0 =>
array (
'name' => 'line_items',
'label' => 'LBL_LINE_ITEMS',
),
),
2 =>
array (
0 =>
array (
'name' => 'total_amt',
'label' => 'LBL_TOTAL_AMT',
),
),
3 =>
array (
0 =>
array (
'name' => 'discount_amount',
'label' => 'LBL_DISCOUNT_AMOUNT',
),
),
4 =>
array (
0 =>
array (
'name' => 'subtotal_amount',
'label' => 'LBL_SUBTOTAL_AMOUNT',
),
),
5 =>
array (
0 =>
array (
'name' => 'shipping_amount',
'label' => 'LBL_SHIPPING_AMOUNT',
'displayParams' =>
array (
'field' =>
array (
'onblur' => 'calculateTotal(\'lineItems\');',
),
),
),
),
6 =>
array (
0 =>
array (
'name' => 'shipping_tax_amt',
'label' => 'LBL_SHIPPING_TAX_AMT',
),
),
7 =>
array (
0 =>
array (
'name' => 'tax_amount',
'label' => 'LBL_TAX_AMOUNT',
),
),
8 =>
array (
0 =>
array (
'name' => 'total_amount',
'label' => 'LBL_GRAND_TOTAL',
),
),
),
These values can be obtained from any module where Positions are used:
The result will be to display the panel in edit and view mode:
If we refresh the page we will see this result:
Step 3. Add translation of field headers for your language /custom/modules/Opportunities/language/en_us.lang.php
$mod_strings = array (
'LBL_OPPORTUNITIES_AOS_PRODUCTS_QUOTES_1_FROM_AOS_PRODUCTS_QUOTES_TITLE' => 'Line Items',
'LBL_IMPORT_LINE_ITEMS' => 'Import Line Items',
'LBL_LINE_ITEMS' => 'Line Items',
'LBL_GRAND_TOTAL' => 'Grand Total',
'LBL_TOTAL_AMT' => 'Total',
'LBL_TAX_AMOUNT' => 'Tax',
'LBL_SUBTOTAL_AMOUNT' => 'Subtotal',
'LBL_SHIPPING_AMOUNT' => 'Shipping',
'LBL_SHIPPING_TAX_AMT' => 'Shipping Tax',
'LBL_DISCOUNT_AMOUNT' => 'Discount',
'LBL_ADD_PRODUCT_LINE' => 'Add Product Line',
'LBL_ADD_SERVICE_LINE' => 'Add Service Line ',
'LBL_REMOVE_PRODUCT_LINE' => 'Remove',
'LBL_SERVICE_NAME' => 'Service',
'LBL_SERVICE_LIST_PRICE' => 'List',
'LBL_SERVICE_PRICE' => 'Sale Price',
'LBL_SERVICE_DISCOUNT' => 'Discount',
'LBL_VAT_AMT' => 'Tax Amount',
'LBL_TOTAL_PRICE' => 'Total',
'LBL_PRODUCT_QUANITY' => 'Quantity',
'LBL_PRODUCT_NAME' => 'Product',
'LBL_PART_NUMBER' => 'Part Number',
'LBL_PRODUCT_NOTE' => 'Note',
'LBL_PRODUCT_DESCRIPTION' => 'Description',
'LBL_LIST_PRICE' => 'List',
'LBL_DISCOUNT_AMT' => 'Discount',
'LBL_UNIT_PRICE' => 'Sale Price',
'LNK_LIST' => 'View Invoices',
'LBL_AOS_CONTRACTS' => 'Contracts',
'LBL_AOS_QUOTES' => 'Quotes',
);
Step 4. Add fields and connections to vardefs /custom/modules/Opportunities/Ext/Vardefs/vardefs.ext.php
For example:
$dictionary['Opportunity']['fields']['tax_amount'] =
array(
'required' => false,
'name' => 'tax_amount',
'vname' => 'LBL_TAX_AMOUNT',
'type' => 'currency',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 1,
'reportable' => true,
'len' => '26,6',
);
$dictionary['Opportunity']['fields']['shipping_tax_amt'] =
array(
'required' => false,
'name' => 'shipping_tax_amt',
'vname' => 'LBL_SHIPPING_TAX_AMT',
'type' => 'currency',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 0,
'reportable' => true,
'len' => '26,6',
'size' => '10',
'enable_range_search' => false,
'function' =>
array(
'name' => 'display_shipping_vat',
'returns' => 'html',
'include' => 'modules/AOS_Products_Quotes/Line_Items.php'
),
);
$dictionary['Opportunity']['fields']['shipping_amount'] =
array(
'required' => false,
'name' => 'shipping_amount',
'vname' => 'LBL_SHIPPING_AMOUNT',
'type' => 'currency',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 0,
'reportable' => true,
'len' => '26,6',
);
$dictionary['Opportunity']['fields']['subtotal_amount'] =
array(
'required' => false,
'name' => 'subtotal_amount',
'vname' => 'LBL_SUBTOTAL_AMOUNT',
'type' => 'currency',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 1,
'reportable' => true,
'len' => '26,6',
);
$dictionary['Opportunity']['fields']['currency_id'] =
array(
'required' => false,
'name' => 'currency_id',
'vname' => 'LBL_CURRENCY',
'type' => 'id',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => 0,
'audited' => false,
'reportable' => false,
'len' => 36,
'size' => '20',
'studio' => 'visible',
'function' =>
array(
'name' => 'getCurrencyDropDown',
'returns' => 'html',
'onListView' => true,
),
);
$dictionary['Opportunity']['fields']['discount_amount'] =
array(
'required' => false,
'name' => 'discount_amount',
'vname' => 'LBL_DISCOUNT_AMOUNT',
'type' => 'currency',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => 1,
'reportable' => true,
'len' => '26,6',
);
$dictionary['Opportunity']['fields']['line_items'] =
array(
'required' => false,
'name' => 'line_items',
'vname' => 'LBL_LINE_ITEMS',
'type' => 'function',
'source' => 'non-db',
'massupdate' => 0,
'importable' => 'false',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => 0,
'audited' => false,
'reportable' => false,
'inline_edit' => false,
'function' =>
array(
'name' => 'display_lines',
'returns' => 'html',
'include' => 'modules/AOS_Products_Quotes/Line_Items.php'
),
);
$dictionary['Opportunity']['fields']['total_amount'] =
array(
'required' => false,
'name' => 'total_amount',
'vname' => 'LBL_GRAND_TOTAL',
'type' => 'currency',
'massupdate' => 0,
'comments' => '',
'help' => '',
'importable' => 'true',
'duplicate_merge' => 'disabled',
'duplicate_merge_dom_value' => '0',
'audited' => false,
'reportable' => true,
'len' => '26,6',
'enable_range_search' => true,
'options' => 'numeric_range_search_dom',
);
$dictionary['Opportunity']['fields']['aos_products_quotes'] =
array(
'name' => 'aos_products_quotes',
'vname' => 'LBL_AOS_PRODUCT_QUOTES',
'type' => 'link',
'relationship' => 'opportunities_aos_products_quotes_1',
'module' => 'AOS_Products_Quotes',
'bean_name' => 'AOS_Products_Quotes',
'source' => 'non-db',
);
$dictionary['Opportunity']['fields']['opportunities_aos_products_quotes_1'] =
array(
'lhs_module' => 'Opportunities',
'lhs_table' => 'opportunities',
'lhs_key' => 'id',
'rhs_module' => 'AOS_Products_Quotes',
'rhs_table' => 'aos_products_quotes',
'rhs_key' => 'parent_id',
'relationship_type' => 'one-to-many',
);
$dictionary['Opportunity']['fields']['opportunities_aos_line_item_groups'] =
array(
'lhs_module' => 'Opportunities',
'lhs_table' => 'opportunities',
'lhs_key' => 'id',
'rhs_module' => 'AOS_Line_Item_Groups',
'rhs_table' => 'aos_line_item_groups',
'rhs_key' => 'parent_id',
'relationship_type' => 'one-to-many',
);
For example:
Step 5. Add logic for saving Positions in the Opportunity module (public function save($check_notify = false)) /modules/Opportunities/Opportunity.php
require_once('modules/AOS_Line_Item_Groups/AOS_Line_Item_Groups.php');
$productQuoteGroup = BeanFactory::newBean('AOS_Line_Item_Groups');
$productQuoteGroup->save_groups($_POST, $this, 'group_');
Important: this code is added to the main module and is not safe when updating SuiteCRM
Results:
All that remains is to add translations of the panels