<?php

namespace RxConnexionBundle\Repository;

use RxConnexionBundle\Entity\PurchaseOrderBreakdownEntity;
use RxConnexionBundle\Entity\PurchaseOrderBreakdownItemDeliveryEntity;
use Symfony\Component\Form\Extension\Core\DataTransformer\DateTimeToStringTransformer;

/**
 * PurchaseOrderBreakdownItemDeliveryRepository
 *
 * This class was generated by the Doctrine ORM. Add your own custom
 * repository methods below.
 */
class PurchaseOrderBreakdownItemDeliveryRepository extends \Doctrine\ORM\EntityRepository
{
    public function validate($purchaseOrderBreakdownItemDelivery_form, $purchaseOrderBreakdown_id) {

        $errors = array();

        $action = $purchaseOrderBreakdownItemDelivery_form['action'];

        // d = delete
        if($action !== 'd') {

            /*if(empty($purchaseOrderBreakdownItemDelivery_form['invoiceDate']))
                $errors[] = 'Invoice date should not be blank.';

            if(empty($purchaseOrderBreakdownItemDelivery_form['invoice_no']))
                $errors[] = 'Invoice no. should not be blank.';*/

            /*if(empty($purchaseOrderBreakdownItemDelivery_form['location']))
                $errors[] = 'Please select location.';*/

            /*if(empty($purchaseOrderBreakdownItemDelivery_form['quantity']))
                $errors[] = 'Quantity should not be blank.';
            else {

                $purchaseOrderBreakdownItem = $this->getEntityManager()->getRepository('RxConnexionBundle:PurchaseOrderBreakdownItemEntity')->find(base64_decode($purchaseOrderBreakdownItemDelivery_form['purchaseOrderBreakdownItem']));
                $purchaseOrderBreakdownItemDelivery = $this->getEntityManager()->getRepository('RxConnexionBundle:PurchaseOrderBreakdownItemDeliveryEntity')->find($purchaseOrderBreakdownItemDelivery_form['id']);

                if(($purchaseOrderBreakdownItem->getQuantityReceived() - ($purchaseOrderBreakdownItemDelivery ? $purchaseOrderBreakdownItemDelivery->getQuantity() : 0)) + str_replace(',', '', $purchaseOrderBreakdownItemDelivery_form['quantity']) > $purchaseOrderBreakdownItem->getQuantityForReceiving())
                    $errors[] = 'Item already exceed its required quantity';
            }*/

            foreach ($purchaseOrderBreakdownItemDelivery_form['deliveries'] as $k => $delivery) {

                $purchaseOrderBreakdownItemDelivery = $this->getEntityManager()->getRepository('RxConnexionBundle:PurchaseOrderBreakdownItemDeliveryEntity')->find($delivery['id']);
                $purchaseOrderBreakdownItem = $purchaseOrderBreakdownItemDelivery->getPurchaseOrderBreakdownItem();

                if(empty($delivery['quantity']))
                    $errors[] = $purchaseOrderBreakdownItem->getPurchaseOrderItem()->getMaterialRequisitionItem()->getItem()->getDescription() . ' quantity should not be blank.';
                else {

                    if(($purchaseOrderBreakdownItem->getQuantityReceived() - ($purchaseOrderBreakdownItemDelivery ? $purchaseOrderBreakdownItemDelivery->getQuantity() : 0)) + str_replace(',', '', $delivery['quantity']) > $purchaseOrderBreakdownItem->getQuantityForReceiving())
                        $errors[] = 'Item already exceed its required quantity';
                }

                if(isset($delivery['serialNo'])) {
                    foreach ($delivery['serialNo'] as $sn) {
                        if (empty($sn['serialNo'])) {
                            $errors[] = 'Serial No/s should not have any blank.';
                            break;
                        }
                    }
                }
            }

	        if ($action == 'u') {
	        	/**@var PurchaseOrderBreakdownEntity $purchaseOrderBreakdown*/
		        $purchaseOrderBreakdown = $this->getEntityManager()->getRepository(PurchaseOrderBreakdownEntity::class)->find(base64_decode($purchaseOrderBreakdown_id));
		        if ($purchaseOrderBreakdown->getPurchaseInvoice()->getTotalPayment() > 0) {
			        $errors[] = 'Cannot update this P.O. because it already has Invoice Payments. This may cause discrepancies. Please contact administrator for more info.';
		        }

	        }
        }

        return $errors;
    }
    public function validate__old($purchaseOrderBreakdownItemDelivery_form, $purchaseOrderBreakdownItems_form) {

        $errors = array();

        $action = $purchaseOrderBreakdownItemDelivery_form['action'];

        // d = delete
        if($action !== 'd') {

            /*if(empty($purchaseOrderBreakdownItemDelivery_form['invoiceDate']))
                $errors[] = 'Invoice date should not be blank.';

            if(empty($purchaseOrderBreakdownItemDelivery_form['invoice_no']))
                $errors[] = 'Invoice no. should not be blank.';*/

            /*if(empty($purchaseOrderBreakdownItemDelivery_form['location']))
                $errors[] = 'Please select location.';*/

            if(empty($purchaseOrderBreakdownItemDelivery_form['quantity']))
                $errors[] = 'Quantity should not be blank.';
            else {

                $purchaseOrderBreakdownItem = $this->getEntityManager()->getRepository('RxConnexionBundle:PurchaseOrderBreakdownItemEntity')->find(base64_decode($purchaseOrderBreakdownItemDelivery_form['purchaseOrderBreakdownItem']));
                $purchaseOrderBreakdownItemDelivery = $this->getEntityManager()->getRepository('RxConnexionBundle:PurchaseOrderBreakdownItemDeliveryEntity')->find($purchaseOrderBreakdownItemDelivery_form['id']);

                if(($purchaseOrderBreakdownItem->getQuantityReceived() - ($purchaseOrderBreakdownItemDelivery ? $purchaseOrderBreakdownItemDelivery->getQuantity() : 0)) + str_replace(',', '', $purchaseOrderBreakdownItemDelivery_form['quantity']) > $purchaseOrderBreakdownItem->getQuantityForReceiving())
                    $errors[] = 'Item already exceed its required quantity';
            }

            if(!is_null($purchaseOrderBreakdownItems_form)) {
                foreach ($purchaseOrderBreakdownItems_form as $k => $pobi) {
                    if(isset($pobi['serialNo'])) {
                        foreach ($pobi['serialNo'] as $sn) {
                            if (empty($sn['serialNo'])) {
                                $errors[] = 'Serial No/s should not have any blank.';
                                break;
                            }
                        }
                    }
                }
            }
        }

        return $errors;
    }

    public function ajax_list__old(array $get, $userData){

        $columns = array(
            'ei.description',
            //'l.description',
            //'ppobid.doc_no',
            'ppobi.quantity',
            'ppobi.quantityVoided',
            'ppobi.quantityReceived',
            'ppobid.drDate',
            'ppobid.drNo',
            'ppobid.invoiceDate',
            'ppobid.invoiceNo',
            'ppobid.quantity',
            'ppobid.id',
            //'ium.description',
            //'pobiium.description'
        );
        $dtColumns = array(
            'ei.description as item_description',
            //'l.description as location_description',
            //'ppobid.doc_no',
            'ppobi.quantity as purchaseOrderBreakdownItemQuantity',
            'ppobi.quantityVoided as purchaseOrderBreakdownItemQuantityVoided',
            'ppobi.quantityReceived as purchaseOrderBreakdownItemQuantityReceived',
            'ppobid.drDate',
            'ppobid.drNo',
            'ppobid.invoiceDate',
            'ppobid.invoiceNo',
            'ppobid.quantity',
            //'pobiium.description as purchaseOrderBreakdownItemUnitMeasurement'
            //'ium.description as itemUnitMeasurement',
            'ppobid.id',
//            'iu.description as itemUnit_desc',
        );
        $dbColumns = array('ppobi.id as purchaseOrderBreakdownItem_id');
        $asColumns = array();

        $query = $this->getEntityManager()
            ->getRepository('RxConnexionBundle:PurchaseOrderBreakdownItemDeliveryEntity')
            ->createQueryBuilder('ppobid')
            ->leftJoin('ppobid.purchaseOrderBreakdownItem', 'ppobi')
            ->leftJoin('ppobi.purchaseOrderItem', 'ppoi')
            ->leftJoin('ppoi.materialRequisitionItem', 'pmri')
            ->leftJoin('pmri.item', 'ei')
//            ->leftJoin('ei.itemUnit', 'iu')
            //->leftJoin('ppobid.itemUnitMeasurement','ium')
            //->leftJoin('ppoi.itemUnitMeasurement','pobiium')
            //->leftJoin('ppobi.location', 'l')
            ->select(array_merge($dtColumns, $dbColumns))
            ->where('ppobi.purchaseOrderBreakdown = :purchaseOrderBreakdown_id')
            ->setParameter('purchaseOrderBreakdown_id', base64_decode($get['purchaseOrderBreakdown_id']));

        /*
         * Ordering
         */
        foreach($get['columns'] as $key => $column) {
            if($column['orderable']=='true') {
                if(isSet($get['order'])) {
                    foreach($get['order'] as $order) {
                        if($order['column']==$key) {
                            $query->addOrderBy($columns[$key], $order['dir']);
                        }
                    }
                }
            }
        }

        /*
           * Filtering
           * NOTE this does not match the built-in DataTables filtering which does it
           * word by word on any field. It's possible to do here, but concerned about efficiency
           * on very large tables, and MySQL's regex functionality is very limited
           */
        if ( isset($get['search']) && $get['search']['value'] != '' ){
            $aLike = array();
            $search_value = $get['search']['value'];
            foreach($get['columns'] as $key => $column) {
                if($column['searchable']=='true') {
                    if(!empty($search_value))
                        $aLike[] = $query->expr()->like($columns[$key], '\'%'. $search_value .'%\'');
                }
            }
            foreach($asColumns as $asColumn) {
                $aLike[] = $query->expr()->like($asColumn, '\'%'. $search_value .'%\'');
            }
            if(count($aLike) > 0) $query->andWhere(new Expr\Orx($aLike));
            else unset($aLike);
        }

        $query_count = $query;
        $result_count = $query_count->getQuery()->getArrayResult();

        /* Set Limit and Length */
        if ( isset( $get['start'] ) && $get['length'] != '-1' ){
            $query->setFirstResult( (int)$get['start'] )
                ->setMaxResults( (int)$get['length'] );
        }

        $result = $query->getQuery()->getResult();

        /* Data Count */
        $recordsTotal = count($result_count);
        /* Data set length after filtering */
        $recordsFiltered = count($result);

        unset($result_count);

        /*
         * Output
         */
        $output = array(
            "draw" => intval($get['draw']),
            "recordsTotal" => $recordsTotal,
            "recordsFiltered" => $recordsTotal,
            "data" => array()
        );

        $hasUpdate = $userData['type'] === 'Super Admin' ||  in_array('Admin Purchase Order Receive Update', $userData['accesses']);

        $dateTimeToStringTransformer = new DateTimeToStringTransformer();

        foreach($result as $row) {

            $id = base64_encode($row['id']);
            $purchaseOrderBreakdownItem_id = base64_encode($row['purchaseOrderBreakdownItem_id']);

            $action = '';

            if($hasUpdate)
                $action .= "<a href='javascript:void(0)' class='action-button-style href-purchaseOrderBreakdownItemDelivery-form' data-action='u' data-id='$id' data-ref-id='$purchaseOrderBreakdownItem_id'>Update</a>";

            $values = array(
                $row['item_description'],
                //$row['doc_no'],
                number_format($row['purchaseOrderBreakdownItemQuantity'], 0),
                number_format($row['purchaseOrderBreakdownItemQuantityVoided'], 0),
                number_format($row['purchaseOrderBreakdownItemQuantityReceived'], 0),
                //$row['location_description'],
                date('m/d/Y', strtotime($dateTimeToStringTransformer->transform($row['drDate']))),
                $row['drNo'],
                !empty($row['invoiceDate']) ? date('m/d/Y', strtotime($dateTimeToStringTransformer->transform($row['invoiceDate']))) : '',
                $row['invoiceNo'],
                number_format($row['quantity'], 0),
                $action
            );

            $output['data'][] = $values;
        }

        unset($result);

        return $output;
    }
    public function ajax_list(array $get){

        $columns = array(
            array('pobid.`received_date`', 'DATE_FORMAT(pobid.`received_date`, "%m/%d/%Y")', 'receivedDate'),
            array('pobid.`dr_date`', 'DATE_FORMAT(pobid.`dr_date`, "%m/%d/%Y")', 'drDate'),
            array('pobid.`dr_no`', 'pobid.`dr_no`'),
            array('pobid.`invoice_date`', 'DATE_FORMAT(pobid.`invoice_date`, "%m/%d/%Y")', 'invoiceDate'),
            array('pobid.`invoice_no`', 'pobid.`invoice_no`'),
            array('i.`description`', "GROUP_CONCAT(CONCAT('&#183; ', i.description, ' (Price: ', mri.`price`, ')', ' (Qty: ', pobid.`quantity`, ')') SEPARATOR '<br>')", 'items'),
            array('pobid.`id`', 'pobid.`id`'),
            array('pobid.`id`', 'GROUP_CONCAT(pobid.`id`)', 'ids'),
            array('pobii.`id`', 'pobii.`id`', 'purchaseOrderBreakdownItem_id'),
            array('mr.`status`', 'mr.`status`', 'mr_status'),
        );
        $asColumns = array();

        $select = "SELECT";
        $from = "FROM `purchase_order_breakdown_item_delivery` pobid";
        $joins = " LEFT JOIN purchase_order_breakdown_invoice pobi ON pobid.purchase_order_breakdown_invoice_id = pobi.id";
        $joins .= " INNER JOIN purchase_order_breakdown_item pobii ON pobid.purchase_order_breakdown_item_id = pobii.id";
        $joins .= " INNER JOIN purchase_order_item poi ON pobii.purchase_order_item_id = poi.id";
        $joins .= " INNER JOIN material_requisition_item mri ON poi.material_requisition_item_id = mri.id";
        $joins .= " INNER JOIN material_requisition mr ON mri.material_requisition_id = mr.id";
        $joins .= " INNER JOIN item i ON mri.item_id = i.id";
        $sqlWhere = "WHERE pobii.`purchase_order_breakdown_id` = :purchaseOrderBreakdown_id";
        $groupBy = " GROUP BY pobid.`dr_no`, pobid.`dr_date`";
        $orderBy = "";
        $limit = "";
        $stmtParams = array(
            'purchaseOrderBreakdown_id' => base64_decode($get['purchaseOrderBreakdown_id']),
        );

        foreach($columns as $key => $column) {
            $select .= ($key > 0 ? ', ' : ' ') . $column[1] . (isset($column[2]) ? ' AS ' . $column[2] : '');
        }

        /*
         * Ordering
         */
        foreach($get['columns'] as $key => $column) {
            if($column['orderable']=='true') {
                if(isSet($get['order'])) {
                    foreach($get['order'] as $order) {
                        if($order['column']==$key) {
                            $orderBy .= (!empty($orderBy) ? ', ' : 'ORDER BY ') . $columns[$key][0] . (!empty($order['dir']) ? ' ' . $order['dir'] : '');
                        }
                    }
                }
            }
        }

        /*
         * Filtering
         */
        if(isset($get['search']) && $get['search']['value'] != ''){
            $aLikes = array();
            foreach($get['columns'] as $key => $column) {
                if($column['searchable']=='true') {
                    $aLikes[] = $columns[$key][0] . ' LIKE :searchValue';
                }
            }
            foreach($asColumns as $asColumn) {
                $aLikes[] = $asColumn . ' LIKE :searchValue';
            }
            if(count($aLikes)) {
                $sqlWhere .= (!empty($sqlWhere) ? ' AND ' : 'WHERE ') . '(' . implode(' OR ', $aLikes) . ')';
                $stmtParams['searchValue'] = "%" . $get['search']['value'] . "%";
            }
        }

        /* Set Limit and Length */
        if(isset( $get['start'] ) && $get['length'] != '-1'){
            $limit = 'LIMIT ' . (int)$get['start'] . ',' . (int)$get['length'];
        }

        $sql = "$select $from $joins $sqlWhere $groupBy $orderBy";
        $query = $this->getEntityManager()->getConnection()->prepare($sql);
        $query->execute($stmtParams);
        $result_count = $query->fetchAll();

        $sql = "$select $from $joins $sqlWhere $groupBy $orderBy $limit";
        $query = $this->getEntityManager()->getConnection()->prepare($sql);
        $query->execute($stmtParams);
        $result = $query->fetchAll();

        return array(
            'results' => $result,
            'total' => count($result_count)
        );
    }


    public function nextDocNo() {

        $year = date('Y');
        $month = date('m');

        $sql = "
            SELECT
                pobid.`doc_no`
            FROM `purchase_order_breakdown_item_delivery` pobid
            WHERE DATE_FORMAT(pobid.`invoice_date`, '%Y') = :year
            AND DATE_FORMAT(pobid.`invoice_date`, '%m') = :month
            ORDER BY pobid.`doc_no` * 1 DESC
            LIMIT 1
        ";

        $query = $this->getEntityManager()->getConnection()->prepare($sql);

        $query->execute(array(
            'year' => $year,
            'month' => $month
        ));

        $result = $query->fetch();


        if($result) {
            $docNo = 'RR-' . $year. '-'. $month .'-'. ((int) $result['doc_no'] + 1);
        } else {
            $docNo = 'RR-' . $year. '-'. $month .'-1';
        }

        return $docNo;
    }

    public function reportPurchaseOrderItem($item_id,$date_from,$date_to){
        $stmtParams = array();
        $sqlWhere = 'WHERE i.id IS NOT NULL';

        if (!is_null($date_from) && $date_from !== 'null' && $date_from !== 'all' && !empty($date_from) && !is_null($date_to) && $date_to !== 'null' && $date_to !== 'all' && !empty($date_to)) {
            $sqlWhere .= ' AND pobid.`invoice_date` BETWEEN :date_from AND :date_to';
            $stmtParams['date_from'] = date('Y-m-d', strtotime(str_replace('-', '/', $date_from))) . ' 00:00:00';
            $stmtParams['date_to'] = date('Y-m-d', strtotime(str_replace('-', '/', $date_to))) . ' 00:00:00';

        }

        if(!is_null($item_id) && $item_id !== 'null' && $item_id !== 'all' && !empty($item_id) && is_numeric($item_id)) {

            $sqlWhere .= ' AND i.`id` = :item_id';
            $stmtParams['item_id'] = $item_id;
        }

        $sql = "SELECT
                  CONCAT(pobid.`quantity`,' ' ,iu.`description`) AS quantity,
                  i.`description` AS item,
                  DATE_FORMAT(pobid.`invoice_date`, '%m-%d-%Y') as invoiceDate,
                  pobid.`doc_no` AS docNo,
                  s.`description` AS supplier,
                  cis.`price` AS price,
                  (cis.`price` * pobid.`quantity`) AS totalAmount,
                  pobid.`id`,
                  i.`id` as itemId
				FROM `purchase_order_breakdown_item_delivery` pobid
				LEFT JOIN `purchase_order_breakdown_item` pobi ON pobid.`purchase_order_breakdown_item_id` = pobi.`id`
				LEFT JOIN `purchase_order_item` poi ON pobi.`purchase_order_item_id` = poi.`id`
				LEFT JOIN `canvass_item_supplier` cis ON poi.`canvass_item_supplier_id` = cis.`id`
				LEFT JOIN `canvass_item` ci ON cis.`canvass_item_id` = ci.`id`
				LEFT JOIN `material_requisition_item` mri ON ci.`material_requisition_item_id` = mri.`id`
				LEFT JOIN `supplier` s ON cis.`supplier_id` = s.`id`
				LEFT JOIN `item` i ON mri.`item_id` = i.`id`
				LEFT JOIN `item_unit` iu ON i.`item_unit_id` = iu.`id`
				$sqlWhere
                ";

        $stmt = $this->getEntityManager()->getConnection()->prepare($sql);
        $stmt->execute($stmtParams);
        $queryResults = $stmt->fetchAll();

        $results = array();
        foreach ($queryResults as $key => $queryResult){
            $results[$queryResult['itemId']]['item'][$key] = $queryResult;
            $results[$queryResult['itemId']]['description'] = $queryResult['item'];

        }

        return $results;
    }

    public function reportPurchaseOrderSupplier($supplier_id,$date_from,$date_to){
        $stmtParams = array();
        $sqlWhere = 'WHERE i.id IS NOT NULL';

        if (!is_null($date_from) && $date_from !== 'null' && $date_from !== 'all' && !empty($date_from) && !is_null($date_to) && $date_to !== 'null' && $date_to !== 'all' && !empty($date_to)) {
            $sqlWhere .= ' AND pobid.`invoice_date` BETWEEN :date_from AND :date_to';
            $stmtParams['date_from'] = date('Y-m-d', strtotime(str_replace('-', '/', $date_from))) . ' 00:00:00';
            $stmtParams['date_to'] = date('Y-m-d', strtotime(str_replace('-', '/', $date_to))) . ' 00:00:00';

        }

        if(!is_null($supplier_id) && $supplier_id !== 'null' && $supplier_id !== 'all' && !empty($supplier_id) && is_numeric($supplier_id)) {

            $sqlWhere .= ' AND s.`id` = :supplier_id';
            $stmtParams['supplier_id'] = $supplier_id;
        }

        $sql = "SELECT
                  CONCAT(pobid.`quantity`,' ' ,iu.`description`) AS quantity,
                  i.`description` AS item,
                  DATE_FORMAT(pobid.`invoice_date`, '%m-%d-%Y') as invoiceDate,
                  pobid.`doc_no` AS docNo,
                  s.`description` AS supplier,
                  cis.`price` AS price,
                  (cis.`price` * pobid.`quantity`) AS totalAmount,
                  pobid.`id`,
                  i.`id` as itemId
				FROM `purchase_order_breakdown_item_delivery` pobid
				LEFT JOIN `purchase_order_breakdown_item` pobi ON pobid.`purchase_order_breakdown_item_id` = pobi.`id`
				LEFT JOIN `purchase_order_item` poi ON pobi.`purchase_order_item_id` = poi.`id`
				LEFT JOIN `canvass_item_supplier` cis ON poi.`canvass_item_supplier_id` = cis.`id`
				LEFT JOIN `canvass_item` ci ON cis.`canvass_item_id` = ci.`id`
				LEFT JOIN `material_requisition_item` mri ON ci.`material_requisition_item_id` = mri.`id`
				LEFT JOIN `supplier` s ON cis.`supplier_id` = s.`id`
				LEFT JOIN `item` i ON mri.`item_id` = i.`id`
				LEFT JOIN `item_unit` iu ON i.`item_unit_id` = iu.`id`
				$sqlWhere
                ";

        $stmt = $this->getEntityManager()->getConnection()->prepare($sql);
        $stmt->execute($stmtParams);
        $queryResults = $stmt->fetchAll();

        $results = array();
        foreach ($queryResults as $key => $queryResult){
            $results[$queryResult['itemId']]['item'][$key] = $queryResult;
            $results[$queryResult['itemId']]['description'] = $queryResult['supplier'];

        }

        return $results;
    }

}
