Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

BTHAB-184: Link Invoice to Quotations/Case using custom fields #972

Merged
merged 5 commits into from
Sep 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 55 additions & 0 deletions CRM/Civicase/Hook/BuildForm/AddEntityReferenceToCustomField.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<?php

use CRM_Civicase_ExtensionUtil as E;

/**
* Converts Opportunity Details Field to Entity Reference.
*/
class CRM_Civicase_Hook_BuildForm_AddEntityReferenceToCustomField {

/**
* Converts Opportunity Details Field to Entity Reference.
*
* @param CRM_Core_Form $form
* Form Class object.
* @param string $formName
* Form Name.
*/
public function run(CRM_Core_Form &$form, $formName) {
if (!$this->shouldRun($formName)) {
return;
}

$customFields[] = [
'name' => CRM_Core_BAO_CustomField::getCustomFieldID('Case_Opportunity', 'Opportunity_Details', TRUE),
'entity' => 'Case',
'placeholder' => '- Select Case/Opportunity -',
];

$customFields[] = [
'name' => CRM_Core_BAO_CustomField::getCustomFieldID('Quotation', 'Opportunity_Details', TRUE),
'entity' => 'CaseSalesOrder',
'placeholder' => '- Select Quotation -',
];

\Civi::resources()->add([
'scriptFile' => [E::LONG_NAME, 'js/contribution-entityref-field.js'],
'region' => 'page-header',
]);
\Civi::resources()->addVars('civicase', ['entityRefCustomFields' => $customFields]);
}

/**
* Checks if the hook should run.
*
* @param string $formName
* Form Name.
*
* @return bool
* True if hook should run, otherwise false.
*/
public function shouldRun($formName) {
return $formName === "CRM_Contribute_Form_Contribution";
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ public function run(CRM_Core_Form &$form, $formName) {
'to_be_invoiced' => $toBeInvoiced,
'percent_value' => $percentValue,
'line_items' => json_encode($lineItems),
'quotation_custom_field' => CRM_Core_BAO_CustomField::getCustomFieldID('Quotation', 'Opportunity_Details', TRUE),
'case_custom_field' => CRM_Core_BAO_CustomField::getCustomFieldID('Case_Opportunity', 'Opportunity_Details', TRUE),
]);
}

Expand Down
12 changes: 12 additions & 0 deletions Civi/Api4/Action/CaseSalesOrder/ContributionCreateAction.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Civi\Api4\CaseSalesOrder;
use Civi\Api4\CaseSalesOrderContribution as Api4CaseSalesOrderContribution;
use Civi\Api4\Contribution as Api4Contribution;
use Civi\Api4\Generic\AbstractAction;
use Civi\Api4\Generic\Result;
use Civi\Api4\Generic\Traits\DAOActionTrait;
Expand Down Expand Up @@ -178,6 +179,17 @@ private function linkCaseSalesOrderToContribution(int $salesOrderId, int $contri
->addValue('percent_value', $this->percentValue)
->addValue('contribution_id', $contributionId)
->execute();

$salesOrder = CaseSalesOrder::get()
->addWhere('id', '=', $salesOrderId)
->execute()
->first();

Api4Contribution::update()
->addValue('Opportunity_Details.Case_Opportunity', $salesOrder['case_id'])
->addValue('Opportunity_Details.Quotation', $salesOrderId)
->addWhere('id', '=', $contributionId)
->execute();
}

/**
Expand Down
2 changes: 1 addition & 1 deletion ang/afsearchQuotationInvoices.aff.html
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
<div af-fieldset="">
<crm-search-display-table search-name="Quotation_Invoices" display-name="Quotation_Invoices" filters="{'CaseSalesOrderContribution_CaseSalesOrder_case_sales_order_id_01.case_id': routeParams.caseId}"></crm-search-display-table>
<crm-search-display-table search-name="Quotation_Contributions" display-name="Contributions_Table_1" filters="{'Opportunity_Details.Case_Opportunity': routeParams.caseId, 'Opportunity_Details.Quotation': options.quotation_ids}"></crm-search-display-table>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ <h1 ng-if="view !== 'contact'" crm-page-title>{{ ts('Manage Quotations') }}</h1>
{{:: ts('Create Quotation') }}
</a>

<div class="panel panel-default">
<div class="panel panel-default quotation__list">
<div class="panel-body">
<div ng-switch="view">
<afsearch-contact-quotations options="{contact_id: contactId}" ng-switch-when="contact"> </afsearch-contact-quotations>
Expand All @@ -34,4 +34,8 @@ <h1 ng-if="view !== 'contact'" crm-page-title>{{ ts('Manage Quotations') }}</h1>
.af-field-range-sep {
margin: 0em 1em;
}
#bootstrap-theme.civicase__container .quotation__list ul.dropdown-menu {
right: 0;
left: auto;
}
</style>
44 changes: 44 additions & 0 deletions api/v3/CaseSalesOrder/Get.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

/**
* @file
* CaseSalesOrder.Get file.
*/

/**
* CaseSalesOrder.Get API.
*
* @param array $params
* API Params.
*
* @return array
* API result descriptor
*
* @see civicrm_api3_create_success
* @see civicrm_api3_create_error
*
* @throws API_Exception
*/
function civicrm_api3_case_sales_order_get($params) {
$sql = CRM_Utils_SQL_Select::fragment();
$salesOrders = _civicrm_api3_basic_get(_civicrm_api3_get_BAO(__FUNCTION__), $params, FALSE, 'CaseSalesOrder', $sql, TRUE);

return civicrm_api3_create_success($salesOrders, $params, 'CaseSalesOrder', 'get');
}

/**
* CaseSalesOrder.Get API specification (optional).
*
* This is used for documentation and validation.
*
* @param array $spec
* description of fields supported by this API call.
*
* @see http://wiki.civicrm.org/confluence/display/CRM/API+Architecture+Standards
*/
function _civicrm_api3_case_sales_order_get_spec(&$spec) {
$fields = CRM_Civicase_BAO_CaseSalesOrder::fields();
foreach ($fields as $fieldname => $field) {
$spec[$fieldname] = $field;
}
}
88 changes: 88 additions & 0 deletions api/v3/CaseSalesOrder/Getlist.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php

/**
* @file
* CaseSalesOrder.Getlist API.
*/

use Civi\Api4\CaseSalesOrder;

/**
* CaseSalesOrder.Getlist API specification (optional).
*
* This is used for documentation and validation.
*
* @param array $params
* Description of fields supported by this API call.
* @param array $apiRequest
* API requesr.
*
* @see https://docs.civicrm.org/dev/en/latest/framework/api-architecture/
*/
function _civicrm_api3_case_sales_order_getlist_spec(&$params, $apiRequest) {
require_once 'api/v3/Generic/Getlist.php';
_civicrm_api3_generic_getlist_spec($params, $apiRequest);
}

/**
* CaseSalesOrder.Getlist API.
*
* @param array $params
* API Params.
*
* @return array
* API result descriptor
*
* @see civicrm_api3_create_success
*
* @throws API_Exception
*/
function civicrm_api3_case_sales_order_getlist($params) {
require_once 'api/v3/Generic/Getlist.php';
$apiRequest = [
'version' => 3,
'entity' => 'CaseSalesOrder',
'action' => 'getlist',
'params' => $params,
];

return civicrm_api3_generic_getList($apiRequest);
}

/**
* Get case sales order list output.
*
* @param array $result
* API Result to format.
* @param array $request
* API Request.
*
* @return array
* API Result
*
* @see _civicrm_api3_generic_getlist_output
*/
function _civicrm_api3_case_sales_order_getlist_output($result, $request) {
$output = [];
if (!empty($result['values'])) {
foreach ($result['values'] as $row) {
$caseSalesOrder = CaseSalesOrder::get()
->addSelect('contact.display_name', 'quotation_date')
->addJoin('Contact AS contact', 'LEFT', ['contact.id', '=', 'client_id'])
->addWhere('id', '=', $row['id'])
->execute()
->first();

$data = [
'id' => $row[$request['id_field']],
'label' => "Client: {$caseSalesOrder['contact.display_name']}",
'description' => [
strip_tags($row['description']),
],
];
$data['description'][] = "Quotation Date: " . CRM_Utils_Date::customFormat($caseSalesOrder['quotation_date']);
$output[] = $data;
}
}
return $output;
}
1 change: 1 addition & 0 deletions civicase.php
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ function civicase_civicrm_buildForm($formName, &$form) {
new CRM_Civicase_Hook_BuildForm_AddCaseCategoryFeaturesField(),
new CRM_Civicase_Hook_BuildForm_AddQuotationsNotesToContributionSettings(),
new CRM_Civicase_Hook_BuildForm_AddSalesOrderLineItemsToContribution(),
new CRM_Civicase_Hook_BuildForm_AddEntityReferenceToCustomField(),
];

foreach ($hooks as $hook) {
Expand Down
28 changes: 28 additions & 0 deletions js/contribution-entityref-field.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
(function ($, _) {
window.waitForElement = function ($, elementPath, callBack) {
window.setTimeout(function () {
if ($(elementPath).length) {
callBack($, $(elementPath));
} else {
window.waitForElement($, elementPath, callBack);
}
}, 500);
};

$(document).one('crmLoad', function () {
const entityRefCustomFields = CRM.vars.civicase.entityRefCustomFields ?? [];

entityRefCustomFields.forEach(field => {
/* eslint-disable no-undef */
waitForElement($, `[name^=${field.name}_]`, function ($, elem) {
$(`[name^=${field.name}_]`)
.attr('placeholder', field.placeholder)
.attr('disabled', false)
.crmEntityRef({
entity: field.entity,
create: false
});
});
});
});
})(CRM.$, CRM._);
20 changes: 20 additions & 0 deletions js/sales-order-contribution.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,23 @@
(function ($, _) {
const waitForElement = function ($, elementPath, callBack) {
window.setTimeout(function () {
if ($(elementPath).length) {
callBack($, $(elementPath));
} else {
window.waitForElement($, elementPath, callBack);
}
}, 500);
};

$(document).one('crmLoad', function () {
const params = CRM.vars['uk.co.compucorp.civicase'];
const salesOrderId = params.sales_order;
const salesOrderStatusId = params.sales_order_status_id;
const percentValue = params.percent_value;
const toBeInvoiced = params.to_be_invoiced;
const lineItems = JSON.parse(params.line_items);
const caseCustomField = params.case_custom_field;
const quotationCustomField = params.quotation_custom_field;
let count = 0;

const apiRequest = {};
Expand Down Expand Up @@ -37,6 +49,14 @@
$(`<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();

waitForElement($, `[name^=${quotationCustomField}_]`, function ($, elem) {
$(`[name^=${quotationCustomField}_]`).val(caseSalesOrder.id).trigger('change');
});

waitForElement($, `[name^=${caseCustomField}_]`, function ($, elem) {
$(`[name^=${caseCustomField}_]`).val(caseSalesOrder.case_id).trigger('change');
});
});
}

Expand Down
Loading
Loading