YetiForceCompany/YetiForceCRM

View on GitHub
modules/PaymentsIn/models/PaymentStatus.php

Summary

Maintainability
A
1 hr
Test Coverage
B
85%
<?php
/**
 * The file contains: Class to change of payment status on related records.
 *
 * @package Model
 *
 * @copyright YetiForce S.A.
 * @license YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
 * @author Arkadiusz Adach <a.adach@yetiforce.com>
 */

/**
 * Change of payment status on related records.
 */
abstract class PaymentsIn_PaymentStatus_Model
{
    /**
     * Module name.
     *
     * @var string
     */
    protected static $moduleName;

    /**
     * Field payment status name.
     *
     * @var string
     */
    protected static $fieldPaymentStatusName;

    /**
     * Field payment sum name.
     *
     * @var string
     */
    protected static $fieldPaymentSumName;

    /**
     * Related record ID name.
     *
     * @var string
     */
    protected static $relatedRecordIdName;

    /**
     * Update if possible.
     *
     * @param Vtiger_Record_Model $recordModel
     *
     * @return void
     */
    public static function updateIfPossible(Vtiger_Record_Model $recordModel)
    {
        if (static::canUpdatePaymentStatus($recordModel)) {
            if ($currentRelatedId = $recordModel->get(static::$relatedRecordIdName)) {
                (new \App\BatchMethod(['method' => static::class . '::updatePaymentStatus', 'params' => [$currentRelatedId]]))->save();
            }
            $previousRelatedId = $recordModel->getPreviousValue(static::$relatedRecordIdName);
            if (false !== $previousRelatedId && $previousRelatedId > 0) {
                (new \App\BatchMethod(['method' => static::class . '::updatePaymentStatus', 'params' => [$previousRelatedId]]))->save();
            }
        }
    }

    /**
     * Update payment status.
     *
     * @param int $recordId
     *
     * @return void
     */
    public static function updatePaymentStatus(int $recordId)
    {
        $changes = false;
        $recordModel = \Vtiger_Record_Model::getInstanceById($recordId, static::$moduleName);
        if (!empty(static::$fieldPaymentStatusName)) {
            $statusFieldModel = $recordModel->getField(static::$fieldPaymentStatusName);
            if ($statusFieldModel && $statusFieldModel->isActiveField()) {
                $recordModel->set(
                    static::$fieldPaymentStatusName,
                    static::calculatePaymentStatus((float) $recordModel->get('sum_gross'), static::getSumOfPaymentsByRecordId($recordId, static::$moduleName))
                );
                $changes = true;
            }
        }
        if (!empty(static::$fieldPaymentSumName)) {
            $sumFieldModel = $recordModel->getField(static::$fieldPaymentSumName);
            if ($sumFieldModel && $sumFieldModel->isActiveField()) {
                $recordModel->set(
                    static::$fieldPaymentSumName,
                    static::getSumOfPaymentsByRecordId($recordId, static::$moduleName)
                );
                $changes = true;
            }
        }
        if ($changes) {
            $recordModel->save();
        }
    }

    /**
     * Get the sum of all payments by record ID.
     *
     * @param int    $recordId
     * @param string $moduleName
     *
     * @return float
     */
    public static function getSumOfPaymentsByRecordId(int $recordId, string $moduleName): float
    {
        $cacheNamespace = "getSumOfPaymentsByRecordId.{$moduleName}";
        if (\App\Cache::staticHas($cacheNamespace, $recordId)) {
            $sumOfPayments = (float) \App\Cache::staticGet($cacheNamespace, $recordId);
        } else {
            $relationModel = Vtiger_Relation_Model::getInstance(
                Vtiger_Module_Model::getInstance($moduleName),
                Vtiger_Module_Model::getInstance('PaymentsIn')
            );
            $relationModel->set('parentRecord', Vtiger_Record_Model::getInstanceById($recordId, $moduleName));
            $queryGenerator = $relationModel->getQuery();
            $queryGenerator->addNativeCondition(['vtiger_paymentsin.paymentsin_status' => 'PLL_PAID']);
            $sumOfPayments = (float) $queryGenerator->createQuery()
                ->sum('vtiger_paymentsin.paymentsvalue');
            \App\Cache::staticSave($cacheNamespace, $recordId, $sumOfPayments);
        }
        return $sumOfPayments;
    }

    /**
     * Calculate payment status.
     *
     * @param float $sumOfGross
     * @param float $sumOfPayments
     *
     * @return string
     */
    protected static function calculatePaymentStatus(float $sumOfGross, float $sumOfPayments): string
    {
        if (\App\Validator::floatIsEqual($sumOfGross, $sumOfPayments, 3)) {
            $paymentStatus = 'PLL_PAID';
        } elseif (\App\Validator::floatIsEqual(0.0, $sumOfPayments, 3)) {
            $paymentStatus = 'PLL_NOT_PAID';
        } elseif ($sumOfGross > $sumOfPayments) {
            $paymentStatus = 'PLL_UNDERPAID';
        } else {
            $paymentStatus = 'PLL_OVERPAID';
        }
        return $paymentStatus;
    }

    /**
     * Checking if you can update the payment status.
     *
     * @param Vtiger_Record_Model $recordModel
     *
     * @return bool
     */
    protected static function canUpdatePaymentStatus(Vtiger_Record_Model $recordModel): bool
    {
        $returnValue = !$recordModel->isEmpty(static::$relatedRecordIdName) && ($recordModel->isNew() || false !== $recordModel->getPreviousValue('paymentsin_status'));
        if ($returnValue) {
            $fieldModel = \Vtiger_Module_Model::getInstance(static::$moduleName)->getFieldByName(static::$fieldPaymentStatusName);
            $returnValue = $fieldModel && $fieldModel->isActiveField();
        }
        return $returnValue;
    }

    /**
     * Check if payment fields for update changed.
     *
     * @param Vtiger_Record_Model $recordModel
     *
     * @return bool
     */
    protected static function checkIfPaymentFieldsChanged(Vtiger_Record_Model $recordModel): bool
    {
        $result = false;
        $fieldsToCheck = ['paymentsin_status', 'finvoiceid', 'ssingleordersid', 'finvoiceproformaid'];
        foreach ($fieldsToCheck as $fieldName) {
            if (false !== $recordModel->getPreviousValue($fieldName)) {
                $result = true;
                break;
            }
        }
        return $result;
    }
}