- Add widget box showing products starting with "New" that need review - Add dashboard statistics for new products (small info box) - Add new_products.php page listing all products to review - Add CSS for dashboard icon - Shows 5 entries on homepage, all entries on product page Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
291 lines
9.9 KiB
PHP
291 lines
9.9 KiB
PHP
<?php
|
|
/* Copyright (C) 2024 Eduard Wisch <data@data-it-solution.de>
|
|
*
|
|
* This program 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 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program 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.
|
|
*/
|
|
|
|
/**
|
|
* \file new_products.php
|
|
* \ingroup importzugferd
|
|
* \brief List of products starting with "New" that need review after import
|
|
*/
|
|
|
|
// Load Dolibarr environment
|
|
require '../../main.inc.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formother.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
|
|
|
|
// Load translation files
|
|
$langs->loadLangs(array('products', 'stocks', 'importzugferd@importzugferd'));
|
|
|
|
// Security check
|
|
if (!$user->hasRight('produit', 'lire')) {
|
|
accessforbidden();
|
|
}
|
|
|
|
// Get parameters
|
|
$action = GETPOST('action', 'aZ09');
|
|
$massaction = GETPOST('massaction', 'alpha');
|
|
$confirm = GETPOST('confirm', 'alpha');
|
|
$toselect = GETPOST('toselect', 'array');
|
|
$optioncss = GETPOST('optioncss', 'alpha');
|
|
|
|
// Search Criteria
|
|
$search_ref = GETPOST("search_ref", 'alpha');
|
|
$search_label = GETPOST("search_label", 'alpha');
|
|
$search_tosell = GETPOST("search_tosell");
|
|
$search_tobuy = GETPOST("search_tobuy");
|
|
|
|
// Load variable for pagination
|
|
$limit = GETPOSTINT('limit') ? GETPOSTINT('limit') : $conf->liste_limit;
|
|
$sortfield = GETPOST('sortfield', 'aZ09comma');
|
|
$sortorder = GETPOST('sortorder', 'aZ09comma');
|
|
$page = GETPOSTISSET('pageplusone') ? (GETPOSTINT('pageplusone') - 1) : GETPOSTINT("page");
|
|
if (empty($page) || $page < 0 || GETPOST('button_search', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
|
|
$page = 0;
|
|
}
|
|
$offset = $limit * $page;
|
|
$pageprev = $page - 1;
|
|
$pagenext = $page + 1;
|
|
if (!$sortfield) {
|
|
$sortfield = "p.datec";
|
|
}
|
|
if (!$sortorder) {
|
|
$sortorder = "DESC";
|
|
}
|
|
|
|
// Initialize objects
|
|
$object = new Product($db);
|
|
$form = new Form($db);
|
|
|
|
$arrayfields = array(
|
|
'p.ref' => array('label' => 'Ref', 'checked' => 1, 'position' => 10),
|
|
'p.label' => array('label' => 'Label', 'checked' => 1, 'position' => 20),
|
|
'p.fk_product_type' => array('label' => 'Type', 'checked' => 1, 'position' => 30),
|
|
'p.price' => array('label' => 'SellingPrice', 'checked' => 1, 'position' => 40),
|
|
'p.price_ttc' => array('label' => 'SellingPriceTTC', 'checked' => 0, 'position' => 41),
|
|
'p.tosell' => array('label' => 'OnSell', 'checked' => 1, 'position' => 50),
|
|
'p.tobuy' => array('label' => 'OnBuy', 'checked' => 1, 'position' => 60),
|
|
'p.datec' => array('label' => 'DateCreation', 'checked' => 1, 'position' => 70),
|
|
);
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
|
|
if (GETPOST('button_removefilter_x', 'alpha') || GETPOST('button_removefilter.x', 'alpha') || GETPOST('button_removefilter', 'alpha')) {
|
|
$search_ref = '';
|
|
$search_label = '';
|
|
$search_tosell = '';
|
|
$search_tobuy = '';
|
|
$toselect = array();
|
|
$search_array_options = array();
|
|
}
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$title = $langs->trans('NewProductsToReview');
|
|
$help_url = '';
|
|
|
|
llxHeader('', $title, $help_url);
|
|
|
|
// Build SQL query
|
|
$sql = "SELECT p.rowid, p.ref, p.label, p.fk_product_type, p.entity,";
|
|
$sql .= " p.price, p.price_ttc, p.price_base_type, p.tva_tx,";
|
|
$sql .= " p.tosell, p.tobuy, p.datec, p.tms";
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."product as p";
|
|
$sql .= " WHERE p.entity IN (".getEntity('product').")";
|
|
$sql .= " AND p.ref LIKE 'New%'";
|
|
|
|
// Add search filters
|
|
if ($search_ref) {
|
|
$sql .= natural_search('p.ref', $search_ref);
|
|
}
|
|
if ($search_label) {
|
|
$sql .= natural_search('p.label', $search_label);
|
|
}
|
|
if ($search_tosell != '' && $search_tosell >= 0) {
|
|
$sql .= " AND p.tosell = ".((int) $search_tosell);
|
|
}
|
|
if ($search_tobuy != '' && $search_tobuy >= 0) {
|
|
$sql .= " AND p.tobuy = ".((int) $search_tobuy);
|
|
}
|
|
|
|
// Count total
|
|
$sqlcount = preg_replace('/^SELECT[^F]*FROM/', 'SELECT COUNT(*) as nbtotalofrecords FROM', $sql);
|
|
$sqlcount = preg_replace('/ORDER BY.*$/', '', $sqlcount);
|
|
$resqlcount = $db->query($sqlcount);
|
|
$nbtotalofrecords = 0;
|
|
if ($resqlcount) {
|
|
$objcount = $db->fetch_object($resqlcount);
|
|
$nbtotalofrecords = $objcount->nbtotalofrecords;
|
|
}
|
|
|
|
// Add sorting
|
|
$sql .= $db->order($sortfield, $sortorder);
|
|
$sql .= $db->plimit($limit + 1, $offset);
|
|
|
|
$resql = $db->query($sql);
|
|
if (!$resql) {
|
|
dol_print_error($db);
|
|
exit;
|
|
}
|
|
|
|
$num = $db->num_rows($resql);
|
|
|
|
$param = '';
|
|
if ($search_ref) {
|
|
$param .= '&search_ref='.urlencode($search_ref);
|
|
}
|
|
if ($search_label) {
|
|
$param .= '&search_label='.urlencode($search_label);
|
|
}
|
|
if ($search_tosell != '') {
|
|
$param .= '&search_tosell='.urlencode($search_tosell);
|
|
}
|
|
if ($search_tobuy != '') {
|
|
$param .= '&search_tobuy='.urlencode($search_tobuy);
|
|
}
|
|
if ($limit > 0 && $limit != $conf->liste_limit) {
|
|
$param .= '&limit='.((int) $limit);
|
|
}
|
|
|
|
// List header
|
|
print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="list">';
|
|
print '<input type="hidden" name="sortfield" value="'.$sortfield.'">';
|
|
print '<input type="hidden" name="sortorder" value="'.$sortorder.'">';
|
|
|
|
print_barre_liste($title, $page, $_SERVER["PHP_SELF"], $param, $sortfield, $sortorder, '', $num, $nbtotalofrecords, 'product', 0, '', '', $limit, 0, 0, 1);
|
|
|
|
// Info box
|
|
print '<div class="info">';
|
|
print $langs->trans('NewProductsToReviewDesc', 'New');
|
|
print '</div><br>';
|
|
|
|
print '<div class="div-table-responsive">';
|
|
print '<table class="tagtable liste'.($optioncss ? ' '.$optioncss : '').'">';
|
|
|
|
// Header row with search fields
|
|
print '<tr class="liste_titre_filter">';
|
|
print '<td class="liste_titre"><input type="text" class="flat maxwidth100" name="search_ref" value="'.dol_escape_htmltag($search_ref).'"></td>';
|
|
print '<td class="liste_titre"><input type="text" class="flat maxwidth200" name="search_label" value="'.dol_escape_htmltag($search_label).'"></td>';
|
|
print '<td class="liste_titre"></td>';
|
|
print '<td class="liste_titre right"></td>';
|
|
print '<td class="liste_titre center">'.$form->selectyesno('search_tosell', $search_tosell, 1, false, 1, 1).'</td>';
|
|
print '<td class="liste_titre center">'.$form->selectyesno('search_tobuy', $search_tobuy, 1, false, 1, 1).'</td>';
|
|
print '<td class="liste_titre"></td>';
|
|
print '<td class="liste_titre center">';
|
|
print '<input type="image" class="liste_titre" name="button_search" src="'.img_picto($langs->trans("Search"), 'search.png', '', 0, 1).'" value="'.dol_escape_htmltag($langs->trans("Search")).'" title="'.dol_escape_htmltag($langs->trans("Search")).'">';
|
|
print '<input type="image" class="liste_titre" name="button_removefilter" src="'.img_picto($langs->trans("RemoveFilter"), 'searchclear.png', '', 0, 1).'" value="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'" title="'.dol_escape_htmltag($langs->trans("RemoveFilter")).'">';
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Column headers
|
|
print '<tr class="liste_titre">';
|
|
print_liste_field_titre('Ref', $_SERVER["PHP_SELF"], 'p.ref', '', $param, '', $sortfield, $sortorder);
|
|
print_liste_field_titre('Label', $_SERVER["PHP_SELF"], 'p.label', '', $param, '', $sortfield, $sortorder);
|
|
print_liste_field_titre('Type', $_SERVER["PHP_SELF"], 'p.fk_product_type', '', $param, '', $sortfield, $sortorder);
|
|
print_liste_field_titre('SellingPrice', $_SERVER["PHP_SELF"], 'p.price', '', $param, '', $sortfield, $sortorder, 'right ');
|
|
print_liste_field_titre('OnSell', $_SERVER["PHP_SELF"], 'p.tosell', '', $param, '', $sortfield, $sortorder, 'center ');
|
|
print_liste_field_titre('OnBuy', $_SERVER["PHP_SELF"], 'p.tobuy', '', $param, '', $sortfield, $sortorder, 'center ');
|
|
print_liste_field_titre('DateCreation', $_SERVER["PHP_SELF"], 'p.datec', '', $param, '', $sortfield, $sortorder, 'center ');
|
|
print_liste_field_titre('', $_SERVER["PHP_SELF"], '', '', $param, '', $sortfield, $sortorder, 'center ');
|
|
print '</tr>';
|
|
|
|
// Data rows
|
|
$i = 0;
|
|
while ($i < min($num, $limit)) {
|
|
$obj = $db->fetch_object($resql);
|
|
if (!$obj) {
|
|
break;
|
|
}
|
|
|
|
$product_static = new Product($db);
|
|
$product_static->id = $obj->rowid;
|
|
$product_static->ref = $obj->ref;
|
|
$product_static->label = $obj->label;
|
|
$product_static->type = $obj->fk_product_type;
|
|
$product_static->entity = $obj->entity;
|
|
$product_static->status = $obj->tosell;
|
|
$product_static->status_buy = $obj->tobuy;
|
|
|
|
print '<tr class="oddeven">';
|
|
|
|
// Ref
|
|
print '<td class="nowraponall">';
|
|
print $product_static->getNomUrl(1);
|
|
print '</td>';
|
|
|
|
// Label
|
|
print '<td class="tdoverflowmax200" title="'.dol_escape_htmltag($obj->label).'">'.dol_escape_htmltag($obj->label).'</td>';
|
|
|
|
// Type
|
|
print '<td>';
|
|
if ($obj->fk_product_type == 0) {
|
|
print $langs->trans('Product');
|
|
} else {
|
|
print $langs->trans('Service');
|
|
}
|
|
print '</td>';
|
|
|
|
// Price
|
|
print '<td class="right nowraponall">';
|
|
if ($obj->price_base_type == 'TTC') {
|
|
print '<span class="amount">'.price($obj->price_ttc).'</span>';
|
|
} else {
|
|
print '<span class="amount">'.price($obj->price).'</span>';
|
|
}
|
|
print '</td>';
|
|
|
|
// On sell
|
|
print '<td class="center">';
|
|
print $product_static->LibStatut($obj->tosell, 5, 0);
|
|
print '</td>';
|
|
|
|
// On buy
|
|
print '<td class="center">';
|
|
print $product_static->LibStatut($obj->tobuy, 5, 1);
|
|
print '</td>';
|
|
|
|
// Date creation
|
|
print '<td class="center nowraponall">';
|
|
print dol_print_date($db->jdate($obj->datec), 'dayhour');
|
|
print '</td>';
|
|
|
|
// Action column
|
|
print '<td class="center">';
|
|
print '<a class="editfielda" href="'.DOL_URL_ROOT.'/product/card.php?id='.$obj->rowid.'&action=edit&token='.newToken().'">';
|
|
print img_picto($langs->trans('Edit'), 'edit');
|
|
print '</a>';
|
|
print '</td>';
|
|
|
|
print '</tr>';
|
|
$i++;
|
|
}
|
|
|
|
if ($num == 0) {
|
|
print '<tr><td colspan="8" class="opacitymedium">'.$langs->trans("NoRecordFound").'</td></tr>';
|
|
}
|
|
|
|
print '</table>';
|
|
print '</div>';
|
|
print '</form>';
|
|
|
|
// End of page
|
|
llxFooter();
|
|
$db->close();
|