<?php

namespace App\ReportsData\Populate\Entity;

class Service extends \App\ReportsData\Populate\GeneralAbstract
{

	/**
	 * The customer passports table.
	 * @var string
	 */
	private $dbTableName_offers;


	/**
	 * Returns the table name that will store the current entity queue.
	 * @return string
	 */
	protected function getDbTableName()
	{
		global $DBTRd_services, $DBTRd_offers;
		$this->dbTableName_offers = $DBTRd_offers;
		return $DBTRd_services;
	}


	/**
	 * {@inheritDoc}
	 * @see \App\ReportsData\Populate\GeneralAbstract::getEntityFields()
	 */
	protected function getEntityFields()
	{
		// get current entity details
		$entity = \Entity\Service::select($this->id);

		// for non existing rows - return null
		if (!$entity->recordExists()) {
			return null;
		}

		// PREPARE SERVICE DETAILS ----------------------------------------------------------------

		// relevant invoice details
		$invoiceEnt = $entity->relevantInvoice;
		$defaultCurrency = \App\Config\Currencies::getInstance()->getDefaultCurrency();
		$workCurrency = \App\Config\Currencies::getInstance()->getWorkCurrency();
		$invoiceCurrencyRate = \App\CurrencyExchange\Rates::getInstance($invoiceEnt->invoiceDate)->convert(1, $invoiceEnt->currency, $defaultCurrency, null);
		$invoiceWorkCurrencyRate = \App\CurrencyExchange\Rates::getInstance($invoiceEnt->invoiceDate)->convert(1, $workCurrency, $defaultCurrency, null);

		// get invoice rows list (for the current service)
		$invRowsList = $entity->invoiceRowsList;
		$invoiceCompVals = [];
		$invoiceVals = [];
		$invoiceComponentsIssue = $invoiceComponentsRefund = [];
		foreach($invRowsList as $idRow=>$rowDetails) {
			$rowVal = \App\CurrencyExchange\Rates::getInstance($rowDetails['invoiceDate'])->convert($rowDetails['pricePrintValue'], $rowDetails['currency'], $invoiceEnt->currency, null);
			$rowVat = \App\CurrencyExchange\Rates::getInstance($rowDetails['invoiceDate'])->convert($rowDetails['vatPrintValue'], $rowDetails['currency'], $invoiceEnt->currency, null);
			$rowTtl = $rowVal + $rowVat;

			$invoiceCurrencyPrecision = \App\Config\CurrencyDecimals::getCurrencyDecimals($rowDetails['currency']);

			$invoiceCompVals[$rowDetails['rowType']]['val'] += $rowVal;
			$invoiceCompVals[$rowDetails['rowType']]['vat'] += $rowVat;
			$invoiceVals['val'] += $rowVal;
			$invoiceVals['vat'] += $rowVat;
			if ($rowDetails['special']) { // refund details
				$invoiceVals['refund']['val'] += $rowVal;
				$invoiceVals['refund']['vat'] += $rowVat;
				if ($rowDetails['rowType']=='price') { // break by supplier + commission
					$invoiceComponentsRefund[$rowDetails['rowType']]['val'] = round( $invoiceComponentsRefund[$rowDetails['rowType']]['val'] + $rowVal, $invoiceCurrencyPrecision );
					$invoiceComponentsRefund[$rowDetails['rowType']]['vat'] = round( $invoiceComponentsRefund[$rowDetails['rowType']]['vat'] + $rowVat, $invoiceCurrencyPrecision );
					$rowEnt = \Entity\InvoiceRow::select($idRow);
					$invoiceComponentsRefund['commission']['val'] = round( $invoiceComponentsRefund['commission']['val'] + $rowEnt->estProfitTotal, $invoiceCurrencyPrecision );
					$invoiceComponentsRefund['supplier']['val'] = round( $invoiceComponentsRefund['supplier']['val'] + $rowTtl - $rowEnt->estProfitTotal, $invoiceCurrencyPrecision );
				} else {
					$invoiceComponentsRefund[$rowDetails['rowType']]['val'] = round( $invoiceComponentsRefund[$rowDetails['rowType']]['val'] + $rowVal, $invoiceCurrencyPrecision );
					$invoiceComponentsRefund[$rowDetails['rowType']]['vat'] = round( $invoiceComponentsRefund[$rowDetails['rowType']]['vat'] + $rowVat, $invoiceCurrencyPrecision );
				}
			} else { // issue details
				$invoiceVals['issue']['val'] += $rowVal;
				$invoiceVals['issue']['vat'] += $rowVat;
				if ($rowDetails['rowType']=='price') { // break by supplier + commission
					$invoiceComponentsIssue[$rowDetails['rowType']]['val'] = round( $invoiceComponentsIssue[$rowDetails['rowType']]['val'] + $rowVal, $invoiceCurrencyPrecision );
					$invoiceComponentsIssue[$rowDetails['rowType']]['vat'] = round( $invoiceComponentsIssue[$rowDetails['rowType']]['vat'] + $rowVat, $invoiceCurrencyPrecision );
					$rowEnt = \Entity\InvoiceRow::select($idRow);
					$invoiceComponentsIssue['commission']['val'] = round( $invoiceComponentsIssue['commission']['val'] + $rowEnt->estProfitTotal, $invoiceCurrencyPrecision );
					$invoiceComponentsIssue['supplier']['val'] = round( $invoiceComponentsIssue['supplier']['val'] + $rowTtl - $rowEnt->estProfitTotal, $invoiceCurrencyPrecision );
				} else { // normal row
					$invoiceComponentsIssue[$rowDetails['rowType']]['val'] = round( $invoiceComponentsIssue[$rowDetails['rowType']]['val'] + $rowVal, $invoiceCurrencyPrecision );
					$invoiceComponentsIssue[$rowDetails['rowType']]['vat'] = round( $invoiceComponentsIssue[$rowDetails['rowType']]['vat'] + $rowVat, $invoiceCurrencyPrecision );
				}
			}

		}

		// determine invoicedPercent
		if ($entity->statusFin=='NI') {
			$invoicedPercent = 0;
		} elseif ($entity->statusFin=='TI') {
			$invoicedPercent = 1;
		} else {
			if ($entity->offerTotal) { // this should not happen, but there was a bug when the offer is different than the invoice and the service is left as PI
				$invoicedPercent = $entity->invoicedTotal / $entity->offerTotal;
			} else {
				$invoicedPercent = 1;
			}
		}

		$multiplierTotal = 0;
		if (is_array($entity->multiplierCode)) {
			foreach ($entity->multiplierCode as $quantity) {
				$multiplierTotal += $quantity;
			}
		}
		else {
			$multiplierTotal = $entity->multiplierCode?:0;
		}

		/**
		 *  [service attributes]: populate serviceAttributes in the following structure:
		 *  category / productType / serviceSource:
		 *  	type: none, text, list;
		 *  	listType: [null], radio, checkbox; - from \App\Config\Services_Fields::getInstance()->getServiceAttributeListType
		 *  	code: [ent->categoryCode] - text / radio code; 3
		 *  	name: text / radio name; 3*
		 *  	codes: [ent->categoryCode] lista (checkbox); [b,c]
		 *  	names: ['a'=>'1*', 'b'=>'2*', 'c'=>'3*',...]
		 *
		 *  multiplier:
		 *  	type: none, value, list;
		 *  	value: [value]; eg: 7
		 *  	values: [pt list]; eg: ['s'=>2, 'd'=>4]
		 *  	names: ['s'=>'SGL', 'd'=>'DBL',...]
		 */
		// [service attributes]: category /////////////////////////////////////////////////////////
		$categoryCode = $categoryName = $categoryCodes = $categoryNames = null;
		$categoryDetails = [];
		$categoryListType = \App\Config\Services_Fields::getInstance()->getServiceAttributeListType($entity->serviceCode, 'category');

		if ($entity->categoryConfig['type'] == 'text') {
			$categoryCode = $categoryName = $entity->categoryCode;
		}
		elseif ($entity->categoryConfig['type'] == 'list') {
			if ($categoryListType == 'radio') {
				$categoryCode = $entity->categoryCode;
				$categoryName = $entity->categoryConfig['list'][$entity->categoryCode];
			}
			elseif ($categoryListType == 'checkbox') {
				$categoryCodes = $entity->categoryCode;
				$categoryNames = array_intersect_key($entity->categoryConfig['list'], array_combine($entity->categoryCode, $entity->categoryCode));
			}
		}

		$categoryDetails = [
			'type' => $entity->categoryConfig['type'],
			'listType' => ($entity->categoryConfig['type'] == 'list') ? $categoryListType : null,
			'code' => $categoryCode,
			'name' => $categoryName,
			'codes' => $categoryCodes,
			'names' => $categoryNames,
		];

		// [service attributes]: product type /////////////////////////////////////////////////////
		$productTypeCode = $productTypeName = $productTypeCodes = $productTypeNames = null;
		$productTypeDetails = [];
		$productTypeListType = \App\Config\Services_Fields::getInstance()->getServiceAttributeListType($entity->serviceCode, 'productType');

		if ($entity->productTypeConfig['type'] == 'text') {
			$productTypeCode = $productTypeName = $entity->productTypeCode;
		}
		elseif ($entity->productTypeConfig['type'] == 'list') {
			if ($productTypeListType == 'radio') {
				$productTypeCode = $entity->productTypeCode;
				$productTypeName = $entity->productTypeConfig['list'][$entity->productTypeCode];
			}
			elseif ($productTypeListType == 'checkbox') {
				$productTypeCodes = $entity->productTypeCode;
				$productTypeNames = array_intersect_key($entity->productTypeConfig['list'], array_combine($entity->productTypeCode, $entity->productTypeCode));
			}
		}

		$productTypeDetails = [
			'type' => $entity->productTypeConfig['type'],
			'listType' => ($entity->productTypeConfig['type'] == 'list') ? $productTypeListType : null,
			'code' => $productTypeCode,
			'name' => $productTypeName,
			'codes' => $productTypeCodes,
			'names' => $productTypeNames,
		];

		// [service attributes]: service source ///////////////////////////////////////////////////
		$serviceSourceCode = $serviceSourceName = $serviceSourceCodes = $serviceSourceNames = null;
		$serviceSourceDetails = [];
		$serviceSourceListType = \App\Config\Services_Fields::getInstance()->getServiceAttributeListType($entity->serviceCode, 'serviceSource');

		if ($entity->serviceSourceConfig['type'] == 'text') {
			$serviceSourceCode = $serviceSourceName = $entity->serviceSourceCode;
		}
		elseif ($entity->serviceSourceConfig['type'] == 'list') {
			if ($serviceSourceListType == 'radio') {
				$serviceSourceCode = $entity->serviceSourceCode;
				$serviceSourceName = $entity->serviceSourceConfig['list'][$entity->serviceSourceCode];
			}
			elseif ($serviceSourceListType == 'checkbox') {
				$serviceSourceCodes = $entity->serviceSourceCode;
				$serviceSourceNames = array_intersect_key($entity->serviceSourceConfig['list'], array_combine($entity->serviceSourceCode, $entity->serviceSourceCode));
			}
		}

		$serviceSourceDetails = [
			'type' => $entity->serviceSourceConfig['type'],
			'listType' => ($entity->serviceSourceConfig['type'] == 'list') ? $serviceSourceListType : null,
			'code' => $serviceSourceCode,
			'name' => $serviceSourceName,
			'codes' => $serviceSourceCodes,
			'names' => $serviceSourceNames,
		];

		// [service attributes]: multiplier ///////////////////////////////////////////////////////
		$multiplierDetails = [
			'type' => $entity->multiplierConfig['type'],
			'value' => ($entity->multiplierConfig['type'] == 'value') ? $entity->multiplierCode : null,
			'values' => ($entity->multiplierConfig['type'] == 'list') ? $entity->multiplierCode : null,
			'names' => ($entity->multiplierConfig['type'] == 'list') ? array_intersect_key($entity->multiplierConfig['list'], $entity->multiplierCode) : null,
		];

		// [service attributes]: populate service attributes //////////////////////////////////////
		$serviceAttributes = [
			'category' => $categoryDetails,
			'productType' => $productTypeDetails,
			'multiplier' => $multiplierDetails,
			'serviceSource' => $serviceSourceDetails,
		];

		// first psg and first tkt no
		if ($entity->passengersTicketsList) {
			$psgTkts = $entity->passengersTicketsList;
			$firstTicketNumber = reset($psgTkts);
		} else {
			$firstTicketNumber = '';
		}
		if ($entity->idCustomersList) {
			$custList = $entity->idCustomersList;
			$idFirstCustomer = reset($custList);
		} else {
			$idFirstCustomer = 0;
		}

		// POPULATE THE ENTITY DETAILS ------------------------------------------------------------
		$return = [
			'id'						=> $this->id,
			'idOrder'					=> $entity->idOrder,
			'idPackageService'			=> $entity->idPackageService,
			'packageOfferMode'			=> $entity->packageOfferMode,
			'linkedToIdService'			=> $entity->linkedToIdService,
			'idImportedService'			=> (Int)$entity->idRelevantImportedService,
			'idExternalSystem'			=> $entity->idExternalSystem,
			'idAutoProcessRule'			=> $entity->idAutoProcessRule,
			'idCustomers'				=> ($entity->idCustomersList ? json_encode($entity->idCustomersList) : ''),
			'idFirstCustomer'			=> $idFirstCustomer,
			'pax'						=> $entity->pax,
			'undefinedPaxDetails'		=> ($entity->undefinedPax ? json_encode($entity->undefinedPax) : ''),
			'serviceCode'				=> $entity->serviceCode,
			'serviceName'				=> $entity->serviceName,
			'serviceAttributes'			=> ($serviceAttributes ? json_encode($serviceAttributes) : ''),
			'serviceCfgCat'				=> (String)$entity->serviceConfigCategoryCode,
			'category'					=> $entity->categoryReadable,
			'productType'				=> $entity->productTypeReadable,
			'multiplier'				=> $entity->multiplierReadable,
			'multiplierTotal'			=> $multiplierTotal,
			'serviceSource'				=> $entity->serviceSourceReadable,
			'productName'				=> $entity->productName,
			'idSupplierProduct'			=> $entity->idSupplierProduct,
			'startDate'					=> $entity->startDate,
			'startTime'					=> $entity->startTime,
			'endDate'					=> ($entity->endDate?:null),
			'endTime'					=> $entity->endTime,
			'duration'					=> $entity->duration,
			'departureCountryCode'		=> $entity->departureCountryCode,
			'departureCityId'			=> $entity->departureCityId,
			'departureStationCode'		=> $entity->departureStationCode,
			'destinationCountryCode'	=> $entity->destinationCountryCode,
			'destinationCityId'			=> $entity->destinationCityId,
			'destinationStationCode'	=> $entity->destinationStationCode,
			'description'				=> $entity->description,
			'preferences'				=> $entity->preferences,
			'comments'					=> $entity->comments,
			'remarks'					=> $entity->remarks,
			'processedRemarks'			=> ($entity->processedRemarks ? json_encode($entity->processedRemarks) : ''),
			'passengersTicketsList'		=> ($entity->passengersTicketsList ? json_encode($entity->passengersTicketsList) : ''),
			'firstTicketNumber'			=> $firstTicketNumber,
			'passengersTicketsDate'		=> ($entity->passengersTicketsDate?:null),
			'invoicedPercent'			=> $invoicedPercent,
			'statusOp'					=> $entity->statusOp,
			'statusFin'					=> $entity->statusFin,
			'estInvoiceDate'			=> $entity->estInvoiceDate,
			'estCashDate'				=> $entity->estCashDate,
			'reversedService'			=> $entity->reversedService,
			'cancelReason'				=> $entity->cancelReason,
			'cancelReasonDetails'		=> $entity->cancelReasonDetails,
			'idBalance'					=> $entity->idBalance,
			'idBalanceRefund'			=> $entity->idBalanceRefund,
			'agencyCostCenter'			=> $entity->agencyCostCenter,
			'genDocsAssoc'				=> ($entity->generatedDocumentsAssoc ? json_encode($entity->generatedDocumentsAssoc) : ''),
			'extraInfo'					=> ($entity->extraInfo ? json_encode($entity->extraInfo) : ''),
			'idUser'					=> $entity->idUser,
			'idOffice'					=> $entity->idOffice,
			'idAddUser'					=> $entity->idAddUser,
			'addTime'					=> \Engine\DateTime::createFromTimestamp($entity->addTime)->formatDatetimeIso(),
			'lastUpdateTime'			=> ( $entity->lastUpdateTime ? \Engine\DateTime::createFromTimestamp($entity->lastUpdateTime)->formatDatetimeIso() : null ),
			'idUpdateUser'				=> $entity->idUpdateUser,
			'updatesCount'				=> $entity->updatesCount,
			'idOffer'					=> $entity->chosenOfferId,
			'idRelevantInvoice'			=> $entity->idRelevantInvoice,
			'idRelevantInvoiceRefund'	=> $entity->idRelevantInvoiceRefund,
			'idInvoiceRows'				=> ($invRowsList ? json_encode(array_keys($invRowsList)) : ''),
			'invoiceCurrency'			=> (String)$invoiceEnt->currency,
			'invoiceCurrencyRate'		=> $invoiceCurrencyRate,
			'invoiceWorkCurrencyRate'	=> $invoiceWorkCurrencyRate,
			'invoiceValue'				=> (Double)$invoiceVals['val'],
			'invoiceVat'				=> (Double)$invoiceVals['vat'],
			'invoiceTotal'				=> (Double)($invoiceVals['val']+$invoiceVals['vat']),
			'invoiceServicePriceValue'	=> (Double)$invoiceCompVals['price']['val'],
			'invoiceServicePriceVat'	=> (Double)$invoiceCompVals['price']['vat'],
			'invoiceCommissionValue'	=> (Double)$invoiceCompVals['commission']['val'],
			'invoiceCommissionVat'		=> (Double)$invoiceCompVals['commission']['vat'],
			'invoiceDiscountValue'		=> (Double)$invoiceCompVals['discount']['val'],
			'invoiceDiscountVat'		=> (Double)$invoiceCompVals['discount']['vat'],
			'invoiceServiceFeeValue'	=> (Double)$invoiceCompVals['serviceFee']['val'],
			'invoiceServiceFeeVat'		=> (Double)$invoiceCompVals['serviceFee']['vat'],
			'invoiceTaxValue'			=> (Double)$invoiceCompVals['tax']['val'],
			'invoiceTaxVat'				=> (Double)$invoiceCompVals['tax']['vat'],
			'invoiceAdvanceValue'		=> (Double)$invoiceCompVals['advance']['val'],
			'invoiceAdvanceVat'			=> (Double)$invoiceCompVals['advance']['vat'],
			'invoicePenaltyValue'		=> (Double)$invoiceCompVals['penalty']['val'],
			'invoicePenaltyVat'			=> (Double)$invoiceCompVals['penalty']['vat'],
			'invoiceIssueTotal'			=> (Double)($invoiceVals['issue']['val']+$invoiceVals['issue']['vat']),
			'invoiceRefundTotal'		=> (Double)($invoiceVals['refund']['val']+$invoiceVals['refund']['vat']),
			'invoiceIssueValues'		=> ( $invoiceComponentsIssue ? json_encode($invoiceComponentsIssue) : ''),
			'invoiceRefundValues'		=> ( $invoiceComponentsRefund ? json_encode($invoiceComponentsRefund) : ''),
			'invoiceCashedStatus'		=> $entity->invoicesCashedStatus,
			'invoiceCashedPercent'		=> $entity->invoiceCashedPercent,
			'invoiceCashedValue'		=> $entity->invoiceCashedValue,
			'invoiceNotCashedValue'		=> $entity->invoiceNotCashedValue,
			'invoiceIssueCashedValue'	=> $entity->invoiceIssueCashedValue,
			'invoiceIssueNotCashedValue' => $entity->invoiceIssueNotCashedValue,
			'invoiceRefundCashedValue'	=> $entity->invoiceRefundCashedValue,
			'invoiceRefundNotCashedValue' => $entity->invoiceRefundNotCashedValue,
			'refunded'					=> $entity->refunded,
			'refundDate'				=> $entity->refundDate?:null,
			'balanceProfitDefCurr'		=> $entity->balanceProfitDefCurr,
			'balanceIssueProfitDefCurr'	=> $entity->balanceIssueProfitDefCurr,
			'balanceRefundProfitDefCurr'=> $entity->balanceRefundProfitDefCurr,
		];

		// ADD POPULATING REFERENCES --------------------------------------------------------------
		// parent order
		$this->addPopulatingReference('Order', $entity->idOrder);
		// linked imported services - both directly (processed from) or indirectly (manually associated afterwards).
		if ($entity->importedServicesList) {
			foreach ($entity->importedServicesList as $impServDet) {
				$this->addPopulatingReference('ImportedService', $impServDet['id']); // esp. a ticketing service may be associated to multiple imported services (via manual tkt number)
			}
		}
		if ($entity->idImportedService) {
			$this->addPopulatingReference('ImportedService', $entity->idImportedService); // esp. a ticketing service may be associated to multiple imported services (via manual tkt number)
		}
		// linked package subservices
		if ($entity->packageSubservices) {
			foreach ($entity->packageSubservices as $idSubServ=>$subServDet) {
				$this->addPopulatingReference('Service', $idSubServ); // the rollback action (service package cancel is solved by manual adding of a trigger on service cancel)
			}
		}

		return $return;
	}


	/**
	 * Add service offer details.
	 * {@inheritDoc}
	 * @see \App\ReportsData\Populate\GeneralAbstract::populate()
	 */
	public function populate() :void
	{

		// INSERT THE SERVICE /////////////////////////////////////////////////////////////////////
		parent::populate();

		// DELETE PREVIOUS OFFERS /////////////////////////////////////////////////////////////////
		$this->dbExecuteDelete($this->dbTableName_offers, 'idService', $this->id);

		// GET OFFER DETAILS //////////////////////////////////////////////////////////////////////
		$offer = \Entity\Service::select($this->id)->chosenOffer;

		// inits
		$flightType = $serviceClassCodeFirst = $serviceClassNameFirst = '';
		$flightDistancesStr = $flightDurationsStr = $flightNumbersStr = '';
		$fareBasisStr = $classNamesStr = $classCodesStr = '';
		$paymentMaskedNo = $paymentCompany = $cashingMaskedNo = $cashingCompany = '';
		$paymentExpireDate = $cashingExpireDate = NULL;

		// ADD NEW OFFER //////////////////////////////////////////////////////////////////////////
		if ($offer->recordExists()) {
			$defaultCurrency = \App\Config\Currencies::getInstance()->getDefaultCurrency();
			$workCurrency = \App\Config\Currencies::getInstance()->getWorkCurrency();
			$offerCurrencyRate = \App\CurrencyExchange\Rates::getInstance($offer->currencyDate)->convert(1, $offer->totalCurrency, $defaultCurrency, null);
			$offerWorkCurrRate = \App\CurrencyExchange\Rates::getInstance($offer->currencyDate)->convert(1, $workCurrency, $defaultCurrency, null);

			if (!$offer->endDatetime->isEmpty()) {
				$endDatetime = $offer->endDatetime->formatDatetimeIso();
			} else {
				$endDatetime = null;;
			}

			if ($offer->itinerary) {
				$itinerary = json_encode($offer->itinerary->exportAsArray());
				$itineraryReadable = $offer->itinerary->getFromFormat();
			} else {
				$itinerary = '';
				$itineraryReadable = '';
			}

			// prepare other fields (related to itinerary)
			$flightDistanceTotal = 0;
			if ($offer->itinerary and $offer->itinerary->getSegmentsCount()) {
				$itineraryObj = $offer->itinerary;

				// determine flight type
				$itineraryAnalyser = new \App\Utils\Itinerary\ItineraryAnalyser($itineraryObj);
				$itineraryAnalyser->analyse();
				$flightType = $itineraryAnalyser->getType();

				// first segment
				$segments = $itineraryObj->getSegments();

				// first segment columns
				$firstSegment = reset($segments);
				$serviceClassCodeFirst = $firstSegment->getServiceClassCode();
				$serviceClassNameFirst = $firstSegment->getServiceClassName();

				// populate all
				$classCodes = $classNames = $fareBasis = $flightNumbers = $flightDurations = $flightDistances = [];
				foreach($segments as $segmentObj) {
					$classCodes[]		= $segmentObj->getServiceClassCode();
					$classNames[]		= $segmentObj->getServiceClassName();
					$fareBasis[]		= $segmentObj->getFareBasis();
					$flightNumbers[]	= $segmentObj->getTransportNumber();
					if ($segmentObj->getDuration()) {
						$flightDurations[]	= substr($segmentObj->getDuration(), 0, 5);
					}
					$thisDist = $segmentObj->getDistance();
					if ($thisDist->value) {
						$flightDistanceTotal += is_numeric($thisDist->value)?$thisDist->value:0;
						$flightDistances[]	= $thisDist->value.' '.$thisDist->unit;
					}
				}

				// cleanup empty elements
				$classCodesStr		= implode('/', array_filter($classCodes));
				$classNamesStr		= implode('/', array_filter($classNames));
				$fareBasisStr		= implode('/', array_filter($fareBasis));
				$flightNumbersStr	= implode('/', array_filter($flightNumbers));
				$flightDurationsStr	= implode('/', array_filter($flightDurations));
				$flightDistancesStr	= implode('/', array_filter($flightDistances));

			}

			// get payment card details
			$creditCardStorage = new \App\Utils\CreditCard\Storage();
			if ($offer->paymentIdCreditCard) {
			    $paymentCardDetails  = $creditCardStorage->getCard($offer->paymentIdCreditCard);
			    if ($paymentCardDetails) { // we had issues on staging instance, but this is useless on production
				    $paymentMaskedNo     = $paymentCardDetails['truncatedNumber'];
				    $paymentExpireDate   = $paymentCardDetails['expireDate'];
				    $paymentCompany      = $paymentCardDetails['company'];
			    }
			}
			if ($offer->cashingIdCreditCard) {
			    $cashingCardDetails  = $creditCardStorage->getCard($offer->cashingIdCreditCard);
			    if ($cashingCardDetails) { // we had issues on staging instance, but this is useless on production
				    $cashingMaskedNo     = $cashingCardDetails['truncatedNumber'];
				    $cashingExpireDate   = $cashingCardDetails['expireDate'];
				    $cashingCompany      = $cashingCardDetails['company'];
			    }
			}

			// ACTUAL INSERT OF THE OFFER -------------------------------------------------------------
			$fields = [
				'id'							=> $offer->getId(),
				'idService'						=> $offer->idService,
				'idSupplier'					=> $offer->idSupplier,
				'idSupplierProduct'				=> $offer->idSupplierProduct,
				'productName'					=> $offer->productName,
				'offerType'						=> $offer->offerTypeCode,
				'serviceCode'					=> $offer->serviceCode,
				'location'						=> $offer->locationCode,
				'calculationType'				=> $offer->calculationType,
				'commissionable'				=> $offer->commissionable,
				'ignoreSupplierOnDocuments'		=> $offer->ignoreSupplierOnDocuments,
				'currency'						=> $offer->totalCurrency,
				'currencyRate'					=> $offerCurrencyRate,
				'workCurrencyRate'				=> $offerWorkCurrRate,
				'supplierValue'					=> $offer->supplierWorkValue,
				'supplierVat'					=> $offer->supplierWorkVat,
				'commissionValue'				=> $offer->commissionWorkValue,
				'commissionVat'					=> $offer->commissionWorkVat,
				'discountValue'					=> $offer->discountWorkValue,
				'discountVat'					=> $offer->discountWorkVat,
				'serviceFeeValue'				=> $offer->serviceFeeWorkValue,
				'serviceFeeVat'					=> $offer->serviceFeeWorkVat,
				'taxValue'						=> $offer->taxWorkValue,
				'taxVat'						=> $offer->taxWorkVat,
				'offerTotal'					=> $offer->offerWorkTotal,
				'netCompanyTotal'				=> $offer->netCompanyWorkTotal,
				'currencyType'					=> $offer->currencyTypeCode,
				'currencyDate'					=> $offer->currencyDate,
				'expirationDate'				=> $offer->expirationDate,
				'cancellationPolicy'			=> $offer->cancellationPolicy,
				'optionDate'					=> $offer->optionDate,
				'formOfPayment'					=> (String)$offer->formOfPayment,
				'paymentCcEntityType'			=> $offer->paymentCcEntityType,
				'paymentCcEntityId'				=> $offer->paymentCcEntityId,
				'paymentCcApprovalCode'			=> $offer->paymentCcApprovalCode,
				'paymentCcValue'				=> $offer->paymentCcValue,
				'paymentCcCurrency'				=> $offer->paymentCcCurrency,
			    'paymentCcMaskedNo'				=> $paymentMaskedNo,
			    'paymentCcExpireDate'			=> $paymentExpireDate,
			    'paymentCcCompany'				=> $paymentCompany,
			    'formOfCashing'					=> (String)$offer->formOfCashing,
				'cashingCcEntityType'			=> $offer->cashingCcEntityType,
				'cashingCcEntityId'				=> $offer->cashingCcEntityId,
				'cashingCcApprovalCode'			=> $offer->cashingCcApprovalCode,
			    'cashingCcMaskedNo'				=> $cashingMaskedNo,
			    'cashingCcExpireDate'			=> $cashingExpireDate,
			    'cashingCcCompany'				=> $cashingCompany,
				'startDatetime'					=> $offer->startDatetime->formatDatetimeIso(),
				'endDatetime'					=> $endDatetime,
				'duration'						=> $offer->duration,
				'departureCountryCode'			=> $offer->departureCountryCode,
				'departureCityId'				=> $offer->departureCityId,
				'departureStationCode'			=> $offer->departureStationCode,
				'destinationCountryCode'		=> $offer->destinationCountryCode,
				'destinationCityId'				=> $offer->destinationCityId,
				'destinationStationCode'		=> $offer->destinationStationCode,
				'itinerary'						=> $itinerary,
				'itineraryReadable'				=> $itineraryReadable,
				'flightType'					=> (String)$flightType,
				'serviceClassCodeFirst'			=> (String)$serviceClassCodeFirst,
				'serviceClassNameFirst'			=> (String)$serviceClassNameFirst,
				'serviceClassCodes'				=> (String)$classCodesStr,
				'serviceClassNames'				=> (String)$classNamesStr,
				'fareBasis'						=> (String)$fareBasisStr,
				'flightNumbers'					=> (String)$flightNumbersStr,
				'flightDurations'				=> (String)$flightDurationsStr,
				'flightDistances'				=> (String)$flightDistancesStr,
				'flightDistanceTotal'			=> $flightDistanceTotal,
				'comments'						=> $offer->comments,
				'externalSystemReservationId'	=> $offer->externalSystemReservationId,
				'externalSystemReservationDate'	=> ( $offer->externalSystemReservationDate ? $offer->externalSystemReservationDate : null ),
				'confirmationNumber'			=> $offer->confirmationNumber,
				'idAddUser'						=> $offer->idAddUser,
				'addTime'						=> \Engine\DateTime::createFromTimestamp($offer->addTime)->formatDatetimeIso(),
				'idUpdateUser'					=> $offer->idUpdateUser,
				'lastUpdateTime'				=> ( $offer->lastUpdateTime ? \Engine\DateTime::createFromTimestamp($offer->lastUpdateTime)->formatDatetimeIso() : null ),
				'updatesCount'					=> $offer->updatesCount,
			];

			$this->dbExecuteInsert($this->dbTableName_offers, $fields);

		}

	}


}
