<?php

namespace Entity;

abstract class Offer_MagicMethodsAbstract extends \App\Entity\GeneralMtAbstract
{

	/**
	 * (non-PHPdoc)
	 * @see \App\Entity\SelectAbstract::getAttribute()
	 */
	protected function getAttribute($var)
	{

		// CHECKS EACH FIELD THAT CAN BE EXTRACTED ////////////////////////////////////////////////
		switch ($var) {

			case 'deleted': case 'idSupplierProduct': case 'idSupplier': case 'productName':
			case 'serviceCode': case 'calculationType': case 'commissionable': case 'discountPercentSource':
			case 'serviceFeeMode': case 'serviceFeePercentSource': case 'currencyDate':
			case 'offerCurrency': case 'serviceFeeCurrency': case 'totalCurrency': case 'comments':
			case 'supplierVatIncluded': case 'commissionVatIncluded': case 'discountVatIncluded': case 'serviceFeeVatIncluded': case 'taxVatIncluded':
			case 'ignoreSupplierOnDocuments': case 'expirationDate': case 'confirmationNumber':
			case 'externalSystemReservationId': case 'externalSystemReservationDate': case 'cancellationPolicy': case 'optionDate':
			case 'duration': case 'idAddUser': case 'addTime': case 'idUpdateUser': case 'lastUpdateTime': case 'updatesCount':
			case 'departureCountryCode':  case 'departureCityId': case 'departureStationCode':
			case 'destinationCountryCode':  case 'destinationCityId': case 'destinationStationCode': case 'formOfPayment': case 'formOfCashing':
			case 'paymentCcEntityType': case 'paymentCcEntityId': case 'paymentCcApprovalCode': case 'paymentCcValue': case 'paymentCcCurrency':
			case 'cashingCcEntityType': case 'cashingCcEntityId': case 'cashingCcApprovalCode': {
				return $this->fields[$var];
			}

			case 'supplierWorkValue': case 'supplierWorkVat': case 'commissionWorkValue': case 'commissionWorkVat':
			case 'discountWorkValue': case 'discountWorkVat': case 'serviceFeeWorkValue': case 'serviceFeeWorkVat':
			case 'taxWorkValue': case 'taxWorkVat': case 'offerWorkTotal': case 'netCompanyWorkTotal': {
				return (float)$this->fields[$var]; // transforms "0.000" => 0 (eliminates trailing 0s for decimals)
			}

			case 'profitWorkTotal': {
			    if ($this->fields['ignoreSupplierOnDocuments']) {
			    	return $this->fields['serviceFeeWorkValue'] + $this->fields['serviceFeeWorkVat'] - $this->fields['discountWorkValue'] - $this->fields['discountWorkVat'];
			    }
			    else {
			    	return $this->fields['offerWorkTotal'] - $this->fields['netCompanyWorkTotal'];
			    }
			}

			// use 'idService' instead of 'idReservationService'
			case 'idService': {
				return $this->fields['idReservationService'];
			}

			// the order service
			case 'service': {
				return Service::select($this->getAttribute('idService'), $this->selectForUpdate);
			}

			// supplier product entity object
			case 'supplierProduct': {
				return SupplierProduct::select($this->fields['idSupplierProduct'], $this->selectForUpdate);
			}

			// relevant product name
			// gets the product name from the offer (if exists), else from the service
			// the priority is: offer->idSupplierProduct->productName > offer->productName >
			// > service->idSupplierProduct->productName > service->productName
			// the simple ->productName(s) can be inputed by hand, whilst the idSupplierProduct->productName(s) can be from autocomplete
			case 'relevantProductName': {

				if (!array_key_exists('relevantProductName', $this->fields)) {

					// check from offer autocomplete first
					$offerSupplierProduct = $this->getAttribute('supplierProduct');
					if ($offerSupplierProduct->productName) {
						$this->fields['relevantProductName'] = $offerSupplierProduct->productName;
					}
					elseif ($this->fields['productName']) {
						// check offer manual input second
						$this->fields['relevantProductName'] = $this->fields['productName'];
					}
					else {
						$service = $this->getAttribute('service');
						$serviceSupplierProduct = $service->supplierProduct;

						// check service autocomplete third
						if ($serviceSupplierProduct->productName) {
							$this->fields['relevantProductName'] = $serviceSupplierProduct->productName;
						}
						else {
							// if all 3 fail, get the manual inputted productName from service level
							$this->fields['relevantProductName'] = $service->productName;
						}
					}

				}
				return $this->fields['relevantProductName'];

			}


			// supplier
			case 'supplier': {
				return Supplier::select($this->fields['idSupplier'], $this->selectForUpdate);
			}

			// offer type
			case 'offerTypeCode': {
				$this->fields['offerTypeCode']=$this->fields['offerType'];
				return $this->fields['offerTypeCode'];
			}

			// offer type
			case 'offerTypeName': {
				if (!isset($this->fields['offerTypeName'])) {
					$offTypes=\App\Config\Services_OfferTypes::getInstance()->get($this->fields['serviceCode']);
					$this->fields['offerTypeName']=$offTypes[$this->fields['offerType']];
				}
				return $this->fields['offerTypeName'];
			}

			// service name
			case 'serviceName': {
				if (!isset($this->fields['serviceName'])) {
					$this->fields['serviceName']=\App\Config\Services_Basic::getInstance()->getServiceName($this->fields['serviceCode']);
				}
				return $this->fields['serviceName'];
			}

			// service config group
			case 'serviceConfigGroupName': case 'serviceConfigGroupCode': {
				if (!array_key_exists($var, $this->fields) and $this->fields['serviceCode']) {

					$serviceObj = \App\Config\Services_Basic::getInstance();
					$serviceGroupCode = $serviceObj->getServiceGroupCode($this->fields['serviceCode']);

					$this->fields['serviceConfigGroupCode'] = $serviceGroupCode;
					$this->fields['serviceConfigGroupName'] = $serviceObj->getGroupName($serviceGroupCode);
				}
				return $this->fields[$var];
			}

			// service config category
			case 'serviceConfigCategoryName': case 'serviceConfigCategoryCode': {
				if (!array_key_exists($var, $this->fields) and $this->fields['serviceCode']) {
					$_LANG = \App\Loader_Lang::getInstance()->getAll();

					$serviceCategory = \App\Config\Services_Basic::getInstance()->getServiceCategory($this->fields['serviceCode']);

					$this->fields['serviceConfigCategoryCode'] = $serviceCategory;
					$this->fields['serviceConfigCategoryName'] = $_LANG['servicesCategories'][$serviceCategory];
				}
				return $this->fields[$var];
			}


			// location code
			case 'locationCode': {
				if (!isset($this->fields['locationCode'])) {
					$this->fields['locationCode']=$this->fields['location'];
				}
				return $this->fields['locationCode'];
			}

			// location name
			case 'locationNameShort': case 'locationNameLong': {
				if (!array_key_exists('locationNameShort', $this->fields)) {
					global $_LANG;
					$this->fields['locationNameShort']=$_LANG['locations']['countriesCriteria']['short'][$this->fields['location']];
					$this->fields['locationNameLong']=$_LANG['locations']['countriesCriteria']['long'][$this->fields['location']];
				}
				return $this->fields[$var];
			}

			// offer calculation type name
			case 'calculationTypeName': {
				if (!array_key_exists('calculationTypeName', $this->fields)) {
					$this->fields['calculationTypeName'] = \App\Config\Services_Calculations::getInstance()->getServiceLocationCalculationName($this->fields['serviceCode'], $this->fields['location'], $this->fields['calculationType']);
				}
				return $this->fields['calculationTypeName'];
			}

			// end date time
			case 'startDatetime': case 'endDatetime': {
				if (!($this->fields[$var] instanceof \Engine\DateTime)) {
					$this->fields[$var]=\Engine\DateTime::createFromIsoDatetime($this->fields[$var]);
				}
				return $this->fields[$var];
			}


			// start date (ISO format)
			case 'startDate': {
				if (!array_key_exists($var, $this->fields)) {
					$this->fields[$var]=$this->__get('startDatetime')->formatDateIso();
				}
				return $this->fields[$var];
			}

			// end date (ISO format)
			case 'endDate': {
				if (!array_key_exists($var, $this->fields)) {
					$this->fields[$var] = $this->__get('endDatetime')->formatDateIso() ? : null;
				}
				return $this->fields[$var];
			}

			// duration type (days/nights)
			case 'durationType': {
				if (!$this->fields['durationType']) {
					$this->fields['durationType'] = \App\Config\Services_Fields::getInstance()->getServiceFieldType($this->fields['serviceCode'], 'durationType');
				}
				return $this->fields['durationType'];

			}

			// currency type code / name
			case 'currencyTypeCode': {
				if (!isset($this->fields['currencyTypeCode'])) {
					$this->fields['currencyTypeCode']=$this->fields['currencyType'];
				}
				return $this->fields['currencyTypeCode'];
			}
			case 'currencyTypeName': {
				return \App\Config\CurrencyTypes::getInstance()->getName( $this->fields['currencyType'] );
			}

			// array of offer items (id=>associative array)
			case 'offerItems': { // TODO: use entity list for this
				if (!is_array($this->fields[$var])) {
					global $DBTReservationServiceOfferItems;
					$db=\DB::getInstance();
					$offerItemsSQL="SELECT * FROM `$DBTReservationServiceOfferItems{$this->tableMonth}` WHERE idOffer='{$this->id}' ORDER BY id ASC";
					if ($this->selectForUpdate) $offerItemsSQL.=' FOR UPDATE';
					$offerItems=$db->GetAll($offerItemsSQL);
					if ($db->ErrorNo()) {
						throw new \DBException('Offer items could not be extracted due to a technical problem.');
					}
					$this->fields[$var]= [];
					foreach($offerItems as $oi) {
						$this->fields[$var][$oi['id']]=$oi;
					}
				}
				return $this->fields[$var];
			}

			// itinerary details
			case 'itinerary': {
				if (!is_object($this->fields[$var])) {
					$itinObj=new \App\Itinerary();
					if ($this->fields[$var]) {
						$itinObj->importFromArray(unserialize($this->fields[$var]));
					}
					$this->fields[$var]=$itinObj;
				}
				return $this->fields[$var];
			}

			case 'itineraryReadable': {
				if (!array_key_exists($var, $this->fields)) {
					$itin=$this->__get('itinerary');
					$this->fields[$var]=$itin->getFromFormat();
				}
				return $this->fields[$var];
			}

			// itinerary passed places
			case 'itineraryPassedAirportCodesReadable': {
				if (!array_key_exists($var, $this->fields)) {
					$this->fields[$var]=implode(' // ', $this->__get('itinerary')->getPassedPlaces('stationCodeStandard'));
				}
				return $this->fields[$var];
			}

			// itinerary readable which contains only the city
			case 'itineraryReadableCityStd': {
				if (!array_key_exists($var, $this->fields)) {
					$format= [
							'departure'=> ['place'=>'cityNameStandard', 'dateAndTime'=>''],
							'arrival'=> ['place'=>'cityNameStandard', 'dateAndTime'=>'',],
							'segmentSeparator'=>' ; ', 'segmentGlue'=>' - ',
					];
					$this->fields[$var]=$this->__get('itinerary')->getFromFormat($format);
				}
				return $this->fields[$var];
			}

			case 'departureCountry': {
				return \Entity\Country::select($this->fields['departureCountryCode'], $this->selectForUpdate);
			}
			case 'departureCity': {
				return \Entity\City::select($this->fields['departureCityId'], $this->selectForUpdate);
			}
			case 'departureStation': {
				return \Entity\Station::select($this->getAttribute('departureStationCode'), $this->selectForUpdate);
			}
			case 'destinationCountry': {
				return \Entity\Country::select($this->fields['destinationCountryCode'], $this->selectForUpdate);
			}
			case 'destinationCity': {
				return \Entity\City::select($this->fields['destinationCityId'], $this->selectForUpdate);
			}
			case 'destinationStation': {
				return \Entity\Station::select($this->getAttribute('destinationStationCode'), $this->selectForUpdate);
			}

			// the imported services id that references to this offer
			case 'importedServiceDetails': {
				if (!is_array($this->fields[$var])) {
					if ($this->recordExists) {
						$impServListObj = new \App\EntityList\ImportedServices();
						$impServListObj->setColumns(['importedService.id', 'importedService.idSystem', 'importedService.idServiceExtSys', 'importedService.idImportedOrder', 'importedService.auxReference', 'importedService.systemStatus']);
						$impServListObj->setFilter('idOfferTina', '=', $this->id);
						$impServListObj->setLimit(1);
						$impServListObj->setForUpdate($this->selectForUpdate);
						$impServList = $impServListObj->exportRecords();
						$this->fields[$var] = $impServList[0];
					} else {
						$this->fields[$var] = [];
					}
				}
				return $this->fields[$var];
			}
			case 'idImportedService': {
				if (!is_array($this->fields[$var])) {
					$impServDet = $this->getAttribute('importedServiceDetails');
					$this->fields[$var] = (Int)$impServDet['id'];
				}
				return $this->fields[$var];
			}
			case 'importedService': {
				return \Entity\ImportedService::select($this->getAttribute('idImportedService'), $this->selectForUpdate);
			}

			// extra info, offerHistory
			case 'extraInfo': case 'offerHistory': {
				if (!is_array($this->fields[$var])) {
					if ($this->fields[$var]) {
						$this->fields[$var]=unserialize($this->fields[$var]);
					} else {
						$this->fields[$var]=[];
					}
				}
				return $this->fields[$var];
			}

			// field(s) that are stored in extra info
			case 'appliedOfferProfileRules': {
				if (!array_key_exists($var, $this->fields)) {
					$ei = $this->getAttribute('extraInfo');
					$this->fields[$var] = $ei[$var];
				}
				return $this->fields[$var];
			}

			// offer configs
			case 'offerVatConfigs': {
				if (!is_array($this->fields['offerVatConfigs'])) {
					$this->fields['offerVatConfigs']=\App\Config\Services_Calculations_OfferVat::getInstance()->getCalculationDetails($this->fields['serviceCode'], $this->fields['location'], $this->fields['calculationType']);
				}
				return $this->fields['offerVatConfigs'];
			}

			// offer quantityType
			case 'quantityType': {
				if (!is_array($this->fields[$var])) {
					$offerDet=\App\Config\Services_OfferDetails::getInstance()->get($this->getAttribute('serviceCode'));
					$this->fields[$var]=$offerDet['quantityType'];
				}
				return $this->fields[$var];
			}

			// offer total in default/work currency
			case 'offerTotalDefCurr': {
				if (!isset($this->fields[$var])) {
					$this->fields[$var]=\App\CurrencyExchange\Rates::getInstance($this->fields['currencyDate'], $this->fields['currencyType'])->convert($this->fields['offerWorkTotal'], $this->fields['totalCurrency'], \App\Config\Currencies::getInstance()->getDefaultCurrency());
				}
				return $this->fields[$var];
			}
			case 'offerTotalWorkCurr': {
				if (!isset($this->fields[$var])) {
					$this->fields[$var]=\App\CurrencyExchange\Rates::getInstance($this->fields['currencyDate'], $this->fields['currencyType'])->convert($this->fields['offerWorkTotal'], $this->fields['totalCurrency'], \App\Config\Currencies::getInstance()->getWorkCurrency());
				}
				return $this->fields[$var];

			}

			// indicates if the main fields of the offer are blocked, and only text ones are still editable
			// eg: you cannot change the main fields of the chosen offer on an invoiced/balanced service
			case 'mainFieldsBlocked': {
				$serviceEnt = $this->getAttribute('service');
				// if the service is blocked
				if ($serviceEnt->statusOp=='XX') {
					return true;
				}
				// if this is the chosen offer of an invoiced service
				if ($serviceEnt->chosenOfferId==$this->id and $serviceEnt->statusFin=='TI') {
					return true;
				}
				// check that if we update the chosen offer - service must not be balanced
				if ($serviceEnt->chosenOfferId==$this->id and ($serviceEnt->idBalance or $serviceEnt->idBalanceRefund) ) {
					return true;
				}
				// check that the parent package service status fin is not "TI" (and we save the chosen offer)
				if ($serviceEnt->chosenOfferId==$this->id and $serviceEnt->idPackageService and $serviceEnt->packageService->statusFin=='TI') {
					return true;
				}
				return false;
			}

			case 'noPenaltyOptionDate': {
				if ($this->fields['optionDate']) {
					$noPenaltyOptionDate = \Engine\DateTime::create($this->fields['optionDate'])->modify("-1day");
					$this->fields[$var] = $noPenaltyOptionDate->formatDateIso();
				}
				else {
					$this->fields[$var] = null;
				}

				return $this->fields[$var];
			}


			// FORM OF PAYMENT / CASHING ----------------------------------------------------------
			case 'paymentAgencyCreditCard': {
				if ($this->fields['paymentCcEntityType']=='agency') {
					return AgencyCreditCard::select($this->fields['paymentCcEntityId'], $this->selectForUpdate);
				} else {
					return AgencyCreditCard::select(0, $this->selectForUpdate);
				}
			}
			case 'paymentCorporateCreditCard': {
				if ($this->fields['paymentCcEntityType']=='corporate') {
					return CorporateCreditCard::select($this->fields['paymentCcEntityId'], $this->selectForUpdate);
				} else {
					return CorporateCreditCard::select(0, $this->selectForUpdate);
				}
			}
			case 'paymentCustomerCreditCard': {
				if ($this->fields['paymentCcEntityType']=='customer') {
					return CustomerCreditCard::select($this->fields['paymentCcEntityId'], $this->selectForUpdate);
				} else {
					return CustomerCreditCard::select(0, $this->selectForUpdate);
				}
			}

			case 'paymentIdCreditCard': {
				$idCc = 0;
				switch ($this->fields['paymentCcEntityType']) {
					case 'agency':
						$idCc = $this->getAttribute('paymentAgencyCreditCard')->idCreditCard;
					break;
					case 'corporate':
						$idCc = $this->getAttribute('paymentCorporateCreditCard')->idCreditCard;
					break;
					case 'customer':
						$idCc = $this->getAttribute('paymentCustomerCreditCard')->idCreditCard;
					break;
					case 'manual':
						$idCc = $this->fields['paymentCcEntityId'];
					break;
					default:
						$idCc = null;
				}
				return $idCc;
			}

			case 'cashingCorporateCreditCard': {
				if ($this->fields['cashingCcEntityType']=='corporate') {
					return CorporateCreditCard::select($this->fields['cashingCcEntityId'], $this->selectForUpdate);
				} else {
					return CorporateCreditCard::select(0, $this->selectForUpdate);
				}
			}
			case 'cashingCustomerCreditCard': {
				if ($this->fields['cashingCcEntityType']=='customer') {
					return CustomerCreditCard::select($this->fields['cashingCcEntityId'], $this->selectForUpdate);
				} else {
					return CustomerCreditCard::select(0, $this->selectForUpdate);
				}
			}

			case 'cashingIdCreditCard': {
				$idCc = 0;
				switch ($this->fields['cashingCcEntityType']) {
					case 'corporate':
						$idCc = $this->getAttribute('cashingCorporateCreditCard')->idCreditCard;
					break;
					case 'customer':
						$idCc = $this->getAttribute('cashingCustomerCreditCard')->idCreditCard;
					break;
					case 'manual':
						$idCc = $this->fields['cashingCcEntityId'];
					break;
					default:
						$idCc = null;
				}
				return $idCc;
			}

			// add user
			case 'addUser': {
				return User::select($this->fields['idAddUser'], $this->selectForUpdate);
			}

			// update user
			case 'updateUser': {
				return User::select($this->fields['idUpdateUser'], $this->selectForUpdate);
			}

			// $var IS NOT VALID - throws Exception -----------------------------------------------
			default: {
				return parent::getAttribute($var);
			}

		}

	}

	/**
	 * (non-PHPdoc)
	 * @see \App\Entity\GeneralAbstract::setAttribute()
	 */
	protected function setAttribute($var, $value)
	{

		// check operation
		if ($this->operation!='insert' and $this->operation!='update') {
			throw new \Exception('You can call '.__METHOD__.' only for insert/update operations.');
		}

		// ATTACH THE AVAILABLE FIELDS TO THE OBJECT //////////////////////////////////////////////
		switch ($var) {

			// simple fields
			case 'idSupplier': case 'productName': case 'currencyType': case 'currencyDate': case 'comments':
			case 'externalSystemReservationId': case 'externalSystemReservationDate': case 'confirmationNumber': case 'cancellationPolicy':
			case 'offerCurrency': case 'serviceFeeCurrency': case 'totalCurrency': case 'expirationDate': case 'optionDate':
			case 'idSupplierProduct': case 'itinerary':
			case 'departureCountryCode': case 'departureCityId': case 'departureStationCode':
			case 'destinationCountryCode': case 'destinationCityId': case 'destinationStationCode':
			case 'calculationType':
			case 'discountPercentSource': case 'serviceFeeMode': case 'serviceFeePercentSource':
			case 'offerItems': case 'formOfPayment': case 'formOfCashing':
			case 'paymentCcEntityType': case 'paymentCcEntityId': case 'paymentCcApprovalCode': case 'paymentCcValue': case 'paymentCcCurrency':
			case 'cashingCcEntityType': case 'cashingCcEntityId': case 'cashingCcApprovalCode': {
				$this->fields[$var]=$value;
				break;
			}

			// boolean fields
			case 'commissionable': case 'ignoreSupplierOnDocuments': case 'supplierVatIncluded': case 'commissionVatIncluded':
			case 'discountVatIncluded': case 'serviceFeeVatIncluded': case 'taxVatIncluded':{
				$this->fields[$var] = (bool)$value;
				break;
			}

			// the reference to the reservation service
			case 'idService': case 'serviceCode': case 'location': {
				if ($this->operation!='insert') throw new \Exception('You can set the order service id of an offer, the service code or the location only for `insert` operation.');
				$this->fields[$var] = $value;
				break;
			}

			case 'redistributeCommissionPercent': {
				if ($this->operation!='update') throw new \Exception('You can set the `redistributeCommissionPercent` for an offer only for `update` operation.');
				$this->fields[$var] = $value;
				break;
			}

			// offer type
			case 'offerType': {
				if ($this->operation!='insert') throw new \Exception('You can set the type of an offer only for `insert` operation.');
				$this->fields[$var]=$value;
				break;
			}

			// start/end date+time
			case 'startDatetime': case 'endDatetime': {
				if ( !($value instanceof \Engine\DateTime) ) {
					throw new \Exception('You can set the `startDatetime` or `endDatetime` only as an instance of `\Engine\DateTime` class.');
				}
				$this->fields[$var]=$value;
				break;
			}

			// field(s) that are eventually stored in extraInfo
			case 'appliedOfferProfileRules': {
				if ($this->operation!='insert') throw new \Exception('You can set the `appliedOfferProfileRules` field only on `insert` operation.');
				if (!is_array($value)) throw new \Exception('You must set the `appliedOfferProfileRules` field as an array.');
				$this->fields[$var] = $value;
				break;
			}

			// associate an imported service id
			case 'idImportedService': {
				if ($this->operation!='insert') throw new \Exception('You can set the `idImportedService` field only for `insert` operation.');
				$this->fields[$var]=$value;
				break;
			}

			// extra info - updates only the new set keys
			case 'extraInfo': {
				if (!is_array($value)) throw new \Exception("The field `extraInfo` can only be set as an array for the `".__CLASS__."` entity.");
				$this->fields[$var]=$value;
				break;
			}


			// offer history
			case 'offerHistory': {
				if (!is_array($value)) throw new \Exception("The field `offerHistory` can only be set as an array for the `".__CLASS__."` entity.");
				$this->fields[$var]=$value;
				break;
			}

			// $var IS NOT VALID - throws Exception -------------------------------------------
			default: {
				throw new \Exception("Wrong var ({$var}) for the '".__CLASS__."' class.");
			}

		}

	}



	/**
	 * Determines the final service code for this offer (if manually set in $this->fields it uses this; otherwise (and only for update operation) it uses the old value.
	 * @throws \Exception - if operation is other than insert/update
	 * @return String - the service code
	 */
	public function getFinalServiceCode()
	{
		// for insert operations
		if ($this->operation=='insert') {
			return $this->fields['serviceCode'];
		}
		// for update operations
		elseif ($this->operation=='update') {
			return Offer::selectForUpdate($this->id)->serviceCode;
		}
		// otherwise - stop it
		else {
			throw new \Exception('You can get the final service code only for insert/update operations.');
		}
	}

	/**
	 * Determines the final service location for this offer (if manually set in $this->fields it uses this; otherwise (and only for update operation) it uses the old value.
	 * @throws \Exception - if operation is other than insert/update
	 * @return String - the service code
	 */
	public function getFinalServiceLocation()
	{
		// chec operation
		if ($this->operation!='insert' and $this->operation!='update') {
			throw new \Exception('You can get the final service location only for insert/update operations.');
		}
		// if something set
		if ($this->operation=='insert' or array_key_exists('location', $this->fields)) {
			return $this->fields['location'];
		} else {
			return self::selectForUpdate($this->id)->locationCode;
		}
	}

	/**
	 * Determines the final service calculation for this offer (if manually set in $this->fields it uses this; otherwise (and only for update operation) it uses the old value.
	 * @throws \Exception - if operation is other than insert/update
	 * @return String - the service code
	 */
	public function getFinalServiceCalculation()
	{
		// chec operation
		if ($this->operation!='insert' and $this->operation!='update') {
			throw new \Exception('You can get the final service calculation only for insert/update operations.');
		}
		// if something set
		if ($this->operation=='insert' or array_key_exists('calculationType', $this->fields)) {
			return $this->fields['calculationType'];
		} else {
			return self::selectForUpdate($this->id)->calculationType;
		}
	}



}
