<?php

class OrdersModel{
    const ID_ADDITONAL_TYPE = 3;
    private $headersHelper;
    const CUSTOMER_ACCEPTANCE_DAYS_INTERVAL = 15;
    const ID_INSTALLATION_CATEGORY = 2;

    function __construct(){
        $this->headersHelper =  new HeadersHelper();
        $this->orderActions = new OrderActions();
    }

    /**
     * Get the headers requried for the orders
     * @param  string $type type of the headere, posible values array or sql
     * @return string|array      returns the sql header or the array of for the headers
     */
    public function getOngoingOrdersHeaders( $type = 'array'){
        global $user;
        $userType = $user->getUserType();
        $data = [];

        switch($userType){
            case 'broker' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'o.idCustomerInstance' => 'idCustomerInstance',
                    'rclc.IdCustomer' => 'idCustomer',
                    'cust.name' => 'customer',
                    'rclc.idCommercialLead' => 'idCommercialLead',
                    'cl.name' => 'commercialLead',
                    'IFNULL(b.name, \'\')' => 'assignedTo',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cust.phone' => 'customerPhone',
                    'uc.mail' => 'customerMail',
                    'cl.phone' => 'commercialLeadPhone',
                    'ucl.mail' => 'commercialLeadMail',
                ];
            break;

            case 'customer' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'rclc.idCommercialLead' => 'idCommercialLead',
                    'cl.name' => 'commercialLead',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cl.phone' => 'commercialLeadPhone',
                    'ucl.mail' => 'commercialLeadMail'
                ];
            break;

            case 'commercial_lead' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'cl.idUser' => 'idCommercialLeadUser',
                    'cl.name' => 'commercialLeadName',
                    'o.idCustomerInstance' => 'idCustomerInstance',
                    'rclc.IdCustomer' => 'idCustomer',
                    'cust.name' => 'customer',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cust.phone' => 'customerPhone',
                    'uc.mail' => 'customerMail'
                ];
            break;

            case 'supplier' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.orderDate' => 'orderDate',
                    '\'\'' => 'orderItems',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cust.phone' => 'customerPhone',
                    'uc.mail' => 'customerMail'
                ];
            break;

            default :
            $headers = [
                'o.id' => 'id',
                'o.orderNumber' => 'orderNumber',
                'o.status' => 'status'
            ];
        }
        $data['headers'] = $this->headersHelper->getHeader($headers, $type);
        if($userType === USER_TYPES['BROKER']){
            $data['brokers'] = $this->getBrokers();
        }

        return $data;
    }

    public function getBrokers(){
        global $database, $user;

        $userType = $user->getUserType();
        if($userType !== USER_TYPES['BROKER']){
            return [];
        }

        $idUser = $user->getUserId();
        $sql = " SELECT b.id as idBroker,
                    CASE WHEN b.idUser=$idUser THEN 'Me' ELSE b.name END as brokerName
                    FROM ".TABLES['brokers']." b
                ORDER BY b.name";

        return $database->fetchResultArray($sql);
    }

    /**
     * get the list of orders
     * @return Array array of orders
     */
    public function getOngoingOrders(){
        global $database;
        global $user;

        $userType = $user->getUserType();
        $idUser = $user->getUserId();
        $headersSql = $this->getOngoingOrdersHeaders('sql')['headers'];
        $whereSql = "WHERE o.status!='production' AND o.status!='canceled' AND o.status!='end-of-life'";
        $extraSql = "";
        $isComercialLead = false;

        switch($userType){
            case 'broker' :
                $extraSql .= "LEFT OUTER JOIN ".TABLES['brokers']." b
                                    ON b.id=o.assignedTo";
            break;

            case 'customer' :
                $whereSql .= " AND cust.idUser=$idUser";
            break;

            case 'commercial_lead':
                $extraSql .= "INNER JOIN ".TABLES['users']." uclCompany
                                ON uclCompany.idCompany = ucl.idCompany
                                AND uclCompany.id = $idUser";
                $isComercialLead = true;
            break;

            case 'supplier' :
                $extraSql .= "INNER JOIN ".TABLES['rel_package_products']." rpp
                                ON rpp.idPackage=rop.idPackage AND rop.packageInstance=rpp.packageInstance
                            INNER JOIN ".TABLES['suppliers_countries_products']." scp
                                ON scp.idProduct=rpp.idProduct
                            INNER JOIN ".TABLES['suppliers']." s
                                ON s.id=scp.idSupplier";
                $whereSql .= " AND s.idUser=$idUser AND o.status='in-progress'";
            break;
        }

        $sql = "SELECT $headersSql
                FROM
                ".TABLES['orders']." o
                INNER JOIN
                ".TABLES['rel_commercial_lead_customers']." rclc ON o.idCustomerInstance = rclc.id
                INNER JOIN
                ".TABLES['customers']." cust ON cust.id = rclc.idCustomer
                INNER JOIN
                ".TABLES['commercial_leads']." cl ON cl.id = rclc.idCommercialLead
                INNER JOIN ".TABLES['rel_order_packages']." rop
                    ON rop.idOrder=o.id
                INNER JOIN ".TABLES['users']." ucl
                    ON ucl.id = cl.idUser
                INNER JOIN ".TABLES['users']." uc
                    ON uc.id = cust.idUser
                $extraSql
                $whereSql
                GROUP BY o.id
                ORDER BY o.orderDate DESC";

        $data = [];
        $orderPackages = $this->getOrderPackages(0, 'ongoing');
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $row['packages'] = isset($orderPackages[$row['id']]) ? $orderPackages[$row['id']] : [];
            if($isComercialLead) {
                $row['isMyOrder'] = $idUser === $row['idCommercialLeadUser'] ? true : false;
            }
            array_push($data, $row);
        }
        return $data;
    }

    /**
     * Get the headers requried for the orders history
     * @param  string $type type of the headere, posible values array or sql
     * @return string|array      returns the sql header or the array of for the headers
     */
    public function getOrdersHistoryHeaders( $type = 'array'){
        global $user;
        $userType = $user->getUserType();

        switch($userType){
            case 'broker' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'o.idCustomerInstance' => 'idCustomerInstance',
                    'rclc.IdCustomer' => 'idCustomer',
                    'cust.name' => 'customer',
                    'rclc.idCommercialLead' => 'idCommercialLead',
                    'cl.name' => 'commercialLead',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    'o.deliveryDate' => 'deliveryDate',
                    'MAX(rop.endOfLife)' => 'endOfLife',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cust.phone' => 'customerPhone',
                    'uc.mail' => 'customerMail',
                    'cl.phone' => 'commercialLeadPhone',
                    'ucl.mail' => 'commercialLeadMail'
                ];
            break;

            case 'customer' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'rclc.idCommercialLead' => 'idCommercialLead',
                    'cl.name' => 'commercialLead',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    'o.deliveryDate' => 'deliveryDate',
                    'MAX(rop.endOfLife)' => 'endOfLife',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cl.phone' => 'commercialLeadPhone',
                    'ucl.mail' => 'commercialLeadMail'
                ];
            break;

            case 'commercial_lead' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'cl.idUser' => 'idCommercialLeadUser',
                    'cl.name' => 'commercialLeadName',
                    'o.idCustomerInstance' => 'idCustomerInstance',
                    'rclc.IdCustomer' => 'idCustomer',
                    'cust.name' => 'customer',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    'o.deliveryDate' => 'deliveryDate',
                    'MAX(rop.endOfLife)' => 'endOfLife',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cust.phone' => 'customerPhone',
                    'uc.mail' => 'customerMail'
                ];
            break;

            case 'supplier' :
                $headers = [
                    'o.id' => 'id',
                    'o.orderNumber' => 'orderNumber',
                    'o.status' => 'status',
                    'o.reference' => 'reference',
                    'o.idCustomerInstance' => 'idCustomerInstance',
                    'rclc.IdCustomer' => 'idCustomer',
                    'cust.name' => 'customer',
                    'o.orderDate' => 'orderDate',
                    'o.estimatedDeliveryDate' => 'estimatedDeliveryDate',
                    'o.deliveryDate' => 'deliveryDate',
                    'MAX(rop.endOfLife)' => 'endOfLife',
                    '\'\'' => 'orderItems',
                    'SUM(rop.packageFixedPrice)' => 'orderTotalPrice',
                    'o.deliveryAddress' => 'deliveryAddress',
                    'cust.phone' => 'customerPhone',
                    'uc.mail' => 'customerMail'
                ];
            break;
        }

        return $this->headersHelper->getHeader($headers, $type);
    }

    /**
     * get the list of orders history
     * @return Array array of orders
     */
    public function getOrdersHistory(){
        global $database;
        global $user;

        $userType = $user->getUserType();
        $idUser = $user->getUserId();
        $headersSql = $this->getOrdersHistoryHeaders('sql');
        $whereSql = "WHERE (o.status='production' OR o.status='canceled' OR o.status='end-of-life')";
        $extraSql = '';
        $isComercialLead = false;

        switch($userType){
            case 'customer' :
                $whereSql .= " AND cust.idUser=$idUser";
            break;

            case 'commercial_lead':
                $extraSql .= "
                              INNER JOIN ".TABLES['users']." uclCompany
                                ON uclCompany.idCompany = ucl.idCompany
                                AND uclCompany.id = $idUser";
                $isComercialLead = true;
            break;
        }

        $sql = "SELECT $headersSql
                FROM
                    ".TABLES['orders']." o
                INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
                    ON o.idCustomerInstance=rclc.id
                INNER JOIN ".TABLES['customers']." cust
                    ON cust.id=rclc.idCustomer
                INNER JOIN ".TABLES['commercial_leads']." cl
                    ON cl.id=rclc.idCommercialLead
                INNER JOIN ".TABLES['rel_order_packages']." rop
                    ON rop.idOrder=o.id
                INNER JOIN ".TABLES['users']." ucl
                    ON ucl.id = cl.idUser
                INNER JOIN ".TABLES['users']." uc
                    ON uc.id = cust.idUser
                $extraSql
                $whereSql
                GROUP BY o.id
                ORDER BY o.orderDate DESC";

        $data = [];
        $orderPackages = $this->getOrderPackages(0, 'history');
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $row['packages'] = isset($orderPackages[$row['id']]) ? $orderPackages[$row['id']] : [];
            if($isComercialLead) {
                $row['isMyOrder'] = $idUser === $row['idCommercialLeadUser'] ? true : false;
            }
            array_push($data, $row);
        }

        return $data;
    }

    /**
     * get all comments for a specific order
     * @param  INT $idOrder id of the order
     * @return Array        Array of commnets for the order
     */
    private function getOrderComments($idOrder){
        global $database;

        $sql = "SELECT c.comment,
                c.addDate,
                u.username
                FROM ".TABLES['rel_order_comments']." c
                INNER JOIN ".TABLES['users']." u
                ON u.id=c.idUser
                WHERE c.idOrder=$idOrder
                ORDER BY c.addDate DESC";

        return $database->fetchResultArray($sql);
    }

    private function getOrderSelections($idOrder){
        global $database;
        $data = [];

        $sql = "SELECT
                    scp.productName,
                    os.idPackage,
                    pc.category
                FROM ".TABLES['suppliers_countries_products']." scp
                INNER JOIN ".TABLES['order_selections']." os
                    ON os.idProduct=scp.idProduct
                INNER JOIN ".TABLES['product_categories']." pc
                    ON pc.id=scp.idProductCategory
                WHERE os.idOrder=$idOrder";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['idPackage']][$row['category']][] = $row;
        }

        return $data;
    }

    /**
     * get all options linked to a package in an order
     * @param  INT $idOrder id for the order
     * @return Array        list of options grouped by packages
     */
    private function getOrderOptions($idOrder){
        global $database;
        $data = [];

        $sql = "SELECT
                    roep.idPackage,
                    p.name AS packageName,
                    pog.name AS groupName
                FROM ".TABLES['rel_order_extra_packages']." roep
                INNER JOIN ".TABLES['packages']." p
                    ON p.id=roep.idExtraPackage
                INNER JOIN ".TABLES['rel_group_options']." rgo
                    ON rgo.idOptionPackage=roep.idExtraPackage
                INNER JOIN ".TABLES['package_option_groups']." pog
                    ON pog.id=rgo.idGroup
                WHERE roep.idOrder=$idOrder";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['idPackage']][] = $row;
        }

        return $data;
    }

    private function getOrderAdditionalPackages($idOrder){
        global $database;
        $data = [];

        $sql = "SELECT
                    roep.idPackage,
                    p.name AS packageName
                FROM ".TABLES['rel_order_extra_packages']." roep
                INNER JOIN ".TABLES['packages']." p
                    ON p.id=roep.idExtraPackage
                WHERE roep.idOrder=$idOrder AND p.idPackageType=".self::ID_ADDITONAL_TYPE;
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['idPackage']][] = $row;
        }

        return $data;
    }

    private function getAvailalbleProcesses($idOrder){
        global $database;
        $data = [];

        $sql = "SELECT
                    proc.id AS idProcess,
                    proc.name AS processName
                    FROM ".TABLES['processes']." proc
                    INNER JOIN
                    (
                        SELECT DISTINCT p.idCountry
                        FROM ".TABLES['rel_order_packages']." rop
                        INNER JOIN ".TABLES['packages']." p
                            ON p.id=rop.idPackage
                        WHERE rop.idORder=$idOrder
                    ) c
                        ON c.idCountry=proc.idCountry
                    ORDER BY proc.name";
        $query = $database->query($sql) ;
        while($row = $database->fetchArray($query)){
            $data[] = $row;
        }

        return $data;
    }

    /**
     * get info for orders (details, packages, available processes)
     * @param  INT $idOrder id for the order
     * @return HashArray          array containtg info, packages, availableProcesses
     */
    public function getOrderInfo($idOrder){
        global $database;
        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $orderHelper = new OrderHelper();
        $orderDocuments = new OrderDocuments();

        if(!$orderHelper->checkOrderOwner($idOrder)){
            return [];
        }

        $sql = "SELECT o.id,
                o.orderNumber,
                o.orderDate,
                o.estimatedDeliveryDate,
                o.status,
                o.reference,
                o.tender,
                o.idTerms,
                IFNULL(b.name, 'Unassigned') as assignedTo,
                cust.name AS customer,
                cust.phone,
                u.mail,
                cl.name AS commercialLead,
                MAX(rop.endOfLife) AS endOfLife
                FROM
                ".TABLES['orders']." o
                LEFT OUTER JOIN ".TABLES['brokers']." b
                    ON b.id=o.assignedTo
                INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
                    ON o.idCustomerInstance=rclc.id
                INNER JOIN ".TABLES['customers']." cust
                    ON cust.id=rclc.idCustomer
                INNER JOIN ".TABLES['users']." u
                    ON u.id = cust.idUser
                INNER JOIN ".TABLES['commercial_leads']." cl
                    ON cl.id=rclc.idCommercialLead
                INNER JOIN ".TABLES['rel_order_packages']." rop
                    ON rop.idOrder=o.id
                WHERE o.id=$idOrder
                GROUP BY o.id
                LIMIT 1";
        $data['info'] = $database->fetchResultArray($sql);
        $data['products'] = $this->getOrderProducts($idOrder);
        $data['packages'] = $this->getOrderPackages($idOrder, 'all');
        $data['packages'] = count($data['packages']) && array_key_exists($idOrder, $data['packages']) ? $data['packages'][$idOrder] : [];
        $data['selections'] = $this->getOrderSelections($idOrder);
        $data['orderComments'] = $this->getOrderComments($idOrder);
        $data['orderOptions'] = $this->getOrderOptions($idOrder);
        $data['additionalPackages'] = $this->getOrderAdditionalPackages($idOrder);
        $data['orderDocuments'] = $orderDocuments->getOrderDocuments($idOrder);

        if(isset($data['info'][0]) && $data['info'][0]['status'] != 'canceled'){
            $data['availableProcesses'] = $this->getAvailalbleProcesses($idOrder);
        }else{
            $data['availableProcesses'] = [];
        }

        return $data;
    }

    /**
     * get products for packages in an order
     * @param  INT $idOrder id for the order
     * @return array        array with all products grouped by package and category
     */
    private function getOrderProducts($idOrder){
        global $database;

        $sql = "SELECT rcp.productName, pc.category, rpp.idPackage
                FROM ".TABLES['suppliers_countries_products']." rcp
                INNER JOIN product_categories pc
                    ON pc.id=rcp.idProductCategory
                INNER JOIN ".TABLES['rel_package_products']." rpp
                    ON rpp.idProduct=rcp.idProduct
                INNER JOIN ".TABLES['rel_order_packages']." rop
                    ON rop.idPackage=rpp.idPackage AND rop.packageInstance=rpp.packageInstance
                WHERE rop.idOrder=$idOrder
                ";
        $query = $database->query($sql);
        $data = [];
        while($row = $database->fetchArray($query)){
            $data[$row['idPackage']][$row['category']][] = $row;
        }

        return $data;
    }

    /**
     * get packages for the order
     * @param  INT $idOrder id for order
     * @return Array         packages array
     */
    private function getOrderPackages($idOrder = 0, $forOrders){
        global $database, $user;

        $whereSql = $idOrder === 0 ? "WHERE 1=1 " : "WHERE rop.idOrder=$idOrder ";
        $extraJoin = "";
        $extraFields = "";

        if($forOrders === 'history'){
            $whereSql .= "AND (o.status='production' OR o.status='canceled' OR o.status='end-of-life')";
            $extraFields = "IFNULL(rop.endOfLife, '') as endOfLife,
                            rop.units,
                            rop.packageFixedPrice,
                            rop.packageRecuringPrice,
                            rop.packageServicePrice,
                            rop.status,
                            pt.packagePayPeriod,
                            pt.servicesContractPeriod,
                            pt.maxContractPeriod,
                            pt.periodUnit,";
        }else if($forOrders === 'ongoing'){
            if($user->getUserType() === USER_TYPES['BROKER']){
                $extraJoin = "LEFT OUTER JOIN
                                (SELECT
                                        rops.idOrder,
                                        rops.idPackage,
                                        ps.shortDesc
                                    FROM
                                    ".TABLES['rel_order_process_step']." rops
                                    INNER JOIN ".TABLES['rel_process_steps']." rps
                                        ON rps.id = rops.idProcessStep
                                    INNER JOIN ".TABLES['process_step']." ps
                                        ON ps.id = rps.idStep
                                    WHERE
                                    rops.status ='in-progress'
                                ) ongoing_steps
                                    ON ongoing_steps.idOrder = rop.idOrder AND ongoing_steps.idPackage = rop.idPackage";
                $extraFields = "IFNULL(ongoing_steps.shortDesc, rop.status) AS shortDesc,
                                rop.units,
                                rop.packageFixedPrice,
                                rop.packageRecuringPrice,
                                rop.packageServicePrice,
                                rop.status,
                                pt.packagePayPeriod,
                                pt.servicesContractPeriod,
                                pt.maxContractPeriod,
                                pt.periodUnit,";
            }if($user->getUserType() === USER_TYPES['SUPPLIER']){
                $extraJoin = "INNER JOIN
                                (SELECT
                                        rops.idOrder,
                                        rops.idPackage,
                                        ps.shortDesc
                                    FROM
                                    ".TABLES['rel_order_process_step']." rops
                                    INNER JOIN ".TABLES['rel_process_steps']." rps
                                        ON rps.id = rops.idProcessStep
                                    INNER JOIN ".TABLES['process_step']." ps
                                        ON ps.id = rps.idStep
                                    INNER JOIN ".TABLES['process_step_actions']." psa
                                        ON psa.id=ps.idActionCode
                                    WHERE
                                    rops.status ='in-progress' AND psa.actionCode='procurement'
                                ) ongoing_steps
                                    ON ongoing_steps.idOrder = rop.idOrder AND ongoing_steps.idPackage = rop.idPackage";
                $extraFields = "IFNULL(ongoing_steps.shortDesc, rop.status) AS shortDesc,
                                rop.units,
                                rop.status,";
            }else{
                $extraJoin = "LEFT OUTER JOIN
                                ( SELECT
                                        done_steps.idOrder,
                                    	done_steps.idPackage,
                                    	ps.shortDesc
                                    FROM
                                        (SELECT
                                            rops.idOrder,
                                                rops.idPackage,
                                                MAX(rops.idProcessStep) AS idProcessStep
                                        FROM
                                            ".TABLES['rel_order_process_step']." rops
                                        INNER JOIN ".TABLES['rel_process_steps']." rps ON rps.id = rops.idProcessStep
                                        INNER JOIN ".TABLES['process_step']." ps ON ps.id = rps.idStep
                                        WHERE
                                            (rops.status = 'done'
                                                OR rops.status = 'in-progress')
                                                AND ps.isVisibleForCustomer = 1
                                        GROUP BY rops.idOrder , rops.idPackage) AS done_steps
                                            INNER JOIN
                                        ".TABLES['rel_process_steps']." rps ON rps.id = done_steps.idProcessStep
                                            INNER JOIN
                                        ".TABLES['process_step']." ps ON ps.id = rps.idStep
                                ) ongoing_steps
                                    ON ongoing_steps.idOrder = rop.idOrder AND ongoing_steps.idPackage = rop.idPackage";
                $extraFields = "IFNULL(ongoing_steps.shortDesc, rop.status) AS shortDesc,
                                rop.units,
                                rop.packageFixedPrice,
                                rop.packageRecuringPrice,
                                rop.packageServicePrice,
                                rop.status,
                                pt.packagePayPeriod,
                                pt.servicesContractPeriod,
                                pt.maxContractPeriod,
                                pt.periodUnit,";
            }

            $whereSql .= "AND (o.status!='production' AND o.status!='canceled' AND o.status!='end-of-life')";

        }else{
            $extraFields = "IFNULL(rop.endOfLife, '') as endOfLife,
                            rop.units,
                            rop.packageFixedPrice,
                            rop.packageRecuringPrice,
                            rop.packageServicePrice,
                            rop.status,
                            pt.packagePayPeriod,
                            pt.servicesContractPeriod,
                            pt.maxContractPeriod,
                            pt.periodUnit,";
        }

        $sql = "SELECT
                $extraFields
                rop.idOrder,
                pkg.id AS idPackage,
                pkg.name AS packageName
                FROM ".TABLES['packages']." pkg
                INNER JOIN ".TABLES['rel_order_packages']." rop
                ON rop.idPackage=pkg.id
                INNER JOIN ".TABLES['orders']." o
                ON o.id=rop.idOrder
                INNER JOIN ".TABLES['payment_types']." pt
                ON pt.id=rop.idPaymentTerm
                $extraJoin
                $whereSql";
        $data = [];
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['idOrder']][] = $row;
        }

        return $data;
    }

    /**
     * update the status for an existing schedule date
     * @param  INT $idSchedule id for schedule date
     * @param  string $status     new status for the schedule date
     * @return Array             update message
     */
    public function updateScheduleDateStatus($idSchedule, $status, $idOrder, $idPackage, $actionCode){
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->updateScheduleDateStatus($idSchedule, $status, $idOrder, $idPackage, $actionCode);
    }

    /**
     * get scheduled dates for a step
     * @param  INT $idOrder       id for the order
     * @param  INT $idPackage     id for the package
     * @param  INT $idProcessStep id for the process step
     * @return Array                array of schedueld dates
     */
    public function getScheduledDates($idOrder, $idPackage, $idProcessStep){
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->getScheduledDates($idOrder, $idPackage, $idProcessStep);
    }

    /**
     * get all steps for an order
     * @param  INT $idOrder id of the order
     * @return Array        list of steps for an order grouped by process and package
     */
    public function getOrderSteps($idOrder){
        $orderProcessHelper = new OrderProcessHelper();

        return $orderProcessHelper->getOrderSteps($idOrder);
    }

    private function getStepChilds($idProcessStep){
        global $database;

        $sqlChilds = "SELECT rps.id AS idProcessStep, psa.actionCode
                FROM ".TABLES['rel_process_steps']." rps
                INNER JOIN ".TABLES['process_step']." ps
                    ON ps.id=rps.idStep
                INNER JOIN ".TABLES['process_step_actions']." psa
                    ON psa.id=ps.idActionCode
                WHERE rps.idParent=$idProcessStep";

        return $database->fetchResultArray($sqlChilds);
    }

    public function updateOrdersEndOfLife(){
        global $database;
        $message = "";

        $sqlUpdatePackages = "UPDATE ".TABLES['rel_order_packages']." rop
                            INNER JOIN
                            (
                            	SELECT rop.idOrder, rop.idPackage
                            	FROM ".TABLES['rel_order_packages']." rop
                            	WHERE rop.endOfLife <= '".date('Y-m-d')."' and rop.status='production'
                            ) endOfLife
                            ON rop.idOrder=endOfLife.idOrder AND rop.idPackage=endOfLife.idPackage
                            SET status='end-of-life'";
        $query = $database->query($sqlUpdatePackages);
        $packagesUpdated = $database->affectedRows();
        $message = "Packages statuses updated: $packagesUpdated" . PHP_EOL;
        if($packagesUpdated > 0){
            $sqlOrders = "SELECT idOrder
                                FROM
                                (
                                	SELECT
                                	rop.idOrder,
                                	SUM(IF(rop.status = 'end-of-life', 1, 0)) as endOfLife,
                                	SUM(IF(rop.status = 'production', 1, 0)) as production,
                                    COUNT(rop.idPackage) as totalPackages
                                	FROM ".TABLES['rel_order_packages']." rop
                                	INNER JOIN ".TABLES['orders']." o
                                	   ON o.id=rop.idOrder
                                	WHERE o.status='production'
                                	GROUP BY rop.idOrder
                                ) packagesStatuses
                                WHERE packagesStatuses.endOfLife=packagesStatuses.totalPackages AND packagesStatuses.production=0";
            $query = $database->query($sqlOrders);

            if($database->numRows($query) > 0){
                $sqlUpdateOrders = "UPDATE orders
                                    SET status='end-of-life'
                                    WHERE id IN(";

                while($row = $database->fetchArray($query)){
                    $sqlUpdateOrders .= $row['idOrder'] . ",";
                }

                $sqlUpdateOrders = rtrim($sqlUpdateOrders, ',') . ')';
                $database->query($sqlUpdateOrders);
                $updatedOrders = $database->affectedRows();
                $message .= "Orders statuses updated: $updatedOrders" . PHP_EOL;
            }
        }

        return $message;
    }

    public function goToNextStep($idOrder, $idProcessStep, $ordersDetailsMail){
        $orderProcessHelper =  new OrderProcessHelper();

        return $orderProcessHelper->goToNextStep($idOrder, $idProcessStep, $ordersDetailsMail);
    }

    /**
     * undo a step
     * @param  INT $idOrder       id for the order
     * @param  INT $idProcessStep id for the process step
     * @return Array              update message
     */
    public function undoStep($idOrder, $idProcessStep){
        $orderProcessHelper = new OrderProcessHelper();

        return $orderProcessHelper->undoStep($idOrder, $idProcessStep);
    }

    /**
     * Insert packages for new orders
     * @param  Int $newIdOrder id for the new order
     * @param  array $packages   array with packages objects
     * @return int             number of packages inserted
     */
    private function insertPackagesToOrder($newIdOrder, $packages){
        global $database;

        $sqlInsOrderPackages = "INSERT INTO ".TABLES['rel_order_packages']."
                                (idOrder, idPackage, packageInstance, idPaymentTerm, units, packageFixedPrice, status)
                                VALUES";

        foreach ($packages as $package) {
            $packageInstance = $this->getLastInstanceOfPackage($package->idPackage);
            $sqlInsOrderPackages .= " (
                                        $newIdOrder,
                                        ".$package->idPackage.",
                                        ".$packageInstance.",
                                        ".$package->idPaymentTerm.",
                                        ".$package->units.",
                                        ".$package->packageFixedPrice.",
                                        'no-process'
                                    ),";
        }
        $sqlInsOrderPackages = rtrim($sqlInsOrderPackages, ',');
        $queryIns = $database->query($sqlInsOrderPackages);

        return $database->affectedRows();
    }

    /**
     * Get the last instance of the package to be added to an order
     * @param int $idPackage - the id of the package to be added
     * @return int the last instance of the package
     */
    private function getLastInstanceOfPackage($idPackage) {
        global $database;

        $sql = "SELECT
                  IFNULL(MAX(rpp.packageInstance), 0) AS lastInstance
                FROM
                 ".TABLES['rel_package_products']." rpp
                WHERE rpp.idPackage = $idPackage";
        $packageInstance = $database->fetchResultArray($sql);

        return $packageInstance[0]['lastInstance'];
    }

    /**
     * select a process for an order
     * @param INT $idOrder   id for the order
     * @param INT $idProcess id for process
     * @return Array update message
     */
    public function setProcessForOrder($idOrder, $idProcess, $ordersDetailsMail){
        $orderProcessHelper = new OrderProcessHelper();

        return $orderProcessHelper->setProcessForOrder($idOrder, $idProcess, $ordersDetailsMail, $this);
    }

    /**
     * Insert orderds in database
     * @param  object $orders orders object decoded from json
     * @return sting         message for orders update
     */
    private function insertOrders($orders){
        global $database;

        $message = "";
        $insertedOrders = 0;
        foreach ($orders as  $order) {
            $sqlInsOrder = "INSERT INTO ".TABLES['orders']."
                            (idCUstomerInstance, orderDate, status, deliveryAddress, reference)
                            VALUES (
                                ".$order->idCustomerInstance.",
                                '".$order->orderDate."',
                                'open',
                                '".$order->deliveryAddress."',
                                '".$order->reference."'
                            )
                            ON DUPLICATE KEY UPDATE
                            deliveryAddress=VALUES(deliveryAddress),
                            reference=VALUES(reference)";
            $queryIns = $database->query($sqlInsOrder);

            if($queryIns){
                $insertedOrders++;
                $newIdOrder = $database->getInsertId();

                $packagesInsert = $this->insertPackagesToOrder($newIdOrder, $order->packages);
                $message .= $packagesInsert ? $packagesInsert . " packages inserted" : "Package insert failed";
                $message .= " for order " . $newIdOrder . PHP_EOL;
                $message .= "-------------------------------------" . PHP_EOL;
            }
        }

        $message .= "Total orders inserted: ".$insertedOrders . PHP_EOL;
        $message .= "-------------------------------------" . PHP_EOL;

        return $message;
    }

    /**
     * Update the estimation for an order
     * @param  Int $idOrder        Id of the order to be modified
     * @param  String $estimationDate new date to be added for an order estimation
     * @return array                 resopnese message for the update
     */
    public function updateOrderEstimation($idOrder, $estimationDate){
        global $database;

        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $estimationDate = $database->escapeValue($estimationDate);
        $checkDate = $database->invalidDate('estimateDate', $estimationDate);
        if($checkDate){
            $data['messages'][] = $checkDate;
            return $data;
        }

        $sql = "UPDATE ".TABLES['orders']."
                SET estimatedDeliveryDate='$estimationDate'
                WHERE id=$idOrder
                LIMIT 1";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_ESTIMATION_UPDATED'
            ];
            $data['messages'][] = $message;

			$data['sendMail'] = [
                'message' => 'orderStatusChanged',
                'status' => 'estimated delivery date set',
                'estimatedDate' => $estimationDate
            ];
        }

        return $data;
    }

    public function updatePackageEndOfLife($idOrder, $idPackage, $endOfLife, $ordersDetailsMail){
        global $database;

        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $endOfLife = $database->escapeValue($endOfLife);
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $orderProcessHelper = new OrderProcessHelper();

        $checkDate = $database->invalidDate('endOfLife', $endOfLife);
        if($checkDate){
            $data['messages'][] = $checkDate;
            return $data;
        }

        $status = time() < strtotime($endOfLife) ? 'production' : 'end-of-life';

        $sql = "UPDATE ".TABLES['rel_order_packages']."
                SET endOfLife='$endOfLife',
                    status='$status'
                WHERE idOrder=$idOrder AND idPackage=$idPackage
                LIMIT 1";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'END_OF_LIFE_UPDATED'
            ];
            $data['messages'][] = $message;

            $ordersDetailsMail['status'] = $status;
            $data['messages'][] = $orderProcessHelper->sendConfirmationMail('packageStatusChanged', $ordersDetailsMail);
        }

        $orderStatusUpdated = $orderProcessHelper->updateOrderStatus($idOrder);

        if($orderStatusUpdated['orderUpdated'] > 0) {
            $message = [
                'code' => 'success',
                'message' => 'ORDER_UPDATED'
            ];
            $data['messages'][] = $message;
            $data['order'] = $orderStatusUpdated['orderUpdated'];

            $ordersDetailsMail['status'] = $orderStatusUpdated['status'];
            $data['messages'][] = $orderProcessHelper->sendConfirmationMail('orderStatusChanged', $ordersDetailsMail);
        }

        return $data;
    }

    /**
     * Update the estimation date for the follow up meeting from an order
     * @param  Int $idOrder        Id of the order to be modified
     * @param  Int $idProcessStep  id of the porcess to be modified
     * @param  String $estimationDate new date to be added for a follow up meeting
     * @param  String $confirmedDate  confirmed date with the customer to be added for a follow up meeting
     * @return array                 response message for the update
     */
    public function updateScheduledDates($idOrder, $idPackage, $idProcess, $idProcessStep, $idSchedule, $newDate) {
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->updateScheduledDates($idOrder, $idPackage, $idProcess, $idProcessStep, $idSchedule, $newDate);
    }

    /**
     * Update the actual date for an order
     * @param  Int $idOrder        Id of the order to be modified
     * @param  Int $idProcessStep  id of the porcess to be modified
     * @param  String $actualDate new date to be added for an order actual date step completed
     * @return array                 resopnese message for the update
     */
    public function updateStepActualDate($idOrder, $idProcessStep, $actualDate, $ordersDetailsMail) {
        $orderProcessHelper = new OrderProcessHelper();

        return $orderProcessHelper->updateStepActualDate($idOrder, $idProcessStep, $actualDate, $ordersDetailsMail);
    }

    /**
     * add a new commnet for an order
     * @param  INT $idOrder     Id of the order
     * @param  String $comment  commnet text
     * @return array            update message
     */
    public function updateOrderComment($idOrder, $comment, $ordersDetailsMail){
        global $database, $user;

        $data = [];
        $idOrder = $database->escapeValue($idOrder);
        $idUser = $user->getUserId();
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $orderProcessHelper = new OrderProcessHelper();

        $checkMessage = $database->isEmpty('comment', $comment);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }

        $checkMessage = $database->invalidLength('comment',$comment, 700);
        if($checkMessage){
            $data['messages'][] = $checkMessage;
        }

        if($data) {
            return $data;
        }

        $allowedLanguages = $this->getSystemAllowedLanguages();
        if(count($allowedLanguages) === 0) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'SYSTEM_ALLOWED_LANGUAGES_EMPTY'
            ];

            return $data;
        }
        $languageDetected = $this->getLanguageDetectResponse($comment);
        if(array_key_exists('language', $languageDetected)) {
            if(!in_array($languageDetected['language'], $allowedLanguages['code'])) {
                $data['messages'][] = [
                    'code' => 'error',
                    'message' => 'ALLOWED_LANGUAGE'
                ];
            }
        } else if(array_key_exists('languageNotReliable', $languageDetected)) {
            $data['messages'][] = [
                'code' => 'warning',
                'message' => 'ALLOWED_LANGUAGE'
            ];
        } else {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'ALLOWED_LANGUAGE_ERROR',
                'additionalMessage' => $languageDetected['error']
            ];

            return $data;
        }

        $sql = "INSERT INTO ".TABLES['rel_order_comments']."
                (idOrder, idUser, comment)
                VALUES ($idOrder, $idUser, '".$database->escapeValue($comment)."')";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_COMMENT_UPDATED'
            ];
            $data['messages'][] = $message;

            $ordersDetailsMail['commentMessage'] = $comment;
            $data['messages'][] = $orderProcessHelper->sendConfirmationMail('orderCommentAdded', $ordersDetailsMail);
        }

        return $data;
    }

    /**
     * returns an array with all the system allowed languages
     * @return Array all the system language allowed
     */
    public function getSystemAllowedLanguages() {
        global $database;
        $data = [];

        $sql = "
                SELECT
                  sal.languageCode AS languageCode,
                  sal.language AS language
                FROM
                  ".TABLES['system_allowed_languages']." sal";
        $query = $database->query($sql);

        while($row = $database->fetchArray($query)) {
            $data['code'][] = $row['languageCode'];
            $data['languages'][] = $row['language'];
        }

        return $data;
    }

    /**
     * get the language of the comment added or array if error
     * @param  String $comment  the comment added by the user
     * @return Array            the language detected or error
     */
    private function getLanguageDetectResponse($comment) {
        $data = [];
        $ch = curl_init();

        $plainText = html_entity_decode(strip_tags($comment));
        $plainTextComment = urlencode($plainText);
        $url = DETECT_LANGUAGE_API_URL.'?q='.$plainTextComment.'&key='.DETECT_LANGUAGE_API_KEY;

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_HEADER, false);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

        $response = json_decode(curl_exec($ch));
        if(curl_errno($ch)){
            $data['error'] = 'Curl error: ' . curl_error($ch);
        }

        curl_close($ch);

        if(gettype($response) === 'object' && $response->data && $response->data->detections) {
            $firstLanguageDetected = $response->data->detections[0];
            if($firstLanguageDetected->isReliable) {
                $data['language'] = $firstLanguageDetected->language;
            } else {
                $data['languageNotReliable'] = true;
            }
        }

        return $data;
    }

    /**
     * update commnet for a step
     * @param  int $idOrder       id of the order
     * @param  int $idProcessStep process step id
     * @param  String $comment       comment
     * @return arary               messages array
     */
    public function updateStepComment($idOrder, $idProcessStep, $comment, $isVisible, $ordersDetailsMail) {
        $orderProcessHelper = new OrderProcessHelper();

        return $orderProcessHelper->updateStepComment($idOrder, $idProcessStep, $comment, $isVisible, $ordersDetailsMail);
    }

    /**
     * update the visibility for a comment
     * @param  INT  $idComment id of the comment
     * @param  boolean $isVisible visibility for the step
     * @return Array             update message
     */
    public function updateStepCommentVisibility($idComment, $isVisible){
        $orderProcessHelper = new OrderProcessHelper();

        return $orderProcessHelper->updateStepCommentVisibility($idComment, $isVisible);
    }

    /**
     * update order status to cancel and disable steps
     * @param  int $idOrder id of the order
     * @return array          messages array
     */
    public function cancelOrder($idOrder, $ordersDetailsMail){
        global $database;

        $idOrder = $database->escapeValue($idOrder);
        $ordersDetailsMail = (array) json_decode($ordersDetailsMail);
        $data = [];
        $orderProcessHelper = new OrderProcessHelper();

        if($idOrder === 0){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;

            return $data;
        }

        $sql = "UPDATE ".TABLES['orders']."
                SET status='canceled'
                WHERE id=$idOrder
                LIMIT 1";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_CANCELED'
            ];
            $data['messages'][] = $message;

            $ordersDetailsMail['status'] = 'canceled';
            $data['messages'][] = $orderProcessHelper->sendConfirmationMail('orderStatusChanged', $ordersDetailsMail);
        }

        $sql = "UPDATE ".TABLES['rel_order_packages']."
                SET status='canceled'
                WHERE idOrder=$idOrder";
        $query = $database->query($sql);

        if($database->affectedRows() === 1){
            $message = [
                'code' => 'success',
                'message' => 'PACKAGES_STATUS_UPDATED'
            ];
            $data['messages'][] = $message;
        }else{
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        $sql = "UPDATE ".TABLES['rel_order_process_step']."
                SET status='inactive'
                WHERE idOrder=$idOrder AND status='in-progress'";
        $query = $database->query($sql);

        if(!$query){
            $err_mes = [
                'code' => 'error',
                'message' => 'SERVER_ERROR'
            ];
            $data['messages'][] = $err_mes;
        }

        if($database->affectedRows() > 0){
            $message = [
                'code' => 'success',
                'message' => 'ORDER_STEPS_DISABLED'
            ];
            $data['messages'][] = $message;
        }

        return $data;

    }

    public function assignBroker($idOrder, $idBroker){
        global $database;
        $idOrder = $database->escapeValue($idOrder);
        $idBroker = $database->escapeValue($idBroker);

        $sql = "UPDATE ".TABLES['orders']."
                SET assignedTo=$idBroker
                WHERE id=$idOrder";
        $query = $database->query($sql);

        if($database->affectedRows() > 0){
            $message = [
                'code' => 'success',
                'message' => 'BROKER_ASSIGNED'
            ];
            $data['messages'][] = $message;
        }else{
            $message = [
                'code' => 'warning',
                'message' => 'NO_CHANGES_ASSIGNED'
            ];
            $data['messages'][] = $message;
        }

        return $data;
    }

    private function getProcurementComponents($idOrder){
        global $database;
        $data = [];

        $sql = "SELECT scp.supplierProductNo,
                       comp.vatCode as supplierVAT,
                       comp.name AS supplierCompany,
                       s.name as supplierName,
                       p.name as packageName,
                       scp.manufacturerProductNo,
                       scp.productName,
                       supb.bidNumber,
                       scp.productDescription,
                       (rpp.quantity * rop.units) as units,
                       (scp.unitCostPrice * rpp.quantity * rop.units) as price,
                       (scp.unitVatCost * rpp.quantity * rop.units) as vatPrice,
                       pc.category,
                       u.mail,
                       s.phone,
                       s.contactPerson as contactPerson,
                       rope.estimatedDate as estimatedDeliveryDate,
                       rope.confirmedDate as confirmedDeliveryDate
                FROM ".TABLES['suppliers_countries_products']." scp
                INNER JOIN ".TABLES['suppliers']." s
                    ON s.id=scp.idSupplier
                INNER JOIN ".TABLES['users']." u
                    ON u.id=s.idUser
                INNER JOIN ".TABLES['company']." comp
                    ON comp.id=u.idCompany
                INNER JOIN ".TABLES['product_categories']." pc
                    ON pc.id=scp.idProductCategory
                INNER JOIN ".TABLES['rel_package_products']." rpp
                    ON rpp.idProduct=scp.idProduct
                INNER JOIN ".TABLES['rel_order_packages']." rop
                    ON rop.idPackage=rpp.idPackage AND rop.packageInstance=rpp.packageInstance
                INNER JOIN ".TABLES['packages']." p
                    ON p.id=rop.idPackage
                LEFT OUTER JOIN ".TABLES['rel_order_products_estimation']." rope
                    ON rope.idOrder=rop.idOrder AND rope.idPackage=rop.idPackage AND rope.idProduct=scp.idProduct
                LEFT OUTER JOIN ".TABLES['rel_bid_supplier_bids']." sbsb
    				ON sbsb.idBid=rop.idBid
                LEFT OUTER JOIN ".TABLES['supplier_bids']." supb
    				ON supb.id=sbsb.idSupplierBid AND supb.idProduct=scp.idProduct
                WHERE rop.idOrder=$idOrder
                ORDER BY s.name";
        $query = $database->query($sql);
        while($row = $database->fetchArray($query)){
            $data[$row['category']][] = $row;
        }

        return $data;
    }

    /**
     * genereate procurment file in excel format
     * @param  INT $idOrder id for the order
     * @return excel output output for the excel file
     */
    public function generateProcurementExcel($idOrder){
        global $database, $user;

        if($user->getUserType() !== USER_TYPES['BROKER']){
            trigger_error("Invalid user! You have no rights to access data for this order!", E_USER_ERROR);
        }

        $objPHPExcel = new PHPExcel();
        $sql = "SELECT c.name as customerName,
                       comp.vatCode,
                       comp.name as companyName,
                       o.orderNumber,
                       o.projectNumber,
                       o.deliveryAddress,
                       o.billingAddress,
                       o.reference
                FROM ".TABLES['orders']." o
                INNER JOIN ".TABLES['rel_commercial_lead_customers']." rclc
                    ON rclc.id=o.idCustomerInstance
                INNER JOIN ".TABLES['customers']." c
                    ON c.id=rclc.idCustomer
                INNER JOIN ".TABLES['users']." u
                    ON u.id=c.idUser
                INNER JOIN ".TABLES['company']." comp
                    ON u.idCompany=comp.id
                WHERE o.id=$idOrder
                LIMIT 1";
        $info = $database->fetchResultArray($sql);

        if(count($info) < 1){
            trigger_error("Invalid order! No information available!", E_USER_ERROR);
        }
        $info = $info[0];

        $objPHPExcel->getProperties()->setCreator("RICOH")
        							 ->setLastModifiedBy("Ricoh Dash")
        							 ->setTitle("Order Procurement Report")
        							 ->setSubject("Order Procurement Report")
        							 ->setDescription("Order Procurement Report")
        							 ->setKeywords("office 2007 openxml php order prcurement")
        							 ->setCategory("Procurement report file");

        $objPHPExcel->setActiveSheetIndex(0)
                    ->setCellValue('A1', 'Customer details')
                    ->setCellValue('A2', 'Name')
                    ->setCellValue('A3', 'Invoice address')
                    ->setCellValue('A4', 'VAT Number')
                    ->setCellValue('B2', $info['customerName'])
                    ->setCellValue('B3', $info['billingAddress'])
                    ->setCellValue('B4', $info['vatCode']);
        $objPHPExcel->getActiveSheet()->getStyle('A1')->getFont()->setBold(true);
        $objPHPExcel->setActiveSheetIndex(0)
                    ->setCellValue('A6', 'OrderDetails')
                    ->setCellValue('A7', 'Order number')
                    ->setCellValue('A8', 'Project number')
                    ->setCellValue('A9', 'Delivery addres')
                    ->setCellValue('A10', 'Reference')
                    ->setCellValue('B7', $info['orderNumber'])
                    ->setCellValue('B8', $info['projectNumber'])
                    ->setCellValue('B9', $info['deliveryAddress'])
                    ->setCellValue('B10', $info['reference']);
        $objPHPExcel->getActiveSheet()->getStyle('A6')->getFont()->setBold(true);

        $procurementComponents =  $this->getProcurementComponents($idOrder);
        $startRow = 12;
        $startColumn = 'A';

        foreach ($procurementComponents as $cateogry => $components) {
            $startColumn = 'A';
            $objPHPExcel->setActiveSheetIndex(0)
                        ->setCellValue($startColumn.$startRow, $cateogry);
            $objPHPExcel->getActiveSheet()->getStyle($startColumn.$startRow)->getFont()->setBold(true);
            $startRow += 2;

            foreach ($components as $index => $component) {
                $startColumn = 'A';
                if($index === 0){
                    $keys = array_keys($component);
                    foreach ($keys as $key) {
                        $objPHPExcel->setActiveSheetIndex(0)
                                    ->setCellValue($startColumn.$startRow, $key);
                        $objPHPExcel->getActiveSheet()->getStyle($startColumn.$startRow)->getFont()->setBold(true);
                        $objPHPExcel->getActiveSheet()->getColumnDimension($startColumn)->setAutoSize(true);
                        $startColumn++;
                    }

                    $startRow++;
                    $startColumn = 'A';
                }

                foreach ($component as $value) {
                    $objPHPExcel->setActiveSheetIndex(0)
                                ->setCellValue($startColumn.$startRow, $value);
                    $startColumn++;
                }
                $startRow++;
            }
            $startRow++;
        }

        $objPHPExcel->getActiveSheet()->setTitle('Order procurement');
        $objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
        header('Content-Disposition: attachment;filename="procurement_report_'.$info['orderNumber'].'.xlsx"');
        $objWriter->save('php://output');
    }

    /**
     * get all installation companies for the order and package selected
     * @param  Int $idOrder   id of the order
     * @param  Int $idPackage id of the package
     * @return Array          array with all the installation companies
     */
    public function getInstallCompaniesForPackage($idOrder, $idPackage) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->getInstallCompaniesForPackage($idOrder, $idPackage);
    }

    /**
     * save the installation company
     * @param  [type] $idOrder        [description]
     * @param  [type] $idPackage      [description]
     * @param  [type] $idInstallation [description]
     * @return [type]                 [description]
     */
    public function saveInstallationCompany($idOrder, $idPackage, $idInstallation) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->saveInstallationCompany($idOrder, $idPackage, $idInstallation);
    }

    /**
     * get customer questionaires / installation protocol for a specific order
     * @param  INT $idOrder  id for the order
     * @param  INT $idPackage id for the pacakge
     * @param  String $documentType the type of the documents needed - Order Questionaire or Installation protocol
     * @return Array            array of documents
     */
    public function getOrderDocumentsPerType($idOrder, $idPackage, $documentType){
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->getOrderDocumentsPerType($idOrder, $idPackage, $documentType);
    }

    /**
     * send mail to customer in case the quesioniare is not valid
     * @param  INT $idOrder    id of the order
     * @param  INT $idDocument id of the document
     * @return array           mail send message
     */
    private function sendQuesionnaireStatusMail($idOrder, $idDocument, $invalidQuestionaireReason){
        global $database;

        $customerInfo = UtilsModel::getDataForMailToCustomer($idOrder);

        $sqlDocInfo = "
                        SELECT d.id AS idDocument,
                            d.documentName,
                            d.extension
                        FROM ".TABLES['documents']." d
                        WHERE d.id=$idDocument
                        LIMIT 1";
        $query = $database->query($sqlDocInfo);
        $documentInfo = $database->fetchArray($query);
        $params = [
            'url' => WIAAS_URL.'/api-wiaas',
            'ordersUrl' => WIAAS_URL.'/orders/'.$idOrder,
            'orderNumber' => $customerInfo['orderNumber'],
            'idOrder' => $idOrder,
            'invalidQuestionaireReason' => preg_replace('#(\\\r|\\\r\\\n|\\\n)#', '<br/>', $invalidQuestionaireReason)
        ];

        $response = Mail::sendMail($customerInfo['mail'], 'Questionaire not valid', 'invalidQuestionnaireTemplate.php', $params);

        if($response){
            return [
                'code' => 'success',
                'message' => 'VALIDATION_MAIL'
            ];
        }

        return [
            'code' => 'error',
            'message' => 'ERROR_MAIL_SENT'
        ];
    }

    /**
     * update questionaire status
     * @param  INT $idOrder          id for the order
     * @param  INT $idPackage        id for the package
     * @param  INT $idDocument       id for the ducemnt
     * @param  INT $idProcessStep    id of the process step
     * @param  String $validationStatus document status (validated, not-validated, invalid)
     * @param  String $invalidQuestionaireReason    the reason why the questionaire is invalid
     * @return Array                  update message
     */
    public function validateQuestionaire($idOrder, $idPackage, $idDocument, $idProcessStep, $validationStatus, $invalidQuestionaireReason){
        global $database;

        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $idDocument = $database->escapeValue($idDocument);
        $idProcessStep = $database->escapeValue($idProcessStep);
        $validationStatus = $database->escapeValue($validationStatus);
        $invalidQuestionaireReason = $database->escapeValue($invalidQuestionaireReason);

        if($validationStatus !== 'validated' && $validationStatus !== 'invalid'){
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'INVALID_STAUTS'
            ];

            return $data;
        }

        if($validationStatus === 'invalid') {
            if(!$invalidQuestionaireReason) {
                $data['messages'][] = [
                    'code' => 'error',
                    'message' => 'REASON_EMPTY'
                ];

                return $data;
            }

            $msg = $database->invalidLength('REASON_LONG', $invalidQuestionaireReason, 700);
            if($msg) {
                $data['messages'][] = $msg;

                return $data;
            }
        }

        $sql = "UPDATE ".TABLES['rel_order_documents']."
                SET validation='$validationStatus'
                WHERE idOrder=$idOrder AND idPackage=$idPackage AND idDocument=$idDocument";
        $query = $database->query($sql);

        if($database->affectedRows()) {
            if($validationStatus === 'invalid'){
                $data['messages'][] = $this->saveInvalidReasonInDB($idOrder, $idPackage, $idProcessStep, $invalidQuestionaireReason);
                $data['messages'][] = $this->sendQuesionnaireStatusMail($idOrder, $idDocument, $invalidQuestionaireReason);
            }

            $data['messages'][] = [
                'code' => 'success',
                'message' => 'QUESTIONNAIRE_STATUS_UPDATED'
            ];
        } else {
            $data['messages'][] = [
                'code' => 'warning',
                'message' => 'NO_CHANGES_QUESTIONNAIRE'
            ];
        }

        return $data;
    }

    /**
     * save the reson of why the customer questionnaire is invalid
     * @param  INT $idOrder          id for the order
     * @param  INT $idPackage        id for the package
     * @param  INT $idProcessStep    id of the process step
     * @param  String $invalidQuestionaireReason    the reason of invalid questionnaire
     * @return Array                                update message
     */
    private function saveInvalidReasonInDB($idOrder, $idPackage, $idProcessStep, $invalidQuestionaireReason) {
        global $database, $user;

        $sql = "INSERT INTO ".TABLES['rel_step_comments']."
            (idProcessStep, idOrder, idPackage, idUser, comment, type)
            VALUES (
                    $idProcessStep,
                    $idOrder,
                    $idPackage,
                    ".$user->getUserId().",
                    '".$invalidQuestionaireReason."',
                    'invalidQuestionnaireComment'
                )
        ";
        $result = $database->query($sql);
        if($database->affectedRows() > 0) {
            $data = [
                'code' => 'success',
                'message' => 'REASON_SAVED'
            ];
        } else {
            $data = [
                'code' => 'error',
                'message' => 'REASON_SAVED_ERROR'
            ];
        }

        return $data;
    }

    /**
     * send mail to broker in case of new quesionnaire upload
     * @param  INT $idOrder    id of the order
     * @param  INT $idDocument id of the document
     * @return array           mail send message
     */
    private function sendQuesionnaireUploadMail($idOrder, $idDocument){
        global $database;

        $sqlCustomerInfo = "
                            SELECT o.orderNumber,
                                    GROUP_CONCAT(DISTINCT b.mail) AS mailList
                            FROM ".TABLES['orders']." o
                            INNER JOIN ".TABLES['brokers']." b
                                ON CASE WHEN o.assignedTo is NOT NULL THEN b.id=o.assignedTo ELSE 1=1 END
                            WHERE o.id=$idOrder AND b.mail is NOT NULL
                            GROUP BY o.id";
        $query = $database->query($sqlCustomerInfo);
        $brokerInfo = $database->fetchArray($query);

        $sqlDocInfo = "
                        SELECT d.id AS idDocument,
                            d.documentName,
                            d.extension
                        FROM ".TABLES['documents']." d
                        WHERE d.id=$idDocument
                        LIMIT 1";
        $query = $database->query($sqlDocInfo);
        $documentInfo = $database->fetchArray($query);
        $params = [
            'url' => WIAAS_URL.'/api-wiaas/utils/api/downloadFile?idDocument='.$documentInfo['idDocument'].'&fileName='.$documentInfo['documentName'].'.'.$documentInfo['extension'],
            'ordersUrl' => WIAAS_URL.'/api-wiaas/orders?subModule=orders_steps&idOrder='.$idOrder.'&orderNumber='.$brokerInfo['orderNumber'],
            'orderNumber' => $brokerInfo['orderNumber'],
            'idOrder' => $idOrder
        ];

        $mailList = trim($brokerInfo['mailList'], ',');
        $mailList = explode(',', $mailList);

        $response = Mail::sendMail($mailList, 'Modified questionaire uploaded', 'reUploadQuestionnaireTemplate.php', $params);

        if($response){
            return [
                'code' => 'success',
                'message' => 'RE_UPLOAD_MAIL'
            ];
        }

        return [
            'code' => 'error',
            'message' => 'ERROR_MAIL_SENT'
        ];
    }

    /**
     * get comments by type e.g stepComment, invalidQuestionaireComment, ...
     * @param  Int $idOrder       the id of the order
     * @param  Int $idPackage     the id of the package
     * @param  Int $idProcessStep the id of the process step
     * @param  String $type          the type of the comment: stepComment, invalidQuestionaireComment
     * @return Array                 the comments wanted
     */
    public function getCommentsByType($idOrder, $idPackage, $idProcessStep, $type) {
        global $database;
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $idProcessStep = $database->escapeValue($idProcessStep);
        $type = $database->escapeValue($type);
        $whereSql = $idPackage ? "AND rsc.idPackage=$idPackage" : "";
        $data = [];

        if(!$idOrder) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'ORDER_ID_MISSING'
            ];
        }

        if(!$idProcessStep) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'PROCESS_STEP_MISSING'
            ];
        }

        if(!$type) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'COMMENT_TYPE_MISSING'
            ];
        }

        if(array_key_exists('messages', $data) && count($data['messages'])) {
            return $data;
        }

        $sql = "
                SELECT  rsc.comment,
                        rsc.addDate,
                        u.username AS user
                FROM ".TABLES['rel_step_comments']." rsc
                INNER JOIN ".TABLES['users']." u
                    ON u.id = rsc.idUser
                WHERE rsc.idOrder=$idOrder

                    AND rsc.idProcessStep=$idProcessStep
                    AND rsc.type='$type'
        ";

        return $database->fetchResultArray($sql);
    }

    /**
     * upload again quesionnaire
     * @param  INT $idOrder    id for the order
     * @param  INT $idPackage  id for the package
     * @param  INT $idDocument id for the document
     * @param  file $file       file to be uploaded
     * @return Array            update message
     */
    public function reUploadQuestionaire($idOrder, $idPackage, $idDocument, $file){
        global $database, $user;
        $idOrder = $database->escapeValue($idOrder);
        $idPackage = $database->escapeValue($idPackage);
        $idDocument = $database->escapeValue($idDocument);
        $documentName = 'customerQuestionaire_'.$idOrder.'_'.$idPackage.'_'.date('Y_m_d');

        $fileManager = new FileManager();
        $data = $fileManager->updateDocument($idDocument, $file, $documentName);

        if(isset($data['messages'])){
            return $data;
        }
        $idDocument = $data['idDocument'];

        $sql = "UPDATE ".TABLES['rel_order_documents']."
                SET validation='not-validated'
                WHERE idOrder=$idOrder AND idPackage=$idPackage AND idDocument=$idDocument";
        $query = $database->query($sql);

        if($database->affectedRows() > 0){
            $data['messages'][] = $this->sendQuesionnaireUploadMail($idOrder, $idDocument);

            $data['messages'][] = [
                'code' => 'success',
                'message' => 'FILE_UPLOADED'
            ];
        }else{
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'NOT_UPLOADED'
            ];
        }

        return $data;
    }

    /**
     * get estimations for suppliers
     * @param  INT $idOrder   id for the order
     * @return Array          Array of products estimations
     */
    public function getSupplierEstimations($idOrder){
        $supplierEstimations = new SupplierEstimations();

        return $supplierEstimations->getSupplierEstimations($idOrder);
    }

    /**
     * get suppliers from package in order
     * @param  INT $idOrder   id for the order
     * @param  INT $idPackage id for the order
     * @param  String $documentType  the type of the document
     * @return Array          Array of products estimations
     */
    public function getSuppliersByPackageOrder($idOrder, $idPackage, $documentType){
        $procurement = new Procurement();

        return $procurement->getSuppliersByPackageOrder($idOrder, $idPackage, $documentType);
    }

    /**
     * remove order document
     * @param  INT $idOrder    id for order
     * @param  INT $idPackage  id for package
     * @param  INT $idDocument id for document
     * @return Array           remove message
     */
    public function removeOrderDocument($idOrder, $idPackage, $idDocument) {
        $orderDocuments = new OrderDocuments();

        return $orderDocuments->removeOrderDocument($idOrder, $idPackage, $idDocument);
    }

    /**
     * update dates for products in an order
     * @param  INT $idOrder       id for the order
     * @param INT $idSupplier     od for the supplier
     * @param  String $estimatedDate estimated date
     * @param  String $confirmedDate confirmed date
     * @return Array                update message
     */
    public function updateSupplierEstimation($idOrder, $idSupplier, $estimatedDate, $confirmedDate){
        $supplierEstimations = new SupplierEstimations();

        return $supplierEstimations->updateSupplierEstimation($idOrder, $idSupplier, $estimatedDate, $confirmedDate);
    }

    /**
     * update dates for products in an order
     * @param  INT $idOrder       id for the order
     * @param  INT $idSupplier     id for the product
     * @param  String $type       estiamtion or confirmation date
     * @return Array                update message
     */
    public function removeSupplierEstimation($idOrder, $idSupplier, $type){
        $supplierEstimations = new SupplierEstimations();

        return $supplierEstimations->removeSupplierEstimation($idOrder, $idSupplier, $type);
    }

    /**
     * add tracking number and url for order/package/supplier
     * @param  INT $idOrder       id for the order
     * @param  INT $idSupplier    id for the supplier
     * @param  String $trackingNumber traking id
     * @param  String $tracingUrl     tracking url
     * @return Array                update message
     */
    public function addTracking($idOrder, $idProduct, $trackingNumber, $trackingUrl){
        $orderTraking = new OrderTraking();

        return $orderTraking->addTracking($idOrder, $idProduct, $trackingNumber, $trackingUrl);
    }

    /**
     * update dates for products in an order
     * @param  INT $idTracking          id for the tracking info
     * @param  String $trackingNumber   traking id
     * @param  String $trackingUrl      traking url
     * @return Array                update message
     */
    public function updateTracking($idTracking, $trackingNumber, $trackingUrl){
        $orderTraking = new OrderTraking();

        return $orderTraking->updateTracking($idTracking, $trackingNumber, $trackingUrl);
    }

    /**
     * update dates for products in an order
     * @param  INT $idTracking          id for the tracking info
     * @return Array                update message
     */
    public function removeTracking($idTracking){
        $orderTraking = new OrderTraking();

        return $orderTraking->removeTracking($idTracking);
    }

    /**
     * upload a new file for configuration
     * @param  INT $idOrder    id for the order
     * @param  INT $idPackage  id for the package
     * @param  INT $idSupplier id for supplier
     * @param  STRING $fileType the type of the file (configuration or installation)
     * @param  FILE $file      file to be uploaded
     * @return Array           upload message
     */
    public function uploadInstallationDocument($idOrder, $idPackage, $idSupplier, $fileType, $file){
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->uploadInstallationDocument($idOrder, $idPackage, $idSupplier, $fileType, $file);
    }

    /**
     * upload a new file for configuration
     * @param  INT $idOrder    id for the order
     * @param  INT $idPackage  id for package
     * @param  INT $idSupplier id for supplier
     * @param  STRING $fileType the type of the file (configuration or installation)
     * @param  FILE $file      file to be uploaded
     * @return Array           upload message
     */
    public function uploadConfigurationDocument($idOrder, $idPackage, $idSupplier, $fileType, $file){
        $orderDocuments = new OrderDocuments();

        return $orderDocuments->uploadConfigurationDocument($idOrder, $idPackage, $idSupplier, $fileType, $file);
    }

    /**
     * get info for customer acceptance
     * @param  INT $idOrder    id for the order
     * @return Array           custoemr acceptance info
     */
    public function getCustomerAcceptance($idOrder){
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->getCustomerAcceptance($idOrder);
    }

    /**
     * upload customer acceptance document
     * @param  INT $idOrder   id for the order
     * @param  INT $idPackage id for the packages
     * @param  FILE $file     file to be uploaded
     * @return Array          upload status
     */
    public function uploadAcceptanceDocument($idOrder, $idPackage, $file){
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->uploadAcceptanceDocument($idOrder, $idPackage, $file);
    }

    /**
     * customer change acceptance status for a package
     * @param  INT $idOrder   id for the order
     * @param  INT $idPackage id for the packages
     * @param  String $actionType accept or decline the installation
     * @param  String $declineReason the reason for why the customer doesn't accept the installation
     * @return Array          update message
     */
    public function acceptDeclineInstallation($idOrder, $idPackage, $actionType, $declineReason){
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->acceptDeclineInstallation($idOrder, $idPackage, $actionType, $declineReason);
    }

    /**
     * check if send support mail is available (if user is customer and status of order is production)
     * @param  Int $idOrder  id of the order needed
     * @return boolean          true or false if send support mail is available
     */
    public function getAvailabilityForSendSupportMail($idOrder) {
        global $database, $user;
        $idOrder = $database->escapeValue($idOrder);

        if($user->getUserType() !== USER_TYPES['CUSTOMER'] || !$idOrder) {
            return false;
        }

        $sql = "
                SELECT
                  status
                FROM
                  ".TABLES['orders']." o
                WHERE o.id = $idOrder
                    AND o.status = 'production'
        ";

        $result = $database->query($sql);
        if($database->numRows($result) > 0) {
            return true;
        }

        return false;
    }

    /**
     * send an email to the support team from the customer
     * @param  Array $ordersInfo    the order informations like orderNumber, so on
     * @param  Array $orderPackages the packages contained in the order
     * @param  String $userText     the text writen by the customer
     * @return Array                confirmation message
     */
    public function sendSupportMail($ordersInfo, $orderPackages, $userText) {
        global $database, $user;
        $ordersInfo = (array) json_decode($ordersInfo);
        $orderPackages = json_decode($orderPackages);
        $userText = $database->escapeValue($userText);
        $mailSubject = "";

        if($user->getUserType() !== USER_TYPES['CUSTOMER']) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'MAIL_NOT_AUTHORIZED'
            ];

            return $data;
        }

        if(empty($userText)) {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'MAIL_TEXT_EMPTY'
            ];

            return $data;
        }


        $orderItems = '<div class="order-details-item">';
        foreach($orderPackages as $package) {
            $orderItems .= '<div class="send-support-mail-details">
                                <span class="glyphicon glyphicon-shopping-cart"></span>
                                ' . $package->units . ' x ' . $package->packageName . '
                            </div>
                            <div class="package-item-info">
                                <div class="send-support-mail-details">
                                    <b>Price: </b>
                                    '. $this->calculatePrice([$package->packageFixedPrice], $package->units) . '
                                    ( ' . $this->calculatePrice([$package->packageRecuringPrice, $package->packageServicePrice], $package->units) . '/ ' . $package->periodUnit . ')
                                </div>
                                <div class="prices-info">';

            if($package->packagePayPeriod > 0) {
                $orderItems .= '<div class="send-support-mail-details">
                                    Package recurent price: ' . $package->units . ' x ' . $package->packageRecuringPrice . ' / ' . $package->periodUnit .'
                                    for ' . $package->packagePayPeriod . ' ' . $package->periodUnit . '
                                </div>';
            }

            $orderItems .= '    <div class="send-support-mail-details">
                                    <b>Services and support</b>
                                    ' . $package->units . ' x ' . $package->packageServicePrice . ' / ' . $package->periodUnit;
            if($package->servicesContractPeriod > 0) {
                $orderItems .=      '<span>for ' . $package->servicesContractPeriod . ' ' . $package->periodUnit . '</span>';
            }

            $orderItems .=          'with possibility to extend each ' . $package->periodUnit . ' (Max ' . $package->maxContractPeriod . ')
                                </div>
                            </div>';

            if(intval($package->packagePayPeriod) > 0 || intval($package->servicesContractPeriod) > 0) {
                $orderItems .= '<div class="send-support-mail-details">
                                    <b>Agreement period: </b>';
                if(intval($package->packagePayPeriod) > 0) {
                    $orderItems .= '<div class="order-info-box">
                                        <b>Agreement for package: </b>
                                        ' . $package->packagePayPeriod . ' ' . $package->periodUnit . '
                                    </div>';
                }

                if(intval($package->servicesContractPeriod) > 0) {
                    $orderItems .= '<div class="order-info-box">
                                        <b>Agreement for services and support: </b>
                                        ' . $package->servicesContractPeriod . ' ' . $package->periodUnit . '
                                    </div>';
                }
                $orderItems .= '</div>';
            }

            if(property_exists($package, 'shortDesc') && $package->shortDesc) {
                $orderItems .= '<div class="send-support-mail-details">
                                    <b>Delivery active step: </b> ' . $package->shortDesc . '
                                </div>';
            }

            if($package->endOfLife) {
                $orderItems .= '<div class="send-support-mail-details">
                                    <b>End of life: </b> ' . $package->endOfLife . '
                                </div>';
            }

            $orderItems .= '<div class="package-item-status order-status-{{package.status}}">
                                <b>Status: </b> '. $package->status . '
                            </div>';
        }
        $orderItems .= '</div>';

        $params = [
            'orderNumber' => $ordersInfo['orderNumber'],
            'idOrder' =>  $ordersInfo['id'],
            'customerName' => $ordersInfo['customer'],
            'customerMail' => $ordersInfo['mail'],
            'customerPhone' => $ordersInfo['phone'],
            'reference' => $ordersInfo['reference'] || '-',
            'tender' => $ordersInfo['tender'] || '-',
            'commercialLead' => $ordersInfo['commercialLead'],
            'orderItems' => $orderItems,
            'userText' => preg_replace('#(\\\r|\\\r\\\n|\\\n)#', '<br/>', $userText)
        ];

        $currentDate = new DateTime();
        $currentDate = $currentDate->format('d-m-Y H:i');
        $mailSubject = "Support needed for " . $ordersInfo['orderNumber'] . " from " . $ordersInfo['customer'] . "(" . $currentDate . ")";

        $response = Mail::sendMail(SUPPORT_MAIL_LIST, $mailSubject, 'supportMailTemplate.php', $params);

        if($response){
            $data['messages'][] = [
                'code' => 'success',
                'message' => 'SUPPORT_MAIL_SENT'
            ];
        } else {
            $data['messages'][] = [
                'code' => 'error',
                'message' => 'ERROR_MAIL_SENT'
            ];
        }

        return $data;
    }

    /**
     * calculates the total price of given package and units
     * @param  Array $packagePrice the prices for each package in order
     * @param  Int $units          the quantity of same packages in order
     * @return Float               the total price for the order
     */
    private function calculatePrice($packagePrice, $units) {
        $total = 0;
        forEach($packagePrice as $val) {
            $total += (float) $val;
        }

        return $units ? ($total * intval($units)) : 0;
    }

    /**
     * sets the earliest installation date in DB
     * @param Int $idOrder                  id of the order
     * @param Int $idPackage                id of the package
     * @param String $maxDeliveryDate       maximumDeliveryDate
     * @return Array                        id of the order and package of the row inserted
     */
    public function setEarliestInstallationDateInDb($idOrder, $idPackage, $maxDeliveryDate) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->setEarliestInstallationDateInDb($idOrder, $idPackage, $maxDeliveryDate);
    }

    /**
     * returns the earliest installation date based on the maximum delivery date plus the additional days
     * @param  Int $idOrder             the id of the order
     * @param  Int $idPackage           the id of the package
     * @return Array                    the earliest installation date or error message
     */
    public function getEarliestInstallationDate($idOrder, $idPackage) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->getEarliestInstallationDate($idOrder, $idPackage);
    }

    /**
     * get installation dates for each package in order
     * @param  INT $idOrder       id for the order
     * @param  INT $idPackage     id for the package
     * @return Array                array of installation dates
     */
    public function getInstallationDates($idOrder, $idPackage){
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->getInstallationDates($idOrder, $idPackage);
    }

    /**
     * Update the estimation date for the installation
     * @param  Int $idOrder        Id of the order to be modified
     * @param  Int $idPackage      id of the package to be modified
     * @param  String $newDate     the date set by the user for the installation
     * @param  String $status      the status of the date to be added
     * @return array                 response message for the update
     */
    public function updateInstallationDate($idOrder, $idPackage, $newDate, $status) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->updateInstallationDate($idOrder, $idPackage, $newDate, $status);
    }

    /**
     * checks if there is at least one already accepted installation date
     * @param  Int $idOrder         the id of the order
     * @param  Int $idPackage       the id of the package
     * @return Boolean              true or false if the installation has an already accepted date
     */
    public function checkIfDateAlreadyAccepted($idOrder, $idPackage) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->checkIfDateAlreadyAccepted($idOrder, $idPackage);
    }

    /**
     * remove the date from the order package
     * @param  Int $idOrder          id of the order
     * @param  Int $idPackage        id of the package
     * @param  String $installationDate the installation date to be removed
     * @return Array                  confirmation messages
     */
    public function removeMyDate($idOrder, $idPackage, $installationDate) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->removeMyDate($idOrder, $idPackage, $installationDate);
    }

    public function checkIfIsNextStepWanted($idOrder, $stepsName) {
        $orderExtraActions = new orderExtraActions();

        return $orderExtraActions->checkIfIsNextStepWanted($idOrder, $stepsName);
    }

    /**
     * upload document for an order
     * @param  Int $idOrder        id of the order
     * @param  Int $idPackage      id of the package
     * @param  Int $idFileType     the id of the type of the file uploaded
     * @param  String $fileName    the name of the file
     * @param  FILE $file          file to be uploaded
     * @return Array               message with status
     */
    public function uploadOrderDocument($idOrder, $idPackage, $idDocumentType, $fileName, $file) {
        $orderHelper = new OrderHelper();

        return $orderHelper->uploadOrderDocument($idOrder, $idPackage, $idDocumentType, $fileName, $file);
    }

    /**
     * verifies if the installation dates are still valid after changing the earliest installation date
     * @param  Int  $idOrder                     id of the order
     * @param  Int  $idPackage                   id of the package
     * @param  String $earliestInstallationDate  empty if not passed or the earliest installation date set
     * @return Array                             array with update messages
     */
    public function checkIfInstallationDateIsValid($idOrder, $idPackage, $earliestInstallationDate) {
        $installationScheduling = new InstallationScheduling();

        return $installationScheduling->checkIfInstallationDateIsValid($idOrder, $idPackage, $earliestInstallationDate);
    }
}
