Files
old-wiaas-legacy/api-wiaas/server/components/v2/cart/CartModel.php
2018-09-30 23:03:33 +02:00

1388 lines
54 KiB
PHP

<?php
/**
* Data manipulation for the model
*/
class CartModel{
const PACKAGE_TYPES = [
'ID_STANDARD_TYPE' => 1,
'ID_OPTION_TYPE' => 2,
'ID_ADDITONAL_TYPE' => 3
];
const DOCUMENT_TYPES = [
'ID_TEMPLATE_QUESIONNAIRE' => 1,
'ID_CUSTOMER_QUESTIONNAIRE' => 2,
'ID_TEMPLATE_AGREEMENT' => 6,
'ID_CUSTOMER_AGREEMENT' => 7
];
const PRODUCT_CATEGORIES = [
'ITEMS' => 1,
'INSTALLATION' => 2
];
/**
* get count of items in the cart
* @return Object number of items in the cart
*/
public function getCartCount(){
global $database, $user;
$sql = "SELECT COUNT(idPackage) as cartItemsCount
FROM ".TABLES['web_shop_cart']."
WHERE idUser=".$user->getUserId();
$data = $database->fetchResultArray($sql);
return !empty($data) ? $data[0] : [];
}
/**
* get items in cart
* @return array list of items in the cart
*/
public function getCartItems(){
global $database, $user;
$data = [
'cartItems' => []
];
$options = $this->getCartItemOptions();
$additionalPackages = $this->getCartAdditionalPackages();
$countries = new Countries();
$packages = new Packages();
$orderTypeInst = new OrderType();
$interestRate = new InterestRate();
$bidsHandler = new Bids();
$bids = $bidsHandler->getCartBids();
$sql = "SELECT
cart.id as idCart,
cart.idPackage,
cart.idCustomerInstance,
cart.idPrice,
cart.packageInstance,
cart.idBid as idSelectedBid,
p.status,
rclc.isLinkEnabled,
p.name as packageName,
cl.id AS idCommercialLead,
cl.name as commercialLead,
pt.payType,
pt.periodUnit AS periodUnit,
pt.id AS idPayType,
cart.quantity
FROM ".TABLES['web_shop_cart']." cart
INNER JOIN ".TABLES['packages']." p
ON p.id=cart.idPackage
INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
ON rclc.id=cart.idCustomerInstance
INNER JOIN ".TABLES['commercial_leads']." cl
ON cl.id=rclc.idCommercialLead
INNER JOIN ".TABLES['price_list_commercial_lead']." plcl
ON plcl.id=cart.idPrice
INNER JOIN ".TABLES['payment_types']." pt
ON pt.id=plcl.idPaymentType
INNER JOIN ".TABLES['price_list_broker']." plb
ON plb.idPackage=plcl.idPackage
AND plb.idPaymentType=plcl.idPaymentType
WHERE cart.idUser=".$user->getUserId();
$query = $database->query($sql);
while($row = $database->fetchArray($query)){
$prices = $packages->getPricesForPackages($row['idCommercialLead'], $row['idPackage'], self::PACKAGE_TYPES['ID_STANDARD_TYPE'], $row['idPayType']);
if(count($prices[$row['idPackage']]) === 1){
$price = $prices[$row['idPackage']][0];
$row['fixedPrice'] = $price['fixedExtra'];
$row['recurentPrice'] = $price['recurentExtra'];
$row['servicesPrice'] = $price['servicesExtra'];
$row['options'] = isset($options[$row['idCart']]) ? $options[$row['idCart']]['options'] : [];
$row['areOptionsAvailable'] = isset($options[$row['idCart']]) ? $options[$row['idCart']]['areOptionsAvailable'] : true;
$row['additionalPackages'] = isset($additionalPackages[$row['idCart']]) ? $additionalPackages[$row['idCart']]['additionalPackages'] : [];
$row['areAdditionalAvailable'] = isset($additionalPackages[$row['idCart']]) ? $additionalPackages[$row['idCart']]['areAdditionalAvailable'] : true;
$row['country'] = $countries->getCurrencyForPackage($row['idPackage']);
$row['bids'] = isset($bids[$row['idPackage']]) ? $bids[$row['idPackage']] : [];
$totalPackagePrice = $this->calculatePackageTotalPrice($row);
$row['totalPrices'] = $totalPackagePrice;
$data['cartItems'][] = $row;
}
}
$data['totalPrice'] = $this->getCartTotalPrice($data['cartItems']);
return $data;
}
/**
* get options for items in the cart
* @return Array list of options grouped by cart id
*/
private function getCartItemOptions(){
global $database, $user;
$data = [];
$packages = new Packages();
$sql = "SELECT
wscep.idCart,
p.name AS packageName,
pog.name AS groupName,
rgo.idOptionPackage,
wsc.idPackage AS idParentPackage,
rclc.idCommercialLead AS idCommercialLead,
plcl.idPaymentType AS idPaymentType
FROM ".TABLES['web_shop_cart_extra_packages']." wscep
INNER JOIN ".TABLES['packages']." p
ON p.id=wscep.idExtraPackage
INNER JOIN ".TABLES['web_shop_cart']." wsc
ON wsc.id=wscep.idCart
INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
ON rclc.id=wsc.idCustomerInstance
INNER JOIN ".TABLES['price_list_commercial_lead']." plcl
ON wsc.idPrice = plcl.id
INNER JOIN ".TABLES['rel_group_options']." rgo
ON rgo.idOptionPackage=wscep.idExtraPackage
INNER JOIN ".TABLES['package_option_groups']." pog
ON pog.id=rgo.idGroup AND pog.idPackage=wsc.idPackage
WHERE wsc.idUser=".$user->getUserId();
$query = $database->query($sql);
while($row = $database->fetchArray($query)){
$packageOptionPrices = $packages->getPricesForPackages($row['idCommercialLead'], $row['idParentPackage'], self::PACKAGE_TYPES['ID_OPTION_TYPE']);
$allPrices = isset($packageOptionPrices[$row['idOptionPackage']]) ? $packageOptionPrices[$row['idOptionPackage']] : [];
$isPaymentTypePresent = array_search($row['idPaymentType'], array_column($allPrices, 'idPaymentType'));
$priceByPaymentTypeKey = $isPaymentTypePresent !== false ? $isPaymentTypePresent : -1;
$row['prices'] = $priceByPaymentTypeKey > -1 ? $allPrices[$priceByPaymentTypeKey] : [];
$row['isAvailable'] = count($row['prices']) > 0;
$data[$row['idCart']]['options'][] = $row;
if(!isset($data[$row['idCart']]['areOptionsAvailable'])){
$data[$row['idCart']]['areOptionsAvailable'] = true;
}
$data[$row['idCart']]['areOptionsAvailable'] = ($data[$row['idCart']]['areOptionsAvailable'] && $row['isAvailable']);
}
return $data;
}
/**
* returns the additional packages from the cart
* @return [type] [description]
*/
private function getCartAdditionalPackages(){
global $database, $user;
$packages = new Packages();
$data = [];
$sql = "SELECT
wscep.idCart,
p.name AS packageName,
wsc.idPackage AS idParentPackage,
rclc.idCommercialLead AS idCommercialLead,
plcl.idPaymentType AS idPaymentType,
rap.idAdditionalPackage AS idAdditionalPackage
FROM ".TABLES['web_shop_cart_extra_packages']." wscep
INNER JOIN ".TABLES['packages']." p
ON p.id=wscep.idExtraPackage
INNER JOIN ".TABLES['web_shop_cart']." wsc
ON wsc.id=wscep.idCart
INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
ON rclc.id=wsc.idCustomerInstance
INNER JOIN ".TABLES['price_list_commercial_lead']." plcl
ON wsc.idPrice = plcl.id
INNER JOIN ".TABLES['rel_additional_packages']." rap
ON p.id=rap.idAdditionalPackage AND rap.idPackage=wsc.idPackage
WHERE wsc.idUser=".$user->getUserId()." AND p.idPackageType=".self::PACKAGE_TYPES['ID_ADDITONAL_TYPE'];
$query = $database->query($sql);
while($row = $database->fetchArray($query)){
$additionalPackagesPrices = $packages->getPricesForPackages($row['idCommercialLead'], $row['idParentPackage'], self::PACKAGE_TYPES['ID_ADDITONAL_TYPE']);
$allPrices = isset($additionalPackagesPrices[$row['idAdditionalPackage']]) ? $additionalPackagesPrices[$row['idAdditionalPackage']] : [];
$isPaymentTypePresent = array_search($row['idPaymentType'], array_column($allPrices, 'idPaymentType'));
$priceByPaymentTypeKey = $isPaymentTypePresent !== false ? $isPaymentTypePresent : -1;
$row['prices'] = $priceByPaymentTypeKey > -1 ? $allPrices[$priceByPaymentTypeKey] : [];
$row['isAvailable'] = count($row['prices']) > 0;
$data[$row['idCart']]['additionalPackages'][] = $row;
if(!isset($data[$row['idCart']]['areAdditionalAvailable'])){
$data[$row['idCart']]['areAdditionalAvailable'] = true;
}
$data[$row['idCart']]['areAdditionalAvailable'] = ($data[$row['idCart']]['areAdditionalAvailable'] && $row['isAvailable']);
}
return $data;
}
/**
* calculates and returns the total price for the order
* @param Array $cartItems all teh items in the cart with the details
* @return String total and recurrent price with it's currency
*/
private function getCartTotalPrice($cartItems) {
$totalPrice = 0;
$totalRecurrentPrice = 0;
$currency = '';
$periodUnit = '';
foreach($cartItems as $item) {
$itemTotalPrice = $item['fixedPrice'];
$itemTotalRecurrentPrice = $item['recurentPrice'] + $item['servicesPrice'];
if(count($item['options'])) {
foreach($item['options'] as $packageOption) {
if(count($packageOption['prices'])) {
$itemTotalPrice += (float) $packageOption['prices']['fixedExtra'];
$itemTotalRecurrentPrice += (float) $packageOption['prices']['recurentExtra'] + (float) $packageOption['prices']['servicesExtra'];
}
}
}
if(count($item['additionalPackages'])) {
foreach($item['additionalPackages'] as $additionalPackage) {
if(count($additionalPackage['prices'])) {
$itemTotalPrice += (float) $additionalPackage['prices']['fixedExtra'];
$itemTotalRecurrentPrice += (float) $additionalPackage['prices']['recurentExtra'] + (float) $additionalPackage['prices']['servicesExtra'];
}
}
}
$itemTotalPrice *= $item['quantity'];
$itemTotalRecurrentPrice *= $item['quantity'];
$totalPrice += $itemTotalPrice;
$totalRecurrentPrice += $itemTotalRecurrentPrice;
$currency = $item['country']['currency'];
$periodUnit = $item['periodUnit'];
}
return $totalPrice . ' ' . $currency . ' ( '. $totalRecurrentPrice . ' ' . $currency . ' / ' . $periodUnit .' )';
}
/**
* update the quantity in the cart for an item
* @param INT $idPackage id for the package
* @param INT $idCustomerInstance id for the customer instance based on linking to cl
* @param INT $idPrice id for the price
* @param INT $quantity quantity value
* @return array update message
*/
public function updateQuantity($idPackage, $idCustomerInstance, $idPrice, $quantity){
global $database, $user;
$data = [];
$idPackage = $database->escapeValue($idPackage);
$idPrice = $database->escapeValue($idPrice);
$idCustomerInstance = $database->escapeValue($idCustomerInstance);
$quantity = $database->escapeValue($quantity);
if($database->invalidNumber('QUANTITY', $quantity, 1, 65000)){
$err_mes = [
'code' => 'error',
'message' => 'INVALID_QUANTITY'
];
$data['messages'][] = $err_mes;
return $data;
}
$sqlUpd = "UPDATE ".TABLES['web_shop_cart']."
SET quantity=$quantity
WHERE idPackage=$idPackage
AND idPrice=$idPrice
AND idCustomerInstance=$idCustomerInstance
AND idUser=".$user->getUserId()."
";
$query = $database->query($sqlUpd);
if($database->affectedRows() !== 1){
$err_mes = [
'code' => 'warning',
'message' => 'NO_CHANGE'
];
$data['messages'][] = $err_mes;
return $data;
}
$mes = [
'code' => 'success',
'message' => 'QUANTITY_UPDATED'
];
$data['messages'][] = $mes;
return $data;
}
/**
* remove item from cart
* @param INT $idCart id for the cart
* @return array update message
*/
public function removeFromCart($idCart){
global $database, $user;
$data = [];
$idCart = $database->escapeValue($idCart);
$sql = "DELETE FROM ".TABLES['web_shop_cart_extra_packages']."
WHERE idCart=$idCart ";
$query = $database->query($sql);
$sql = "DELETE FROM ".TABLES['web_shop_cart']."
WHERE id=$idCart
AND idUser=".$user->getUserId();
$query = $database->query($sql);
if($database->affectedRows() !== 1){
$err_mes = [
'code' => 'error',
'message' => 'INVALID_PACKAGE_FOR_REMOVE'
];
$data['messages'][] = $err_mes;
}else{
$message = [
'code' => 'success',
'message' => 'PACKAGE_REMOVED_FROM_CART'
];
$data['messages'][] = $message;
}
return $data;
}
/**
* upload questionaires for placing an order
* @param Array $file uploaded file
* @param String $idDocumentType type of the document
* @param String $documentName the name to be set for the file in database
* @param INT $idPackage id for the package
* @return Array upload message
*/
public function uploadOrderDocument($file, $idDocumentType, $idPackage){
global $database, $user;
$isReUpload = false;
$fileManager = new FileManager();
$documentField = '';
if(intval($idDocumentType) === self::DOCUMENT_TYPES['ID_CUSTOMER_QUESTIONNAIRE']){
$documentField = 'idDocument';
$documentName = 'customerQuestionaire_';
}else{
$documentField = 'idAgreementDocument';
$documentName = 'customerAgreement_';
}
$documentName .= $idPackage.'_'.date('Y_m_d');
$sql = "SELECT $documentField AS idDocument
FROM ".TABLES['web_shop_cart']."
WHERE idUser=".$user->getUserId()." AND idPackage=$idPackage AND $documentField IS NOT NULL";
$documents = $database->fetchResultArray($sql);
if(count($documents) > 0){
$document = $documents[0];
$data = $fileManager->updateDocument($document['idDocument'], $file);
$isReUpload = true;
}else{
$uploadedBy = $user->getUserId();
$data = $fileManager->uploadFile($file, $idDocumentType, $documentName, $uploadedBy);
$isReUpload = false;
}
if(isset($data['messages'])){
return $data;
}
if(!$isReUpload){
$idDocument = $data['idDocument'];
$sql = "UPDATE ".TABLES['web_shop_cart']."
SET $documentField=$idDocument
WHERE idUser=".$user->getUserId()." AND idPackage=$idPackage";
$query = $database->query($sql);
if($database->affectedRows() > 0){
$data['messages'][] = [
'code' => 'success',
'message' => 'FILE_UPLOADED'
];
}else{
$data['messages'][] = [
'code' => 'error',
'message' => 'NOT_LINKED_TO_CART'
];
}
}else{
$data['messages'][] = [
'code' => 'success',
'message' => 'FILE_UPLOADED'
];
}
return $data;
}
/**
* get files that have been uploaded before palcing an order and are found in the cart
* @param INT $packages id of the package
* @return Array array of uploaded documetns for a package
*/
private function getUploadedFilesForOrder($packages){
global $database, $user;
$data = [];
$sql = "SELECT
doc.id as idDocument,
doc.documentName,
doc.extension,
doc.idDocumentType,
wsc.idPackage
FROM ".TABLES['documents']." doc
INNER JOIN ".TABLES['web_shop_cart']." wsc
ON (doc.id=wsc.idDocument OR doc.id=wsc.idAgreementDocument) AND wsc.idUser=doc.uploadedBy
WHERE wsc.idPackage IN($packages) AND wsc.idUser=".$user->getUserId()."";
$query = $database->query($sql);
while($row = $database->fetchArray($query)){
$data[$row['idDocumentType']][$row['idPackage']] = $row;
}
return $data;
}
/**
* get required template documents to place an order
* @param Array $packages ids for the packages in the cart
* @return Array array of documents
*/
private function getTempalteDocuments($packages){
global $database;
$data = [];
$sql = "SELECT
d.id as idDocument,
d.documentName,
d.documentPath,
d.extension,
p.id AS idPackage,
p.name AS packageName,
d.idDocumentType
FROM ".TABLES['documents']." d
INNER JOIN ".TABLES['rel_package_documents']." rpd
ON rpd.idDocument=d.id
INNER JOIN ".TABLES['packages']." p
ON p.id=rpd.idPackage
WHERE rpd.idPackage IN($packages)
AND d.idDocumentType IN(".self::DOCUMENT_TYPES['ID_TEMPLATE_QUESIONNAIRE'].", ".self::DOCUMENT_TYPES['ID_TEMPLATE_AGREEMENT'].")";
$query = $database->query($sql);
while($row = $database->fetchArray($query)){
$data[$row['idDocumentType']][$row['idPackage']] = $row;
$idCustomerDocType = $row['idDocumentType'] == self::DOCUMENT_TYPES['ID_TEMPLATE_QUESIONNAIRE'] ? self::DOCUMENT_TYPES['ID_CUSTOMER_QUESTIONNAIRE'] : self::DOCUMENT_TYPES['ID_CUSTOMER_AGREEMENT'];
$data['docsPackage'][$idCustomerDocType][$row['idPackage']] = $row;
}
return $data;
}
/**
* get required documents to place an order
* @param Array $packages ids for the packages in the cart
* @return Array array of documents
*/
public function getCartDocuments($packages){
global $database;
$data = [];
$areFilesUploaded = true;
$uploaded = [];
$templates = [];
$packages = implode(',', $packages);
$packages = $database->escapeValue($packages);
if($packages) {
$uploaded = $this->getUploadedFilesForOrder($packages);
$templates = $this->getTempalteDocuments($packages);
}
if(array_key_exists('docsPackage', $templates)) {
foreach($templates['docsPackage'] as $idDocType => $templateDoc) {
foreach ($templateDoc as $idPackage => $packageDocDetails) {
if(!isset($uploaded[$idDocType]) || !isset($uploaded[$idDocType][$idPackage])){
$areFilesUploaded = false;
break;
}
}
}
unset($templates['docsPackage']);
}
return ['templates' => $templates, 'uploaded' => $uploaded, 'areFilesUploaded' => $areFilesUploaded];
}
/**
* get details of the customer logged in
* @return Array with neccessary details
*/
public function getCustomerDetails() {
global $database, $user;
$userId = $user->getUserId();
$data = [];
$addresHelper = new AddressHelper();
$sqlVatCode = "
SELECT c.vatCode,
c.name AS companyName
FROM ".TABLES['company']." c
INNER JOIN ".TABLES['users']." u
ON u.idCompany=c.id
WHERE u.id = ".$userId."
LIMIT 1";
$result = $database->fetchResultArray($sqlVatCode);
$data['vat'] = $result ? $result[0]['vatCode'] : '';
$data['companyName'] = $result ? $result[0]['companyName'] : '';
$data['deliveryAddresses'] = $addresHelper->getDeliveryAddress();
$data['billing'] = $addresHelper->getBillingAddress();
if($result = $this->getReferenceAndTender()) {
$data['details'] = $result[0];
}
return ['customerDetails' => $data];
}
/**
* returns the reference and tender if exists
* @return Array reference and tender for the order
*/
private function getReferenceAndTender() {
global $database, $user;
$sqlDetails = "
SELECT
reference,
tender,
idDeliveryAddress,
idBillingAddress,
idProject
FROM
".TABLES['web_shop_cart']." wsc
WHERE wsc.idUser = ".$user->getUserId();
return $database->fetchResultArray($sqlDetails);
}
/**
* gets the country name for the id provided
* @param Array $data all details
* @param String $addressType delivery or billing address
* @return String name of the country
*/
private function getCountryName($data, $addressType) {
if(array_key_exists($addressType, $data)) {
return $this->getCountryDetailsById($data[$addressType]['idCountrySelected'])[0]['countryName'];
}
return '';
}
/**
* returns the name and code of the country by it's id
* @param int $idCountry id of the country
* @return string the name of the country
*/
public function getCountryDetailsById($idCountry) {
global $database;
$countryName = '';
$sql = "
SELECT name AS countryName,
UPPER(code) AS countryCode
FROM ".TABLES['countries']."
WHERE id=$idCountry
LIMIT 1";
return $database->fetchResultArray($sql);
}
/**
* get all the countries
* @return Array country names and ids
*/
public function getCountries() {
global $database;
$sql = "SELECT c.id, c.name
FROM ".TABLES['countries']." c";
return ['countries' => $database->fetchResultArray($sql)];
}
/**
* checks whether the informations for the order are correct
* @param Array $cartPackages the packages to be placed in the order
* @param Array $deliveryInfo the delivery information for the order
* @param Array $billingInfo the billing information for the order
* @return Array error message ot empty
*/
private function validateOrderDetails($cartPackages, $deliveryInfo, $billingInfo, $details) {
global $database;
if(count($cartPackages) < 1) {
return [
'code' => 'error',
'message' => 'CART_EMPTY'
];
}
if(empty($deliveryInfo)){
return [
'code' => 'error',
'message' => 'NO_DELIVERY_ADDRESS'
];
}
if(empty($billingInfo)){
return [
'code' => 'error',
'message' => 'NO_BILLING_ADDRESS'
];
}
return [];
}
/**
* adds or updates the delivery address for the user logged in
* @param Array $deliveryInfo contaions the delivery address
* @return Int affected rows
*/
private function addUpdateOrderDeliveryAddress($deliveryInfo) {
global $database, $user;
foreach($deliveryInfo as $deliveryIndex => $detail) {
$deliveryInfo[$deliveryIndex] = $database->escapeValue($detail);
}
$sql = "
SELECT
id
FROM
".TABLES['delivery_addresses']."
WHERE idUser = ".$user->getUserId()."
AND idCountry = ".$deliveryInfo['idCountrySelected']."
AND city = '".$deliveryInfo['city']."'
AND detailedAddress = '".$deliveryInfo['detailedAddress']."'
AND zip = '".$deliveryInfo['zipCode']."'
";
$query = $database->query($sql);
if($database->numRows($query) === 0) {
$sqlDeliveryAddress = "
INSERT INTO ".TABLES['delivery_addresses']."
(idUser, idCountry, city, detailedAddress, zip)
VALUES (
".$user->getUserId().",
".$deliveryInfo['idCountrySelected'].",
'".$deliveryInfo['city']."',
'".$deliveryInfo['detailedAddress']."',
'".$deliveryInfo['zipCode']."'
)
";
$query = $database->query($sqlDeliveryAddress);
return $database->affectedRows();
}
return 0;
}
/**
* adds or updates the billing information for the user
* @param Array $billingInfo array of billing info - names and address
* @return Int affected rows
*/
private function addUpdateOrderBillingAddress($billingInfo) {
global $database, $user;
foreach($billingInfo as $billingIndex => $detail) {
$billingInfo[$billingIndex] = $database->escapeValue($detail);
}
$sql = "
SELECT
id
FROM
".TABLES['billing_information']."
WHERE idUser = ".$user->getUserId()."
AND idCountry = ".$billingInfo['idCountrySelected']."
AND company = '".$billingInfo['companyName']."'
AND firstName = '".$billingInfo['firstName']."'
AND lastname = '".$billingInfo['lastName']."'
AND city = '".$billingInfo['city']."'
AND detailedAddress = '".$billingInfo['detailedAddress']."'
AND zip = '".$billingInfo['zipCode']."'
";
$query = $database->query($sql);
if($database->numRows($query) === 0) {
$sqlBillingAddress = "
INSERT INTO ".TABLES['billing_information']."
(idUser, idCountry, company, firstName, lastName, city, detailedAddress, zip)
VALUES (
".$user->getUserId().",
".$billingInfo['idCountrySelected'].",
'".$billingInfo['companyName']."',
'".$billingInfo['firstName']."',
'".$billingInfo['lastName']."',
'".$billingInfo['city']."',
'".$billingInfo['detailedAddress']."',
'".$billingInfo['zipCode']."'
)
";
$query = $database->query($sqlBillingAddress);
return $database->affectedRows();
}
return 0;
}
/**
* returns the name and code of the country by it's id
* @param array $details details of the order
* @param array $items items from the cart
* @return array update messages
*/
public function saveOrderDetails($details, $items) {
global $database;
$addressInserted = 0;
$deliveryInfo = $details['delivery'];
$billingInfo = $details['billing'];
$orderDetails = $details['details'];
$orderDetails['idDeliveryAddress'] = isset($deliveryInfo['id']) ? $deliveryInfo['id'] : 'null';
$orderDetails['idBillingAddress'] = isset($billingInfo['id']) ? $billingInfo['id'] : 'null';
if($data['messages'][] = $this->validateOrderDetails($items, $deliveryInfo, $billingInfo, $orderDetails)) {
return $data;
}
if($this->updateCartInfo($orderDetails) > 0) {
$addressInserted++;
}
if($addressInserted) {
$data['messages'][] = [
'code' => 'success',
'message' => 'ADDRESS_INSERTED'
];
} else {
$data['messages'][] = [
'code' => 'warning',
'message' => 'NO_ADDRESS_CHANGES'
];
}
return $data;
}
/**
* updates the reference and tender for the order to be placed
* @param Array $details reference and tender
* @return Int number of rows affected
*/
private function updateCartInfo($details) {
global $database, $user;
foreach($details as $key => $detail) {
$details[$key] = $database->escapeValue($detail);
}
$idProject = isset($details['idProject']) && $details['idProject'] ? $details['idProject'] : 'NULL';
$sql = "
UPDATE
".TABLES['web_shop_cart']."
SET
reference = '".$details['reference']."',
tender = '".$details['tender']."',
idDeliveryAddress = '".$details['idDeliveryAddress']."',
idBillingAddress = '".$details['idBillingAddress']."',
idProject = $idProject
WHERE idUser = ".$user->getUserId();
$query = $database->query($sql);
return $database->affectedRows();
}
/**
* calculate the packages total price
* @param Array $cartPackage the details for the package in the cart
* @return float the total price per package
*/
private function calculatePackageTotalPrice($cartPackage){
$totalPrice = [
'fixedPrice' => 0,
'recurrentPrice' => 0,
'servicesPrice' => 0
];
if(!empty($cartPackage['bids']) && $cartPackage['idSelectedBid']){
$selectedBid = null;
foreach ($cartPackage['bids'] as $bid) {
if($bid['idBid'] === $cartPackage['idSelectedBid']){
$selectedBid = $bid;
break;
}
}
$totalPrice['fixedPrice'] += $selectedBid ? $selectedBid['fixedPrice'] : $cartPackage['fixedPrice'];
$totalPrice['recurrentPrice'] += $selectedBid ? $selectedBid['recurrentPrice'] : $cartPackage['recurentPrice'];
$totalPrice['servicesPrice'] += $selectedBid ? $selectedBid['servicesPrice'] : $cartPackage['servicesPrice'];
}else{
$totalPrice['fixedPrice'] += $cartPackage['fixedPrice'];
$totalPrice['recurrentPrice'] += $cartPackage['recurentPrice'];
$totalPrice['servicesPrice'] += $cartPackage['servicesPrice'];
}
if(isset($cartPackage['options'])){
foreach ($cartPackage['options'] as $option) {
if(count($option) && array_key_exists('prices', $option) && count($option['prices'])) {
$totalPrice['fixedPrice'] += $option['prices']['fixedExtra'];
$totalPrice['recurrentPrice'] += $option['prices']['recurentExtra'];
$totalPrice['servicesPrice'] += $option['prices']['servicesExtra'];
}
}
}
if(isset($cartPackage['additionalPackages'])){
foreach ($cartPackage['additionalPackages'] as $additionalPackage) {
if(count($additionalPackage) && array_key_exists('prices', $additionalPackage) && count($additionalPackage['prices'])) {
$totalPrice['fixedPrice'] += $additionalPackage['prices']['fixedExtra'];
$totalPrice['recurrentPrice'] += $additionalPackage['prices']['recurentExtra'];
$totalPrice['servicesPrice'] += $additionalPackage['prices']['servicesExtra'];
}
}
}
return $totalPrice;
}
/**
* genereate the order number using the id
* @param INT $idOrder id of the order
* @return INT order number containg the id value
*/
private function generateOrderNumber($idOrder){
return 1000000000 + $idOrder;
}
/**
* adds the relation between order and packages
* @param Array $orderPackages all the details for packages in order
* @param Int $idOrder the order id inserted
* @return Int the number of packages inserted
*/
private function addOrderPackageRelation($orderPackages, $idOrder) {
global $database;
$insertValues = '';
$sql = "
INSERT INTO ".TABLES['rel_order_packages']."
(idOrder, idPackage, packageInstance, idPaymentTerm, units, packageFixedPrice, packageRecuringPrice, packageServicePrice, idBid)
VALUES
";
foreach($orderPackages as $packageInfo) {
$totalPackagePrice = $this->calculatePackageTotalPrice($packageInfo);
$isPriceInRange = $this->checkIfPriceInRange($totalPackagePrice);
if($isPriceInRange) {
return $isPriceInRange;
}
$packageInfo['idSelectedBid'] = $packageInfo['idSelectedBid'] ? $packageInfo['idSelectedBid'] : 'NULL';
$sqlPaymentType = "
SELECT id
FROM ".TABLES['payment_types']." pt
WHERE pt.payType='".$packageInfo['payType']."'";
$result = $database->fetchResultArray($sqlPaymentType);
$idPayType = $result && $result[0]['id'] ? $result[0]['id'] : 0;
$insertValues .= "(
$idOrder,
'".$packageInfo['idPackage']."',
'".$packageInfo['packageInstance']."',
".$packageInfo['idPayType'].",
'".$packageInfo['quantity']."',
'".$totalPackagePrice['fixedPrice']."',
'".$totalPackagePrice['recurrentPrice']."',
'".$totalPackagePrice['servicesPrice']."',
".$packageInfo['idSelectedBid']."
),";
}
$insertValues = $insertValues ? rtrim($insertValues, ',') : '';
if($insertValues) {
$sql .= $insertValues;
$query = $database->query($sql);
return $database->affectedRows();
}
return 0;
}
/**
* add order documents to relation table
* @param Int $idOrder id of the order
* @param Int $idCustomerInstance id customer instance
* @return Int affected rows or 1
*/
private function addOrderDocuments($idOrder, $idCustomerInstance){
global $database, $user;
$getDocSql = "SELECT wsc.idDocument, wsc.idAgreementDocument, wsc.idPackage
FROM ".TABLES['web_shop_cart']." wsc
WHERE idCustomerInstance=$idCustomerInstance";
$query = $database->query($getDocSql);
$vals = "";
while($row = $database->fetchArray($query)){
if($row['idDocument']){
$vals .= "(" . $idOrder . ", " . $row['idPackage'] . ", " . $row['idDocument'] . "),";
}
if($row['idAgreementDocument']){
$vals .= "(" . $idOrder . ", " . $row['idPackage'] . ", " . $row['idAgreementDocument'] . "),";
}
}
;
if($vals){
$vals = rtrim($vals, ',');
$sql = "INSERT INTO ".TABLES['rel_order_documents']."
(idOrder, idPackage, idDocument)
VALUES $vals";
$query = $database->query($sql);
return $database->affectedRows();
}
return 1;
}
/**
* add extra option for order packages
* @param INT $idOrder id for the ORDER
* @return INT number of inserted elements
*/
private function addOrderExtraPackages($idOrder){
global $database, $user;
$sql = "INSERT INTO ".TABLES['rel_order_extra_packages']."
(idOrder, idPackage, idExtraPackage)
SELECT $idOrder, wsc.idPackage, wscep.idExtraPackage
FROM ".TABLES['web_shop_cart']." wsc
INNER JOIN ".TABLES['web_shop_cart_extra_packages']." wscep
ON wsc.id=wscep.idCart
WHERE wsc.idUser=".$user->getUserId();
$query = $database->query($sql);
return $database->affectedRows();
}
/**
* remove the packages from the web shop cart after placing the order
* @param Int $idCustomerInstance id of the customer
* @return Int number of rows deleted
*/
private function removePackagesFromCartAfterOrder($idCustomerInstance) {
global $database;
$sql = "
DELETE
FROM
".TABLES['web_shop_cart']."
WHERE idCustomerInstance = $idCustomerInstance";
$result = $database->query($sql);
return $database->affectedRows();
}
/**
* adds the installation company in the selection relations table
* @param Array $cartPackages the packages from the cart
* @param Int $idOrder the id of the order
* @return Array with confirmation message
*/
private function addInstallationCompanySelection($cartPackages, $idOrder) {
global $database;
$message = [];
foreach($cartPackages as $position => $package) {
$sql = "
SELECT
rpp.idProduct
FROM
".TABLES['rel_package_products']." rpp
INNER JOIN ".TABLES['suppliers_countries_products']." scp
ON scp.idProduct = rpp.idProduct
INNER JOIN ".TABLES['product_categories']." pc
ON scp.idProductCategory = pc.id
WHERE pc.id = ".self::PRODUCT_CATEGORIES['INSTALLATION']."
AND rpp.idPackage = ".$package['idPackage']."
AND rpp.packageInstance = ".$package['packageInstance'];
$products = $database->fetchResultArray($sql);
if(count($products) === 1) {
$installationScheduling = new InstallationScheduling();
$message = $installationScheduling->changeInstallationCompany($idOrder, $package['idPackage'], $products[0]['idProduct']);
}
}
return $message;
}
/**
* adds the order with the whole details
* @param String $cartPackages Json string with object containing the packages to order
* @param String $details Json string with object containing the details like refenrence or tender numbers
* @return Array confirmation message
*/
public function placeOrder($cartItems, $orderDetails) {
global $database, $user;
$rowsAffected = 0;
$deletedFromCart = 0;
$totalFixedPrice = 0;
$totalServicePrice = 0;
$userId = $user->getUserId();
$newCartPackages = [];
$packageToDisplay = '';
$unavailablePackageKey = '';
$idPackages = '';
$orderTypeInst = new OrderType();
$clCustomersInst = new ClCustomers();
$cartPackages = $cartItems;
$deliveryInfo = $orderDetails['delivery'];
$billingInfo = $orderDetails['billing'];
$details = $orderDetails['details'];
$options = $this->getCartItemOptions();
$additionalPackages = $this->getCartAdditionalPackages();
foreach($cartPackages as $packKey => $packageDetails) {
$packageDetails = (array) $packageDetails;
$areOptionsAvailable[$packageDetails['packageName']] = isset($options[$packageDetails['idCart']]) ? $options[$packageDetails['idCart']]['areOptionsAvailable'] : true;
$areAdditionalAvailable[$packageDetails['packageName']] = isset($additionalPackages[$packageDetails['idCart']]) ? $additionalPackages[$packageDetails['idCart']]['areAdditionalAvailable'] : true;
$packageNames[] = $packageDetails['packageName'];
foreach($packageDetails as $packDetailKey => $packageDetail) {
if(!is_array($packageDetail)){
$newCartPackages[$packKey][$packDetailKey] = $database->escapeValue($packageDetail);
}else{
$newCartPackages[$packKey][$packDetailKey] = $packageDetail;
}
}
$commercialLeadName = $packageDetails['commercialLead'];
$idCommercialLead = $packageDetails['idCommercialLead'];
$idPackages .= $packageDetails['idPackage'].',';
}
$unavailablePackageKey = $this->getNameIfPackageUnavailable($idPackages);
$optionPackageKey = array_keys($areOptionsAvailable, false);
if(count($optionPackageKey)) {
$unavailablePackageKey = $optionPackageKey[0];
} else {
$additionalPackageKey = array_keys($areAdditionalAvailable, false);
if(count($additionalPackageKey)) {
$unavailablePackageKey = $additionalPackageKey[0];
}
}
if($unavailablePackageKey) {
$data['messages'][] = [
'code' => 'error',
'message' => 'UNAVAILABLE_PACKAGE_IN_CART',
'key' => $unavailablePackageKey
];
return $data;
}
$cartPackages = $newCartPackages;
foreach ($cartPackages as $position => $cartPackage) {
$optionsToDisplay = '';
if(isset($cartPackage['options'])){
$optionsToDisplay .= '(';
foreach ($cartPackage['options'] as $key => $option) {
$optionsToDisplay .= $option['groupName'] . ' : ' . $option['packageName'] .',';
}
$optionsToDisplay = rtrim($optionsToDisplay, ',');
$optionsToDisplay .= ')';
}
if(isset($cartPackage['additionalPackages'])){
$optionsToDisplay .= '(';
foreach ($cartPackage['additionalPackages'] as $key => $option) {
$optionsToDisplay .= $option['packageName'] .', ';
}
$optionsToDisplay = rtrim($optionsToDisplay, ',');
$optionsToDisplay .= ')';
}
$packageTotalPrices = $this->calculatePackageTotalPrice($cartPackage);
$packageToDisplay .= ($position + 1).'. <b>'.$packageNames[$position].'</b>
'.$optionsToDisplay.'
<div class="mail-order-package-detail">
<div>Commercial lead: '.$cartPackage['commercialLead'].'</div>
<div>Payment type: '.$cartPackage['payType'].'</div>
<div>Quantity: '.$cartPackage['quantity'].'</div>
<label>'.$packageTotalPrices['fixedPrice'] * $cartPackage['quantity'].' ('.($packageTotalPrices['recurrentPrice'] + $packageTotalPrices['servicesPrice']) * $cartPackage['quantity'].' / '.$cartPackage['periodUnit'].')</label>
</div> <br /><hr>
';
$totalFixedPrice += $packageTotalPrices['fixedPrice'] * $cartPackage['quantity'];
$totalServicePrice += ($packageTotalPrices['recurrentPrice'] + $packageTotalPrices['servicesPrice']) * $cartPackage['quantity'];
$totalPeriodUnit = $cartPackage['periodUnit'];
}
$packageToDisplay .= 'Total Price: <b>'.$totalFixedPrice.' ('.$totalServicePrice.' / '.$totalPeriodUnit.')</b><br /><br />';
foreach($deliveryInfo as $deliveryKey => $delivery) {
$deliveryInfo[$deliveryKey] = $database->escapeValue($delivery);
}
foreach($billingInfo as $billingKey => $billing) {
$billingInfo[$billingKey] = $database->escapeValue($billing);
}
foreach($details as $detailKey => $detail) {
$details[$detailKey] = $database->escapeValue($detail);
}
$database->beginTransaction();
$sqlCustomerInstance = "
SELECT
rclc.id AS idCustomerInstance
FROM
".TABLES['rel_commercial_lead_customers']." rclc
INNER JOIN ".TABLES['customers']." c
ON c.id = rclc.idCustomer
AND c.idUser = $userId
INNER JOIN ".TABLES['commercial_leads']." cl
ON cl.id = rclc.idCommercialLead
AND cl.id = '".$idCommercialLead."'
WHERE rclc.isLinkEnabled=1
LIMIT 1";
$result = $database->fetchResultArray($sqlCustomerInstance);
if($result && $result[0]['idCustomerInstance']) {
$idCustomerInstance = $result[0]['idCustomerInstance'];
} else {
$data['messages'][] = [
'code' => 'error',
'message' => 'LINK_CUSTOMER_CL'
];
$database->rollback();
return $data;
}
$customerInfo = $clCustomersInst->getClCustomerInfo($idCommercialLead);
$orderType = $customerInfo['idOrderType'] ? $customerInfo['idOrderType'] : $orderTypeInst->getCLDefaultOrderType($idCommercialLead);
if($customerInfo['isSameCompanyAsCl'] == 1){
$orderType = $orderTypeInst::ORDER_TYPES['reseller'];
}
$sqlOrderNumber = "
SELECT
MAX(id) + 1 AS orderNumber
FROM
".TABLES['orders']."
LIMIT 1";
$result = $database->fetchResultArray($sqlOrderNumber);
$orderNumber = $result && $result[0]['orderNumber'] ? $this->generateOrderNumber($result[0]['orderNumber']) : '1000000000';
$today = new DateTime();
$reference = array_key_exists('reference', $details) && $details['reference'] ? $details['reference'] : '';
$tender = array_key_exists('tender', $details) && $details['tender'] ? $details['tender'] : '';
$idProject = array_key_exists('idProject', $details) && $details['idProject'] ? $details['idProject'] : 'NULL';
$countryDetails = $this->getCountryDetailsById($deliveryInfo['idCountrySelected'])[0];
$countryName = $countryDetails['countryName'];
$countryCode = $countryDetails['countryCode'];
$concatenatedDeliveryAddress = $deliveryInfo['detailedAddress'].", ".$deliveryInfo['city'].", $countryName, ".$deliveryInfo['zipCode'];
$billingCountryDetails = $this->getCountryDetailsById($billingInfo['idCountrySelected'])[0];
$concatenatedBillingAddress = $billingInfo['detailedAddress'].", ".$billingInfo['city'].", ".$billingCountryDetails['countryName'].", ".$billingInfo['zipCode'];
$deliveryFirstName = $deliveryInfo['firstName'];
$deliveryLastName = $deliveryInfo['lastName'];
$deliveryMail = $deliveryInfo['deliveryMail'];
$billingFirstName = $billingInfo['firstName'];
$billingLastName = $billingInfo['lastName'];
$billingMail = $billingInfo['invoiceMail'];
$projectNumber = $countryCode . $orderNumber;
$orderDate = $today->format('Y-m-d H:m:s');
$packageToDisplay .= '<b>Delivery address</b>: '.$concatenatedDeliveryAddress.'<br />';
$packageToDisplay .= '<b>Billing address</b>: '.$concatenatedBillingAddress.'<br />';
$sql = "SELECT MAX(t.id) as idTemrs
FROM ".TABLES['terms']." t";
$terms = $database->fetchResultArray($sql)[0];
$sql = "
INSERT INTO ".TABLES['orders']."
(idCustomerInstance, orderNumber, orderDate, reference, tender, projectNumber, deliveryAddress, deliveryFirstName, deliveryLastName, deliveryMail, billingAddress, billingFirstName, billingLastName, billingMail, idTerms, idOrderType, idProject)
VALUES (
$idCustomerInstance,
'".$orderNumber."',
'".$orderDate."',
'".$reference."',
'".$tender."',
'".$projectNumber."',
'".$concatenatedDeliveryAddress."',
'".$deliveryFirstName."',
'".$deliveryLastName."',
'".$deliveryMail."',
'".$concatenatedBillingAddress."',
'".$billingFirstName."',
'".$billingLastName."',
'".$billingMail."',
'".$terms['idTemrs']."',
'".$orderType."',
".$idProject."
)
";
$query = $database->query($sql);
if($database->affectedRows() === 1){
$rowsAffected++;
} else {
$data['messages'][] = [
'code' => 'error',
'message' => 'ERROR_ORDER_INSERT'
];
$database->rollback();
return $data;
}
$idOrder = $database->getInsertId();
$relationData = $this->addOrderPackageRelation($cartPackages, $idOrder);
if(is_array($relationData) || $relationData <= 0) {
$data['messages'][] = is_array($relationData) ? $relationData : [
'code' => 'error',
'message' => 'ERROR_ORDER_PACK_RELATION'
];
$database->rollback();
return $data;
} else {
$rowsAffected++;
}
if($this->addOrderDocuments($idOrder, $idCustomerInstance) > 0) {
$rowsAffected++;
} else {
$data['messages'][] = [
'code' => 'error',
'message' => 'ERROR_ON_ADDING_DOCUMENTS'
];
$database->rollback();
return $data;
}
$addedOptions = $this->addOrderExtraPackages($idOrder);
$deletedFromCart = $this->removePackagesFromCartAfterOrder($idCustomerInstance, $userId);
if($this->addInstallationCompanySelection($cartPackages, $idOrder)) {
$data['messages'][] = $this->addInstallationCompanySelection($cartPackages, $idOrder);
}
if($rowsAffected >= 3) {
$database->commit();
$data['messages'][] = [
'code' => 'success',
'message' => 'ORDER_PLACED'
];
if($deletedFromCart > 0) {
$data['messages'][] = [
'code' => 'success',
'message' => 'PACKAGES_DELETED'
];
}
$orderInfo['idOrder'] = $idOrder;
$orderInfo['orderNumber'] = $orderNumber;
$orderInfo['orderDate'] = $orderDate;
$data['messages'][] = UtilsModel::sendOrderConfirmationMail($packageToDisplay, 'customer', $orderInfo);
$data['messages'][] = UtilsModel::sendOrderConfirmationMail($packageToDisplay, 'broker', $orderInfo);
} else {
$data['messages'][] = [
'code' => 'error',
'message' => 'ORDER_ERROR'
];
$database->rollback();
}
return $data;
}
/**
* return the name of the package unavailable or empty
* @param String $idPackages all the ids of the packages from the cart
* @return String the name of the package unavailable or empty
*/
private function getNameIfPackageUnavailable($idPackages) {
global $database;
if(!$idPackages) {
return '';
}
$idPackages = rtrim($idPackages, ',');
$sql = "SELECT
IF(p.status = 'available', 1, 0) AS isAvailable,
p.name
FROM
".TABLES['packages']." p
WHERE p.id IN ($idPackages)";
$query = $database->query($sql);
while($row = $database->fetchArray($query)) {
if(intval($row['isAvailable']) === 0) {
return $row['name'];
}
}
return '';
}
/**
* checks if the prices have more than 15 digits
* @return Bool true if all the prices have digits lower than 15
*/
private function checkIfPriceInRange($packageTotalPrice) {
global $database;
$max_value = 1 * pow(10, 15);
$fixPriceMessage = $database->invalidNumber('fixed price', $packageTotalPrice['fixedPrice'], 0, $max_value);
if($fixPriceMessage) {
return $fixPriceMessage;
} else {
$recurrentPriceMessage = $database->invalidNumber('recurrent price', $packageTotalPrice['recurrentPrice'], 0, $max_value);
if($recurrentPriceMessage) {
return $recurrentPriceMessage;
} else {
$servicePriceMessage = $database->invalidNumber('services price', $packageTotalPrice['servicesPrice'], 0, $max_value);
return $servicePriceMessage ? $servicePriceMessage : null;
}
}
return null;
}
public function setBidForCart($idBid, $idCart){
$bidsHandler = new Bids();
return $bidsHandler->setBidForCart($idBid, $idCart);
}
}