<?php
/**
 * phpaga
 *
 * Materials functionality.
 *
 * This file contains the necessary routines to manage materials.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @version $Id: materials.php 897 2007-11-11 16:44:17Z christian $
 *
 * Copyright (c) 2003, 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.
 */

/**
 * Checks if all fields of an material contain valid values.
 *
 *
 * @param  array  $matinfo  Array containing the material's information.
 *
 * @return bool   $errors  True. A PhPagaError object on failure.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_materials_validdata ($matinfo)
{

    $errors = array();

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

    if (!isset($matinfo['prj_id']) || !is_numeric($matinfo['prj_id']))
        $errors[] = PHPAGA_ERR_PROJECT_INVALIDID;

    if (!isset($matinfo['pe_id']) || !is_numeric($matinfo['pe_id']))
        $errors[] = PHPAGA_ERR_PERSON_INVALIDID;

    if (!isset($matinfo['curr_id']) || !is_numeric($matinfo['curr_id']))
        $errors[] = PHPAGA_ERR_CURRENCY_INVALIDID;

    if (!isset($matinfo['mat_name']) || !strlen($matinfo['mat_name']))
        $errors[] = PHPAGA_ERR_MATERIAL_INVALIDNAME;

    if (!isset($matinfo['mat_price']) || !is_numeric($matinfo['mat_price']))
        $errors[] = PHPAGA_ERR_MATERIAL_INVALIDPRICE;

    if (isset($matinfo['mat_qty']) && strlen($matinfo['mat_qty']) && !is_numeric($matinfo['mat_qty']))
        $errors[] = PHPAGA_ERR_INVALIDQTY;

    if (count($errors))
        return PhPagaError::raiseErrorByCode($errors);

    return true;
}

/**
 * Adds a material to the database
 *
 * @param array  $matinfo  Array containing the material information
 *
 * @return int   $result  ID of the freshly inserted material. A PhPagaError object on failure.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_materials_add($matinfo)
{

    $id = null;

    $result = phpaga_materials_validdata($matinfo);

    if (PhPagaError::isError($result))
        return $result;

    $d = new PhPagaDbData;

    $id = $d->nextId('material_mat_id');

    if (!isset($matinfo['mat_prodcode']) || !strlen($matinfo['mat_prodcode']))
        $matinfo['mat_prodcode'] = NULL;

    if (!isset($matinfo['prod_id']) || !is_numeric($matinfo['prod_id']))
        $matinfo['prod_id'] = NULL;

    if (!isset($matinfo['mat_name']) || !strlen($matinfo['mat_name']))
        $matinfo['mat_name'] = NULL;

    if (!isset($matinfo['mat_qty']) || !is_numeric($matinfo['mat_qty']))
        $matinfo['mat_qty'] = NULL;

    if (!isset($matinfo['mat_desc']) || !strlen($matinfo['mat_desc']))
        $matinfo['mat_desc'] = NULL;

    $fields = array('mat_id' => $id,
                    'pe_id' => $matinfo['pe_id'],
                    'prj_id' => $matinfo['prj_id'],
                    'prod_id' => $matinfo['prod_id'],
                    'mat_name' => $matinfo['mat_name'],
                    'mat_desc' => $matinfo['mat_desc'],
                    'mat_price' => $matinfo['mat_price'],
                    'curr_id' => $matinfo['curr_id'],
                    'mat_prodcode' => $matinfo['mat_prodcode'],
                    'mat_qty' =>$matinfo['mat_qty']
        );

    $r = $d->insert('material', $fields);

    if (PhPagaError::isError($r))
        return $r;

    return $id;
}


/**
 * Delete a tracked material from a project. The material can only be
 * deleted if it has not been billed yet.
 *
 * @param  int     $mat_id      Material to be deleted
 *
 * @return bool    $result      True if successful, PhPagaError otherwise.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_materials_delete($mat_id)
{

    if (!isset($mat_id) || !is_numeric($mat_id))
        return PhPagaError::raiseErrorByCode(PHPAGA_ERR_MATERIAL_INVALIDID);

    $d = new PhPagaDbData;

    $n = $d->queryOneVal('SELECT COUNT(prj_id) FROM material WHERE bill_id IS NOT NULL AND mat_id = ?', $mat_id);

    if (PhPagaError::isError($n))
        return $n;

    if ($n > 0)
        return PhPagaError::raiseErrorByCode(PHPAGA_ERR_DEL_DEPENDENCIES);

    $result = $d->execute('DELETE FROM material WHERE mat_id = ?', $mat_id);

    if (PhPagaError::isError($result))
        return $result;

    return true;
}


/**
 * Fetches the materials according to the search parameters in matinfo.
 *
 * @param array  $matinfo    Array containing search parameters
 *
 * @return array $materials  Array containing the matching materials. A PhPagaError object on failure.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_materials_getmaterials($matinfo)
{

    $materials = array();
    $where = array();
    $qparam = array();

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

    if (PHPAGA_DB_SYSTEM == 'pgsql')
        $t_mat_added = "to_char(mat_added, 'yyyy-mm-dd hh24:mi:ss'::text) as mat_added";
    else
        $t_mat_added = 'mat_added';

    $query = 'SELECT mat_id, m.pe_id, pe_firstname, pe_lastname, '.$t_mat_added.',
        m.prj_id, prj_title, mat_name, mat_desc, mat_price, mat_qty, m.curr_id, c.curr_name,
        m.bill_id, mat_prodcode
        FROM material m
        LEFT JOIN persons p ON p.pe_id = m.pe_id
        LEFT JOIN currencies c ON c.curr_id = m.curr_id
        LEFT JOIN projects s ON s.prj_id = m.prj_id ';

    if (isset($matinfo['pe_id']) && is_numeric($matinfo['pe_id'])) {
        $where[] = 'm.pe_id = ?';
        $qparam[] = $matinfo['pe_id'];
    }

    if (isset($matinfo['prj_id']) && is_numeric($matinfo['prj_id'])) {
        $where[] = 'm.prj_id = ?';
        $qparam[] = $matinfo['prj_id'];
    }

    if (isset($matinfo['curr_id']) && is_numeric($matinfo['curr_id'])) {
        $where[] = 'm.curr_id = ?';
        $qparam[] = $matinfo['curr_id'];
    }

    if (isset($matinfo['unbilled']) && $matinfo['unbilled'])
        $where[] = 'm.bill_id IS NULL';

    if (count($where))
        $query .= sprintf('WHERE %s ', implode(' AND ', $where));

    $query .= 'ORDER BY m.mat_added ';

    $d = new PhPagaDbData;

    $r = $d->queryAll($query, $qparam);

    if (PhPagaError::isError($r))
        return $r;

    if (isset($matinfo['prj_id']) && is_numeric($matinfo['prj_id']))
        $prjmanage = phpaga_project_canmanage($matinfo['prj_id']);
    else
        $prjmanage = false;

    foreach ($r as $qrow) {

        phpaga_sanitizeArray($qrow);

        if ((!isset($qrow['bill_id']) || !strlen($qrow['bill_id']))
            && ($prjmanage ||
                (isset($qrow['pe_id']) && ($qrow['pe_id'] == $_SESSION['auth_user']['pe_id']))))

            $qrow['mat_canedit'] = true;
        else
            $qrow['mat_canedit'] = false;

        $qrow['mat_price'] = (float) $qrow['mat_price'];
        $qrow['pe_person'] = phpaga_persons_formatname ($qrow['pe_lastname'], $qrow['pe_firstname']);

        $materials[] = $qrow;
    }

    return $materials;
}


/**
 * Fetches information about one specific tracked material.
 *
 * @param int    $mat_id     Material ID
 *
 * @return array $matinfo    Array containing the results. A PhPagaError object on failure.
 *
 * @author Florian Lanthaler <florian@phpaga.net>
 * @since phpaga 0.3
 */

function phpaga_materials_getInfo($mat_id)
{

    if (!isset($mat_id) || !is_numeric($mat_id))
        return PhPagaError::raiseErrorByCode(PHPAGA_ERR_INVALID_PARAMTYPE);

    $matinfo = array();

    if (PHPAGA_DB_SYSTEM == 'pgsql')
        $t_mat_added = "to_char(mat_added, 'yyyy-mm-dd hh24:mi:ss'::text) as mat_added";
    else
        $t_mat_added = 'mat_added';

    $query = 'SELECT mat_id, m.pe_id, pe_firstname, pe_lastname, '.$t_mat_added.',
        m.prj_id, prj_title, mat_name, mat_desc, mat_price, mat_qty, m.curr_id, c.curr_name,
        m.bill_id, mat_prodcode
        FROM material m
        LEFT JOIN persons p ON p.pe_id = m.pe_id
        LEFT JOIN currencies c ON c.curr_id = m.curr_id
        LEFT JOIN projects s ON s.prj_id = m.prj_id
        WHERE mat_id = ?';

    $d = new PhPagaDbData;

    $matinfo = $d->queryRow($query, $mat_id);

    if (PhPagaError::isError($matinfo) || !count($matinfo))
        return $matinfo;

    phpaga_sanitizeArray($matinfo);
    $matinfo['mat_price'] = (float)$matinfo['mat_price'];
    $matinfo['pe_person'] = phpaga_persons_formatname ($matinfo['pe_lastname'], $matinfo['pe_firstname']);

    return $matinfo;
}

?>
