<?php

namespace App\PartnerBalance\History\Transactions;

/**
 * The class is used for getting the transactions of a certain supplier, for a certain currency
 * and for a given interval.
 * @author Gabriel
 */
class Supplier extends GeneralAbstract
{

	/**
	 * Adds transactions collected from supplier invoice level and payment documents level.
	 * @see \App\PartnerBalance\History\Transactions\GeneralAbstract::populateTransactions()
	 */
	public function populateTransactions()
	{

		$this->addInvoices();

		$this->addPaymentDocs();

		// orders the keys (the inv/docs date)
		ksort($this->transactionsList);

	}

	/**
	 * The method adds the issued invoices to the internal transactions list.
	 */
	private function addInvoices()
	{

		$invListObj = new \App\EntityList\SupplierInvoices();
		$invListObj->applyUserRestriction(false);

		if ($this->startDate and $this->endDate) {
			$invListObj->setFilter('inv.invoiceDate', 'BETWEEN', [$this->startDate, $this->endDate]);
		} elseif ($this->startDate) {
			$invListObj->setFilter('inv.invoiceDate', '>=', $this->startDate);
		}  elseif ($this->endDate) {
			$invListObj->setFilter('inv.invoiceDate', '<=', $this->endDate);
		}

		$invListObj->setFilter('inv.idSupplier', '=', $this->id);
		$invListObj->setFilter('inv.currency', '=', $this->currency);
		$invListObj->setFilter('inv.statusOp', '=', 'confirmed');
		$invListObj->setColumns(['inv.id', 'inv.invoiceDate', 'inv.totalValue']);
		if ($this->selectForUpdate) {
			$invListObj->setForUpdate(true);
		}
		$invListEx = $invListObj->getExecution();

		// add  invoices
		foreach($invListEx as $inv) {
			$this->addTransaction($inv['invoiceDate'], $inv['totalValue'], 'inv', $inv['id']);
		}

	}

	/**
	 * The method adds the payment docs to the internal transactions list.
	 */
	private function addPaymentDocs()
	{

		$payDocListObj = new \App\EntityList\SupplierInvoicePayments();
		$payDocListObj->applyUserRestriction(false);
		if ($this->startDate and $this->endDate) {
			$payDocListObj->setFilter('doc.docDate', 'BETWEEN', [$this->startDate, $this->endDate]);
		} elseif ($this->startDate) {
			$payDocListObj->setFilter('doc.docDate', '>=', $this->startDate);
		} elseif ($this->endDate) {
			$payDocListObj->setFilter('doc.docDate', '<=', $this->endDate);
		}
		$payDocListObj->setFilter('inv.idSupplier', '=', $this->id);
		$payDocListObj->setFilter('inv.currency', '=', $this->currency);
		$payDocListObj->setColumns(['doc.id'=>'idDoc', 'doc.docDate', 'doc.invoicePayedValue'=>'docInvoicePayedValue']);
		$payDocListObj->setColumns(['doc.idInvoice'=>'idInvoice', 'inv.totalValue'=>'invTotalValue', 'inv.payedValue'=>'invPayedTotal']);
		if ($this->selectForUpdate) {
			$payDocListObj->setForUpdate(true);
		}
		$payDocListEx = $payDocListObj->getExecution();

		// go through each payment doc and add it to the transactions
		foreach($payDocListEx as $doc) {

			$extraInfo = [];
			// if the invoice is NOT overpayed
			if (abs($doc['invPayedTotal'])<=abs($doc['invTotalValue'])) {
				$docPayedValue = -$doc['docInvoicePayedValue'];
			}
			// if the invoice is overpayed - the document may only be partially "used" (the overpayed value is ignored when determining the balances)
			else {
				$allInvPaymentDocs = \Entity\SupplierInvoice::select($doc['idInvoice'], $this->selectForUpdate)->paymentDocumentsApplyMode;
				$docPayedValue = -$allInvPaymentDocs[$doc['idDoc']]['realPayedValue'];
				$extraInfo['docInvoicePayedValue'] = -(Float)$doc['docInvoicePayedValue'];
			}
			$this->addTransaction($doc['docDate'], $docPayedValue, 'doc', $doc['idDoc'], $extraInfo);
		}

	}

}

