<?php
/**
 * The control file of order module of ZDOO.
 *
 * @copyright   Copyright 2009-2018 青岛易软天创网络科技有限公司(QingDao Nature Easy Soft Network Technology Co,LTD, www.cnezsoft.com)
 * @license     ZPL (http://zpl.pub/page/zplv12.html)
 * @author      Tingting Dai <daitingting@xirangit.com>
 * @package     order
 * @version     $Id$
 * @link        http://www.zdoo.com
 */
class order extends control
{
    /** 
     * The index page, locate to browse.
     * 
     * @access public
     * @return void
     */
    public function index()
    {   
        $this->locate(inlink('browse'));
    }   

    /**
     * Browse order.
     * 
     * @param string $mode
     * @param string $orderBy     the order by
     * @param int    $recTotal 
     * @param int    $recPerPage 
     * @param int    $pageID 
     * @access public
     * @return void
     */
    public function browse($mode = 'all', $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
    {
        $this->app->loadClass('pager', $static = true);
        $pager = new pager($recTotal, $recPerPage, $pageID);

        $orders = $this->order->getList($mode, '', $owner = 'all', $needQueryCondition = true, $orderBy, $pager);

        /* Set pre and next condition. */
        $this->session->set('orderList', $this->app->getURI(true));

        /* Set allowed edit order ID list. */
        $this->app->user->canEditOrderIdList = ',' . implode(',', $this->order->getOrdersSawByMe('edit', array_keys($orders))) . ',';

        /* Build search form. */
        $traders = '';
        if($this->session->orderForm)
        {
            foreach($this->session->orderForm as $formKey => $formValue)
            {
                if(strpos($formKey, 'field') !== false and $formValue == 'o.customer')
                {
                    $fieldNO  = substr($formKey, 5);
                    $traderID = $this->session->orderForm["value{$fieldNO}"];
                    $traders .= $traderID . ',';
                }
            }
        }
        $this->loadModel('search');
        $this->config->order->search['actionURL'] = inlink('browse', 'mode=bysearch');
        $this->config->order->search['params']['o.customer']['values'] = $this->loadModel('customer')->getPairs('client', $emptyOption = true, 'id_desc', $limit = $this->config->customerLimit, $traders);
        $this->config->order->search['params']['o.product']['values']  = array('' => '') + $this->loadModel('product')->getPairs();
        $this->search->setSearchParams($this->config->order->search);

        $this->view->title        = $this->lang->order->browse;
        $this->view->orders       = $orders;
        $this->view->users        = $this->loadModel('user')->getPairs();
        $this->view->pager        = $pager;
        $this->view->mode         = $mode;
        $this->view->orderBy      = $orderBy;
        $this->view->currencySign = $this->loadModel('common')->getCurrencySign();
        $this->view->currencyList = $this->common->getCurrencyList();
        if($orders) $this->view->totalAmount = $this->order->countAmount($orders);
        $this->display();
    }

    /**
     * Create an order.
     * 
     * @param  int    $customer
     * @access public
     * @return viod
     */
    public function create($customer = 0)
    {
        if($_POST)
        {
            $return = $this->order->create();

            if(!empty($return['result']) && $return['result'] == 'success')
            {
                $message = $this->executeHooks($return['orderID'], false);
                if($message) $return['message'] = $message;
            }

            return $this->send($return);
        }

        unset($this->lang->order->menu);
        $this->view->title             = $this->lang->order->create;
        $this->view->position[]        = $this->lang->order->create;
        $this->view->products          = array('') + $this->loadModel('product')->getPairs($status = 'normal');
        $this->view->customers         = $this->loadModel('customer')->getPairs('client', $emptyOption = true, $orderBy = 'id_desc', $limit = $this->config->customerLimit, $customer);
        $this->view->currencyList      = $this->loadModel('common')->getCurrencyList();
        $this->view->customer          = $customer;
        $this->view->mainCurrency      = $this->config->setting->mainCurrency;
        $this->view->subjects          = $this->loadModel('tree')->getOptionMenuByMajor();
        $this->view->productCategories = array('') + $this->tree->getOptionMenu('product', 0, true);
        $this->view->moduleMenu        = false;

        $this->display();
    }

    /**
     * Edit an order.
     * 
     * @param  int    $orderID 
     * @access public
     * @return void
     */
    public function edit($orderID)
    {
        $order = $this->order->getByID($orderID);
        $this->loadModel('common')->checkPrivByCustomer(empty($order)? '0' : $order->customer, 'edit');

        if($_POST)
        {
            $changes = $this->order->update($orderID);
            if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));

            $files = $this->loadModel('file')->saveUpload('order', $orderID);

            if(!empty($changes) or $files)
            {
                $comment = '';
                if($files) $comment = $this->lang->addFiles . join(',', $files);

                $actionID = $this->loadModel('action')->create('order', $orderID, 'Edited', $comment);
                $this->action->logHistory($actionID, $changes);

                $extra    = array('crm.order', 'view', "orderID=$orderID", $order->id);
                $actionID = $this->action->create('customer', $order->customer, 'editOrder', $comment, $extra);
                $this->action->logHistory($actionID, $changes);
            }

            return $this->send(array('result' => 'success', 'message' => $this->lang->saveSuccess, 'locate' => inlink('view', "orderID=$orderID")));
        }

        $this->view->title        = $this->lang->order->edit;
        $this->view->position[]   = $this->lang->order->edit;
        $this->view->order        = $order;
        $this->view->users        = $this->loadModel('user')->getPairs('nodeleted,noforbidden,noclosed');
        $this->view->products     = $this->loadModel('product')->getPairs($status = 'normal');
        $this->view->customer     = $this->loadModel('customer')->getByID($order->customer);
        $this->view->contract     = $this->order->getContract($orderID);
        $this->view->customers    = $this->customer->getPairs('client', $emptyOption = true, $orderBy = 'id_desc', $limit = $this->config->customerLimit, $order->customer);
        $this->view->currencyList = $this->common->getCurrencyList();
        $this->view->currencySign = $this->common->getCurrencySign();
        $this->view->moduleMenu   = false;

        $this->display();
    }

    /**
     * View an order.
     * 
     * @param  int $orderID 
     * @access public
     * @return void
     */
    public function view($orderID)
    {
        $order = $this->order->getByID($orderID);
        $this->loadModel('common')->checkPrivByCustomer(empty($order) ? '0' : $order->customer);

        /* Set allowed edit order ID list. */
        $this->app->user->canEditOrderIdList = ',' . implode(',', $this->order->getOrdersSawByMe('edit', (array)$orderID)) . ',';

        $this->app->loadLang('resume', 'crm');
        $this->app->loadLang('contract', 'crm');

        $uri = $this->app->getURI(true);
        $this->session->set('productList',  $uri);
        $this->session->set('contactList',  $uri);

        if(strpos($this->session->orderList, 'customer') === false and strpos($this->session->orderList, 'view') === false) $this->session->set('customerList', $this->app->getURI(true));
        if(strpos($this->session->orderList, 'contract') === false and strpos($this->session->orderList, 'view') === false) $this->session->set('contractList', $this->app->getURI(true));

        $this->view->title        = $this->lang->order->view;
        $this->view->position[]   = $this->lang->order->view;
        $this->view->customer     = $this->loadModel('customer')->getByID($order->customer);
        $this->view->contract     = $this->order->getContract($orderID);
        $this->view->users        = $this->loadModel('user')->getPairs();
        $this->view->currencySign = $this->common->getCurrencySign();
        $this->view->preAndNext   = $this->common->getPreAndNextObject('order', $orderID);
        $this->view->appOperate   = $this->order->buildAppOperateMenu($order);
        $this->view->order        = $order;
        $this->view->moduleMenu   = false;
    
        $this->executeHooks($orderID);
        $this->display();
    }
    
    /**
     * Close an order.
     * 
     * @param  int    $orderID 
     * @access public
     * @return void
     */
    public function close($orderID) 
    {
        $order = $this->order->getByID($orderID);
        $this->loadModel('common')->checkPrivByCustomer(empty($order)? '0' : $order->customer, 'edit');

        if(!empty($_POST))
        {
            $this->order->close($orderID);
            $this->loadModel('customer')->updateEditedDate($order->customer);
            if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));

            $comment = $this->lang->order->closedReason . $this->lang->order->closedReasonList[$this->post->closedReason] . '<br />' . $this->post->closedNote;
            $extra   = array('crm.order', 'view', "orderID=$orderID", $orderID);
            $this->loadModel('action')->create('order', $orderID, 'Closed', $this->post->closedNote, $this->lang->order->closedReasonList[$this->post->closedReason]);
            $this->action->create('customer', $order->customer, 'closeOrder', $comment, $extra);

            $message = $this->executeHooks($orderID);
            if(!$message) $message = $this->lang->saveSuccess;

            return $this->send(array('result' => 'success', 'message' => $message, 'locate' => $this->server->http_referer));
        }

        $this->view->title   = $this->lang->order->close;
        $this->view->order   = $order;
        $this->display();
    }

    /**
     * Activate an order.
     * 
     * @param  int    $orderID 
     * @access public
     * @return void
     */
    public function activate($orderID) 
    {
        $order = $this->order->getByID($orderID); 
        $this->loadModel('common')->checkPrivByCustomer(empty($order)? '0' : $order->customer, 'edit');

        if(!empty($_POST))
        {
            $this->order->activate($orderID);
            $this->loadModel('customer')->updateEditedDate($order->customer);
            if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));

            $extra = array('crm.order', 'view', "orderID=$orderID", $orderID);
            $this->loadModel('action')->create('order', $orderID, 'Activated', $this->post->note);
            $this->action->create('customer', $order->customer, 'activateOrder', $this->post->note, $extra);

            $message = $this->executeHooks($orderID);
            if(!$message) $message = $this->lang->saveSuccess;

            return $this->send(array('result' => 'success', 'message' => $message, 'locate' => $this->server->http_referer));
        }

        $this->view->title   = $this->lang->order->activate;
        $this->view->order   = $order;
        $this->view->users   = $this->loadModel('user')->getPairs('nodeleted,noforbidden,noclosed');
        $this->display();
    }

    /**
     * Get contact of an customer.
     *
     * @param  int    $order
     * @param  string $orderBy     the order by
     * @param  int    $recTotal 
     * @param  int    $recPerPage 
     * @param  int    $pageID 
     * @access public
     * @return void
     */
    public function contact($order, $orderBy = 'id_desc', $recTotal = 0, $recPerPage = 20, $pageID = 1)
    {
        $this->app->loadClass('pager', $static = true);
        $pager = new pager($recTotal, $recPerPage, $pageID);

        $order = $this->order->getByID($order);
        $contacts = $this->loadModel('contact', 'crm')->getList($order->customer, $relation = 'client', $mode = '', $status = 'normal', $origin = '', $orderBy, $pager);

        $this->view->title    = $this->lang->order->contact;
        $this->view->contacts = $contacts;
        $this->view->pager    = $pager;
        $this->view->orderBy  = $orderBy;

        $this->display();
    }

    /**
     * Assign an order function.
     *
     * @param  int    $orderID
     * @param  null   $table  
     * @access public
     * @return void
     */
    public function assign($orderID, $table = null)
    {
        $order   = $this->order->getByID($orderID);
        $members = $this->loadModel('user')->getPairs('noclosed,nodeleted,noforbidden');
        $this->loadModel('common')->checkPrivByCustomer(empty($order)? '0' : $order->customer, 'edit');

        if($_POST)
        {
            $this->order->assign($orderID);
            $this->loadModel('customer')->updateEditedDate($order->customer);
            if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));

            if($this->post->assignedTo)
            {
                $actionID = $this->loadModel('action')->create('order', $orderID, 'Assigned', $this->post->note, $this->post->assignedTo);
                $this->sendmail($orderID, $actionID);

                $comment = $this->lang->order->assignedTo . $members[$this->post->assignedTo] . '<br />' . $this->post->note;
                $extra   = array('crm.order', 'view', "orderID=$orderID", $orderID);
                $this->action->create('customer', $order->customer, 'assignOrder', $comment, $extra);
            }

            $message = $this->executeHooks($orderID);
            if(!$message) $message = $this->lang->saveSuccess;

            return $this->send(array('result' => 'success', 'message' => $message, 'locate' => $this->server->http_referer));
        }

        $this->view->title   = $this->lang->order->assignedTo;
        $this->view->order   = $order;
        $this->view->members = $members;
        $this->display();
    }

    /**
     * Batch assign orders.
     *
     * @access public
     * @return void
     */
    public function batchAssign()
    {
        if($_POST)
        {
            $customers = $this->loadModel('customer')->getCustomersSawByMe('edit');
            $orders    = $this->dao->select('id, customer')->from(TABLE_ORDER)->where('id')->in($this->post->orderIDList)->fetchPairs();

            foreach($orders as $order => $customer)
            {
                if(!isset($customers[$customer])) unset($orders[$order]);
            }

            if(empty($orders)) return $this->send(array('result' => 'fail', 'message' => $this->lang->order->batchAssignDeny));

            $order = new stdclass();
            $order->assignedTo   = $this->post->assignedTo;
            $order->assignedBy   = $this->app->user->account;
            $order->assignedDate = helper::now();
            $order->editedBy     = $this->app->user->account;
            $order->editedDate   = helper::now();

            $this->dao->update(TABLE_ORDER)->data($order)->where('id')->in(array_keys($orders))->exec();
            if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));

            $this->loadModel('action');
            $users = $this->loadModel('user')->getPairs();
            foreach($orders as $orderID => $customerID)
            {
                $actionID = $this->action->create('order', $orderID, 'Assigned', '', $this->post->assignedTo);
                $this->sendmail($orderID, $actionID);

                $comment = $this->lang->order->assignedTo . zget($users, $this->post->assignedTo);
                $extra   = array('crm.order', 'view', "orderID=$orderID", $orderID);
                $this->action->create('customer', $customerID, 'assignOrder', $comment, $extra);

                $message = $this->executeHooks($orderID);
            }
            if(!$message) $message = $this->lang->saveSuccess;

            return $this->send(array('result' => 'success', 'message' => $message, 'locate' => $this->server->http_referer));
        }

        die(js::alert($this->lang->order->noOrderSelected) . js::locate('back'));
    }

    /**
     * delete 
     * 
     * @param  int    $orderID 
     * @access public
     * @return void
     */
    public function delete($orderID)
    {
        $this->order->delete(TABLE_ORDER, $orderID);
        if(dao::isError()) return $this->send(array('result' => 'fail', 'message' => dao::getError()));

        $this->executeHooks($orderID);
        return $this->send(array('result' => 'success'));
    }

    /**
     * Send email.
     * 
     * @param  int    $orderID 
     * @param  int    $actionID 
     * @access public
     * @return void
     */
    public function sendmail($orderID, $actionID)
    {
        /* Reset $this->output. */
        $this->clear();

        /* Set toList and ccList. */
        $order  = $this->order->getByIdList($orderID);
        $users  = $this->loadModel('user')->getPairs();
        $order  = $order[$orderID];
        $toList = $order->assignedTo;

        /* send notice if user is online and return failed accounts. */
        $toList = $this->loadModel('action')->sendNotice($actionID, $toList);

        /* Get action info. */
        $action          = $this->action->getById($actionID);
        $history         = $this->action->getHistory($actionID);
        $action->history = isset($history[$actionID]) ? $history[$actionID] : array();

        /* Create the email content. */
        $this->view->order    = $order;
        $this->view->action   = $action;
        $this->view->users    = $users;
        $this->view->contract = $this->order->getContract($orderID);

        $mailContent = $this->parse($this->moduleName, 'sendmail');

        /* Send emails. */
        $this->loadModel('mail')->send($toList, 'ORDER#' . $order->id . ' ' . $order->title, $mailContent);
        if($this->mail->isError()) trigger_error(join("\n", $this->mail->getError()));
    }

    /**
     * Export orders.
     *
     * @param  string $mode         all | thisPage
     * @access public
     * @return void
     */
    public function export($mode = 'all')
    { 
        if($_POST)
        {
            $orderLang   = $this->lang->order;
            $orderConfig = $this->config->order;

            /* Create field lists. */
            $fields = explode(',', $orderConfig->list->exportFields);
            foreach($fields as $key => $fieldName)
            {
                $fieldName = trim($fieldName);
                $fields[$fieldName] = isset($orderLang->$fieldName) ? $orderLang->$fieldName : $fieldName;
                unset($fields[$key]);
            }

            $orders         = array();
            $queryCondition = $this->session->orderQueryCondition;
            if($queryCondition)
            {
                if($mode == 'all' && strpos($queryCondition, 'LIMIT') !== false) $queryCondition = substr($queryCondition, 0, strpos($queryCondition, 'LIMIT'));

                $stmt = $this->dbh->query($queryCondition);
                while($row = $stmt->fetch()) $orders[$row->id] = $row;
            }

            /* Get users, products and projects. */
            $users    = $this->loadModel('user')->getPairs();
            $products = $this->loadModel('product')->getPairs();

            foreach($orders as $order)
            {
                if(isset($order->products)) continue;
                $order->products = array();
                $productList = explode(',', $order->product);
                foreach($productList as $product) if(isset($products[$product])) $order->products[] = $products[$product];
            }

            foreach($orders as $order)
            {
                /* fill some field with useful value. */
                if(isset($orderLang->statusList[$order->status]))             $order->status       = $orderLang->statusList[$order->status];
                if(isset($orderLang->closedReasonList[$order->closedReason])) $order->closedReason = $orderLang->closedReasonList[$order->closedReason];
                if(isset($this->lang->currencyList[$order->currency]))        $order->currency     = $this->lang->currencyList[$order->currency];

                if(isset($users[$order->createdBy]))   $order->createdBy   = $users[$order->createdBy];
                if(isset($users[$order->editedBy]))    $order->editedBy    = $users[$order->editedBy];
                if(isset($users[$order->assignedTo]))  $order->assignedTo  = $users[$order->assignedTo];
                if(isset($users[$order->assignedBy]))  $order->assignedBy  = $users[$order->assignedBy];
                if(isset($users[$order->signedBy]))    $order->signedBy    = $users[$order->signedBy];
                if(isset($users[$order->activatedBy])) $order->activatedBy = $users[$order->activatedBy];
                if(isset($users[$order->contactedBy])) $order->contactedBy = $users[$order->contactedBy];
                if(isset($users[$order->closedBy]))    $order->closedBy    = $users[$order->closedBy]; 

                $order->createdDate   = formatTime($order->createdDate, DT_DATE1);
                $order->editedDate    = formatTime($order->editedDate, DT_DATE1);
                $order->assignedDate  = formatTime($order->assignedDate, DT_DATE1);
                $order->signedDate    = formatTime($order->signedDate, DT_DATE1);
                $order->activatedDate = formatTime($order->activatedDate, DT_DATE1);
                $order->contactedDate = formatTime($order->contactedDate, DT_DATE1);
                $order->nextDate      = formatTime($order->nextDate, DT_DATE1);
                $order->closedDate    = formatTime($order->closedDate, DT_DATE1);

                $order->customer = $order->customerName;
                if(!empty($order->products)) $order->product = join("; \n", $order->products);
            }

            $this->post->set('fields', $fields);
            $this->post->set('rows', $orders);
            $this->post->set('kind', 'order');
            $this->fetch('file', 'export2CSV' , $_POST);
        }

        $this->view->fileName = $this->lang->order->list;
        $this->display();
    }

    /**
     * ajax get orders this week need conect. 
     * 
     * @param  string $account   not used.
     * @param  string $id 
     * @param  string $type      select|json|board
     * @access public
     * @return void
     */
    public function ajaxGetTodoList($account = '', $id = '', $type = 'select')
    {
        if($account == '') $account = $this->app->user->account;

        $orders = array();
        $customerIdList  = $this->loadModel('customer')->getCustomersSawByMe();
        $products        = $this->loadModel('product')->getPairs();
        $datingOrderList = $this->dao->select('objectID')->from(TABLE_DATING)
            ->where('account')->eq($account)
            ->andWhere('objectType')->eq('order')
            ->andWhere('status')->eq('wait')
            ->orderBy('date')
            ->fetchPairs();

        $sql = $this->dao->select('o.id, o.product, o.createdDate, c.name as customerName')->from(TABLE_ORDER)->alias('o')
            ->leftJoin(TABLE_CUSTOMER)->alias('c')->on("o.customer=c.id")
            ->where('o.deleted')->eq('0')
            ->andWhere('o.assignedTo')->eq($account)
            ->andWhere('o.id')->in($datingOrderList)
            ->andWhere('o.customer')->in($customerIdList)
            ->orderBy('o.id_desc');

        $stmt = $sql->query();
        while($order = $stmt->fetch())
        {    
            $order->products = array();
            $productList = explode(',', $order->product);
            foreach($productList as $product) if(isset($products[$product])) $order->products[] = $products[$product];
            $productName  = count($order->products) > 1 ? current($order->products) . $this->lang->etc : current($order->products);
            $order->title = sprintf($this->lang->order->titleLBL, $order->customerName, $productName, date('Y-m-d', strtotime($order->createdDate))); 
            $orders[$order->id] = $order->title;
        } 

        if($type == 'select')
        {
            $orders = array('') + $orders;
            if($id) die(html::select("idvalues[$id]", $orders, '', 'class="form-control"'));
            die(html::select('idvalue', $orders, '', 'class=form-control'));
        }
        if($type == 'board')
        {
            die($this->loadModel('todo')->buildBoardList($orders, 'order'));
        }

        return json_encode($orders);
    }

    /**
     * Get orders by ajax. 
     * 
     * @param  int    $customer 
     * @access public
     * @return void
     */
    public function ajaxGetOrders($customer)
    {
        $html   = '<option></option>';
        $orders = $this->order->getPairs($customer);
        foreach($orders as $id => $name)
        {
            $html .= "<option value='$id'>$name</option>";
        }

        echo $html;
    }

    /**
     * Get option menu by ajax.
     *
     * @param  int    $customer
     * @access public
     * @return void
     */
    public function ajaxGetOptionMenu($customer)
    {
        $orders = $this->order->getListByCustomer($customer);

        echo "<option value=''></option>";
        foreach($orders as $order)
        {
            if(!$order) continue;
            echo "<option value='{$order->id}' data-customer='{$order->customer}' data-amount='{$order->real}'>{$order->title}</option>";
        }
        exit;
    }

    /**
     * Search order by ajax.
     *
     * @param  string $key
     * @param  string $orders
     * @access public
     * @return void
     */
    public function ajaxSearchOrder($key = '', $orders = '')
    {
        $this->view->title  = $this->lang->order->search;
        $this->view->key    = $key;
        $this->view->orders = $orders;
        $this->display();
    }

    /**
     * Ajax get order pairs.
     *
     * @param  string $key
     * @param  int    $limit
     * @access public
     * @return void
     */
    public function ajaxGetPairs($key = '', $limit = 0)
    {
        $i      = 0;
        $result = array();
        if(!$limit) $limit = $this->config->searchLimit;
        $orders = $this->order->getPairs();
        foreach($orders as $id => $order)
        {
            if($limit > 0 && $i > $limit) break;
            if(stripos($order,  $key) !== false)
            {
                $result[$id] = $order;
                $i++;
            }
        }
        if($i < 1)
        {
            $result['info'] = $this->lang->noResultsMatch;
        }

        die(json_encode($result));
    }
}
