combinations.php 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836
  1. <?php
  2. /* Copyright (C) 2016 Marcos García <marcosgdf@gmail.com>
  3. * Copyright (C) 2017 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2018 Frédéric France <frederic.france@netlogic.fr>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. require '../main.inc.php';
  20. require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
  21. require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
  22. require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttribute.class.php';
  23. require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductAttributeValue.class.php';
  24. require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
  25. require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination2ValuePair.class.php';
  26. $langs->loadLangs(array("products", "other"));
  27. $id = GETPOST('id', 'int');
  28. $valueid = GETPOST('valueid', 'int');
  29. $ref = GETPOST('ref');
  30. $weight_impact = (float) GETPOST('weight_impact');
  31. $price_impact = (float) GETPOST('price_impact');
  32. $price_impact_percent = (bool) GETPOST('price_impact_percent');
  33. $form = new Form($db);
  34. $action=GETPOST('action','alpha');
  35. $massaction=GETPOST('massaction','alpha');
  36. $show_files=GETPOST('show_files','int');
  37. $confirm=GETPOST('confirm','alpha');
  38. $toselect = GETPOST('toselect', 'array');
  39. $cancel = GETPOST('cancel','alpha');
  40. // Security check
  41. $fieldvalue = (! empty($id) ? $id : $ref);
  42. $fieldtype = (! empty($ref) ? 'ref' : 'rowid');
  43. $result=restrictedArea($user,'produit|service',$fieldvalue,'product&product','','',$fieldtype);
  44. $prodstatic = new Product($db);
  45. $prodattr = new ProductAttribute($db);
  46. $prodattr_val = new ProductAttributeValue($db);
  47. $object = new Product($db);
  48. if ($id > 0 || $ref)
  49. {
  50. $object->fetch($id, $ref);
  51. }
  52. $selectedvariant = $_SESSION['addvariant_'.$object->id];
  53. /*
  54. * Actions
  55. */
  56. if ($cancel) {
  57. $action='';
  58. $massactions='';
  59. unset($_SESSION['addvariant_'.$object->id]);
  60. }
  61. if (! $object->isProduct() && ! $object->isService()) {
  62. header('Location: '.dol_buildpath('/product/card.php?id='.$object->id, 2));
  63. exit();
  64. }
  65. if ($action == 'add')
  66. {
  67. unset($selectedvariant);
  68. unset($_SESSION['addvariant_'.$object->id]);
  69. }
  70. if ($action == 'create' && GETPOST('selectvariant','alpha')) // We click on select combination
  71. {
  72. $action = 'add';
  73. if (GETPOST('attribute') != '-1' && GETPOST('value') != '-1')
  74. {
  75. $selectedvariant[GETPOST('attribute').':'.GETPOST('value')]=GETPOST('attribute').':'.GETPOST('value');
  76. $_SESSION['addvariant_'.$object->id]=$selectedvariant;
  77. }
  78. }
  79. $prodcomb = new ProductCombination($db);
  80. $prodcomb2val = new ProductCombination2ValuePair($db);
  81. $productCombination2ValuePairs1 = array();
  82. if ($_POST) {
  83. if (($action == 'add' || $action == 'create') && empty($massaction) && ! GETPOST('selectvariant', 'alpha')) // We click on Create all defined combinations
  84. {
  85. //$features = GETPOST('features', 'array');
  86. $features = $_SESSION['addvariant_'.$object->id];
  87. if (!$features) {
  88. setEventMessages($langs->trans('ErrorFieldsRequired'), null, 'errors');
  89. }
  90. else
  91. {
  92. $weight_impact = price2num($weight_impact);
  93. $price_impact = price2num($price_impact);
  94. $sanit_features = array();
  95. //First, sanitize
  96. foreach ($features as $feature) {
  97. $explode = explode(':', $feature);
  98. if ($prodattr->fetch($explode[0]) < 0) {
  99. continue;
  100. }
  101. if ($prodattr_val->fetch($explode[1]) < 0) {
  102. continue;
  103. }
  104. // Valuepair
  105. $sanit_features[$explode[0]] = $explode[1];
  106. $tmp = new ProductCombination2ValuePair($db);
  107. $tmp->fk_prod_attr = $explode[0];
  108. $tmp->fk_prod_attr_val = $explode[1];
  109. $productCombination2ValuePairs1[] = $tmp;
  110. }
  111. $db->begin();
  112. // sanit_feature is an array with 1 (and only 1) value per attribute.
  113. // For example: Color->blue, Size->Small, Option->2
  114. //var_dump($sanit_features);
  115. //var_dump($productCombination2ValuePairs1); exit;
  116. if (! $prodcomb->fetchByProductCombination2ValuePairs($id, $sanit_features))
  117. {
  118. $result = $prodcomb->createProductCombination($object, $sanit_features, array(), $price_impact_percent, $price_impact, $weight_impact);
  119. if ($result > 0)
  120. {
  121. setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
  122. unset($_SESSION['addvariant_'.$object->id]);
  123. $db->commit();
  124. header('Location: '.dol_buildpath('/variants/combinations.php?id='.$id, 2));
  125. exit();
  126. } else {
  127. $langs->load("errors");
  128. setEventMessages('', $prodcomb->errors, 'errors');
  129. }
  130. } else {
  131. setEventMessages($langs->trans('ErrorRecordAlreadyExists'), null, 'errors');
  132. }
  133. $db->rollback();
  134. }
  135. }
  136. elseif (! empty($massaction))
  137. {
  138. $bulkaction = $massaction;
  139. $error = 0;
  140. $prodstatic = new Product($db);
  141. $db->begin();
  142. foreach ($toselect as $prodid) {
  143. if ($prodstatic->fetch($prodid) < 0) {
  144. continue;
  145. }
  146. if ($bulkaction == 'on_sell') {
  147. $prodstatic->status = 1;
  148. $res = $prodstatic->update($prodstatic->id, $user);
  149. } elseif ($bulkaction == 'on_buy') {
  150. $prodstatic->status_buy = 1;
  151. $res = $prodstatic->update($prodstatic->id, $user);
  152. } elseif ($bulkaction == 'not_sell') {
  153. $prodstatic->status = 0;
  154. $res = $prodstatic->update($prodstatic->id, $user);
  155. } elseif ($bulkaction == 'not_buy') {
  156. $prodstatic->status_buy = 0;
  157. $res = $prodstatic->update($prodstatic->id, $user);
  158. } elseif ($bulkaction == 'delete') {
  159. $res = $prodstatic->delete($user, $prodstatic->id);
  160. } else {
  161. break;
  162. }
  163. if ($res <= 0) {
  164. $error++;
  165. break;
  166. }
  167. }
  168. if ($error) {
  169. $db->rollback();
  170. if ($prodstatic->error) {
  171. setEventMessages($prodstatic->error, $prodstatic->errors, 'errors');
  172. } else {
  173. setEventMessages($langs->trans('CoreErrorMessage'), null, 'errors');
  174. }
  175. } else {
  176. $db->commit();
  177. setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
  178. }
  179. }
  180. elseif ($valueid > 0) {
  181. if ($prodcomb->fetch($valueid) < 0) {
  182. dol_print_error($db, $langs->trans('ErrorRecordNotFound'));
  183. exit();
  184. }
  185. $prodcomb->variation_price_percentage = $price_impact_percent;
  186. $prodcomb->variation_price = $price_impact;
  187. $prodcomb->variation_weight = $weight_impact;
  188. if ($prodcomb->update($user) > 0) {
  189. setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
  190. header('Location: '.dol_buildpath('/variants/combinations.php?id='.$id, 2));
  191. exit();
  192. } else {
  193. setEventMessages($prodcomb->error, $prodcomb->errors, 'errors');
  194. }
  195. }
  196. }
  197. // Reload variants
  198. $productCombinations = $prodcomb->fetchAllByFkProductParent($object->id);
  199. if ($action === 'confirm_deletecombination') {
  200. if ($prodcomb->fetch($valueid) > 0) {
  201. $db->begin();
  202. if ($prodcomb->delete($user) > 0 && $prodstatic->fetch($prodcomb->fk_product_child) > 0 && $prodstatic->delete($user) > 0) {
  203. $db->commit();
  204. setEventMessages($langs->trans('RecordSaved'), null, 'mesgs');
  205. header('Location: '.dol_buildpath('/variants/combinations.php?id='.$object->id, 2));
  206. exit();
  207. }
  208. $db->rollback();
  209. setEventMessages($langs->trans('ProductCombinationAlreadyUsed'), null, 'errors');
  210. $action = '';
  211. }
  212. } elseif ($action === 'edit') {
  213. if ($prodcomb->fetch($valueid) < 0) {
  214. dol_print_error($db, $langs->trans('ErrorRecordNotFound'));
  215. exit();
  216. }
  217. $weight_impact = $prodcomb->variation_weight;
  218. $price_impact = $prodcomb->variation_price;
  219. $price_impact_percent = $prodcomb->variation_price_percentage;
  220. $productCombination2ValuePairs1 = $prodcomb2val->fetchByFkCombination($valueid);
  221. } elseif ($action === 'confirm_copycombination') {
  222. //Check destination product
  223. $dest_product = GETPOST('dest_product');
  224. if ($prodstatic->fetch('', $dest_product) > 0) {
  225. //To prevent from copying to the same product
  226. if ($prodstatic->ref != $object->ref) {
  227. if ($prodcomb->copyAll($object->id, $prodstatic) > 0) {
  228. header('Location: '.dol_buildpath('/variants/combinations.php?id='.$prodstatic->id, 2));
  229. exit();
  230. } else {
  231. setEventMessages($langs->trans('ErrorCopyProductCombinations'), null, 'errors');
  232. }
  233. }
  234. } else {
  235. setEventMessages($langs->trans('ErrorDestinationProductNotFound'), null, 'errors');
  236. }
  237. }
  238. /*
  239. * View
  240. */
  241. $form = new Form($db);
  242. if (! empty($id) || ! empty($ref))
  243. {
  244. llxHeader("", "", $langs->trans("CardProduct".$object->type));
  245. $showbarcode=empty($conf->barcode->enabled)?0:1;
  246. if (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->barcode->lire_advance)) $showbarcode=0;
  247. $head=product_prepare_head($object);
  248. $titre=$langs->trans("CardProduct".$object->type);
  249. $picto=($object->type== Product::TYPE_SERVICE?'service':'product');
  250. dol_fiche_head($head, 'combinations', $titre, 0, $picto);
  251. $linkback = '<a href="'.DOL_URL_ROOT.'/product/list.php?type='.$object->type.'">'.$langs->trans("BackToList").'</a>';
  252. $object->next_prev_filter=" fk_product_type = ".$object->type;
  253. dol_banner_tab($object, 'ref', $linkback, ($user->societe_id?0:1), 'ref', '', '', '', 0, '', '', 1);
  254. print '<div class="fichecenter">';
  255. print '<div class="underbanner clearboth"></div>';
  256. print '<table class="border tableforfield" width="100%">';
  257. // TVA
  258. print '<tr><td class="titlefield">' . $langs->trans("DefaultTaxRate") . '</td><td>';
  259. $positiverates='';
  260. if (price2num($object->tva_tx)) $positiverates.=($positiverates?'/':'').price2num($object->tva_tx);
  261. if (price2num($object->localtax1_type)) $positiverates.=($positiverates?'/':'').price2num($object->localtax1_tx);
  262. if (price2num($object->localtax2_type)) $positiverates.=($positiverates?'/':'').price2num($object->localtax2_tx);
  263. if (empty($positiverates)) $positiverates='0';
  264. echo vatrate($positiverates.($object->default_vat_code?' ('.$object->default_vat_code.')':''), '%', $object->tva_npr);
  265. /*
  266. if ($object->default_vat_code)
  267. {
  268. print vatrate($object->tva_tx, true) . ' ('.$object->default_vat_code.')';
  269. }
  270. else print vatrate($object->tva_tx, true, $object->tva_npr, true);*/
  271. print '</td></tr>';
  272. // Price
  273. print '<tr><td>' . $langs->trans("SellingPrice") . '</td><td>';
  274. if ($object->price_base_type == 'TTC') {
  275. print price($object->price_ttc) . ' ' . $langs->trans($object->price_base_type);
  276. } else {
  277. print price($object->price) . ' ' . $langs->trans($object->price_base_type);
  278. }
  279. print '</td></tr>';
  280. // Price minimum
  281. print '<tr><td>' . $langs->trans("MinPrice") . '</td><td>';
  282. if ($object->price_base_type == 'TTC') {
  283. print price($object->price_min_ttc) . ' ' . $langs->trans($object->price_base_type);
  284. } else {
  285. print price($object->price_min) . ' ' . $langs->trans($object->price_base_type);
  286. }
  287. print '</td></tr>';
  288. // Weight
  289. print '<tr><td>'.$langs->trans("Weight").'</td><td>';
  290. if ($object->weight != '')
  291. {
  292. print $object->weight." ".measuring_units_string($object->weight_units,"weight");
  293. }
  294. else
  295. {
  296. print '&nbsp;';
  297. }
  298. print "</td></tr>\n";
  299. print "</table>\n";
  300. print '</div>';
  301. print '<div style="clear:both"></div>';
  302. dol_fiche_end();
  303. // Create or edit a varian
  304. if ($action == 'add' || ($action == 'edit')) {
  305. if ($action == 'add') {
  306. $title = $langs->trans('NewProductCombination');
  307. //print dol_fiche_head();
  308. $features = $_SESSION['addvariant_'.$object->id];
  309. //First, sanitize
  310. print '<div id="parttoaddvariant">';
  311. if (! empty($features)) {
  312. foreach ($features as $feature) {
  313. $explode = explode(':', $feature);
  314. if ($prodattr->fetch($explode[0]) < 0) {
  315. continue;
  316. }
  317. if ($prodattr_val->fetch($explode[1]) < 0) {
  318. continue;
  319. }
  320. print '<i>' . $prodattr->label . '</i>:'. $prodattr_val->value . ' ';
  321. }
  322. }
  323. print '</div>';
  324. print '<br><br>';
  325. //print dol_fiche_end();
  326. } else {
  327. $title = $langs->trans('EditProductCombination');
  328. }
  329. print load_fiche_titre($title);
  330. if ($action == 'add') {
  331. $prodattr_all = $prodattr->fetchAll();
  332. if (!$selected) {
  333. $selected = $prodattr_all[key($prodattr_all)]->id;
  334. }
  335. $prodattr_alljson = array();
  336. foreach ($prodattr_all as $each) {
  337. $prodattr_alljson[$each->id] = $each;
  338. }
  339. ?>
  340. <script type="text/javascript">
  341. variants_available = <?php echo json_encode($prodattr_alljson); ?>;
  342. variants_selected = {
  343. index: [],
  344. info: []
  345. };
  346. <?php
  347. foreach ($productCombination2ValuePairs1 as $pc2v) {
  348. $prodattr_val->fetch($pc2v->fk_prod_attr_val);
  349. ?>
  350. variants_selected.index.push(<?php echo $pc2v->fk_prod_attr ?>);
  351. variants_selected.info[<?php echo $pc2v->fk_prod_attr ?>] = {
  352. attribute: variants_available[<?php echo $pc2v->fk_prod_attr ?>],
  353. value: {
  354. id: <?php echo $pc2v->fk_prod_attr_val ?>,
  355. label: '<?php echo $prodattr_val->value ?>'
  356. }
  357. };
  358. <?php
  359. }
  360. ?>
  361. restoreAttributes = function() {
  362. jQuery("select[name=attribute]").empty().append('<option value="-1">&nbsp;</option>');
  363. jQuery.each(variants_available, function (key, val) {
  364. if (jQuery.inArray(val.id, variants_selected.index) == -1) {
  365. jQuery("select[name=attribute]").append('<option value="' + val.id + '">' + val.label + '</option>');
  366. }
  367. });
  368. };
  369. jQuery(document).ready(function() {
  370. jQuery("select#attribute").change(function () {
  371. console.log("Change of field variant attribute");
  372. var select = jQuery("select#value");
  373. if (!jQuery(this).val().length || jQuery(this).val() == '-1') {
  374. select.empty();
  375. select.append('<option value="-1">&nbsp;</option>');
  376. return;
  377. }
  378. select.empty().append('<option value="">Loading...</option>');
  379. jQuery.getJSON("ajax/get_attribute_values.php", {
  380. id: jQuery(this).val()
  381. }, function(data) {
  382. if (data.error) {
  383. select.empty();
  384. select.append('<option value="-1">&nbsp;</option>');
  385. return alert(data.error);
  386. }
  387. select.empty();
  388. select.append('<option value="-1">&nbsp;</option>');
  389. jQuery(data).each(function (key, val) {
  390. keyforoption = val.id
  391. valforoption = val.value
  392. select.append('<option value="' + keyforoption + '">' + valforoption + '</option>');
  393. });
  394. });
  395. });
  396. });
  397. </script>
  398. <?php
  399. }
  400. print '<form method="post" id="combinationform" action="'.$_SERVER["PHP_SELF"].'">'."\n";
  401. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  402. print '<input type="hidden" name="id" value="'.dol_escape_htmltag($id).'">'."\n";
  403. print '<input type="hidden" name="action" value="' . (($valueid > 0) ? "update" : "create") .'">'."\n";
  404. if($valueid > 0) {
  405. print '<input type="hidden" name="valueid" value="' . $valueid .'">'."\n";
  406. }
  407. print dol_fiche_head();
  408. ?>
  409. <table class="border" style="width: 100%">
  410. <?php if ($action == 'add') { ?>
  411. <!-- Variant -->
  412. <tr>
  413. <td class="titlefieldcreate fieldrequired"><label for="attribute"><?php echo $langs->trans('ProductAttribute') ?></label></td>
  414. <td>
  415. <?php
  416. if (is_array($prodattr_all))
  417. {
  418. print '<select class="flat minwidth100" id="attribute" name="attribute">';
  419. print '<option value="-1">&nbsp;</option>';
  420. foreach ($prodattr_all as $attr)
  421. {
  422. print '<option value="'.$attr->id.'">'.$attr->label.'</option>';
  423. }
  424. print '</select>';
  425. }
  426. $htmltext=$langs->trans("GoOnMenuToCreateVairants", $langs->transnoentities("Product"), $langs->transnoentities("VariantAttributes"));
  427. print $form->textwithpicto('', $htmltext);
  428. /*print ' &nbsp; &nbsp; <a href="'.DOL_URL_ROOT.'/variants/create.php?action=create&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=add&id='.$object->id).'">';
  429. print $langs->trans("Create");
  430. print '</a>';*/
  431. ?>
  432. </td>
  433. </tr>
  434. <!-- Value -->
  435. <tr>
  436. <td class="fieldrequired"><label for="value"><?php echo $langs->trans('Value') ?></label></td>
  437. <td>
  438. <select class="flat minwidth100" id="value" name="value">
  439. <option value="-1">&nbsp;</option>
  440. </select>
  441. <?php
  442. $htmltext=$langs->trans("GoOnMenuToCreateVairants", $langs->transnoentities("Product"), $langs->transnoentities("VariantAttributes"));
  443. print $form->textwithpicto('', $htmltext);
  444. /*
  445. print ' &nbsp; &nbsp; <a href="'.DOL_URL_ROOT.'/variants/create.php?action=create&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=add&id='.$object->id).'">';
  446. print $langs->trans("Create");
  447. print '</a>';
  448. */
  449. ?>
  450. </td>
  451. </tr>
  452. <tr>
  453. <td></td><td>
  454. <input type="submit" class="button" name="selectvariant" id="selectvariant" value="<?php echo dol_escape_htmltag($langs->trans("SelectCombination")); ?>">
  455. </td>
  456. </tr>
  457. </table>
  458. <?php
  459. }
  460. if (is_array($productCombination2ValuePairs1)) {
  461. ?>
  462. <hr>
  463. <table class="border" style="width: 100%">
  464. <tr>
  465. <td class="titlefieldcreate fieldrequired tdtop"><label for="features"><?php echo $langs->trans('Combination') ?></label></td>
  466. <td class="tdtop">
  467. <div class="inline-block valignmiddle quatrevingtpercent">
  468. <?php
  469. if (is_array($productCombination2ValuePairs1))
  470. {
  471. foreach ($productCombination2ValuePairs1 as $key => $val) {
  472. $result1 = $prodattr->fetch($val->fk_prod_attr);
  473. $result2 = $prodattr_val->fetch($val->fk_prod_attr_val);
  474. if ($result1 > 0 && $result2 > 0)
  475. {
  476. print $prodattr->label . ' - '.$prodattr_val->value.'<br>';
  477. // TODO Add delete link
  478. }
  479. }
  480. }
  481. ?>
  482. </div>
  483. <!-- <div class="inline-block valignmiddle">
  484. <a href="#" class="inline-block valignmiddle button" id="delfeature"><?php echo img_edit_remove() ?></a>
  485. </div>-->
  486. </td>
  487. <td>
  488. </td>
  489. </tr>
  490. <tr>
  491. <td><label for="price_impact"><?php echo $langs->trans('PriceImpact') ?></label></td>
  492. <td><input type="text" id="price_impact" name="price_impact" value="<?php echo price($price_impact) ?>">
  493. <input type="checkbox" id="price_impact_percent" name="price_impact_percent" <?php echo $price_impact_percent ? ' checked' : '' ?>> <label for="price_impact_percent"><?php echo $langs->trans('PercentageVariation') ?></label></td>
  494. </tr>
  495. <?php if ($object->isProduct()) {
  496. print '<tr>';
  497. print '<td><label for="weight_impact">'.$langs->trans('WeightImpact').'</label></td>';
  498. print '<td><input type="text" id="weight_impact" name="weight_impact" value="'.price($weight_impact).'"></td>';
  499. print '</tr>';
  500. }
  501. print '</table>';
  502. }
  503. print dol_fiche_end();
  504. ?>
  505. <div style="text-align: center">
  506. <input type="submit" name="create" <?php if (! is_array($productCombination2ValuePairs1)) print ' disabled="disabled"'; ?> value="<?php echo $action == 'add' ? $langs->trans('Create') : $langs->trans('Save') ?>" class="button">
  507. &nbsp;
  508. <input type="submit" name="cancel" value="<?php echo $langs->trans('Cancel'); ?>" class="button">
  509. </div>
  510. <?php
  511. print '</form>';
  512. }
  513. else
  514. {
  515. if ($action === 'delete') {
  516. if ($prodcomb->fetch($valueid) > 0) {
  517. $prodstatic->fetch($prodcomb->fk_product_child);
  518. print $form->formconfirm(
  519. "combinations.php?id=".$id."&valueid=".$valueid,
  520. $langs->trans('Delete'),
  521. $langs->trans('ProductCombinationDeleteDialog', $prodstatic->ref),
  522. "confirm_deletecombination",
  523. '',
  524. 0,
  525. 1
  526. );
  527. }
  528. } elseif ($action === 'copy') {
  529. print $form->formconfirm(
  530. 'combinations.php?id='.$id,
  531. $langs->trans('CloneCombinationsProduct'),
  532. $langs->trans('ConfirmCloneProductCombinations'),
  533. 'confirm_copycombination',
  534. array(
  535. array(
  536. 'type' => 'text',
  537. 'label' => $langs->trans('CloneDestinationReference'),
  538. 'name' => 'dest_product'
  539. )
  540. ),
  541. 0,
  542. 1
  543. );
  544. }
  545. $comb2val = new ProductCombination2ValuePair($db);
  546. if ($productCombinations)
  547. {
  548. ?>
  549. <script type="text/javascript">
  550. jQuery(document).ready(function() {
  551. jQuery('input[name="select_all"]').click(function() {
  552. if (jQuery(this).prop('checked')) {
  553. var checked = true;
  554. } else {
  555. var checked = false;
  556. }
  557. jQuery('table.liste input[type="checkbox"]').prop('checked', checked);
  558. });
  559. jQuery('input[name^="select["]').click(function() {
  560. jQuery('input[name="select_all"]').prop('checked', false);
  561. });
  562. });
  563. </script>
  564. <?php }
  565. // Buttons
  566. print '<div class="tabsAction">';
  567. print ' <div class="inline-block divButAction">';
  568. print '<a href="combinations.php?id='.$object->id.'&action=add" class="butAction">'.$langs->trans('NewProductCombination').'</a>'; // NewVariant
  569. if ($productCombinations)
  570. {
  571. print '<a href="combinations.php?id='.$object->id.'&action=copy" class="butAction">'.$langs->trans('PropagateVariant').'</a>';
  572. }
  573. // Too much bugged page.
  574. /*
  575. print '<a href="generator.php?id='.$object->id.'" class="butAction">'.$langs->trans('ProductCombinationGenerator').'</a>';
  576. */
  577. print ' </div>';
  578. print '</div>';
  579. $arrayofselected=is_array($toselect)?$toselect:array();
  580. // List of variants
  581. print '<form method="POST" action="'.$_SERVER["PHP_SELF"].'">';
  582. print '<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  583. print '<input type="hidden" name="action" value="massaction">';
  584. print '<input type="hidden" name="id" value="'.$id.'">';
  585. print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
  586. // List of mass actions available
  587. /*
  588. $arrayofmassactions = array(
  589. 'presend'=>$langs->trans("SendByMail"),
  590. 'builddoc'=>$langs->trans("PDFMerge"),
  591. );
  592. if ($user->rights->product->supprimer) $arrayofmassactions['predelete']=$langs->trans("Delete");
  593. if (in_array($massaction, array('presend','predelete'))) $arrayofmassactions=array();
  594. $massactionbutton=$form->selectMassAction('', $arrayofmassactions);
  595. */
  596. $aaa='';
  597. if (count($productCombinations))
  598. {
  599. $aaa = '<label for="massaction">'.$langs->trans('BulkActions').'</label>';
  600. $aaa .= '<select id="bulk_action" name="massaction" class="flat">';
  601. $aaa .= ' <option value="nothing">&nbsp;</option>';
  602. $aaa .= ' <option value="not_buy">'.$langs->trans('ProductStatusNotOnBuy').'</option>';
  603. $aaa .= ' <option value="not_sell">'.$langs->trans('ProductStatusNotOnSell').'</option>';
  604. $aaa .= ' <option value="on_buy">'.$langs->trans('ProductStatusOnBuy').'</option>';
  605. $aaa .= ' <option value="on_sell">'.$langs->trans('ProductStatusOnSell').'</option>';
  606. $aaa .= ' <option value="delete">'.$langs->trans('Delete').'</option>';
  607. $aaa .= '</select>';
  608. $aaa .= '<input type="submit" value="'.dol_escape_htmltag($langs->trans("Apply")).'" class="button">';
  609. }
  610. $massactionbutton = $aaa;
  611. $title = $langs->trans("ProductCombinations");
  612. print_barre_liste($title, 0, $_SERVER["PHP_SELF"], '', $sortfield, $sortorder, $aaa, 0);
  613. print '<div class="div-table-responsive">';
  614. ?>
  615. <table class="liste">
  616. <tr class="liste_titre">
  617. <td class="liste_titre"><?php echo $langs->trans('Product') ?></td>
  618. <td class="liste_titre"><?php echo $langs->trans('Combination') ?></td>
  619. <td class="liste_titre right"><?php echo $langs->trans('PriceImpact') ?></td>
  620. <?php if ($object->isProduct()) print'<td class="liste_titre right">'.$langs->trans('WeightImpact').'</td>'; ?>
  621. <td class="liste_titre center"><?php echo $langs->trans('OnSell') ?></td>
  622. <td class="liste_titre center"><?php echo $langs->trans('OnBuy') ?></td>
  623. <td class="liste_titre"></td>
  624. <?php
  625. print '<td class="liste_titre" align="middle">';
  626. $searchpicto=$form->showCheckAddButtons('checkforselect', 1);
  627. print $searchpicto;
  628. print '</td>';
  629. ?>
  630. </tr>
  631. <?php
  632. if (count($productCombinations))
  633. {
  634. foreach ($productCombinations as $currcomb)
  635. {
  636. $prodstatic->fetch($currcomb->fk_product_child);
  637. ?>
  638. <tr class="oddeven">
  639. <td><?php echo $prodstatic->getNomUrl(1) ?></td>
  640. <td>
  641. <?php
  642. $productCombination2ValuePairs = $comb2val->fetchByFkCombination($currcomb->id);
  643. $iMax = count($productCombination2ValuePairs);
  644. for ($i = 0; $i < $iMax; $i++) {
  645. echo dol_htmlentities($productCombination2ValuePairs[$i]);
  646. if ($i !== ($iMax - 1)) {
  647. echo ', ';
  648. }
  649. } ?>
  650. </td>
  651. <td class="right"><?php echo ($currcomb->variation_price >= 0 ? '+' : '').price($currcomb->variation_price).($currcomb->variation_price_percentage ? ' %' : '') ?></td>
  652. <?php if ($object->isProduct()) print '<td class="right">'.($currcomb->variation_weight >= 0 ? '+' : '').price($currcomb->variation_weight).' '.measuring_units_string($prodstatic->weight_units, 'weight').'</td>'; ?>
  653. <td style="text-align: center;"><?php echo $prodstatic->getLibStatut(2, 0) ?></td>
  654. <td style="text-align: center;"><?php echo $prodstatic->getLibStatut(2, 1) ?></td>
  655. <td class="right">
  656. <a class="paddingleft paddingright" href="<?php echo dol_buildpath('/variants/combinations.php?id='.$id.'&action=edit&valueid='.$currcomb->id, 2) ?>"><?php echo img_edit() ?></a>
  657. <a class="paddingleft paddingright" href="<?php echo dol_buildpath('/variants/combinations.php?id='.$id.'&action=delete&valueid='.$currcomb->id, 2) ?>"><?php echo img_delete() ?></a>
  658. </td>
  659. <?php
  660. print '<td class="nowrap" align="center">';
  661. if ($productCombinations || $massactionbutton || $massaction) // If we are in select mode (massactionbutton defined) or if we have already selected and sent an action ($massaction) defined
  662. {
  663. $selected=0;
  664. if (in_array($prodstatic->id, $arrayofselected)) $selected=1;
  665. print '<input id="cb'.$prodstatic->id.'" class="flat checkforselect" type="checkbox" name="toselect[]" value="'.$prodstatic->id.'"'.($selected?' checked="checked"':'').'>';
  666. }
  667. print '</td>';
  668. ?>
  669. </tr>
  670. <?php
  671. }
  672. }
  673. else
  674. {
  675. print '<tr><td colspan="8"><span class="opacitymedium">'.$langs->trans("None").'</span></td></tr>';
  676. }
  677. ?>
  678. </table>
  679. <?php
  680. print '</div>';
  681. print '</form>';
  682. }
  683. } else {
  684. llxHeader();
  685. // not found
  686. }
  687. // End of page
  688. llxFooter();
  689. $db->close();