From c51eef2dce29e97de288ea882d5aa6c2a2ab038a Mon Sep 17 00:00:00 2001 From: shahrukh-compuco Date: Mon, 23 Oct 2023 12:37:11 +0500 Subject: [PATCH] BTHAB-271: Fix invoice and payment status bugs for quotations The payment and invoice statuses were being calculated in accordance to just invoiced amount without considering the quoted amount and the calculations previously also took into account the deleted invoices which were resulting in incorrect statuses calculations --- .../Hook/Pre/DeleteSalesOrderContribution.php | 10 +++++-- .../AbstractBaseSalesOrderCalculator.php | 2 +- .../CaseSalesOrderContributionCalculator.php | 29 +++++++++++++----- .../CaseSalesOrderOpportunityCalculator.php | 30 ++++++++++++++----- 4 files changed, 53 insertions(+), 18 deletions(-) diff --git a/CRM/Civicase/Hook/Pre/DeleteSalesOrderContribution.php b/CRM/Civicase/Hook/Pre/DeleteSalesOrderContribution.php index e8d5c9f98..9dacd7a73 100644 --- a/CRM/Civicase/Hook/Pre/DeleteSalesOrderContribution.php +++ b/CRM/Civicase/Hook/Pre/DeleteSalesOrderContribution.php @@ -30,7 +30,10 @@ public function run($op, $objectName, $objectId, &$params) { return; } - $caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSalesOrderContributionCalculator($salesOrderId); + $caseSaleOrderContributionService = new CRM_Civicase_Service_CaseSalesOrderContributionCalculator( + $salesOrderId, + (int) $objectId + ); $invoicingStatusId = $caseSaleOrderContributionService->calculateInvoicingStatus(); $paymentStatusId = $caseSaleOrderContributionService->calculatePaymentStatus(); @@ -46,7 +49,10 @@ public function run($op, $objectName, $objectId, &$params) { ->execute() ->first(); - $caseSaleOrderContributionService = new \CRM_Civicase_Service_CaseSalesOrderOpportunityCalculator($caseSalesOrder['case_id']); + $caseSaleOrderContributionService = new \CRM_Civicase_Service_CaseSalesOrderOpportunityCalculator( + $caseSalesOrder['case_id'], + (int) $objectId + ); $caseSaleOrderContributionService->updateOpportunityFinancialDetails(); } diff --git a/CRM/Civicase/Service/AbstractBaseSalesOrderCalculator.php b/CRM/Civicase/Service/AbstractBaseSalesOrderCalculator.php index 1e9b74b2c..ce7752b0f 100644 --- a/CRM/Civicase/Service/AbstractBaseSalesOrderCalculator.php +++ b/CRM/Civicase/Service/AbstractBaseSalesOrderCalculator.php @@ -13,7 +13,7 @@ abstract class CRM_Civicase_Service_AbstractBaseSalesOrderCalculator { INVOICING_STATUS_FULLY_INVOICED = 'fully_invoiced', PAYMENT_STATUS_NO_PAYMENTS = 'no_payments', PAYMENT_STATUS_PARTIALLY_PAID = 'partially_paid', - PAYMENT_STATUS_OVERPAID = 'overpaid', + PAYMENT_STATUS_OVERPAID = 'over_paid', PAYMENT_STATUS_FULLY_PAID = 'fully_paid'; /** diff --git a/CRM/Civicase/Service/CaseSalesOrderContributionCalculator.php b/CRM/Civicase/Service/CaseSalesOrderContributionCalculator.php index 2e44c8470..fedfe8bda 100644 --- a/CRM/Civicase/Service/CaseSalesOrderContributionCalculator.php +++ b/CRM/Civicase/Service/CaseSalesOrderContributionCalculator.php @@ -36,6 +36,12 @@ class CRM_Civicase_Service_CaseSalesOrderContributionCalculator extends CRM_Civi * @var float */ private float $totalPaymentsAmount; + /** + * ID of contribution that is being deleted. + * + * @var null|int + */ + private ?int $deletingContributionId = null; /** * Class constructor. @@ -43,13 +49,17 @@ class CRM_Civicase_Service_CaseSalesOrderContributionCalculator extends CRM_Civi * @param string $salesOrderId * Sales Order ID. * + * @param string $deletingContributionId + * ID of contribution that is being deleted. + * * @throws API_Exception * @throws CiviCRM_API3_Exception * @throws \Civi\API\Exception\UnauthorizedException */ - public function __construct($salesOrderId) { + public function __construct($salesOrderId, ?int $deletingContributionId = null) { parent::__construct(); $this->salesOrder = $this->getSalesOrder($salesOrderId); + $this->deletingContributionId = $deletingContributionId; $this->contributions = $this->getContributions(); $this->totalInvoicedAmount = $this->getTotalInvoicedAmount(); $this->totalPaymentsAmount = $this->getTotalPaymentsAmount(); @@ -115,11 +125,12 @@ public function calculatePaymentStatus() { return $this->getValueFromOptionValues(parent::PAYMENT_STATUS_NO_PAYMENTS, $this->paymentStatusOptionValues); } - if ($this->totalPaymentsAmount < $this->totalInvoicedAmount) { + $quotationTotalAmount = $this->salesOrder['total_after_tax']; + if ($this->totalPaymentsAmount < $quotationTotalAmount) { return $this->getValueFromOptionValues(parent::PAYMENT_STATUS_PARTIALLY_PAID, $this->paymentStatusOptionValues); } - if ($this->totalPaymentsAmount > $this->totalInvoicedAmount) { + if ($this->totalPaymentsAmount > $quotationTotalAmount) { return $this->getValueFromOptionValues(parent::PAYMENT_STATUS_OVERPAID, $this->paymentStatusOptionValues); } @@ -140,10 +151,14 @@ private function getContributions() { return []; } - return Contribution::get(FALSE) - ->addWhere('Opportunity_Details.Quotation', '=', $this->salesOrder['id']) - ->execute() - ->getArrayCopy(); + $contributions = Contribution::get(FALSE) + ->addWhere('Opportunity_Details.Quotation', '=', $this->salesOrder['id']); + + if ($this->deletingContributionId !== null) { + $contributions->addWhere('id', '!=', $this->deletingContributionId); + } + + return $contributions->execute()->getArrayCopy(); } /** diff --git a/CRM/Civicase/Service/CaseSalesOrderOpportunityCalculator.php b/CRM/Civicase/Service/CaseSalesOrderOpportunityCalculator.php index b73923908..89815191e 100644 --- a/CRM/Civicase/Service/CaseSalesOrderOpportunityCalculator.php +++ b/CRM/Civicase/Service/CaseSalesOrderOpportunityCalculator.php @@ -31,16 +31,26 @@ class CRM_Civicase_Service_CaseSalesOrderOpportunityCalculator extends CRM_Civic * @var string */ private string $caseId; + /** + * ID of contribution that is being deleted. + * + * @var null|int + */ + private ?int $deletingContributionId = null; /** * Constructor for CaseSalesOrderOpportunityCalculator class. * * @param string $caseId * Case Id. + * + * @param string $deletingContributionId + * ID of contribution that is being deleted. */ - public function __construct($caseId) { + public function __construct($caseId, ?int $deletingContributionId = null) { parent::__construct(); $this->caseId = $caseId; + $this->deletingContributionId = $deletingContributionId; $contributions = $this->getContributions($caseId); $this->calculateOpportunityFinancialAmount($contributions); } @@ -104,11 +114,11 @@ public function calculatePaymentStatus() { return $this->getLabelFromOptionValues(parent::PAYMENT_STATUS_NO_PAYMENTS, $this->paymentStatusOptionValues); } - if ($this->totalPaidAmount < $this->totalInvoicedAmount) { + if ($this->totalPaidAmount < $this->totalQuotedAmount) { return $this->getLabelFromOptionValues(parent::PAYMENT_STATUS_PARTIALLY_PAID, $this->paymentStatusOptionValues); } - if ($this->totalPaidAmount > $this->totalInvoicedAmount) { + if ($this->totalPaidAmount > $this->totalQuotedAmount) { return $this->getLabelFromOptionValues(parent::PAYMENT_STATUS_OVERPAID, $this->paymentStatusOptionValues); } @@ -122,7 +132,7 @@ public function calculatePaymentStatus() { public function updateOpportunityFinancialDetails(): void { CiviCase::update() ->addValue('Case_Opportunity_Details.Total_Amount_Quoted', $this->calculateTotalQuotedAmount()) - ->addValue('Case_Opportunity_Details.Total_Amount_Invoiced', $this->calculateTotalQuotedAmount()) + ->addValue('Case_Opportunity_Details.Total_Amount_Invoiced', $this->calculateTotalInvoicedAmount()) ->addValue('Case_Opportunity_Details.Invoicing_Status', $this->calculateInvoicingStatus()) ->addValue('Case_Opportunity_Details.Total_Amounts_Paid', $this->calculateTotalPaidAmount()) ->addValue('Case_Opportunity_Details.Payments_Status', $this->calculatePaymentStatus()) @@ -161,11 +171,15 @@ private function calculateOpportunityFinancialAmount($contributions) { * List of contributions that link to the opportunity. */ private function getContributions($caseId) { - return Contribution::get(FALSE) + $contributions = Contribution::get(FALSE) ->addSelect('*', 'Opportunity_Details.Quotation') - ->addWhere('Opportunity_Details.Case_Opportunity', '=', $caseId) - ->execute() - ->getArrayCopy(); + ->addWhere('Opportunity_Details.Case_Opportunity', '=', $caseId); + + if ($this->deletingContributionId !== null) { + $contributions->addWhere('id', '!=', $this->deletingContributionId); + } + + return $contributions->execute()->getArrayCopy(); } }