dolibarr 25.0.0-alpha
stockcorrection.tpl.php
1<?php
2/* Copyright (C) 2010-2017 Laurent Destailleur <eldy@users.sourceforge.net>
3 * Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
4 * Copyright (C) 2024-2025 MDW <mdeweerd@users.noreply.github.com>
5 * Copyright (C) 2026 Jose Martinez <jose.martinez@pichinov.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 *
20 * $object must be defined
21 * $backtopage
22 */
23
35// Protection to avoid direct call of template
36if (empty($conf) || !is_object($conf)) {
37 print "Error, template page can't be called as URL";
38 exit(1);
39}
40
41'
42@phan-var-force Entrepot|MouvementStock $object
43@phan-var-force FormProduct $formproduct
44@phan-var-force FormProjets $formproject
45@phan-var-force string $backtopage
46';
47
48?>
49
50<!-- BEGIN PHP TEMPLATE PRODUCT/STOCK/TPL/STOCKCORRECTION.TPL.PHP -->
51<?php
52
53$productref = '';
54if ($object->element == 'product') {
56 $productref = (string) $object->ref;
57}
58
59$langs->load("productbatch");
60
61
62if (empty($id)) {
63 $id = $object->id;
64}
65
66$pdluoid = GETPOSTINT('pdluoid');
67
68$pdluo = new Productbatch($db);
69
70if ($pdluoid > 0) {
71 $result = $pdluo->fetch($pdluoid);
72 if ($result > 0) {
73 $pdluoid = $pdluo->id;
74 } else {
75 dol_print_error($db, $pdluo->error, $pdluo->errors);
76 }
77}
78
79$sellByCss = '';
80$eatByCss = '';
81// A date is mandatory when we record the lot the first time. Then once lot and date is recorded
82// a user should be able to manage the lot only (this is main goal of lot)
83/*
84if ($object->sell_or_eat_by_mandatory == Product::SELL_OR_EAT_BY_MANDATORY_ID_SELL_BY) {
85 $sellByCss = 'fieldrequired';
86} elseif ($object->sell_or_eat_by_mandatory == Product::SELL_OR_EAT_BY_MANDATORY_ID_EAT_BY) {
87 $eatByCss = 'fieldrequired';
88} elseif ($object->sell_or_eat_by_mandatory == Product::SELL_OR_EAT_BY_MANDATORY_ID_SELL_AND_EAT) {
89 $sellByCss = 'fieldrequired';
90 $eatByCss = 'fieldrequired';
91}
92*/
93
94$disableSellBy = getDolGlobalInt('PRODUCT_DISABLE_SELLBY');
95$disableEatBy = getDolGlobalInt('PRODUCT_DISABLE_EATBY');
96print '<script type="text/javascript">
97 jQuery(document).ready(function() {
98 function init_price()
99 {
100 if (jQuery("#mouvement").val() == \'0\') jQuery("#unitprice").removeAttr("disabled");
101 else jQuery("#unitprice").prop("disabled", true);
102 }
103 init_price();
104 jQuery("#mouvement").change(function() {
105 console.log("We change the direction of movement");
106 init_price();
107 });
108 jQuery("#nbpiece").keyup(function(event) {
109 console.log("We enter a qty on "+event.key);
110 if ( event.key == "-" ) { /* char - */
111 console.log("We set direction to value 1");
112 jQuery("#nbpiece").val(jQuery("#nbpiece").val().replace("-", ""));
113 jQuery("#mouvement option").removeAttr("selected").change();
114 jQuery("#mouvement option[value=1]").attr("selected","selected").trigger("change");
115 jQuery("#mouvement").trigger("change");
116 } else if ( event.key == "+" ) { /* char + */
117 console.log("We set direction to value 0");
118 jQuery("#nbpiece").val(jQuery("#nbpiece").val().replace("+", ""));
119 jQuery("#mouvement option").removeAttr("selected").change();
120 jQuery("#mouvement option[value=0]").attr("selected","selected").trigger("change");
121 jQuery("#mouvement").trigger("change");
122 }
123 });';
124
125if ($disableSellBy == 0 || $disableEatBy == 0) {
126 print '
127 var disableSellBy = '.dol_escape_js((string) $disableSellBy).';
128 var disableEatBy = '.dol_escape_js((string) $disableSellBy).';
129 jQuery("#batch_number").change(function(event) {
130 var batch = jQuery(this).val();
131 jQuery.getJSON("'.DOL_URL_ROOT.'/product/ajax/product_lot.php?action=search&token='.currentToken().'&product_id='.$id.'&batch="+batch, function(data) {
132 if (data.length > 0) {
133 var productLot = data[0];
134 if (disableSellBy == 0) {
135 jQuery("#sellby").val(productLot.sellby);
136 }
137 if (disableEatBy == 0) {
138 jQuery("#eatby").val(productLot.eatby);
139 }
140 }
141 });
142 });';
143}
144print '});';
145print '</script>';
146
147
148print load_fiche_titre($langs->trans("StockCorrection"), '', 'generic');
149
150print '<form action="'.$_SERVER["PHP_SELF"].'?id='.$id.'" method="post">'."\n";
151
152print dol_get_fiche_head(array(), '', '', 0, '', 0, '', '', 0, '', 0, 'marginbottomonly');
153
154print '<input type="hidden" name="token" value="'.newToken().'">';
155print '<input type="hidden" name="action" value="correct_stock">';
156print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
157if ($pdluoid) {
158 print '<input type="hidden" name="pdluoid" value="'.$pdluoid.'">';
159}
160print '<table class="border centpercent">';
161
162// Warehouse or product
163print '<tr>';
164if ($object->element == 'product') {
166 print '<td class="fieldrequired">'.$langs->trans("Warehouse").'</td>';
167 print '<td>';
168 $ident = (GETPOST("dwid") ? GETPOSTINT("dwid") : (GETPOST('id_entrepot') ? GETPOSTINT('id_entrepot') : ($object->element == 'product' && $object->fk_default_warehouse ? $object->fk_default_warehouse : 'ifone')));
169 if (empty($ident) && getDolGlobalString('MAIN_DEFAULT_WAREHOUSE')) {
170 $ident = getDolGlobalString('MAIN_DEFAULT_WAREHOUSE');
171 }
172 print img_picto('', 'stock', 'class="pictofixedwidth"').$formproduct->selectWarehouses($ident, 'id_entrepot', 'warehouseopen,warehouseinternal', 1, 0, 0, '', 0, 0, array(), 'minwidth100 maxwidth300 widthcentpercentminusx');
173 print '</td>';
174}
175if ($object->element == 'stockmouvement') {
177 print '<td class="fieldrequired">'.$langs->trans("Product").'</td>';
178 print '<td>';
179 print img_picto('', 'product');
180 $form->select_produits(GETPOSTINT('product_id'), 'product_id', (!getDolGlobalString('STOCK_SUPPORTS_SERVICES') ? '0' : ''), 0, 0, -1, 2, '', 0, array(), 0, 1, 0, 'maxwidth500');
181 print '</td>';
182}
183print '<td class="fieldrequired">'.$langs->trans("NumberOfUnit").'</td>';
184print '<td>';
185if ($object->element == 'product' || $object->element == 'stockmouvement') {
187 print '<select name="mouvement" id="mouvement" class="minwidth100 valignmiddle">';
188 print '<option value="0">'.$langs->trans("Add").'</option>';
189 print '<option value="1"'.(GETPOST('mouvement') ? ' selected="selected"' : '').'>'.$langs->trans("Delete").'</option>';
190 print '</select>';
191 print ajax_combobox("mouvement");
192}
193print '<input name="nbpiece" id="nbpiece" class="center valignmiddle maxwidth75" value="'.GETPOST("nbpiece").'">';
194print '</td>';
195print '</tr>';
196
197// If product is a Kit, we ask if we must disable stock change of subproducts
198if (getDolGlobalString('PRODUIT_SOUSPRODUITS') && $object->element == 'product' && $object->hasFatherOrChild(1)) {
200 print '<tr>';
201 print '<td></td>';
202 print '<td colspan="3">';
203 print '<input type="checkbox" name="disablesubproductstockchange" id="disablesubproductstockchange" value="1"'.(GETPOST('disablesubproductstockchange') ? ' checked="checked"' : '').'">';
204 print ' <label for="disablesubproductstockchange">'.$langs->trans("DisableStockChangeOfSubProduct").'</label>';
205 print '</td>';
206 print '</tr>';
207}
208
209// Serial / Eat-by date
210if (isModEnabled('productbatch') &&
211(($object->element == 'product' && $object->hasbatch())
212|| ($object->element == 'stockmouvement'))
213) {
215 print '<tr>';
216 print '<td'.($object->element == 'stockmouvement' ? '' : ' class="fieldrequired"').'>'.$langs->trans("batch_number").'</td><td colspan="3">';
217 if ($pdluoid > 0) {
218 // If form was opened for a specific pdluoid, field is disabled
219 print '<input type="text" name="batch_number_bis" size="40" disabled="disabled" value="'.(GETPOST('batch_number') ? GETPOST('batch_number') : $pdluo->batch).'">';
220 print '<input type="hidden" name="batch_number" value="'.(GETPOST('batch_number') ? GETPOST('batch_number') : $pdluo->batch).'">';
221 } else {
222 print img_picto('', 'barcode', 'class="pictofixedwidth"').'<input type="text" id="batch_number" name="batch_number" class="minwidth300" value="'.(GETPOST('batch_number') ? GETPOST('batch_number') : $pdluo->batch).'">';
223 }
224 print '</td>';
225 print '</tr>';
226
227 print '<tr>';
228 if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
229 // print '<td'.($sellByCss ? ' class="'.$sellByCss.'"' : '').'>'.$langs->trans("SellByDate").'</td><td>';
230 print '<td>'.$langs->trans("SellByDate").'</td><td>';
231 $sellbyselected = dol_mktime(0, 0, 0, GETPOSTINT('sellbymonth'), GETPOSTINT('sellbyday'), GETPOSTINT('sellbyyear'));
232 // If form was opened for a specific pdluoid, field is disabled
233 print $form->selectDate(($pdluo->id > 0 ? $pdluo->sellby : $sellbyselected), 'sellby', 0, 0, 1, "", 1, 0, ($pdluoid > 0 ? 1 : 0));
234 print '</td>';
235 }
236 if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
237 // print '<td'.($eatByCss ? ' class="'.$eatByCss.'"' : '').'>'.$langs->trans("EatByDate").'</td><td>';
238 print '<td>'.$langs->trans("EatByDate").'</td><td>';
239 $eatbyselected = dol_mktime(0, 0, 0, GETPOSTINT('eatbymonth'), GETPOSTINT('eatbyday'), GETPOSTINT('eatbyyear'));
240 // If form was opened for a specific pdluoid, field is disabled
241 print $form->selectDate(($pdluo->id > 0 ? $pdluo->eatby : $eatbyselected), 'eatby', 0, 0, 1, "", 1, 0, ($pdluoid > 0 ? 1 : 0));
242 print '</td>';
243 }
244 print '</tr>';
245}
246
247// Purchase price and project
248print '<tr>';
249print '<td>'.$langs->trans("UnitPurchaseValue").'</td>';
250print '<td colspan="'.(isModEnabled('project') ? '1' : '3').'"><input name="unitprice" id="unitprice" size="10" value="'.GETPOST("unitprice").'"></td>';
251if (isModEnabled('project')) {
252 print '<td>'.$langs->trans('Project').'</td>';
253 print '<td>';
254 print img_picto('', 'project');
255 $formproject->select_projects(-1, '', 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, 'maxwidth300 widthcentpercentminusx');
256 print '</td>';
257}
258print '</tr>';
259
260// Label for movement of id of inventory
261$valformovementlabel = ((GETPOST("label") && (GETPOST('label') != $langs->trans("MovementCorrectStock", ''))) ? GETPOST("label") : $langs->trans("MovementCorrectStock", $productref));
262print '<tr>';
263print '<td>'.$langs->trans("MovementLabel").'</td>';
264print '<td>';
265print '<input type="text" name="label" class="minwidth400" value="'.dol_escape_htmltag($valformovementlabel).'">';
266print '</td>';
267print '<td>'.$langs->trans("InventoryCode").'</td>';
268print '<td>';
269// Prefix the default inventory code so corrections can be told apart from other movement batches
270print '<input class="maxwidth100onsmartphone" name="inventorycode" id="inventorycode" value="'.(GETPOSTISSET("inventorycode") ? GETPOST("inventorycode", 'alpha') : getDolGlobalString('STOCK_CORRECTION_CODE_PREFIX', 'COR-').dol_print_date(dol_now(), '%Y%m%d%H%M%S')).'">';
271print '</td>';
272print '</tr>';
273
274print '</table>';
275
276print dol_get_fiche_end();
277
278print '<div class="center">';
279print '<input type="submit" class="button button-save" name="save" value="'.dol_escape_htmltag($langs->trans("Save")).'">';
280print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
281print '<input type="submit" class="button button-cancel" name="cancel" value="'.dol_escape_htmltag($langs->trans("Cancel")).'">';
282print '</div>';
283
284print '<br>';
285
286print '</form>';
287?>
288<!-- END PHP STOCKCORRECTION.TPL.PHP -->
$id
Support class for third parties, contacts, members, users or resources.
Definition account.php:47
if(! $sortfield) if(! $sortorder) $object
Definition account.php:100
ajax_combobox($htmlname, $events=array(), $minLengthToAutocomplete=0, $forcefocus=0, $widthTypeOfAutocomplete='resolve', $idforemptyvalue='-1', $morecss='')
Convert a html select field into an ajax combobox.
Definition ajax.lib.php:476
Manage record for batch number management.
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $conf
The main.inc.php has been included so the following variable are now defined:
if(!isModEnabled('ai')||!getDolGlobalString('AI_ASSISTANT_ENABLED')) global $db
API class for accounts.
dol_now($mode='gmt')
Return date for now.
dol_mktime($hour, $minute, $second, $month, $day, $year, $gm='auto', $check=1)
Return a timestamp date built from detailed information (by default a local PHP server timestamp) Rep...
currentToken()
Return the value of token currently saved into session with name 'token'.
getDolGlobalInt($key, $default=0)
Return a Dolibarr global constant int value.
dol_escape_js($stringtoescape, $mode=0, $noescapebackslashn=0)
Returns text escaped for inclusion into JavaScript code.
GETPOST($paramname, $check='alphanohtml', $method=0, $filter=null, $options=null, $noreplace=0, $nodefault=0)
Return value of a param into GET or POST supervariable.
GETPOSTINT($paramname, $method=0, $nodefault=0)
Return the value of a $_GET or $_POST supervariable, converted into integer.
dol_print_date($time, $format='', $tzoutput='auto', $outputlangs=null, $encodetooutput=false, $decorate=0)
Output date in a string format according to outputlangs (or langs if not defined).
getDolGlobalString($key, $default='')
Return a Dolibarr global constant string value.
isModEnabled($module)
Is Dolibarr module enabled.
img_picto($titlealt, $picto, $moreatt='', $pictoisfullpath=0, $srconly=0, $notitle=0, $alt='', $morecss='', $marginleftonlyshort=2, $allowothertags=array())
Show picto whatever it's its name (generic function)
dol_get_fiche_head($links=array(), $active='', $title='', $notab=0, $picto='', $pictoisfullpath=0, $morehtmlright='', $morecss='', $limittoshow=0, $moretabssuffix='', $dragdropfile=0, $morecssdiv='')
Show tabs of a record.
Definition html.lib.php:519
dol_get_fiche_end($notab=0)
Return tab footer of a card.
Definition html.lib.php:717
dol_print_error($db=null, $error='', $errors=null)
Displays error message system with all the information to facilitate the diagnosis and the escalation...
load_fiche_titre($title, $morehtmlright='', $picto='generic', $pictoisfullpath=0, $id='', $morecssontable='', $morehtmlcenter='', $morecssonpicto='widthpictotitle')
Load a title with picto.
print $langs trans("Show") . '< td style="' . $timeColor . '" align="center"> s</td > badge status0 badge status4 badge status3 Error badge status8< td align="center">< span class="badge ' . $badge . '"></span ></td >< td align="center">< a href="#" class="button button-small" onclick="openLogModal(this)" data-req="' . dol_escape_htmltag($reqSafe) . '" data-res="' . dol_escape_htmltag($resSafe) . '" data-err="' . dol_escape_htmltag($errSafe) . '">< span class="fa fa-search-plus"></span ></a ></td ></tr >< tr >< td colspan="' . $colspan . '" class="opacitymedium"></td ></tr ></table ></div ></form > logModal none logModal none s a JSON string