diff --git a/CRM/Civicase/Hook/BuildForm/AttachQuotationToInvoiceMail.php b/CRM/Civicase/Hook/BuildForm/AttachQuotationToInvoiceMail.php new file mode 100644 index 000000000..9c36c431b --- /dev/null +++ b/CRM/Civicase/Hook/BuildForm/AttachQuotationToInvoiceMail.php @@ -0,0 +1,63 @@ +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); + } + +} diff --git a/CRM/Civicase/Hook/alterMailParams/AttachQuotation.php b/CRM/Civicase/Hook/alterMailParams/AttachQuotation.php new file mode 100644 index 000000000..dcf2d8ecf --- /dev/null +++ b/CRM/Civicase/Hook/alterMailParams/AttachQuotation.php @@ -0,0 +1,79 @@ +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; + } + +} diff --git a/CRM/Civicase/Service/CaseSalesOrderInvoice.php b/CRM/Civicase/Service/CaseSalesOrderInvoice.php new file mode 100644 index 000000000..57dfa46a2 --- /dev/null +++ b/CRM/Civicase/Service/CaseSalesOrderInvoice.php @@ -0,0 +1,142 @@ +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', + ]; + } + +} diff --git a/civicase.php b/civicase.php index 89ac2b026..88bc77c3b 100644 --- a/civicase.php +++ b/civicase.php @@ -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) { @@ -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) { diff --git a/templates/CRM/Civicase/Form/Contribute/AttachQuotation.tpl b/templates/CRM/Civicase/Form/Contribute/AttachQuotation.tpl new file mode 100644 index 000000000..82a949091 --- /dev/null +++ b/templates/CRM/Civicase/Form/Contribute/AttachQuotation.tpl @@ -0,0 +1,14 @@ + + + + + +
+ +{literal} + +{/literal}