<?php
  /**
   * phpaga
   *
   * Add invoice
   *
   * This is the interface to create a new invoice with line items.
   *
   * @author Florian Lanthaler <florian@phpaga.net>
   * @version $Id: add_bill.php 726 2006-08-05 22:34:30Z florian $
   *
   * Copyright (c) 2005, Florian Lanthaler <florian@phpaga.net>
   *
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions are
   * met:
   *
   *    * Redistributions of source code must retain the above copyright
   *      notice, this list of conditions and the following disclaimer.
   *
   *    * Redistributions in binary form must reproduce the above copyright
   *      notice, this list of conditions and the following disclaimer in
   *      the documentation and/or other materials provided with the
   *      distribution.
   *
   *    * Neither the name of Florian Lanthaler nor the names of his
   *      contributors may be used to endorse or promote products derived
   *      from this software without specific prior written permission.
   *
   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
   * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
   * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
   * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
   * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
   * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
   * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
   * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   */

include_once("./config.php");

phpaga_user_pageperm(PHPAGA_PERM_MANAGE_INVOICES);

$opIds = array();
$oprows = array();
$select_bmt = array();
$select_currency = array();#
$products = null;
$prodcount = 0;
$prodIds = null;

$humancost = array("total_amount" => "");

$billInfo = array("bill_number" => "",
                  "bill_date" => "",
                  "bill_payterm" => "",
                  "cpn_id" => "",
                  "bmt_id" => "",
                  "curr_id" => PHPAGA_DEFAULTCURRENCY,
                  "bill_startsum" => 0,
                  "taskassociation" => 0,
                  "lineitems" => array());

$opInfo = array("cpn_id" => "",
                "pe_id" => "",
                "prj_id" => "",
                "opcat_id" => "",
                "op_desc" => "",
                "op_startdatefrom" => "",
                "op_startdateto" => "");

$duration = "";
$statusmsg = "";
$statusmsgarr = array();
$op_id = "";
$bill_id = "";
$billing_err = "";
$tmp_nr = "";
$bill_endsum = "";
$bill_details = null;
$dropped_operations = 0;
$dropped_materialref = 0;

function _add_lineitems(&$lineitems)
{
    for ($i = 0; $i < 5; $i++) {
        $lineitems[] = array("op_id" => null,
                             "mat_id" => null,
                             "lit_prodcode" => null,
                             "lit_desc" => null,
                             "lit_qty" => null,
                             "lit_unitnetprice" => null,
                             "lit_netprice" => null);
    }
}

if (isset($_REQUEST["id"]) && is_numeric($_REQUEST["id"])
    && isset($_REQUEST["action"]) && ($_REQUEST["action"] == ACTION_CLONE))
{
    /* clone an existing bill */

    $result = phpaga_bills_getinfo($_REQUEST["id"], $billInfo);

    if ($result == PHPAGA_ERR_NONE)
    {

        /* we don't want to bill tasks twice */
        $billInfo["operations"] = array();

        if (is_array($billInfo["lineitems"]) && (count($billInfo["lineitems"]) > 0))
        {
            $tmp_lit = $billInfo["lineitems"];
            $billInfo["lineitems"] = array();

            foreach ($tmp_lit as $tlit)
            {
                if (!isset($tlit["op_id"]) || !strlen($tlit["op_id"])) {

                    if (isset($tlit["mat_id"]) && strlen($tlit["mat_id"])) {
                        $tlit["mat_id"] = null;
                        $dropped_materialref++;
                    }

                    $billInfo["lineitems"][] = $tlit;
                }  else
                    $dropped_operations++;
            }
        }
        else
            $billInfo["lineitems"] = array();

        if ($dropped_operations > 0)
            $statusmsgarr[] = sprintf(_("%s line items that were associated to tasks have been removed in this cloned invoice."),
                                      $dropped_operations);

        if ($dropped_materialref > 0)
            $statusmsgarr[] = sprintf(_("%s material references have been removed, the respective line items have been preserved."),
                                      $dropped_materialref);

        phpaga_bills_getNewInvoiceNumber($billInfo["bill_number"]);

        /* overwrite old bill's date with current date */
        $billInfo["bill_date"] = date("Y-m-d");

    }
}
elseif (isset($_REQUEST["id"]) && is_numeric($_REQUEST["id"])
        && isset($_REQUEST["action"]) && ($_REQUEST["action"] == ACTION_FROMQUOTATION))
{
    /* create a bill from a quotation */

    $result = phpaga_quotations_getinfo($_REQUEST["id"], $quotInfo);

    if ($result == PHPAGA_ERR_NONE)
    {

        phpaga_bills_getNewInvoiceNumber($tmp_nr);
        $billInfo = array("bill_date" => date("Y-m-d"),
                          "bill_number" => $tmp_nr,
                          "cpn_id" => (int)$quotInfo["cpn_id"],
                          "bill_startsum" => $quotInfo["quot_startsum"],
                          "bmt_id" =>  $quotInfo["bmt_id"],
                          "curr_id" => $quotInfo["curr_id"]
            );

        $billInfo["operations"] = array();

        if (is_array($quotInfo["lineitems"]) && (count($quotInfo["lineitems"]) > 0))
        {
            $tmp_lit = $quotInfo["lineitems"];
            $billInfo["lineitems"] = array();

            foreach ($tmp_lit as $tlit)
                $billInfo["lineitems"][] = $tlit;

        }
        else
            $billInfo["lineitems"] = array();

    }
}
elseif (isset($_REQUEST["action"]) && is_numeric($_REQUEST["action"]))
{

    if (isset($_REQUEST["bill_number"]) && strlen($_REQUEST["bill_number"]))
        $billInfo["bill_number"] = $_REQUEST["bill_number"];

    if (isset($_REQUEST["bill_date"]) && strlen($_REQUEST["bill_date"]))
        $billInfo["bill_date"] = $_REQUEST["bill_date"];

    if (isset($_REQUEST["bill_payterm"]) && strlen($_REQUEST["bill_payterm"]))
        $billInfo["bill_payterm"] = $_REQUEST["bill_payterm"];

    if (isset($_REQUEST["cpn_id"]) && is_numeric($_REQUEST["cpn_id"]))
    {
        $billInfo["cpn_id"] = $_REQUEST["cpn_id"];

        if (!isset($billInfo["bill_payterm"]) || !strlen($billInfo["bill_payterm"]))
            $billInfo["bill_payterm"] = phpaga_companies_getdefaultpayterm($billInfo["cpn_id"]);
    }

    if (isset($_REQUEST["bmt_id"]) && is_numeric($_REQUEST["bmt_id"]))
        $billInfo["bmt_id"] = $_REQUEST["bmt_id"];

    if (isset($_REQUEST["curr_id"]) && is_numeric($_REQUEST["curr_id"]))
        $billInfo["curr_id"] = $_REQUEST["curr_id"];

    if (isset($_REQUEST["taskassociation"]) && strlen($_REQUEST["taskassociation"]))
        $billInfo["taskassociation"] = $_REQUEST["taskassociation"];

    /* operation ids (if chosen) */
    if (isset($_REQUEST["op_id"]) && is_array($_REQUEST["op_id"]))
    {

        $opIds = phpaga_operations_sanitizeopids($_REQUEST["op_id"]);

        $billInfo["operations_listin"] = implode(", ", $opIds);

        /* load all records that match the search criteria */

        $operations = phpaga_operations_search ($oprows,
                                                $dummy_count,
                                                $duration,
                                                $dummy_opIds,
                                                array("opidlist" => $billInfo["operations_listin"]));

        if (phpaga_errorhappened($operations))
            phpaga_error($operations);

    }

    /* line items */

    if (isset($_REQUEST["lit_prodcode"]) && is_array($_REQUEST["lit_prodcode"]))
    {
        for ($x = 0; $x <= count($_REQUEST["lit_prodcode"]); $x++)
        {

            $h_lit_op_id = null;
            $h_lit_mat_id = null;
            $h_lit_prodcode = null;
            $h_lit_desc = null;
            $h_lit_qty = null;
            $h_lit_unitnetprice = null;
            $h_lit_netprice = null;

            if (isset($_REQUEST["lit_prodcode"][$x]) && strlen($_REQUEST["lit_prodcode"][$x]))
                $h_lit_prodcode = $_REQUEST["lit_prodcode"][$x];

            if (isset($_REQUEST["lit_op_id"][$x]) && strlen($_REQUEST["lit_op_id"][$x]))
                $h_lit_op_id = $_REQUEST["lit_op_id"][$x];

            if (isset($_REQUEST["lit_mat_id"][$x]) && strlen($_REQUEST["lit_mat_id"][$x]))
                $h_lit_mat_id = $_REQUEST["lit_mat_id"][$x];

            if (isset($_REQUEST["lit_desc"][$x]) && strlen($_REQUEST["lit_desc"][$x]))
                $h_lit_desc = $_REQUEST["lit_desc"][$x];

            if (isset($_REQUEST["lit_qty"][$x]) && strlen($_REQUEST["lit_qty"][$x]))
                $h_lit_qty = $_REQUEST["lit_qty"][$x];

            if (isset($_REQUEST["lit_unitnetprice"][$x]) && strlen($_REQUEST["lit_unitnetprice"][$x]))
                $h_lit_unitnetprice = $_REQUEST["lit_unitnetprice"][$x];

            if (isset($_REQUEST["lit_netprice"][$x]) && strlen($_REQUEST["lit_netprice"][$x]))
                $h_lit_netprice = $_REQUEST["lit_netprice"][$x];

            if (is_numeric($h_lit_netprice))
                $billInfo["bill_startsum"] += $h_lit_netprice;

            if (strlen($h_lit_op_id) ||
                strlen($h_lit_mat_id) ||
                strlen($h_lit_prodcode) ||
                strlen($h_lit_desc) ||
                strlen($h_lit_qty) ||
                strlen($h_lit_unitnetprice) ||
                strlen($h_lit_netprice))

                $billInfo["lineitems"][] = array("op_id" => $h_lit_op_id,
                                                 "mat_id" => $h_lit_mat_id,
                                                 "lit_prodcode" => $h_lit_prodcode,
                                                 "lit_desc" => $h_lit_desc,
                                                 "lit_qty" => $h_lit_qty,
                                                 "lit_unitnetprice" => $h_lit_unitnetprice,
                                                 "lit_netprice" => $h_lit_netprice);


        }
    }

    switch($_REQUEST["action"])
    {

    case ACTION_BILL_MAKEIT:
        /* include_once billing method plugin */
        $result = phpaga_bills_includebmtPlugin($billInfo["bmt_id"]);

        if (phpaga_errorhappened($result))
            $billing_err = phpaga_returnerror($result);
        else
        {

            /* check if all billInfo fields are valid */
            $result = phpaga_bills_checkInfo($billInfo);

            if (phpaga_errorhappened($result))
                $billing_err = phpaga_returnerror($result);
            else
            {
                /* now we should do our fine calculation with the billing
                 * method plugin */
                phpaga_bill_calculate($billInfo["bill_startsum"],
                                      $billInfo["curr_id"],
                                      $billInfo["bill_endsum"],
                                      $h_details);

                $result = phpaga_bills_add($billInfo, $bill_id);

                if (phpaga_errorhappened($result))
                    $billing_err = phpaga_returnerror($result);
                else
                    header("Location: bill.php?id=$bill_id");
            }
        }
        break;

    case ACTION_BILL_WITHOPERATIONS:
        $result = phpaga_bills_getNewInvoiceNumber($billInfo["bill_number"]);
        $billInfo["bill_date"] = date("Y-m-d");
        $billInfo["bmt_id"] = PHPAGA_DEFAULTBMT;

        /* get search criteria for related operations */

        if (isset($_REQUEST["cpn_id"]) && is_numeric($_REQUEST["cpn_id"]))
            $opInfo["cpn_id"] = $_REQUEST["cpn_id"];

        if (isset($_REQUEST["pe_id"]) && is_numeric($_REQUEST["pe_id"]))
            $opInfo["pe_id"] = $_REQUEST["pe_id"];

        if (isset($_REQUEST["prj_id"]) && is_numeric($_REQUEST["prj_id"]))
            $opInfo["prj_id"] = $_REQUEST["prj_id"];

        if (isset($_REQUEST["opcat_id"]) && is_numeric($_REQUEST["opcat_id"]))
            $opInfo["opcat_id"] = $_REQUEST["opcat_id"];

        if (isset($_REQUEST["op_desc"]) && ($_REQUEST["op_desc"] != ""))
            $opInfo["op_desc"] = rawurldecode($_REQUEST["op_desc"]);

        if (isset($_REQUEST["prj_billabletype"]) && is_numeric($_REQUEST["prj_billabletype"]))
            $opInfo["prj_billabletype"] = $_REQUEST["prj_billabletype"];

        if (isset($_REQUEST["op_startdatefrom"]) && ($_REQUEST["op_startdatefrom"] != ""))
            $opInfo["op_startdatefrom"] = rawurldecode($_REQUEST["op_startdatefrom"]);

        if (isset($_REQUEST["op_startdateto"]) && ($_REQUEST["op_startdateto"] != ""))
            $opInfo["op_startdateto"] = rawurldecode($_REQUEST["op_startdateto"]);

        /* we can only bill operations that have not been billed yet */
        $opInfo["op_billed"] = PHPAGA_BILL_NOTBILLED;

        /* load all records that match the search criteria */
        $operations = phpaga_operations_search($oprows, $count, $duration,
                                               $opIds, $opInfo);

        _add_lineitems($billInfo["lineitems"]);

        break;

    case ACTION_BILL_RECALC:
    case ACTION_BILL_ADDLINEITEMS:

        if ($_REQUEST["action"] == ACTION_BILL_ADDLINEITEMS)
            _add_lineitems($billInfo["lineitems"]);
        elseif (count($billInfo["lineitems"]) == 0)
            _add_lineitems($billInfo["lineitems"]);

        break;


    case ACTION_BILL_MAKEOPITEMS:

        $billInfo["taskassociation"] = PHPAGA_BILL_TASKASSOC_LOCKED;

        if (count($oprows) > 0)
        {
            foreach ($oprows as $op) {
                $billInfo["lineitems"][] = array("op_id" => $op["op_id"],
                                                 "mat_id" => null,
                                                 "lit_prodcode" => isset($op["prj_title"]) && strlen($op["prj_title"]) ? $op["prj_title"] : null,
                                                 "lit_desc" => $op["op_desc"],
                                                 "lit_qty" => phpaga_minutes2duration($op["op_duration"]),
                                                 "lit_unitnetprice" => null,
                                                 "lit_netprice" => sprintf("%01.2f", $op["amount"]));

                $billInfo["bill_startsum"] += $op["amount"];
            }

        }

        break;

    case ACTION_BILL_MAKESINGLEOPITEM:

        $billInfo["taskassociation"] = PHPAGA_BILL_TASKASSOC_LOCKED;

        if (count($oprows) > 0)
        {
            $h_amount = 0;

            foreach ($oprows as $op)
                $h_amount += $op["amount"];

            $billInfo["bill_startsum"] += $h_amount;

            $billInfo["lineitems"][] = array("op_id" => "-1",
                                             "mat_id" => null,
                                             "lit_prodcode" => null,
                                             "lit_desc" => null,
                                             "lit_qty" => $duration,
                                             "lit_unitnetprice" => null,
                                             "lit_netprice" => sprintf("%01.2f", $h_amount));

        }
        break;

    case ACTION_BILL_MAKEOPITEMSPERPRJ:

        $billInfo["taskassociation"] = PHPAGA_BILL_TASKASSOC_LOCKED;

        $h_lineitems = array();

        if (count($oprows) > 0)
        {
            foreach ($oprows as $op) {

                if (!isset($h_lineitems[$op["prj_id"]]))
                    $h_lineitems[$op["prj_id"]] = array("lit_prodcode" => $op["prj_title"],
                                                        "lit_qty" => 0,
                                                        "lit_unitnetprice" => null,
                                                        "lit_netprice" => 0);

                $h_lineitems[$op["prj_id"]]["lit_qty"] += $op["op_duration"];
                $h_lineitems[$op["prj_id"]]["lit_netprice"] += $op["amount"];
            }

            foreach ($h_lineitems as $h_lineitem) {

                $billInfo["lineitems"][] = array("op_id" => -1,
                                                 "mat_id" => null,
                                                 "lit_prodcode" => $h_lineitem["lit_prodcode"],
                                                 "lit_desc" => null,
                                                 "lit_qty" => phpaga_minutes2duration($h_lineitem["lit_qty"]),
                                                 "lit_unitnetprice" => null,
                                                 "lit_netprice" => sprintf("%01.2f", $h_lineitem["lit_netprice"]));

                $billInfo["bill_startsum"] += $h_lineitem["lit_netprice"];
            }

        }

        break;

    case ACTION_BILL_FROMPROJECT:
        $result = phpaga_bills_getNewInvoiceNumber($billInfo["bill_number"]);
        $billInfo["bill_date"] = date("Y-m-d");
        $billInfo["bmt_id"] = PHPAGA_DEFAULTBMT;


        $materials = array();
        $matinfo = array("prj_id" => null,
                         "unbilled" => true);

        if (isset($_REQUEST["add_material"]) && isset($_REQUEST["prj_id"]) && is_numeric($_REQUEST["prj_id"])) {
            $matinfo["prj_id"] = $_REQUEST["prj_id"];
            $matres = phpaga_materials_getmaterials ($matinfo, $materials);

            if ($matres != PHPAGA_ERR_NONE)
                phpaga_error($matres);
            else
            {
                if (count($materials) > 0)
                {
                    foreach ($materials as $mat) {

                        $h_desc = null;

                        if (isset($mat["mat_name"]) && strlen($mat["mat_name"]))
                            $h_desc .= $mat["mat_name"];


                        if (isset($mat["mat_desc"]) && strlen($mat["mat_desc"])) {

                            if (strlen($h_desc))
                                $h_desc .= " - ";

                            $h_desc .= $mat["mat_desc"];
                        }

                        $billInfo["lineitems"][] = array("mat_id" => $mat["mat_id"],
                                                         "op_id" => null,
                                                         "lit_prodcode" => $mat["mat_prodcode"],
                                                         "lit_desc" => $h_desc,
                                                         "lit_qty" => $mat["mat_qty"],
                                                         "lit_unitnetprice" => null,
                                                         "lit_netprice" => sprintf("%01.2f", $mat["mat_price"]));

                        $billInfo["bill_startsum"] += $mat["mat_price"];
                    }

                }

            }
        }

        /* get search criteria for related operations */

        if (isset($_REQUEST["add_manhours"]) && isset($_REQUEST["prj_id"]) && is_numeric($_REQUEST["prj_id"])) {

            $billInfo["taskassociation"] = PHPAGA_BILL_TASKASSOC_LOCKED;

            $opInfo["prj_id"] = $_REQUEST["prj_id"];

            $opInfo["op_billed"] = PHPAGA_BILL_NOTBILLED;

            $operations = phpaga_operations_search($oprows, $count, $duration,
                                                   $opIds, $opInfo);

            if (count($oprows) > 0) {
                if (isset($_REQUEST["singlemulti"]) && ($_REQUEST["singlemulti"] == 1)) {

                    $h_amount = 0;
                    $h_prodcode = null;

                    foreach ($oprows as $op) {
                        $h_amount += $op["amount"];

                        if (!strlen($h_prodcode) && isset($op["prj_title"]) && strlen($op["prj_title"]))
                            $h_prodcode = $op["prj_title"];
                    }

                    $billInfo["bill_startsum"] += $h_amount;

                    $billInfo["lineitems"][] = array("op_id" => "-1",
                                                     "mat_id" => null,
                                                     "lit_prodcode" => $h_prodcode,
                                                     "lit_desc" => null,
                                                     "lit_qty" => $duration,
                                                     "lit_unitnetprice" => null,
                                                     "lit_netprice" => sprintf("%01.2f", $h_amount));

                } else {

                    foreach ($oprows as $op) {
                        $billInfo["lineitems"][] = array("op_id" => $op["op_id"],
                                                         "mat_id" => null,
                                                         "lit_prodcode" => isset($op["prj_title"]) && strlen($op["prj_title"]) ? $op["prj_title"] : null,
                                                         "lit_desc" => $op["op_desc"],
                                                         "lit_qty" => phpaga_minutes2duration($op["op_duration"]),
                                                         "lit_unitnetprice" => null,
                                                         "lit_netprice" => sprintf("%01.2f", $op["amount"]));

                        $billInfo["bill_startsum"] += $op["amount"];
                    }
                }
            }
        }
        _add_lineitems($billInfo["lineitems"]);

        break;

    default:
        $result = phpaga_bills_getNewInvoiceNumber($billInfo["bill_number"]);
        $billInfo["bill_date"] = date("Y-m-d");
        $billInfo["bmt_id"] = PHPAGA_DEFAULTBMT;
        break;
    }

    /* check if all billInfo fields are valid */
    $result = phpaga_bills_checkInfo($billInfo);

    if (phpaga_errorhappened($result))
        $billing_err = phpaga_returnmessage(_("Notice"), $result);
}
else
{
    $result = phpaga_bills_getNewInvoiceNumber($billInfo["bill_number"]);
    $billInfo["bill_date"] = date("Y-m-d");
    $billInfo["bmt_id"] = PHPAGA_DEFAULTBMT;
    _add_lineitems($billInfo["lineitems"]);
}

if (isset($billInfo["bmt_id"]) && is_numeric($billInfo["bmt_id"])
    && isset($billInfo["curr_id"]) && is_numeric($billInfo["curr_id"])
    && isset($billInfo["bill_startsum"]) && is_numeric($billInfo["bill_startsum"]))
{
    /* include_once billing method plugin */
    $result = phpaga_bills_includebmtPlugin($billInfo["bmt_id"]);

    if (phpaga_errorhappened($result))
        $billing_err = phpaga_returnerror($result);
    else
    {

        /* now we should do our fine calculation with the billing
         * method plugin */
        phpaga_bill_calculate($billInfo["bill_startsum"],
                              $billInfo["curr_id"],
                              $bill_endsum,
                              $bill_details);

    }
}

phpaga_header(array("calendar" => true, "menuitem" => "finance"));

phpaga_companies_getCompanyList($select_company);
phpaga_arrayAddOption($select_company, PHPAGA_OPTION_SELECT);

phpaga_currencies_getCurrencyList($select_currency);
phpaga_bills_getInvoiceTypeList($select_bmt);

if (count($opIds) >0) {
    phpaga_operations_gethumancost($opIds, $humancost);
}

if (isset($operations) && phpaga_errorhappened($operations)) {
    $statusmsgarr[] = $operations;
}

$prodresult = phpaga_products_search($products, $prodcount, $prodIds, array());

$tpl = new psmarty;
$tpl->assign("STATUSMSG", count($statusmsgarr) ? phpaga_returnmessage(_("Notice"), $statusmsgarr) : null);
$tpl->assign("select_cpn", $select_company);
$tpl->assign("select_bmt", $select_bmt);
$tpl->assign("select_curr", $select_currency);
$tpl->assign("billinfo", $billInfo);
$tpl->assign("BILLING_ERR", $billing_err);
$tpl->assign("bill_details", $bill_details->details);
$tpl->assign("humancost", $humancost);
$tpl->assign("operations", $oprows);
$tpl->assign("products", $products);
$tpl->assign("TOTALHOURS", $duration);

$tpl->display("add_bill.tpl.html");

phpaga_footer ();

?>