Skip to content

Commit

Permalink
Merge pull request #1033 from compucorp/BTHAMM-31-correct-qot
Browse files Browse the repository at this point in the history
BTHAMM-31: Set sales order line items from backend
  • Loading branch information
olayiwola-compucorp authored Aug 19, 2024
2 parents 74b4d50 + 1edecbf commit 431cb63
Show file tree
Hide file tree
Showing 4 changed files with 170 additions and 41 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<?php

use Civi\Api4\PriceField;
use Civi\Api4\PriceFieldValue;
use Civi\Api4\PriceSet;
use CRM_Civicase_ExtensionUtil as E;
use CRM_Civicase_Service_CaseSalesOrderLineItemsGenerator as salesOrderlineItemGenerator;

Expand Down Expand Up @@ -27,6 +30,14 @@ public function run(CRM_Core_Form &$form, $formName) {
}
$lineItemGenerator = new salesOrderlineItemGenerator($salesOrderId, $toBeInvoiced, $percentValue);
$lineItems = $lineItemGenerator->generateLineItems();
$priceField = $this->getDefaultPriceSetFields();
\Civi::cache('short')->set('sales_order_line_items', $lineItems);

$submittedValues = [];
foreach ($lineItems as $index => &$lineItem) {
$submittedValues[] = $priceField[$index]['id'];
}
$form->assign('lineItemSubmitted', json_encode($submittedValues));

CRM_Core_Resources::singleton()
->addScriptFile(E::LONG_NAME, 'js/sales-order-contribution.js')
Expand Down Expand Up @@ -61,4 +72,25 @@ public function shouldRun(CRM_Core_Form $form, string $formName, ?int $salesOrde
&& !empty($salesOrderId);
}

/**
* Returns default contribution price set fields.
*
* @return array
* Array of price fields
*/
private function getDefaultPriceSetFields(): array {
$priceSet = PriceSet::get(FALSE)
->addWhere('name', '=', 'default_contribution_amount')
->addWhere('is_quick_config', '=', 1)
->execute()
->first();

return PriceField::get(FALSE)
->addWhere('price_set_id', '=', $priceSet['id'])
->addChain('price_field_value', PriceFieldValue::get(FALSE)
->addWhere('price_field_id', '=', '$id')
)->execute()
->getArrayCopy();
}

}
125 changes: 125 additions & 0 deletions CRM/Civicase/Hook/alterContent/AddSalesOrderLineToContribution.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
<?php

/**
* Adds sales order line items to the contribution.
*/
class CRM_Civicase_Hook_alterContent_AddSalesOrderLineToContribution {

/**
* Stores the sales order line items retrieved from the cache.
*
* @var array
*/
private $salesOrderLineItems;

/**
* Constructs the AddSalesOrderLindeToContribution class.
*
* @param string $content
* The content to be altered.
* @param array $context
* The context for the hook.
* @param string $tplName
* The name of the template.
*/
public function __construct(private &$content, private $context, private $tplName) {
$this->salesOrderLineItems = \Civi::cache('short')->get('sales_order_line_items');
}

/**
* Add sales order line items to the contribution.
*/
public function run() {
if (!$this->shouldRun()) {
return;
}

$this->addLineItems();
}

/**
* Adds sales order line items to the contribution.
*
* This method retrieves the sales order line items from the cache, and then
* updates the corresponding input fields in the contribution
* page's HTML content.
*/
public function addLineItems() {
$dom = new DomDocument();
$dom->loadHTML($this->content);

$table = $dom->getElementById('info');

// Delete the first row (index 0)
if ($table) {
$firstRow = $table->getElementsByTagName('tr')->item(0);
if ($firstRow) {
$table->removeChild($firstRow);
}
}

$rows = $table->getElementsByTagName('tr');
// Set the values in the DOM.
foreach ($this->salesOrderLineItems as $index => $item) {
if ($index < $rows->length) {
// Get the current row.
$row = $rows->item($index);

// Remove 'hiddenElement' class if it exists.
$row->setAttribute('class', str_replace('hiddenElement', '', $row->getAttribute('class')));

// Set the values from the line item array.
$inputs = $row->getElementsByTagName('input');
$selects = $row->getElementsByTagName('select');

foreach ($inputs as $input) {
$name = $input->getAttribute('name');

if (strpos($name, 'qty') !== FALSE) {
$input->setAttribute('value', $item['qty']);
}
elseif (strpos($name, 'tax_amount') !== FALSE) {
$input->setAttribute('value', $item['tax_amount']);
}
elseif (strpos($name, 'line_total') !== FALSE) {
$input->setAttribute('value', $item['line_total']);
}
elseif (strpos($name, 'unit_price') !== FALSE) {
$input->setAttribute('value', $item['unit_price']);
}
elseif (strpos($name, 'label') !== FALSE) {
$input->setAttribute('value', $item['label']);
}
}

foreach ($selects as $select) {
$name = $select->getAttribute('name');

if (strpos($name, 'financial_type_id') !== FALSE) {
foreach ($select->getElementsByTagName('option') as $option) {
if ($option->getAttribute('value') == $item['financial_type_id']) {
$option->setAttribute('selected', 'selected');
break;
}
}
}
}
}
}

\Civi::cache('short')->delete('sales_order_line_items');

$this->content = $dom->saveHTML();
}

/**
* Determines whether the hook should run.
*
* @return bool
* TRUE if the hook should run, FALSE otherwise.
*/
public function shouldRun() {
return $this->tplName === "CRM/Contribute/Page/Tab.tpl" && $this->context == "page" && !empty($this->salesOrderLineItems);
}

}
8 changes: 8 additions & 0 deletions civicase.php
Original file line number Diff line number Diff line change
Expand Up @@ -646,4 +646,12 @@ function civicase_civicrm_alterContent(&$content, $context, $tplName, &$object)
$content = str_replace("#_qf_Activity_upload-top, #_qf_Activity_upload-bottom", "#_qf_Activity_upload-top, #_qf_Activity_upload-bottom, #_qf_Activity_submit-bottom, #_qf_Activity_submit-top, #_qf_Activity_refresh-top, #_qf_Activity_refresh-bottom", $content);
}
}

$hooks = [
new CRM_Civicase_Hook_alterContent_AddSalesOrderLineToContribution($content, $context, $tplName),
];

foreach ($hooks as $hook) {
$hook->run();
}
}
46 changes: 5 additions & 41 deletions js/sales-order-contribution.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
(function ($, _) {
const waitForElement = function ($, elementPath, callBack) {
window.setTimeout(function () {
if ($(elementPath).length) {
callBack($, $(elementPath));
} else {
window.waitForElement($, elementPath, callBack);
}
}, 500);
(new window.MutationObserver(function () {
callBack($, $(elementPath));
})).observe(document.querySelector(elementPath), {
attributes: true
});
};

$(document).one('crmLoad', async function () {
Expand All @@ -18,7 +16,6 @@
const lineItems = JSON.parse(params.line_items);
const caseCustomField = params.case_custom_field;
const quotationCustomField = params.quotation_custom_field;
let count = 0;

const apiRequest = {};
apiRequest.caseSalesOrders = ['CaseSalesOrder', 'get', {
Expand All @@ -37,14 +34,6 @@
CRM.api4(apiRequest).then(function (batch) {
const caseSalesOrder = batch.caseSalesOrders[0];

lineItems.forEach(lineItem => {
setTimeout(
() => addLineItem(lineItem.qty, lineItem.unit_price, lineItem.label, lineItem.financial_type_id, lineItem.tax_amount),
2000
);
});

$('input[id="total_amount"]').trigger('change');
$('#contribution_status_id').val(batch.optionValues[0].value);
$('#source').val(`Quotation ${caseSalesOrder.id}`).trigger('change');
$('#contact_id').select2('val', caseSalesOrder.client_id).trigger('change');
Expand All @@ -63,30 +52,5 @@
CRM.$('form#Contribution').css('visibility', 'visible');
});
}

/**
* @param {number} quantity Item quantity
* @param {number} unitPrice Item unit price
* @param {string} description Item description
* @param {number} financialTypeId Item financial type
* @param {number|object} taxAmount Item tax amount
*/
function addLineItem (quantity, unitPrice, description, financialTypeId, taxAmount) {
const row = $($(`tr#add-item-row-${count}`));
row.show().removeClass('hiddenElement');
quantity = +parseFloat(quantity).toFixed(10); // limit to 10 decimal places

$('input[id^="item_label"]', row).val(ts(description));
$('select[id^="item_financial_type_id"]', row).select2('val', financialTypeId);
$('input[id^="item_qty"]', row).val(quantity);

const total = quantity * parseFloat(unitPrice);

$('input[id^="item_line_total"]', row).val(CRM.formatMoney(total, true));
$('input[id^="item_tax_amount"]', row).val(taxAmount);
$('input[id^="item_unit_price"]', row).val(unitPrice).trigger('change');

count++;
}
});
})(CRM.$, CRM._);

0 comments on commit 431cb63

Please sign in to comment.