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-186: Add case's opportunity details #977

Merged
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
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
Loading