<?php
/*******************************************************************************

    Copyright 2010 Whole Foods Co-op

    This file is part of CORE-POS.

    CORE-POS is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.

    CORE-POS is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    in the file license.txt along with IT CORE; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

*********************************************************************************/

include(dirname(__FILE__) . '/../../config.php');
if (!class_exists('FannieAPI')) {
    include_once(__DIR__ . '/../../classlib2.0/FannieAPI.php');
}

class TenderEditor extends FannieRESTfulPage 
{
    protected $title = "Fannie : Tenders";
    protected $header = "Tenders";
    protected $must_authenticate = True;
    protected $auth_classes = array('tenders');
    public $description = '[Tenders] creates and updates tender types.';
    public $has_unit_tests = true;

    public function preprocess()
    {
        $this->addRoute('post<id><saveCode>');
        $this->addRoute('post<id><saveName>');
        $this->addRoute('post<id><saveType>');
        $this->addRoute('post<id><saveCMsg>');
        $this->addRoute('post<id><saveMin>');
        $this->addRoute('post<id><saveMax>');
        $this->addRoute('post<id><saveRLimit>');
        $this->addRoute('post<id><saveModule>');
        $this->addRoute('post<id><saveSalesCode>');
        $this->addRoute('post<newTender>');

        return parent::preprocess();
    }

    private $model = null;
    protected function getTenderModel($id=false)
    {
        if ($this->model === null) {
            $this->connection->selectDB($this->config->get('OP_DB')); 
            $this->model = new TendersModel($this->connection);
        }
        if ($id !== false) {
            $this->model->TenderID($id);
        }

        return $this->model;
    }

    protected function post_id_saveCode_handler()
    {
        $this->connection->selectDB($this->config->get('OP_DB')); 
        $tester = new TendersModel($this->connection);
        $tester->TenderCode($this->saveCode);
        $tester->TenderID($this->id, '<>');
        if (count($tester->find()) > 0) {
            echo "Error: Code " . $this->saveCode . " is already in use";
        } else {
            $model = $this->getTenderModel($this->id);
            $model->TenderCode($this->saveCode);
            $model->save();
        }

        return false;
    }

    protected function post_id_saveName_handler()
    {
        $model = $this->getTenderModel($this->id);
        $model->TenderName($this->saveName);
        $model->save();

        return false;
    }

    protected function post_id_saveType_handler()
    {
        $model = $this->getTenderModel($this->id);
        $model->TenderType($this->saveType);
        $model->save();

        return false;
    }

    protected function post_id_saveCMsg_handler()
    {
        $model = $this->getTenderModel($this->id);
        $model->ChangeMessage($this->saveCMsg);
        $model->save();

        return false;
    }

    protected function post_id_saveMin_handler()
    {
        if (!is_numeric($this->saveMin)) {
            echo "Error: Minimum must be a number";
        } else {
            $model = $this->getTenderModel($this->id);
            $model->MinAmount($this->saveMin);
            $model->save();
        }

        return false;
    }

    protected function post_id_saveMax_handler()
    {
        if (!is_numeric($this->saveMax)) {
            echo "Error: Maximum must be a number";
        } else {
            $model = $this->getTenderModel($this->id);
            $model->MaxAmount($this->saveMax);
            $model->save();
        }

        return false;
    }

    protected function post_id_saveRLimit_handler()
    {
        if (!is_numeric($this->saveRLimit)) {
            echo "Error: Refund limit must be a number";
        } else {
            $model = $this->getTenderModel($this->id);
            $model->MaxRefund($this->saveRLimit);
            $model->save();
        }

        return false;
    }

    protected function post_id_saveModule_handler()
    {
        if (is_numeric($this->saveModule)) {
            echo "Error: Module must be text";
        } else {
            $model = $this->getTenderModel($this->id);
            $model->TenderModule($this->saveModule);
            $model->save();
        }

        return false;
    }

    protected function post_id_saveSalesCode_handler()
    {
        if (!is_numeric($this->saveSalesCode)) {
            echo "Error: account # must be a number";
        } else {
            $model = $this->getTenderModel($this->id);
            $model->SalesCode($this->saveSalesCode);
            $model->save();
        }

        return false;
    }

    protected function post_newTender_handler()
    {
        $dbc = $this->connection;
        $dbc->selectDB($this->config->get('OP_DB'));
        $newID=1;
        $idQ = $dbc->prepare("SELECT MAX(TenderID) FROM " . FannieDB::fqn('tenders', 'op'));
        $idR = $dbc->execute($idQ);
        if ($dbc->numRows($idR) > 0){
            $idW = $dbc->fetchRow($idR);
            if (!empty($idW[0])) $newID = $idW[0] + 1;
        }

        $model = new TendersModel($dbc);
        $model->TenderID($newID);
        $model->TenderName('NEW TENDER');
        $model->TenderType('CA');
        $model->MinAmount(0);
        $model->MaxAmount(500);
        $model->MaxRefund(0);
        $model->save();
        
        echo $this->getTenderTable();

        return false;
    }

    private function getTenderTable()
    {
        $this->connection->selectDB($this->config->get('OP_DB'));
        $model = new TendersModel($this->connection);
        
        $ret = '<table class="table">
            <tr><th>Code</th><th>Name</th><th>Change Type</th>
            <th>Change Msg</th><th>Min</th><th>Max</th>
            <th>Refund Limit</th><th>TenderModule</th><th>Account #</th></tr>';

        foreach($model->find('TenderID') as $row){
            $ret .= sprintf('<tr>
                <td><input size="2" maxlength="2" value="%s"
                    class="form-control"
                    onchange="tenderEditor.saveCode.call(this, this.value,%d);" /></td>
                <td><input size="10" maxlength="255" value="%s"
                    class="form-control"
                    onchange="tenderEditor.saveName.call(this, this.value,%d);" /></td>
                <td><input size="2" maxlength="2" value="%s"
                    class="form-control"
                    onchange="tenderEditor.saveType.call(this, this.value,%d);" /></td>
                <td><input size="10" maxlength="255" value="%s"
                    class="form-control"
                    onchange="tenderEditor.saveCMsg.call(this, this.value,%d);" /></td>
                <td class="col-sm-1"><div class="input-group">
                    <span class="input-group-addon">$</span>
                    <input size="6" maxlength="10" value="%.2f"
                    class="form-control price-field"
                    onchange="tenderEditor.saveMin.call(this, this.value,%d);" />
                </div></td>
                <td class="col-sm-1"><div class="input-group">
                    <span class="input-group-addon">$</span>
                    <input size="6" maxlength="10" value="%.2f"
                    class="form-control price-field"
                    onchange="tenderEditor.saveMax.call(this, this.value,%d);" />
                </div></td>
                <td class="col-sm-1"><div class="input-group"><span class="input-group-addon">$</span>
                    <input size="6" maxlength="10" value="%.2f"
                    class="form-control price-field"
                    onchange="tenderEditor.saveRLimit.call(this, this.value,%d);" />
                <td><input size="10" maxlength="50" value="%s"
                    class="form-control"
                    onchange="tenderEditor.saveModule.call(this, this.value,%d);" /></td>
                <td><input size="10" value="%s"
                    class="form-control"
                    onchange="tenderEditor.saveSalesCode.call(this, this.value, %d);" /></td>
                </tr>',
                $row->TenderCode(),$row->TenderID(),
                $row->TenderName(),$row->TenderID(),
                $row->TenderType(),$row->TenderID(),
                $row->ChangeMessage(),$row->TenderID(),
                $row->MinAmount(),$row->TenderID(),
                $row->MaxAmount(),$row->TenderID(),
                $row->MaxRefund(),$row->TenderID(),
                $row->TenderModule(),$row->TenderID(),
                $row->SalesCode(),$row->TenderID()
            );
        }
        $ret .= "</table>";
        $ret .= "<p>";
        $ret .= '<button type="button" class="btn btn-default" onclick="tenderEditor.addTender();return false;">Add a new tender</button>';
        $ret .= "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;";
        $ret .= '<button type="button" class="btn btn-default" onclick="location=\'DeleteTenderPage.php\';">Delete a tender</button>';
        $ret .= '</p>';
        return $ret;
    }

    function get_view()
    {
        $this->addScript('edit.js');
        $ret = '<div id="alert-area"></div>';
        $ret .= '<div id="mainDisplay">';
        $ret .= $this->getTenderTable();
        $ret .= '</div>';
        return $ret;
    }

    public function helpContent()
    {
        return '<p>Tenders are different kinds of payment the store accepts.
            Each field saves when changed.</p>
            <ul>
                <li><em>Code</em> is the two letter code used by cashiers to enter
                the tender. These codes must be unique. While they are editable, using
                the defaults defined in sample tenders is recommended. In particular,
                changing CA, MI, CP, IC, EF, or FS could lead to oddities.</li>
                <li><em>Name</em> appears on screen and on receipt.</li>
                <li><em>Change Type</em> is the tender code used when the amount tendered
                exceeds the amount due resulting in a change line. Cash (CA) is
                most common.</li>
                <li><em>Change Msg</em> appears on screen and receipts for change lines.</li>
                <li><em>Min</em> and <em>Max</em> are soft limits. Attempting to tender 
                an amount outside that range results in a warning.</li>
                <li><em>Refund Limit</em> is a soft limit on the maximum allowed refund.
                Attempting to refund a larger amount results in a warning.</li>
                <li><em>Account #</em> is provided for accounting purposes. The value here
                will appear as a chart of accounts number in reports of tender activity.</li>
            </ul>';
    }

    /**
      Create a new tender
      Change & verify all fields of sample data tenderID=1
    */
    public function unitTest($phpunit)
    {
        $get = $this->get_view();
        $phpunit->assertNotEquals(0, strlen($get));

        $this->newTender = 1;
        ob_start(); // handler is noisy
        $this->post_newTender_handler();
        ob_end_clean();
        $model = $this->getTenderModel(false);
        $model->TenderName('NEW TENDER');
        $phpunit->assertNotEquals(0, count($model->find()));

        $this->id = 1;
        $model = $this->getTenderModel(1);
        $phpunit->assertEquals(true, $model->load());

        foreach (array('Code', 'Name', 'Type', 'Change', 'Min', 'Max', 'Refund', 'SalesCode') as $method) {
            $save = 'save' . $method;
            $this->$save($phpunit);
        }
        $model->load();
        foreach (array('Code', 'Name', 'Type', 'Change', 'Min', 'Max', 'Refund', 'SalesCode') as $method) {
            $save = 'test' . $method;
            $this->$save($phpunit, $model);
        }
    }

    private function saveCode($phpunit)
    {
        $this->saveCode = 'ZZ';
        $phpunit->assertInternalType('bool', $this->post_id_saveCode_handler());
    }

    private function testCode($phpunit, $model)
    {
        $phpunit->assertEquals('ZZ', $model->TenderCode());
    }

    private function saveName($phpunit)
    {
        $this->saveName = 'Test Changed';
        $phpunit->assertInternalType('bool', $this->post_id_saveName_handler());
    }

    private function testName($phpunit, $model)
    {
        $phpunit->assertEquals('Test Changed', $model->TenderName());
    }

    private function saveType($phpunit)
    {
        $this->saveType = 'YY';
        $phpunit->assertInternalType('bool', $this->post_id_saveType_handler());
    }

    private function testType($phpunit, $model)
    {
        $phpunit->assertEquals('YY', $model->TenderType());
    }

    private function saveChange($phpunit)
    {
        $this->saveCMsg = 'Kickbacks';
        $phpunit->assertInternalType('bool', $this->post_id_saveCMsg_handler());
    }

    private function testChange($phpunit, $model)
    {
        $phpunit->assertEquals('Kickbacks', $model->ChangeMessage());
    }

    private function saveMin($phpunit)
    {
        $this->saveMin = 5;
        $phpunit->assertInternalType('bool', $this->post_id_saveMin_handler());
    }

    private function testMin($phpunit, $model)
    {
        $phpunit->assertEquals(5, $model->MinAmount());
    }

    private function saveMax($phpunit)
    {
        $this->saveMax = 15;
        $phpunit->assertInternalType('bool', $this->post_id_saveMax_handler());
    }

    private function testMax($phpunit, $model)
    {
        $phpunit->assertEquals(15, $model->MaxAmount());
    }

    private function saveRefund($phpunit)
    {
        $this->saveRLimit = 25;
        $phpunit->assertInternalType('bool', $this->post_id_saveRLimit_handler());
    }

    private function testRefund($phpunit, $model)
    {
        $phpunit->assertEquals(25, $model->MaxRefund());
    }

    private function saveSalesCode($phpunit)
    {
        $this->saveSalesCode = 2500;
        $phpunit->assertInternalType('bool', $this->post_id_saveSalesCode_handler());
    }

    private function testSalesCode($phpunit, $model)
    {
        $phpunit->assertEquals(2500, $model->SalesCode());
    }
}

FannieDispatch::conditionalExec();

