Skip to content

Commit

Permalink
BTHAB-182: Attach quotation invoice to contribution mail
Browse files Browse the repository at this point in the history
  • Loading branch information
olayiwola-compucorp committed Sep 21, 2023
1 parent 072f2c8 commit 0f6bfbd
Show file tree
Hide file tree
Showing 5 changed files with 300 additions and 0 deletions.
63 changes: 63 additions & 0 deletions CRM/Civicase/Hook/BuildForm/AttachQuotationToInvoiceMail.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
<?php

use Civi\Api4\CaseSalesOrder;
use Civi\Api4\Contribution;

/**
* Gives user the option to attach quotation to invoice mail.
*/
class CRM_Civicase_Hook_BuildForm_AttachQuotationToInvoiceMail {

/**
* Adds the Attach Quote checkbox to invoice mail form.
*
* @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;
}

$form->add('checkbox', 'attach_quote', ts('Attach Quotation'));

CRM_Core_Region::instance('page-body')->add([
'template' => "CRM/Civicase/Form/Contribute/AttachQuotation.tpl",
]);
}

/**
* Determines if the hook will run.
*
* @param string $formName
* Form Name.
*
* @return bool
* TRUE if the hook should run, FALSE otherwise.
*/
private function shouldRun($formName) {
if ($formName != 'CRM_Contribute_Form_Task_Invoice') {
return FALSE;
}

$contributionId = CRM_Utils_Request::retrieve('id', 'Positive');
if (!$contributionId) {
return FALSE;
}

$salesOrder = Contribution::get()
->addSelect('Opportunity_Details.Quotation')
->addWhere('Opportunity_Details.Quotation', 'IS NOT EMPTY')
->addWhere('id', '=', $contributionId)
->addChain('salesOrder', CaseSalesOrder::get()
->addWhere('id', '=', '$Opportunity_Details.Quotation')
)
->execute()
->first()['salesOrder'];

return !empty($salesOrder);
}

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

use Civi\Api4\CaseSalesOrder;
use Civi\Api4\Contribution;

/**
* Adds Quotation invoice as an attachement.
*/
class CRM_Civicase_Hook_alterMailParams_AttachQuotation {

/**
* Attaches quotation to single invoice.
*
* @param array $params
* Mail parameters.
* @param string $context
* Mail context.
*/
public function run(array &$params, $context) {
$shouldAttachQuote = CRM_Utils_Request::retrieve('attach_quote', 'String');

if (!$this->shouldRun($params, $context, $shouldAttachQuote)) {
return;
}

$rendered = $this->getContributionQuotationInvoice($params['tokenContext']['contributionId']);

$params['attachments'][] = CRM_Utils_Mail::appendPDF('quotation_invoice.pdf', $rendered['html'], $rendered['format']);
}

/**
* Renders the Invoice for the quotation linked to the contribution.
*
* @param int $contributionId
* The contribution ID.
*/
private function getContributionQuotationInvoice($contributionId) {
$salesOrder = Contribution::get()
->addSelect('Opportunity_Details.Quotation')
->addWhere('Opportunity_Details.Quotation', 'IS NOT EMPTY')
->addWhere('id', '=', $contributionId)
->addChain('salesOrder', CaseSalesOrder::get()
->addWhere('id', '=', '$Opportunity_Details.Quotation')
)
->execute()
->first()['salesOrder'];

if (empty($salesOrder)) {
return;
}

/** @var \CRM_Civicase_Service_CaseSalesOrderInvoice */
$invoiceService = new \CRM_Civicase_Service_CaseSalesOrderInvoice(new CRM_Civicase_WorkflowMessage_SalesOrderInvoice());
return $invoiceService->render($salesOrder[0]['id']);
}

/**
* Determines if the hook will run.
*
* @param array $params
* Mail parameters.
* @param string $context
* Mail context.
* @param string $shouldAttachQuote
* If the Attach Quote is set.
*
* @return bool
* returns TRUE if hook should run, FALSE otherwise.
*/
private function shouldRun(array $params, $context, $shouldAttachQuote) {
$component = $params['tplParams']['component'] ?? '';
if ($component !== 'contribute' || $context !== 'messageTemplate' || empty($shouldAttachQuote)) {
return FALSE;
}

return TRUE;
}

}
142 changes: 142 additions & 0 deletions CRM/Civicase/Service/CaseSalesOrderInvoice.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
<?php

use Civi\Api4\Address;
use Civi\Api4\CaseSalesOrder;
use Civi\Api4\CaseSalesOrderLine;
use Civi\Api4\Contact;
use Civi\Api4\Setting;
use CRM_Civicase_WorkflowMessage_SalesOrderInvoice as SalesOrderInvoice;

/**
* Renders sales order invoice.
*/
class CRM_Civicase_Service_CaseSalesOrderInvoice {

/**
* CreditNoteInvoiceService constructor.
*
* @param \CRM_Civicase_WorkflowMessage_SalesOrderInvoice $template
* Workflow template.
*/
public function __construct(private SalesOrderInvoice $template) {
}

/**
* Renders the sales order invoice message template.
*
* @param int $id
* Sales Order ID.
*
* @return array
* Rendered message, consistent of 'subject', 'text', 'html'
*/
public function render(int $id) {
$caseSalesOrder = CaseSalesOrder::get()
->addWhere('id', '=', $id)
->addChain('items', CaseSalesOrderLine::get()
->addWhere('sales_order_id', '=', '$id')
->addSelect('*', 'product_id.name', 'financial_type_id.name')
)
->addChain('computedRates', CaseSalesOrder::computeTotal()
->setLineItems('$items')
)
->addChain('client', Contact::get()
->addWhere('id', '=', '$client_id'), 0
)
->execute()
->first();

if (!empty($caseSalesOrder['client_id'])) {
$caseSalesOrder['clientAddress'] = Address::get()
->addSelect('*', 'country_id:label', 'state_province_id:label')
->addWhere('contact_id', '=', $caseSalesOrder['client_id'])
->execute()
->first();
$caseSalesOrder['clientAddress']['country'] = $caseSalesOrder['clientAddress']['country_id:label'];
$caseSalesOrder['clientAddress']['state'] = $caseSalesOrder['clientAddress']['state_province_id:label'];
}

$caseSalesOrder['taxRates'] = $caseSalesOrder['computedRates'][0]['taxRates'] ?? [];
$caseSalesOrder['quotation_date'] = date('Y-m-d', strtotime($caseSalesOrder['quotation_date']));

$domain = CRM_Core_BAO_Domain::getDomain();
$organisation = Contact::get()
->addSelect('image_URL')
->addWhere('id', '=', $domain->contact_id)
->execute()
->first();

$model = new CRM_Civicase_WorkflowMessage_SalesOrderInvoice();
$terms = self::getTerms();
$model->setDomainLogo($organisation['image_URL']);
$model->setSalesOrder($caseSalesOrder);
$model->setTerms($terms);
$model->setSalesOrderId($id);
$model->setDomainLocation(self::getDomainLocation());
$model->setDomainName($domain->name ?? '');
$rendered = $model->renderTemplate();

$rendered['format'] = $rendered['format'] ?? self::defaultInvoiceFormat();

return $rendered;
}

/**
* Returns the Quotation invoice terms.
*/
private static function getTerms() {
$terms = NULL;
$invoicing = Setting::get()
->addSelect('invoicing')
->execute()
->first();

if (!empty($invoicing['value'])) {
$terms = Civi::settings()->get('quotations_notes');
}

return $terms;
}

/**
* Gets domain location.
*
* @return array
* An array of address lines.
*/
private static function getDomainLocation() {
$domain = CRM_Core_BAO_Domain::getDomain();
$locParams = ['contact_id' => $domain->contact_id];
$locationDefaults = CRM_Core_BAO_Location::getValues($locParams);
if (empty($locationDefaults['address'][1])) {
return [];
}
$stateProvinceId = $locationDefaults['address'][1]['state_province_id'] ?? NULL;
$stateProvinceAbbreviationDomain = !empty($stateProvinceId) ? CRM_Core_PseudoConstant::stateProvinceAbbreviation($stateProvinceId) : '';
$countryId = $locationDefaults['address'][1]['country_id'];
$countryDomain = !empty($countryId) ? CRM_Core_PseudoConstant::country($countryId) : '';

return [
'street_address' => CRM_Utils_Array::value('street_address', CRM_Utils_Array::value('1', $locationDefaults['address'])),
'supplemental_address_1' => CRM_Utils_Array::value('supplemental_address_1', CRM_Utils_Array::value('1', $locationDefaults['address'])),
'supplemental_address_2' => CRM_Utils_Array::value('supplemental_address_2', CRM_Utils_Array::value('1', $locationDefaults['address'])),
'supplemental_address_3' => CRM_Utils_Array::value('supplemental_address_3', CRM_Utils_Array::value('1', $locationDefaults['address'])),
'city' => CRM_Utils_Array::value('city', CRM_Utils_Array::value('1', $locationDefaults['address'])),
'postal_code' => CRM_Utils_Array::value('postal_code', CRM_Utils_Array::value('1', $locationDefaults['address'])),
'state' => $stateProvinceAbbreviationDomain,
'country' => $countryDomain,
];
}

/**
* Returns the default format to use for Invoice.
*/
private static function defaultInvoiceFormat() {
return [
'margin_top' => 10,
'margin_left' => 65,
'metric' => 'px',
];
}

}
2 changes: 2 additions & 0 deletions civicase.php
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ function civicase_civicrm_buildForm($formName, &$form) {
new CRM_Civicase_Hook_BuildForm_AddQuotationsNotesToContributionSettings(),
new CRM_Civicase_Hook_BuildForm_AddSalesOrderLineItemsToContribution(),
new CRM_Civicase_Hook_BuildForm_AddEntityReferenceToCustomField(),
new CRM_Civicase_Hook_BuildForm_AttachQuotationToInvoiceMail(),
];

foreach ($hooks as $hook) {
Expand Down Expand Up @@ -556,6 +557,7 @@ function _civicase_add_case_category_case_type_entity(array &$entityTypes) {
function civicase_civicrm_alterMailParams(&$params, $context) {
$hooks = [
new CRM_Civicase_Hook_alterMailParams_SubjectCaseTypeCategoryProcessor(),
new CRM_Civicase_Hook_alterMailParams_AttachQuotation(),
];

foreach ($hooks as &$hook) {
Expand Down
14 changes: 14 additions & 0 deletions templates/CRM/Civicase/Form/Contribute/AttachQuotation.tpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<table>
<tr class="crm-email-element attach-quote">
<td class="label">{$form.attach_quote.label}</td>
<td class="html-adjust">{$form.attach_quote.html} <span>Yes</span></td>
</tr>
</table>

{literal}
<script type="text/javascript">
CRM.$(function ($) {
$('form.CRM_Contribute_Form_Task_Invoice > table.form-layout-compressed > tbody').append($('tr.attach-quote'))
})
</script>
{/literal}

0 comments on commit 0f6bfbd

Please sign in to comment.