<?php

// TODO: [not important] sa se elimine toate atributele care se determina folosind \Engine\DateTime::isoToStd
// TODO: [not important] sa se elimine toate atributele care se se pot determina din formule

namespace App\GenDocument\Vars;

class Values_Invoice extends ValuesAbstract
{

	protected $pivot = 'invoice';


	/**
	 * {@inheritDoc}
	 * @see \App\GenDocument\Vars\ValuesAbstract::checkPivot()
	 */
	protected function checkPivot() :void
	{
		$pivotObj = \Entity\Invoice::select($this->idPivot);
		if ($this->idPivot!=-1 and !$pivotObj->recordExists()) {
			throw new \Exception("The pivot `{$this->pivot}` with id = `{$this->idPivot}` is not valid.");
		}
	}

	/**
	 * The methd is used for getting the value of a certain field for the current pivot.
	 * Called from \App\GenDocument\Vars\ValuesInterface::getValue().
	 * @param String $field
	 * @return Mixed - the value of the field or NULL if the field is not present here
	 */
	protected function getSpecificPivotValue($field) {

		$CFG = \Engine\Loader_Cfg::getInstance()->getGlobal();
		$_LANG = \App\Loader_Lang::getInstance()->getGlobal();

		// the return value
		$r = null;

		// the invoice pivot
		$invoice=\Entity\Invoice::select($this->idPivot);

		// field is found in this huge switch
		$fieldFound=true;

		// THE HUGE SWITCH WHICH WILL TREAT ALL THE VARIABLES /////////////////////////////////////
		switch ($field) {

			// GENERAL INVOICE DETAILS ////////////////////////////////////////////////////////////

			case 'invId' :								$r=$this->idPivot; break;
			case 'invObj' :								$r=$invoice; break;
			case 'invDateIso':							$r=$invoice->invoiceDate; break;
			case 'invDateStandard':						$r=\Engine\DateTime::isoToStd($invoice->invoiceDate); break;
			case 'invNumber': 							$r=$invoice->invoiceNumber; break;
			case 'invSeriesId':							$r=$invoice->idInvoiceSeries; break;
			case 'invSeriesCode':						$r=$invoice->invoiceSeries->code; break;
			case 'invDueDateIso':						$r=$invoice->dueDate; break;
			case 'invDueDateStandard':					$r=\Engine\DateTime::isoToStd($invoice->dueDate); break;
			case 'invDueDuration':						$r=$invoice->dueDuration; break;
			case 'fulfillmentDateIso':					$r=$invoice->fulfillmentDate; break;
			case 'fulfillmentDateStandard':				$r=\Engine\DateTime::isoToStd($invoice->fulfillmentDate); break;
			case 'invComments':							$r=$invoice->comments; break;
			case 'invFormOfPayment':					$r=$invoice->formOfPaymentName; break;
			case 'invValue':							$r=$invoice->printValue; break;
			case 'invVat':								$r=$invoice->printVat; break;
			case 'invTotal':							$r=$invoice->printTotal; break;
			case 'invCashedTotal':
				$currDecimals = \App\Config\CurrencyDecimals::getCurrencyDecimals($invoice->currency);
				$r=round($invoice->cashedTotal, $currDecimals);
				break;
			case 'invCurrency':							$r=$invoice->currency; break;
			case 'invCurrency2':
				$currDet=\App\Config\Currencies::getInstance()->get($invoice->currency);
				$r=$currDet['currencyName2'];
				break;
			case 'invCurrencySubdivision':
				$currDet=\App\Config\Currencies::getInstance()->get($invoice->currency);
				$r=$currDet['subdivisionName']?$currDet['subdivisionName']:"";
				break;
			case 'invReferCurrencyTypeName':			$r=\App\Config\CurrencyTypes::getInstance()->getName($CFG['currencies']['defaultCurrencyType']); break;
			case 'invReferCurrencyTypeRate':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) {
					$r=\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert(1, $invoice->currency, $CFG['currencies']['defaultCurrency'], null);
				}
				break;
			case 'invReferCurrencyTypeRateAbs':			$r=\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert(1, $invoice->currency, $CFG['currencies']['defaultCurrency'], null); break;
			case 'invReferCurrencyTypeRateWorkCurr':	$r=\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert(1, $CFG['currencies']['workCurrency'], $CFG['currencies']['defaultCurrency'], null); break;
			case 'invReferCurrency':					$r=$CFG['currencies']['defaultCurrency']; break;
			case 'invCurrencyExchangeRate':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) {
					$r=$_LANG['documentsSpecialWords']['currencyExchangeRate'].' '.\App\Config\CurrencyTypes::getInstance()->getName($CFG['currencies']['defaultCurrencyType']).' ';
					$r.='1'.$invoice->currency.'='.\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert(1, $invoice->currency, $CFG['currencies']['defaultCurrency'], null).$CFG['currencies']['defaultCurrency'];
				}
				break;
			case 'invTotalInDefaultCurrency':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) $r=\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert($invoice->printTotal, $invoice->currency, $CFG['currencies']['defaultCurrency']);
				break;
			case 'invTotalInDefCurrWithCurr':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) $r=$this->getValue('invTotalInDefaultCurrency').' '.$CFG['currencies']['defaultCurrency'];
				break;
			case 'invVatInDefaultCurrency':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) $r=\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert($invoice->printVat, $invoice->currency, $CFG['currencies']['defaultCurrency']);
				break;
			case 'invVatInDefCurrWithCurr':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) $r=$this->getValue('invVatInDefaultCurrency').' '.$CFG['currencies']['defaultCurrency'];
				break;
			case 'invValueInDefaultCurrency':
				if ($invoice->currency!=$CFG['currencies']['defaultCurrency']) $r=\App\CurrencyExchange\Rates::getInstance($invoice->invoiceDate)->convert($invoice->printValue, $invoice->currency, $CFG['currencies']['defaultCurrency']);
				break;
			case 'firstServStartDateIso': case 'firstServStartDateStandard': case 'lastServEndDateIso':
				$minDate=DATE_LIMIT_MAX;$maxDate=DATE_LIMIT_MIN;
				foreach($invoice->rowsList as $row) {
					$servStartDate=\Entity\Service::select($row['idReservationService'])->startDate;
					$servEndDate=\Entity\Service::select($row['idReservationService'])->endDate;
					if (!$servEndDate or $servEndDate==DATE_LIMIT_MIN) $servEndDate=$servStartDate;
					if ($servStartDate<$minDate) $minDate=$servStartDate;
					if ($servEndDate>$maxDate) $maxDate=$servEndDate;
				}
				if ($field=='firstServStartDateIso') $r=$minDate;
				if ($field=='firstServStartDateStandard') $r=\Engine\DateTime::isoToStd($minDate);
				if ($field=='lastServEndDateIso') $r=$maxDate;
				break;
			case 'servicesDestCntrZones':
				$zones=[];
				foreach($invoice->rowsList as $row) {
					$servCntrZone=\Entity\Service::select($row['idReservationService'])->destinationCountry->zoneName;
					$zones[$servCntrZone]=true;
				}
				$r=implode(', ', array_keys($zones));
				break;
			case 'servicesDefinedPaxList':
				// get full list of passengers ids
				$fullPsgIdList = [];
				foreach($invoice->rowsList as $row) {
					$psgList=\Entity\Service::select($row['idReservationService'])->idCustomersList;
					$fullPsgIdList=array_merge($fullPsgIdList, $psgList);
				}
				$fullPsgIdList=array_unique($fullPsgIdList);
				// determine the list of passengers names
				$fullPsgNames = [];
				foreach($fullPsgIdList as $id) { $fullPsgNames[]= \Entity\Customer::select($id)->name; }
				$r=implode(', ', $fullPsgNames);
				break;
			case 'invReservationConvId':
				$resNos = [];
				foreach($invoice->rowsList as $row) {
					$resNos[ \Entity\Service::select($row['idReservationService'])->order->convertedId ] = true;
				}
				$r=implode(', ', array_keys($resNos));
				break;
			case 'invReservationNumber':
				$resNos = [];
				foreach($invoice->rowsList as $row) {
					$resNos[ \Entity\Service::select($row['idReservationService'])->order->reservationNumber ] = true;
				}
				$r=implode(', ', array_keys($resNos));
				break;
			case 'invReservationContactPersons':
				$resCtcPers = [];
				foreach($invoice->rowsList as $row) {
					$ctcPersName = \Entity\Service::select($row['idReservationService'])->order->contactPerson->name;
					$resCtcPers[$ctcPersName] = true;
				}
				$r=implode(', ', array_keys($resCtcPers));
				break;
			case 'invMiceProjects':
				$miceProjects = [];
				foreach($invoice->rowsList as $row) {
					$ord = \Entity\Service::select($row['idReservationService'])->order;
					$miceProjects[$ord->idMiceProject] = $ord->miceProject->name;
				}
				$r=implode(', ', $miceProjects);
				break;
			case 'invVatBase':
				$r=0;
				foreach(\Entity\Invoice::select($this->idPivot)->rowsList as $id=>$row) $r+=\Entity\InvoiceRow::select($id)->vatBasePrintValue;
				break;
			case 'invCreditNoteRef': case 'invCreditNoteRefNoSer':
				$orgInvRef = [];
				foreach($invoice->rowsList as $row) {
					// get the reversed invoice row id
					$revRowId=0;
					if ($row['reversesInvoiceRowId']) $revRowId=$row['reversesInvoiceRowId'];
					elseif ($row['cumulatesInvoiceRowId']) $revRowId=\Entity\InvoiceRow::select($row['cumulatesInvoiceRowId'])->reversesInvoiceRowId;
					// get invoice details for this row
					if ($revRowId) {
						if ($field=='invCreditNoteRef') {
							$key = sprintf("%s %s/%s",
								\Entity\InvoiceRow::select($revRowId)->invoice->invoiceSeries->code,
								\Entity\InvoiceRow::select($revRowId)->invoice->invoiceNumber,
								\Engine\DateTime::createFromIsoDate(\Entity\InvoiceRow::select($revRowId)->invoice->invoiceDate)->formatDateStd()
							);
						} else {
							$key = sprintf("%s/%s",
								\Entity\InvoiceRow::select($revRowId)->invoice->invoiceNumber,
								\Engine\DateTime::createFromIsoDate(\Entity\InvoiceRow::select($revRowId)->invoice->invoiceDate)->formatDateStd()
							);
						}
						$orgInvRef[$key] = true;
					}
				}
				$r=implode(', ', array_keys($orgInvRef));
				break;
			case 'invOffersEquivDetails':
				// get offers value/currency in a list
				$invOfferRows = [];
				foreach($invoice->rowsList as $row) {
					$offCurr=\Entity\Service::select($row['idReservationService'])->offerTotalCurrency;
					$invOfferRows[$offCurr][$row['currencyType']]+=array_sum($row['accountingDetails']);
				}
				// compose the result
				$r='';
				$currTypesDet=\App\Config\CurrencyTypes::getInstance()->getSimple();
				foreach($invOfferRows as $curr=>$currDet) {
					foreach($currDet as $currType=>$val) {
						$r.=round($val, 2).' '.$curr.';'.$currTypesDet[$currType]."\n";
					}
				}
				$r=trim($r);
				break;


			// INVOICE ROWS COUNT /////////////////////////////////////////////////////////////////
			case 'invRowsCount_invoice':
				$r=count($invoice->visibleRowsList);
				break;

			// INVOICE VAT QUOTAS /////////////////////////////////////////////////////////////////
			case 'invVatQuotaFull': case 'invVatRemarksFull':
				$elems = [];
				foreach ($invoice->rowsList as $row) {
					if ($field=='invVatQuotaFull') {
						$elems[$row['vatText']] = true;
					}
					if ($field=='invVatRemarksFull') {
						$thisVatRmArr = \App\Config\Services_Calculations_InvoiceVat::getInstance()->getCalculationDetails($row['serviceCode'], $row['location'], $row['calculationType']);
						$elems[ $thisVatRmArr[$row['rowType']]['vatRemark'] ] = true;
					}
				}
				$r = implode(', ', array_keys($elems));
				break;
			case 'invVatQuotaServices':
				$elems = [];
				foreach ($invoice->rowsList as $row) {
					if (!isset($elems[$row['idReservationService']])) {
						$elems[$row['idReservationService']] = $row['vatText'];
					}
				}
				$r = implode(', ', array_unique($elems));
				break;

			// generated documents
			case 'idGenDoc_invoiceProforma':
				$idSelectedDoc=0;
				foreach($invoice->documentsList as $idDoc=>$docDet) {
					if ($docDet['docType']=='invoiceProforma' and !$docDet['preview'] and !$docDet['voided']) {
						$idSelectedDoc=$idDoc; // this is overwritten - to get the last document
					}
				}
				$r=$idSelectedDoc;
				break;

			// CORPORATE CLIENT FIELDS ////////////////////////////////////////////////////////////
			case 'invClientGeneralType':				if ($invoice->idCorporate) $r='corporate';else $r='customer'; break;
			case 'invClientCorpId':						$r=$invoice->idCorporate; break;
			case 'invClientCorpCompany':				$r=$invoice->corporate->companyStandard; break;
			case 'invClientCorpCompanyFull':			$r=$invoice->corporate->companyFullStandard; break;
			case 'invClientCorpCompanyPrefix':			$r=$invoice->corporate->companyPrefixStandard; break;
			case 'invClientCorpCompanySuffix':			$r=$invoice->corporate->companySuffixStandard; break;
			case 'invClientCorpCompany2':				$r=$invoice->corporate->companyLocal; break;
			case 'invClientCorpCompanyFull2':			$r=$invoice->corporate->companyFullLocal; break;
			case 'invClientCorpCompanyPrefix2':			$r=$invoice->corporate->companyPrefixLocal; break;
			case 'invClientCorpCompanySuffix2':			$r=$invoice->corporate->companySuffixLocal; break;
			case 'invClientCorpCompany_alt':
				$r=$invoice->corporate->companyStandard;
				if (!$r) $r=$invoice->corporate->companyLocal;
				break;
			case 'invClientCorpCompanyFull_alt':
				$r=$invoice->corporate->companyFullStandard;
				if (!$r) $r=$invoice->corporate->companyFullLocal;
				break;
			case 'invClientCorpCompany2_alt':
				$r=$invoice->corporate->companyLocal;
				if (!$r) $r=$invoice->corporate->companyStandard;
				break;
			case 'invClientCorpCompanyFull2_alt':
				$r=$invoice->corporate->companyFullLocal;
				if (!$r) $r=$invoice->corporate->companyFullStandard;
				break;
			case 'invClientCorpAlias':					$r=$invoice->corporate->alias; break;
			case 'invClientCorpTrust':					$r=$invoice->corporate->trust->name; break;
			case 'invClientCorpTelephone':				$r=$invoice->corporate->telephone; break;
			case 'invClientCorpFax':					$r=$invoice->corporate->fax; break;
			case 'invClientCorpEmail':					$r=$invoice->corporate->email; break;
			case 'invClientCorpFiscalCode':				$r=$invoice->corporate->fiscalCode; break;
			case 'invClientCorpRegNo':					$r=$invoice->corporate->regNo; break;
			case 'invClientCorpEuid':					$r=$invoice->corporate->euid; break;
			case 'invClientCorpRegistryAddress':		$r=$invoice->corporate->registryAddress; break;
			case 'invClientCorpVatCertificateNumber':	$r=$invoice->corporate->vatCertificateNumber; break;
			case 'invClientCorpAccountingNumber':		$r=$invoice->corporate->accountingNumber; break;
			case 'invClientCorpContractNumbersList':
				if ($invoice->idCorporate) {
					// services on this invoice
					$servOnInv = [];
					foreach($invoice->rowsList as $row) $servOnInv[$row['serviceCode']]=true;
					// collect contracts that are associated to one of these services or "all"
					$cntrNumbersList = [];

					$corporateContractObj = new \App\EntityList\CorporateContracts();
					$corporateContractObj->setColumns(['active', 'deleted', 'serviceCode', 'idResponsibleUser', 'contractNumber', 'contractDate', 'expireDate']);
					$corporateContractObj->setFilter('idCorporate', '=', $invoice->idCorporate);

					$corporateContractArray = [];

					foreach ($corporateContractObj->exportRecords() as $corporateContract) {
						$corporateContractArray[$corporateContract['id']] = [
							'active' => 			$corporateContract['active'],
							'deleted' =>			$corporateContract['deleted'],
							'serviceCode' => 		$corporateContract['serviceCode'],
							'idResponsibleUser' => 	$corporateContract['idResponsibleUser'],
							'contractNumber' => 	$corporateContract['contractNumber'],
							'contractDate' => 		$corporateContract['contractDate'],
							'expireDate' => 		$corporateContract['expireDate'],
						];
					}


					foreach($corporateContractArray as $thisContract) {
						if ( !$thisContract['serviceCode'] or $servOnInv[$thisContract['serviceCode']]) {
							$cntrNumbersList[] = $thisContract['contractNumber'] . '/' . \Engine\DateTime::isoToStd($thisContract['contractDate']);
						}
					}
					$r=implode(', ', $cntrNumbersList);
				}
				break;

			// CORPORATE ACCOUNT MANAGER ----------------------------------------------------------
			case 'invClientCorpAccMngName':				$r=$invoice->corporate->accountManager->name; break;
			case 'invClientCorpAccMngLastName':			$r=$invoice->corporate->accountManager->lastName; break;
			case 'invClientCorpAccMngFirstName':		$r=$invoice->corporate->accountManager->firstName; break;
			case 'invClientCorpAccMngIdSeries':			$r=$invoice->corporate->accountManager->ID_series; break;
			case 'invClientCorpAccMngIdNumber':			$r=$invoice->corporate->accountManager->ID_number; break;
			case 'invClientCorpAccMngIdReleaseBy':		$r=$invoice->corporate->accountManager->ID_releaseBy; break;
			case 'invClientCorpAccMngIdReleaseDateIso':	$r=$invoice->corporate->accountManager->ID_releaseDate; break;
			case 'invClientCorpAccMngIdReleaseDateStandard':$r=\Engine\DateTime::isoToStd($invoice->corporate->accountManager->ID_releaseDate); break;
			case 'invClientCorpAccMngPNC':				$r=$invoice->corporate->accountManager->PNC; break;
			case 'invClientCorpAccMngJob':				$r=$invoice->corporate->accountManager->job; break;
			case 'invClientCorpAccMngEmail':			$r=$invoice->corporate->accountManager->email; break;
			case 'invClientCorpAccMngEmailAlternative':	$r=$invoice->corporate->accountManager->emailAlternative; break;
			case 'invClientCorpAccMngTelephone':		$r=$invoice->corporate->accountManager->telephone; break;
			case 'invClientCorpAccMngFax':				$r=$invoice->corporate->accountManager->fax; break;
			case 'invClientCorpAccMngDeptName':			$r=$invoice->corporate->accountManager->department->name; break;
			case 'invClientCorpAccMngDeptCode':			$r=$invoice->corporate->accountManager->department->code; break;

			// CORPORATE MAIN OFFICE DETAILS ------------------------------------------------------
			case 'invClientCorpMainOffId':				$r=$invoice->corporate->idMainOffice; break;
			case 'invClientCorpMainOffName':			$r=$invoice->corporate->mainOffice->name; break;
			case 'invClientCorpMainOffCountry':			$r=$invoice->corporate->mainOffice->country->name; break;
			case 'invClientCorpMainOffCity':			$r=$invoice->corporate->mainOffice->city->name; break;
			case 'invClientCorpMainOffAddress':			$r=$invoice->corporate->mainOffice->address; break;
			case 'invClientCorpMainOffDeliveryAddress':
				$r=$invoice->corporate->mainOffice->deliveryAddress;
				if (!$r) $r=$invoice->corporate->mainOffice->address;
				break;
			case 'invClientCorpMainOffZipCode':			$r=$invoice->corporate->mainOffice->zipCode; break;
			case 'invClientCorpMainOffTelephone':		$r=$invoice->corporate->mainOffice->telephone; break;
			case 'invClientCorpMainOffFax':				$r=$invoice->corporate->mainOffice->fax; break;
			case 'invClientCorpMainOffEmail':			$r=$invoice->corporate->mainOffice->email; break;
			case 'invClientCorpMainOffBank':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBank']) {
					$r=\Entity\Bank::select($defaultBankAccount['idBank'])->name;
					if ($defaultBankAccount['idBankOffice']) $r.=' ('.\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->name.')';
				}
				break;
			case 'invClientCorpMainOffBankName':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBank']) {
					$r=\Entity\Bank::select($defaultBankAccount['idBank'])->name;
				}
				break;
			case 'invClientCorpMainOffBankCode':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBank']) {
					$r=\Entity\Bank::select($defaultBankAccount['idBank'])->code;
				}
				break;
			case 'invClientCorpMainOffBankOffName':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->name;
				}
				break;
			case 'invClientCorpMainOffBankOffAddress':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->address;
				}
				break;
			case 'invClientCorpMainOffBankOffMfo':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->mfo;
				}
				break;
			case 'invClientCorpMainOffBankOffSwiftCode':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->swiftCode;
				}
				break;
			case 'invClientCorpMainOffBankAccount':
				$defaultBankAccount=$invoice->corporate->mainOffice->defaultBankAccountDetails;
				$r=$defaultBankAccount['account'];
				break;



			// CORPORATE CURRENT OFFICE DETAILS ---------------------------------------------------

			case 'invClientCorpCurrOffId':				$r=$invoice->idCorporateOffice; break;
			case 'invClientCorpCurrOffName':			$r=$invoice->corporateOffice->name; break;
			case 'invClientCorpCurrOffCountry':			$r=$invoice->corporateOffice->country->name; break;
			case 'invClientCorpCurrOffCity':			$r=$invoice->corporateOffice->city->name; break;
			case 'invClientCorpCurrOffAddress':			$r=$invoice->corporateOffice->address; break;
			case 'invClientCorpCurrOffDeliveryAddress':
				$r=$invoice->corporateOffice->deliveryAddress;
				if (!$r) $r=$invoice->corporateOffice->address;
				break;
			case 'invClientCorpCurrOffZipCode':			$r=$invoice->corporateOffice->zipCode; break;
			case 'invClientCorpCurrOffTelephone':		$r=$invoice->corporateOffice->telephone; break;
			case 'invClientCorpCurrOffFax':				$r=$invoice->corporateOffice->fax; break;
			case 'invClientCorpCurrOffEmail':			$r=$invoice->corporateOffice->email; break;
			case 'invClientCorpCurrOffBank':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBank']) {
					$r=\Entity\Bank::select($defaultBankAccount['idBank'])->name;
					if ($defaultBankAccount['idBankOffice']) $r.=' ('.\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->name.')';
				}
				break;
			case 'invClientCorpCurrOffBankName':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBank']) {
					$r=\Entity\Bank::select($defaultBankAccount['idBank'])->name;
				}
				break;
			case 'invClientCorpCurrOffBankCode':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBank']) {
					$r=\Entity\Bank::select($defaultBankAccount['idBank'])->code;
				}
				break;
			case 'invClientCorpCurrOffBankOffName':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->name;
				}
				break;
			case 'invClientCorpCurrOffBankOffAddress':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->address;
				}
				break;
			case 'invClientCorpCurrOffBankOffMfo':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->mfo;
				}
				break;
			case 'invClientCorpCurrOffBankOffSwiftCode':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				if ($defaultBankAccount['idBankOffice']) {
					$r=\Entity\BankOffice::select($defaultBankAccount['idBankOffice'])->swiftCode;
				}
				break;
			case 'invClientCorpCurrOffBankAccount':
				$defaultBankAccount=$invoice->corporateOffice->defaultBankAccountDetails;
				$r=$defaultBankAccount['account'];
				break;


			// CUSTOMER CLIENT FIELDS /////////////////////////////////////////////////////////////

			case 'invClientCustId':						$r=$invoice->idCustomer;break;
			case 'invClientCustName':					$r=$invoice->customer->nameStandard;break;
			case 'invClientCustLastName':				$r=$invoice->customer->lastNameStandard;break;
			case 'invClientCustMiddleName':				$r=$invoice->customer->middleNameStandard;break;
			case 'invClientCustFirstName':				$r=$invoice->customer->firstNameStandard;break;
			case 'invClientCustName2':					$r=$invoice->customer->nameLocal;break;
			case 'invClientCustLastName2':				$r=$invoice->customer->lastNameLocal;break;
			case 'invClientCustMiddleName2':			$r=$invoice->customer->middleNameLocal;break;
			case 'invClientCustFirstName2':				$r=$invoice->customer->firstNameLocal;break;
			case 'invClientCustName_alt':
				$r=$invoice->customer->nameStandard;
				if (!$r) $r=$invoice->customer->nameLocal;
				break;
			case 'invClientCustLastName_alt':
				$r=$invoice->customer->lastNameStandard;
				if (!$r) $r=$invoice->customer->lastNameLocal;
				break;
			case 'invClientCustMiddleName_alt':
				$r=$invoice->customer->middleNameStandard;
				if (!$r) $r=$invoice->customer->middleNameLocal;
				break;
			case 'invClientCustFirstName_alt':
				$r=$invoice->customer->firstNameStandard;
				if (!$r) $r=$invoice->customer->firstNameLocal;
				break;
			case 'invClientCustName2_alt':
				$r=$invoice->customer->nameLocal;
				if (!$r) $r=$invoice->customer->nameStandard;
				break;
			case 'invClientCustLastName2_alt':
				$r=$invoice->customer->lastNameLocal;
				if (!$r) $r=$invoice->customer->lastNameStandard;
				break;
			case 'invClientCustMiddleName2_alt':
				$r=$invoice->customer->middleNameLocal;
				if (!$r) $r=$invoice->customer->middleNameStandard;
				break;
			case 'invClientCustFirstName2_alt':
				$r=$invoice->customer->firstNameLocal;
				if (!$r) $r=$invoice->customer->firstNameStandard;
				break;

			case'invClientCustTitle': 					$r=$invoice->customer->titleName;break;
			case 'invClientCustType':					$r=$invoice->customer->typeName;break;
			case 'invClientCustCountry':				$r=$invoice->customer->country->name;break;
			case 'invClientCustCity':					$r=$invoice->customer->city->name;break;
			case 'invClientCustPNC':					$r=$invoice->customer->PNC;break;
			case 'invClientCustIdSeries':				$r=$invoice->customer->ID_series;break;
			case 'invClientCustIdNumber':				$r=$invoice->customer->ID_number;break;
			case 'invClientCustIdReleaseBy':			$r=$invoice->customer->ID_releaseBy;break;
			case 'invClientCustIdReleaseDateIso':		$r=$invoice->customer->ID_releaseDate;break;
			case 'invClientCustIdReleaseDateStandard':	$r=\Engine\DateTime::isoToStd($invoice->customer->ID_releaseDate);break;

			case 'invClientCustPassportNo':
				$defPassp=$invoice->customer->defaultPassport;
				$r=$defPassp['number'];
				break;
			case 'invClientCustPassportType':
				$defPassp=$invoice->customer->defaultPassport;
				$r=$defPassp['type'];
				break;
			case 'invClientCustPassportExpireDateIso':
				$defPassp=$invoice->customer->defaultPassport;
				$r=$defPassp['expireDate'];
				break;
			case 'invClientCustPassportExpireDateStandard':
				$defPassp=$invoice->customer->defaultPassport;
				$r=\Engine\DateTime::isoToStd($defPassp['expireDate']);
				break;

			case 'invClientCustAddress':				$r=$invoice->customer->address;break;
			case 'invClientCustDeliveryAddress':
				$r=$invoice->customer->deliveryAddress;
				if (!$r) $r=$invoice->customer->address;
				break;
			case 'invClientCustZipCode':				$r=$invoice->customer->zipCode;break;
			case 'invClientCustBank':
				$r=$invoice->customer->bank->name;
				if ($invoice->customer->idBankOffice) $r.=' ('.$invoice->customer->bankOffice->name.')';
				break;
			case 'invClientCustBankName':				$r=$invoice->customer->bank->name;break;
			case 'invClientCustBankCode':				$r=$invoice->customer->bank->code;break;
			case 'invClientCustBankOffName':			$r=$invoice->customer->bankOffice->name;break;
			case 'invClientCustBankOffMfo':				$r=$invoice->customer->bankOffice->mfo;break;
			case 'invClientCustBankOffAddress':			$r=$invoice->customer->bankOffice->address;break;
			case 'invClientCustBankOffSwiftCode':		$r=$invoice->customer->bankOffice->swiftCode;break;
			case 'invClientCustBankAccount':			$r=$invoice->customer->bankAccount;break;
			case 'invClientCustEmail':					$r=$invoice->customer->email;break;
			case 'invClientCustTelephone':				$r=$invoice->customer->telephone;break;
			case 'invClientCustTelephoneMobile':		$r=$invoice->customer->telephoneMobile;break;
			case 'invClientCustFax':					$r=$invoice->customer->fax;break;


			// INVOICE RESPONSIBLE USER ///////////////////////////////////////////////////////////
			case 'invRespUserId':						$r=$invoice->idUser; break;
			case 'invRespUserName':						$r=$invoice->user->name; break;
			case 'invRespUserLastName':					$r=$invoice->user->lastName; break;
			case 'invRespUserFirstName':				$r=$invoice->user->firstName; break;
			case 'invRespUserIdSeries':					$r=$invoice->user->ID_series; break;
			case 'invRespUserIdNumber':					$r=$invoice->user->ID_number; break;
			case 'invRespUserIdReleaseBy':				$r=$invoice->user->ID_releaseBy; break;
			case 'invRespUserIdReleaseDateIso':			$r=$invoice->user->ID_releaseDate; break;
			case 'invRespUserIdReleaseDateStandard':	$r=\Engine\DateTime::isoToStd($invoice->user->ID_releaseDate); break;
			case 'invRespUserPNC':						$r=$invoice->user->PNC; break;
			case 'invRespUserJob':						$r=$invoice->user->job; break;
			case 'invRespUserEmail':					$r=$invoice->user->email; break;
			case 'invRespUserEmailAlternative':			$r=$invoice->user->emailAlternative; break;
			case 'invRespUserTelephone':				$r=$invoice->user->telephone; break;
			case 'invRespUserFax':						$r=$invoice->user->fax; break;
			case 'invRespUserDeptName':					$r=$invoice->user->department->name; break;
			case 'invRespUserDeptCode':					$r=$invoice->user->department->code; break;


			// INVOICE RESPONSIBLE OFFICE /////////////////////////////////////////////////////////
			case 'invRespOffName':						$r=$invoice->office->name; break;
			case 'invRespOfficeIataCode':				$r=implode(",", $invoice->office->iataCode); break;
			case 'invRespOffAddress':					$r=$invoice->office->address; break;
			case 'invRespOffDeliveryAddress':			$r=$invoice->office->deliveryAddress; break;
			case 'invRespOffZipCode':					$r=$invoice->office->zipCode; break;
			case 'invRespOffCountry':					$r=$invoice->office->country->name; break;
			case 'invRespOffCity':						$r=$invoice->office->city->name; break;
			case 'invRespOffTelephone':					$r=$invoice->office->telephone; break;
			case 'invRespOffFax':						$r=$invoice->office->fax; break;
			case 'invRespOffEmail':						$r=$invoice->office->email; break;
			case 'invRespOffWeb':						$r=$invoice->office->web; break;


			// INVOICE ADD USER ///////////////////////////////////////////////////////////////////
			case 'invAddUserId':						$r=$invoice->idAddUser; break;
			case 'invAddUserName':						$r=$invoice->addUser->name; break;
			case 'invAddUserLastName':					$r=$invoice->addUser->lastName; break;
			case 'invAddUserFirstName':					$r=$invoice->addUser->firstName; break;
			case 'invAddUserIdSeries':					$r=$invoice->addUser->ID_series; break;
			case 'invAddUserIdNumber':					$r=$invoice->addUser->ID_number; break;
			case 'invAddUserIdReleaseBy':				$r=$invoice->addUser->ID_releaseBy; break;
			case 'invAddUserIdReleaseDateIso':			$r=$invoice->addUser->ID_releaseDate; break;
			case 'invAddUserIdReleaseDateStandard':		$r=\Engine\DateTime::isoToStd($invoice->addUser->ID_releaseDate); break;
			case 'invAddUserPNC':						$r=$invoice->addUser->PNC; break;
			case 'invAddUserJob':						$r=$invoice->addUser->job; break;
			case 'invAddUserEmail':						$r=$invoice->addUser->email; break;
			case 'invAddUserEmailAlternative':			$r=$invoice->addUser->emailAlternative; break;
			case 'invAddUserTelephone':					$r=$invoice->addUser->telephone; break;
			case 'invAddUserFax':						$r=$invoice->addUser->fax; break;
			case 'invAddUserDeptName':					$r=$invoice->addUser->department->name; break;
			case 'invAddUserDeptCode':					$r=$invoice->addUser->department->code; break;

			// INVOICE ISSUE USER/TIME ////////////////////////////////////////////////////////////
			case 'invIssueUserName':					$r=$invoice->issueUser->name; break;
			case 'invIssueUserLastName':				$r=$invoice->issueUser->lastName; break;
			case 'invIssueUserFirstName':				$r=$invoice->issueUser->firstName; break;
			case 'invIssueUserIdSeries':				$r=$invoice->issueUser->ID_series; break;
			case 'invIssueUserIdNumber':				$r=$invoice->issueUser->ID_number; break;
			case 'invIssueUserIdReleaseBy':				$r=$invoice->issueUser->ID_releaseBy; break;
			case 'invIssueUserIdReleaseDateIso':		$r=$invoice->issueUser->ID_releaseDate; break;
			case 'invIssueUserIdReleaseDateStandard':	$r=\Engine\DateTime::isoToStd($invoice->issueUser->ID_releaseDate); break;
			case 'invIssueUserPNC':						$r=$invoice->issueUser->PNC; break;
			case 'invIssueUserJob':						$r=$invoice->issueUser->job; break;
			case 'invIssueUserEmail':					$r=$invoice->issueUser->email; break;
			case 'invIssueUserEmailAlternative':		$r=$invoice->issueUser->emailAlternative; break;
			case 'invIssueUserTelephone':				$r=$invoice->issueUser->telephone; break;
			case 'invIssueUserFax':						$r=$invoice->issueUser->fax; break;
			case 'invIssueUserDeptName':				$r=$invoice->issueUser->department->name; break;
			case 'invIssueUserDeptCode':				$r=$invoice->issueUser->department->code; break;
			case 'invIssueTimestamp':					if ($invoice->issueTime) $r=date(DATETIME_FORMAT, $invoice->issueTime); break;


			// AGENCY MAIN BANK ACCOUNT ///////////////////////////////////////////////////////////
			case 'compBankMainAccAccount': case 'compBankMainAccBankName': case 'compBankMainAccBankCode': case 'compBankMainAccCurrency':
			case 'compBankMainAccSwiftCode': case 'compBankMainAccBankAddress':
				// determine either office bank account or the agency bank account (the office is the first choice)
				$idBa=$invoice->office->idDefaultBankAccount;
				if (!$idBa) $idBa = \Entity\AgencyBankAccount::getDefaultId();
				if ($idBa) $r = \Entity\AgencyBankAccount::select($idBa)->account;
				// fill in the fields if some bank account found
				if ($idBa) {
					if ($field=='compBankMainAccAccount') 			$r = \Entity\AgencyBankAccount::select($idBa)->account;
					elseif ($field=='compBankMainAccBankName') {
						$r = \Entity\AgencyBankAccount::select($idBa)->bank->name;
						if (\Entity\AgencyBankAccount::select($idBa)->idBankOffice) $r.=' ('.\Entity\AgencyBankAccount::select($idBa)->bankOffice->name.')';
					}
					elseif ($field=='compBankMainAccBankCode') 		$r = \Entity\AgencyBankAccount::select($idBa)->bank->code;
					elseif ($field=='compBankMainAccCurrency') 		$r = \Entity\AgencyBankAccount::select($idBa)->currency;
					elseif ($field=='compBankMainAccSwiftCode') 	$r = \Entity\AgencyBankAccount::select($idBa)->bankOffice->swiftCode;
					elseif ($field=='compBankMainAccBankAddress') 	$r = \Entity\AgencyBankAccount::select($idBa)->bankOffice->address;
				}
				break;


			// INVOICE SELECTED BANK ACCOUNT //////////////////////////////////////////////////////
			case 'compBankSelAccAccount':				$r=$invoice->bankAccount->account; break;
			case 'compBankSelAccBankName':
				$r=$invoice->bankAccount->bank->name;
				if ($invoice->bankAccount->idBankOffice) $r.=' ('.$invoice->bankAccount->bankOffice->name.')';
				break;
			case 'compBankSelAccBankCode':				$r=$invoice->bankAccount->bank->code; break;
			case 'compBankSelAccCurrency':				$r=$invoice->bankAccount->currency; break;
			case 'compBankSelAccSwiftCode':				$r=$invoice->bankAccount->bankOffice->swiftCode; break;
			case 'compBankSelAccBankAddress':			$r=$invoice->bankAccount->bankOffice->address; break;

			// service passengers passport number
			case 'passengersPassportNumber' :
				// get full list of passengers ids
				$idCustomersList = [];
				foreach($invoice->rowsList as $row) {
					$psgList = \Entity\Service::select($row['idReservationService'])->idCustomersList;
					$idCustomersList = array_merge($idCustomersList, $psgList);
				}
				$idCustomersList = array_unique($idCustomersList);

				// determine the list of passengers passport number
				$passengersPassportNumber = [];
				foreach($idCustomersList as $id) {
					$customerEntity = \Entity\Customer::select($id);
					$customerPassportsList = $customerEntity->passports;

					// get first passport details
					$customerFirstPassport = (array)reset($customerPassportsList);
					$passengersPassportNumber[] = $customerEntity->name.' '.(String)$customerFirstPassport['number'];
				}

				$r=implode(', ', $passengersPassportNumber);

				break;


			case 'invServicePriceTotalBase': case 'invServicePriceTotalVat':
			case 'invDiscountTotalBase': case 'invDiscountTotalVat':
			case 'invServiceFeeTotalBase': case 'invServiceFeeTotalVat':
			case 'invTaxTotalBase': case 'invTaxTotalVat':
			case 'invPenaltiesTotal':

				$totals = [];
				foreach ($invoice->rowsList as $row) {
					if ($row['rowType'] == 'price' or $row['rowType'] == 'commission') {
						$totals['invServicePriceTotalBase'] += $row['pricePrintValue'];
						$totals['invServicePriceTotalVat'] += $row['vatPrintValue'];
					}
					elseif ($row['rowType'] == 'discount') {
						$totals['invDiscountTotalBase'] += $row['pricePrintValue'];
						$totals['invDiscountTotalVat'] += $row['vatPrintValue'];
					}
					elseif ($row['rowType'] == 'serviceFee') {
						$totals['invServiceFeeTotalBase'] += $row['pricePrintValue'];
						$totals['invServiceFeeTotalVat'] += $row['vatPrintValue'];
					}
					elseif ($row['rowType'] == 'tax') {
						$totals['invTaxTotalBase'] += $row['pricePrintValue'];
						$totals['invTaxTotalVat'] += $row['vatPrintValue'];
					}
					elseif ($row['rowType'] == 'penalty') {
						$totals['invPenaltiesTotal'] += $row['pricePrintValue'] + $row['vatPrintValue'];
					}
				}

				$r = $totals[$field];
				break;

			case 'invServicesFormOfPayment':
				$servicesFOP = [];
				$invoiceServices = [];
				foreach ($invoice->rowsList as $row) {
					if (!array_key_exists($row['idReservationService'], $invoiceServices)) {
						$offerEntity = \Entity\Service::select($row['idReservationService'])->chosenOffer;
						$invoiceServices[$row['idReservationService']] = true;
						if ($offerEntity->paymentIdCreditCard) {
							$storage = new \App\Utils\CreditCard\Storage();
							$truncatedNumber = $storage->getCard($offerEntity->paymentIdCreditCard)['truncatedNumber'];

							if (!array_key_exists($truncatedNumber, $servicesFOP)) {
								$servicesFOP[$truncatedNumber] = [];
							}

							if ($offerEntity->paymentCcValue && $offerEntity->paymentCcCurrency) {
								$servicesFOP[$truncatedNumber][$offerEntity->paymentCcCurrency] += $offerEntity->paymentCcValue;
							}
						}
					}
				}

				$finalOutput = [];
				foreach ($servicesFOP as $truncatedNumber => $cardDetails) {
					$outputPrices = implode(" + ", array_map(
							function ($v, $k) {
								return \App\Utils\PriceFormat::format($v, $k);

							}, $cardDetails, array_keys($cardDetails)));

					$finalOutput[] = sprintf("%s %s", $truncatedNumber, $outputPrices);
				}

				$r = implode(",", $finalOutput);
			break;

			case 'invServicesFormOfCashing':
				$servicesFOC = [];
				foreach ($invoice->rowsList as $row) {
					if (!array_key_exists($row['idReservationService'], $servicesFOC)) {
						$offerEntity = \Entity\Service::select($row['idReservationService'])->chosenOffer;
						$servicesFOC[$row['idReservationService']] = '';
						if ($offerEntity->cashingIdCreditCard) {
							$storage = new \App\Utils\CreditCard\Storage();
							$truncatedNumber = $storage->getCard($offerEntity->cashingIdCreditCard)['truncatedNumber'];
							if (!in_array($truncatedNumber, $servicesFOC)) {
								$servicesFOC[$row['idReservationService']] = $truncatedNumber;
							}
						}
					}
				}

				$r = implode(",", array_filter($servicesFOC));
			break;

			case 'suppliersDetails':
				$suppliersDetails = [];

				foreach ($invoice->rowsList as $row) {
					$suppEnt = \Entity\Service::select($row['idReservationService'])->chosenOffer->supplier;
					$suppDet = array_filter([$suppEnt->company, $suppEnt->fiscalCode, $suppEnt->address, $suppEnt->city->name, $suppEnt->processedRemarks['INSURANCE_POLICY']]);
					$suppliersDetails[$suppEnt->getId()] = implode(", ", $suppDet);
				}

				$r = implode("\n", array_values($suppliersDetails));
			break;

			// field is not found here
			default: {
				$fieldFound=false;
			}

		}

		// if the field is found but is null - transform it to blank
		if ($fieldFound and $r===null) {
			$r='';
		}

		return $r;

	}

}
