Skip to content

Commit

Permalink
Merge pull request #1038 from compucorp/BTHA-188-fix-qto
Browse files Browse the repository at this point in the history
BTHA-188: Fix quotes to order feature issues
  • Loading branch information
olayiwola-compucorp authored Aug 22, 2024
2 parents 6fabbaf + 3ef0206 commit cc9d86b
Show file tree
Hide file tree
Showing 8 changed files with 210 additions and 40 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);
}

}
2 changes: 1 addition & 1 deletion CRM/Civicase/Service/CaseSalesOrderLineItemsGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ private function lineItemToContributionLineItem(array $item) {
'entity_table' => 'civicrm_contribution',
'financial_type_id' => $item['financial_type_id'],
'line_total' => round($item['total'], 2),
'unit_price' => round($item['unit_price'], 2),
'unit_price' => $item['unit_price'],
];
}

Expand Down
5 changes: 4 additions & 1 deletion CRM/Civicase/Service/CaseSalesOrderOpportunityCalculator.php
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,10 @@ private function calculateOpportunityFinancialAmount($contributions) {
private function getContributions($caseId) {
$contributions = Contribution::get(FALSE)
->addSelect('*', 'Opportunity_Details.Quotation')
->addWhere('Opportunity_Details.Case_Opportunity', '=', $caseId);
->addWhere('Opportunity_Details.Case_Opportunity', '=', $caseId)
->addJoin('CaseSalesOrder AS case_sales_order', 'INNER',
['Opportunity_Details.Quotation', '=', 'case_sales_order.id']
);

if ($this->deletingContributionId !== NULL) {
$contributions->addWhere('id', '!=', $this->deletingContributionId);
Expand Down
13 changes: 13 additions & 0 deletions civicase.php
Original file line number Diff line number Diff line change
Expand Up @@ -632,3 +632,16 @@ function civicase_civicrm_searchTasks(string $objectName, array &$tasks) {
}
}
}

/**
* Implements hook_civicrm_alterContent().
*/
function civicase_civicrm_alterContent(&$content, $context, $tplName, &$object) {
$hooks = [
new CRM_Civicase_Hook_alterContent_AddSalesOrderLineToContribution($content, $context, $tplName),
];

foreach ($hooks as $hook) {
$hook->run();
}
}
12 changes: 12 additions & 0 deletions js/contribution-entityref-field.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,18 @@
if (field.value) {
$(`[name^=${field.name}_]`).val(field.value).trigger('change');
}

$(`[name^=${field.name}_]`).on('change', field, function (event) {
const f = event.data;

$(`[name^=${f.name}_]`)
.attr('placeholder', f.placeholder)
.attr('disabled', false)
.crmEntityRef({
entity: f.entity,
create: false
});
});
});
});
});
Expand Down
52 changes: 14 additions & 38 deletions js/sales-order-contribution.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
});
};

$(document).one('crmLoad', function () {
$(document).one('crmLoad', async function () {
const params = CRM.vars['uk.co.compucorp.civicase'];
const salesOrderId = params.sales_order;
const salesOrderStatusId = params.sales_order_status_id;
Expand All @@ -16,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 @@ -29,56 +28,33 @@
}];

if (Array.isArray(lineItems)) {
CRM.$.blockUI();
CRM.$('form#Contribution').css('visibility', 'hidden');
await new Promise(resolve => setTimeout(resolve, 1000));
CRM.api4(apiRequest).then(function (batch) {
const caseSalesOrder = batch.caseSalesOrders[0];

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

$('#total_amount').val(0);
$('#lineitem-add-block').show().removeClass('hiddenElement');
$('#contribution_status_id').val(batch.optionValues[0].value);
$('#source').val(`Quotation ${caseSalesOrder.id}`).trigger('change');
$('#contact_id').select2('val', caseSalesOrder.client_id).trigger('change');
$('input[id="total_amount"]', 'form.CRM_Contribute_Form_Contribution').trigger('change');
$(`<input type="hidden" value="${salesOrderId}" name="sales_order" />`).insertBefore('#source');
$(`<input type="hidden" value="${toBeInvoiced}" name="to_be_invoiced" />`).insertBefore('#source');
$(`<input type="hidden" value="${percentValue}" name="percent_value" />`).insertBefore('#source');
$(`<input type="hidden" value="${salesOrderStatusId}" name="sales_order_status_id" />`).insertBefore('#source');
$('#totalAmount, #totalAmountORaddLineitem, #totalAmountORPriceSet, #price_set_id, #choose-manual').hide();
$(' #totalAmountORaddLineitem, #totalAmountORPriceSet, #price_set_id, #choose-manual').hide();

if ($('#customData')) {
CRM.$(`[name^=${caseCustomField}_]`).val(caseSalesOrder.case_id).trigger('change');
CRM.$(`[name^=${quotationCustomField}_]`).val(caseSalesOrder.id).trigger('change');
}
waitForElement($, '#customData', function ($, elem) {
$(`[name^=${caseCustomField}_]`).val(caseSalesOrder.case_id).trigger('change');
$(`[name^=${quotationCustomField}_]`).val(caseSalesOrder.id).trigger('change');
CRM.$(`[name^=${caseCustomField}_]`).val(caseSalesOrder.case_id).trigger('change');
CRM.$(`[name^=${quotationCustomField}_]`).val(caseSalesOrder.id).trigger('change');
});
}).finally(() => {
CRM.$.unblockUI();
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_unit_price"]', row).val(unitPrice);
$('input[id^="item_line_total"]', row).val(CRM.formatMoney(total, true));

$('input[id^="item_tax_amount"]', row).val(taxAmount);

count++;
}
});
})(CRM.$, CRM._);
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@
});
</script>
{/literal}
{literal}
<style>
#bootstrap-theme #status {
appearance: auto;
}
</style>
{/literal}

0 comments on commit cc9d86b

Please sign in to comment.