Skip to content

Commit

Permalink
Merge pull request #977 from compucorp/BTHAB-186-diplay-opportunity-f…
Browse files Browse the repository at this point in the history
…inancial-details

BTHAB-186: Add case's opportunity details
  • Loading branch information
erawat authored Sep 22, 2023
2 parents 13b7c16 + 00cf2f1 commit 56cbd51
Show file tree
Hide file tree
Showing 11 changed files with 720 additions and 84 deletions.
80 changes: 64 additions & 16 deletions CRM/Civicase/Hook/Post/CaseSalesOrderPayment.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
class CRM_Civicase_Hook_Post_CaseSalesOrderPayment {

/**
* Updates CaseSaleOrder statuses when creating a payment transcation.
* Updates CaseSalesOrder statuses when creating a payment transaction.
*
* @param string $op
* The operation being performed.
Expand All @@ -21,36 +21,45 @@ class CRM_Civicase_Hook_Post_CaseSalesOrderPayment {
* Object reference.
*/
public function run($op, $objectName, $objectId, &$objectRef) {
if (!$this->shouldRun($op, $objectName)) {
if (!$this->shouldRun($op, $objectName, $objectRef)) {
return;
}

$entityFinancialTrxn = civicrm_api3('EntityFinancialTrxn', 'get', [
'sequential' => 1,
'entity_table' => 'civicrm_contribution',
'financial_trxn_id' => $objectRef->financial_trxn_id,
]);

if (empty($entityFinancialTrxn['values'][0])) {
$financialTrnxId = $objectRef->financial_trxn_id;
if (empty($financialTrnxId)) {
return;
}

$contributionId = $entityFinancialTrxn['values'][0]['entity_id'];
$contributionId = $this->getContributionId($financialTrnxId);
if (empty($contributionId)) {
return;
}

$salesOrderID = Contribution::get()
->addSelect('Opportunity_Details.Quotation')
$contribution = Contribution::get()
->addSelect('Opportunity_Details.Case_Opportunity', 'Opportunity_Details.Quotation')
->addWhere('id', '=', $contributionId)
->execute()
->first()['Opportunity_Details.Quotation'];
->first();

$this->updateQuotationFinancialStatuses($contribution['Opportunity_Details.Quotation']);
$this->updateCaseOpportunityFinancialDetails($contribution['Opportunity_Details.Case_Opportunity']);
}

/**
* Updates CaseSalesOrder financial statuses.
*
* @param int $salesOrderID
* CaseSalesOrder ID.
*/
private function updateQuotationFinancialStatuses(int $salesOrderID): void {
if (empty($salesOrderID)) {
return;
}

$transaction = CRM_Core_Transaction::create();

try {
$caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSaleOrderContribution($salesOrderID);
$caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSalesOrderContributionCalculator($salesOrderID);
$paymentStatusID = $caseSaleOrderContributionService->calculatePaymentStatus();
$invoicingStatusID = $caseSaleOrderContributionService->calculateInvoicingStatus();

Expand All @@ -68,19 +77,58 @@ public function run($op, $objectName, $objectId, &$objectRef) {
}
}

/**
* Updates Case financial statuses.
*
* @param int? $caseId
* CaseSalesOrder ID.
*/
private function updateCaseOpportunityFinancialDetails(?int $caseId) {
if (empty($caseId)) {
return;
}

try {
$calculator = new CRM_Civicase_Service_CaseSalesOrderOpportunityCalculator($caseId);
$calculator->updateOpportunityFinancialDetails();
}
catch (\Throwable $th) {
CRM_Core_Error::statusBounce(ts('Error updating opportunity details'));
}
}

/**
* Gets Contribution ID by Financial Transaction ID.
*/
private function getContributionId($financialTrxnId) {
$entityFinancialTrxn = civicrm_api3('EntityFinancialTrxn', 'get', [
'sequential' => 1,
'entity_table' => 'civicrm_contribution',
'financial_trxn_id' => $financialTrxnId,
]);

if (empty($entityFinancialTrxn['values'][0])) {
return NULL;
}

return $entityFinancialTrxn['values'][0]['entity_id'];
}

/**
* Determines if the hook should run or not.
*
* @param string $op
* The operation being performed.
* @param string $objectName
* Object name.
* @param string $objectRef
* The hook object reference.
*
* @return bool
* returns a boolean to determine if hook will run or not.
*/
private function shouldRun($op, $objectName) {
return $objectName == 'EntityFinancialTrxn' && $op == 'create';
private function shouldRun($op, $objectName, $objectRef) {
return $objectName == 'EntityFinancialTrxn' && $op == 'create' && property_exists($objectRef, 'financial_trxn_id');
}

}
21 changes: 15 additions & 6 deletions CRM/Civicase/Hook/Post/CreateSalesOrderContribution.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,20 @@ public function run($op, $objectName, $objectId, &$objectRef) {
return;
}

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

$salesOrderStatusId = CRM_Utils_Request::retrieve('sales_order_status_id', 'Integer');
if (empty($salesOrderStatusId)) {
$salesOrderStatusId = CaseSalesOrder::get()
->addSelect('status_id')
->addWhere('id', '=', $salesOrderId)
->execute()
->first()['status_id'];
$salesOrder = $salesOrder['status_id'];
}

$transaction = CRM_Core_Transaction::create();
try {
$caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSaleOrderContribution($salesOrderId);
$caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSalesOrderContributionCalculator($salesOrderId);
$paymentStatusID = $caseSaleOrderContributionService->calculatePaymentStatus();
$invoicingStatusID = $caseSaleOrderContributionService->calculateInvoicingStatus();

Expand All @@ -55,6 +57,13 @@ public function run($op, $objectName, $objectId, &$objectRef) {
->addValue('invoicing_status_id', $invoicingStatusID)
->addValue('payment_status_id', $paymentStatusID)
->execute();

$caseId = $salesOrder['case_id'];
if (empty($caseId)) {
return;
}
$calculator = new CRM_Civicase_Service_CaseSalesOrderOpportunityCalculator($caseId);
$calculator->updateOpportunityFinancialDetails();
}
catch (\Throwable $th) {
$transaction->rollback();
Expand Down
79 changes: 79 additions & 0 deletions CRM/Civicase/Hook/Pre/DeleteSalesOrderContribution.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
<?php

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

/**
* Handles Precessing Contribution deletion.
*/
class CRM_Civicase_Hook_Pre_DeleteSalesOrderContribution {

/**
* Updates CaseSaleOrder and Opportunity statuses and financial details.
*
* @param string $op
* The operation being performed.
* @param string $objectName
* Object name.
* @param mixed $objectId
* Object ID.
* @param array &$params
* Array of an entity.
*/
public function run($op, $objectName, $objectId, &$params) {
if (!$this->shouldRun($op, $objectName)) {
return;
}

$salesOrderId = $this->getQuotationId($objectId);
if (empty($salesOrderId)) {
return;
}

$caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSalesOrderContributionCalculator($salesOrderId);
$invoicingStatusId = $caseSaleOrderContributionService->calculateInvoicingStatus();
$paymentStatusId = $caseSaleOrderContributionService->calculatePaymentStatus();

CaseSalesOrder::update()
->addWhere('id', '=', $salesOrderId)
->addValue('invoicing_status_id', $invoicingStatusId)
->addValue('payment_status_id', $paymentStatusId)
->execute();

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

$caseSaleOrderContributionService = new \CRM_Civicase_Service_CaseSalesOrderOpportunityCalculator($caseSalesOrder['case_id']);
$caseSaleOrderContributionService->updateOpportunityFinancialDetails();
}

/**
* Determines if the hook should run or not.
*
* @param string $op
* The operation being performed.
* @param string $objectName
* Object name.
*
* @return bool
* returns a boolean to determine if hook will run or not.
*/
private function shouldRun($op, $objectName) {
return strtolower($objectName) == 'contribution' && $op == 'delete';
}

/**
* Gets quotation ID by contribution ID.
*/
private function getQuotationId($id) {
return Contribution::get()
->addSelect('Opportunity_Details.Quotation')
->addWhere('id', '=', $id)
->execute()
->first()['Opportunity_Details.Quotation'];
}

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

use Civi\Api4\OptionValue;

/**
* An Abstract class for SalesOrder and Opportunity statuses and amounts.
*/
abstract class CRM_Civicase_Service_AbstractBaseSalesOrderCalculator {

const
INVOICING_STATUS_NO_INVOICES = 'no_invoices',
INVOICING_STATUS_PARTIALLY_INVOICED = 'partially_invoiced',
INVOICING_STATUS_FULLY_INVOICED = 'fully_invoiced',
PAYMENT_STATUS_NO_PAYMENTS = 'no_payments',
PAYMENT_STATUS_PARTIALLY_PAID = 'partially_paid',
PAYMENT_STATUS_OVERPAID = 'overpaid',
PAYMENT_STATUS_FULLY_PAID = 'fully_paid';

/**
* Case Sales Order payment status option values.
*
* @var array
*/
protected array $paymentStatusOptionValues;
/**
* Case Sales Order Invoicing status option values.
*
* @var array
*/
protected array $invoicingStatusOptionValues;

/**
* AbstractBaseSalesOrderCalculator constructor.
*/
public function __construct() {
$this->paymentStatusOptionValues = $this->getOptionValues('case_sales_order_payment_status');
$this->invoicingStatusOptionValues = $this->getOptionValues('case_sales_order_invoicing_status');
}

/**
* Gets option values by option group name.
*
* @param string $name
* Option group name.
*
* @return array
* Option values.
*
* @throws API_Exception
* @throws \Civi\API\Exception\UnauthorizedException
*/
protected function getOptionValues($name) {
return OptionValue::get(FALSE)
->addSelect('*')
->addWhere('option_group_id:name', '=', $name)
->execute()
->getArrayCopy();
}

/**
* Gets status (option values' value) from the given options.
*
* @param string $needle
* Search value.
* @param array $options
* Option value.
*
* @return string
* Option values' value.
*/
protected function getValueFromOptionValues($needle, $options) {
$key = array_search($needle, array_column($options, 'name'));

return $options[$key]['value'];
}

/**
* Gets status (option values' label) from the given options.
*
* @param string $needle
* Search value.
* @param array $options
* Option value.
*
* @return string
* Option values' value.
*/
protected function getLabelFromOptionValues($needle, $options) {
$key = array_search($needle, array_column($options, 'name'));

return $options[$key]['label'];
}

}
Loading

0 comments on commit 56cbd51

Please sign in to comment.