Tried to add Line items to Opportunities

Hello,
I am trying to add Line items to Opportunities. I followed the instructions here::

What I have done so far:

  1. Created Opportunities module in custom, and copied over the vardefs.php and added line item and product quote props. Also added the relationships.
  2. Added the items in the language file.
  3. Copied in changes from invoices for the save functionailty
  4. Modified the detail and edit files.
    When I tried this , this is what I see

I also don’t see a script generated for the new data when I do a quick repair and rebuild. What am I missing here.

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
image

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

1 Like

Thank you for such a detailed answer. I truly appreciate it. I have got it working to the point of having the items appear. The line items however do not get saved in the DB. The totals (the data that is in the opportunities table itself is getting saved - just not the line items. Any idea why that could be?

Check step 5, this is save logic