Initial commit
This commit is contained in:
647
api-wiaas/server/components/v1/prices/Prices.php
Normal file
647
api-wiaas/server/components/v1/prices/Prices.php
Normal file
@@ -0,0 +1,647 @@
|
||||
<?php
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class Prices{
|
||||
|
||||
/**
|
||||
* calculate total price for a product in a package
|
||||
* @param boolean $isRecurring is the price recurring
|
||||
* @param FLOAT $unitCost cost for the product
|
||||
* @param INT $payPeriod pay period in case of recurring
|
||||
* @param INT $quantity quantity of the product in the package
|
||||
* @return FLOAT total cost for a prodcut
|
||||
*/
|
||||
private function calculateTotalPrice($isRecurring, $unitCost, $payPeriod, $quantity){
|
||||
$totalUnitCost = intVal($isRecurring) === 1
|
||||
? floatval($unitCost) * intVal($payPeriod)
|
||||
: floatval($unitCost);
|
||||
$totalUnitCost *= $quantity;
|
||||
|
||||
return $totalUnitCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* get max price for products with multiple selection
|
||||
* @param FLOAT $totalCategoryUnitCost max value for category
|
||||
* @param FLOAT $totalUnitCost cost of the product
|
||||
* @return FLOAT final cost for the product
|
||||
*/
|
||||
private function getMultiProductsTotal($totalCategoryUnitCost, $totalUnitCost){
|
||||
return $totalCategoryUnitCost < $totalUnitCost
|
||||
? $totalUnitCost
|
||||
: $totalCategoryUnitCost;
|
||||
}
|
||||
|
||||
/**
|
||||
* check margin for a package in case a product price is updated
|
||||
* @param INT $idProduct id for the product that has been updated
|
||||
* @return INT number of affected packages
|
||||
*/
|
||||
function checkPackagePriceMargin($idProduct = 0, $idPackage = 0){
|
||||
global $database;
|
||||
|
||||
if($idProduct === 0 && $idPackage === 0){
|
||||
return 0;
|
||||
}
|
||||
|
||||
if($idProduct !== 0){
|
||||
$whereSql = "idProduct=$idProduct";
|
||||
}
|
||||
|
||||
if($idPackage !== 0){
|
||||
$whereSql = "idPackage=$idPackage";
|
||||
}
|
||||
|
||||
$sql = "SELECT rpp.idPackage,
|
||||
scp.unitCostPrice AS unitCostPrice,
|
||||
scp.unitVatCost AS unitVatCost,
|
||||
scp.isPriceRecurring AS isPriceRecurring,
|
||||
scp.payPeriod AS payPeriod,
|
||||
rpp.quantity AS quantity,
|
||||
pc.hasMultipleRealProducts,
|
||||
scp.idProductCategory AS idCategory
|
||||
FROM ".TABLES['suppliers_countries_products']." scp
|
||||
INNER JOIN ".TABLES['rel_package_products']." rpp
|
||||
ON rpp.idProduct=scp.idProduct
|
||||
INNER JOIN ".TABLES['product_categories']." pc
|
||||
ON scp.idProductCategory=pc.id
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT idPackage
|
||||
FROM ".TABLES['rel_package_products']."
|
||||
WHERE $whereSql
|
||||
) affectedPackages
|
||||
ON rpp.idPackage=affectedPackages.idPackage
|
||||
INNER JOIN
|
||||
(SELECT
|
||||
rpp_last.idPackage,
|
||||
MAX(rpp_last.packageInstance) AS maxInstance
|
||||
FROM
|
||||
".TABLES['rel_package_products']." rpp_last
|
||||
GROUP BY rpp_last.idPackage) last_instance
|
||||
ON last_instance.idPackage = rpp.idPackage
|
||||
AND last_instance.maxInstance = rpp.packageInstance";
|
||||
$query = $database->query($sql);
|
||||
$totalPrices = [];
|
||||
$multiProdTotals = [];
|
||||
while($row = $database->fetchArray($query)){
|
||||
if(!isset($totalPrices[$row['idPackage']])){
|
||||
$totalPrices[$row['idPackage']] = 0;
|
||||
}
|
||||
$tempTotal = $this->calculateTotalPrice($row['isPriceRecurring'], $row['unitCostPrice'], $row['payPeriod'], $row['quantity']);
|
||||
if(intval($row['hasMultipleRealProducts']) === 1){
|
||||
if(!isset($multiProdTotals[$row['idPackage']][$row['idCategory']])){
|
||||
$multiProdTotals[$row['idPackage']][$row['idCategory']] = 0;
|
||||
}
|
||||
$multiProdTotals[$row['idPackage']][$row['idCategory']] = $this->getMultiProductsTotal($multiProdTotals[$row['idPackage']][$row['idCategory']], $tempTotal);
|
||||
}else{
|
||||
$totalPrices[$row['idPackage']] += $tempTotal;
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($multiProdTotals as $idPackage => $categories) {
|
||||
foreach($categories as $categoryTotal){
|
||||
$totalPrices[$idPackage] += $categoryTotal;
|
||||
}
|
||||
}
|
||||
|
||||
$sql = "SELECT plb.idPackage,
|
||||
plb.payMargin
|
||||
FROM ".TABLES['broker_commission_split']." plb
|
||||
INNER JOIN (
|
||||
SELECT DISTINCT idPackage
|
||||
FROM ".TABLES['rel_package_products']."
|
||||
WHERE $whereSql
|
||||
) affectedPackages
|
||||
ON plb.idPackage=affectedPackages.idPackage
|
||||
WHERE plb.payMargin!=0";
|
||||
$query = $database->query($sql);
|
||||
$invalidPackages = [];
|
||||
$validPackages = [];
|
||||
while($row = $database->fetchArray($query)){
|
||||
if($row['payMargin'] < $totalPrices[$row['idPackage']]){
|
||||
$invalidPackages[] = $row['idPackage'];
|
||||
}else{
|
||||
$validPackages[] = $row['idPackage'];
|
||||
}
|
||||
}
|
||||
|
||||
if(count($invalidPackages) > 0){
|
||||
$sqlUpd = "UPDATE ".TABLES['packages']."
|
||||
SET status='high-cost'
|
||||
WHERE id IN(".implode(',', $invalidPackages).") AND status!='not-available'";
|
||||
$query = $database->query($sqlUpd);
|
||||
|
||||
return $database->affectedRows();
|
||||
}
|
||||
|
||||
if(count($validPackages) > 0){
|
||||
$sqlUpd = "UPDATE ".TABLES['packages']."
|
||||
SET status='available'
|
||||
WHERE id IN(".implode(',', $validPackages).") AND status='high-cost'";
|
||||
$query = $database->query($sqlUpd);
|
||||
|
||||
return $database->affectedRows();
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public function getPackageProductPrices($idPackage, $sumBy = 'category'){
|
||||
global $database;
|
||||
|
||||
$sql = "SELECT scp.unitCostPrice AS unitCostPrice,
|
||||
scp.unitVatCost AS unitVatCost,
|
||||
scp.isPriceRecurring AS isPriceRecurring,
|
||||
scp.payPeriod AS payPeriod,
|
||||
pc.category AS productCategory,
|
||||
pt.type AS productType,
|
||||
rpp.quantity AS quantity
|
||||
FROM ".TABLES['suppliers_countries_products']." scp
|
||||
INNER JOIN ".TABLES['product_categories']." pc
|
||||
ON pc.id=scp.idProductCategory
|
||||
INNER JOIN ".TABLES['product_types']." pt
|
||||
ON pt.id = pc.idType
|
||||
INNER JOIN ".TABLES['rel_package_products']." rpp
|
||||
ON rpp.idProduct=scp.idProduct
|
||||
INNER JOIN
|
||||
(SELECT
|
||||
rpp_last.idPackage,
|
||||
MAX(rpp_last.packageInstance) AS maxInstance
|
||||
FROM
|
||||
".TABLES['rel_package_products']." rpp_last
|
||||
GROUP BY rpp_last.idPackage) last_instance
|
||||
ON last_instance.idPackage = rpp.idPackage
|
||||
AND last_instance.maxInstance = rpp.packageInstance
|
||||
WHERE rpp.idPackage=$idPackage";
|
||||
|
||||
$query = $database->query($sql);
|
||||
$data['productsPrices'] = [];
|
||||
|
||||
while($row = $database->fetchArray($query)) {
|
||||
$productKey = $sumBy === 'type' ? $row['productType'] : $row['productCategory'];
|
||||
if(!isset($data['productsPrices'][$productKey])){
|
||||
$data['productsPrices'][$productKey]['totalUnitCost'] = 0;
|
||||
$data['productsPrices'][$productKey]['totalVatCost'] = 0;
|
||||
}
|
||||
|
||||
unset($totalCategoryUnitCost);
|
||||
unset($totalCategoryVatCost);
|
||||
|
||||
$totalCategoryUnitCost =& $data['productsPrices'][$productKey]['totalUnitCost'];
|
||||
$totalCategoryVatCost =& $data['productsPrices'][$productKey]['totalVatCost'];
|
||||
|
||||
if($sumBy === 'type' && $row['productType'] === 'service') {
|
||||
$totalUnitCost = $this->calculateTotalPrice(0, $row['unitCostPrice'], $row['payPeriod'], $row['quantity']);
|
||||
$totalVatCost = $this->calculateTotalPrice(0, $row['unitVatCost'], $row['payPeriod'], $row['quantity']);
|
||||
|
||||
if($row['isPriceRecurring'] == 1) {
|
||||
if(!isset($data['productsPrices'][$row['productType']]['recurringPrice'])) {
|
||||
$data['productsPrices'][$row['productType']]['recurringPrice'] = 0;
|
||||
$data['productsPrices'][$row['productType']]['recurringVatPrice'] = 0;
|
||||
}
|
||||
$data['productsPrices'][$row['productType']]['recurringPrice'] += $totalUnitCost;
|
||||
$data['productsPrices'][$row['productType']]['recurringVatPrice'] += $totalVatCost;
|
||||
} else {
|
||||
if(!isset($data['productsPrices'][$row['productType']]['recurringPrice'])) {
|
||||
$data['productsPrices'][$row['productType']]['fixedPrice'] = 0;
|
||||
$data['productsPrices'][$row['productType']]['fixedVatPrice'] = 0;
|
||||
}
|
||||
$data['productsPrices'][$row['productType']]['fixedPrice'] += $totalUnitCost;
|
||||
$data['productsPrices'][$row['productType']]['fixedVatPrice'] += $totalVatCost;
|
||||
}
|
||||
} else {
|
||||
$totalUnitCost = $this->calculateTotalPrice($row['isPriceRecurring'], $row['unitCostPrice'], $row['payPeriod'], $row['quantity']);
|
||||
$totalVatCost = $this->calculateTotalPrice($row['isPriceRecurring'], $row['unitVatCost'], $row['payPeriod'], $row['quantity']);
|
||||
}
|
||||
|
||||
if($row['productType'] === 'installation'){
|
||||
$totalCategoryUnitCost = $this->getMultiProductsTotal($totalCategoryUnitCost, $totalUnitCost);
|
||||
$totalCategoryVatCost = $this->getMultiProductsTotal($totalCategoryVatCost, $totalVatCost);
|
||||
} else {
|
||||
$totalCategoryUnitCost += $totalUnitCost;
|
||||
$totalCategoryVatCost += $totalVatCost;
|
||||
}
|
||||
}
|
||||
|
||||
return $data['productsPrices'];
|
||||
}
|
||||
|
||||
public function getCommissionSplit($idPackage){
|
||||
global $database;
|
||||
|
||||
$sql = "SELECT bcs.brokerSplit as broker,
|
||||
bcs.commercialLeadSplit as commercialLead,
|
||||
bcs.payMargin
|
||||
FROM ".TABLES['broker_commission_split']." bcs
|
||||
WHERE idPackage=$idPackage";
|
||||
$commissionSplit = $database->fetchResultArray($sql);
|
||||
|
||||
return !empty($commissionSplit) ? $commissionSplit[0] : [];
|
||||
}
|
||||
|
||||
/**
|
||||
* get product prices list and comissions
|
||||
* @param INT $idPackage id of the package
|
||||
* @param BOOLEAN $getOnlySelectedTpes if true will return just prices set by the broker
|
||||
* @param String $sumBy type to sum by 'category' or 'type'
|
||||
* @param Float $interestRate interest rate to calculate the prices with
|
||||
* @return json list of prices and list of comission
|
||||
*/
|
||||
public function getPriceTypes($idPackage, $getOnlySelectedTpes = false, $sumBy = 'category', $interestRate = -1){
|
||||
global $database;
|
||||
$joinType = $getOnlySelectedTpes ? "INNER JOIN" : "LEFT OUTER JOIN";
|
||||
$data = [];
|
||||
|
||||
if($interestRate !== -1) {
|
||||
$interestRateValue = $interestRate;
|
||||
} else {
|
||||
$interestRate = new InterestRate();
|
||||
$interestRateValue = $interestRate->getInterestRate()['interestRate'];
|
||||
}
|
||||
|
||||
$interestRatePercentage = $interestRateValue ? floatval($interestRateValue) / 100 : 0;
|
||||
$data['interestRate'] = $interestRateValue;
|
||||
$data['priceTypes'] = [];
|
||||
|
||||
$sql = "SELECT pt.id as idPayType,
|
||||
pt.payType,
|
||||
pt.packagePayPeriod,
|
||||
pt.servicesContractPeriod,
|
||||
pt.maxContractPeriod,
|
||||
pt.periodUnit,
|
||||
plb.minimalFixedPrice,
|
||||
plb.principalAmount,
|
||||
plb.minimalServicesPrice
|
||||
FROM ".TABLES['payment_types']." pt
|
||||
$joinType
|
||||
(SELECT idPaymentType,
|
||||
minimalFixedPrice,
|
||||
principalAmount,
|
||||
minimalServicesPrice
|
||||
FROM ".TABLES['price_list_broker']."
|
||||
WHERE idPackage=$idPackage) plb
|
||||
ON pt.id=plb.idPaymentType";
|
||||
$query = $database->query($sql);
|
||||
while($row = $database->fetchArray($query)){
|
||||
$row['minimalRecurentPrice'] = $row['packagePayPeriod'] > 0
|
||||
? $this->PMT($interestRatePercentage, $row['packagePayPeriod'], $row['principalAmount'])
|
||||
: 0;
|
||||
$row['minimalRecurentPrice'] = number_format($row['minimalRecurentPrice'], 2, '.', '');
|
||||
$data['priceTypes'][] = $row;
|
||||
}
|
||||
|
||||
$data['productsPrices'] = $this->getPackageProductPrices($idPackage, $sumBy);
|
||||
|
||||
$data['commissionSplit'] = $this->getCommissionSplit($idPackage);
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getCommercialLeadPrices($idPackage = 0, $idUserCommercialLead = 0){
|
||||
global $database, $user;
|
||||
$idPackage = $database->escapeValue($idPackage);
|
||||
$whereSql = "";
|
||||
$clPrices = [];
|
||||
|
||||
if($idPackage){
|
||||
$whereSql .= " AND plcl.idPackage=$idPackage";
|
||||
}
|
||||
|
||||
if($idUserCommercialLead){
|
||||
$whereSql .= " AND cl.idUser=$idUserCommercialLead";
|
||||
}
|
||||
|
||||
$sql = "SELECT
|
||||
plcl.idPackage,
|
||||
plcl.idPaymentType,
|
||||
pt.payType,
|
||||
IFNULL(plcl.idCustomer, 0) as idCustomer,
|
||||
plcl.fixedExtra ,
|
||||
plcl.recurentExtra,
|
||||
plcl.servicesExtra,
|
||||
plcl.visibleToCustomer,
|
||||
pt.packagePayPeriod
|
||||
FROM ".TABLES['price_list_commercial_lead']." plcl
|
||||
INNER JOIN ".TABLES['payment_types']." pt
|
||||
ON pt.id = plcl.idPaymentType
|
||||
INNER JOIN ".TABLES['commercial_leads']." cl
|
||||
ON cl.id=plcl.idCommercialLead
|
||||
WHERE 1=1 $whereSql";
|
||||
$query = $database->query($sql);
|
||||
|
||||
while($row = $database->fetchArray($query)){
|
||||
$clPrices[$row['idPackage']][$row['idCustomer']][$row['idPaymentType']] = $row;
|
||||
}
|
||||
|
||||
return $clPrices;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate values to insert/update broker prices
|
||||
* @param INT $idPackage id of package
|
||||
* @param Object $price object containtg the info for prices
|
||||
* @return Array error message array or empty array if no error
|
||||
*/
|
||||
public function validateBrokerPrices($idPackage, $price){
|
||||
global $database;
|
||||
|
||||
$data =[];
|
||||
$max_value = pow(10, 13);
|
||||
|
||||
if(filter_var($idPackage, FILTER_VALIDATE_INT) === false || $idPackage == 0){
|
||||
$data['messages'][] = [
|
||||
'code' => 'error',
|
||||
'message' => 'INVALID_PACKAGE_ID'
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
if(filter_var($price->idPayType, FILTER_VALIDATE_INT) === false || $price->idPayType == 0){
|
||||
$data['messages'][] = [
|
||||
'code' => 'error',
|
||||
'message' => 'INVALID_PAY_TYPE_ID'
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
$checkMessage = $database->invalidNumber('minimalFixedPrice', $price->minimalFixedPrice, 0, $max_value);
|
||||
if($checkMessage){
|
||||
$data['messages'][] = $checkMessage;
|
||||
}
|
||||
|
||||
$checkMessage = $database->invalidNumber('principalAmount', $price->principalAmount, 0, $max_value);
|
||||
if($checkMessage){
|
||||
$data['messages'][] = $checkMessage;
|
||||
}
|
||||
|
||||
$checkMessage = $database->invalidNumber('minimalServicesPrice', $price->minimalServicesPrice, 0, $max_value);
|
||||
if($checkMessage){
|
||||
$data['messages'][] = $checkMessage;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* validate values for commission split
|
||||
* @param Obect $commissionSplit info for commissison split
|
||||
* @return Array error message array or empty array if no error
|
||||
*/
|
||||
public function validateComissionSplit($commissionSplit){
|
||||
global $database;
|
||||
|
||||
$data =[];
|
||||
$max_value = 100;
|
||||
|
||||
$checkMessage = $database->invalidNumber('brokerSplit', $commissionSplit->broker, 0, $max_value);
|
||||
if($checkMessage){
|
||||
$data['messages'][] = $checkMessage;
|
||||
}
|
||||
|
||||
$checkMessage = $database->invalidNumber('commercialLeadSplit', $commissionSplit->commercialLead, 0, $max_value);
|
||||
if($checkMessage){
|
||||
$data['messages'][] = $checkMessage;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* update values for broker prices and comissions
|
||||
* @param INT $idPackage id for package
|
||||
* @param Objects Array $prices Array with prices to be inserted/updated
|
||||
* @param Objects Array $commissionSplit Array with commission to be inserted/updated
|
||||
* @return Array Update message
|
||||
*/
|
||||
public function updateBrokerPricesAndCommission($idPackage, $prices, $commissionSplit){
|
||||
global $database;
|
||||
|
||||
$idPackage = $database->escapeValue($idPackage);
|
||||
$prices = json_decode($prices);
|
||||
$commissionSplit = json_decode($commissionSplit);
|
||||
|
||||
$valuesSql = "";
|
||||
$idsToNotDelete = "";
|
||||
$data = [];
|
||||
|
||||
if(empty($prices)){
|
||||
$data['messages'][] = [
|
||||
'code' => 'error',
|
||||
'message' => 'ONE_PRICE_REQUIRED'
|
||||
];
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
foreach ($prices as $price) {
|
||||
$price->idPayType = $database->escapeValue($price->idPayType);
|
||||
$price->minimalFixedPrice = $price->minimalFixedPrice ? $database->escapeValue($price->minimalFixedPrice) : 0;
|
||||
$price->principalAmount = $price->principalAmount ? $database->escapeValue($price->principalAmount) : 0;
|
||||
$price->minimalServicesPrice =$price->minimalServicesPrice ? $database->escapeValue($price->minimalServicesPrice) : 0;
|
||||
$data = array_merge($data, $this->validateBrokerPrices($idPackage, $price));
|
||||
$valuesSql .= "(".$idPackage.",
|
||||
".$database->escapeValue($price->idPayType).",
|
||||
".$price->minimalFixedPrice.",
|
||||
".$price->principalAmount.",
|
||||
".$price->minimalServicesPrice."
|
||||
),";
|
||||
$idsToNotDelete .= $price->idPayType.",";
|
||||
}
|
||||
|
||||
if(!empty($data)){
|
||||
return $data;
|
||||
}
|
||||
|
||||
if($valuesSql !== ""){
|
||||
$valuesSql = rtrim($valuesSql, ',');
|
||||
$idsToNotDelete = rtrim($idsToNotDelete, ',');
|
||||
$sql = "INSERT INTO ".TABLES['price_list_broker']."
|
||||
(idPackage, idPaymentType, minimalFixedPrice, principalAmount, minimalServicesPrice)
|
||||
VALUES $valuesSql
|
||||
ON DUPLICATE KEY UPDATE
|
||||
minimalFixedPrice=VALUES(minimalFixedPrice),
|
||||
principalAmount=VALUES(principalAmount),
|
||||
minimalServicesPrice=VALUES(minimalServicesPrice)";
|
||||
$query = $database->query($sql);
|
||||
$updatedPrices = $database->affectedRows();
|
||||
|
||||
$sql = "DELETE FROM ".TABLES['price_list_broker']."
|
||||
WHERE idPackage=$idPackage AND idPaymentType NOT IN($idsToNotDelete)";
|
||||
$query = $database->query($sql);
|
||||
$deletePrices = $database->affectedRows();
|
||||
|
||||
if($updatedPrices === 0 && $deletePrices === 0){
|
||||
$data['messages'][] = [
|
||||
'code' => 'warning',
|
||||
'message' => 'NO_CHANGES_PRICES'
|
||||
];
|
||||
}else{
|
||||
$data['messages'][] = [
|
||||
'code' => 'success',
|
||||
'message' => 'BROKER_PRICES_UPDATED'
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
$data = array_merge($data, $this->validateComissionSplit($commissionSplit));
|
||||
$commissionSplit->broker = $commissionSplit->broker ? $database->escapeValue($commissionSplit->broker) : 0;
|
||||
$commissionSplit->commercialLead = $commissionSplit->commercialLead ? $database->escapeValue($commissionSplit->commercialLead) : 0;
|
||||
$commissionSplit->payMargin = $commissionSplit->payMargin ? $database->escapeValue($commissionSplit->payMargin) : 0;
|
||||
|
||||
$sql = "INSERT INTO ".TABLES['broker_commission_split']."
|
||||
(idPackage, brokerSplit, commercialLeadSplit, payMargin)
|
||||
VALUES(".$database->escapeValue($idPackage).",
|
||||
".$commissionSplit->broker.",
|
||||
".$commissionSplit->commercialLead.",
|
||||
".$commissionSplit->payMargin."
|
||||
)
|
||||
ON DUPLICATE KEY UPDATE
|
||||
brokerSplit=VALUES(brokerSplit),
|
||||
commercialLeadSplit=VALUES(commercialLeadSplit),
|
||||
payMargin=VALUES(payMargin)
|
||||
";
|
||||
$query = $database->query($sql);
|
||||
|
||||
if($database->affectedRows() < 1){
|
||||
$data['messages'][] = [
|
||||
'code' => 'warning',
|
||||
'message' => 'NO_CHANGES_COMMISSION_SPLIT'
|
||||
];
|
||||
}else{
|
||||
$data['messages'][] = [
|
||||
'code' => 'success',
|
||||
'message' => 'COMMISSION_SPLIT_UPDATED'
|
||||
];
|
||||
}
|
||||
|
||||
$priceChange = $this->checkPackagePriceMargin(0, $idPackage);
|
||||
if($priceChange > 0){
|
||||
$data['messages'][] = [
|
||||
'code' => 'warning',
|
||||
'message' => 'PACKAGES_HIGH_PRICE_CHANGED'
|
||||
];
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getPackagesAvailablePayTypes(){
|
||||
global $database;
|
||||
$data = [];
|
||||
|
||||
$sql = "SELECT
|
||||
plb.idPackage,
|
||||
plb.idPaymentType,
|
||||
pt.payType
|
||||
FROM ".TABLES['price_list_broker']." plb
|
||||
INNER JOIN ".TABLES['payment_types']." pt
|
||||
ON pt.id=plb.idPaymentType";
|
||||
$query = $database->query($sql);
|
||||
while($row = $database->fetchArray($query)){
|
||||
$data[$row['idPackage']][] = $row;
|
||||
}
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getClDefaultPrices($idPackage){
|
||||
global $database, $user;
|
||||
$data = [];
|
||||
|
||||
$sql = "SELECT d.idPackage,
|
||||
d.idPaymentType,
|
||||
d.fixedExtra,
|
||||
d.recurentExtra,
|
||||
d.servicesExtra
|
||||
FROM ".TABLES['price_list_commercial_lead']." d
|
||||
INNER JOIN ".TABLES['commercial_leads']." cl
|
||||
ON cl.id=d.idCommercialLead
|
||||
WHERE idUser=".$user->getUserId()." AND idPackage=$idPackage AND d.idCustomer IS NULL";
|
||||
$query = $database->query($sql);
|
||||
while($row = $database->fetchArray($query)){
|
||||
$data[$row['idPaymentType']] = $row;
|
||||
}
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function calculatePackageTotalCost($productsPrices){
|
||||
$total = 0;
|
||||
foreach ($productsPrices as $category) {
|
||||
$total += $category['totalUnitCost'];
|
||||
}
|
||||
|
||||
return $total;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy of Excel's PMT function.
|
||||
* Credit: http://thoughts-of-laszlo.blogspot.nl/2012/08/complete-formula-behind-excels-pmt.html
|
||||
*
|
||||
* @param double $interest The interest rate for the loan.
|
||||
* @param int $num_of_payments The total number of payments for the loan in months.
|
||||
* @param double $PV The present value, or the total amount that a series of future payments is worth now;
|
||||
* Also known as the principal.
|
||||
* @param double $FV The future value, or a cash balance you want to attain after the last payment is made.
|
||||
* If fv is omitted, it is assumed to be 0 (zero), that is, the future value of a loan is 0.
|
||||
* @param int $Type Optional, defaults to 0. The number 0 (zero) or 1 and indicates when payments are due.
|
||||
* 0 = At the end of period
|
||||
* 1 = At the beginning of the period
|
||||
*
|
||||
* @return float
|
||||
*/
|
||||
public function PMT($interest, $num_of_payments, $PV, $FV = 0.00, $Type = 0){
|
||||
/*$interest = $interest / 12;
|
||||
$xp=pow((1+$interest),$num_of_payments);
|
||||
return
|
||||
($PV* $interest*$xp/($xp-1)+$interest/($xp-1)*$FV)*
|
||||
($Type==0 ? 1 : 1/($interest+1));*/
|
||||
$rates = [
|
||||
24 => 4.282,
|
||||
30 => 3.451,
|
||||
36 => 2.896,
|
||||
42 => 2.500,
|
||||
48 => 2.223,
|
||||
54 => 2.025,
|
||||
60 => 1.834
|
||||
];
|
||||
|
||||
$interest = isset($rates[$num_of_payments]) ? $rates[$num_of_payments] : 10;
|
||||
|
||||
return round($PV * ($interest / 100));
|
||||
}
|
||||
|
||||
private function calculateMargin($payType, $totalCost){
|
||||
$totalGain = $payType['minimalFixedPrice'] + $payType['principalAmount'];
|
||||
|
||||
return $totalGain - $totalCost;
|
||||
}
|
||||
|
||||
public function getPriceMargins($commisisonPercent, $payType, $totalCost){
|
||||
$margin = $this->calculateMargin($payType, $totalCost);
|
||||
|
||||
return [
|
||||
'margin' => $margin,
|
||||
'clMargin' => ($margin * $commisisonPercent['commercialLead'] / 100),
|
||||
'brokerMargin' => ($margin * $commisisonPercent['broker'] / 100)
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* calculate fixed mortage based on principal amount
|
||||
* @param HashArray $payType pay type hash array (principalAmount and packagePayPeriod keys required)
|
||||
* @param Float $clMargin commercial lead margin
|
||||
* @param Float $interestRate interest rate percent value
|
||||
* @return Float fixed mortage formated to two decimals
|
||||
*/
|
||||
public function getRecurrentPriceMortage($payType, $clMargin, $interestRate){
|
||||
$newPrincipalAmount = $payType['principalAmount'] - $clMargin;
|
||||
$interestRate = $interestRate / 100;
|
||||
$fixedMortage = $this->PMT($interestRate, $payType['packagePayPeriod'], $newPrincipalAmount);
|
||||
|
||||
return number_format($fixedMortage, 2, '.', '');
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user