<?php
/**
 * phpaga
 *
 * Product management functionality.
 *
 * This file contains the necessary routines to manage products.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @version $Id: products.php 653 2005-10-03 21:53:26Z worf $
 *
 * 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.
 */


/**
 * Gets a list of products from the database and returns them as an
 * array.
 *
 * @param int    $prodID    Product's ID
 * @param array  $prodList  Array of productsd
 *
 * @return int   $result  A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_getProductList (&$prodList)
{
    $prodList = array();

    phpaga_db_connect($db);

    $query = "SELECT prod_id, prod_code, prod_name, prod_price ".
        "FROM products ".
        "ORDER BY prod_name";

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    while ($qrow = $result->fetchRow())
    {
        $tmp = sprintf("%s - %s", $qrow["prod_code"], $qrow["prod_name"]);

        if (isset($qrow["prod_price"]) && strlen($qrow["prod_price"]))
            $tmp .= " (".$qrow["prod_price"].")";

        $prodList[$qrow["prod_id"]] = $tmp;
    }

    $result->free();
    return PHPAGA_ERR_NONE;
}


/**
 * Gets a product's information
 *
 * @param int    $prodID     Product ID (or product code, see $bycode)
 * @param array  &$prodInfo  Array containing the results.
 * @param bool   $bycode     If set to true then $prodID contains the product
 *                           code, otherwise the product ID
 * @return int   $result     A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_getInfo ($prodID, &$prodInfo, $bycode = false)
{
    $prodInfo = array();
    $prjInfo = array();
    $billInfo = array();
    $rows = array();
    $count = 0;
    $summary = array();
    $offset = "";

    if (!isset($prodID) || (!strlen($prodID)))
        return PHPAGA_ERR_PRODUCT_INVALIDID;

    if ($bycode)
        $idfield = "products.prod_code";
    else
        $idfield = "products.prod_id";
    phpaga_db_connect($db);

    if (PHPAGA_DB_SYSTEM == "pgsql")
        $_times = "to_char(prod_created, 'yyyy-mm-dd hh24:mi:ss'::text) as prod_created, ".
            "to_char(prod_lastmod, 'yyyy-mm-dd hh24:mi:ss'::text) as prod_lastmod ";
    else
        $_times = "prod_created, prod_lastmod";

    $query = "SELECT products.prod_id, prod_code, prod_name, prod_price, prod_consumption, prod_stock, ".
        "products.prcat_id, prcat_title, $_times ".
        "FROM products ".
        "LEFT JOIN productcat ON productcat.prcat_id = products.prcat_id ".
        "WHERE $idfield = ".$db->quoteSmart($prodID);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    if ($result->numRows() < 1)
        return PHPAGA_ERR_DB_NO_ROWS;

    if ($qrow = $result->fetchRow())
         $prodInfo = $qrow;

    $result->free();
    phpaga_sanitizeArray($prodInfo);

    return PHPAGA_ERR_NONE;
}


/**
 * Checks if all fields of a product contain valid values.
 *
 * @param  array  $prodInfo  Array containing the product's information.
 *
 * @return array  $errors    Array containing error codes
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_validdata ($prodInfo)
{

    $errors = array();

    if (!is_array($prodInfo))
        $prodInfo = array($prodInfo);

    if (!isset($prodInfo["prod_code"]) || !strlen($prodInfo["prod_code"]))
        $errors[] = PHPAGA_ERR_PRODUCT_INVALIDCODE;

    if (!isset($prodInfo["prod_name"]) || !strlen($prodInfo["prod_name"]))
        $errors[] = PHPAGA_ERR_PRODUCT_INVALIDNAME;

    if (isset($prodInfo["prcat_id"]) && strlen($prodInfo["prcat_id"]) && !is_numeric($prodInfo["prcat_id"]))
        $errors[] = PHPAGA_ERR_PRCAT_INVALIDID;

    if (isset($prodInfo["prod_price"]) && strlen($prodInfo["prod_price"]) && !is_numeric($prodInfo["prod_price"]))
        $errors[] = PHPAGA_ERR_PRODUCT_INVALIDPRICE;

    if (isset($prodInfo["prod_consumption"]) && strlen($prodInfo["prod_consumption"]) && !is_numeric($prodInfo["prod_consumption"]))
        $errors[] = PHPAGA_ERR_PRODUCT_INVALIDCONSUMPTION;

    if (isset($prodInfo["prod_stock"]) && strlen ($prodInfo["prod_stock"]) && !is_numeric($prodInfo["prod_stock"]))
        $errors[] = PHPAGA_ERR_PRODUCT_INVALIDSTOCK;

    return $errors;
}


/**
 * Adds a product to the database
 *
 * @param array  $prodInfo  Array containing the product information
 * @param int    &$prod_id  The resulting ID of the newly inserted product
 *
 * @return int   $result  A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_add ($prodInfo, &$prod_id)
{

    $result = phpaga_products_validdata($prodInfo);

    if (count($result) > 0)
        return $result;

    phpaga_db_connect($db);

    $prod_id = $db->nextId("products_prod_id");

    if (!isset($prodInfo["prod_name"]) || !strlen($prodInfo["prod_name"]))
        $prodInfo["prod_name"] = NULL;

    if (!isset($prodInfo["prod_code"]) || !strlen($prodInfo["prod_code"]))
        $prodInfo["prod_code"] = NULL;

    if (!isset($prodInfo["prod_price"]) || !is_numeric($prodInfo["prod_price"]))
        $prodInfo["prod_price"] = NULL;

    if (!isset($prodInfo["prod_consumption"]) || !is_numeric($prodInfo["prod_consumption"]))
        $prodInfo["prod_consumption"] = NULL;

    if (!isset($prodInfo["prod_stock"]) || !is_numeric($prodInfo["prod_stock"]))
        $prodInfo["prod_stock"] = NULL;

    if (!isset($prodInfo["prcat_id"]) || !is_numeric($prodInfo["prcat_id"]))
        $prodInfo["prcat_id"] = NULL;

    $fields = array("prod_id" => $prod_id,
                    "prod_name" => $prodInfo["prod_name"],
                    "prod_code" => $prodInfo["prod_code"],
                    "prod_price" => $prodInfo["prod_price"],
                    "prod_consumption" => $prodInfo["prod_consumption"],
                    "prod_stock" => $prodInfo["prod_stock"],
                    "prcat_id" => $prodInfo["prcat_id"],
                    "prod_lastmod" => date("Y-m-d H:i:s")
        );

    $result = $db->autoExecute("products", $fields, DB_AUTOQUERY_INSERT);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;
    else
        return PHPAGA_ERR_NONE;
}


/**
 * Updates a product.
 *
 * @param array  $prodInfo Array containing the product information
 *
 * @return int   $result  A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_update ($prodInfo)
{

    $result = phpaga_products_validdata($prodInfo);

    if (count($result) > 0)
        return $result;

    if (!isset($prodInfo["prod_name"]) || !strlen($prodInfo["prod_name"]))
        $prodInfo["prod_name"] = NULL;

    if (!isset($prodInfo["prod_code"]) || !strlen($prodInfo["prod_code"]))
        $prodInfo["prod_code"] = NULL;

    if (!isset($prodInfo["prod_price"]) || !is_numeric($prodInfo["prod_price"]))
        $prodInfo["prod_price"] = NULL;

    if (!isset($prodInfo["prod_consumption"]) || !is_numeric($prodInfo["prod_consumption"]))
        $prodInfo["prod_consumption"] = NULL;

    if (!isset($prodInfo["prod_stock"]) || !is_numeric($prodInfo["prod_stock"]))
        $prodInfo["prod_stock"] = NULL;

    if (!isset($prodInfo["prcat_id"]) || !is_numeric($prodInfo["prcat_id"]))
        $prodInfo["prcat_id"] = NULL;

    $fields = array("prod_name" => $prodInfo["prod_name"],
                    "prod_code" => $prodInfo["prod_code"],
                    "prod_price" => $prodInfo["prod_price"],
                    "prod_consumption" => $prodInfo["prod_consumption"],
                    "prod_stock" => $prodInfo["prod_stock"],
                    "prcat_id" => $prodInfo["prcat_id"],
                    "prod_lastmod" => date("Y-m-d H:i:s")
        );

    phpaga_db_connect($db);
    $result = $db->autoExecute("products", $fields, DB_AUTOQUERY_UPDATE,
                               "prod_id = ".$db->quoteSmart($prodInfo["prod_id"]));

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;
    else
        return PHPAGA_ERR_NONE;
}

/**
 * Loads all product categories into an array.
 *
 * @param array  &$prcatInfo  Array containing the results
 * @param bool   $assoc       If true then load data into an associative array
 *                            (optional, defaults to false))
 *
 * @return int   $result       A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_getProdcats (&$prcatInfo, $assoc = false)
{
    $prcatInfo = array();

    phpaga_db_connect($db);

    $query = "SELECT prcat_id, prcat_title FROM productcat ORDER BY prcat_title";

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    while ($qrow = $result->fetchRow())
    {
        phpaga_sanitizeArray($qrow);

        if ($assoc)
            $prcatInfo[$qrow["prcat_id"]] = $qrow["prcat_title"];
        else
            $prcatInfo[] = $qrow;
    }

    $result->free();
    return PHPAGA_ERR_NONE;
}


/**
 * Add a new product category.
 *
 * @param  string  $prcat_title   Product category to be added
 *
 * @return int     $result       A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_addProdcat ($prcat_title)
{

    if (!isset($prcat_title) || !strlen($prcat_title))
        return PHPAGA_ERR_PRCAT_INVALIDTITLE;

    phpaga_db_connect($db);

    $fields = array("prcat_id" => $db->nextId("productcat_prcat_id"),
                    "prcat_title" => $prcat_title);

    $result = $db->autoExecute("productcat", $fields, DB_AUTOQUERY_INSERT);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;
    else
        return PHPAGA_ERR_NONE;
}


/**
 * Delete a product category.
 *
 * @param  int     $prcat_id     Product category to be deleted
 *
 * @return int     $result      A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_deleteProdcat ($prcat_id)
{
    if (!isset($prcat_id) || !is_numeric($prcat_id))
        return PHPAGA_ERR_PRCAT_INVALIDID;

    phpaga_db_connect($db);

    /* first check if this prcat is needed by any table relationship
     * if it is not needed, then delete it, otherwise don't */

    $query = "SELECT prod_id ".
        "FROM products ".
        "WHERE prcat_id = ".$db->quoteSmart($prcat_id);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    /* any record matching the query? in that case we cannot delete
     * this product category, as there are dependencies
     */

    if ($result->numRows() > 0)
        return PHPAGA_ERR_DEL_DEPENDENCIES;

    $query = "DELETE FROM productcat WHERE prcat_id = ".
        $db->quoteSmart($prcat_id);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;
    else
        return PHPAGA_ERR_NONE;
}

/**
 * Delete a product.
 *
 * @param  int     $prod_id      Product ID
 *
 * @return int     $result       A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_delete ($prod_id)
{
    if (!isset($prod_id) || !is_numeric($prod_id))
        return PHPAGA_ERR_PRODUCT_INVALIDID;

    phpaga_db_connect($db);

    /* first check, if this product is needed by any table relationship
     * if it is not needed, then delete it, otherwise don't */

    /*
    $query = "SELECT prod_id FROM materials ".
        "WHERE prod_id = ".$db->quoteSmart($prod_id);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    if ($result->numRows() > 0)
        return PHPAGA_ERR_DEL_DEPENDENCIES;
    */


    $query = "DELETE FROM products ".
        "WHERE prod_id = ".$db->quoteSmart($prod_id);

    $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;
    else
        return PHPAGA_ERR_NONE;
}


/**
 * Gets all products matching the search parmeters
 * (from $offset to $limit, if set)
 *
 * @param array  $rows      Array containing the results
 * @param int    $count     Number of records matching the query
 * @param array  $prodInfo  Product information
 * @param array  $prodIds   IDs of the resulting products
 * @param int    $order     Specifies the order by field
 *
 * @param int    $offset    Offset (optional)
 * @param int    $limit     Limit (optional)
 *
 * @return int   $result    A result code.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_products_search (&$rows,
                                 &$count,
                                 &$prodIds,
                                 $prodInfo,
                                 $order = 0,
                                 $offset = "",
                                 $limit = "")
{

    $count = 0;
    $rows = array();
    $prodIds = array();
    $where = array();
    $where_clause = "";

    phpaga_db_connect($db);

    /* how many matching records are there */

    $countquery = "SELECT COUNT(products.prod_id) AS count_prod FROM products ".
        "LEFT JOIN productcat ON productcat.prcat_id = products.prcat_id ";

    /* select limited number of records */

    if (PHPAGA_DB_SYSTEM == "pgsql")
        $_times = "to_char(prod_created, 'yyyy-mm-dd hh24:mi:ss'::text) as prod_created, ".
            "to_char(prod_lastmod, 'yyyy-mm-dd hh24:mi:ss'::text) as prod_lastmod ";
    else
        $_times = "prod_created, prod_lastmod";

    $query = "SELECT products.prod_id, prod_code, prod_name, prod_price, prod_consumption, prod_stock, ".
        "products.prcat_id, prcat_title, $_times ".
        "FROM products ".
        "LEFT JOIN productcat ON productcat.prcat_id = products.prcat_id ";

    /* collect elements of the where clause */

    if (isset($prodInfo["prod_name"]) && strlen($prodInfo["prod_name"]))
        $where[] = "products.prod_name like '%".$db->escapeSimple($prodInfo["prod_name"])."%'";

    if (isset($prodInfo["prod_code"]) && strlen($prodInfo["prod_code"]))
        $where[] = "products.prod_code =  ".$db->quoteSmart($prodInfo["prod_code"]);

    if (isset($prodInfo["prcat_id"]) && is_numeric($prodInfo["prcat_id"]))
        $where[] = "products.prcat_id = ".$db->quoteSmart($prodInfo["prcat_id"]);

    if (count($where) > 0)
    {
        $query .= "WHERE ".implode(" AND ", $where)." ";
        $countquery .= "WHERE ".implode(" AND ", $where)." ";
    }

    $query .= " ORDER BY prod_name ";

    /* first do the count stuff */

    $result = $db->query($countquery);

    if ((!DB::isError($result)) && ($result->numRows() > 0)
        && ($countrow = $result->fetchRow()))
    {
        $count = $countrow["count_prod"];
    }

    /* limit the number of results starting from $offset if both $offset
     * and $limit are set and valid */

    if (isset($offset) && is_numeric($offset) && isset($limit)
        && is_numeric($limit) && ($limit > 0))

        $result = $db->limitQuery($query, $offset, $limit);
    else
        $result = $db->query($query);

    if (DB::isError($result))
        return PHPAGA_ERR_DB_EXEC_QUERY;

    if ($result->numRows() < 1)
        return PHPAGA_ERR_DB_NO_ROWS;

    while ($qrow = $result->fetchRow())
    {

        phpaga_sanitizearray($qrow);

        $rows[] = $qrow;
        $prodIds[] = $qrow["prod_id"];
    }

    $result->free();
    return PHPAGA_ERR_NONE;
}

?>