<?php

namespace common\models;

use Yii;
use yii\base\Object;
use yii\helpers\ArrayHelper;
use yii\behaviors\TimestampBehavior;
use common\components\AccountAwareBehavior;
use common\components\UserAwareBehavior;
use common\components\DiscountAwareBehavior;
use common\components\CustomerAwareBehavior;
use yii\db\Query;
use yii\db\Expression;
use common\components\RoleDefinition;
use common\components\Helper;

/**
 * This is the model class for table "transfer".
 *
 * @property integer $id_transfer
 * @property integer $id_discount
 * @property integer $id_currency
 * @property integer $id_account
 * @property integer $id_object
 * @property integer $status
 * @property integer $type
 * @property integer $item_price
 * @property integer $count
 * @property integer $money
 * @property integer $money_currency
 * @property integer $rate
 * @property integer $id_user
 * @property string $comment
 * @property string $created_at
 * @property string $updated_at
 * @property integer $direction
 * @property string $paid_at
 * @property integer $id_customer
 */
class Transfer extends \common\models\BaseFitnessActiveRecord {
	const TYPE_PRODUCT = 10;
	const TYPE_TICKET = 20;
	const TYPE_MONEY_MOVEMENT_OUT = 30; // MONEY OUT FROM ACCOUNT
	const STATUS_NOT_PAID = 10;
	const STATUS_PAID = 20;
	const STATUS_STORNO = 30;
	const DIRECTION_OUT = 10; // MONEY GOES OUT FROM ACCOUNT ( COMPANY LOST MONEY )
	const DIRECTION_IN = 20; // MONEY GOES IN TO THE ACCOUNT ( COMPANY EARN MONEY )
	const PAYMENT_METHOD_CASH = 10;
	const PAYMENT_METHOD_BANCCARD = 20; // BANKKÁRTYA
	const PAYMENT_METHOD_TRANSFER = 30; // ÁTUTALÁS
	const PAYMENT_METHOD_CAFETERY = 40; // SZÉCHENYI KÁRTYA
	                                    // const PAYMENT_METHOD_DEBIT_MANDATE = 50;//CSOPORTOS BESZEDÉSI MEGBÍZÁS
	const PAYMENT_METHOD_TRANSFER_LATER = 50;
	/**
	 * @inheritdoc
	 */
	public function behaviors() {
		return ArrayHelper::merge ( [ 
				[ 
						'class' => TimestampBehavior::className (),
						'value' => function () {
							return date ( 'Y-m-d H:i:s', \Yii::$app->formatter->asTimestamp ( date ( 'Y-d-m h:i:s' ) ) );
						} 
				],
				[ 
						'class' => DiscountAwareBehavior::className () 
				],
				[ 
						'class' => CustomerAwareBehavior::className () 
				] 
		], parent::behaviors () );
	}
	
	/**
	 * @inheritdoc
	 */
	public static function tableName() {
		return 'transfer';
	}
	
	/**
	 * @inheritdoc
	 */
	public function rules() {
		return [ 
				[ 
						[ 
								'id_discount',
								'id_currency',
								'id_object',
								'status',
								'type',
								'item_price',
								'count',
								'money',
								'money_currency',
								'rate',
								'id_user' 
						],
						'integer' 
				],
				[ 
						[ 
								'created_at',
								'updated_at' 
						],
						'safe' 
				],
				[ 
						[ 
								'comment' 
						],
						'string',
						'max' => 255 
				] 
		];
	}
	
	/**
	 * @inheritdoc
	 */
	public function attributeLabels() {
		return [ 
				'id_transfer' => Yii::t ( 'common/transfer', 'Id Transfer' ),
				'id_account' => Yii::t ( 'common/transfer', 'Account' ),
				'id_discount' => Yii::t ( 'common/transfer', 'Id Discount' ),
				'id_currency' => Yii::t ( 'common/transfer', 'Id Currency' ),
				'id_object' => Yii::t ( 'common/transfer', 'Id Object' ),
				'objectName' => Yii::t ( 'common/transfer', 'Id Object' ),
				'status' => Yii::t ( 'common/transfer', 'Status' ),
				'type' => Yii::t ( 'common/transfer', 'Type' ),
				'item_price' => Yii::t ( 'common/transfer', 'Item Price' ),
				'count' => Yii::t ( 'common/transfer', 'Count' ),
				'money' => Yii::t ( 'common/transfer', 'Money' ),
				'money_currency' => Yii::t ( 'common/transfer', 'Money Currency' ),
				'rate' => Yii::t ( 'common/transfer', 'Rate' ),
				'id_user' => Yii::t ( 'common/transfer', 'Id User' ),
				'id_customer' => Yii::t ( 'common/transfer', 'Customer' ),
				'comment' => Yii::t ( 'common/transfer', 'Comment' ),
				'created_at' => Yii::t ( 'common/transfer', 'Created At' ),
				'updated_at' => Yii::t ( 'common/transfer', 'Updated At' ),
				'paid_at' => Yii::t ( 'common/transfer', 'Paid At' ),
				'types' => Yii::t ( 'common/transfer', 'Types' ),
				'start' => Yii::t ( 'common/transfer', 'Start' ),
				'end' => Yii::t ( 'common/transfer', 'End' ),
				'payment_method' => Yii::t ( 'common/transfer', 'Fizetési mód' ) 
		];
	}
	public function getUser() {
		return $this->hasOne ( User::className (), [ 
				"id" => "id_user" 
		] );
	}
	public function getProduct() {
		return $this->hasOne ( Product::className (), [ 
				"id_product" => "id_product" 
		] )->via ( 'sale' );
	}
	public function getMoneyMovement() {
		return $this->hasOne ( MoneyMovement::className (), [ 
				"id_money_movement" => "id_object" 
		] );
	}
	public function getTicket() {
		return $this->hasOne ( Ticket::className (), [ 
				"id_ticket" => "id_object" 
		] );
	}
	public function getTicketType() {
		return $this->hasOne ( TicketType::className (), [ 
				"id_ticket_type" => "id_ticket_type" 
		] )->via ( 'ticket' );
	}
	public function getAccount() {
		return $this->hasOne ( Account::className (), [ 
				"id_account" => "id_account" 
		] );
	}
	public function getCurrency() {
		return $this->hasOne ( Currency::className (), [ 
				"id_currency" => "id_currency" 
		] );
	}
	public function getUserSoldItem() {
		return $this->hasOne ( UserSoldItem::className (), [ 
				"id_transfer" => "id_transfer" 
		] );
	}
	public function getCustomerCart() {
		return $this->hasOne ( ShoppingCart::className (), [ 
				"id_transfer" => "id_transfer" 
		] );
	}
	public function getSale() {
		return $this->hasOne ( Sale::className (), [ 
				"id_sale" => "id_object" 
		] );
	}
	public function getPaidByUser() {
		return $this->hasOne ( User::className (), [ 
				"id" => "paid_by" 
		] );
	}
	public function getPaidByName() {
		$result = "";
		$user = $this->paidByUser;
		if (isset ( $this->paidByUser )) {
			$result = $user->username;
		}
		
		return $result;
	}
	public function getObjectName() {
		$result = "";
		if ($this->type == Transfer::TYPE_TICKET) {
			$result = $this->ticketName;
		} else if ($this->type == Transfer::TYPE_PRODUCT) {
			$result = $this->productName;
		} else if ($this->type == Transfer::TYPE_MONEY_MOVEMENT_OUT) {
			$result = $this->moneyMovement->humanType;
		}
		return $result;
	}
	public function getUserName() {
		$result = "";
		$user = $this->user;
		if (isset ( $this->user )) {
			$result = $user->username;
		}
		
		return $result;
	}
	public function getProductName() {
		$result = "";
		$product = $this->product;
		if (isset ( $product )) {
			$result = $product->name;
		}
		
		return $result;
	}
	public function getTicketName() {
		$result = "";
		$ticket = $this->ticket;
		if (isset ( $ticket )) {
			$result = $this->ticket->ticketTypeName;
		}
		
		return $result;
	}
	public function getAccountName() {
		$result = "";
		$account = $this->account;
		if (isset ( $account )) {
			$result = $account->name;
		}
		
		return $result;
	}
	public function getTransferTypeName() {
		$result = "";
		if ($this->type == Transfer::TYPE_TICKET) {
			$result = Yii::t ( 'common/transfer', 'Ticket' );
		} else if ($this->type == Transfer::TYPE_PRODUCT) {
			$result = Yii::t ( 'common/transfer', 'Product' );
		} else if ($this->type == Transfer::TYPE_MONEY_MOVEMENT_OUT) {
			$result = Yii::t ( 'common/transfer', 'Money movement' );
		}
		return $result;
	}
	public function getSaleName() {
		$result = "";
		$sale = $this->sale;
		if (isset ( $sale )) {
			$result = $sale->name;
		}
		return $result;
	}
	public function getSignedMoney() {
		$m = 1;
		$result = $this->money;
		if ($this->direction == self::DIRECTION_OUT) {
			$m = - 1;
		}
		
		$result = $result * $m;
		
		return $result;
	}
	public static function toSignedMoney($dir, $money) {
		$m = 1;
		$result = $money;
		if ($dir == Transfer::DIRECTION_OUT) {
			$m = - 1;
		}
		
		$result = $result * $m;
		
		return $result;
	}
	public function toProductSoldString() {
		$s = "";
		
		$s .= $this->count;
		$s .= " " . Yii::t ( 'frontend/transfer', 'pieces' ) . " ";
		$s .= $this->product->name;
		$s .= " - ";
		$s .= $this->account->name;
		
		return $s;
	}
	
	/**
	 *
	 * @param $account common\models\Account        	
	 * @param $discount common\models\Discount        	
	 * @param $currency common\models\Currency        	
	 * @param $product common\models\Product        	
	 * @param $customer common\models\Customer        	
	 *
	 */
	public static function createProductTransfer($sale, $account, $discount, $currency, $count, $product, $status = Transfer::STATUS_PAID, $customer = null) {
		$transfer = new Transfer ();
		
		$transfer->type = Transfer::TYPE_PRODUCT;
		
		$transfer->id_object = $sale->id_sale;
		
		$transfer->item_price = $product->sale_price;
		$totalPrice = $transfer->item_price;
		
		$transfer->count = $count;
		$totalPrice = $totalPrice * $count;
		
		if (isset ( $discount )) {
			$transfer->id_discount = $discount->id_discount;
			$totalPrice = Discount::applyDiscount ( $totalPrice, $discount );
		}
		
		$transfer->money = $totalPrice;
		
		if (isset ( $currency )) {
			$transfer->rate = $currency->rate;
			$transfer->money_currency = Currency::applyCurrency ( $totalPrice, $currency );
		}
		
		$transfer->direction = Transfer::DIRECTION_IN;
		$transfer->status = $status;
		
		$transfer->id_account = $account->id_account;
		
		if (isset ( $customer )) {
			$transfer->id_customer = $customer->id_customer;
		}
		
		return $transfer;
	}
	
	/**
	 *
	 * @param $account common\models\Account        	
	 * @param $discount common\models\Discount        	
	 * @param $currency common\models\Currency        	
	 * @param $moneyMovement common\models\MoneyMovement        	
	 *
	 */
	public static function createMoneyMovementOutTransfer($account, $moneyMovement) {
		$transfer = new Transfer ();
		$transfer->payment_method = Transfer::PAYMENT_METHOD_CASH;
		$transfer->type = Transfer::TYPE_MONEY_MOVEMENT_OUT;
		$transfer->status = Transfer::STATUS_PAID;
		if ($moneyMovement->type == MoneyMovement::TYPE_OUT) {
			$transfer->direction = Transfer::DIRECTION_OUT;
		} else if ($moneyMovement->type == MoneyMovement::TYPE_IN) {
			$transfer->direction = Transfer::DIRECTION_IN;
		}
		$transfer->count = null;
		
		$transfer->id_object = $moneyMovement->id_money_movement;
		$transfer->money = $moneyMovement->money;
		
		$transfer->id_account = $account->id_account;
		
		$transfer->paid_at = date ( 'Y-m-d H:i:s' );
		$transfer->paid_by = \Yii::$app->user->id;
		
		return $transfer;
	}
	/**
	 *
	 * @param $account common\models\Account        	
	 * @param $discount common\models\Discount        	
	 * @param $currency common\models\Currency        	
	 * @param $ticket common\models\Ticket        	
	 *
	 */
	public static function createTicketTransfer($account, $discount, $currency, $count, $ticket, $status = Transfer::STATUS_NOT_PAID) {
		$transfer = new Transfer ();
		
		$transfer->status = $status;
		$transfer->type = Transfer::TYPE_TICKET;
		$transfer->direction = Transfer::DIRECTION_IN;
		
		$transfer->id_object = $ticket->id_ticket;
		
		$transfer->item_price = $ticket->price_brutto;
		$totalPrice = $transfer->item_price;
		
		$transfer->count = $count;
		$totalPrice = $totalPrice * $count;
		
		if (isset ( $discount )) {
			$transfer->id_discount = $discount->id_discount;
			$totalPrice = Discount::applyDiscount ( $totalPrice, $discount );
		}
		
		$transfer->money = $totalPrice;
		
		if (isset ( $currency )) {
			$transfer->rate = $currency->rate;
			$transfer->money_currency = Currency::applyCurrency ( $totalPrice, $currency );
		}
		
		$transfer->id_account = $account->id_account;
		
		return $transfer;
	}
	public static function modelsToArray($transfers, $default = []) {
		if ($transfers == null) {
			return $default;
		}
		
		return ArrayHelper::toArray ( $transfers, [ 
				'common\models\Transfer' => [ 
						'id_transfer',
						'item_price',
						'count',
						'money',
						'money_currency',
						'time' => function ($transfer) {
							return Yii::$app->formatter->asDatetime ( $transfer->created_at );
						},
						'account_name' => function ($transfer) {
							return $transfer->account->name;
						},
						'product_name' => function ($transfer) {
							$result = "";
							if ($transfer->type == Transfer::TYPE_TICKET) {
								$result = $transfer->ticket->ticketTypeName;
							} else if ($transfer->type == Transfer::TYPE_PRODUCT) {
								$result = $transfer->product->name;
							} else if ($transfer->type == Transfer::TYPE_MONEY_MOVEMENT_OUT) {
								$result = "Pénzmozgás";
							}
							return $result;
						},
						'category' => function ($transfer) {
							if ($transfer->type == Transfer::TYPE_TICKET) {
								return Yii::t ( 'frontend/transfer', 'Ticket' );
							} else if ($transfer->type == Transfer::TYPE_PRODUCT) {
								return $transfer->product->productCategoryName;
							} else if ($transfer->type == Transfer::TYPE_MONEY_MOVEMENT_OUT) {
								return "Pénzmozgás";
							}
						} 
				] 
		] );
	}
	public static function toPaymentMethodName($id) {
		$result = "";
		$arr = static::paymentMethods ();
		
		if (array_key_exists ( $id, $arr )) {
			$result = $arr [$id];
		}
		
		return $result;
	}
	public static function readUserSoldTransfers($user) {
		$transfers = [ ];
		
		$query = Transfer::find ();
		$query->innerJoin ( "user_sold_item", "user_sold_item.id_transfer = transfer.id_transfer" );
		
		// $query->innerJoinWith ( 'userSoldItem' );
		if (Helper::isUserCartVisibilityUser ()) {
			$query->andWhere ( [ 
					'user_sold_item.id_user' => $user->id 
			] );
		}
		$transfers = $query->all ();
		
		return $transfers;
	}
	public static function readCustomerCart($customer) {
		$transfers = [ ];
		
		if (isset ( $customer )) {
			$query = Transfer::find ();
			$query->innerJoinWith ( 'customerCart' );
			$query->andWhere ( [ 
					'shopping_cart.id_customer' => $customer->id_customer 
			] );
			$transfers = $query->all ();
		}
		
		return $transfers;
	}
	public static function types() {
		return [ 
				self::TYPE_MONEY_MOVEMENT_OUT => Yii::t ( 'common/transfer', 'Pénzmozgás' ),
				self::TYPE_PRODUCT => Yii::t ( 'common/transfer', 'Product' ),
				self::TYPE_TICKET => Yii::t ( 'common/transfer', 'Ticket' ) 
		];
	}
	public static function paymentMethods() {
		return [ 
				self::PAYMENT_METHOD_CASH => Yii::t ( 'common/transfer', 'Készpénz' ),
				self::PAYMENT_METHOD_BANCCARD => Yii::t ( 'common/transfer', 'Bankkártyás fizetés' ),
				self::PAYMENT_METHOD_TRANSFER => Yii::t ( 'common/transfer', 'Átutalás' ),
				self::PAYMENT_METHOD_CAFETERY => Yii::t ( 'common/transfer', 'Széchenyi kártya' ),
				self::PAYMENT_METHOD_TRANSFER_LATER => Yii::t ( 'common/transfer', 'Átutalás később' ) 
		];
		// self::PAYMENT_METHOD_DEBIT_MANDATE => Yii::t('common/transfer','Csoportos beszedési megbízás'),
		
	}
	public static function paymentMethodsForProduct() {
		return [ 
				self::PAYMENT_METHOD_CASH => Yii::t ( 'common/transfer', 'Készpénz' ),
				self::PAYMENT_METHOD_BANCCARD => Yii::t ( 'common/transfer', 'Bankkártyás fizetés' ),
				self::PAYMENT_METHOD_TRANSFER => Yii::t ( 'common/transfer', 'Átutalás' ),
				self::PAYMENT_METHOD_CAFETERY => Yii::t ( 'common/transfer', 'Széchenyi kártya' ) 
		];
		// self::PAYMENT_METHOD_DEBIT_MANDATE => Yii::t('common/transfer','Csoportos beszedési megbízás'),
		
	}
	public static function statuses() {
		return [ 
				self::STATUS_NOT_PAID => Yii::t ( 'common/transfer', 'Nincs fizetve' ),
				self::STATUS_PAID => Yii::t ( 'common/transfer', 'Fizetve' ),
				self::STATUS_STORNO => Yii::t ( 'common/transfer', 'Törölve' ) 
		];
	}
	public function getStatusName() {
		$status = null;
		$statuses = self::statuses ();
		if (array_key_exists ( $this->status, $statuses )) {
			$status = $statuses [$this->status];
		}
		return $status;
	}
	public function getPaymentMethodName() {
		$status = null;
		$statuses = self::paymentMethods ();
		if (array_key_exists ( $this->payment_method, $statuses )) {
			$status = $statuses [$this->payment_method];
		}
		return $status;
	}
	public function beforeDelete() {
		parent::beforeDelete ();
		if ($this->type == Transfer::TYPE_TICKET) {
			$ticket = $this->ticket;
			if ($ticket != null) {
				$ticket->delete ();
			}
		} else if ($this->type == Transfer::TYPE_MONEY_MOVEMENT_OUT) {
			$mm = $this->moneyMovement;
			$mm->delete ();
		} else if ($this->type == Transfer::TYPE_PRODUCT) {
			$sale = $this->sale;
			$product = $this->product;
			
			$product->stock = $product->stock + $this->count;
			
			$product->save ();
			$sale->delete ();
		}
		
		ShoppingCart::deleteAll ( [ 
				'id_transfer' => $this->id_transfer 
		] );
		UserSoldItem::deleteAll ( [ 
				'id_transfer' => $this->id_transfer 
		] );
		
		return true;
	}
	
	/**
	 *
	 * @param string $mode
	 *        	The mode to load
	 *        	Available modes
	 *        	<ul>
	 *        	<li>
	 *        	<h2>created_at</h2>
	 *        	<p>Load all transfer which were created </p>
	 *        	</li>
	 *        	<li>
	 *        	<h2>paid_at</h2>
	 *        	<p>Load all transfer which were paid </p>
	 *        	</li>
	 *        	<li>
	 *        	<h2>created_at_paid</h2>
	 *        	<p>Load all transfer which were created and paid </p>
	 *        	</li>
	 *        	<li>
	 *        	<h2>created_at_not_paid</h2>
	 *        	<p>Load all transfer which were created but not paid </p>
	 *        	</li>
	 *        	<li>
	 *        	<h2>paid_at_not_created_at</h2>
	 *        	<p>Load all transfer which were not created but paid . Works correctly only,
	 *        	when start and end date given
	 *        	</p>
	 *        	</li>
	 *        	</ul>
	 *        	
	 *        	
	 */
	public static function mkTotalQuery($mode, $start, $end, $idUser, $types, $idAccount) {
		$query = new Query ();
		
		$query->addSelect ( [ 
				new Expression ( 'transfer.id_account as account' ),
				new Expression ( ' COALESCE(sum(  ( case when direction =  ' . Transfer::DIRECTION_OUT . ' then  -1 else  1 end )*  transfer.money ),0) as money /** --' . $mode . '*/' ) 
		] );
		$query->from ( 'transfer' );
		
		if (! RoleDefinition::isAdmin ()) {
			$query->innerJoin ( "user_account_assignment", 'transfer.id_account = user_account_assignment.id_account' );
			$query->andWhere ( [ 
					'user_account_assignment.id_user' => Yii::$app->user->id 
			] );
		}
		$query->innerJoin ( "account", 'transfer.id_account = account.id_account' );
		$query->andWhere ( [ 
				'account.type' => Account::TYPE_ALL 
		] );
		
		$query->andFilterWhere ( [ 
				'transfer.id_account' => $idAccount 
		] );
		
		$query->andFilterWhere ( [ 
				'transfer.id_user' => $idUser 
		] );
		
		$query->andFilterWhere ( [ 
				'in',
				'transfer.type',
				$types 
		] );
		
		$query->andWhere ( [ 
				'not in',
				'transfer.status',
				Transfer::STATUS_STORNO 
		] );
		
		if ($mode == 'created_at') {
			self::inInterval ( $query, 'transfer.created_at', $start, $end );
		} else if ($mode == 'paid_at') {
			self::inInterval ( $query, 'transfer.paid_at', $start, $end );
		} else if ($mode == 'created_at_not_paid') {
			self::notPaid ( $query, 'transfer.paid_at', $start, $end );
			self::inInterval ( $query, 'transfer.created_at', $start, $end );
		} else if ($mode == 'created_at_paid') {
			self::inInterval ( $query, 'transfer.created_at', $start, $end );
			self::inInterval ( $query, 'transfer.paid_at', $start, $end );
		} else if ($mode == 'paid_at_not_created_at') {
			self::inInterval ( $query, 'transfer.paid_at', $start, $end );
			self::notInInterval ( $query, 'transfer.created_at', $start, $end );
		}
		
		// echo "start date is: ". $start;
		// echo "start date is: " . gettype( $start );
		
		if (! RoleDefinition::isAdmin ()) {
			Helper::restrictIfNotAdminTheStartDate ( $query, $start );
		}
		
		$query->groupBy ( 'transfer.id_account' );
		
		return $query;
	}
	public static function notInInterval($query, $field, $start, $end) {
		$query->andFilterWhere ( [ 
				'or',
				[ 
						'<',
						$field,
						isset ( $start ) ? $start : '1900-01-01' 
				],
				[ 
						'>=',
						$field,
						isset ( $end ) ? $end : '3000-01-01' 
				] 
		] );
	}
	public static function notPaid($query, $field, $start, $end) {
		$query->andFilterWhere ( [ 
				'or',
				[ 
						'<',
						$field,
						isset ( $start ) ? $start : '1900-01-01' 
				],
				[ 
						'>=',
						$field,
						isset ( $end ) ? $end : '3000-01-01' 
				],
				[ 
						"transfer.status" => Transfer::STATUS_NOT_PAID 
				] 
		] );
	}
	public static function inInterval($query, $field, $start, $end) {
		$query->andFilterWhere ( [ 
				'>=',
				$field,
				$start 
		] );
		$query->andFilterWhere ( [ 
				'<',
				$field,
				$end 
		] );
	}
	
	/**
	 *
	 * Parse query results so, that all available account will be display, even then , if $queryResult does not contain any result for the given account
	 *
	 * @param mixed $queryResult
	 *        	an array, wchic contains items. each item has to key - value pairs: [ id_account => 0, money => 0 ]
	 *        	
	 */
	public static function mkTotalsResultWithAllAvailableAccount($queryResult, $accounts, $accountMap, $idAccount) {
		$totals = [ ];
		$totals ['total'] = 0;
		
		$totals ['accounts'] = [ ];
		
		foreach ( $accounts as $account ) {
			if (isset ( $idAccount ) && is_numeric ( $idAccount ) && $idAccount != $account->id_account) {
				continue;
			}
			
			$accountTotal = [ 
					'id_account' => $account->id_account,
					'label' => $account->name,
					'money' => 0 
			];
			
			$item = self::findByAccountInQueryResult ( $queryResult, $account );
			
			if (isset ( $item )) {
				$accountTotal ['money'] = $item ['money'];
			}
			
			$totals ['accounts'] [] = $accountTotal;
			$totals ['total'] += $accountTotal ['money'];
		}
		return $totals;
	}
	public static function findByAccountInQueryResult($queryResult, $account) {
		$result = null;
		foreach ( $queryResult as $item ) {
			if ($item ['account'] == $account->id_account) {
				$result = $item;
			}
		}
		return $result;
	}
	
	/**
	 * create and execute a "total" query
	 */
	public static function exTotalQuery($mode, $start, $end, $idUser, $types, $idAccount) {
		$query = self::mkTotalQuery ( $mode, $start, $end, $idUser, $types, $idAccount );
		$command = $query->createCommand ();
		$result = $command->queryAll ();
		return $result;
	}
	
	/**
	 * find all transfers which were paid in the period
	 */
	public static function mkPaidAtTotals($start, $end, $idUser, $types, $idAccount, $accounts, $accountMap) {
		$result = [ ];
		$queryResult = self::exTotalQuery ( 'paid_at', $start, $end, $idUser, $types, $idAccount );
		$result = self::mkTotalsResultWithAllAvailableAccount ( $queryResult, $accounts, $accountMap, $idAccount );
		return $result;
	}
	
	/**
	 * find all transfers in the period ( doesn't matter if paid or not )
	 */
	public static function mkCreatedAtTotals($start, $end, $idUser, $types, $idAccount, $accounts, $accountMap) {
		$result = [ ];
		$queryResult = self::exTotalQuery ( 'created_at', $start, $end, $idUser, $types, $idAccount );
		$result = self::mkTotalsResultWithAllAvailableAccount ( $queryResult, $accounts, $accountMap, $idAccount );
		return $result;
	}
	
	/**
	 * find transfers which were created but not paid in the period
	 */
	public static function mkCreatedAtNotPaidTotals($start, $end, $idUser, $types, $idAccount, $accounts, $accountMap) {
		$result = [ ];
		$queryResult = self::exTotalQuery ( 'created_at_not_paid', $start, $end, $idUser, $types, $idAccount );
		$result = self::mkTotalsResultWithAllAvailableAccount ( $queryResult, $accounts, $accountMap, $idAccount );
		return $result;
	}
	
	/**
	 * find transfers which were created and paid in the period
	 */
	public static function mkCreatedAtPaidTotals($start, $end, $idUser, $types, $idAccount, $accounts, $accountMap) {
		$result = [ ];
		$queryResult = self::exTotalQuery ( 'created_at_paid', $start, $end, $idUser, $types, $idAccount );
		$result = self::mkTotalsResultWithAllAvailableAccount ( $queryResult, $accounts, $accountMap, $idAccount );
		return $result;
	}
	
	/**
	 * find transfers, where depth was paid
	 */
	public static function mkPaidAtNotCreatedAtPaidTotals($start, $end, $idUser, $types, $idAccount, $accounts, $accountMap) {
		$result = [ ];
		$queryResult = self::exTotalQuery ( 'paid_at_not_created_at', $start, $end, $idUser, $types, $idAccount );
		$result = self::mkTotalsResultWithAllAvailableAccount ( $queryResult, $accounts, $accountMap, $idAccount );
		return $result;
	}
	public static function mkTotals($start, $end, $idUser, $types, $idAccount, $accounts, $accountMap) {
		$result = [ ];
		
		$result ['paid_at'] = self::mkPaidAtTotals ( $start, $end, $idUser, $types, $idAccount, $accounts, $accountMap );
		$result ['created_at'] = self::mkCreatedAtTotals ( $start, $end, $idUser, $types, $idAccount, $accounts, $accountMap );
		$result ['created_at_not_paid'] = self::mkCreatedAtNotPaidTotals ( $start, $end, $idUser, $types, $idAccount, $accounts, $accountMap );
		$result ['created_at_paid'] = self::mkCreatedAtPaidTotals ( $start, $end, $idUser, $types, $idAccount, $accounts, $accountMap );
		$result ['paid_at_not_created_at'] = self::mkPaidAtNotCreatedAtPaidTotals ( $start, $end, $idUser, $types, $idAccount, $accounts, $accountMap );
		
		return $result;
	}
	
	/**
	 * Ezt a függvényt használjuk a zárások összegének kiszámolására!
	 * A számolás csak a következő feltételekkel bíró tranzakciókat
	 * tartalmazza:
	 * - trazakció típus: common\models\Account::TYPE_ALL
	 * - tranzakció fizetési módja: készpénz
	 * - tranzakció státusza: fizetve
	 * -
	 */
	public static function readPaid($start, $end, $idUser) {
		$query = (new \yii\db\Query ());
		$query->select ( [ 
				'coalesce(sum( case when transfer.direction = ' . Transfer::DIRECTION_IN . ' then transfer.money else -1 * transfer.money end  ),0) AS transfer_money' 
		] );
		$query->from ( 'transfer' );
		$query->innerJoin ( "account", "account.id_account = transfer.id_account" );
		$query->andWhere ( [ 
				'transfer.paid_by' => $idUser 
		] );
		
		$created_condition = [ 
				'and',
				[ 
						'>=',
						'transfer.created_at',
						$start 
				],
				[ 
						'<',
						'transfer.created_at',
						$end 
				] 
		];
		$paid_condition = [ 
				'and',
				[ 
						'>=',
						'transfer.paid_at',
						$start 
				],
				[ 
						'<',
						'transfer.paid_at',
						$end 
				] 
		];
		
		$query->andFilterWhere ( [ 
				'or',
				$created_condition,
				$paid_condition 
		] );
		$query->andWhere ( [ 
				'transfer.status' => Transfer::STATUS_PAID 
		] );
		$query->andWhere ( [ 
				'account.type' => Account::TYPE_ALL 
		] );
		$query->andWhere ( [ 
				'transfer.payment_method' => Transfer::PAYMENT_METHOD_CASH 
		] );
		
		return $query->scalar ();
	}
	public function storno() {
		$this->status = Transfer::STATUS_STORNO;
		$this->save ( false );
		if ($this->type == Transfer::TYPE_TICKET) {
			$ticket = $this->ticket;
			$ticket->status = Ticket::STATUS_DELETED;
			
			$ticket->save ( false );
			
			if ($ticket->part == 0) {
				TicketInstallmentRequest::updateAll ( [ 
						'status' => TicketInstallmentRequest::$STATUS_CANCELED 
				], [ 
						'id_ticket' => $this->ticket->id_ticket 
				] );
			}
			
			// storno contract
		} else if ($this->type == Transfer::TYPE_PRODUCT) {
			$sale = $this->sale;
			$product = $this->sale->product;
			$product->stock = $product->stock + $this->count;
			$product->save ( false );
			$sale->status = Sale::STATUS_DELETED;
			$sale->save ( false );
		} else if ($this->type == Transfer::TYPE_MONEY_MOVEMENT_OUT) {
			$mm = $this->moneyMovement;
			$mm->status = MoneyMovement::STATUS_STORNO;
			$mm->save ( false );
		}
		
		ShoppingCart::deleteAll ( [ 
				'id_transfer' => $this->id_transfer 
		] );
		UserSoldItem::deleteAll ( [ 
				'id_transfer' => $this->id_transfer 
		] );
	}
	public function unstorono() {
		if ($this->type != Transfer::TYPE_TICKET) {
			throw new NotAcceptableHttpException ( "Csak bérletet lehet visszaállítani" );
		}
		
		$this->status = Transfer::STATUS_NOT_PAID;
		$this->paid_at = null;
		$this->paid_by = null;
		$this->save ( false );
		
		$ticket = $this->ticket;
		$ticket->status = Ticket::STATUS_INACTIVE;
		
		$ticket->save ( false );
		
		TicketInstallmentRequest::updateAll ( [ 
				'status' => TicketInstallmentRequest::$STATUS_ACCEPTED_MANUAL 
		], [ 
				'id_ticket' => $ticket->id_ticket 
		] );
		
		$item = new ShoppingCart ();
		$item->id_customer = $this->id_customer;
		$item->id_transfer = $this->id_transfer;
		$item->save ( false );
	}
	
	
	
	public function payout($id_account = null) {
		if ($this->status != Transfer::STATUS_NOT_PAID) {
			return false;
		}
		
		$this->status = Transfer::STATUS_PAID;
		$this->paid_at = Helper::getDateTimeString ();
		$this->paid_by = \Yii::$app->user->id;
		
		if (isset ( $id_account )) {
			$this->id_account = $id_account;
		} else {
			if (Helper::isUserCartVisibilityAll ()) {
				$this->id_account = Account::readDefault ();
			}
		}
		
		ShoppingCart::deleteAll ( [ 
				'id_transfer' => $this->id_transfer 
		] );
		UserSoldItem::deleteAll ( [ 
				'id_transfer' => $this->id_transfer 
		] );
		return $this->save ( false );
	}
	public static function payoutAll($id_user, $id_array) {
		ShoppingCart::deleteAll ( [ 
				'in',
				'id_transfer',
				$id_array 
		] );
		UserSoldItem::deleteAll ( [ 
				'in',
				'id_transfer',
				$id_array 
		] );
		
		$updateConfig = null;
		if (Helper::isUserCartVisibilityUser ()) {
			$updateConfig = [ 
					'status' => Transfer::STATUS_PAID,
					'paid_at' => Helper::getDateTimeString (),
					'paid_by' => $id_user 
			];
		} else {
			$updateConfig = [ 
					'status' => Transfer::STATUS_PAID,
					'paid_at' => Helper::getDateTimeString (),
					'paid_by' => $id_user,
					'id_account' => Account::readDefault () 
			];
		}
		
		$updateConditions = [ 
				[ 
						'in',
						'id_transfer',
						$id_array 
				],
				[ 
						'in',
						'status',
						[ 
								Transfer::STATUS_NOT_PAID 
						] 
				] 
		];
		
		Transfer::updateAll ( $updateConfig, $updateConditions );
	}
	
	/**
	 *
	 * @param common\models\Contract $contract        	
	 * @param common\models\TicketInstallmentRequest $request        	
	 * @param common\models\Account $account        	
	 * @param int $transferStatus        	
	 *
	 *
	 */
	public static function sellContractTicket($contract, $request, $account, $transferStatus, $paymentMethod, $addToCustomerCart = false) {
		$ticketType = $contract->ticketType;
		$customer = $contract->customer;
		$card = $customer->card;
		
		$ticket = new Ticket ();
		
		$ticket->id_user = \Yii::$app->user->id;
		$ticket->id_ticket_type = $ticketType->id_ticket_type; // save to contract
		$ticket->id_account = $account->id_account;
		$ticket->id_discount = null; // contract.id_discount
		$ticket->start = $request->request_target_time_at;
		$ticket->end = date ( 'Y-m-d', strtotime ( $request->request_target_time_at . " +1 month -1 day" ) );
		$ticket->max_usage_count = $ticketType->max_usage_count;
		$ticket->usage_count = 0;
		$ticket->status = Ticket::STATUS_INACTIVE;
		$ticket->price_brutto = $request->money;
		$ticket->id_card = $card->id_card;
		$ticket->part = $request->priority;
		$ticket->id_contract = $contract->id_contract;
		$ticket->save ( false );
		
		$transfer = new Transfer ();
		
		$transfer->status = $transferStatus;
		$transfer->type = Transfer::TYPE_TICKET;
		$transfer->direction = Transfer::DIRECTION_IN;
		$transfer->id_object = $ticket->id_ticket;
		$transfer->item_price = $ticketType->price_brutto;
		$transfer->money = $request->money;
		$transfer->id_account = $account->id_account;
		$transfer->count = 1;
		
		if ($transferStatus == Transfer::STATUS_PAID) {
			$transfer->paid_at = date ( 'Y-m-d H:i:s' );
			$transfer->paid_by = \Yii::$app->user->id;
		}
		
		$transfer->payment_method = $paymentMethod;
		
		$transfer->comment = "Szerződéses bérlet létrehozás";
		$transfer->id_user = \Yii::$app->user->id;
		$transfer->id_customer = $customer->id_customer;
		$transfer->save ( false );
		
		if ($addToCustomerCart == true) {
			$cart = new ShoppingCart ();
			$cart->id_customer = $customer->id_customer;
			$cart->id_transfer = $transfer->id_transfer;
			$cart->save ( false );
		}
		
		return [ 
				$transfer,
				$ticket 
		];
	}
	public static function canBeAddedToCart($payment_method) {
		if ($payment_method == Transfer::PAYMENT_METHOD_TRANSFER_LATER) {
			return false;
		}
		return true;
	}
	public static function canMarkPaidByReception($payment_method) {
		if ($payment_method == Transfer::PAYMENT_METHOD_TRANSFER_LATER) {
			return false;
		}
		return true;
	}
}
