* FIX Drag and drop of a file reports a wrong error, or none at all
The error handler of dragAndDropFileUpload() had three defects that all end on
the user believing the file was attached when it was not.
- The first assignment of the message was dead code, there was no return after
the test on the http code 403, so a refusal was reported as a generic error.
- The key ErrorUploadPermissionDenied it used exists in no language file, so
the raw key was shown.
- JSON.parse() was called with no try/catch on an answer that is not always a
json, a fatal error of the endpoint or a request over post_max_size for
example. The exception left the user on a page with no message at all.
- An empty list of files was treated as a success, while it means the endpoint
stored nothing.
The value of PHP_SELF is also escaped before it is written into the 6 generated
javascript strings. It holds the path info of the request on a server that
accepts it, so it is a user input. dol_escape_js() is called with the mode that
escapes a double quote by a double quote, the strings being delimited by double
quotes, and the sequence '</' is escaped too because the function does not do it
and the path info could otherwise close the script tag and open one of its own.
Adds the key ErrorOnAtLeastOneFileUpload to en_US, used when some files of a
batch failed and some did not.
* FIX getMultidirOutput returns a directory the Documents tab does not read
Four defects of the same function, all ending on a file stored where the user
will never see it, or written outside the documents directory.
- The ref of the project of a task was only passed through dol_sanitizePathName(),
which keeps a slash, a colon and the accented chars, while projet/tasks/document.php
sanitizes it with dol_sanitizeFileName(). A project ref holding a slash even
created an extra level of directory. Measured on real databases: 304 projects
over 330 hold a slash on one of them, carrying 701 tasks over 824.
- The same case calls $object->fetchProject() with no guard, while the signature
of the function accepts an object that is not a CommonObject, and even a null
when a module is given. Such a caller gets a fatal error where it expects the
error string. No core caller is in that case today, an external module or a
hook can be.
- The entity of the object may have no declared directory, an object shared by
another entity for example. The undefined index returned a relative path, so
the caller read or wrote under the web root. The current entity is used
instead, and the fallback is logged because the directory is then not the one
of the entity of the object, which matters for a caller that deletes files.
- When the current entity has no declared directory either, the fallback
returned the sub directory alone, again a relative path. The same error than
for a module that declares no directory at all is now returned.
Adds the sub directory of a partnership and of a stock transfer, which their own
document tabs already read.
* FIX getElementProperties answers wrong properties for 9 elements
A customer payment, a supplier payment, a various payment, a stock transfer and
the 4 objects of the hrm module had no properties at all, or wrong ones, so any
caller that resolves a class, a table or a document directory from an element
failed on them.
- payment, payment_supplier and payment_various had no branch. The branch of a
customer payment tests $elementType and not $element, because the rule on the
elements named myobject_mysubobject rewrites $element to 'payment' for
'payment_salary' too, which is stored somewhere else.
- job, position, skill and evaluation answered a wrong table (hrm_job_user for
a position, and so on) and no sub directory, while their document tabs read
one named after the element.
- stocktransfer answered an empty classname, because it is not the ucfirst() of
the element, so a caller doing new $classname($db) ended on a fatal error.
- The sub directory was concatenated even when the module is disabled and the
directory is empty, which answered a path at the root of the file system.
- A contact and a conference are stored into a sub directory their tab reads.
isModEnabled('invoice') is tested for a customer payment: there is no module
named 'compta', so testing it was always false, while $conf->compta->payment is
set unconditionally by Conf::setValues() and could not be used as a proxy.
* FIX Access refused to everyone on 11 objects of the core
restrictedArea() and checkUserAccessToObject() refuse the access to objects that
no permission and no rule can match, whatever the user, an administrator
included.
- The hrm module declares no permission at its first level, only 'all', and the
stocktransfer module only 'stocktransfer'. A check on the module itself
therefore tests a permission that does not exist. The mapping is the same one
as into User::hasRight().
- The module of an event organization declares no permission at all, its whole
permission block being commented out on purpose, and its cards check the
parent project instead. The feature is mapped onto that project, with the two
guards the card has: an external user is refused, and so is a conference with
no parent project, whose id of 0 would otherwise grant an access with no check
on the record at all.
- The default rule of checkUserAccessToObject() builds its sql on the columns
entity and fk_soc of the table. llx_asset, llx_paiement, llx_paiementfourn and
llx_workstation_workstation have no fk_soc, and llx_hrm_job, llx_hrm_job_user
and llx_hrm_skill have neither. The sql failed, so the access was refused to
every user this rule applies to. These tables are now checked on their entity
only, which is what the $check rule already does for the same class of tables,
and the 3 tables of hrm can be checked on nothing at all. The rule is selected
on the table and not on the element, because $object is an id and not an
object for most of the callers, the cards of an asset and of a workstation
included, which are broken today for any user without the permission to see
all third parties.
- An external user is refused explicitly on those tables: none of these objects
is linked to a third party, so the default rule refused him through a link
that does not exist, and the rules that replace it do not look at the third
party of the user at all.
Measured on a vanilla instance with 5 profiles, an administrator, an internal
user with every right, one without the permission to see all third parties, one
that is not a sales representative of the third party of the object, and an
external user: the 11 objects go from refused to granted for the internal users
and stay refused for the external one, and the 26 other elements answer exactly
the same for the 5 profiles.
* FIX A file dropped on a card is lost, or reported as refused when it was stored
FileUpload stores the file into a directory that the "Attached files" tab of the
object never reads, so the user attaches a file that no screen will ever show,
and nothing is indexed in database to find it back. Measured on real databases:
216487 thirdparties over 216887 and 157852 products over 280319 are in that case
on the cards that already enable the drag and drop.
- The directory of the object is now forged with get_exdir(), the way the tabs
do: it always uses the id for a thirdparty, whose ref is a company name and is
not unique, and it falls back on the id when the ref is empty. The sub
directory of the module is read with getMultidirOutput(), which knows the
elements that store their documents into one. That function does not return
an empty string when it fails but a string starting with 'error-', so only an
absolute path is accepted: writing into that string would create the files
under the web root.
- fetchObjectByElement() returns an object even when fetch() returned 0. The
object was then not loaded, and the file was stored at the root of the
directory of the module, out of any object. The constructor now throws, and
the endpoint answers the error with the same json contract than a successful
call so that the caller can show it, instead of a fatal error and an http 500.
- An attachment of the same name was silently overwritten, dol_move_uploaded_file()
being called with $allowoverwrite = 1 while the name was checked before the
ref of the object was added as a prefix. The check is done again on the final
name, and on the .noexe suffixed name too, which that function appends to an
executable file.
- An executable file was renamed with that .noexe suffix and then reported as an
error, while it was correctly stored.
- The endpoint called restrictedArea() with an empty feature when the element is
unknown, and the loop of that function then takes no branch at all and grants
the access with no check. It refuses before, with the same http code and the
same message than a refusal, so that a user cannot tell an object that exists
but is not allowed from an object that does not exist. The refusal of an
external user on an object of another third party answered a message of its
own, which allowed the same enumeration.
Comes with the tests of the path resolution, of the fallback of get_exdir(), of
the rejection of the error string of getMultidirOutput(), and of the file name
deduplication.
* FIX Remove the drop area from 13 cards where dropping a file is harmful
Two distinct groups, both of them removing a drop area that only produces a
result the user does not want.
7 pages have no "Attached files" tab at all, so a file dropped on them can be
reached by no screen: a fiscal year and its info page, an accounting model, a
webhook trigger history, an intracomm report, a bookcal calendar and its booking
list. Measured: 4 of them accepted the upload and wrote an orphan file, the
accounting model wrote it at the root of the directory of the module, out of any
object, and the 2 bookcal ones answered an http 500.
6 cards print their tabs inside their edit form, so the drop area covered that
form: a product, an expense report, a VAT payment, a social contribution, a loan
and a salary. Dropping a file there reloads the page, which discards what the
user is typing. A product and an expense report have a second call for the read
only view, so the drop area is only removed from the call of the edit branch;
the 4 others share a single call between both views, so the parameter is now
conditional.
* NEW Drag and drop a file on the 23 remaining cards
Every card of the core that owns an "Attached files" tab can now receive a file
by drag and drop, which was the case of 32 of them only. The 23 added here are
an asset, an event, a various payment, a customer payment, a contact, a donation,
a conference or booth, a shipment, a supplier payment, a leave request, an
evaluation, a job, a position, a skill, a knowledge record, a manufacturing
order, a partnership, a lot, a stock transfer, a task, a reception, a resource
and a workstation.
The tab bar of a leave request and of a resource is printed inside their edit
form, so the drop area is not enabled there: dropping a file reloads the page,
which would discard what the user is typing. The card of a supplier payment
prints its tab bar even when the object was not loaded, so the drop area is only
enabled when it is.
* FIX getMultidirOutput refuses an entity with no directory instead of falling back [skip-claudemd]
The previous revision of this PR fell back on the directory of the current
entity when the entity of the object had none, with a LOG_WARNING. On a
multicompany install that made a caller read, write and above all delete
files in the directory of another entity. Refuse instead: the function
already answers 'error-diroutput-not-defined-for-this-object' when the
module declares no directory at all, so the caller has one behaviour to
handle, not two.
The entity is cast to int, which is what the array index needs and what
silences the four PhanTypeMismatchDimFetchNullable this function reported.
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
3037 lines
122 KiB
PHP
3037 lines
122 KiB
PHP
<?php
|
|
/* Copyright (C) 2003-2008 Rodolphe Quiedeville <rodolphe@quiedeville.org>
|
|
* Copyright (C) 2005-2016 Laurent Destailleur <eldy@users.sourceforge.net>
|
|
* Copyright (C) 2005 Simon TOSSER <simon@kornog-computing.com>
|
|
* Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
|
|
* Copyright (C) 2011-2017 Juanjo Menent <jmenent@2byte.es>
|
|
* Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
|
|
* Copyright (C) 2013 Marcos García <marcosgdf@gmail.com>
|
|
* Copyright (C) 2014 Cedric GROSS <c.gross@kreiz-it.fr>
|
|
* Copyright (C) 2014-2017 Francis Appels <francis.appels@yahoo.com>
|
|
* Copyright (C) 2015 Claudio Aschieri <c.aschieri@19.coop>
|
|
* Copyright (C) 2016 Ferran Marcet <fmarcet@2byte.es>
|
|
* Copyright (C) 2016 Yasser Carreón <yacasia@gmail.com>
|
|
* Copyright (C) 2018 Quentin Vial-Gouteyron <quentin.vial-gouteyron@atm-consulting.fr>
|
|
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
|
* Copyright (C) 2024-2025 Frédéric France <frederic.france@free.fr>
|
|
* Copyright (C) 2025 Nick Fragoulis
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
/**
|
|
* \file htdocs/reception/card.php
|
|
* \ingroup reception
|
|
* \brief Card of a reception
|
|
*/
|
|
|
|
// Load Dolibarr environment
|
|
require '../main.inc.php';
|
|
/**
|
|
* @var Conf $conf
|
|
* @var DoliDB $db
|
|
* @var HookManager $hookmanager
|
|
* @var Societe $mysoc
|
|
* @var Translate $langs
|
|
* @var User $user
|
|
*/
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/reception/class/reception.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/product/class/html.formproduct.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/product.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/reception.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/extrafields.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/entrepot.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
|
|
if (isModEnabled("product") || isModEnabled("service")) {
|
|
require_once DOL_DOCUMENT_ROOT.'/product/class/product.class.php';
|
|
}
|
|
if (isModEnabled("propal")) {
|
|
require_once DOL_DOCUMENT_ROOT.'/comm/propal/class/propal.class.php';
|
|
}
|
|
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.orderline.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/fourn/class/fournisseur.commande.dispatch.class.php';
|
|
if (isModEnabled('productbatch')) {
|
|
require_once DOL_DOCUMENT_ROOT.'/product/class/productbatch.class.php';
|
|
}
|
|
if (isModEnabled('project')) {
|
|
require_once DOL_DOCUMENT_ROOT.'/projet/class/project.class.php';
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/html.formprojet.class.php';
|
|
}
|
|
|
|
$langs->loadLangs(array("receptions", "companies", "bills", 'orders', 'stocks', 'other', 'propal', 'sendings'));
|
|
|
|
if (isModEnabled('incoterm')) {
|
|
$langs->load('incoterm');
|
|
}
|
|
if (isModEnabled('productbatch')) {
|
|
$langs->load('productbatch');
|
|
}
|
|
|
|
$origin = GETPOST('origin', 'alpha'); // Example: commande, propal
|
|
$origin_id = GETPOSTINT('origin_id') ? GETPOSTINT('id') : '';
|
|
$id = GETPOSTINT('id');
|
|
if (empty($origin_id) && !empty($origin)) {
|
|
$origin_id = GETPOSTINT('origin_id'); // Id of order or propal
|
|
}
|
|
if (empty($origin_id) && !empty($origin)) {
|
|
$origin_id = GETPOSTINT('object_id'); // Id of order or propal
|
|
}
|
|
if (empty($origin_id) && !empty($origin)) {
|
|
$origin_id = GETPOSTINT('originid'); // Id of order or propal
|
|
}
|
|
$ref = GETPOST('ref', 'alpha');
|
|
$line_id = GETPOSTINT('lineid') ? GETPOSTINT('lineid') : 0;
|
|
$facid = GETPOSTINT('facid');
|
|
$socid = GETPOSTINT('socid');
|
|
$action = GETPOST('action', 'alpha');
|
|
//Select mail models is same action as presend
|
|
if (GETPOST('modelselected')) {
|
|
$action = 'presend';
|
|
}
|
|
$confirm = GETPOST('confirm', 'alpha');
|
|
$cancel = GETPOST('cancel', 'alpha');
|
|
$backtopage = GETPOST('backtopage', 'alpha');
|
|
$backtopageforcancel = GETPOST('backtopageforcancel', 'alpha');
|
|
|
|
$contactid = GETPOSTINT('contactid');
|
|
$projectid = GETPOSTINT('projectid');
|
|
|
|
|
|
$cancel = GETPOST('cancel', 'alpha');
|
|
$rank = (GETPOSTINT('rank') > 0) ? GETPOSTINT('rank') : -1;
|
|
$lineid = GETPOSTINT('lineid');
|
|
$backtopage = GETPOST('backtopage', 'alpha');
|
|
//PDF
|
|
$hidedetails = (GETPOSTINT('hidedetails') ? GETPOSTINT('hidedetails') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS') ? 1 : 0));
|
|
$hidedesc = (GETPOSTINT('hidedesc') ? GETPOSTINT('hidedesc') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_DESC') ? 1 : 0));
|
|
$hideref = (GETPOSTINT('hideref') ? GETPOSTINT('hideref') : (getDolGlobalString('MAIN_GENERATE_DOCUMENTS_HIDE_REF') ? 1 : 0));
|
|
|
|
$object = new Reception($db);
|
|
$objectorder = new CommandeFournisseur($db);
|
|
$extrafields = new ExtraFields($db);
|
|
|
|
// fetch optionals attributes and labels
|
|
$extrafields->fetch_name_optionals_label($object->table_element);
|
|
$extrafields->fetch_name_optionals_label($object->table_element_line);
|
|
$extrafields->fetch_name_optionals_label($objectorder->table_element_line);
|
|
|
|
// Load object. Make an object->fetch
|
|
include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be 'include', not 'include_once'
|
|
|
|
// Restore $origin and $origin_id from the loaded object when the request only carried the
|
|
// reception id (e.g. the line edit form on an existing reception posts action=updateline
|
|
// and id=N but no origin field). Without this, the action handler below sees $origin
|
|
// empty and silently skips both its standalone and its origin branches, so updates to
|
|
// quantity, comment, batch and extrafields on an existing line are not persisted
|
|
// (see issue #38386, regression from PR #36134).
|
|
// The restore is gated on $object->origin_id > 0 so standalone receptions, which have
|
|
// no upstream origin, are not affected: $origin stays empty and the standalone branch
|
|
// of the updateline handler is still selected.
|
|
if ($object->origin_id > 0) {
|
|
if (empty($origin)) {
|
|
if (!empty($object->origin_type)) {
|
|
$origin = $object->origin_type;
|
|
} elseif (is_string($object->origin) && $object->origin !== '') {
|
|
$origin = (string) $object->origin;
|
|
}
|
|
}
|
|
if (empty($origin_id)) {
|
|
$origin_id = $object->origin_id;
|
|
}
|
|
}
|
|
|
|
// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
|
|
$hookmanager->initHooks(array('receptioncard', 'globalcard'));
|
|
|
|
$date_delivery = dol_mktime(GETPOSTINT('date_deliveryhour'), GETPOSTINT('date_deliverymin'), 0, GETPOSTINT('date_deliverymonth'), GETPOSTINT('date_deliveryday'), GETPOSTINT('date_deliveryyear'));
|
|
$date_reception = dol_mktime(GETPOSTINT('date_receptionhour'), GETPOSTINT('date_receptionmin'), 0, GETPOSTINT('date_receptionmonth'), GETPOSTINT('date_receptionday'), GETPOSTINT('date_receptionyear'));
|
|
|
|
// Security check
|
|
if ($user->socid) {
|
|
$socid = $user->socid;
|
|
}
|
|
$result = restrictedArea($user, 'reception', $object->id, '');
|
|
// TODO Test on reception module on only
|
|
if (isModEnabled("reception") || $origin == 'reception' || empty($origin)) {
|
|
$result = restrictedArea($user, 'reception', $object->id);
|
|
} else {
|
|
// We do not use the reception module, so we test permission on the supplier orders
|
|
if ($origin == 'supplierorder' || $origin == 'order_supplier') {
|
|
$result = restrictedArea($user, 'fournisseur', $origin_id, 'commande_fournisseur', 'commande');
|
|
} elseif (!$user->hasRight($origin, 'lire') && !$user->hasRight($origin, 'read')) {
|
|
accessforbidden();
|
|
}
|
|
}
|
|
|
|
if (isModEnabled("reception")) {
|
|
$permissiontoread = $user->hasRight('reception', 'lire');
|
|
$permissiontoadd = $user->hasRight('reception', 'creer');
|
|
$permissiontoedit = $user->hasRight('reception', 'creer'); // Used by the include of actions_lineupdown.inc.php
|
|
$permissiondellink = $user->hasRight('reception', 'creer'); // Used by the include of actions_dellink.inc.php
|
|
$permissiontovalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate')));
|
|
$permissiontodelete = $user->hasRight('reception', 'supprimer');
|
|
} else {
|
|
$permissiontoread = $user->hasRight('fournisseur', 'commande', 'receptionner');
|
|
$permissiontoadd = $user->hasRight('fournisseur', 'commande', 'receptionner');
|
|
$permissiondellink = $user->hasRight('fournisseur', 'commande', 'receptionner'); // Used by the include of actions_dellink.inc.php
|
|
$permissiontovalidate = ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande', 'receptionner')) || (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('fournisseur', 'commande_advance', 'check')));
|
|
$permissiontodelete = $user->hasRight('fournisseur', 'commande', 'receptionner');
|
|
}
|
|
$permissiontoeditextra = $permissiontoadd;
|
|
if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
|
|
// For action 'update_extras' there is a specific permission set for the attribute to update
|
|
$permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
|
|
}
|
|
|
|
$editColspan = 0;
|
|
$objectsrc = null;
|
|
$typeobject = null;
|
|
$ref_customer = null;
|
|
$shipping_method_id = null;
|
|
$warehouse_id = null;
|
|
$note_public = null;
|
|
$note_private = null;
|
|
|
|
|
|
/*
|
|
* Actions
|
|
*/
|
|
|
|
$error = 0;
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
}
|
|
|
|
if (empty($reshook)) {
|
|
$backurlforlist = DOL_URL_ROOT.'/reception/list.php';
|
|
|
|
if (empty($backtopage) || ($cancel && empty($id))) {
|
|
if (empty($backtopage) || ($cancel && strpos($backtopage, '__ID__'))) {
|
|
if (empty($id) && (($action != 'add' && $action != 'create') || $cancel)) {
|
|
$backtopage = $backurlforlist;
|
|
} else {
|
|
$backtopage = DOL_URL_ROOT.'/reception/card.php?id='.((!empty($id) && $id > 0) ? $id : '__ID__');
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($cancel) {
|
|
if (!empty($backtopageforcancel)) {
|
|
header("Location: ".$backtopageforcancel);
|
|
exit;
|
|
} elseif (!empty($backtopage)) {
|
|
header("Location: ".$backtopage);
|
|
exit;
|
|
}
|
|
|
|
$action = '';
|
|
}
|
|
|
|
if ($cancel) {
|
|
if (!$origin) {
|
|
$action = '';
|
|
$object->fetch($object->id); // show reception also after canceling modification
|
|
}
|
|
}
|
|
|
|
include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
|
|
|
|
// Reopen
|
|
if ($action == 'reopen' && $permissiontoadd) { // Test on permissions not required here
|
|
$result = $object->reOpen();
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
}
|
|
|
|
// Confirm back to draft status
|
|
if ($action == 'modif' && $permissiontoadd) {
|
|
$result = $object->setDraft($user);
|
|
if ($result >= 0) {
|
|
// Define output language
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
$model = $object->model_pdf;
|
|
$ret = $object->fetch($id); // Reload to get new records
|
|
$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
}
|
|
|
|
// Set incoterm
|
|
if ($action == 'set_incoterms' && isModEnabled('incoterm') && $permissiontoadd) {
|
|
$result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
|
|
}
|
|
|
|
if ($action == 'setref_supplier' && $permissiontoadd) {
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
|
|
$result = $object->setValueFrom('ref_supplier', GETPOST('ref_supplier', 'alpha'), '', null, 'text', '', $user, 'RECEPTION_MODIFY');
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$action = 'editref_supplier';
|
|
} else {
|
|
header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if ($action == 'update_extras' && $permissiontoeditextra) {
|
|
$object->oldcopy = dol_clone($object, 2); // @phan-suppress-current-line PhanTypeMismatchProperty
|
|
|
|
$attribute_name = GETPOST('attribute', 'aZ09');
|
|
|
|
// Fill array 'array_options' with data from update form
|
|
$ret = $extrafields->setOptionalsFromPost(null, $object, $attribute_name);
|
|
if ($ret < 0) {
|
|
$error++;
|
|
}
|
|
|
|
if (!$error) {
|
|
$result = $object->updateExtraField($attribute_name, 'RECEPTION_MODIFY');
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
|
|
if ($error) {
|
|
$action = 'edit_extras';
|
|
}
|
|
}
|
|
|
|
// Create reception
|
|
if ($action == 'add' && $permissiontoadd) {
|
|
$db->begin();
|
|
|
|
if (!$error && !$origin && getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
if (GETPOSTINT('socid') < 1) {
|
|
$error++;
|
|
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors');
|
|
$action = 'create';
|
|
}
|
|
|
|
$object->socid = GETPOSTINT('socid');
|
|
$object->fetch_thirdparty();
|
|
$object->note = GETPOST('note', 'alpha');
|
|
$object->note_private = GETPOST('note', 'alpha');
|
|
$object->origin = $origin; // deprecated
|
|
$object->origin_type = $origin;
|
|
$object->origin_id = $origin_id;
|
|
$object->fk_project = GETPOSTINT('projectid');
|
|
$object->weight = GETPOSTINT('weight') == '' ? null : GETPOSTINT('weight');
|
|
$object->trueHeight = GETPOSTINT('trueHeight') == '' ? null : GETPOSTINT('trueHeight');
|
|
$object->trueWidth = GETPOSTINT('trueWidth') == '' ? null : GETPOSTINT('trueWidth');
|
|
$object->trueDepth = GETPOSTINT('trueDepth') == '' ? null : GETPOSTINT('trueDepth');
|
|
$object->size_units = GETPOSTINT('size_units');
|
|
$object->weight_units = GETPOSTINT('weight_units');
|
|
$object->ref_supplier = GETPOST('ref_supplier', 'alpha');
|
|
$object->model_pdf = GETPOST('model');
|
|
$object->date_delivery = $date_delivery; // Date delivery planned
|
|
$object->date_reception = $date_reception;
|
|
$object->shipping_method_id = GETPOSTINT('shipping_method_id');
|
|
$object->tracking_number = GETPOST('tracking_number', 'alpha');
|
|
$object->note_private = GETPOST('note_private', 'restricthtml');
|
|
$object->note_public = GETPOST('note_public', 'restricthtml');
|
|
$object->fk_incoterms = GETPOSTINT('incoterm_id');
|
|
$object->location_incoterms = GETPOST('location_incoterms', 'alpha');
|
|
|
|
$product = new Product($db);
|
|
|
|
// Fill array 'array_options' with data from add form
|
|
$ret = $extrafields->setOptionalsFromPost(null, $object);
|
|
if ($ret < 0) {
|
|
$error++;
|
|
}
|
|
|
|
if (!$error) {
|
|
$ret = $object->create($user);
|
|
if ($ret <= 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
}
|
|
if ($origin && $origin_id > 0) {
|
|
$object->note = GETPOST('note', 'alpha');
|
|
$object->note_private = GETPOST('note', 'alpha');
|
|
$object->origin = $origin;
|
|
$object->origin_type = $origin;
|
|
$object->origin_id = $origin_id;
|
|
$object->fk_project = GETPOSTINT('projectid');
|
|
$object->weight = GETPOST('weight') == '' ? null : GETPOSTINT('weight');
|
|
$object->trueHeight = GETPOST('trueHeight') == '' ? null : GETPOSTINT('trueHeight');
|
|
$object->trueWidth = GETPOST('trueWidth') == '' ? null : GETPOSTINT('trueWidth');
|
|
$object->trueDepth = GETPOST('trueDepth') == '' ? null : GETPOSTINT('trueDepth');
|
|
$object->size_units = GETPOSTINT('size_units');
|
|
$object->weight_units = GETPOSTINT('weight_units');
|
|
|
|
$object->ref_supplier = GETPOST('ref_supplier', 'alpha');
|
|
$object->model_pdf = GETPOST('model');
|
|
$object->date_delivery = $date_delivery; // Date delivery planned
|
|
$object->date_reception = $date_reception;
|
|
$object->shipping_method_id = GETPOSTINT('shipping_method_id');
|
|
$object->tracking_number = GETPOST('tracking_number', 'alpha');
|
|
$object->note_private = GETPOST('note_private', 'restricthtml');
|
|
$object->note_public = GETPOST('note_public', 'restricthtml');
|
|
$object->fk_incoterms = GETPOSTINT('incoterm_id');
|
|
$object->location_incoterms = GETPOST('location_incoterms', 'alpha');
|
|
|
|
if ($object->origin == "supplierorder") {
|
|
$object->origin = 'order_supplier';
|
|
$object->origin_type = 'order_supplier';
|
|
$classname = 'CommandeFournisseur';
|
|
} else {
|
|
$classname = ucfirst($object->origin_type);
|
|
}
|
|
$objectsrc = new $classname($db);
|
|
$objectsrc->fetch($object->origin_id);
|
|
|
|
$object->socid = $objectsrc->socid;
|
|
|
|
$product = new Product($db);
|
|
$batch_line = array();
|
|
$stockLine = array();
|
|
$array_options = array();
|
|
|
|
$totalqty = 0;
|
|
|
|
$num = 0;
|
|
foreach ($_POST as $key => $value) {
|
|
// without batch module enabled
|
|
|
|
if (strpos($key, 'qtyasked') !== false) {
|
|
$num++;
|
|
}
|
|
}
|
|
|
|
// Loop lines to calculate $totalqty
|
|
for ($i = 1; $i <= $num; $i++) {
|
|
$idl = "idl".$i; // id line source
|
|
|
|
//$sub_qty = array();
|
|
//$subtotalqty = 0;
|
|
|
|
//$j = 0;
|
|
//$batch = "batchl".$i."_0";
|
|
//$stockLocation = "ent1".$i."_0";
|
|
$qty = "qtyl".$i; // qty
|
|
|
|
//reception line for product with no batch management and no multiple stock location
|
|
if (GETPOST($qty, 'alpha') > 0) {
|
|
$totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
|
|
}
|
|
|
|
// Extrafields
|
|
$array_options[$i] = $extrafields->getOptionalsFromPost($object->table_element_line, (string) $i);
|
|
}
|
|
|
|
|
|
if ($totalqty > 0) { // There is at least one thing to ship
|
|
for ($i = 1; $i <= $num; $i++) {
|
|
$idl = "idl".$i; // id line source
|
|
$lineToTest = '';
|
|
$lineId = GETPOSTINT($idl);
|
|
foreach ($objectsrc->lines as $linesrc) {
|
|
if ($linesrc->id == $lineId) {
|
|
$lineToTest = $linesrc;
|
|
break;
|
|
}
|
|
}
|
|
if (empty($lineToTest)) {
|
|
continue;
|
|
}
|
|
$qty = "qtyl".$i;
|
|
$comment = "comment".$i;
|
|
// EATBY <-> DLUO and SELLBY <-> DLC, see productbatch.class.php
|
|
$eatby = "dluo".$i;
|
|
$sellby = "dlc".$i;
|
|
$batch = "batch".$i;
|
|
$cost_price = "cost_price".$i;
|
|
|
|
//var_dump(GETPOST("productl".$i, 'int').' '.GETPOST('entl'.$i, 'int').' '.GETPOST($idl, 'int').' '.GETPOST($qty, 'int').' '.GETPOST($batch, 'alpha'));
|
|
|
|
//if (GETPOST($qty, 'int') > 0 || (GETPOST($qty, 'int') == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS')) || (GETPOST($qty, 'int') < 0 && getDolGlobalString('RECEPTION_ALLOW_NEGATIVE_QTY'))) {
|
|
if (GETPOSTFLOAT($qty) > 0 || (GETPOSTFLOAT($qty) == 0 && getDolGlobalString('RECEPTION_GETS_ALL_ORDER_PRODUCTS'))) {
|
|
$ent = "entl".$i;
|
|
$idl = "idl".$i;
|
|
|
|
$entrepot_id = is_numeric(GETPOST($ent)) ? GETPOSTINT($ent) : GETPOSTINT('entrepot_id');
|
|
|
|
/*
|
|
if (!empty($lineToTest)) {
|
|
$fk_product = $lineToTest->fk_product;
|
|
} else {
|
|
$fk_product = $linesrc->fk_product;
|
|
}*/
|
|
$fk_product = GETPOSTINT("productl".$i);
|
|
|
|
if ($entrepot_id < 0) {
|
|
$entrepot_id = '';
|
|
}
|
|
if (!($fk_product > 0) && !getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
|
|
$entrepot_id = 0;
|
|
}
|
|
|
|
$eatby = GETPOST($eatby, 'alpha');
|
|
$sellby = GETPOST($sellby, 'alpha');
|
|
$eatbydate = str_replace('/', '-', $eatby);
|
|
$sellbydate = str_replace('/', '-', $sellby);
|
|
|
|
if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
|
|
$ret = $object->addline($entrepot_id, GETPOSTINT($idl), (float) price2num(GETPOST($qty), 'MS'), $array_options[$i], GETPOST($comment), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch), GETPOSTFLOAT($cost_price, 'MU'));
|
|
} else {
|
|
$ret = $object->addline($entrepot_id, GETPOSTINT($idl), (float) price2num(GETPOST($qty), 'MS'), $array_options[$i], GETPOST($comment), strtotime($eatbydate), strtotime($sellbydate), GETPOST($batch));
|
|
}
|
|
if ($ret < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Fill array 'array_options' with data from add form
|
|
$ret = $extrafields->setOptionalsFromPost(null, $object);
|
|
if ($ret < 0) {
|
|
$error++;
|
|
}
|
|
if (!$error) {
|
|
$ret = $object->create($user); // This create reception (like Odoo picking) and line of receptions. Stock movement will when validating reception.
|
|
|
|
if ($ret <= 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
// Define output language
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
$object->fetch_thirdparty();
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
$model = $object->model_pdf;
|
|
$ret = $object->fetch($object->id); // Reload to get new records
|
|
|
|
$result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
if ($result < 0) {
|
|
dol_print_error($db, $object->error, $object->errors);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("QtyToReceive").'/'.$langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
if (!$error) {
|
|
$db->commit();
|
|
header("Location: card.php?id=" . $object->id);
|
|
exit;
|
|
} else {
|
|
$db->rollback();
|
|
//$_GET["commande_id"] = GETPOSTINT('commande_id');
|
|
$action = 'create';
|
|
}
|
|
} elseif ($action == 'confirm_valid' && $confirm == 'yes' && $permissiontovalidate) {
|
|
$object->fetch_thirdparty();
|
|
|
|
$result = $object->valid($user);
|
|
|
|
if ($result < 0) {
|
|
$langs->load("errors");
|
|
setEventMessages($langs->trans($object->error), null, 'errors');
|
|
} else {
|
|
// Define output language
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
$model = $object->model_pdf;
|
|
$ret = $object->fetch($id); // Reload to get new records
|
|
|
|
$result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
if ($result < 0) {
|
|
dol_print_error($db, $object->error, $object->errors);
|
|
}
|
|
}
|
|
}
|
|
} elseif ($action == 'confirm_delete' && $confirm == 'yes' && $permissiontodelete) {
|
|
$result = $object->delete($user);
|
|
if ($result > 0) {
|
|
header("Location: ".DOL_URL_ROOT.'/reception/index.php');
|
|
exit;
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
|
|
// TODO add alternative status
|
|
/*} elseif ($action == 'reopen' && ($user->hasRights('reception', 'creer') || $user->hasRights('reception', 'reception_advance', 'validate'))) {
|
|
$result = $object->setStatut(Reception::STATUS_DRAFT);
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}*/
|
|
} elseif ($action == 'setdate_livraison' && $permissiontoadd) {
|
|
$datedelivery = dol_mktime(GETPOSTINT('liv_hour'), GETPOSTINT('liv_min'), 0, GETPOSTINT('liv_month'), GETPOSTINT('liv_day'), GETPOSTINT('liv_year'));
|
|
|
|
$object->fetch($id);
|
|
$result = $object->setDeliveryDate($user, $datedelivery);
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'setdate_reception' && $user->hasRight('reception', 'creer')) {
|
|
$datereception = dol_mktime(GETPOSTINT('recep_hour'), GETPOSTINT('recep_min'), 0, GETPOSTINT('recep_month'), GETPOSTINT('recep_day'), GETPOSTINT('recep_year'));
|
|
|
|
$object->fetch($id);
|
|
$result = $object->setReceptionDate($user, $datereception);
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'confirm_deleteline' && $confirm == 'yes' && $permissiontoadd) {
|
|
// Remove a product line
|
|
$result = $object->deleteLine($user, $lineid);
|
|
if ($result > 0) {
|
|
// reorder lines
|
|
$object->line_order(true);
|
|
// Define output language
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
$ret = $object->fetch($object->id); // Reload to get new records
|
|
$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit;
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif (in_array($action, array('settracking_number', 'settracking_url', 'settrueWeight', 'settrueWidth', 'settrueHeight', 'settrueDepth', 'setshipping_method_id')) && $permissiontoadd) {
|
|
// Action update
|
|
$error = 0;
|
|
|
|
if ($action == 'settracking_number') { // Test on permission already done
|
|
$object->tracking_number = trim(GETPOST('tracking_number', 'alpha'));
|
|
}
|
|
if ($action == 'settracking_url') { // Test on permission already done
|
|
$object->tracking_url = trim(GETPOST('tracking_url', 'restricthtml'));
|
|
}
|
|
if ($action == 'settrueWeight') { // Test on permission already done
|
|
$object->trueWeight = GETPOST('trueWeight');
|
|
$object->weight_units = GETPOSTINT('weight_units');
|
|
}
|
|
if ($action == 'settrueWidth') { // Test on permission already done
|
|
$object->trueWidth = GETPOST('trueWidth');
|
|
}
|
|
if ($action == 'settrueHeight') { // Test on permission already done
|
|
$object->trueHeight = GETPOST('trueHeight');
|
|
$object->size_units = GETPOSTINT('size_units');
|
|
}
|
|
if ($action == 'settrueDepth') { // Test on permission already done
|
|
$object->trueDepth = GETPOST('trueDepth');
|
|
}
|
|
if ($action == 'setshipping_method_id') { // Test on permission already done
|
|
$object->shipping_method_id = GETPOSTINT('shipping_method_id');
|
|
}
|
|
|
|
if ($object->update($user) >= 0) {
|
|
header("Location: card.php?id=" . $object->id);
|
|
exit;
|
|
}
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
|
|
$action = "";
|
|
} elseif ($action == 'builddoc' && $permissiontoread) {
|
|
// Build document
|
|
// En get ou en post
|
|
// Save last template used to generate document
|
|
if (GETPOST('model')) {
|
|
$object->setDocModel($user, GETPOST('model', 'alpha'));
|
|
}
|
|
|
|
// Define output language
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
$result = $object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
if ($result <= 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$action = '';
|
|
}
|
|
} elseif ($action == 'remove_file' && $permissiontoadd) {
|
|
// Delete file in doc form
|
|
require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php';
|
|
|
|
$upload_dir = $conf->reception->dir_output;
|
|
$file = $upload_dir.'/'.GETPOST('file');
|
|
$ret = dol_delete_file($file, 1, 0, 0, $object);
|
|
if ($ret) {
|
|
setEventMessages($langs->trans("FileWasRemoved", GETPOST('urlfile')), null, 'mesgs');
|
|
} else {
|
|
setEventMessages($langs->trans("ErrorFailToDeleteFile", GETPOST('urlfile')), null, 'errors');
|
|
}
|
|
} elseif ($action == 'classifybilled' && $permissiontoadd) {
|
|
$result = $object->setBilled();
|
|
if ($result >= 0) {
|
|
header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
|
|
exit();
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$action = '';
|
|
}
|
|
} elseif ($action == 'classifyclosed' && $permissiontoread) {
|
|
$result = $object->setClosed();
|
|
if ($result >= 0) {
|
|
header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
|
|
exit();
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$action = '';
|
|
}
|
|
} elseif ($action == 'deleteline' && !empty($line_id) && $permissiontoread) {
|
|
// delete a line
|
|
$lines = $object->lines;
|
|
$line = new CommandeFournisseurDispatch($db);
|
|
|
|
$num_prod = count($lines);
|
|
for ($i = 0; $i < $num_prod; $i++) {
|
|
if ($lines[$i]->id == $line_id) {
|
|
// delete single warehouse line
|
|
$line->id = $line_id;
|
|
if (!$error && $line->delete($user) < 0) {
|
|
$error++;
|
|
}
|
|
}
|
|
unset($_POST["lineid"]);
|
|
}
|
|
|
|
if (!$error) {
|
|
header('Location: '.$_SERVER["PHP_SELF"].'?id='.$object->id);
|
|
exit();
|
|
} else {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'updateline' && GETPOST('save') && $permissiontoadd) {
|
|
if (!$origin && getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
// Update a line
|
|
// Clean parameters
|
|
|
|
if (!$object->fetch($id) > 0) {
|
|
dol_print_error($db);
|
|
}
|
|
$object->fetch_thirdparty();
|
|
|
|
$qty = GETPOST('qty', 'alpha');
|
|
$description = '';
|
|
$element_type = 'reception';
|
|
$fk_unit = '';
|
|
$fk_product = 0;
|
|
$rang = 0;
|
|
|
|
// Extrafields
|
|
$extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
|
|
$array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
|
|
// Unset extrafield
|
|
if (is_array($extralabelsline)) {
|
|
// Get extra fields
|
|
foreach ($extralabelsline as $key => $value) {
|
|
unset($_POST["options_" . $key]);
|
|
}
|
|
}
|
|
|
|
$receptionline = new ReceptionLineBatch($db);
|
|
$receptionline->fetch(GETPOSTINT('lineid'));
|
|
|
|
|
|
if (!$error) {
|
|
$result = $object->updatelinefree(GETPOSTINT('lineid'), (float) $qty, $element_type, $fk_product, GETPOSTINT('units'), $rang, $description, 0, $array_options);
|
|
|
|
if ($result >= 0) {
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
// Define output language
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
$outputlangs->load('products');
|
|
}
|
|
|
|
$ret = $object->fetch($object->id); // Reload to get new records
|
|
$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
unset($_POST['qty']);
|
|
unset($_POST['units']);
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
}
|
|
} elseif ($origin && $origin_id > 0) {
|
|
// Update a line
|
|
// Clean parameters
|
|
$qty = 0;
|
|
$entrepot_id = 0;
|
|
$batch_id = 0;
|
|
|
|
$lines = $object->lines;
|
|
$num_prod = count($lines);
|
|
for ($i = 0; $i < $num_prod; $i++) {
|
|
if ($lines[$i]->id == $line_id) { // we have found line to update
|
|
$line = new CommandeFournisseurDispatch($db);
|
|
$line->fetch($line_id);
|
|
// Extrafields Lines
|
|
$extrafields->fetch_name_optionals_label($object->table_element_line);
|
|
$line->array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
|
|
|
|
$line->fk_product = $lines[$i]->fk_product;
|
|
|
|
if ($lines[$i]->fk_product > 0) {
|
|
// single warehouse reception line
|
|
$stockLocation = "entl".$line_id;
|
|
$qty = "qtyl".$line_id;
|
|
$comment = "comment".$line_id;
|
|
|
|
$line->id = $line_id;
|
|
$line->fk_entrepot = GETPOSTINT($stockLocation);
|
|
$line->qty = GETPOSTFLOAT($qty, 'MS');
|
|
$line->comment = GETPOST($comment, 'alpha');
|
|
|
|
if (isModEnabled('productbatch')) {
|
|
$batch = "batch".$line_id;
|
|
$dlc = "dlc".$line_id;
|
|
$dluo = "dluo".$line_id;
|
|
// EATBY <-> DLUO
|
|
$eatby = GETPOST($dluo, 'alpha');
|
|
$eatbydate = str_replace('/', '-', $eatby);
|
|
// SELLBY <-> DLC
|
|
$sellby = GETPOST($dlc, 'alpha');
|
|
$sellbydate = str_replace('/', '-', $sellby);
|
|
$line->batch = GETPOST($batch, 'alpha');
|
|
$line->eatby = strtotime($eatbydate);
|
|
$line->sellby = strtotime($sellbydate);
|
|
}
|
|
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
}
|
|
} else { // Product no predefined
|
|
$qty = "qtyl".$line_id;
|
|
$line->id = $line_id;
|
|
$line->qty = GETPOSTFLOAT($qty, 'MS');
|
|
$line->fk_entrepot = 0;
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
}
|
|
unset($_POST[$qty]);
|
|
}
|
|
}
|
|
}
|
|
|
|
unset($_POST["lineid"]);
|
|
|
|
if (!$error) {
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
// Define output language
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') /* && empty($newlang) */ && GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
|
|
$ret = $object->fetch($object->id); // Reload to get new records
|
|
$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
|
|
// Redirect after the successful save so the page leaves edit mode and the
|
|
// updated values are read back from DB, matching the cancel path below
|
|
// and the header-data save handlers (see issue #38386).
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id);
|
|
exit();
|
|
} else {
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
|
|
exit();
|
|
}
|
|
}
|
|
} elseif ($action == 'updateline' && $permissiontoadd && GETPOST('cancel', 'alpha') == $langs->trans("Cancel")) {
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To reshow the record we edit
|
|
exit();
|
|
} elseif ($action == 'addline' && !$origin && getDolGlobalString('RECEPTION_STANDALONE') && $permissiontoadd) { // Add a new line
|
|
$langs->load('errors');
|
|
$error = 0;
|
|
$line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
|
|
$predef = '';
|
|
$description = '';
|
|
$fk_elementdet = '';
|
|
$element_type = 'reception';
|
|
$fk_unit = '';
|
|
$idprod = 0;
|
|
$fk_product = 0;
|
|
$fk_entrepot = '';
|
|
$rang = '';
|
|
$prod_entry_mode = GETPOST('prod_entry_mode', 'aZ09');
|
|
if ($prod_entry_mode == 'free') {
|
|
$idprod = 0;
|
|
} else {
|
|
$idprod = GETPOSTINT('idprod');
|
|
if (getDolGlobalString('MAIN_DISABLE_FREE_LINES') && $idprod <= 0) {
|
|
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ProductOrService")), null, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
|
|
$qty = price2num(GETPOST('qty'.$predef, 'alpha'), 'MS', 2);
|
|
|
|
// Extrafields
|
|
$extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
|
|
$array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
|
|
// Unset extrafield
|
|
if (is_array($extralabelsline)) {
|
|
// Get extra fields
|
|
foreach ($extralabelsline as $key => $value) {
|
|
unset($_POST["options_".$key]);
|
|
}
|
|
}
|
|
|
|
if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
|
|
$error++;
|
|
}
|
|
|
|
if ($qty == '') {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
|
|
$error++;
|
|
}
|
|
if ($qty < 0) {
|
|
setEventMessages($langs->trans('FieldCannotBeNegative', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
|
|
$error++;
|
|
}
|
|
if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($line_desc)) {
|
|
setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
|
|
$error++;
|
|
}
|
|
|
|
if (!$error && isModEnabled('variants') && $prod_entry_mode != 'free') {
|
|
if ($combinations = GETPOST('combinations', 'array')) {
|
|
// Check if there is a product with the given combination
|
|
$prodcomb = new ProductCombination($db);
|
|
|
|
if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
|
|
$idprod = $res->fk_product_child;
|
|
$fk_product = $idprod; // Update $fk_product with the fetched child product
|
|
} else {
|
|
setEventMessages($langs->trans('ErrorProductCombinationNotFound'), null, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!$error && ($qty >= 0) && (!empty($line_desc) || (!empty($idprod) && $idprod > 0))) {
|
|
// Clean parameters
|
|
if (!empty($idprod) && $idprod > 0) {
|
|
$prod = new Product($db);
|
|
$prod->fetch($idprod);
|
|
$desc = $prod->label;
|
|
$description = $desc;
|
|
// Define output language
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
|
|
$description = (!empty($prod->multilangs[$outputlangs->defaultlang]["description"])) ? $prod->multilangs[$outputlangs->defaultlang]["description"] : $prod->description;
|
|
} else {
|
|
$description = $prod->description;
|
|
}
|
|
if (getDolGlobalInt('PRODUIT_AUTOFILL_DESC') == 0) {
|
|
$description = dol_concatdesc($desc, $line_desc, false, getDolGlobalString('MAIN_CHANGE_ORDER_CONCAT_DESCRIPTION') ? true : false);
|
|
} else {
|
|
$description = $line_desc;
|
|
}
|
|
|
|
// Add custom code and origin country into description
|
|
if (!getDolGlobalString('MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE') && (!empty($prod->customcode) || !empty($prod->country_code))) {
|
|
$tmptxt = '(';
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
|
|
$outputlangs = $langs;
|
|
$newlang = '';
|
|
if (GETPOST('lang_id', 'alpha')) {
|
|
$newlang = GETPOST('lang_id', 'alpha');
|
|
}
|
|
if (empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
$outputlangs->load('products');
|
|
}
|
|
if (!empty($prod->customcode)) {
|
|
$tmptxt .= $outputlangs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
|
|
}
|
|
if (!empty($prod->customcode) && !empty($prod->country_code)) {
|
|
$tmptxt .= ' - ';
|
|
}
|
|
if (!empty($prod->country_code)) {
|
|
$tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $outputlangs, 0);
|
|
}
|
|
} else {
|
|
if (!empty($prod->customcode)) {
|
|
$tmptxt .= $langs->transnoentitiesnoconv("CustomsCode").': '.$prod->customcode;
|
|
}
|
|
if (!empty($prod->customcode) && !empty($prod->country_code)) {
|
|
$tmptxt .= ' - ';
|
|
}
|
|
if (!empty($prod->country_code)) {
|
|
$tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin").': '.getCountry($prod->country_code, '', $db, $langs, 0);
|
|
}
|
|
}
|
|
$tmptxt .= ')';
|
|
$description = dol_concatdesc($desc, $tmptxt);
|
|
}
|
|
$type = $prod->type;
|
|
$fk_unit = $prod->fk_unit;
|
|
} else {
|
|
$label = (GETPOST('product_label') ? GETPOST('product_label') : '');
|
|
$desc = $line_desc;
|
|
$type = GETPOST('type');
|
|
$fk_unit = GETPOST('units', 'alpha');
|
|
$description = $desc;
|
|
$fk_elementdet = '';
|
|
}
|
|
$desc = dol_htmlcleanlastbr($desc);
|
|
|
|
if (!$error) {
|
|
// Insert line
|
|
$result = $object->addlinefree((float) $qty, $element_type, $idprod, $fk_unit, min($rank, count($object->lines) + 1), $description, $array_options);
|
|
|
|
if ($result > 0) {
|
|
$ret = $object->fetch($object->id); // Reload to get new records
|
|
$object->fetch_thirdparty();
|
|
if (!getDolGlobalString('MAIN_DISABLE_PDF_AUTOUPDATE')) {
|
|
// Define output language
|
|
$outputlangs = $langs;
|
|
$newlang = GETPOST('lang_id', 'alpha');
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
} else {
|
|
header('Location: '.$_SERVER['PHP_SELF'].'?id='.$object->id); // To redisplay the form being edited
|
|
exit();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
|
|
|
|
// Actions to send emails
|
|
if (empty($id)) {
|
|
$id = $facid;
|
|
}
|
|
$triggersendname = 'RECEPTION_SENTBYMAIL';
|
|
$paramname = 'id';
|
|
$mode = 'emailfromreception';
|
|
$autocopy = 'MAIN_MAIL_AUTOCOPY_RECEPTION_TO';
|
|
$trackid = 'rec'.$object->id;
|
|
include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
|
|
}
|
|
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$title = $object->ref.' - '.$langs->trans('Reception');
|
|
if ($action == 'create') {
|
|
$title = $langs->trans("NewReception");
|
|
}
|
|
llxHeader('', $title, 'Reception', '', 0, 0, '', '', '', 'mod-reception page-card');
|
|
|
|
$form = new Form($db);
|
|
$formfile = new FormFile($db);
|
|
$formproduct = new FormProduct($db);
|
|
$formproject = null;
|
|
if (isModEnabled('project')) {
|
|
$formproject = new FormProjets($db);
|
|
} else {
|
|
$formproject = null;
|
|
}
|
|
|
|
$product_static = new Product($db);
|
|
$reception_static = new Reception($db);
|
|
$warehousestatic = new Entrepot($db);
|
|
|
|
if ($action == 'create' && $origin != 'supplierorder' && !getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
print load_fiche_titre($langs->trans("CreateReception"), '', 'dollyrevert');
|
|
|
|
print '<br>'.$langs->trans("ReceptionCreationIsDoneFromOrder");
|
|
$action = '';
|
|
$id = '';
|
|
$ref = '';
|
|
}
|
|
|
|
// Mode creation.
|
|
if ($action == 'create' && $permissiontoadd) {
|
|
$recept = new Reception($db);
|
|
|
|
print load_fiche_titre($langs->trans("NewReception"), '', 'dollyrevert');
|
|
if (empty($origin) && getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
$soc = new Societe($db);
|
|
if ($socid > 0) {
|
|
$res = $soc->fetch($socid);
|
|
}
|
|
|
|
$note_private = $object->getDefaultCreateValueFor('note_private');
|
|
$note_public = $object->getDefaultCreateValueFor('note_public');
|
|
|
|
print '<form name="crea_reception" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
|
|
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
|
print '<input type="hidden" name="action" value="add">';
|
|
print '<input type="hidden" name="changecompany" value="0">'; // will be set to 1 by javascript so we know post is done after a company change
|
|
print '<input type="hidden" name="originid" value="' . $id . '">';
|
|
print '<input type="hidden" name="backtopage" value="' . $backtopage . '">';
|
|
|
|
print dol_get_fiche_head([]);
|
|
|
|
print '<table class="border centpercent">';
|
|
|
|
|
|
// Thirdparty
|
|
print '<tr>';
|
|
print '<td class="fieldrequired">' . $langs->trans('ThirdParty') . '</td>';
|
|
if ($socid > 0) {
|
|
print '<td>';
|
|
print $soc->getNomUrl(1);
|
|
print '<input type="hidden" name="socid" value="' . $soc->id . '">';
|
|
print '</td>';
|
|
} else {
|
|
print '<td class="valuefieldcreate">';
|
|
print img_picto('', 'company', 'class="pictofixedwidth"').$form->select_company('', 'socid', '', 'SelectThirdParty', 1, 0, array(), 0, 'minwidth175 maxwidth500 widthcentpercentminusxx');
|
|
// reload page to retrieve customer information
|
|
if (!getDolGlobalString('RELOAD_PAGE_ON_CUSTOMER_CHANGE_DISABLED')) {
|
|
print '<script>
|
|
$(document).ready(function() {
|
|
$("#socid").change(function() {
|
|
console.log("We have changed the company - Reload page");
|
|
var socid = $(this).val();
|
|
// reload page
|
|
$("input[name=action]").val("create");
|
|
$("input[name=changecompany]").val("1");
|
|
$("form[name=crea_reception]").submit();
|
|
});
|
|
});
|
|
</script>';
|
|
}
|
|
print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'"><span class="fa fa-plus-circle valignmiddle paddingleft" title="'.$langs->trans("AddThirdParty").'"></span></a>';
|
|
print '</td>';
|
|
}
|
|
print '</tr>'."\n";
|
|
|
|
// Project
|
|
if (isModEnabled('project') && is_object($formproject)) {
|
|
$projectid = GETPOSTINT('projectid');
|
|
if (empty($projectid) && !empty($object->fk_project)) {
|
|
$projectid = (int) $object->fk_project;
|
|
}
|
|
$langs->load("projects");
|
|
print '<tr>';
|
|
print '<td>' . $langs->trans("Project") . '</td><td colspan="2">';
|
|
print img_picto('', 'project', 'class="pictofixedwidth"');
|
|
print $formproject->select_projects($soc->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 1, 0, 'widthcentpercentminusxx');
|
|
print ' <a class="paddingleft" href="' . DOL_URL_ROOT . '/projet/card.php?socid=' . $soc->id . '&action=create&status=1&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?action=create&socid=' . $soc->id) . '"><span class="fa fa-plus-circle valignmiddle"></span></a>';
|
|
print '</td>';
|
|
print '</tr>';
|
|
}
|
|
|
|
// Reception Date
|
|
print '<tr><td>'.$langs->trans("DateReception").'</td>';
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'action', 'class="pictofixedwidth"');
|
|
$date_reception = ($date_reception ? $date_reception : $object->date_reception); // $date_reception comes from GETPOST
|
|
print $form->selectDate($date_reception ? $date_reception : -1, 'date_reception', 1, 1, 1);
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
|
|
// Date delivery planned
|
|
print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'action', 'class="pictofixedwidth"');
|
|
$date_delivery = ($date_delivery ? $date_delivery : $object->delivery_date); // $date_delivery comes from GETPOST
|
|
print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
|
|
// Weight
|
|
print '<tr><td>';
|
|
print $langs->trans("Weight");
|
|
print '</td><td colspan="3">';
|
|
print img_picto('', 'fa-balance-scale', 'class="pictofixedwidth"');
|
|
print '<input name="weight" size="4" value="'.GETPOST('weight').'"> ';
|
|
$text = $formproduct->selectMeasuringUnits("weight_units", "weight", (string) GETPOSTINT('weight_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Dim
|
|
print '<tr><td>';
|
|
print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
|
|
print ' </td><td colspan="3">';
|
|
print img_picto('', 'fa-ruler', 'class="pictofixedwidth"');
|
|
print '<input name="sizeW" size="4" value="'.GETPOST('sizeW').'">';
|
|
print ' x <input name="sizeH" size="4" value="'.GETPOST('sizeH').'">';
|
|
print ' x <input name="sizeS" size="4" value="'.GETPOST('sizeS').'">';
|
|
print ' ';
|
|
$text = $formproduct->selectMeasuringUnits("size_units", "size", (string) GETPOSTINT('size_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Delivery method
|
|
print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
|
|
print '<td colspan="3">';
|
|
$recept->fetch_delivery_methods();
|
|
print $form->selectarray("shipping_method_id", $recept->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1);
|
|
if ($user->admin) {
|
|
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
|
|
}
|
|
print "</td></tr>\n";
|
|
|
|
// Tracking number
|
|
print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'barcode', 'class="pictofixedwidth"');
|
|
print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
|
|
print "</td></tr>\n";
|
|
|
|
// Here $object can be of an object Reception
|
|
$extrafields->fetch_name_optionals_label($object->table_element);
|
|
if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
|
|
if ($object->fetch_optionals() > 0) {
|
|
$recept->array_options = array_merge($recept->array_options, $object->array_options);
|
|
}
|
|
print $recept->showOptionals($extrafields, 'create', $parameters);
|
|
}
|
|
|
|
// Incoterms
|
|
if (isModEnabled('incoterm')) {
|
|
print '<tr>';
|
|
print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $object->label_incoterms, 1).'</label></td>';
|
|
print '<td colspan="3" class="maxwidthonsmartphone">';
|
|
print img_picto('', 'incoterm', 'class="pictofixedwidth"');
|
|
print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''));
|
|
print '</td></tr>';
|
|
}
|
|
|
|
// Template to use by default
|
|
$list = ModelePdfReception::liste_modeles($db);
|
|
if (is_countable($list) && count($list) > 0) {
|
|
print '<tr><td>'.$langs->trans('Model').'</td>';
|
|
print '<td colspan="2">';
|
|
print img_picto('', 'pdf', 'class="pictofixedwidth"');
|
|
include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
|
|
print $form->selectarray('model', $list, getDolGlobalString('RECEPTION_ADDON_PDF'), 0, 0, 0, '', 0, 0, 0, '', 'maxwidth200 widthcentpercentminusx', 1);
|
|
print "</td></tr>";
|
|
}
|
|
|
|
// Note Public
|
|
$htmltext = '';
|
|
print '<tr>';
|
|
print '<td class="tdtop">';
|
|
print $form->textwithpicto($langs->trans('NotePublic'), $htmltext);
|
|
print '</td>';
|
|
print '<td valign="top" colspan="2">';
|
|
$doleditor = new DolEditor('note_public', (string) $note_public, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
|
|
print $doleditor->Create(1);
|
|
|
|
// Note Private
|
|
if (!$user->socid) {
|
|
print '<tr>';
|
|
print '<td class="tdtop">';
|
|
print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext);
|
|
print '</td>';
|
|
print '<td valign="top" colspan="2">';
|
|
$doleditor = new DolEditor('note_private', (string) $note_private, '', 80, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
|
|
print $doleditor->Create(1);
|
|
print "</td></tr>";
|
|
}
|
|
|
|
print "</table>\n";
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
print $form->buttonsSaveCancel("CreateDraft");
|
|
|
|
print "</form>\n";
|
|
} elseif ($origin) {
|
|
if ($origin == 'supplierorder') {
|
|
$classname = 'CommandeFournisseur';
|
|
} else {
|
|
$classname = ucfirst($origin);
|
|
}
|
|
|
|
$objectsrc = new $classname($db);
|
|
if ($objectsrc->fetch($origin_id)) { // This include the fetch_lines
|
|
$soc = new Societe($db);
|
|
$soc->fetch($objectsrc->socid);
|
|
|
|
$author = new User($db);
|
|
$author->fetch($objectsrc->user_author_id);
|
|
|
|
if (isModEnabled('stock')) {
|
|
$entrepot = new Entrepot($db);
|
|
}
|
|
|
|
print '<form action="'.$_SERVER["PHP_SELF"].'" method="post">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="add">';
|
|
print '<input type="hidden" name="origin" value="'.$origin.'">';
|
|
print '<input type="hidden" name="origin_id" value="'.$objectsrc->id.'">';
|
|
print '<input type="hidden" name="backtopageforcancel" value="'.$backtopageforcancel.'">';
|
|
print '<input type="hidden" name="backtopage" value="'.$backtopage.'">';
|
|
if (GETPOSTINT('entrepot_id')) {
|
|
print '<input type="hidden" name="entrepot_id" value="'.GETPOSTINT('entrepot_id').'">';
|
|
}
|
|
|
|
print dol_get_fiche_head();
|
|
|
|
print '<table class="border centpercent">';
|
|
|
|
// Ref
|
|
print '<tr><td class="titlefieldcreate fieldrequired">';
|
|
if ($origin == 'supplierorder' && isModEnabled("supplier_order")) {
|
|
print $langs->trans("RefOrder").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/fourn/commande/card.php?id='.$objectsrc->id.'">'.img_object($langs->trans("ShowOrder"), 'order').' '.$objectsrc->ref;
|
|
}
|
|
if ($origin == 'propal' && isModEnabled("propal")) {
|
|
print $langs->trans("RefProposal").'</td><td colspan="3"><a href="'.DOL_URL_ROOT.'/comm/card.php?id='.$objectsrc->id.'">'.img_object($langs->trans("ShowProposal"), 'propal').' '.$objectsrc->ref;
|
|
}
|
|
print '</a></td>';
|
|
print "</tr>\n";
|
|
|
|
// Ref client
|
|
print '<tr><td>';
|
|
if ($origin == 'supplier_order') {
|
|
print $langs->trans('SupplierOrder');
|
|
} else {
|
|
print $langs->trans('RefSupplier');
|
|
}
|
|
print '</td><td colspan="3">';
|
|
print '<input type="text" name="ref_supplier" value="'.$objectsrc->ref_supplier.'" />';
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Thirdparty provider
|
|
print '<tr><td class="titlefieldcreate fieldrequired">'.$langs->trans('Company').'</td>';
|
|
print '<td colspan="3">'.$soc->getNomUrl(1).'</td>';
|
|
print '</tr>';
|
|
|
|
// Project
|
|
if (isModEnabled('project') && $formproject !== null) {
|
|
$projectid = GETPOSTINT('projectid') ? GETPOSTINT('projectid') : 0;
|
|
if (empty($projectid) && !empty($objectsrc->fk_project)) {
|
|
$projectid = $objectsrc->fk_project;
|
|
}
|
|
if ($origin == 'project') {
|
|
$projectid = ($origin_id ? $origin_id : 0);
|
|
}
|
|
|
|
$langs->load("projects");
|
|
print '<tr>';
|
|
print '<td>'.$langs->trans("Project").'</td><td colspan="2">';
|
|
print img_picto('', 'project', 'class="paddingright"');
|
|
print $formproject->select_projects((!getDolGlobalString('PROJECT_CAN_ALWAYS_LINK_TO_ALL_SUPPLIERS') ? $soc->id : -1), (string) $projectid, 'projectid', 0, 0, 1, 0, 1, 0, 0, '', 1, 0, 'maxwidth500');
|
|
print ' <a href="'.DOL_URL_ROOT.'/projet/card.php?socid='.$soc->id.'&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id).'"><span class="fa fa-plus-circle valignmiddle" title="'.$langs->trans("AddProject").'"></span></a>';
|
|
print '</td>';
|
|
print '</tr>';
|
|
}
|
|
|
|
// Reception Date
|
|
print '<tr><td>'.$langs->trans("DateReception").'</td>';
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'action', 'class="pictofixedwidth"');
|
|
$date_reception = ($date_reception ? $date_reception : $object->date_reception); // $date_reception comes from GETPOST
|
|
print $form->selectDate($date_reception ? $date_reception : -1, 'date_reception', 1, 1, 1);
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
|
|
// Date delivery planned
|
|
print '<tr><td>'.$langs->trans("DateDeliveryPlanned").'</td>';
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'action', 'class="pictofixedwidth"');
|
|
$date_delivery = ($date_delivery ? $date_delivery : $objectsrc->delivery_date); // $date_delivery comes from GETPOST
|
|
print $form->selectDate($date_delivery ? $date_delivery : -1, 'date_delivery', 1, 1, 1);
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
|
|
// Note Public
|
|
print '<tr><td>'.$langs->trans("NotePublic").'</td>';
|
|
print '<td colspan="3">';
|
|
$doleditor = new DolEditor('note_public', $objectsrc->note_public, '', 60, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PUBLIC') ? 0 : 1, ROWS_3, '90%');
|
|
print $doleditor->Create(1);
|
|
print "</td></tr>";
|
|
|
|
// Note Private
|
|
if ($objectsrc->note_private && !$user->socid) {
|
|
print '<tr><td>'.$langs->trans("NotePrivate").'</td>';
|
|
print '<td colspan="3">';
|
|
$doleditor = new DolEditor('note_private', $objectsrc->note_private, '', 60, 'dolibarr_notes', 'In', false, false, !getDolGlobalString('FCKEDITOR_ENABLE_NOTE_PRIVATE') ? 0 : 1, ROWS_3, '90%');
|
|
print $doleditor->Create(1);
|
|
print "</td></tr>";
|
|
}
|
|
|
|
// Weight
|
|
print '<tr><td>';
|
|
print $langs->trans("Weight");
|
|
print '</td><td colspan="3"><input name="weight" size="4" value="'.GETPOST('weight').'"> ';
|
|
$text = $formproduct->selectMeasuringUnits("weight_units", "weight", (string) GETPOSTINT('weight_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
// Dim
|
|
print '<tr><td>';
|
|
print $langs->trans("Width").' x '.$langs->trans("Height").' x '.$langs->trans("Depth");
|
|
print ' </td><td colspan="3"><input name="trueWidth" size="4" value="'.GETPOST('trueWidth').'">';
|
|
print ' x <input name="trueHeight" size="4" value="'.GETPOST('trueHeight').'">';
|
|
print ' x <input name="trueDepth" size="4" value="'.GETPOST('trueDepth').'">';
|
|
print ' ';
|
|
$text = $formproduct->selectMeasuringUnits("size_units", "size", (string) GETPOSTINT('size_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Delivery method
|
|
print "<tr><td>".$langs->trans("ReceptionMethod")."</td>";
|
|
print '<td colspan="3">';
|
|
$recept->fetch_delivery_methods();
|
|
print $form->selectarray("shipping_method_id", $recept->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1);
|
|
if ($user->admin) {
|
|
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
|
|
}
|
|
print "</td></tr>\n";
|
|
|
|
// Tracking number
|
|
print "<tr><td>".$langs->trans("TrackingNumber")."</td>";
|
|
print '<td colspan="3">';
|
|
print '<input name="tracking_number" size="20" value="'.GETPOST('tracking_number', 'alpha').'">';
|
|
print "</td></tr>\n";
|
|
|
|
// Other attributes
|
|
$parameters = array('objectsrc' => $objectsrc, 'colspan' => ' colspan="3"', 'cols' => '3', 'socid' => $socid);
|
|
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $recept, $action); // Note that $action and $objectsrc may have been modified by hook
|
|
print $hookmanager->resPrint;
|
|
|
|
// Here $object can be of an object Reception
|
|
$extrafields->fetch_name_optionals_label($object->table_element);
|
|
if (empty($reshook) && !empty($extrafields->attributes[$object->table_element]['label'])) {
|
|
// copy from order
|
|
if ($objectsrc->fetch_optionals() > 0) {
|
|
$recept->array_options = array_merge($recept->array_options, $objectsrc->array_options);
|
|
}
|
|
print $recept->showOptionals($extrafields, 'create', $parameters);
|
|
}
|
|
|
|
// Incoterms
|
|
if (isModEnabled('incoterm')) {
|
|
print '<tr>';
|
|
print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->label_incoterms, 1).'</label></td>';
|
|
print '<td colspan="3" class="maxwidthonsmartphone">';
|
|
print $form->select_incoterms((!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : ''), (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : ''));
|
|
print '</td></tr>';
|
|
}
|
|
|
|
// Document model
|
|
include_once DOL_DOCUMENT_ROOT.'/core/modules/reception/modules_reception.php';
|
|
$list = ModelePdfReception::liste_modeles($db);
|
|
|
|
if (is_array($list) && count($list) > 1) {
|
|
print "<tr><td>".$langs->trans("DefaultModel")."</td>";
|
|
print '<td colspan="3">';
|
|
print $form->selectarray('model', $list, getDolGlobalString('RECEPTION_ADDON_PDF'));
|
|
print "</td></tr>\n";
|
|
}
|
|
|
|
print "</table>";
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
// Number of lines show on the reception card
|
|
$numAsked = 0;
|
|
|
|
/**
|
|
* @var array<string,int> $suffix2numAsked map HTTP query parameter suffixes (like '1_0') to line indices so that
|
|
* extrafields from HTTP query can be assigned to the correct dispatch line
|
|
*/
|
|
$suffix2numAsked = array();
|
|
$dispatchLines = array();
|
|
|
|
foreach ($_POST as $key => $value) {
|
|
// If create form is coming from the button "Create Reception" of previous page
|
|
|
|
// without batch module enabled or product with no lot/serial
|
|
$reg = array();
|
|
if (preg_match('/^product_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
|
|
$numAsked++;
|
|
$paramSuffix = $reg[1] . '_' . $reg[2];
|
|
$suffix2numAsked[$paramSuffix] = $numAsked;
|
|
|
|
// $numline=$reg[2] + 1; // line of product
|
|
$numline = $numAsked;
|
|
|
|
$prod = "product_" . $paramSuffix;
|
|
$qty = "qty_" . $paramSuffix;
|
|
$ent = "entrepot_" . $paramSuffix;
|
|
$pu = "pu_" . $paramSuffix; // This is unit price including discount
|
|
$fk_commandefourndet = "fk_commandefourndet_" . $paramSuffix;
|
|
$dispatchLines[$numAsked] = array('paramSuffix' => $paramSuffix, 'prod' => GETPOSTINT($prod), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOSTINT($ent), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST('comment'), 'fk_commandefourndet' => GETPOSTINT($fk_commandefourndet));
|
|
}
|
|
|
|
// with batch module enabled and product with lot/serial
|
|
if (preg_match('/^product_batch_([0-9]+)_([0-9]+)$/i', $key, $reg)) {
|
|
$numAsked++;
|
|
$paramSuffix = $reg[1] . '_' . $reg[2];
|
|
$suffix2numAsked[$paramSuffix] = $numAsked;
|
|
|
|
// eat-by date dispatch
|
|
// $numline=$reg[2] + 1; // line of product
|
|
$numline = $numAsked;
|
|
|
|
$prod = 'product_batch_' . $paramSuffix;
|
|
$qty = 'qty_' . $paramSuffix;
|
|
$ent = 'entrepot_' . $paramSuffix;
|
|
$pu = 'pu_' . $paramSuffix;
|
|
$lot = 'lot_number_' . $paramSuffix;
|
|
$dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo_'.$paramSuffix.'month'), GETPOSTINT('dluo_'.$paramSuffix.'day'), GETPOSTINT('dluo_'.$paramSuffix.'year'));
|
|
$dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc_'.$paramSuffix.'month'), GETPOSTINT('dlc_'.$paramSuffix.'day'), GETPOSTINT('dlc_'.$paramSuffix.'year'));
|
|
$fk_commandefourndet = 'fk_commandefourndet_'.$paramSuffix;
|
|
$dispatchLines[$numAsked] = array('paramSuffix' => $paramSuffix, 'prod' => GETPOSTINT($prod), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOSTINT($ent), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST('comment'), 'fk_commandefourndet' => GETPOSTINT($fk_commandefourndet), 'DLC' => $dDLC, 'DLUO' => $dDLUO, 'lot' => GETPOST($lot));
|
|
}
|
|
|
|
// If create form is coming from same page, it means that post was sent but an error occurred
|
|
if (preg_match('/^productl([0-9]+)$/i', $key, $reg)) {
|
|
$numAsked++;
|
|
$paramSuffix = $reg[1];
|
|
$suffix2numAsked[$paramSuffix] = $numAsked;
|
|
|
|
// eat-by date dispatch
|
|
// $numline=$reg[2] + 1; // line of product
|
|
$numline = $numAsked;
|
|
|
|
$prod = 'productid'.$paramSuffix;
|
|
$comment = 'comment'.$paramSuffix;
|
|
$qty = 'qtyl'.$paramSuffix;
|
|
$ent = 'entl'.$paramSuffix;
|
|
$pu = 'pul'.$paramSuffix;
|
|
$lot = 'batch'.$paramSuffix;
|
|
$dDLUO = dol_mktime(12, 0, 0, GETPOSTINT('dluo'.$paramSuffix.'month'), GETPOSTINT('dluo'.$paramSuffix.'day'), GETPOSTINT('dluo'.$paramSuffix.'year'));
|
|
$dDLC = dol_mktime(12, 0, 0, GETPOSTINT('dlc'.$paramSuffix.'month'), GETPOSTINT('dlc'.$paramSuffix.'day'), GETPOSTINT('dlc'.$paramSuffix.'year'));
|
|
$fk_commandefourndet = 'fk_commandefournisseurdet'.$paramSuffix;
|
|
$dispatchLines[$numAsked] = array('prod' => GETPOSTINT($prod), 'qty' => price2num(GETPOST($qty), 'MS'), 'ent' => GETPOSTINT($ent), 'pu' => price2num(GETPOST($pu), 'MU'), 'comment' => GETPOST($comment), 'fk_commandefourndet' => GETPOSTINT($fk_commandefourndet), 'DLC' => $dDLC, 'DLUO' => $dDLUO, 'lot' => GETPOSTINT($lot));
|
|
}
|
|
}
|
|
|
|
// If extrafield values are passed in the HTTP query, assign them to the correct dispatch line
|
|
// Note that if an extrafield with the same name exists in the origin supplier order line, the value
|
|
// from the HTTP query will be ignored
|
|
foreach ($suffix2numAsked as $suffix => $n) {
|
|
$dispatchLines[$n]['array_options'] = $extrafields->getOptionalsFromPost('receptiondet_batch', '_' . $suffix, '');
|
|
}
|
|
|
|
$reshook = $hookmanager->executeHooks('dataProcessing', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} elseif (empty($reshook)) {
|
|
// Only merge if resArray is a valid, non-empty array
|
|
if (is_array($hookmanager->resArray) && !empty($hookmanager->resArray)) {
|
|
// Check if the merge would overwrite valid data with NULL
|
|
$tempMerged = array_merge($dispatchLines, $hookmanager->resArray);
|
|
|
|
// Sanity check: ensure our existing keys are still valid arrays
|
|
$corrupted = false;
|
|
foreach ($dispatchLines as $idx => $val) {
|
|
if (!is_array($tempMerged[$idx]) || !isset($tempMerged[$idx]['fk_commandefourndet'])) {
|
|
$corrupted = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!$corrupted) {
|
|
$dispatchLines = $tempMerged;
|
|
} else {
|
|
// If merge corrupted data, ignore the hook result and keep original
|
|
error_log("WARNING: Hook dataProcessing returned invalid data, ignoring merge.");
|
|
}
|
|
}
|
|
} elseif ($reshook > 0) {
|
|
// $resArray starts from [0], we need $dispatchLines to start from [1], so we shift it
|
|
$dispatchLines = $hookmanager->resArray;
|
|
array_unshift($dispatchLines, null);
|
|
unset($dispatchLines[0]);
|
|
$numAsked = count($dispatchLines);
|
|
}
|
|
|
|
print '<script type="text/javascript">
|
|
jQuery(document).ready(function() {
|
|
jQuery("#autofill").click(function(event) {
|
|
event.preventDefault();';
|
|
$i = 1;
|
|
while ($i <= $numAsked) {
|
|
print 'jQuery("#qtyl'.$i.'").val(jQuery("#qtyasked'.$i.'").val() - jQuery("#qtydelivered'.$i.'").val());'."\n";
|
|
$i++;
|
|
}
|
|
print '});
|
|
jQuery("#autoreset").click(function(event) {
|
|
event.preventDefault();';
|
|
$i = 1;
|
|
while ($i <= $numAsked) {
|
|
print 'jQuery("#qtyl'.$i.'").val(0);'."\n";
|
|
$i++;
|
|
}
|
|
print '});
|
|
});
|
|
</script>';
|
|
|
|
print '<br>';
|
|
|
|
print '<table class="noborder centpercent">';
|
|
|
|
// Load receptions already done for same order
|
|
$objectsrc->loadReceptions();
|
|
|
|
if ($numAsked) {
|
|
print '<tr class="liste_titre">';
|
|
print '<td>'.$langs->trans("Description").'</td>';
|
|
print '<td>'.$langs->trans("Comment").'</td>';
|
|
print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
|
|
print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
|
|
print '<td class="center">'.$langs->trans("QtyToReceive");
|
|
if (getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalInt('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
|
|
print '<td>'.$langs->trans("BuyingPrice").'</td>';
|
|
}
|
|
if (!isModEnabled('productbatch')) {
|
|
print ' <br><center><a href="#" id="autofill"><span class="fas fa-fill pictofixedwidth" style=""></span> '.$langs->trans("Fill").'</a>';
|
|
print ' <a href="#" id="autoreset"><span class="fas fa-eraser pictofixedwidth" style=""></span>'.$langs->trans("Reset").'</a></center><br>';
|
|
}
|
|
print '</td>';
|
|
if (isModEnabled('stock')) {
|
|
print '<td class="left">'.$langs->trans("Warehouse").' ('.$langs->trans("Stock").')</td>';
|
|
}
|
|
if (isModEnabled('productbatch')) {
|
|
print '<td class="left">'.$langs->trans("batch_number").'</td>';
|
|
if (!getDolGlobalInt('PRODUCT_DISABLE_SELLBY')) {
|
|
print '<td class="left">'.$langs->trans("SellByDate").'</td>';
|
|
}
|
|
if (!getDolGlobalInt('PRODUCT_DISABLE_EATBY')) {
|
|
print '<td class="left">'.$langs->trans("EatByDate").'</td>';
|
|
}
|
|
}
|
|
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
print "</tr>\n";
|
|
}
|
|
|
|
// $objectsrc->lines contains the line of the purchase order
|
|
// $dispatchLines is an array with dispatching detail (with product, qty, warehouse and fk_commandefourndet). One purchase order line may have n of this dispatch lines.
|
|
|
|
$arrayofpurchaselinealreadyoutput = array();
|
|
|
|
// $_POST contains fk_commandefourndet_X_Y where Y is num of product line and X is number of split lines
|
|
$indiceAsked = 1;
|
|
while ($indiceAsked <= $numAsked) { // Loop on $dispatchLines. Warning: $dispatchLines must be sorted by fk_commandefourndet (it is a regroupment key on output)
|
|
$product = new Product($db);
|
|
$line = new CommandeFournisseurLigne($db); // By default
|
|
|
|
// We search the purchase order line that is linked to the dispatchLines
|
|
foreach ($objectsrc->lines as $supplierLine) {
|
|
if ($dispatchLines[$indiceAsked]['fk_commandefourndet'] == $supplierLine->id) {
|
|
$line = $supplierLine;
|
|
break;
|
|
}
|
|
}
|
|
|
|
// Now $line can be CommandeFournisseurLigne but could be other type of line.
|
|
|
|
// Show product and description
|
|
$type = $line->product_type ? $line->product_type : $line->fk_product_type;
|
|
// Try to enhance type detection using date_start and date_end for free lines where type was not saved.
|
|
if (!empty($line->date_start)) {
|
|
$type = 1;
|
|
}
|
|
if (!empty($line->date_end)) {
|
|
$type = 1;
|
|
}
|
|
|
|
print '<!-- line fk_commandefourndet='.$line->id.' for product='.$line->fk_product.' -->'."\n";
|
|
print '<tr class="oddeven">'."\n";
|
|
|
|
// Product label
|
|
if ($line->fk_product > 0) { // If predefined product
|
|
$product->fetch($line->fk_product);
|
|
$product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
|
|
//var_dump($product->stock_warehouse[1]);
|
|
//var_dump($dispatchLines[$indiceAsked]);
|
|
|
|
print '<td>';
|
|
print '<a name="'.$line->id.'"></a>'; // Anchor to return to the line
|
|
|
|
print '<input type="hidden" name="productl'.$indiceAsked.'" value="'.$line->fk_product.'">';
|
|
|
|
if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
|
|
print '<input type="hidden" name="productid'.$indiceAsked.'" value="'.$line->fk_product.'">';
|
|
|
|
// Show product and description
|
|
$product_static = $product;
|
|
|
|
$text = $product_static->getNomUrl(1);
|
|
$text .= ' - '.(!empty($line->label) ? $line->label : $line->product_label);
|
|
$description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($line->desc));
|
|
print $form->textwithtooltip($text, $description, 3, 0, '', (string) $i);
|
|
|
|
// Show range
|
|
print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
|
|
|
|
// Add description in form
|
|
if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
|
|
print ($line->desc && $line->desc != $line->product_label) ? '<br>'.dol_htmlentitiesbr($line->desc) : '';
|
|
}
|
|
}
|
|
print '</td>';
|
|
} else {
|
|
print "<td>";
|
|
if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
|
|
if ($type == 1) {
|
|
$text = img_object($langs->trans('Service'), 'service');
|
|
} else {
|
|
$text = img_object($langs->trans('Product'), 'product');
|
|
}
|
|
|
|
if (!empty($line->label)) {
|
|
$text .= ' <strong>'.$line->label.'</strong>';
|
|
print $form->textwithtooltip($text, $line->desc, 3, 0, '', (string) $i);
|
|
} else {
|
|
print $text.' '.nl2br($line->desc);
|
|
}
|
|
|
|
// Show range
|
|
print_date_range($db->jdate($line->date_start), $db->jdate($line->date_end));
|
|
}
|
|
print "</td>\n";
|
|
}
|
|
|
|
// Comment
|
|
//$defaultcomment = 'Line create from order line id '.$line->id;
|
|
$defaultcomment = $dispatchLines[$indiceAsked]['comment'];
|
|
print '<td>';
|
|
print '<input type="text" class="maxwidth100" name="comment'.$indiceAsked.'" value="'.$defaultcomment.'">';
|
|
print '</td>';
|
|
|
|
// Qty in source purchase order line
|
|
print '<td class="center">';
|
|
if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
|
|
print $line->qty;
|
|
}
|
|
print '<input type="hidden" name="fk_commandefournisseurdet'.$indiceAsked.'" value="'.$line->id.'">';
|
|
print '<input type="hidden" name="pul'.$indiceAsked.'" value="'.$line->subprice.'">';
|
|
print '<input name="qtyasked'.$indiceAsked.'" id="qtyasked'.$indiceAsked.'" type="hidden" value="'.$line->qty.'">';
|
|
print '</td>';
|
|
$qtyProdCom = $line->qty;
|
|
|
|
// Qty already received
|
|
print '<td class="center">';
|
|
$quantityDelivered = isset($objectsrc->receptions[$line->id]) ? $objectsrc->receptions[$line->id] : 0;
|
|
if (! array_key_exists($line->id, $arrayofpurchaselinealreadyoutput)) { // Add test to avoid to show qty twice
|
|
print $quantityDelivered;
|
|
}
|
|
print '<input name="qtydelivered'.$indiceAsked.'" id="qtydelivered'.$indiceAsked.'" type="hidden" value="'.$quantityDelivered.'">';
|
|
print '</td>';
|
|
|
|
|
|
if ($line->product_type == 1 && !getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
|
|
$quantityToBeDelivered = 0;
|
|
} else {
|
|
$quantityToBeDelivered = $dispatchLines[$indiceAsked]['qty'];
|
|
}
|
|
$warehouse_id = $dispatchLines[$indiceAsked]['ent'];
|
|
|
|
|
|
$warehouseObject = null;
|
|
if (isModEnabled('stock')) {
|
|
// If warehouse was already selected or if product is not a predefined, we go into this part with no multiwarehouse selection
|
|
print '<!-- Case warehouse already known or product not a predefined product -->';
|
|
if (array_key_exists($dispatchLines[$indiceAsked]['ent'], $product->stock_warehouse)) {
|
|
$stock = +$product->stock_warehouse[$dispatchLines[$indiceAsked]['ent']]->real; // Convert to number
|
|
}
|
|
$deliverableQty = $dispatchLines[$indiceAsked]['qty'];
|
|
$cost_price = $dispatchLines[$indiceAsked]['pu'];
|
|
|
|
// Quantity to send
|
|
print '<td class="center">';
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
|
|
if (GETPOSTINT('qtyl'.$indiceAsked)) {
|
|
$defaultqty = GETPOSTINT('qtyl'.$indiceAsked);
|
|
}
|
|
print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
|
|
print '<input class="right" name="qtyl'.$indiceAsked.'" id="qtyl'.$indiceAsked.'" type="text" size="4" value="'.$deliverableQty.'">';
|
|
} else {
|
|
print $langs->trans("NA");
|
|
}
|
|
print '</td>';
|
|
|
|
if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION') || getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
|
|
print '<td>';
|
|
print '<input class="width75 right" name="cost_price'.$indiceAsked.'" id="cost_price'.$indiceAsked.'" value="'.price($cost_price).'">';
|
|
print '</td>';
|
|
}
|
|
|
|
// Stock
|
|
if (isModEnabled('stock')) {
|
|
print '<td class="left">';
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) { // Type of product need stock change ?
|
|
// Show warehouse combo list
|
|
$ent = "entl".$indiceAsked;
|
|
$idl = "idl".$indiceAsked;
|
|
$tmpentrepot_id = is_numeric(GETPOST($ent)) ? GETPOSTINT($ent) : $warehouse_id;
|
|
if ($line->fk_product > 0) {
|
|
print '<!-- Show warehouse selection -->';
|
|
print $formproduct->selectWarehouses($tmpentrepot_id, 'entl'.$indiceAsked, '', 0, 0, $line->fk_product, '', 1);
|
|
}
|
|
} else {
|
|
print $langs->trans("Service");
|
|
}
|
|
print '</td>';
|
|
}
|
|
|
|
if (isModEnabled('productbatch')) {
|
|
if (!empty($product->status_batch)) {
|
|
print '<td><input name="batch'.$indiceAsked.'" value="'.$dispatchLines[$indiceAsked]['lot'].'"></td>';
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
|
|
print '<td class="nowraponall">';
|
|
print $form->selectDate($dispatchLines[$indiceAsked]['DLC'], 'dlc'.$indiceAsked, 0, 0, 1, "");
|
|
print '</td>';
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
|
|
print '<td class="nowraponall">';
|
|
print $form->selectDate($dispatchLines[$indiceAsked]['DLUO'], 'dluo'.$indiceAsked, 0, 0, 1, "");
|
|
print '</td>';
|
|
}
|
|
} else {
|
|
print '<td colspan="3"></td>';
|
|
}
|
|
}
|
|
|
|
$parameters = array();
|
|
$parameters['dispatchLine'] = $dispatchLines[$indiceAsked];
|
|
$parameters['indiceAsked'] = $indiceAsked;
|
|
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
}
|
|
|
|
$arrayofpurchaselinealreadyoutput[$line->id] = $line->id;
|
|
|
|
print "</tr>\n";
|
|
|
|
// Display lines for extrafields of the Reception line
|
|
// $line is a 'CommandeFournisseurLigne', $dispatchLines contains values of Reception lines so properties of CommandeFournisseurDispatch
|
|
if (!empty($extrafields)) {
|
|
$colspan = 5;
|
|
if (isModEnabled('productbatch')) {
|
|
$colspan += 2;
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
|
|
$colspan += 1;
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
|
|
$colspan += 1;
|
|
}
|
|
}
|
|
$recLine = new CommandeFournisseurDispatch($db);
|
|
|
|
$srcLine = new CommandeFournisseurLigne($db);
|
|
$srcLine->id = $line->id;
|
|
$srcLine->fetch_optionals(); // fetch extrafields also available in orderline
|
|
|
|
if (empty($recLine->array_options) && !empty($dispatchLines[$indiceAsked]['array_options'])) {
|
|
$recLine->array_options = $dispatchLines[$indiceAsked]['array_options'];
|
|
}
|
|
$recLine->array_options = array_merge($recLine->array_options, $srcLine->array_options);
|
|
|
|
print $recLine->showOptionals($extrafields, 'edit', array('style' => 'class="oddeven"', 'colspan' => $colspan), (string) $indiceAsked, '', '1');
|
|
}
|
|
|
|
$indiceAsked++;
|
|
}
|
|
|
|
print "</table>";
|
|
|
|
print '<br>';
|
|
|
|
print $form->buttonsSaveCancel("Create");
|
|
|
|
print '</form>';
|
|
|
|
print '<br>';
|
|
} else {
|
|
dol_print_error($db);
|
|
}
|
|
}
|
|
} elseif ($object->id > 0) {
|
|
/* *************************************************************************** */
|
|
/* */
|
|
/* Edit and view mode */
|
|
/* */
|
|
/* *************************************************************************** */
|
|
$lines = $object->lines;
|
|
|
|
$num_prod = count($lines);
|
|
$indiceAsked = 0;
|
|
|
|
if ($object->id <= 0) {
|
|
print $langs->trans("NoRecordFound");
|
|
llxFooter();
|
|
exit;
|
|
}
|
|
|
|
$typeobject = '';
|
|
if (!empty($object->origin) && $object->origin_id > 0) {
|
|
$typeobject = $object->origin;
|
|
$origin = $object->origin;
|
|
$origin_id = $object->origin_id;
|
|
$object->fetch_origin(); // Load property $object->origin_object, $object->commande, $object->propal, ...
|
|
}
|
|
|
|
$soc = new Societe($db);
|
|
$soc->fetch($object->socid);
|
|
|
|
$res = $object->fetch_optionals();
|
|
|
|
$head = reception_prepare_head($object);
|
|
print dol_get_fiche_head($head, 'reception', $langs->trans("Reception"), -1, 'dollyrevert', 0, '', '', 0, '', 1);
|
|
|
|
$formconfirm = '';
|
|
|
|
// Confirm deletion
|
|
if ($action == 'delete') {
|
|
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('DeleteReception'), $langs->trans("ConfirmDeleteReception", $object->ref), 'confirm_delete', '', 0, 1);
|
|
}
|
|
|
|
// Confirmation validation
|
|
if ($action == 'valid') {
|
|
$objectref = substr($object->ref, 1, 4);
|
|
if ($objectref == 'PROV') {
|
|
$numref = $object->getNextNumRef($soc);
|
|
} else {
|
|
$numref = (string) $object->ref;
|
|
}
|
|
|
|
$text = $langs->trans("ConfirmValidateReception", $numref);
|
|
if (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION')) {
|
|
$text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementWillBeRecorded").'.';
|
|
} elseif (getDolGlobalString('STOCK_CALCULATE_ON_RECEPTION_CLOSE')) {
|
|
$text .= '<br>'.img_picto('', 'movement', 'class="pictofixedwidth"').$langs->trans("StockMovementNotYetRecorded").'.';
|
|
}
|
|
|
|
if (isModEnabled('notification')) {
|
|
require_once DOL_DOCUMENT_ROOT.'/core/class/notify.class.php';
|
|
$notify = new Notify($db);
|
|
$text .= '<br>';
|
|
$text .= $notify->confirmMessage('RECEPTION_VALIDATE', $object->socid, $object);
|
|
}
|
|
|
|
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateReception'), $text, 'confirm_valid', '', 0, 1, 250);
|
|
}
|
|
|
|
// Confirm cancellation
|
|
if ($action == 'annuler') {
|
|
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('CancelReception'), $langs->trans("ConfirmCancelReception", $object->ref), 'confirm_cancel', '', 0, 1);
|
|
}
|
|
|
|
if (!$formconfirm) {
|
|
$parameters = array('formConfirm' => $formconfirm);
|
|
$reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
|
if (empty($reshook)) {
|
|
$formconfirm .= $hookmanager->resPrint;
|
|
} elseif ($reshook > 0) {
|
|
$formconfirm = $hookmanager->resPrint;
|
|
}
|
|
}
|
|
|
|
// Print form confirm
|
|
print $formconfirm;
|
|
|
|
|
|
// Calculate totalWeight and totalVolume for all products
|
|
// by adding weight and volume of each product line.
|
|
$tmparray = $object->getTotalWeightVolume();
|
|
$totalWeight = $tmparray['weight'];
|
|
$totalVolume = $tmparray['volume'];
|
|
|
|
|
|
if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
|
|
$objectsrc = new Commande($db);
|
|
$objectsrc->fetch($object->origin_object->id);
|
|
}
|
|
if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
|
|
$objectsrc = new Propal($db);
|
|
$objectsrc->fetch($object->origin_object->id);
|
|
}
|
|
if (($typeobject == 'supplier_order' || $typeobject == 'CommandeFournisseur') && $object->origin_object->id && isModEnabled("supplier_order")) {
|
|
$objectsrc = new CommandeFournisseur($db);
|
|
$objectsrc->fetch($object->origin_object->id);
|
|
}
|
|
// Reception card
|
|
$linkback = '<a href="'.DOL_URL_ROOT.'/reception/list.php?restore_lastsearch_values=1'.(!empty($socid) ? '&socid='.$socid : '').'">'.$langs->trans("BackToList").'</a>';
|
|
$morehtmlref = '<div class="refidno">';
|
|
// Ref customer reception
|
|
|
|
$morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', 0, 1);
|
|
$morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $user->hasRight('reception', 'creer'), 'string', '', null, null, '', 1);
|
|
|
|
// Thirdparty
|
|
$morehtmlref .= '<br>'.$object->thirdparty->getNomUrl(1);
|
|
// Project
|
|
if ($origin && $origin_id > 0) {
|
|
if (isModEnabled('project')) {
|
|
$langs->load("projects");
|
|
$morehtmlref .= '<br>';
|
|
if (0) { // @phpstan-ignore-line Do not change on shipment
|
|
$morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
|
|
if ($action != 'classify') {
|
|
$morehtmlref .= '<a class="editfielda" href="'.$_SERVER['PHP_SELF'].'?action=classify&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->transnoentitiesnoconv('SetProject')).'</a> ';
|
|
}
|
|
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'].'?id='.$object->id, $objectsrc->socid, (string) $objectsrc->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
|
|
} else {
|
|
if (!empty($objectsrc) && !empty($objectsrc->fk_project)) {
|
|
$proj = new Project($db);
|
|
$proj->fetch($objectsrc->fk_project);
|
|
$morehtmlref .= $proj->getNomUrl(1);
|
|
if ($proj->title) {
|
|
$morehtmlref .= '<span class="opacitymedium"> - '.dol_escape_htmltag($proj->title).'</span>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} elseif (!$origin && getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
// Project
|
|
if (isModEnabled('project')) {
|
|
$langs->load("projects");
|
|
$morehtmlref .= '<br>';
|
|
if ($permissiontoadd) {
|
|
$morehtmlref .= img_picto($langs->trans("Project"), 'project', 'class="pictofixedwidth"');
|
|
if ($action != 'classify') {
|
|
$morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> ';
|
|
}
|
|
$morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, (string) $object->fk_project, ($action == 'classify' ? 'projectid' : 'none'), 0, 0, 0, 1, '', 'maxwidth300');
|
|
} else {
|
|
if (!empty($object->fk_project)) {
|
|
$proj = new Project($db);
|
|
$proj->fetch($object->fk_project);
|
|
$morehtmlref .= $proj->getNomUrl(1);
|
|
if ($proj->title) {
|
|
$morehtmlref .= '<span class="opacitymedium"> - ' . dol_escape_htmltag($proj->title) . '</span>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
$morehtmlref .= '</div>';
|
|
|
|
dol_banner_tab($object, 'ref', $linkback, 1, 'ref', 'ref', $morehtmlref);
|
|
|
|
|
|
print '<div class="fichecenter">';
|
|
print '<div class="fichehalfleft">';
|
|
print '<div class="underbanner clearboth"></div>';
|
|
|
|
print '<table class="border centpercent tableforfield">';
|
|
|
|
// Linked documents
|
|
if ($typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
|
|
print '<tr><td>';
|
|
print $langs->trans("RefOrder").'</td>';
|
|
print '<td colspan="3">';
|
|
print $objectsrc->getNomUrl(1, 'commande');
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
}
|
|
if ($typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
|
|
print '<tr><td>';
|
|
print $langs->trans("RefProposal").'</td>';
|
|
print '<td colspan="3">';
|
|
print $objectsrc->getNomUrl(1, 'reception');
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
}
|
|
if (($typeobject == 'supplier_order' || $typeobject == 'CommandeFournisseur') && $object->origin_object->id && isModEnabled("propal")) {
|
|
print '<tr><td>';
|
|
print $langs->trans("SupplierOrder").'</td>';
|
|
print '<td colspan="3">';
|
|
print $objectsrc->getNomUrl(1, 'reception');
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
}
|
|
|
|
// Date creation
|
|
print '<tr><td class="titlefield">'.$langs->trans("DateCreation").'</td>';
|
|
print '<td colspan="3">'.dol_print_date($object->date_creation, "dayhour", "tzuserrel")."</td>\n";
|
|
print '</tr>';
|
|
|
|
// Reception Date
|
|
print '<tr><td height="10">';
|
|
print '<table class="nobordernopadding centpercent"><tr><td>';
|
|
print $langs->trans('DateReception');
|
|
print '</td>';
|
|
if ($action != 'editdate_reception') {
|
|
print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editdate_reception&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->trans('SetReceptionDate'), 1) . '</a></td>';
|
|
}
|
|
print '</tr></table>';
|
|
print '</td><td>';
|
|
if ($action == 'editdate_reception') {
|
|
print '<form name="setdate_reception" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
|
|
print '<input type="hidden" name="token" value="' . newToken() . '">';
|
|
print '<input type="hidden" name="action" value="setdate_reception">';
|
|
print $form->selectDate($object->date_reception ? $object->date_reception : -1, 'recep_', 1, 1, 0, "setdate_reception", 1, 0);
|
|
print '<input type="submit" class="button button-edit smallpaddingimp" value="' . $langs->trans('Modify') . '">';
|
|
print '</form>';
|
|
} else {
|
|
print $object->date_reception ? dol_print_date($object->date_reception, 'dayhour') : ' ';
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Delivery date planned
|
|
print '<tr><td height="10">';
|
|
print '<table class="nobordernopadding" width="100%"><tr><td>';
|
|
print $langs->trans('DateDeliveryPlanned');
|
|
print '</td>';
|
|
|
|
if ($action != 'editdate_livraison' && $permissiontoadd) {
|
|
print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editdate_livraison&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetDeliveryDate'), 1).'</a></td>';
|
|
}
|
|
print '</tr></table>';
|
|
print '</td><td colspan="2">';
|
|
if ($action == 'editdate_livraison') {
|
|
print '<form name="setdate_livraison" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="setdate_livraison">';
|
|
print $form->selectDate($object->date_delivery ? $object->date_delivery : -1, 'liv_', 1, 1, 0, "setdate_livraison", 1, 0);
|
|
print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
|
|
print '</form>';
|
|
} else {
|
|
print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : ' ';
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Weight
|
|
print '<tr><td>';
|
|
print $form->editfieldkey("Weight", 'trueWeight', (string) $object->trueWeight, $object, $user->hasRight('reception', 'creer'));
|
|
print '</td><td colspan="3">';
|
|
|
|
if ($action == 'edittrueWeight') {
|
|
print '<form name="settrueweight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
|
|
print '<input name="action" value="settrueWeight" type="hidden">';
|
|
print '<input name="id" value="'.$object->id.'" type="hidden">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input id="trueWeight" name="trueWeight" value="'.$object->trueWeight.'" type="text">';
|
|
print $formproduct->selectMeasuringUnits("weight_units", "weight", (string) $object->weight_units, 0, 2);
|
|
print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
|
|
print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
|
|
print '</form>';
|
|
} else {
|
|
print $object->trueWeight;
|
|
print ($object->trueWeight && $object->weight_units != '') ? ' '.measuringUnitString(0, "weight", $object->weight_units) : '';
|
|
}
|
|
|
|
// Calculated
|
|
if ($totalWeight > 0) {
|
|
if (!empty($object->trueWeight)) {
|
|
print ' ('.$langs->trans("SumOfProductWeights").': ';
|
|
}
|
|
print showDimensionInBestUnit($totalWeight, 0, "weight", $langs, getDolGlobalInt('MAIN_WEIGHT_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_WEIGHT_DEFAULT_UNIT', 'no'));
|
|
if (!empty($object->trueWeight)) {
|
|
print ')';
|
|
}
|
|
}
|
|
print '</td></tr>';
|
|
|
|
// Width
|
|
print '<tr><td>'.$form->editfieldkey("Width", 'trueWidth', (string) $object->trueWidth, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
|
|
print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->hasRight('reception', 'creer'));
|
|
print ($object->trueWidth && $object->width_units != '') ? ' '.measuringUnitString(0, "size", $object->width_units) : '';
|
|
print '</td></tr>';
|
|
|
|
// Height
|
|
print '<tr><td>'.$form->editfieldkey("Height", 'trueHeight', (string) $object->trueHeight, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
|
|
if ($action == 'edittrueHeight') {
|
|
print '<form name="settrueHeight" action="'.$_SERVER["PHP_SELF"].'" method="post">';
|
|
print '<input name="action" value="settrueHeight" type="hidden">';
|
|
print '<input name="id" value="'.$object->id.'" type="hidden">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input id="trueHeight" name="trueHeight" value="'.$object->trueHeight.'" type="text">';
|
|
print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
|
|
print ' <input class="button" name="modify" value="'.$langs->trans("Modify").'" type="submit">';
|
|
print ' <input class="button button-cancel" name="cancel" value="'.$langs->trans("Cancel").'" type="submit">';
|
|
print '</form>';
|
|
} else {
|
|
print $object->trueHeight;
|
|
print ($object->trueHeight && $object->height_units != '') ? ' '.measuringUnitString(0, "size", $object->height_units) : '';
|
|
}
|
|
|
|
print '</td></tr>';
|
|
|
|
// Depth
|
|
print '<tr><td>'.$form->editfieldkey("Depth", 'trueDepth', (string) $object->trueDepth, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
|
|
print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->hasRight('reception', 'creer'));
|
|
print ($object->trueDepth && $object->depth_units != '') ? ' '.measuringUnitString(0, "size", $object->depth_units) : '';
|
|
print '</td></tr>';
|
|
|
|
// Volume
|
|
print '<tr><td>';
|
|
print $langs->trans("Volume");
|
|
print '</td>';
|
|
print '<td colspan="3">';
|
|
$calculatedVolume = 0;
|
|
$volumeUnit = 0;
|
|
if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
|
|
$calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
|
|
$volumeUnit = $object->size_units * 3;
|
|
}
|
|
// If reception volume not defined we use sum of products
|
|
if ($calculatedVolume > 0) {
|
|
if ($volumeUnit < 50) {
|
|
print showDimensionInBestUnit($calculatedVolume, $volumeUnit, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString("MAIN_VOLUME_DEFAULT_UNIT", 'no'));
|
|
} else {
|
|
print $calculatedVolume.' '.measuringUnitString(0, "volume", $volumeUnit);
|
|
}
|
|
}
|
|
if ($totalVolume > 0) {
|
|
if ($calculatedVolume) {
|
|
print ' ('.$langs->trans("SumOfProductVolumes").': ';
|
|
}
|
|
print showDimensionInBestUnit($totalVolume, 0, "volume", $langs, getDolGlobalInt('MAIN_VOLUME_DEFAULT_ROUND', -1), getDolGlobalString('MAIN_VOLUME_DEFAULT_UNIT', 'no'));
|
|
//if (empty($calculatedVolume)) print ' ('.$langs->trans("Calculated").')';
|
|
if ($calculatedVolume) {
|
|
print ')';
|
|
}
|
|
}
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
|
|
// Other attributes
|
|
$cols = 2;
|
|
|
|
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_view.tpl.php';
|
|
|
|
print '</table>';
|
|
|
|
print '</div>';
|
|
print '<div class="fichehalfright">';
|
|
print '<div class="underbanner clearboth"></div>';
|
|
|
|
print '<table class="border centpercent tableforfield">';
|
|
|
|
// Reception method
|
|
print '<tr><td height="10">';
|
|
print '<table class="nobordernopadding centpercent"><tr><td>';
|
|
print $langs->trans('ReceptionMethod');
|
|
print '</td>';
|
|
|
|
if ($action != 'editshipping_method_id' && $permissiontoadd) {
|
|
print '<td class="right"><a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?action=editshipping_method_id&token='.newToken().'&id='.$object->id.'">'.img_edit($langs->trans('SetReceptionMethod'), 1).'</a></td>';
|
|
}
|
|
print '</tr></table>';
|
|
print '</td><td colspan="2">';
|
|
if ($action == 'editshipping_method_id') {
|
|
print '<form name="setshipping_method_id" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'" method="post">';
|
|
print '<input type="hidden" name="token" value="'.newToken().'">';
|
|
print '<input type="hidden" name="action" value="setshipping_method_id">';
|
|
$object->fetch_delivery_methods();
|
|
print $form->selectarray("shipping_method_id", $object->meths, $object->shipping_method_id, 1, 0, 0, "", 1);
|
|
if ($user->admin) {
|
|
print info_admin($langs->trans("YouCanChangeValuesForThisListFromDictionarySetup"), 1);
|
|
}
|
|
print '<input type="submit" class="button button-edit" value="'.$langs->trans('Modify').'">';
|
|
print '</form>';
|
|
} else {
|
|
if ($object->shipping_method_id > 0) {
|
|
// Get code using getLabelFromKey
|
|
$code = $langs->getLabelFromKey($db, (string) $object->shipping_method_id, 'c_shipment_mode', 'rowid', 'code');
|
|
print $langs->trans("SendingMethod".strtoupper($code));
|
|
}
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Tracking Number
|
|
print '<tr><td class="titlefield">'.$form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->hasRight('reception', 'creer')).'</td><td colspan="3">';
|
|
print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->hasRight('reception', 'creer'), 'safehtmlstring', $object->tracking_number);
|
|
print '</td></tr>';
|
|
|
|
// Incoterms
|
|
if (isModEnabled('incoterm')) {
|
|
print '<tr><td>';
|
|
print '<table width="100%" class="nobordernopadding"><tr><td>';
|
|
print $langs->trans('IncotermLabel');
|
|
print '<td><td class="right">';
|
|
if ($user->hasRight('reception', 'creer')) {
|
|
print '<a class="editfielda" href="'.DOL_URL_ROOT.'/reception/card.php?id='.$object->id.'&action=editincoterm&token='.newToken().'">'.img_edit().'</a>';
|
|
} else {
|
|
print ' ';
|
|
}
|
|
print '</td></tr></table>';
|
|
print '</td>';
|
|
print '<td colspan="3">';
|
|
if ($action != 'editincoterm') {
|
|
print $form->textwithpicto($object->display_incoterms(), $object->label_incoterms, 1);
|
|
} else {
|
|
print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms) ? $object->location_incoterms : ''), $_SERVER['PHP_SELF'].'?id='.$object->id);
|
|
}
|
|
print '</td></tr>';
|
|
}
|
|
|
|
print "</table>";
|
|
|
|
print '</div>';
|
|
print '</div>';
|
|
|
|
print '<div class="clearboth"></div>';
|
|
|
|
/*
|
|
* Lines of simple reception
|
|
*/
|
|
if (!$origin_id && getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
if (!empty($object->table_element_line)) {
|
|
// Show object lines
|
|
$result = $object->getLinesArray();
|
|
|
|
print ' <form name="addproduct" id="addproduct" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.(($action != 'editline') ? '' : '#line_'.GETPOSTINT('lineid')).'" method="POST">
|
|
<input type="hidden" name="token" value="' . newToken().'">
|
|
<input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline').'">
|
|
<input type="hidden" name="mode" value="">
|
|
<input type="hidden" name="page_y" value="">
|
|
<input type="hidden" name="id" value="' . $object->id.'">
|
|
';
|
|
|
|
if (!empty($conf->use_javascript_ajax) && $object->status == $object::STATUS_DRAFT) {
|
|
include DOL_DOCUMENT_ROOT.'/core/tpl/ajaxrow.tpl.php';
|
|
}
|
|
|
|
print '<div class="div-table-responsive-no-min">';
|
|
if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
|
|
print '<table id="tablelines" class="noborder noshadow" width="100%">';
|
|
}
|
|
|
|
if (!empty($object->lines)) {
|
|
$object->printObjectLines($action, $mysoc, null, GETPOSTINT('lineid'), 0, '/reception/tpl');
|
|
}
|
|
|
|
// Form to add new line
|
|
if ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines') {
|
|
if ($action != 'editline') {
|
|
// Add products/services form
|
|
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
}
|
|
if (empty($reshook)) {
|
|
$object->formAddObjectLine(0, $mysoc, $soc);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($object->lines) || ($object->status == Reception::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
|
|
print '</table>';
|
|
}
|
|
print '</div>';
|
|
|
|
print "</form>\n";
|
|
}
|
|
} elseif (!empty($object->origin) && $object->origin_id > 0) {
|
|
// Lines of products of origin
|
|
if ($action == 'editline') {
|
|
print '<form name="updateline" id="updateline" action="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&lineid='.$line_id.'" method="POST">
|
|
<input type="hidden" name="token" value="' . newToken().'">
|
|
<input type="hidden" name="action" value="updateline">
|
|
<input type="hidden" name="mode" value="">
|
|
<input type="hidden" name="id" value="' . $object->id.'">';
|
|
}
|
|
print '<br><br>';
|
|
|
|
print '<div class="div-table-responsive-no-min">';
|
|
print '<table id="tablelines" class="noborder centpercent">';
|
|
print '<thead>';
|
|
print '<tr class="liste_titre">';
|
|
// #
|
|
if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
|
|
print '<td width="5" class="center"> </td>';
|
|
}
|
|
// Product/Service
|
|
print '<td>'.$langs->trans("Products").'</td>';
|
|
// Comment
|
|
print '<td>'.$langs->trans("Comment").'</td>';
|
|
// Qty
|
|
print '<td class="center">'.$langs->trans("QtyOrdered").'</td>';
|
|
if ($origin && $origin_id > 0) {
|
|
print '<td class="center">'.$langs->trans("QtyInOtherReceptions").'</td>';
|
|
}
|
|
|
|
$editColspan = 3;
|
|
if ($action == 'editline') {
|
|
if (!isModEnabled('stock')) {
|
|
$editColspan--;
|
|
}
|
|
if (empty($conf->productbatch->enabled)) {
|
|
$editColspan--;
|
|
}
|
|
print '<td class="center" colspan="'.$editColspan.'">';
|
|
if ($object->statut <= 1) {
|
|
print $langs->trans("QtyToReceive").' - ';
|
|
} else {
|
|
print $langs->trans("QtyReceived").' - ';
|
|
}
|
|
if (isModEnabled('stock')) {
|
|
print $langs->trans("WarehouseTarget").' - ';
|
|
}
|
|
if (isModEnabled('productbatch')) {
|
|
print $langs->trans("Batch");
|
|
}
|
|
print '</td>';
|
|
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
} else {
|
|
$statusreceived = $object::STATUS_CLOSED;
|
|
if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION")) {
|
|
$statusreceived = $object::STATUS_VALIDATED;
|
|
}
|
|
if (getDolGlobalInt("STOCK_CALCULATE_ON_RECEPTION_CLOSE")) {
|
|
$statusreceived = $object::STATUS_CLOSED;
|
|
}
|
|
if ($object->statut < $statusreceived) {
|
|
print '<td class="center">'.$langs->trans("QtyToReceive").'</td>';
|
|
} else {
|
|
print '<td class="center">'.$langs->trans("QtyReceived").'</td>';
|
|
}
|
|
if (isModEnabled('stock')) {
|
|
print '<td class="left">'.$langs->trans("WarehouseTarget").'</td>';
|
|
}
|
|
|
|
if (isModEnabled('productbatch')) {
|
|
print '<td class="left">'.$langs->trans("Batch").'</td>';
|
|
}
|
|
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('printFieldListTitle', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
}
|
|
print '<td class="center">'.$langs->trans("CalculatedWeight").'</td>';
|
|
print '<td class="center">'.$langs->trans("CalculatedVolume").'</td>';
|
|
//print '<td class="center">'.$langs->trans("Size").'</td>';
|
|
if ($object->statut == 0) {
|
|
print '<td class="linecoledit"></td>';
|
|
print '<td class="linecoldelete" width="10"></td>';
|
|
}
|
|
print "</tr>\n";
|
|
print '</thead>';
|
|
|
|
$var = false;
|
|
|
|
$outputlangs = $langs;
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
|
|
$object->fetch_thirdparty();
|
|
$newlang = '';
|
|
if (/* empty($newlang) && */ GETPOST('lang_id', 'aZ09')) {
|
|
$newlang = GETPOST('lang_id', 'aZ09');
|
|
}
|
|
if (empty($newlang)) {
|
|
$newlang = $object->thirdparty->default_lang;
|
|
}
|
|
if (!empty($newlang)) {
|
|
$outputlangs = new Translate("", $conf);
|
|
$outputlangs->setDefaultLang($newlang);
|
|
}
|
|
}
|
|
|
|
// Get list of products already sent for same source object into $alreadysent
|
|
$alreadysent = array();
|
|
|
|
if (empty($origin) || $origin == 'order_supplier') {
|
|
$origin = 'supplier_order';
|
|
}
|
|
|
|
if ($origin_id > 0) {
|
|
$sql = "SELECT obj.rowid, obj.fk_product, obj.label, obj.description, obj.product_type as fk_product_type, obj.qty as qty_asked, obj.date_start, obj.date_end";
|
|
$sql .= ", ed.rowid as receptionline_id, ed.qty, ed.fk_reception as reception_id, ed.fk_entrepot";
|
|
$sql .= ", e.rowid as reception_id, e.ref as reception_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_reception";
|
|
$sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tobatch as product_tobatch';
|
|
$sql .= ', p.description as product_desc';
|
|
$sql .= " FROM ".MAIN_DB_PREFIX."receptiondet_batch as ed";
|
|
$sql .= ", ".MAIN_DB_PREFIX."reception as e";
|
|
$sql .= ", ".MAIN_DB_PREFIX.(($origin == 'supplier_order') ? 'commande_fournisseur' : $origin)."det as obj"; // @phan-suppress-current-line SqlInjection
|
|
$sql .= " LEFT JOIN ".MAIN_DB_PREFIX."product as p ON obj.fk_product = p.rowid";
|
|
$sql .= " WHERE e.entity IN (".getEntity('reception').")";
|
|
$sql .= " AND obj.fk_commande = ".((int) $origin_id);
|
|
$sql .= " AND obj.rowid = ed.fk_elementdet";
|
|
$sql .= " AND ed.fk_reception = e.rowid";
|
|
$sql .= " AND ed.fk_reception !=".((int) $object->id);
|
|
$sql .= " ORDER BY obj.fk_product";
|
|
|
|
dol_syslog("get list of reception lines", LOG_DEBUG);
|
|
$resql = $db->query($sql);
|
|
if ($resql) {
|
|
$num = $db->num_rows($resql);
|
|
$i = 0;
|
|
|
|
while ($i < $num) {
|
|
$obj = $db->fetch_object($resql);
|
|
if ($obj) {
|
|
// $obj->rowid is rowid in $origin."det" table
|
|
$alreadysent[$obj->rowid][$obj->receptionline_id] = array('reception_ref' => $obj->reception_ref, 'reception_id' => $obj->reception_id, 'warehouse' => $obj->fk_entrepot, 'qty' => $obj->qty, 'date_valid' => $obj->date_valid, 'date_delivery' => $obj->date_delivery);
|
|
}
|
|
$i++;
|
|
}
|
|
}
|
|
//var_dump($alreadysent);
|
|
}
|
|
|
|
$arrayofpurchaselinealreadyoutput = array();
|
|
|
|
// Loop on each product to send/sent. Warning: $lines must be sorted by ->fk_commandefourndet (it is a regroupment key on output)
|
|
print '<tbody>';
|
|
for ($i = 0; $i < $num_prod; $i++) {
|
|
print '<!-- origin line id = '.(!empty($lines[$i]->origin_line_id) ? $lines[$i]->origin_line_id : 0).' -->'; // id of order line
|
|
print '<tr class="oddeven" id="row-'.$lines[$i]->id.'" data-id="'.$lines[$i]->id.'" data-element="'.$lines[$i]->element.'">';
|
|
|
|
// #
|
|
if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
|
|
print '<td class="center">'.($i + 1).'</td>';
|
|
}
|
|
|
|
// Predefined product or service
|
|
if ($lines[$i]->fk_product > 0) {
|
|
// Define output language
|
|
if (getDolGlobalInt('MAIN_MULTILANGS') && getDolGlobalString('PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE')) {
|
|
$prod = new Product($db);
|
|
$prod->fetch($lines[$i]->fk_product);
|
|
$label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product->label;
|
|
} else {
|
|
$label = (!empty($lines[$i]->product->label) ? $lines[$i]->product->label : $lines[$i]->product->product_label);
|
|
}
|
|
|
|
print '<td class="linecoldescription">';
|
|
if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
|
|
$text = $lines[$i]->product->getNomUrl(1);
|
|
$text .= ' - '.$label;
|
|
$description = (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE') ? '' : dol_htmlentitiesbr($lines[$i]->description));
|
|
print $form->textwithtooltip($text, $description, 3, 0, '', (string) $i);
|
|
print_date_range(!empty($lines[$i]->date_start) ? $lines[$i]->date_start : 0, !empty($lines[$i]->date_end) ? $lines[$i]->date_end : 0);
|
|
if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
|
|
print (!empty($lines[$i]->description) && $lines[$i]->description != $label) ? '<br>'.dol_htmlentitiesbr($lines[$i]->description) : '';
|
|
}
|
|
}
|
|
print "</td>\n";
|
|
} else {
|
|
print '<td class="linecoldescription">';
|
|
if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
|
|
if ($lines[$i]->product_type == Product::TYPE_SERVICE) {
|
|
$text = img_object($langs->trans('Service'), 'service');
|
|
} else {
|
|
$text = img_object($langs->trans('Product'), 'product');
|
|
}
|
|
|
|
if (!empty($lines[$i]->label)) {
|
|
$text .= ' <strong>'.$lines[$i]->label.'</strong>';
|
|
print $form->textwithtooltip($text, $lines[$i]->description, 3, 0, '', (string) $i);
|
|
} else {
|
|
print $text.' '.nl2br($lines[$i]->description);
|
|
}
|
|
|
|
print_date_range($lines[$i]->date_start, $lines[$i]->date_end);
|
|
}
|
|
print "</td>\n";
|
|
}
|
|
|
|
if ($action == 'editline' && $lines[$i]->id == $line_id) {
|
|
print '<td><input name="comment'.$line_id.'" id="comment'.$line_id.'" value="'.dol_escape_htmltag($lines[$i]->comment).'"></td>';
|
|
} else {
|
|
print '<td style="white-space: pre-wrap; max-width: 200px;">'.dol_escape_htmltag($lines[$i]->comment).'</td>';
|
|
}
|
|
|
|
|
|
// Qty ordered
|
|
print '<td class="center linecolqty">';
|
|
if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
|
|
print $lines[$i]->qty_asked;
|
|
}
|
|
print '</td>';
|
|
|
|
// Qty in other receptions (with reception and warehouse used)
|
|
if ($origin && $origin_id > 0) {
|
|
print '<td class="center nowrap linecolqtyinotherreceptions">';
|
|
$htmltooltip = '';
|
|
$qtyalreadyreceived = 0;
|
|
if (!array_key_exists($lines[$i]->fk_commandefourndet, $arrayofpurchaselinealreadyoutput)) {
|
|
foreach ($alreadysent as $key => $val) {
|
|
if ($lines[$i]->fk_commandefourndet == $key) {
|
|
$j = 0;
|
|
foreach ($val as $receptionline_id => $receptionline_var) {
|
|
if ($receptionline_var['reception_id'] == $lines[$i]->fk_reception) {
|
|
continue; // We want to show only "other receptions"
|
|
}
|
|
|
|
$j++;
|
|
if ($j > 1) {
|
|
$htmltooltip .= '<br>';
|
|
}
|
|
if (empty($conf->cache['reception'][$receptionline_var['reception_id']])) {
|
|
$reception_static = new Reception($db);
|
|
$reception_static->fetch($receptionline_var['reception_id']);
|
|
$conf->cache['reception'][$receptionline_var['reception_id']] = $reception_static;
|
|
} else {
|
|
$reception_static = $conf->cache['reception'][$receptionline_var['reception_id']];
|
|
}
|
|
$htmltooltip .= $reception_static->getNomUrl(1, 'nolink', 0, 0, 1);
|
|
$htmltooltip .= ' - '.$receptionline_var['qty'];
|
|
|
|
$htmltext = $langs->trans("DateValidation").' : '.(empty($receptionline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($receptionline_var['date_valid'], 'dayhour'));
|
|
if (isModEnabled('stock') && $receptionline_var['warehouse'] > 0) {
|
|
if (empty($conf->cache['warehouse'][$receptionline_var['warehouse']])) {
|
|
$warehousestatic = new Entrepot($db);
|
|
$warehousestatic->fetch($receptionline_var['warehouse']);
|
|
$conf->cache['warehouse'][$receptionline_var['warehouse']] = $warehousestatic;
|
|
} else {
|
|
$warehousestatic = $conf->cache['warehouse'][$receptionline_var['warehouse']];
|
|
}
|
|
$htmltext .= '<br>'.$langs->trans("From").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
|
|
}
|
|
$htmltooltip .= ' '.$form->textwithpicto('', $htmltext, 1);
|
|
|
|
$qtyalreadyreceived += $receptionline_var['qty'];
|
|
}
|
|
if ($j) {
|
|
$htmltooltip = $langs->trans("QtyInOtherReceptions").'...<br><br>'.$htmltooltip.'<br><input type="submit" name="dummyhiddenbuttontogetfocus" style="display:none" autofocus>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
print $form->textwithpicto((string) $qtyalreadyreceived, $htmltooltip, 1, 'info', '', 0, 3, 'tooltip'.$lines[$i]->id);
|
|
print '</td>';
|
|
}
|
|
|
|
if ($action == 'editline' && $lines[$i]->id == $line_id) {
|
|
// edit mode
|
|
print '<td colspan="'.$editColspan.'" class="center"><table class="nobordernopadding">';
|
|
if (isModEnabled('stock')) {
|
|
if ($lines[$i]->fk_product > 0) {
|
|
print '<!-- case edit 1 -->';
|
|
print '<tr>';
|
|
// Qty to receive or received
|
|
print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
|
|
// Warehouse source
|
|
print '<td>'.$formproduct->selectWarehouses($lines[$i]->fk_entrepot, 'entl'.$line_id, '', 1, 0, $lines[$i]->fk_product, '', 1).'</td>';
|
|
// Batch number management
|
|
if ($conf->productbatch->enabled && !empty($lines[$i]->product->status_batch)) {
|
|
print '<td class="nowraponall left"><input name="batch'.$line_id.'" id="batch'.$line_id.'" type="text" value="'.$lines[$i]->batch.'"><br>';
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
|
|
print $langs->trans('SellByDate').' : ';
|
|
print $form->selectDate($lines[$i]->sellby, 'dlc'.$line_id, 0, 0, 1, "").'</br>';
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
|
|
print $langs->trans('EatByDate').' : ';
|
|
print $form->selectDate($lines[$i]->eatby, 'dluo'.$line_id, 0, 0, 1, "");
|
|
}
|
|
print '</td>';
|
|
}
|
|
print '</tr>';
|
|
} else {
|
|
print '<!-- case edit 2 -->';
|
|
print '<tr>';
|
|
// Qty to receive or received
|
|
print '<td><input name="qtyl'.$line_id.'" id="qtyl'.$line_id.'" type="text" size="4" value="'.$lines[$i]->qty.'"></td>';
|
|
// Warehouse source
|
|
print '<td></td>';
|
|
// Batch number management
|
|
print '<td></td>';
|
|
print '</tr>';
|
|
}
|
|
}
|
|
print '</table></td>';
|
|
|
|
$parameters = array();
|
|
$parameters['line'] = $lines[$i];
|
|
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
} else {
|
|
// Qty to receive or received
|
|
print '<td class="center linecolqtytoreceive">'.$lines[$i]->qty.'</td>';
|
|
|
|
// Warehouse source
|
|
if (isModEnabled('stock')) {
|
|
if ($lines[$i]->fk_entrepot > 0) {
|
|
$entrepot = new Entrepot($db);
|
|
$entrepot->fetch($lines[$i]->fk_entrepot);
|
|
|
|
print '<td class="left tdoverflowmax150" title="'.dol_escape_htmltag($entrepot->label).'">';
|
|
print $entrepot->getNomUrl(1);
|
|
print '</td>';
|
|
} else {
|
|
print '<td></td>';
|
|
}
|
|
}
|
|
|
|
// Batch number management
|
|
if (isModEnabled('productbatch')) {
|
|
if (isset($lines[$i]->batch)) {
|
|
print '<!-- Detail of lot -->';
|
|
print '<td class="linecolbatch nowrap">';
|
|
$detail = $langs->trans("NA");
|
|
if ($lines[$i]->product->status_batch > 0 && $lines[$i]->fk_product > 0) {
|
|
require_once DOL_DOCUMENT_ROOT.'/product/stock/class/productlot.class.php';
|
|
$productlot = new Productlot($db);
|
|
$reslot = $productlot->fetch(0, $lines[$i]->fk_product, $lines[$i]->batch);
|
|
if ($reslot > 0) {
|
|
$detail = $productlot->getNomUrl(1);
|
|
} else {
|
|
// lot is not created and info is only in reception lines
|
|
$batchinfo = $langs->trans("Batch").': '.$lines[$i]->batch;
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
|
|
$batchinfo .= ' - '.$langs->trans("SellByDate").': '.dol_print_date($lines[$i]->sellby, "day");
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
|
|
$batchinfo .= ' - '.$langs->trans("EatByDate").': '.dol_print_date($lines[$i]->eatby, "day");
|
|
}
|
|
$detail = $form->textwithtooltip(img_picto('', 'object_barcode').' '.$langs->trans("DetailBatchNumber"), $batchinfo);
|
|
}
|
|
}
|
|
print $detail . '</td>';
|
|
} else {
|
|
print '<td></td>';
|
|
}
|
|
}
|
|
|
|
$parameters = array();
|
|
$parameters['line'] = $lines[$i];
|
|
$reshook = $hookmanager->executeHooks('printFieldListValue', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
}
|
|
|
|
// Weight
|
|
print '<td class="center linecolweight">';
|
|
if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
|
|
print $lines[$i]->product->weight * $lines[$i]->qty.' '.measuringUnitString(0, "weight", $lines[$i]->product->weight_units);
|
|
} else {
|
|
print ' ';
|
|
}
|
|
print '</td>';
|
|
|
|
// Volume
|
|
print '<td class="center linecolvolume">';
|
|
if (!empty($lines[$i]->fk_product_type) && $lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
|
|
print $lines[$i]->product->volume * $lines[$i]->qty.' '.measuringUnitString(0, "volume", $lines[$i]->product->volume_units);
|
|
} else {
|
|
print ' ';
|
|
}
|
|
print '</td>';
|
|
|
|
|
|
if ($action == 'editline' && $lines[$i]->id == $line_id) {
|
|
print '<td class="center valignmiddle" colspan="2">';
|
|
print '<input type="submit" class="button small button-save" id="savelinebutton marginbottomonly" name="save" value="'.$langs->trans("Save").'"><br>';
|
|
print '<input type="submit" class="button small button-cancel" id="cancellinebutton" name="cancel" value="'.$langs->trans("Cancel").'"><br>';
|
|
print '</td>';
|
|
} elseif ($object->statut == Reception::STATUS_DRAFT) {
|
|
// edit-delete buttons
|
|
print '<td class="linecoledit center">';
|
|
print '<a class="editfielda" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=editline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_edit().'</a>';
|
|
print '</td>';
|
|
print '<td class="linecoldelete" width="10">';
|
|
print '<a class="reposition" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deleteline&token='.newToken().'&lineid='.$lines[$i]->id.'">'.img_delete().'</a>';
|
|
print '</td>';
|
|
|
|
// Display lines extrafields
|
|
if (isset($rowExtrafieldsStart, $rowExtrafieldsView, $rowEnd)) { // @phan-suppress-current-line PhanPluginUndeclaredVariableIsset
|
|
print $rowExtrafieldsStart;
|
|
print $rowExtrafieldsView;
|
|
print $rowEnd;
|
|
}
|
|
}
|
|
print "</tr>";
|
|
|
|
$arrayofpurchaselinealreadyoutput[$lines[$i]->fk_commandefourndet] = $lines[$i]->fk_commandefourndet;
|
|
|
|
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
} else {
|
|
print $hookmanager->resPrint;
|
|
}
|
|
|
|
// Display lines extrafields
|
|
$extralabelslines = $extrafields->attributes[$lines[$i]->table_element];
|
|
if (!empty($extralabelslines) && is_array($extralabelslines) && count($extralabelslines) > 0) {
|
|
$colspan = 8;
|
|
if (isModEnabled('stock')) {
|
|
$colspan++;
|
|
}
|
|
if (isModEnabled('productbatch')) {
|
|
$colspan++;
|
|
}
|
|
|
|
$line = new CommandeFournisseurDispatch($db);
|
|
$line->id = $lines[$i]->id;
|
|
$line->fetch_optionals();
|
|
|
|
if ($action == 'editline' && $lines[$i]->id == $line_id) {
|
|
print $line->showOptionals($extrafields, 'edit', array('colspan' => $colspan), '');
|
|
} else {
|
|
print $line->showOptionals($extrafields, 'view', array('colspan' => $colspan), '');
|
|
}
|
|
}
|
|
}
|
|
print '</tbody>';
|
|
|
|
// TODO Show also lines ordered but not delivered
|
|
|
|
print "</table>\n";
|
|
print '</div>';
|
|
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
|
|
$object->fetchObjectLinked($object->id, $object->element);
|
|
}
|
|
|
|
/*
|
|
* Button actions
|
|
*/
|
|
|
|
if (($user->socid == 0) && ($action != 'presend')) {
|
|
print '<div class="tabsAction">';
|
|
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
|
if (empty($reshook)) {
|
|
if ($object->statut == Reception::STATUS_DRAFT && $num_prod > 0) {
|
|
if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'creer'))
|
|
|| (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('reception', 'reception_advance', 'validate'))) {
|
|
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=valid&token='.newToken().'">'.$langs->trans("Validate").'</a>';
|
|
} else {
|
|
print '<a class="butActionRefused" href="#" title="'.$langs->trans("NotAllowed").'">'.$langs->trans("Validate").'</a>';
|
|
}
|
|
}
|
|
// Back to draft
|
|
if ($object->statut == Reception::STATUS_VALIDATED && $user->hasRight('reception', 'creer')) {
|
|
print '<div class="inline-block divButAction"><a class="butAction" href="card.php?id='.$object->id.'&action=modif&token='.newToken().'">'.$langs->trans('SetToDraft').'</a></div>';
|
|
}
|
|
|
|
// TODO add alternative status
|
|
// 0=draft, 1=validated, 2=billed, we miss a status "delivered" (only available on order)
|
|
if ($object->statut == Reception::STATUS_CLOSED && $user->hasRight('reception', 'creer')) {
|
|
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=reopen&token='.newToken().'">'.$langs->trans("ReOpen").'</a>';
|
|
}
|
|
|
|
// Send mail
|
|
if (empty($user->socid)) {
|
|
if ($object->statut > 0) {
|
|
if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('reception', 'reception_advance', 'send')) {
|
|
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=presend&mode=init#formmailbeforetitle">'.$langs->trans('SendByMail').'</a>';
|
|
} else {
|
|
print '<a class="butActionRefused" href="#">'.$langs->trans('SendByMail').'</a>';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Create bill
|
|
if (isModEnabled("supplier_invoice") && ($object->statut == Reception::STATUS_VALIDATED || $object->statut == Reception::STATUS_CLOSED) && !getDolGlobalString('RECEPTION_STANDALONE')) {
|
|
if ($user->hasRight('fournisseur', 'facture', 'creer') || $user->hasRight('supplier_invoice', 'creer')) {
|
|
if (getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
|
|
print '<a class="butAction" href="'.DOL_URL_ROOT.'/fourn/facture/card.php?action=create&origin='.$object->element.'&originid='.$object->id.'&socid='.$object->socid.'">'.$langs->trans("CreateBill").'</a>';
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// Set Billed and Closed
|
|
if ($object->statut == Reception::STATUS_VALIDATED) {
|
|
if ($user->hasRight('reception', 'creer') && $object->statut > 0) {
|
|
if (!$object->billed && getDolGlobalString('WORKFLOW_BILL_ON_RECEPTION') !== '0') {
|
|
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifybilled&token='.newToken().'">'.$langs->trans('ClassifyBilled').'</a>';
|
|
}
|
|
print '<a class="butAction" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=classifyclosed&token='.newToken().'">'.$langs->trans("Close").'</a>';
|
|
}
|
|
}
|
|
|
|
if ($user->hasRight('reception', 'supprimer')) {
|
|
print '<a class="butActionDelete" href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=delete&token='.newToken().'">'.$langs->trans("Delete").'</a>';
|
|
}
|
|
}
|
|
|
|
print '</div>';
|
|
}
|
|
|
|
|
|
/*
|
|
* Documents generated
|
|
*/
|
|
|
|
if ($action != 'presend' && $action != 'editline') {
|
|
print '<div class="fichecenter"><div class="fichehalfleft">';
|
|
|
|
$objectref = dol_sanitizeFileName((string) $object->ref);
|
|
$filedir = $conf->reception->dir_output."/".$objectref;
|
|
|
|
$urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
|
|
|
|
$genallowed = $user->hasRight('reception', 'lire');
|
|
$delallowed = $user->hasRight('reception', 'creer');
|
|
|
|
print $formfile->showdocuments('reception', $objectref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
|
|
|
|
// Show links to link elements
|
|
//$tmparray = $form->showLinkToObjectBlock($object, null, array('order'), 1);
|
|
$somethingshown = $form->showLinkedObjectBlock($object, '');
|
|
|
|
print '</div><div class="fichehalfright">';
|
|
|
|
print '</div></div>';
|
|
}
|
|
|
|
// Presend form
|
|
$modelmail = 'reception_send';
|
|
$defaulttopic = 'SendReceptionRef';
|
|
$diroutput = $conf->reception->dir_output;
|
|
$trackid = 'rec'.$object->id;
|
|
|
|
include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
|
|
}
|
|
|
|
|
|
llxFooter();
|
|
|
|
$db->close();
|