1296 lines
35 KiB
PHP
1296 lines
35 KiB
PHP
<?php
|
|
/*************************************************************************************/
|
|
/* */
|
|
/* Thelia - Plugin de combinaison des déclinaisons */
|
|
/* */
|
|
/* Copyright (c) Franck Allimant, 2011 */
|
|
/* email : franck.allimant@cqfdev.fr */
|
|
/* web : http://www.cqfdev.fr */
|
|
/* idée originale: Jean-Baptiste Billot (ottoroots@gmail.com) */
|
|
/* */
|
|
/* 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 2 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. */
|
|
/* */
|
|
/* You should have received a copy of the GNU General Public License */
|
|
/* along with this program; if not, write to the Free Software */
|
|
/* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|
/* */
|
|
/*************************************************************************************/
|
|
|
|
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/PluginsClassiques.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Rubdeclinaison.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Produit.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Declinaison.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Declidispdesc.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Exdecprod.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Stock.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/../../../classes/Variable.class.php");
|
|
|
|
include_once(realpath(dirname(__FILE__)) . "/CombidecliProduit.class.php");
|
|
include_once(realpath(dirname(__FILE__)) . "/CombidecliCommande.class.php");
|
|
|
|
class Combidecli extends PluginsClassiques
|
|
{
|
|
const MODULE = 'combidecli';
|
|
const NOMMODULE = 'Combidecli';
|
|
const VERSION = '0.991';
|
|
const PREFIXE = 'cd_';
|
|
|
|
const TABLE = 'combidecli';
|
|
|
|
public $id;
|
|
public $produit;
|
|
public $ref;
|
|
public $stock;
|
|
public $surplus;
|
|
public $actif;
|
|
|
|
public $label;
|
|
|
|
public $table = self::TABLE;
|
|
|
|
public $bddvars = array('id', 'produit', 'ref', 'stock', 'surplus', 'actif');
|
|
|
|
private $ordre_manuel = false;
|
|
private $ordre_reference = false;
|
|
|
|
private $lang;
|
|
|
|
public function Combidecli()
|
|
{
|
|
$this->PluginsClassiques(self::MODULE);
|
|
|
|
$this->lang = isset($_SESSION['navig']->lang) ? intval($_SESSION['navig']->lang) : 0;
|
|
|
|
if ($this->lang == 0) $this->lang = 1;
|
|
}
|
|
|
|
public function init()
|
|
{
|
|
$this->ajout_desc(
|
|
self::NOMMODULE,
|
|
"Déclinaisons combinées",
|
|
"Ce plugin permet de combiner vos déclinaisons, et de gérer stock et surplus pour chaque combinaison",
|
|
1);
|
|
|
|
$query = "
|
|
CREATE TABLE IF NOT EXISTS `".self::TABLE."` (
|
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
|
`produit` int(11) NOT NULL,
|
|
`ref` text,
|
|
`stock` float DEFAULT NULL,
|
|
`surplus` float DEFAULT NULL,
|
|
`actif` int(1) DEFAULT '1',
|
|
PRIMARY KEY (`id`),
|
|
KEY `ref` (`ref`(64),`produit`),
|
|
KEY `produit` (`produit`,`actif`)
|
|
)";
|
|
|
|
$this->_query($query);
|
|
|
|
CombidecliProduit::init();
|
|
CombidecliCommande::init();
|
|
}
|
|
|
|
public function destroy()
|
|
{
|
|
$this->_query("DROP TABLE IF EXISTS ".self::TABLE);
|
|
|
|
CombidecliProduit::destroy();
|
|
CombidecliCommande::destroy();
|
|
}
|
|
|
|
public function charger($id)
|
|
{
|
|
return $this->getVars("select * from $this->table where id=$id");
|
|
}
|
|
|
|
public function charger_ref($ref, $idproduit)
|
|
{
|
|
return $this->getVars("select * from $this->table where ref='$ref' and produit=$idproduit");
|
|
}
|
|
|
|
public function boucle($texte, $args)
|
|
{
|
|
$boucle = strtolower(lireTag($args, 'boucle'));
|
|
|
|
switch($boucle)
|
|
{
|
|
case 'combinaison':
|
|
return $this->boucleCombinaison($texte, $args);
|
|
break;
|
|
|
|
case 'declidisp':
|
|
return $this->boucleDeclidisp($texte, $args);
|
|
break;
|
|
|
|
case 'quantite':
|
|
return $this->boucleQuantite($texte, $args);
|
|
break;
|
|
|
|
case 'stock':
|
|
return $this->boucleStock($texte, $args);
|
|
break;
|
|
}
|
|
}
|
|
|
|
public function action()
|
|
{
|
|
global $ref, $quantite, $append, $nouveau, $parent;
|
|
|
|
if (isset($_REQUEST['action']) && $_REQUEST['action'] == 'ajouter_combidecli')
|
|
{
|
|
$produit = new Produit();
|
|
|
|
if ($produit->charger($ref))
|
|
{
|
|
// Construire la combinaison courante
|
|
$combi = $this->combinaison_courante($produit);
|
|
|
|
// $this->_debug("combi: ",$combi);
|
|
|
|
$surplus = 0;
|
|
|
|
if ($combi)
|
|
{
|
|
$perso = array();
|
|
|
|
$declidisp = new Declidisp();
|
|
$declinaison = new Declinaison();
|
|
|
|
$result = $this->_query("
|
|
select
|
|
d.id as declinaison, dd.id as declidisp
|
|
from
|
|
$declidisp->table dd
|
|
left join
|
|
$declinaison->table d on dd.declinaison = d.id
|
|
where
|
|
dd.id in ($combi->ref)
|
|
order by
|
|
d.classement
|
|
");
|
|
|
|
$combinees = array();
|
|
|
|
while ($result && $declidisp = mysql_fetch_object($result, 'Declidisp'))
|
|
{
|
|
$tmp = new Perso();
|
|
$tmp->declinaison = $declidisp->declinaison ;
|
|
$tmp->valeur = $declidisp->declidisp;
|
|
|
|
$perso[] = $tmp;
|
|
|
|
$combinees[] = $declidisp->declinaison;
|
|
}
|
|
|
|
// Ajouter les déclinaisons hors combinaison s'il y en a
|
|
foreach ($_REQUEST as $key => $valeur)
|
|
{
|
|
if (strstr($key, "declinaison"))
|
|
{
|
|
$decli = intval(substr($key, 11));
|
|
|
|
if ($decli > 0 && ! in_array($decli, $combinees))
|
|
{
|
|
$tmp = new Perso();
|
|
$tmp->declinaison = $decli;
|
|
$tmp->valeur = stripslashes($valeur);
|
|
|
|
$perso[] = $tmp;
|
|
}
|
|
}
|
|
}
|
|
|
|
// $this->_debug("Perso: ", $perso);
|
|
|
|
$tabarticle = &$_SESSION['navig']->panier->tabarticle;
|
|
|
|
$avaj = count($tabarticle);
|
|
|
|
// Ajouter le produit au panier (en désactivant temporairement la verif des stocks)
|
|
$vs = new Variable('verifstock');
|
|
|
|
$ovs = $vs->valeur;
|
|
|
|
$vs->valeur = 0;
|
|
$vs->maj();
|
|
|
|
$_SESSION['navig']->panier->ajouter($ref, $quantite, $perso, $append, $nouveau, $parent);
|
|
|
|
$vs->valeur = $ovs;
|
|
$vs->maj();
|
|
|
|
// Ajouter le surplus de la combinaison courante, uniquement si un article a été ajouté au pbnier
|
|
if ($avaj < count($tabarticle))
|
|
{
|
|
$art = count($tabarticle)-1;
|
|
|
|
// $this->_debug("prix: ",$tabarticle[count($tabarticle)-1]->produit->prix," surp: $combi->surplus");
|
|
|
|
$tabarticle[$art]->produit->prix += $combi->surplus;
|
|
$tabarticle[$art]->produit->prix2 += $combi->surplus;
|
|
|
|
if (! isset($_SESSION['combidecli'])) $_SESSION['combidecli'] = array();
|
|
|
|
$_SESSION['combidecli'][$art] = $combi->id;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ajouter($ref, $quantite, $append, $nouveau, $parent);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Corriger le stock du produit après une modif.
|
|
public function modprod($refproduit)
|
|
{
|
|
if ($refproduit instanceof Produit) $refproduit = $refproduit->ref;
|
|
|
|
// Si on n'a pas de combi ni de déclis actives, le stock du produit ne sera pas utilisé.
|
|
$utiliser_stock_produit = true;
|
|
|
|
$produit = new Produit();
|
|
|
|
if ($produit->charger($refproduit))
|
|
{
|
|
$result = $this->_query("select stock from $this->table where produit = $produit->id and actif <> 0");
|
|
|
|
$stock_total = 0;
|
|
|
|
while ($result && $combi = mysql_fetch_object($result))
|
|
{
|
|
$utiliser_stock_produit = false;
|
|
|
|
$stock_total += $combi->stock;
|
|
}
|
|
|
|
// Ajouter le stock des déclinaisons non combinées.
|
|
$dnc = $this->declinaisons_non_combinees($produit->id, $produit->rubrique);
|
|
|
|
foreach($dnc as $dec)
|
|
{
|
|
$utiliser_stock_produit = false;
|
|
|
|
// Lire les déclidps de la combinaison, et ajouter leur stock au stock total
|
|
$query = "
|
|
select
|
|
*
|
|
from
|
|
stock s
|
|
left join
|
|
declidisp dd on dd.id = s.declidisp
|
|
where
|
|
s.produit = $produit->id
|
|
and
|
|
dd.declinaison = $dec
|
|
and
|
|
dd.id not in (select declidisp from exdecprod where produit = $produit->id)
|
|
";
|
|
|
|
$result = $this->_query($query);
|
|
|
|
|
|
while ($result && $row = mysql_fetch_object($result))
|
|
{
|
|
$stock_total += $row->valeur;
|
|
}
|
|
}
|
|
|
|
if ($utiliser_stock_produit === false)
|
|
{
|
|
$produit->stock = $stock_total;
|
|
|
|
$produit->maj();
|
|
}
|
|
}
|
|
}
|
|
|
|
public function aprescommande($commande)
|
|
{
|
|
$idx = 0;
|
|
|
|
foreach($_SESSION['navig']->panier->tabarticle as $art)
|
|
{
|
|
if (isset($_SESSION['combidecli'][$idx]))
|
|
{
|
|
$combidecli = new Combidecli();
|
|
|
|
if ($combidecli->charger($_SESSION['combidecli'][$idx]))
|
|
{
|
|
$combidecli->stock -= $art->quantite;
|
|
$combidecli->maj();
|
|
|
|
// Mettre l'historique à jour
|
|
$cdc = new CombidecliCommande();
|
|
|
|
$cdc->commande = $commande->id;
|
|
$cdc->combidecli = $combidecli->id;
|
|
$cdc->quantite = $art->quantite;
|
|
|
|
$cdc->add();
|
|
}
|
|
}
|
|
|
|
$idx++;
|
|
}
|
|
}
|
|
|
|
// Retour en stock sur les combinaisons
|
|
public function statut($commande)
|
|
{
|
|
if ($commande->statut == 5)
|
|
{
|
|
|
|
// Remettre en stock les combinaisons concernées.
|
|
$combicmds = CombidecliCommande::lister_par_commande($commande->id);
|
|
|
|
$combi = new Combidecli();
|
|
|
|
foreach($combicmds as $combicmd)
|
|
{
|
|
if ($combi->charger($combicmd->combidecli))
|
|
{
|
|
$combi->stock += $combicmd->quantite;
|
|
|
|
$combi->maj();
|
|
}
|
|
|
|
$combicmd->delete();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Suppression d'un produit
|
|
// On reçoit en fait la ref... Donc on ne peut plus retrouver l'ID du produit, il a été supprimé dans produit_modifier.php !
|
|
public function supprod($refproduit)
|
|
{
|
|
$result = $this->_query("select produit FROM $this->table WHERE produit not in (select id from produit)");
|
|
|
|
while ($result && $row = mysql_fetch_object($result))
|
|
{
|
|
CombidecliProduit::supprimer_par_produit($row->produit);
|
|
}
|
|
}
|
|
|
|
public function _query($sql, $log = false)
|
|
{
|
|
if ($log) echo "<br/>SQL:$sql";
|
|
|
|
$result = mysql_query($sql, $this->link);
|
|
|
|
if ($result === false) die('Erreur SQL:'.mysql_error().': ' . $sql);
|
|
|
|
return $result;
|
|
}
|
|
|
|
public function _escape($value)
|
|
{
|
|
if(get_magic_quotes_gpc()) $value = stripslashes($value);
|
|
|
|
return mysql_real_escape_string($value);
|
|
}
|
|
|
|
|
|
/*
|
|
* Appelle une boucle et retourne les variables valuées dans une table.
|
|
* Exemple d'appel:
|
|
* $this->wrapboucle(
|
|
* 'boucleProduit',
|
|
* array('ID', 'REF', 'TITRE'),
|
|
* array('rubrique' => 12, 'classement' => 'manuel')
|
|
* );
|
|
*
|
|
* La methode retourne un tableau comportant autant d'éléments que
|
|
* de 'tours' de boucle, chaque élément étant un tableau associatif
|
|
* var => valeur. Exemple:
|
|
*
|
|
* Array(
|
|
* [0] => Array(
|
|
* '#ID' => 1,
|
|
* '#REF' => 'ABC',
|
|
* '#TITRE' => 'un produit'
|
|
* ),
|
|
* [1] => Array(
|
|
* '#ID' => 4,
|
|
* '#REF' => 'DEF',
|
|
* '#TITRE' => 'un autre produit'
|
|
* )
|
|
*
|
|
* etc..
|
|
* );
|
|
*/
|
|
public function wrapboucle($boucle, $variables_sans_diese, $arguments)
|
|
{
|
|
$texte = '';
|
|
$resultat = array();
|
|
|
|
foreach($variables_sans_diese as $var)
|
|
{
|
|
$texte .= $var . chr(5) . '#' . $var . chr(6);
|
|
}
|
|
|
|
$texte .= rtrim($texte, chr(6)) . chr(7);
|
|
|
|
$args = '';
|
|
|
|
foreach($arguments as $nom => $val) $args .= $nom . '="' . $val . '" ';
|
|
|
|
// $this->_debug('texte', $texte, 'args=', $args);
|
|
|
|
$res = $boucle($texte, $args);
|
|
|
|
// $this->_debug('wrap result', $res);
|
|
|
|
if ($res != '')
|
|
{
|
|
$res = rtrim($res, chr(7));
|
|
|
|
$lignes = explode(chr(7), $res);
|
|
|
|
foreach($lignes as $ligne)
|
|
{
|
|
$vars = array();
|
|
|
|
$colonnes = explode(chr(6), $ligne);
|
|
|
|
foreach($colonnes as $colonne)
|
|
{
|
|
list($var, $value) = explode(chr(5), $colonne);
|
|
|
|
$vars['#'.$var] = $value;
|
|
}
|
|
|
|
$resultat[] = $vars;
|
|
}
|
|
}
|
|
|
|
// $this->_debug("Final: ",$resultat);
|
|
|
|
return $resultat;
|
|
}
|
|
|
|
// Methodes privées
|
|
// ----------------
|
|
|
|
public function _debug()
|
|
{
|
|
$text = '';
|
|
|
|
$numargs = func_num_args();
|
|
|
|
for($idx = 0; $idx < $numargs; $idx++)
|
|
{
|
|
$arg = func_get_arg($idx);
|
|
|
|
$text .= is_scalar($arg) ? $arg : print_r($arg, true);
|
|
}
|
|
|
|
echo '<pre style="text-align: left; margin: 0; padding: 0;">[DEBUG] ' . htmlspecialchars($text)."</pre>";
|
|
}
|
|
|
|
// Valeur courante de paramètres importants pour pour le calcul
|
|
// de la déclinaison par defaut.
|
|
// Memorise les paramètres stockmini et classement indiqués dans les boucles,
|
|
// afin de les réutiliser s'ils ne sont pas spécifiés.
|
|
private static $valeurs_defaut = array();
|
|
|
|
protected function lireTagPrev($args, $nom, $type = 'string')
|
|
{
|
|
$val = lireTag($args, $nom, $type);
|
|
|
|
//$this->_debug("args: $args, $nom=$val");
|
|
|
|
if ($val == '')
|
|
{
|
|
if (isset(self::$valeurs_defaut[$nom])) $val = self::$valeurs_defaut[$nom];
|
|
}
|
|
else
|
|
{
|
|
self::$valeurs_defaut[$nom] = $val;
|
|
}
|
|
|
|
//$this->_debug("valeur: $nom=$val");
|
|
|
|
return $val;
|
|
}
|
|
|
|
// Retourne la liste des déclinaisons non combinées (ou test si une declinaison est combinee si $iddeclinaison != false)
|
|
protected function declinaisons_non_combinees($idproduit, $idrubrique, $stockmini = 0, $iddeclinaison = false)
|
|
{
|
|
$declinaisons = array();
|
|
|
|
// Verfier qu'il existe des déclidisps actives hors combinaison et avec le stock voulu sur la declinaison courante (à la COMBIX)
|
|
$rd = new Rubdeclinaison();
|
|
$d = new Declinaison();
|
|
$dd = new Declidisp();
|
|
$s = new Stock();
|
|
$ex = new Exdecprod();
|
|
|
|
$where = $iddeclinaison !== false ? "and dd.declinaison = $iddeclinaison" : '';
|
|
|
|
$result = $this->_query("
|
|
select distinct
|
|
dd.declinaison as iddeclinaison
|
|
from
|
|
$rd->table rd
|
|
left join
|
|
$dd->table dd on dd.declinaison = rd.declinaison
|
|
left join
|
|
$s->table s on s.declidisp = dd.id
|
|
left join
|
|
$d->table d on d.id = dd.declinaison
|
|
where
|
|
rd.rubrique = $idrubrique
|
|
and
|
|
s.produit = $idproduit
|
|
$where
|
|
and
|
|
s.valeur >= $stockmini
|
|
and
|
|
s.declidisp not in (select declidisp from $ex->table where produit = $idproduit)
|
|
and
|
|
d.id not in (select declinaison from ".CombidecliProduit::TABLE." where produit = $idproduit)
|
|
order by
|
|
d.classement
|
|
");
|
|
|
|
while($result && $row = mysql_fetch_object($result))
|
|
{
|
|
$declinaisons[] = $row->iddeclinaison;
|
|
}
|
|
|
|
return $declinaisons;
|
|
}
|
|
// Lire toutes les declidisps pour un produit et éventuellement une déclinaison
|
|
// Retourne false si aucune combinaison n'a été trouvée (e.g., les combinaisons ne sont pas activées pour le produit)
|
|
// Sinon, retourne un tableau des declinaisons actives avec le stock requis.
|
|
private function lire_declidisps_pour_produit($idproduit, $iddeclinaison = 0, $stockmini = 0, $filtre = false)
|
|
{
|
|
$like = $filtre ? "AND ref LIKE '$filtre'" : '';
|
|
|
|
$query = "
|
|
SELECT
|
|
*
|
|
FROM
|
|
$this->table
|
|
WHERE
|
|
produit = $idproduit
|
|
$like
|
|
ORDER BY
|
|
id
|
|
";
|
|
|
|
$result = $this->_query($query);
|
|
|
|
if ($result)
|
|
{
|
|
if (mysql_numrows($result) > 0)
|
|
{
|
|
$declidisps = array();
|
|
|
|
while ($combinaison = mysql_fetch_object($result, 'Combidecli'))
|
|
{
|
|
if ($combinaison->stock >= $stockmini && $combinaison->actif != 0)
|
|
{
|
|
$iddeclidisps = explode(',', $combinaison->ref);
|
|
|
|
foreach($iddeclidisps as $iddeclidisp)
|
|
{
|
|
$declidisp = new Declidisp();
|
|
|
|
if ($declidisp->charger($iddeclidisp) && ($iddeclinaison == 0 || $iddeclinaison == $declidisp->declinaison) )
|
|
{
|
|
$declidisps[] = $declidisp;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return $declidisps;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
// Retrouve l'ordre de base des déclinaisons, celui avec lequel la ref des combinaisons est ordonnée
|
|
private function ordre_declinaisons($produit)
|
|
{
|
|
if (! $this->ordre_manuel)
|
|
{
|
|
$this->ordre_manuel = array();
|
|
|
|
$rd = new Rubdeclinaison();
|
|
$d = new Declinaison();
|
|
$dd = new Declidisp();
|
|
$edp = new Exdecprod();
|
|
$cdp = new CombidecliProduit();
|
|
|
|
// Trouver les declinaisons ayant au moins une déclidisp active sur le produit courant
|
|
$result = $this->_query("
|
|
select distinct
|
|
d.id
|
|
from
|
|
declidisp dd
|
|
left join
|
|
$d->table d on d.id = dd.declinaison
|
|
where
|
|
dd.id not in (select $dd->table from exdecprod where produit=$produit->id)
|
|
and
|
|
d.id in (select declinaison from $rd->table where rubrique=$produit->rubrique)
|
|
and
|
|
d.id in (select declinaison from $cdp->table where produit=$produit->id)
|
|
order by
|
|
d.classement
|
|
");
|
|
|
|
while ($result && $decli = mysql_fetch_object($result))
|
|
{
|
|
$this->ordre_manuel[] = $decli->id;
|
|
}
|
|
|
|
// Ordre naturel des référence (e.g., triées par ID declidisp croissant)
|
|
$this->ordre_reference = $this->ordre_manuel;
|
|
|
|
sort($this->ordre_reference);
|
|
}
|
|
|
|
return count($this->ordre_manuel);
|
|
}
|
|
|
|
// Determiner si une combinaison (ou une portion de combinaison) est valide
|
|
private function lire_ref($produit, $stockmini, $ref_combinaison)
|
|
{
|
|
// $this->_debug("lire_ref ",$ref_combinaison);
|
|
|
|
$result = $this->_query("
|
|
SELECT
|
|
*
|
|
from
|
|
$this->table
|
|
where
|
|
produit=$produit->id
|
|
and
|
|
stock >= $stockmini
|
|
and
|
|
actif <> 0
|
|
and
|
|
ref like '$ref_combinaison'
|
|
order by
|
|
id
|
|
limit 0,1
|
|
");
|
|
|
|
if ($result && $combi = mysql_fetch_object($result, 'Combidecli'))
|
|
return $combi;
|
|
else
|
|
return false;
|
|
}
|
|
|
|
// Trouver le filtre qui convient pour retrouver les declidisp possibles
|
|
// de la déclinaison indiquée, en fonction du contexte et de l'ordre
|
|
// d'affichage des déclinaisons.
|
|
private function filtre_combinaison($produit, $stockmini, $declinaison = 0)
|
|
{
|
|
// Retrouver l'ordre des declinaisons tel qu'utilisé pour calculer la ref combinaison
|
|
$nbdeclis = $this->ordre_declinaisons($produit);
|
|
|
|
if ($nbdeclis <= 0) return '';
|
|
|
|
$ref_combinaison = array_fill(0, $nbdeclis, '%');
|
|
|
|
$idx = 0;
|
|
|
|
// $this->_debug("Ordre declis: ", $this->ordre_manuel);
|
|
// $this->_debug("Ordre naturel: ", $this->ordre_reference);
|
|
|
|
foreach($this->ordre_manuel as $iddeclinaison)
|
|
{
|
|
$test_combinaison = $ref_combinaison;
|
|
|
|
// Trouver la position de la déclinaison courante dans la ref combinaison
|
|
for($pos = 0; $pos < $nbdeclis; $pos++)
|
|
{
|
|
if ($this->ordre_reference[$pos] == $iddeclinaison) break;
|
|
}
|
|
|
|
$curr_declidisp = intval($_REQUEST['declinaison'.$iddeclinaison]);
|
|
|
|
// $this->_debug("idx=$idx, pos $iddeclinaison=$pos,>declinaison[$iddeclinaison]=$curr_declidisp");
|
|
|
|
if ($declinaison == $iddeclinaison && (! $exact))
|
|
{
|
|
// $this->_debug("$idx:CURRENT");
|
|
|
|
// On va récupérer toutes les declidisp possibles (on laisse '%' dans la ref)
|
|
break;
|
|
}
|
|
else if ($curr_declidisp > 0)
|
|
{
|
|
// $this->_debug("$idx:DEFINED AND VALIDE:$curr_declidisp");
|
|
|
|
// On utilise la déclidisp selectionnée
|
|
$test_combinaison[$pos] = $curr_declidisp;
|
|
}
|
|
else
|
|
{
|
|
// $this->_debug("$idx:SEARCH");
|
|
|
|
// Trouver la première combinaison qui matche
|
|
$search_ref = implode(',', $test_combinaison);
|
|
|
|
if ($combi = $this->lire_ref($produit, $stockmini, implode(',', $test_combinaison)))
|
|
{
|
|
// $this->_debug("found ref for $search_ref", $combi->ref);
|
|
|
|
$refs = explode(',', $combi->ref);
|
|
|
|
$test_combinaison[$pos] = $refs[$pos];
|
|
}
|
|
else
|
|
{
|
|
// $this->_debug("Nothing found");
|
|
break;
|
|
}
|
|
}
|
|
|
|
// On arrête dès qu'on ne trouve plus de combinaison valide
|
|
$valide = $this->lire_ref($produit, $stockmini, implode(',', $test_combinaison));
|
|
|
|
// $this->_debug("ref:", implode(',', $ref_combinaison),", test=", implode(',', $test_combinaison), ", valide:", ($valide !== false));
|
|
|
|
// La nouvelle n'est pas valide => on utilise la précédente et on termine
|
|
if (! $valide) break;
|
|
|
|
$ref_combinaison = $test_combinaison;
|
|
|
|
$idx++;
|
|
}
|
|
|
|
$ref_combinaison = implode(',', $ref_combinaison);
|
|
|
|
// $this->_debug("Ref pour $declinaison: $ref_combinaison");
|
|
|
|
return $ref_combinaison;
|
|
}
|
|
|
|
private function combinaison_courante($produit, $stockmini = 0)
|
|
{
|
|
$ref_courante = $this->filtre_combinaison($produit, $stockmini);
|
|
|
|
// $this->_debug("combinaison_courante: $ref_courante");
|
|
|
|
return $this->lire_ref($produit, $stockmini, $ref_courante);
|
|
}
|
|
|
|
private function get_declidispdesc_classement($prefixe_table, $classement)
|
|
{
|
|
if ($classement == "alpha")
|
|
return "order by $prefixe_table.titre";
|
|
else if ($classement == "alphainv")
|
|
return "order by $prefixe_table.titre desc";
|
|
else if ($classement == "manuel")
|
|
return "order by $prefixe_table.classement";
|
|
else
|
|
return '';
|
|
}
|
|
|
|
// Trouve le stock et le surplus d'un produit ou d'un article.
|
|
|
|
private function trouver_stock_et_surplus($produit, $article, $stockmini, $classement, &$surplus, &$stockproduit)
|
|
{
|
|
// $this->_debug("trouver_stock_et_surplus: p=$produit->id, a=$article, s=$stockmini, c=$classement");
|
|
|
|
$utiliser_stock_produit = true;
|
|
|
|
$combi = false;
|
|
|
|
if ($article !== false)
|
|
{
|
|
$produit = $_SESSION['navig']->panier->tabarticle[$article]->produit;
|
|
|
|
if (isset($_SESSION['combidecli'][$article]))
|
|
{
|
|
$combi = new Combidecli();
|
|
|
|
$combi->charger($_SESSION['combidecli'][$article]);
|
|
}
|
|
}
|
|
else if ($produit)
|
|
{
|
|
// Construire la combinaison courante
|
|
$combi = $this->combinaison_courante($produit, $stockmini);
|
|
}
|
|
|
|
//$this->_debug("Combi = ",$this->combinaison_courante($produit, $stockmini));
|
|
|
|
$surplus = 0;
|
|
$stockproduit = 0;
|
|
|
|
if ($combi)
|
|
{
|
|
$surplus += $combi->surplus;
|
|
$stockproduit += $combi->stock;
|
|
|
|
$utiliser_stock_produit = false;
|
|
}
|
|
|
|
// Retrouver stock & surplus des éventuelles declinaisons non combinees, pour l'ajouter au prix
|
|
// le stock de ces déclinaisons est ajouté au stock de la combinaison (si elle existe)
|
|
$declinaisons_nc = $this->declinaisons_non_combinees($produit->id, $produit->rubrique, $stockmini);
|
|
|
|
foreach($declinaisons_nc as $declinaison)
|
|
{
|
|
// Trouver la declidisp couramment selectionnee,
|
|
// ou trouver la 1ere déclidisp a afficher.
|
|
|
|
if (isset($_REQUEST['declinaison'.$declinaison]))
|
|
{
|
|
$declidisp = intval($_REQUEST['declinaison'.$declinaison]);
|
|
|
|
$stock = new Stock();
|
|
|
|
if ($stock->charger($declidisp, $produit->id))
|
|
{
|
|
$surplus += $stock->surplus;
|
|
$stockproduit += $stock->valeur;
|
|
|
|
$utiliser_stock_produit = false;
|
|
}
|
|
}
|
|
else if ($article !== false) {
|
|
// Dans le panier, déterminer quelle est la declidisp choisie pour cette declinaison
|
|
$art = $_SESSION['navig']->panier->tabarticle[$article];
|
|
|
|
foreach($art->perso as $perso) {
|
|
if ($perso->declinaison == $declinaison) {
|
|
|
|
$stock = new Stock();
|
|
|
|
if ($stock->charger($perso->valeur, $art->produit->id))
|
|
{
|
|
$surplus += $stock->surplus;
|
|
$stockproduit += $stock->valeur;
|
|
|
|
$utiliser_stock_produit = false;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// Trouver la 1ere déclidisp
|
|
// ATTENTION: il faut que le classement soit le même que pour l'affichage
|
|
// des choix de déclidisp, d'ou le paramètre 'classement'
|
|
$ex = new Exdecprod();
|
|
$dd = new Declidisp();
|
|
$ddd = new Declidispdesc();
|
|
$s = new Stock();
|
|
|
|
$order = $this->get_declidispdesc_classement('ddd', $classement);
|
|
|
|
$result = $this->_query("
|
|
select
|
|
s.*
|
|
from
|
|
$dd->table dd
|
|
left join
|
|
$ddd->table as ddd on ddd.declidisp = dd.id
|
|
left join
|
|
$s->table s on s.declidisp = dd.id
|
|
where
|
|
dd.declinaison = $declinaison
|
|
and
|
|
s.produit = $produit->id
|
|
and
|
|
s.valeur >= $stockmini
|
|
and
|
|
s.declidisp not in (select declidisp from $ex->table where produit = $produit->id)
|
|
$order
|
|
limit 1
|
|
");
|
|
|
|
if ($result && $stock = mysql_fetch_object($result, 'Stock'))
|
|
{
|
|
$surplus += $stock->surplus;
|
|
$stockproduit += $stock->valeur;
|
|
|
|
$utiliser_stock_produit = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Pas de combinaison ni de declidisp trouvées ? le stock est celui du produit.
|
|
if ($utiliser_stock_produit === true)
|
|
{
|
|
$stockproduit = $produit->stock;
|
|
}
|
|
|
|
// $this->_debug("$produit->id, $article, $stockmini, $classement, &$surplus, &$stockproduit");
|
|
|
|
return $combi;
|
|
}
|
|
|
|
private function boucleCombinaison($texte, $args)
|
|
{
|
|
$res = '';
|
|
|
|
$iddeclinaison = intval(lireTag($args, "id"));
|
|
$idproduit = intval(lireTag($args, "produit"));
|
|
$stockmini = intval($this->lireTagPrev($args, "stockmini", 'int'));
|
|
$forcecombinaisons = intval(lireTag($args, "forcecombinaisons"));
|
|
|
|
$declidisps = $this->lire_declidisps_pour_produit($idproduit, 0, $stockmini);
|
|
|
|
// $this->_debug("declidisps: ", $declidisps);
|
|
|
|
if ($declidisps !== false)
|
|
{
|
|
$declinaisons = array();
|
|
|
|
foreach($declidisps as $declidisp)
|
|
{
|
|
if (! in_array($declidisp->declinaison, $declinaisons))
|
|
{
|
|
$declinaisons[] = $declidisp->declinaison;
|
|
}
|
|
}
|
|
|
|
if (count($declinaisons) > 0)
|
|
{
|
|
$declinaison = new Declinaison();
|
|
$declinaisondesc = new Declinaisondesc();
|
|
|
|
// Afficher les déclinaisons classées dans l'ordre indiqué
|
|
|
|
// Afficher les déclinaisons classées dans l'ordre indiqué
|
|
$result = $this->_query("SELECT id from $declinaison->table where id in (".implode(',', $declinaisons).") order by classement");
|
|
|
|
$ids = array();
|
|
|
|
while ($result && $row = mysql_fetch_object($result)) $ids[] = $row->id;
|
|
|
|
// Il faut masquer le paramètre stockmini, pour ne pas prendre en compte
|
|
// le stock des déclis dans la boucle declinaison (1.4.4)
|
|
$pargs = str_replace('stockmini', '_combidecli_stock_mini_', $args);
|
|
|
|
$res = boucleDeclinaison($texte, $pargs . 'id="'.implode(',', $ids).'"');
|
|
}
|
|
}
|
|
|
|
// Afficher aussi les déclinaisons qui ne sont pas combinées, si c'est demandé.
|
|
if ($forcecombinaisons == 0)
|
|
{
|
|
$produit = new Produit();
|
|
|
|
if ($produit->charger_id($idproduit))
|
|
{
|
|
if ($iddeclinaison != 0) $where = "and dd.declinaison = $iddeclinaison";
|
|
|
|
// Verfier qu'il existe des déclidisps actives hors combinaison et avec le stock voulu sur la declinaison courante (à la COMBIX)
|
|
$rd = new Rubdeclinaison();
|
|
$d = new Declinaison();
|
|
$dd = new Declidisp();
|
|
$s = new Stock();
|
|
$ex = new Exdecprod();
|
|
|
|
$result = $this->_query("
|
|
select distinct
|
|
dd.declinaison as iddeclinaison
|
|
from
|
|
$rd->table rd
|
|
left join
|
|
$dd->table dd on dd.declinaison = rd.declinaison
|
|
left join
|
|
$s->table s on s.declidisp = dd.id
|
|
left join
|
|
$d->table d on d.id = dd.declinaison
|
|
where
|
|
rd.rubrique = $produit->rubrique
|
|
and
|
|
s.produit = $idproduit
|
|
$where
|
|
and
|
|
s.valeur >= $stockmini
|
|
and
|
|
s.declidisp not in (select declidisp from $ex->table where produit = $idproduit)
|
|
and
|
|
d.id not in (select declinaison from ".CombidecliProduit::TABLE." where produit = $idproduit)
|
|
order by
|
|
d.classement
|
|
");
|
|
|
|
// Retrouver toutes les declinaisons non combinees, ayant au moins une déclidisp avec le stock requis
|
|
$declinaisons_nc = $this->declinaisons_non_combinees($idproduit, $produit->rubrique, $stockmini);
|
|
|
|
foreach($declinaisons_nc as $declinaison)
|
|
{
|
|
$pargs = 'id="'.$declinaison.'" '.preg_replace('/id="[0-9]*"/', '', $args);
|
|
|
|
$res .= boucleDeclinaison($texte, $pargs);
|
|
}
|
|
}
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
private function boucleDeclidisp($texte, $args)
|
|
{
|
|
$res = '';
|
|
|
|
$iddeclinaison = intval(lireTag($args, "declinaison"));
|
|
$idproduit = intval(lireTag($args, "produit"));
|
|
$stockmini = intval($this->lireTagPrev($args, "stockmini", 'int'));
|
|
$classement = $this->lireTagPrev($args, "classement", 'string');
|
|
$courante = intval(lireTag($args, "courante"));
|
|
$num = lireTag($args, "num", "int");
|
|
|
|
$order = $this->get_declidispdesc_classement('ddd', $classement);
|
|
|
|
$produit = new Produit();
|
|
|
|
if ($produit->charger_id($idproduit))
|
|
{
|
|
$filtre = $this->filtre_combinaison($produit, $stockmini, $iddeclinaison);
|
|
|
|
$declidisps = $this->lire_declidisps_pour_produit($idproduit, $iddeclinaison, $stockmini, $filtre);
|
|
|
|
// $this->_debug("Decli: $iddeclinaison, v=$declidisp, filtre=$filtre, declidisps:", $declidisps);
|
|
|
|
if ($declidisps !== false)
|
|
{
|
|
$occ_declidisp = array();
|
|
|
|
foreach($declidisps as $declidisp)
|
|
{
|
|
if (! in_array($declidisp->id, $occ_declidisp))
|
|
{
|
|
$occ_declidisp[] = $declidisp->id;
|
|
}
|
|
}
|
|
|
|
// $this->_debug('occ_declidisp:',$occ_declidisp);
|
|
|
|
if (count($occ_declidisp) > 0)
|
|
{
|
|
$declidispdesc = new Declidispdesc();
|
|
$declidisp = new Declidisp();
|
|
|
|
// Afficher les declidisp classées dans l'ordre demandé
|
|
$result = $this->_query("
|
|
SELECT
|
|
dd.*, ddd.titre
|
|
FROM
|
|
$declidisp->table dd
|
|
LEFT JOIN
|
|
$declidispdesc->table ddd on ddd.declidisp = dd.id and ddd.lang = $this->lang
|
|
WHERE
|
|
dd.id in (".implode(',', $occ_declidisp).")
|
|
$order
|
|
");
|
|
|
|
// Trouver la declidisp selectionnée
|
|
if ( ($curdeclidisp = intval($_REQUEST['declinaison'.$iddeclinaison])) == 0)
|
|
{
|
|
- $curdeclidisp = $occ_declidisp[0];
|
|
}
|
|
|
|
$count = 0;
|
|
|
|
while ($result && ($num == '' || $count < $num) && $row = mysql_fetch_object($result))
|
|
{
|
|
if ($courante > 0 && $curdeclidisp != $row->id) continue;
|
|
|
|
$temp = $texte;
|
|
|
|
$selected = $curdeclidisp == $row->id ? 1 : 0;
|
|
|
|
$temp = str_replace("#ID", $row->id, $temp);
|
|
$temp = str_replace("#DECLINAISON", $row->declinaison, $temp);
|
|
$temp = str_replace("#TITRE", $row->titre, $temp);
|
|
$temp = str_replace("#PRODUIT", $idproduit, $temp);
|
|
$temp = str_replace("#SELECTED", $selected, $temp);
|
|
|
|
$res .= $temp;
|
|
|
|
$count++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Si il existe des déclinaisons non combinées, on affiche ses déclidisp avec la boucle classique,
|
|
// en ajoutant l'information #SELECTED. On a en principe une seule declinaison, car l'ID de la declinaison
|
|
// est passée à cette boucle.
|
|
$declinaisons_nc = $this->declinaisons_non_combinees($idproduit, $produit->rubrique, $stockmini, $iddeclinaison);
|
|
|
|
// $this->_debug('declinaisons non combinées: ', $declinaisons_nc);
|
|
|
|
foreach ($declinaisons_nc as $declinaison)
|
|
{
|
|
// Appel (wrappé) de la boucle déclidisp, pour ajouter l'information 'selected'
|
|
$wrap = $this->wrapboucle(
|
|
'boucleDeclidisp',
|
|
array('ID', 'DECLINAISON', 'TITRE', 'PRODUIT'),
|
|
array(
|
|
'declinaison' => $declinaison,
|
|
'produit' => $idproduit,
|
|
'stockmini' => $stockmini,
|
|
'classement' => $classement,
|
|
'num' => $num
|
|
)
|
|
);
|
|
|
|
// $this->_debug('wrap:',$wrap);
|
|
|
|
// La valeur selectionnée
|
|
$selected = isset($_REQUEST['declinaison'.$declinaison]) ? intval($_REQUEST['declinaison'.$declinaison]) : 0;
|
|
|
|
foreach($wrap as $ln)
|
|
{
|
|
$iddeclidisp = $ln['#ID'];
|
|
|
|
// Si aucune declidisp n'est selectionnée, la première est selectionnée par défaut
|
|
if ($selected == 0) $selected = $iddeclidisp;
|
|
|
|
$ln['#SELECTED'] = $selected == $iddeclidisp ? 1 : 0;
|
|
|
|
if ($courante > 0 && $ln['#SELECTED'] == 0) continue;
|
|
|
|
$res .= str_replace(array_keys($ln), array_values($ln), $texte);
|
|
}
|
|
|
|
// $this->_debug('res decli non combinées=', $res);
|
|
}
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
/*
|
|
* Le stock est calculé comme suit:
|
|
*
|
|
* 1) combinaison totale: stock de la combinaison courante
|
|
* 2) combinaison partielle: stock de la combinaison courante + somme des stocks des déclidisp courantes
|
|
* 3) pas de combinaison, déclinaisons actives: somme des stocks des déclidisp courantes
|
|
* 4) pas de déclinaisons (ou toutes déclidisps désactivées) => stock produit
|
|
*
|
|
* Le surplus est calculé comme suit:
|
|
*
|
|
* 1) combinaison totale: surplus de la combinaison courante
|
|
* 2) combinaison partielle: surplus de la combinaison courante + somme des surplus des déclidisp courantes
|
|
* 3) pas de combinaison, déclinaisons actives: somme des surplus des déclidisp courantes
|
|
* 4) pas de déclinaisons (ou toutes déclidisps désactivées) => 0 (aucun surplus)
|
|
*/
|
|
private function boucleStock($texte, $args)
|
|
{
|
|
$res = '';
|
|
|
|
$idproduit = intval(lireTag($args, "produit"));
|
|
$stockmini = intval($this->lireTagPrev($args, "stockmini", 'int'));
|
|
$classement = $this->lireTagPrev($args, "classement", "string");
|
|
|
|
$produit = new Produit();
|
|
|
|
if ($produit->charger_id($idproduit))
|
|
{
|
|
$surplus = 0;
|
|
$stockproduit = 0;
|
|
|
|
$this->trouver_stock_et_surplus($produit, false, $stockmini, $classement, $surplus, $stockproduit);
|
|
|
|
$produit->prix += $surplus;
|
|
$produit->prix2 += $surplus;
|
|
|
|
$res = $texte;
|
|
|
|
$res = preg_replace("/\#PROMO\[([^]]*)\]\[([^]]*)\]/", $produit->promo == 1 ? "\\1" : "\\2", $res);
|
|
|
|
$res = str_replace("#VALEUR", $stockproduit, $res);
|
|
|
|
$res = str_replace("#PRIX2", $produit->prix2, $res);
|
|
$res = str_replace("#PRIX", $produit->prix, $res);
|
|
$res = str_replace("#SURPLUS", $surplus, $res);
|
|
$res = str_replace("#PRODUIT", $idproduit, $res);
|
|
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
|
|
private function boucleQuantite($texte, $args)
|
|
{
|
|
$res = '';
|
|
|
|
$article = lireTag($args, "article", "int");
|
|
$idproduit = intval(lireTag($args, "produit", "int"));
|
|
$ref = lireTag($args, "ref", "string");
|
|
$max = lireTag($args, "max", "int");
|
|
$min = lireTag($args, "min", "int");
|
|
$force = lireTag($args, "force", "int");
|
|
$valeur = lireTag($args, "valeur", "int");
|
|
|
|
|
|
// Utiliser imperativement les valeurs précedemment indiquées de stockmini et classement,
|
|
// sinon on ne retrouve pas la combinaison par defaut.
|
|
$stockmini = intval(self::$valeurs_defaut["stockmini"]);
|
|
$classement = self::$valeurs_defaut["classement"];
|
|
|
|
$produit = new Produit();
|
|
|
|
$surplus = $stockproduit = 0;
|
|
|
|
if ($article != "")
|
|
{
|
|
$this->trouver_stock_et_surplus(false, $article, $stockmini, $classement, $surplus, $stockproduit);
|
|
}
|
|
else if ( ($ref != "" && $produit->charger($ref)) || ($idproduit > 0 && $produit->charger_id($idproduit)) )
|
|
{
|
|
$this->trouver_stock_et_surplus($produit, false, $stockmini, $classement, $surplus, $stockproduit);
|
|
}
|
|
|
|
if ($min == '') $min = 1;
|
|
|
|
if ($max == '' || $max > $stockproduit) $max = $stockproduit;
|
|
|
|
if ($force != '' && $valeur != '')
|
|
{
|
|
$min = 1;
|
|
$max = intval($valeur);
|
|
}
|
|
|
|
if ($stockproduit >= $min)
|
|
{
|
|
for($idx = $min; $idx <= $max; $idx++)
|
|
{
|
|
if ($idx == $_SESSION['navig']->panier->tabarticle[$article]->quantite)
|
|
$selected = 'selected="selected"';
|
|
else
|
|
$selected = '';
|
|
|
|
$temp = str_replace("#NUM", $idx, $texte);
|
|
$temp = str_replace("#SELECTED", $selected, $temp);
|
|
$temp = str_replace("#REF", $ref, $temp);
|
|
|
|
$res .= $temp;
|
|
}
|
|
}
|
|
|
|
return $res;
|
|
}
|
|
}
|
|
?>
|