mirror of
https://github.com/Dolibarr/dolibarr.git
synced 2026-03-20 09:03:55 +01:00
* ticket progress nullable (#36178)
* ticket progress nullable
* ticket progress nullable
* clean code (#36180)
* clean code
* clean code
* clean code
* Fix update of color when using HTML5
* CSS
* css
* Fix date input on smartphone
* css
* css
* css
* Clean code
* Responsive
* NEW add hourly rate in list of users
* Fix reset of budget
* Clean code
* Debug v23
* Fix regression
* Debug v23
* CSS
* Qual: Update Phan baseline.txt (#36190)
#Qual: Update Phan baseline.txt
Update the Phan baseline.txt file to reflect changes in the number of occurrences of specific issues.
* clean code (#36179)
* clean code
* clean code
* fix
* fix
* fix
* fix
* fix
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* NEW Holiday - Allow to specify a specific mail address from (#36184)
* NEW Holiday - Allow to specify a specific mail address from
* Update card.php
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Qual: Make $fields covariant, define type for $FIELDS in BankAccounts api (#36188)
* Qual: Make $fields covariant
* Qual: Update BankAccounts class phpDoc ($FIELDS)
# Qual: Update BankAccounts class phpDoc ($FIELDS)
Updated the documentation for the $FIELDS property.
* NEW Dashboard - Add option in ihm to disable MRP thumb (#36185)
* Fix CI
* Removed PROPALE_ADDON_NOTE_PUBLIC_DEFAULT. Must use the generic feature
"default value feature"
* Clean code
* css
* Fix CI
* Doc
* FIX Import/Export - Do not list imports or exports of Builder module backups of module descriptor files (#36192)
* FIX Import/Export - Do not list imports or exports of Builder module backups of module descriptor files
* FIX
* Add phone info in form public/members/new.php (#36119)
* Add phone info in form public/members/new.php
* Use GETPOST instead of GETPOSTISSET
* FIX wrong path of libraries (#36194)
* Updated PHPDoc (#36191)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Fix CI
* Fix 35017 accounts for local taxes 2 (#36160)
* FIX#35017 add locattaxes accounts to accounting defaults
* corr. libellés localtax pour afficher le bon pourcentage
* assurer la cohérence de la structure def_tva
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* NEW stock API GET movement (#36193)
* Added stock movement GET method
* Updated PHPDoc
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* css
* Fix js not found
* Add sortorder parameter to selectForFormsList method (#36173)
there are a problem on many extrafields list : we can't sort list by decrease and sort from a specific fields since we have add an sql prevention on filter based on : separator (who is used to separate parameters)
@eldy i propose to remplace on extrafields parameters the : in the sql injection prevention by another caracters, by exemple the ; or the § , and replace it after having explode all the parameters
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* css
* Removed duplicated code
* Debug v23
* Add property parent
* Debug v23
* Manage position of captcha modules. Fix responsive of setup page.
* Debug v23
* Try to fix phpstan
* Clean language files
* Debug v23
* Fix regression
* WIP LNE
* Drop a not used column to simplify
* Add test on data decryption
* PHPStan > Update baseline (#36208)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
* FIX member photo and thirdparty logo not deleted in documents directory (#36197)
* FIX member photo with web portal don't need login
* FIX member photo not deleted
* FIX pre-commit
* FIX phan error and uniformize code
* FIX pfffffff pre-commit
* FIX uniformize code
* FIX remove TODO
* FIX change const name
* FIX missing add in ECM during creation
* FIX add user photo in ecm
* FIX phan error
* display member photo with hash (#36205)
* display member photo with hash
* display member photo with hash
* display member photo with hash
* display member photo with hash
* FIX adding tms and datec to email templates (#36189)
* NEW: adding tms and datec to email templates
* Escaping a timestamp string I just generated myself
* switching single and double quotes in escape line for tms and datec to make the build system happy?
* Add an id to the table
* showing better names than tms and datec
* Changing code to label to fix #29116
* using hregis advice to use idate not escape the string with date
* requested changes
* forgot to add my name to editors
* had to make class changes for API to work
* setting datec back to int|string
* removing unused code lines and using idate in the api file
* no tms in create or update, but select. No datec in update
* expanding hurl tests to prevent post with id or tms, put with id or datec
---------
Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk>
* Update ticket.class.php (#34932)
* Update ticket.class.php
bad init in class
* Update ticket.class.php
* Update ticket.class.php
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* WIP LNE
* Debug v23
* fix stock display in replenish (#36209)
* [FEAT] Displaying the label instead of the id (#36210)
* Fix rename of function
* fix typo in interface_20_modWorkflow_WorkflowManager.class.php (#36212)
* add interventional feature on subtotal admin (#36207)
* Fi CI
* Fix CI
* Fix CI
* NEW Add Type, Description columns to Project Overview Expense Reports (#36214)
Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk>
* Fix PHP Warning: Undefined array key "nblinesnull" in /var/www/html/projet/element.php (#36198)
Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk>
* FIX use $this->db instead $db (#36219)
* FIX use $this->db instead $db
* FIX use $db with static function
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* add date_c update on project_task (#36217)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Trans
* Responsive
* Fix autogenerate login
* Update commondocgenerator.class.php (#36227)
* clean code (#36228)
* Fix typo in DLLMissing message for MyGerman.isl (#36223)
* Fix typo in DLLMissing message for MyGerman.isl
Typos:
- s/Mcrsoft/Microsoft/g
- s/credist_x86.exe/vc_redist.x86.exe/g
- dl link
* Fix DLLMissing message link for Visual C++ Redistributable
Updated the link for the Microsoft Visual C++ Redistributable installation instructions.
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* harmonize fields orders between holiday and expensereport (#36222)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Update header_login.tpl.php (#36220)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* avoid changing object after call (#36159)
* avoid changing object after call
* avoid changing object after call
* avoid changing object after call
* avoid changing object after call
* avoid changing object after call
* avoid changing object after call
* avoid changing object after call
* clean code
* clean code
* clean code
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* fix
* clean code
* clean
* clean
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Implement setCategories method in task class (#36218)
Added setCategories method to manage task categories.
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* check access doc for massfilesarea_stock (#36229)
* clean code (#36230)
* New : action to clone ticket (#36231)
* Clean permissions
* Debug v23
* Tipo
* clean code (#36233)
* clean code
* Update html_cerfafr.modules.php
* Update interface_50_modEventOrganization_EventOrganization.class.php
* Fix case
* add phone mobile of target (#36234)
* Debug v23
* WIP
* Short version of Go back
* Fix bad translation string
* Fix trans
* CSS
* css
* css
* Debug v23
* css
* Debug v23
* Doc
* Fix CI
* FIX add constant for the member photo width in web portal + avoid error (#36221)
* Close #35917
* Fix regression
* Fix type
* Fix GETPOST
* Fix GETPOST
* Fix SQL
* Fix error reporting
* Fix warning
* CSS
* Fix CI
* Fix CI
* Fix CI
* Fix CI
* Fix CI GETPOST -> GETPOSTINT
* Fix CI
* Fix CI
* Trans
* add gps position for files (#36240)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* clean code (#36241)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* PHPStan > Update baseline (#36242)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
* New import profile for leave requests (#36244)
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
* WIP LNE
* WIP LNE
* add show and filter in fields public and private notes (#36255)
* NEW Add SQL table for expensereport line extrafields support (#36251)
* Fix: Correct unit comparison bug in webportal document download (#36256)
The file size check was comparing bytes (from dol_filesize) directly with
kilobytes (from MAIN_SECURITY_MAXFILESIZE_DOWNLOADED config), causing false
positives that blocked downloads of small files.
Example: A 94 KB file (96678 bytes) was rejected because 96678 > 20480,
even though the limit was actually 20480 KB (20 MB).
Changes:
- Convert KB limit to bytes before comparison: $fileSizeMax * 1024
- Improve error message to display file size in KB for consistency
- Add detailed logging with both bytes and KB values
Fixes: Files under the configured limit are now correctly allowed to download
* NEW - Add a new API "product lots" (#36243)
* Add new API product lots
* fix precommit
* CSS
* NEW Introduce getCurrency(). $conf is no more allowed into computed
formulae.
* Doc
* Doc
* Trans tooltip
* NEW Invert logic of default date in proposal/order/invoice creation:
Need option to NOT autofill instead of the opposite.
* WIP LNE
* Fight against optionflation.
* Trans
* Trans
* The script generate_filelist_xml.php can check integrity from command
line.
* Doc
* Doc
* Debug
* Merge branch 'develop' of github.com:Dolibarr/dolibarr into develop
* Simple way to trap error to Close #36292
* Clean code
* Fix CI
* Fix CI
* Bump mdeweerd/logToCheckStyle from 2025.1.1 to 2025.11.2 (#36284)
Bumps [mdeweerd/logToCheckStyle](https://github.com/mdeweerd/logtocheckstyle) from 2025.1.1 to 2025.11.2.
- [Commits](https://github.com/mdeweerd/logtocheckstyle/compare/v2025.1.1...v2025.11.2)
---
updated-dependencies:
- dependency-name: mdeweerd/logToCheckStyle
dependency-version: 2025.11.2
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
* Update admin.lang (#36293)
* Update loanschedule.class.php (#36272)
Solve Error when schedule loans : "ERROR: 55000: currval of sequence "llx_payment_loan_rowid_seq" is not yet defined in this session LOCATION: currval_oid, sequence.c:884"
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Fix CI
* Fix phpunit
* Update SecurityTest.php (#36295)
* Update SecurityTest.php
* Update SecurityTest.php
* Update SecurityTest.php
* PHPStan > Update baseline (#36264)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Qual: Update pre-commit hooks (#36262)
* Qual: Update pre-commit hooks
# Qual: Update pre-commit hook
Updated several pre-commit hooks as long as the new ones are not alpha or beta versions
* Qual: Fix/ignore some shellcheck issues
* Qual: Enhance hurl test documentation and run script (#36291)
- Added detailed documentation for running specific tests, including options and exclusions
- Improved installation instructions with platform-specific guidance
- Enhanced error handling and user feedback
- Added support for GitHub-compatible messages
- Improved script structure and readability
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Qual: (commonnumrefgenerator): Add abstract method getExample (#36271)
- `getExample()`: Returns an example of the numbering format
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* FIX: Fix version extraction in setup_conf.sh (#36281)
# FIX: Fix version extraction in setup_conf.sh
The version extraction regex was updated to handle both DOL_VERSION and DOL_MAJOR_VERSION constants in version.inc.php.
The version is now available as DOL_MAJOR_VERSION since 29b1e75
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* FIX QUAL intervention API close (#36278)
* Refactored close method
* Updated PHPDoc
* Updated PHPDoc
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* can edit color in dict.php (#36270)
* can edit color in dict.php
* Update html.form.class.php
* Update html.form.class.php
* New tooltip freeze from experimental to develop branch (#36266)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Look and feel Debug v23
* Debug v23
* Close #36298
* Qual: Change field name to let phan warn about argument order (#36261)
* FIX wrong $param parameter position
* FIX ok it's good ! ;-)
* Qual: Change field name to let phan warn about argument order
# Qual: Change field name to let phan warn about argument order
Most of the time print_liste_field_titre() is called with $param instead of $moreparam.
By changing the argument name, phan will warn if the position is likely incorrect.
* Fix: Fix parameter order in print_liste_field_titre calls
- Fixed parameter order in print_liste_field_titre calls to maintain consistency
---------
Co-authored-by: Regis Houssin <regis.houssin@inodbox.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* clean code (#36260)
* clean code
* clean code
* clean code
* clean code
* fix $val might not be defined
* fix phpstan errors reported
* fix phpstan errors reported
* fix phpstan errors reported
* fix phpstan errors reported
* fix phpstan errors reported
* fix phpstan errors reported
* ignore phpstan reported for later
* clean code
* clean code
* clean code
* clean
* test
* Clean code
* Clean code
* add drag-and-drop functionality for managing draft expedition lines
* WIP LNE
* Debug v23
* refactor expedition card: clean up unused code and improve table rendering logic
* fix expedition card: correct colspan increment for draft status
* fix expedition card: adjust colspan indentation for better readability
* fix expedition card: uncomment shipment creation code for standalone mode
* fix expedition card: adjust colspan indentation to match coding standards
* fix expedition card: correct indentation of colspan logic to follow standards
* NEW Add hook on calcula_price() and get_default_tva()
* Comment
* Clean code
* fix expedition: add permission check for expedition details and update fetch_lines ordering logic
* Secure the dol_eval
* NEW Add filter on agenda event progression on agenda page
* fix css login page patch 01 (#36313)
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Fix CI
* FIX #36306 (#36307)
* NEW Disable by default obfuscation methods and function in extrafields
evaluable strings. Can re-enable with
MAIN_ALLOW_OBFUSCATION_METHODS_IN_DOL_EVAL=1
* Doc
* MAIN_DISALLOW_STRING_OBFUSCATION_IN_DOL_EVAL replaced with
MAIN_ALLOW_OBFUSCATION_METHODS_IN_DOL_EVAL
* Doc
* Add config param $dolibarr_main_restrict_eval_methods with whitelist of
functionsallowed in dol_eval. Advisory GHSA-x3w7-24rq-gvc5
* fix expedition: ensure expeditiondet rows remain in sync during drag-and-drop reorder operation
* fix expedition card: reindent colspan logic for consistency with coding standards
* Fix CI
* Qual: Update phan baseline (#36318)
# Qual: Update phan baseline
Remove fixed notices from exceptions.
* fix expedition: add phpcs annotations to suppress naming convention warnings around scope
* Doc
* Fix CI
* Fix CI
* Fix ci
* Fix CI
* Fix CI
* Fix ci
* Fix css login page patch 02 (#36320)
* fix css login page patch 01
* fix css login page patch 02
* fix css login page patch 02
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Clean code
* Fix CSS
* Fix CI
* Add product type check in line validation (#36319)
* Add product type check in line validation
needed by sous total plugins style which use line with type 9 for title, subtitle or free text. without the chek inb line validation, title, sub title or free text disappears
* Update card.php
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Migrate holiday files
* FIX Move 'holiday' from old path array to new one (#36308)
* Remove 'supplier_invoice' from old path array
* Update module path in arrayforoldpath
Sorry Eldy, I was confused. You are absolutely right, it is already corrected.
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Fix: PhanTypeMismatchProperty error in invoice creation (#36323)
* 🐛 Fix PhanTypeMismatchProperty error in invoice creation
The error occurred due to incorrect type handling in the invoice creation process. The changes fix this by properly handling the subtype field as an integer. This ensures type consistency and prevents potential runtime errors.
* FIX: Correct assignment to linkedObjectsIds in card.php
# FIX: Correct assignment to linkedObjectsIds in card.php
Modified the structure of linkedObjectsIds to include the rowid as a key to match the property type.
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* PHPStan > Update baseline (#36305)
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
* Accountancy - Resolve some problem on new function "Discount in accountancy" (#36285)
* FIX Accountancy - Discount wrong function & problem HTML injection
* FIX Accountancy - Wrong base for already / not yet function - Piece_num is not enough strong et editable
* FIX Accountancy - Discount - Use closing date rather than the invoice date
* FIX
* PHPPhan
* Update accountingjournal.class.php
* Update accountingjournal.class.php
---------
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
* Update expedition.class.php
* Update expedition.class.php
* Improve shipment line handling: fix origin/ID management, add extrafields display, and handle unchanged lines
* fix
---------
Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: Frédéric FRANCE <frederic34@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@destailleur.fr>
Co-authored-by: MDW <mdeweerd@users.noreply.github.com>
Co-authored-by: Alexandre SPANGARO <alexandre.spangaro@gmail.com>
Co-authored-by: Aksanti Bahiga tacite <71480535+marcellintacite@users.noreply.github.com>
Co-authored-by: Regis Houssin <regis.houssin@inodbox.com>
Co-authored-by: William Mead <william@m34d.com>
Co-authored-by: Vincent de Grandpré <vincent@de-grandpre.quebec>
Co-authored-by: Charlène Benke <1179011+defrance@users.noreply.github.com>
Co-authored-by: Laurent Destailleur <eldy@users.sourceforge.net>
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: Dolibot <dolibarr-bot@users.noreply.github.com>
Co-authored-by: Jon Bendtsen <github@jonb.dk>
Co-authored-by: Jon Bendtsen <xcodeauthor@jonb.dk>
Co-authored-by: Norbert Penel <homer8173@gmail.com>
Co-authored-by: PierrickV <8960084+PierrickV@users.noreply.github.com>
Co-authored-by: Maxime Kohlhaas <maxime@atm-consulting.fr>
Co-authored-by: Eric - CAP-REL <1468823+rycks@users.noreply.github.com>
Co-authored-by: Lucas Marcouiller <45882981+Hystepik@users.noreply.github.com>
Co-authored-by: Lucas Marcouiller <lmarcouiller@dolicloud.com>
Co-authored-by: HeilDenDus <rafagledesma@gmail.com>
Co-authored-by: Rudi Herouard <rudi.herouard@gmail.com>
Co-authored-by: Gigarun ingénierie <thomas@gigarun.eu>
Co-authored-by: atm-lucas <121817516+atm-lucasmantegari@users.noreply.github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: sweetcorreze <76868896+sweetcorreze@users.noreply.github.com>
Co-authored-by: John BOTELLA <68917336+thersane-john@users.noreply.github.com>
Co-authored-by: Marc <99648320+emheyarssi@users.noreply.github.com>
Co-authored-by: iouston <4319513+iouston@users.noreply.github.com>
Co-authored-by: Yamil Esteban Garcia <120027058+developmentOYR@users.noreply.github.com>
Co-authored-by: Quentin VIAL--GOUTEYRON <quentin.vial-gouteyron@atm-consulting.fr>
3917 lines
163 KiB
PHP
3917 lines
163 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@inodbox.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-2018 Ferran Marcet <fmarcet@2byte.es>
|
|
* Copyright (C) 2016 Yasser Carreón <yacasia@gmail.com>
|
|
* Copyright (C) 2018-2025 Frédéric France <frederic.france@free.fr>
|
|
* Copyright (C) 2020 Lenin Rivas <lenin@leninrivas.com>
|
|
* Copyright (C) 2022 Josep Lluís Amador <joseplluis@lliuretic.cat>
|
|
* Copyright (C) 2024-2026 MDW <mdeweerd@users.noreply.github.com>
|
|
* Copyright (C) 2025 Nick Fragoulis
|
|
* Copyright (C) 2025 Charlene Benke <charlene@patas-monkey.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 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/expedition/card.php
|
|
* \ingroup expedition
|
|
* \brief Card of a shipment
|
|
*/
|
|
|
|
// 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 . '/expedition/class/expedition.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/sendings.lib.php';
|
|
require_once DOL_DOCUMENT_ROOT . '/core/modules/expedition/modules_expedition.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';
|
|
require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.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';
|
|
}
|
|
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';
|
|
}
|
|
|
|
// Load translation files required by the page
|
|
$langs->loadLangs(array("sendings", "companies", "bills", 'orders', 'stocks', 'other', 'propal', 'productbatch'));
|
|
|
|
if (isModEnabled('incoterm')) {
|
|
$langs->load('incoterm');
|
|
}
|
|
if (isModEnabled('productbatch')) {
|
|
$langs->load('productbatch');
|
|
}
|
|
|
|
|
|
$origin = GETPOST('origin', 'alpha'); // Example: commande, propal
|
|
$origin_id = GETPOSTINT('origin_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
|
|
}
|
|
$socid = GETPOSTINT('socid');
|
|
$ref = GETPOST('ref', 'alpha');
|
|
$line_id = GETPOSTINT('lineid');
|
|
$facid = GETPOSTINT('facid');
|
|
$contactid = GETPOSTINT('contactid');
|
|
$projectid = GETPOSTINT('projectid');
|
|
$action = GETPOST('action', 'alpha');
|
|
$confirm = GETPOST('confirm', 'alpha');
|
|
$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 Expedition($db);
|
|
$objectorder = new Commande($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'
|
|
|
|
if (empty($origin) && !empty($object->origin_type)) {
|
|
$origin = $object->origin_type;
|
|
} elseif (empty($origin) && !empty($object->origin)) {
|
|
$origin = $object->origin;
|
|
}
|
|
if (empty($origin_id) && !empty($object->origin_id)) {
|
|
$origin_id = $object->origin_id;
|
|
}
|
|
$origin_type = is_string($origin) ? $origin : '';
|
|
|
|
// Permissions / Rights
|
|
$usercanread = $user->hasRight("expedition", "lire");
|
|
$usercancreate = $user->hasRight("expedition", "creer");
|
|
$usercandelete = $user->hasRight("expedition", "supprimer");
|
|
|
|
// Initialize a technical object to manage hooks of page. Note that conf->hooks_modules contains an array of hook context
|
|
$hookmanager->initHooks(array('expeditioncard', 'globalcard'));
|
|
|
|
$date_delivery = dol_mktime(GETPOSTINT('date_deliveryhour'), GETPOSTINT('date_deliverymin'), 0, GETPOSTINT('date_deliverymonth'), GETPOSTINT('date_deliveryday'), GETPOSTINT('date_deliveryyear'));
|
|
|
|
$date_shipping = dol_mktime(GETPOSTINT('date_shippinghour'), GETPOSTINT('date_shippingmin'), 0, GETPOSTINT('date_shippingmonth'), GETPOSTINT('date_shippingday'), GETPOSTINT('date_shippingyear'));
|
|
|
|
|
|
// Security check
|
|
|
|
if ($user->socid) {
|
|
$socid = $user->socid;
|
|
}
|
|
|
|
$result = restrictedArea($user, 'expedition', $object->id, '');
|
|
|
|
$permissiondellink = $user->hasRight('expedition', 'delivery', 'creer'); // Used by the include of actions_dellink.inc.php
|
|
$permissiontoadd = $user->hasRight('expedition', 'creer');
|
|
$permissiontoedit = $usercancreate; // Used by the include of actions_lineupdown.inc.php
|
|
$permissiontoeditextra = $permissiontoadd;
|
|
if (GETPOST('attribute', 'aZ09') && isset($extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')])) {
|
|
// For action 'update_extras', is there a specific permission set for the attribute to update
|
|
$permissiontoeditextra = dol_eval((string) $extrafields->attributes[$object->table_element]['perms'][GETPOST('attribute', 'aZ09')]);
|
|
}
|
|
|
|
$upload_dir = $conf->expedition->dir_output . '/sending';
|
|
|
|
$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.'/expedition/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.'/expedition/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_id > 0) {
|
|
if ($origin == 'commande') {
|
|
header("Location: " . DOL_URL_ROOT . '/expedition/shipment.php?id=' . ((int) $origin_id));
|
|
exit;
|
|
}
|
|
} else {
|
|
$action = '';
|
|
$object->fetch($object->id); // show shipment also after canceling modification
|
|
}
|
|
}
|
|
|
|
include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be 'include', not 'include_once'
|
|
|
|
// Actions to build doc
|
|
include DOL_DOCUMENT_ROOT . '/core/actions_builddoc.inc.php';
|
|
|
|
// Back to draft
|
|
if ($action == 'setdraft' && $permissiontoadd) {
|
|
$object->fetch($id);
|
|
$result = $object->setDraft($user, 0);
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
} else {
|
|
header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
|
|
exit;
|
|
}
|
|
}
|
|
// Reopen
|
|
if ($action == 'reopen' && $permissiontoadd) {
|
|
$object->fetch($id);
|
|
$result = $object->reOpen();
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
} else {
|
|
header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
// Set incoterm
|
|
if ($action == 'set_incoterms' && isModEnabled('incoterm') && $permissiontoadd) {
|
|
$result = $object->setIncoterms(GETPOSTINT('incoterm_id'), GETPOST('location_incoterms'));
|
|
}
|
|
|
|
if ($action == 'setref_customer' && $permissiontoadd) {
|
|
$result = $object->fetch($id);
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
|
|
$result = $object->setValueFrom('ref_customer', GETPOST('ref_customer', 'alpha'), '', null, 'text', '', $user, 'SHIPPING_MODIFY');
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$action = 'editref_customer';
|
|
} else {
|
|
header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
|
|
exit;
|
|
}
|
|
}
|
|
|
|
if ($action == 'update_extras' && $permissiontoeditextra) {
|
|
$object->oldcopy = dol_clone($object, 2);
|
|
|
|
$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) {
|
|
// Actions on extra fields
|
|
$result = $object->updateExtraField($attribute_name, 'SHIPPING_MODIFY');
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
|
|
if ($error) {
|
|
$action = 'edit_extras';
|
|
}
|
|
}
|
|
|
|
// Create shipment
|
|
if ($action == 'add' && $permissiontoadd) {
|
|
$db->begin();
|
|
|
|
if ($origin && $origin_id > 0) {
|
|
// We will loop on each line of the original document to complete the shipping object with various info and quantity to deliver
|
|
$classname = ucfirst($origin);
|
|
$objectsrc = new $classname($db);
|
|
'@phan-var-force Facture|Commande $objectsrc';
|
|
$objectsrc->fetch($origin_id);
|
|
$object->socid = $objectsrc->socid;
|
|
}
|
|
|
|
if (GETPOSTINT('socid') < 1 && $object->socid < 1) {
|
|
$error++;
|
|
setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ThirdParty")), null, 'errors');
|
|
$action = 'create';
|
|
}
|
|
|
|
if (!$origin && getDolGlobalString('SHIPMENT_STANDALONE')) {
|
|
$object->socid = GETPOSTINT('socid');
|
|
$object->fetch_thirdparty();
|
|
|
|
$object->origin = $origin; // deprecated
|
|
$object->origin_type = $origin_type;
|
|
$object->origin_id = $origin_id;
|
|
$object->fk_project = GETPOSTINT('projectid');
|
|
$object->weight = GETPOST('weight') == '' ? '' : GETPOSTFLOAT('weight');
|
|
$object->sizeH = GETPOST('sizeH') == '' ? '' : GETPOSTFLOAT('sizeH');
|
|
$object->sizeW = GETPOST('sizeW') == '' ? '' : GETPOSTFLOAT('sizeW');
|
|
$object->sizeS = GETPOST('sizeS') == '' ? '' : GETPOSTFLOAT('sizeS');
|
|
$object->size_units = GETPOSTINT('size_units');
|
|
$object->weight_units = GETPOSTINT('weight_units');
|
|
$object->ref_customer = GETPOST('ref_customer', 'alpha');
|
|
$object->model_pdf = GETPOST('model');
|
|
$object->date_delivery = $date_delivery; // Date delivery planned
|
|
$object->date_shipping = $date_shipping; // Sending date
|
|
$object->shipping_method_id = GETPOSTINT('shipping_method_id');
|
|
$object->tracking_number = GETPOST('tracking_number', 'alpha');
|
|
$object->note = GETPOST('note_private', 'restricthtml'); // deprecated
|
|
$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->origin = $origin; // deprecated
|
|
$object->origin_type = $origin_type;
|
|
$object->origin_id = $origin_id;
|
|
$object->fk_project = GETPOSTINT('projectid');
|
|
$object->weight = GETPOST('weight') == '' ? '' : GETPOSTFLOAT('weight');
|
|
$object->sizeH = GETPOST('sizeH') == '' ? '' : GETPOSTFLOAT('sizeH');
|
|
$object->sizeW = GETPOST('sizeW') == '' ? '' : GETPOSTFLOAT('sizeW');
|
|
$object->sizeS = GETPOST('sizeS') == '' ? '' : GETPOSTFLOAT('sizeS');
|
|
$object->size_units = GETPOSTINT('size_units');
|
|
$object->weight_units = GETPOSTINT('weight_units');
|
|
$object->ref_customer = GETPOST('ref_customer', 'alpha');
|
|
$object->model_pdf = GETPOST('model');
|
|
$object->date_delivery = $date_delivery; // Date delivery planned
|
|
$object->date_shipping = $date_shipping; // Sending date
|
|
$object->shipping_method_id = GETPOSTINT('shipping_method_id');
|
|
$object->tracking_number = GETPOST('tracking_number', 'alpha');
|
|
$object->note = GETPOST('note_private', 'restricthtml'); // deprecated
|
|
$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');
|
|
|
|
// We will loop on each line of the original document to complete the shipping object with various info and quantity to deliver
|
|
$classname = ucfirst($object->origin_type);
|
|
$objectsrc = new $classname($db);
|
|
'@phan-var-force Facture|Commande $objectsrc';
|
|
$objectsrc->fetch($object->origin_id);
|
|
|
|
$object->socid = $objectsrc->socid;
|
|
$object->fk_delivery_address = $objectsrc->fk_delivery_address;
|
|
|
|
$product = new Product($db);
|
|
|
|
$batch_line = array();
|
|
$stockLine = array();
|
|
$array_options = array();
|
|
|
|
$num = count($objectsrc->lines);
|
|
$totalqty = 0;
|
|
|
|
$product_batch_used = array();
|
|
|
|
for ($i = 0; $i < $num; $i++) {
|
|
$idl = "idl" . $i;
|
|
|
|
$sub_qty = array();
|
|
$subtotalqty = 0;
|
|
|
|
$j = 0;
|
|
|
|
$batch = "batchl" . $i . "_0";
|
|
$stockLocation = "ent1" . $i . "_0";
|
|
$qty = "qtyl" . $i;
|
|
|
|
$is_batch_or_serial = 0;
|
|
if (!empty($objectsrc->lines[$i]->fk_product)) {
|
|
$resultFetch = $product->fetch($objectsrc->lines[$i]->fk_product, '', '', '', 1, 1, 1);
|
|
if ($resultFetch < 0) {
|
|
setEventMessages($product->error, $product->errors, 'errors');
|
|
}
|
|
$is_batch_or_serial = $product->status_batch;
|
|
}
|
|
|
|
// If product need a batch or serial number
|
|
if (isModEnabled('productbatch') && $objectsrc->lines[$i]->product_tobatch) {
|
|
if (GETPOSTISSET($batch)) {
|
|
//shipment line with batch-enable product
|
|
$qty .= '_' . $j;
|
|
while (GETPOSTISSET($batch)) {
|
|
// save line of detail into sub_qty
|
|
$sub_qty[$j]['q'] = price2num(GETPOST($qty, 'alpha'), 'MS'); // the qty we want to move for this stock record
|
|
$sub_qty[$j]['id_batch'] = GETPOSTINT($batch); // the id into llx_product_batch of stock record to move
|
|
$subtotalqty += $sub_qty[$j]['q'];
|
|
|
|
if ($is_batch_or_serial == 2 && ($sub_qty[$j]['q'] > 1 || ($sub_qty[$j]['q'] > 0 && in_array($sub_qty[$j]['id_batch'], $product_batch_used)))) {
|
|
setEventMessages($langs->trans("TooManyQtyForSerialNumber", $product->ref, ''), null, 'errors');
|
|
$totalqty = 0;
|
|
break 2;
|
|
}
|
|
|
|
if ($is_batch_or_serial == 2 && $sub_qty[$j]['q'] > 0) {
|
|
// we stock the batch id to test later if the same serial is shipped on another line for the same product
|
|
$product_batch_used[$j] = $sub_qty[$j]['id_batch'];
|
|
}
|
|
|
|
$j++;
|
|
$batch = "batchl" . $i . "_" . $j;
|
|
$qty = "qtyl" . $i . '_' . $j;
|
|
}
|
|
|
|
$batch_line[$i]['detail'] = $sub_qty; // array of details
|
|
$batch_line[$i]['qty'] = $subtotalqty;
|
|
$batch_line[$i]['ix_l'] = GETPOSTINT($idl);
|
|
|
|
$totalqty += $subtotalqty;
|
|
} else {
|
|
// No detail were provided for lots, so if a qty was provided, we can throw an error.
|
|
if (GETPOST($qty)) {
|
|
// We try to set an amount
|
|
// Case we don't use the list of available qty for each warehouse/lot
|
|
// GUI does not allow this yet
|
|
setEventMessages($langs->trans("StockIsRequiredToChooseWhichLotToUse") . ' (' . $langs->trans("Line") . ' ' . GETPOSTINT($idl) . ')', null, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
} elseif (GETPOSTISSET($stockLocation)) {
|
|
//shipment line from multiple stock locations
|
|
$qty .= '_' . $j;
|
|
while (GETPOSTISSET($stockLocation)) {
|
|
// save sub line of warehouse
|
|
$stockLine[$i][$j]['qty'] = price2num(GETPOST($qty, 'alpha'), 'MS');
|
|
$stockLine[$i][$j]['warehouse_id'] = GETPOSTINT($stockLocation);
|
|
$stockLine[$i][$j]['ix_l'] = GETPOSTINT($idl);
|
|
|
|
$totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
|
|
$subtotalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
|
|
|
|
$j++;
|
|
$stockLocation = "ent1" . $i . "_" . $j;
|
|
$qty = "qtyl" . $i . '_' . $j;
|
|
}
|
|
} else {
|
|
//shipment line for product with no batch management and no multiple stock location
|
|
if (GETPOSTFLOAT($qty) > 0) {
|
|
$totalqty += price2num(GETPOST($qty, 'alpha'), 'MS');
|
|
$subtotalqty = price2num(GETPOST($qty, 'alpha'), 'MS');
|
|
}
|
|
}
|
|
|
|
// check qty shipped not greater than ordered
|
|
if (getDolGlobalInt("MAIN_DONT_SHIP_MORE_THAN_ORDERED") && $subtotalqty > $objectsrc->lines[$i]->qty) {
|
|
setEventMessages($langs->trans("ErrorTooMuchShipped", $i + 1), null, 'errors');
|
|
$error++;
|
|
continue;
|
|
}
|
|
|
|
// Extrafields
|
|
$array_options[$i] = $extrafields->getOptionalsFromPost($object->table_element_line, (string) $i);
|
|
// Unset extrafield
|
|
if (isset($extrafields->attributes[$object->table_element_line]['label']) && is_array($extrafields->attributes[$object->table_element_line]['label'])) {
|
|
// Get extra fields
|
|
foreach ($extrafields->attributes[$object->table_element_line]['label'] as $key => $value) {
|
|
unset($_POST["options_" . $key]);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (($totalqty > 0 || getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) && !$error) { // There is at least one thing to ship and no error
|
|
$selected_subtotal_lines = GETPOST('subtotal_toselect', 'array:int');
|
|
for ($i = 0; $i < $num; $i++) {
|
|
$qty = "qtyl" . $i;
|
|
|
|
if (!isset($batch_line[$i])) {
|
|
// not batch mode
|
|
if (isset($stockLine[$i])) {
|
|
//shipment from multiple stock locations
|
|
$nbstockline = count($stockLine[$i]);
|
|
for ($j = 0; $j < $nbstockline; $j++) {
|
|
if ($stockLine[$i][$j]['qty'] > 0 || ($stockLine[$i][$j]['qty'] == 0 && getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
|
|
$ret = $object->addline($stockLine[$i][$j]['warehouse_id'], $stockLine[$i][$j]['ix_l'], (float) $stockLine[$i][$j]['qty'], $array_options[$i]);
|
|
if ($ret < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (GETPOSTFLOAT($qty) > 0 || getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
|
|
$ent = "entl" . $i;
|
|
$idl = "idl" . $i;
|
|
$entrepot_id = is_numeric(GETPOSTINT($ent)) ? GETPOSTINT($ent) : GETPOSTINT('entrepot_id');
|
|
if ($entrepot_id < 0) {
|
|
$entrepot_id = '';
|
|
}
|
|
if (!($objectsrc->lines[$i]->fk_product > 0)) {
|
|
$entrepot_id = 0;
|
|
}
|
|
|
|
|
|
$ret = $object->addline($entrepot_id, GETPOSTINT($idl), (float) price2num(GETPOSTFLOAT($qty), 'MS'), $array_options[$i]);
|
|
if ($ret < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
if (isModEnabled('subtotals') && $objectsrc->lines[$i]->special_code == SUBTOTALS_SPECIAL_CODE && in_array($objectsrc->lines[$i]->id, $selected_subtotal_lines)) {
|
|
$object->addSubtotalLine($langs, $objectsrc->lines[$i]->desc, (int) $objectsrc->lines[$i]->qty, $objectsrc->lines[$i]->extraparams, $objectsrc->lines[$i]->id);
|
|
}
|
|
}
|
|
} else {
|
|
// batch mode
|
|
if ($batch_line[$i]['qty'] > 0 || ($batch_line[$i]['qty'] == 0 && getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS'))) {
|
|
$origin_line_id = (int) $batch_line[$i]['ix_l'];
|
|
$origin_line = new OrderLine($db);
|
|
$res = $origin_line->fetch($origin_line_id);
|
|
if ($res <= 0) {
|
|
$error++;
|
|
setEventMessages($origin_line->error, $origin_line->errors, 'errors');
|
|
}
|
|
$ret = $object->addline_batch($batch_line[$i], $array_options[$i], $origin_line);
|
|
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 shipment (like Odoo picking) and lines of shipments. Stock movement will be done when validating or closing shipment.
|
|
if ($ret <= 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
} elseif (!$error) {
|
|
$labelfieldmissing = $langs->transnoentitiesnoconv("QtyToShip");
|
|
if (isModEnabled('stock')) {
|
|
$labelfieldmissing .= '/' . $langs->transnoentitiesnoconv("Warehouse");
|
|
}
|
|
setEventMessages($langs->trans("ErrorFieldRequired", $labelfieldmissing), null, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
if (!$error) {
|
|
$db->commit();
|
|
$object->fetch_lines();
|
|
foreach ($object->lines as $line) {
|
|
$objectsrc_line = new $objectsrc->class_element_line($db);
|
|
'@phan-var-force CommonObjectLine $objectsrc_line';
|
|
$objectsrc_line->fetch($line->origin_line_id);
|
|
$line->extraparams = $objectsrc_line->extraparams;
|
|
$line->setExtraParameters();
|
|
}
|
|
header("Location: card.php?id=" . $object->id);
|
|
exit;
|
|
} else {
|
|
$db->rollback();
|
|
//$_GET["commande_id"] = GETPOSTINT('commande_id');
|
|
$action = 'create';
|
|
}
|
|
} elseif ($action == 'create_delivery' && getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && $user->hasRight('expedition', 'delivery', 'creer')) {
|
|
// Build a receiving receipt
|
|
$db->begin();
|
|
|
|
$result = $object->create_delivery($user);
|
|
if ($result > 0) {
|
|
$db->commit();
|
|
|
|
header("Location: " . DOL_URL_ROOT . '/delivery/card.php?action=create_delivery&token=' . newToken() . '&id=' . $result);
|
|
exit;
|
|
} else {
|
|
$db->rollback();
|
|
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif (
|
|
$action == 'confirm_valid' && $confirm == 'yes' && ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'creer'))
|
|
|| (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'shipping_advance', 'validate')))
|
|
) {
|
|
$object->fetch_thirdparty();
|
|
|
|
$result = $object->valid($user);
|
|
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, '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_cancel' && $confirm == 'yes' && $user->hasRight('expedition', 'creer')) {
|
|
$also_update_stock = (GETPOST('alsoUpdateStock', 'alpha') ? 1 : 0);
|
|
$result = $object->cancel($user, 0, (bool) $also_update_stock);
|
|
if ($result > 0) {
|
|
$result = $object->setStatut(Expedition::STATUS_CANCELED);
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'confirm_delete' && $confirm == 'yes' && $user->hasRight('expedition', 'supprimer')) {
|
|
$also_update_stock = (GETPOST('alsoUpdateStock', 'alpha') ? 1 : 0);
|
|
$result = $object->delete($user, 0, (bool) $also_update_stock);
|
|
if ($result > 0) {
|
|
header("Location: " . DOL_URL_ROOT . '/expedition/index.php');
|
|
exit;
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
// TODO add alternative status
|
|
//} elseif ($action == 'reopen' && ($user->hasRight('expedition', 'creer') || $user->hasRight('expedition', 'shipping_advance', 'validate')))
|
|
//{
|
|
// $result = $object->setStatut(Expedition::STATUS_DRAFT);
|
|
// if ($result < 0)
|
|
// {
|
|
// setEventMessages($object->error, $object->errors, 'errors');
|
|
// }
|
|
//}
|
|
} elseif ($action == 'confirm_delete_subtotalline' && $confirm == 'yes' && $permissiontoadd) {
|
|
$result = $object->deleteSubtotalLine($langs, GETPOSTINT('lineid'), (bool) GETPOST('deletecorrespondingsubtotalline'), $user);
|
|
if ($result > 0) {
|
|
// reorder lines
|
|
$object->line_order(true, 'ASC', false);
|
|
// 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 ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
|
|
// 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 ($action == 'confirm_sign' && $confirm == 'yes' && $user->hasRight('expedition', 'creer')) {
|
|
$result = $object->setSignedStatus($user, GETPOSTINT('signed_status'), 0, 'SHIPPING_MODIFY');
|
|
if ($result >= 0) {
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit;
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'confirm_unsign' && $confirm == 'yes' && $user->hasRight('expedition', 'creer')) {
|
|
$result = $object->setSignedStatus($user, Expedition::$SIGNED_STATUSES['STATUS_NO_SIGNATURE'], 0, 'SHIPPING_MODIFY');
|
|
if ($result >= 0) {
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit;
|
|
} else {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'setdate_livraison' && $user->hasRight('expedition', 'creer')) {
|
|
$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); // Set the planned delivery date
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif ($action == 'setdate_shipping' && $user->hasRight('expedition', 'creer')) {
|
|
$dateshipping = dol_mktime(GETPOSTINT('ship_hour'), GETPOSTINT('ship_min'), 0, GETPOSTINT('ship_month'), GETPOSTINT('ship_day'), GETPOSTINT('ship_year'));
|
|
|
|
$object->fetch($id);
|
|
$result = $object->setShippingDate($user, $dateshipping);
|
|
if ($result < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
}
|
|
} elseif (in_array($action, array('settracking_number', 'settracking_url', 'settrueWeight', 'settrueWidth', 'settrueHeight', 'settrueDepth', 'setshipping_method_id')) && $user->hasRight('expedition', 'creer')) {
|
|
// Action update
|
|
$error = 0;
|
|
|
|
if ($action == 'settracking_number') { // Test on permission not required
|
|
$object->tracking_number = trim(GETPOST('tracking_number', 'alpha'));
|
|
$object->tracking_number = preg_replace('/\s+/', '', $object->tracking_number);
|
|
}
|
|
if ($action == 'settracking_url') { // Test on permission not required
|
|
$object->tracking_url = trim(GETPOST('tracking_url', 'restricthtml'));
|
|
}
|
|
if ($action == 'settrueWeight') { // Test on permission not required
|
|
$object->trueWeight = GETPOSTFLOAT('trueWeight');
|
|
$object->weight_units = GETPOSTINT('weight_units');
|
|
}
|
|
if ($action == 'settrueWidth') { // Test on permission not required
|
|
$object->trueWidth = GETPOSTFLOAT('trueWidth');
|
|
}
|
|
if ($action == 'settrueHeight') { // Test on permission not required
|
|
$object->trueHeight = GETPOSTFLOAT('trueHeight');
|
|
$object->size_units = GETPOSTINT('size_units');
|
|
}
|
|
if ($action == 'settrueDepth') { // Test on permission not required
|
|
$object->trueDepth = GETPOSTFLOAT('trueDepth');
|
|
}
|
|
if ($action == 'setshipping_method_id') { // Test on permission not required
|
|
$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 == 'classifybilled' && $permissiontoadd) {
|
|
$object->fetch($id);
|
|
$result = $object->setBilled();
|
|
if ($result >= 0) {
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit();
|
|
}
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
} elseif ($action == 'classifyclosed' && $permissiontoadd) {
|
|
$object->fetch($id);
|
|
$result = $object->setClosed();
|
|
if ($result >= 0) {
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit();
|
|
}
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
} elseif ($action == 'deleteline' && !empty($line_id) && $permissiontoadd) {
|
|
// delete a line
|
|
$object->fetch($id);
|
|
$lines = $object->lines;
|
|
$line = new ExpeditionLigne($db);
|
|
$line->fk_expedition = $object->id;
|
|
|
|
$num_prod = count($lines);
|
|
for ($i = 0; $i < $num_prod; $i++) {
|
|
if ($lines[$i]->id == $line_id) {
|
|
if (count($lines[$i]->details_entrepot) > 1) {
|
|
// delete multi warehouse lines
|
|
foreach ($lines[$i]->details_entrepot as $details_entrepot) {
|
|
$line->id = $details_entrepot->line_id;
|
|
if (!$error && $line->delete($user) < 0) {
|
|
$error++;
|
|
}
|
|
}
|
|
} else {
|
|
// 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' && $permissiontoadd && GETPOST('cancel', 'alpha') != $langs->trans("Cancel")) {
|
|
if (!$origin && getDolGlobalString('SHIPMENT_STANDALONE')) {
|
|
// Update a line
|
|
// Clean parameters
|
|
|
|
if (!$object->fetch($id) > 0) {
|
|
dol_print_error($db);
|
|
}
|
|
$object->fetch_thirdparty();
|
|
|
|
$qty = GETPOST('qty', 'alpha');
|
|
$description = '';
|
|
$fk_parent = 0;
|
|
$element_type = 'shipping';
|
|
$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]);
|
|
}
|
|
}
|
|
|
|
$shipline = new ExpeditionLigne($db);
|
|
$shipline->fetch(GETPOSTINT('lineid'));
|
|
|
|
|
|
if (!$error) {
|
|
$result = $object->updatelinefree(GETPOSTINT('lineid'), (float) $qty, $element_type, $fk_product, GETPOSTINT('units'), $rang, $description, $fk_parent, 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
|
|
$update_done = false;
|
|
$line = new ExpeditionLigne($db);
|
|
$line->fk_expedition = $object->id;
|
|
|
|
// Extrafields Lines
|
|
$line->array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
|
|
// Unset extrafield POST Data
|
|
if (is_array($extrafields->attributes[$object->table_element_line]['label'])) {
|
|
foreach ($extrafields->attributes[$object->table_element_line]['label'] as $key => $value) {
|
|
unset($_POST["options_" . $key]);
|
|
}
|
|
}
|
|
$line->fk_product = $lines[$i]->fk_product;
|
|
if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0) {
|
|
// line with lot
|
|
foreach ($lines[$i]->detail_batch as $detail_batch) {
|
|
$lotStock = new Productbatch($db);
|
|
$batch = "batchl" . $detail_batch->fk_expeditiondet . "_" . $detail_batch->fk_origin_stock;
|
|
$qty = "qtyl" . $detail_batch->fk_expeditiondet . '_' . $detail_batch->id;
|
|
$batch_id = GETPOSTINT($batch);
|
|
$batch_qty = GETPOSTFLOAT($qty);
|
|
if (!empty($batch_id)) {
|
|
if ($lotStock->fetch($batch_id) > 0 && $line->fetch($detail_batch->fk_expeditiondet) > 0) { // $line is ExpeditionLine
|
|
if ($lines[$i]->entrepot_id != 0) {
|
|
// allow update line entrepot_id if not multi warehouse shipping
|
|
$line->entrepot_id = $lotStock->warehouseid;
|
|
}
|
|
|
|
// detail_batch can be an object with keys, or an array of ExpeditionLineBatch
|
|
if (empty($line->detail_batch)) {
|
|
$line->detail_batch = new stdClass();
|
|
}
|
|
|
|
$line->detail_batch->fk_origin_stock = $batch_id;
|
|
$line->detail_batch->batch = $lotStock->batch;
|
|
$line->detail_batch->id = $detail_batch->id;
|
|
$line->detail_batch->entrepot_id = $lotStock->warehouseid;
|
|
$line->detail_batch->qty = $batch_qty;
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
} else {
|
|
setEventMessages($lotStock->error, $lotStock->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
unset($_POST[$batch]);
|
|
unset($_POST[$qty]);
|
|
}
|
|
// add new batch
|
|
$lotStock = new Productbatch($db);
|
|
$batch = "batchl" . $line_id . "_0";
|
|
$qty = "qtyl" . $line_id . "_0";
|
|
$batch_id = GETPOSTINT($batch);
|
|
$batch_qty = GETPOSTFLOAT($qty);
|
|
$lineIdToAddLot = 0;
|
|
if ($batch_qty > 0 && !empty($batch_id)) {
|
|
if ($lotStock->fetch($batch_id) > 0) {
|
|
// check if lotStock warehouse id is same as line warehouse id
|
|
if ($lines[$i]->entrepot_id > 0) {
|
|
// single warehouse shipment line
|
|
if ($lines[$i]->entrepot_id == $lotStock->warehouseid) {
|
|
$lineIdToAddLot = $line_id;
|
|
}
|
|
} elseif (count($lines[$i]->details_entrepot) > 1) {
|
|
// multi warehouse shipment lines
|
|
foreach ($lines[$i]->details_entrepot as $detail_entrepot) {
|
|
if ($detail_entrepot->entrepot_id == $lotStock->warehouseid) {
|
|
$lineIdToAddLot = $detail_entrepot->line_id;
|
|
}
|
|
}
|
|
}
|
|
if ($lineIdToAddLot) {
|
|
// add lot to existing line
|
|
if ($line->fetch($lineIdToAddLot) > 0) {
|
|
$line->detail_batch->fk_origin_stock = $batch_id;
|
|
$line->detail_batch->batch = $lotStock->batch;
|
|
$line->detail_batch->entrepot_id = $lotStock->warehouseid;
|
|
$line->detail_batch->qty = $batch_qty;
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
} else {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
}
|
|
} else {
|
|
// create new line with new lot
|
|
$line->origin_line_id = $lines[$i]->origin_line_id;
|
|
$line->entrepot_id = $lotStock->warehouseid;
|
|
$line->detail_batch[0] = new ExpeditionLineBatch($db);
|
|
$line->detail_batch[0]->fk_origin_stock = $batch_id;
|
|
$line->detail_batch[0]->batch = $lotStock->batch;
|
|
$line->detail_batch[0]->entrepot_id = $lotStock->warehouseid;
|
|
$line->detail_batch[0]->qty = $batch_qty;
|
|
if ($object->create_line_batch($line, $line->array_options) < 0) {
|
|
setEventMessages($object->error, $object->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
}
|
|
} else {
|
|
setEventMessages($lotStock->error, $lotStock->errors, 'errors');
|
|
$error++;
|
|
}
|
|
}
|
|
} else {
|
|
if ($lines[$i]->fk_product > 0) {
|
|
// line without lot
|
|
if ($lines[$i]->entrepot_id == 0) {
|
|
// single warehouse shipment line or line in several warehouses context but with warehouse not defined
|
|
$stockLocation = "entl" . $line_id;
|
|
$qty = "qtyl" . $line_id;
|
|
$line->id = $line_id;
|
|
$line->entrepot_id = GETPOSTINT((string) $stockLocation);
|
|
$line->qty = GETPOSTFLOAT($qty);
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
unset($_POST[$stockLocation]);
|
|
unset($_POST[$qty]);
|
|
} elseif ($lines[$i]->entrepot_id > 0) {
|
|
// single warehouse shipment line
|
|
$stockLocation = "entl" . $line_id;
|
|
$qty = "qtyl" . $line_id;
|
|
$line->id = $line_id;
|
|
$line->entrepot_id = GETPOSTINT($stockLocation);
|
|
$line->qty = GETPOSTFLOAT($qty);
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
unset($_POST[$stockLocation]);
|
|
unset($_POST[$qty]);
|
|
} elseif (count($lines[$i]->details_entrepot) > 1) {
|
|
// multi warehouse shipment lines
|
|
foreach ($lines[$i]->details_entrepot as $detail_entrepot) {
|
|
if (!$error) {
|
|
$stockLocation = "entl" . $detail_entrepot->line_id;
|
|
$qty = "qtyl" . $detail_entrepot->line_id;
|
|
$warehouse = GETPOSTINT($stockLocation);
|
|
if (!empty($warehouse)) {
|
|
$line->id = $detail_entrepot->line_id;
|
|
$line->entrepot_id = $warehouse;
|
|
$line->qty = GETPOSTFLOAT($qty);
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
}
|
|
unset($_POST[$stockLocation]);
|
|
unset($_POST[$qty]);
|
|
}
|
|
}
|
|
} elseif (!isModEnabled('stock') && !isModEnabled('productbatch')) { // both product batch and stock are not activated.
|
|
$qty = "qtyl" . $line_id;
|
|
$line->id = $line_id;
|
|
$line->qty = GETPOSTFLOAT($qty);
|
|
$line->entrepot_id = 0;
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
unset($_POST[$qty]);
|
|
}
|
|
} else {
|
|
// Product no predefined
|
|
$qty = "qtyl" . $line_id;
|
|
$line->id = $line_id;
|
|
$line->qty = GETPOSTFLOAT($qty);
|
|
$line->entrepot_id = 0;
|
|
if ($line->update($user) < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} else {
|
|
$update_done = true;
|
|
}
|
|
unset($_POST[$qty]);
|
|
}
|
|
}
|
|
|
|
if (empty($update_done)) {
|
|
$line->id = $lines[$i]->id;
|
|
$resultInsertExtraFields = $line->insertExtraFields();
|
|
if ($resultInsertExtraFields < 0) {
|
|
setEventMessages($line->error, $line->errors, 'errors');
|
|
$error++;
|
|
} elseif ($resultInsertExtraFields > 0) {
|
|
$update_done = true;
|
|
}
|
|
}
|
|
|
|
if (empty($update_done) && !$error) {
|
|
setEventMessages($langs->trans('NoShipmentLineChangeDetected'), null, 'warnings');
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
} else {
|
|
header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // To redisplay the form being edited
|
|
exit();
|
|
}
|
|
}
|
|
} elseif ($action == 'updateline' && $permissiontoadd && GETPOST('cancel', 'alpha') == $langs->trans("Cancel")) {
|
|
header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // To redisplay the form being edited
|
|
exit();
|
|
} elseif ($action == 'addline' && !$origin && getDolGlobalString('SHIPMENT_STANDALONE') && $usercancreate) { // Add a new line
|
|
$langs->load('errors');
|
|
$error = 0;
|
|
$line_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
|
|
$predef = '';
|
|
$description = '';
|
|
$fk_parent = 0;
|
|
$fk_elementdet = '';
|
|
$element_type = 'shipping';
|
|
$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);
|
|
|
|
// Insert line
|
|
$result = $object->addlinefree((float) $qty, $element_type, $idprod, $fk_unit, min($rank, count($object->lines) + 1), $description, $fk_parent, $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();
|
|
}
|
|
}
|
|
} elseif ($action == 'confirm_sign' && $confirm == 'yes' && $permissiontoadd) {
|
|
$result = $object->setSignedStatus($user, GETPOSTINT('signed_status'), 0, 'SHIPPING_MODIFY');
|
|
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);
|
|
}
|
|
$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit;
|
|
} else {
|
|
$mesg = $object->error;
|
|
}
|
|
} elseif ($action == 'confirm_unsign' && $confirm == 'yes' && $permissiontoadd) {
|
|
$result = $object->setSignedStatus($user, Expedition::$SIGNED_STATUSES['STATUS_NO_SIGNATURE'], 0, 'SHIPPING_MODIFY');
|
|
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);
|
|
}
|
|
$object->generateDocument($object->model_pdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
|
|
}
|
|
|
|
header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
|
|
exit;
|
|
} else {
|
|
$mesg = $object->error;
|
|
}
|
|
}
|
|
|
|
include DOL_DOCUMENT_ROOT . '/core/actions_printing.inc.php';
|
|
|
|
// Actions to send emails
|
|
if (empty($id)) {
|
|
$id = $facid;
|
|
}
|
|
$triggersendname = 'SHIPPING_SENTBYMAIL';
|
|
$paramname = 'id';
|
|
$autocopy = 'MAIN_MAIL_AUTOCOPY_SHIPMENT_TO';
|
|
$mode = 'emailfromshipment';
|
|
$trackid = 'shi' . $object->id;
|
|
include DOL_DOCUMENT_ROOT . '/core/actions_sendmails.inc.php';
|
|
}
|
|
|
|
/*
|
|
* View
|
|
*/
|
|
|
|
$title = $object->ref . ' - ' . $langs->trans("Card");
|
|
if ($action == 'create') {
|
|
$title = $langs->trans("NewSending");
|
|
}
|
|
|
|
$help_url = 'EN:Module_Shipments|FR:Module_Expéditions|ES:Módulo_Expediciones|DE:Modul_Lieferungen';
|
|
|
|
llxHeader('', $title, $help_url, '', 0, 0, '', '', '', 'mod-expedition page-card');
|
|
|
|
if (empty($action)) {
|
|
$action = 'view';
|
|
}
|
|
|
|
$form = new Form($db);
|
|
$formfile = new FormFile($db);
|
|
$formproduct = new FormProduct($db);
|
|
if (isModEnabled('project')) {
|
|
$formproject = new FormProjets($db);
|
|
} else {
|
|
$formproject = null;
|
|
}
|
|
|
|
$product_static = new Product($db);
|
|
$shipment_static = new Expedition($db);
|
|
$warehousestatic = new Entrepot($db);
|
|
|
|
if (!$origin && $action == 'create' && !getDolGlobalString('SHIPMENT_STANDALONE')) {
|
|
print load_fiche_titre($langs->trans("CreateShipment"), '', 'dolly');
|
|
|
|
print '<br>' .$langs->trans("ShipmentCreationIsDoneFromOrder");
|
|
$action = '';
|
|
$id = '';
|
|
$ref = '';
|
|
}
|
|
|
|
// Mode creation.
|
|
if ($action == 'create' && $usercancreate) {
|
|
$expe = new Expedition($db);
|
|
|
|
print load_fiche_titre($langs->trans("NewSending"), '', 'dolly');
|
|
|
|
if (!$origin && getDolGlobalString('SHIPMENT_STANDALONE')) {
|
|
$soc = new Societe($db);
|
|
if ($socid > 0) {
|
|
$res = $soc->fetch($socid);
|
|
}
|
|
|
|
$shipping_method_id = $soc->shipping_method_id;
|
|
$note_private = $object->getDefaultCreateValueFor('note_private');
|
|
$note_public = $object->getDefaultCreateValueFor('note_public');
|
|
|
|
print '<form name="crea_expedition" 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_expedition]").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>';
|
|
}
|
|
|
|
// Date sending
|
|
print '<tr><td>'.$langs->trans("DateShipping").'</td>';
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'action', 'class="pictofixedwidth"');
|
|
$date_shipping = ($date_shipping ? $date_shipping : $object->date_shipping); // $date_shipping comes from GETPOST
|
|
print $form->selectDate($date_shipping ? $date_shipping : -1, 'date_shipping', 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') . '"> '; // Do not use GETPOSTINT here, we must accept '' also.
|
|
$text = $formproduct->selectMeasuringUnits("weight_units", "weight", GETPOST('weight_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Dim width x height x depth
|
|
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", GETPOST('size_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Delivery method
|
|
print "<tr><td>".$langs->trans("DeliveryMethod")."</td>";
|
|
print '<td colspan="3">';
|
|
$expe->fetch_delivery_methods();
|
|
print img_picto('', 'dolly', 'class="pictofixedwidth"');
|
|
print $form->selectarray("shipping_method_id", $expe->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1, 0, 0, '', 'widthcentpercentminusxx');
|
|
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";
|
|
|
|
// Other attributes
|
|
$parameters = array('objectsrc' => isset($objectsrc) ? $objectsrc : '', 'colspan' => ' colspan="3"', 'cols' => '3', 'socid' => $socid);
|
|
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $expe, $action); // Note that $action and $object may have been modified by hook
|
|
print $hookmanager->resPrint;
|
|
|
|
if (empty($reshook)) {
|
|
// copy from order
|
|
if ($object->fetch_optionals() > 0) {
|
|
$expe->array_options = array_merge($expe->array_options, $object->array_options);
|
|
}
|
|
print $expe->showOptionals($extrafields, 'edit', $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>';
|
|
}
|
|
|
|
// Document model
|
|
include_once DOL_DOCUMENT_ROOT.'/core/modules/expedition/modules_expedition.php';
|
|
$list = ModelePdfExpedition::liste_modeles($db);
|
|
if (is_countable($list) && count($list) > 1) {
|
|
print "<tr><td>".$langs->trans("DefaultModel")."</td>";
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'pdf', 'class="pictofixedwidth"');
|
|
print $form->selectarray('model', $list, getDolGlobalString('EXPEDITION_ADDON_PDF'), 0, 0, 0, '', 0, 0, 0, '', 'widthcentpercentminusx');
|
|
print "</td></tr>\n";
|
|
}
|
|
|
|
// 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) {
|
|
$classname = ucfirst($origin);
|
|
|
|
$object = new $classname($db);
|
|
/* @var Commande|Facture $object */
|
|
'@phan-var-force Commande|Facture $object';
|
|
|
|
|
|
if ($object->fetch($origin_id)) { // This include the fetch_lines
|
|
$soc = new Societe($db);
|
|
$soc->fetch($object->socid);
|
|
|
|
$author = new User($db);
|
|
$author->fetch($object->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="' . $object->id . '">';
|
|
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 == 'commande' && isModEnabled('order')) {
|
|
print $langs->trans("RefOrder");
|
|
}
|
|
if ($origin == 'propal' && isModEnabled("propal")) {
|
|
print $langs->trans("RefProposal");
|
|
}
|
|
print '</td><td colspan="3">';
|
|
print $object->getNomUrl(1);
|
|
print '</td>';
|
|
print "</tr>\n";
|
|
|
|
// Ref client
|
|
print '<tr><td>';
|
|
if ($origin == 'commande') {
|
|
print $langs->trans('RefCustomerOrder');
|
|
} elseif ($origin == 'propal') {
|
|
print $langs->trans('RefCustomerOrder');
|
|
} else {
|
|
print $langs->trans('RefCustomer');
|
|
}
|
|
print '</td><td colspan="3">';
|
|
print '<input type="text" name="ref_customer" value="' . $object->ref_client . '" />';
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Thirdparty
|
|
print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Company') . '</td>';
|
|
print '<td colspan="3">' . $soc->getNomUrl(1) . '</td>';
|
|
print '<input type="hidden" name="socid" value="' . $soc->id . '">';
|
|
print '</tr>';
|
|
|
|
// Project
|
|
if (isModEnabled('project') && is_object($formproject)) {
|
|
$projectid = GETPOSTINT('projectid');
|
|
if (empty($projectid) && !empty($object->fk_project)) {
|
|
$projectid = (int) $object->fk_project;
|
|
}
|
|
if ($origin == 'project') {
|
|
$projectid = ($object->id ? $object->id : 0);
|
|
}
|
|
$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>';
|
|
}
|
|
|
|
// 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>';
|
|
|
|
// Date shipment (sending)
|
|
print '<tr><td>' . $langs->trans("DateShipping") . '</td>';
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'action', 'class="pictofixedwidth"');
|
|
//$date_shipping = ($date_shipping ? $date_shipping : $object->date_shipping); // $date_shipping comes from GETPOST
|
|
print $form->selectDate($date_shipping ? $date_shipping : -1, 'date_shipping', 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', $object->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 ($object->note_private && !$user->socid) {
|
|
print '<tr><td>' . $langs->trans("NotePrivate") . '</td>';
|
|
print '<td colspan="3">';
|
|
$doleditor = new DolEditor('note_private', $object->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">';
|
|
print img_picto('', 'fa-balance-scale', 'class="pictofixedwidth"');
|
|
print '<input name="weight" size="4" value="' . GETPOST('weight') . '"> '; // Do not use GETPOSTINT here, we must accept '' also.
|
|
$text = $formproduct->selectMeasuringUnits("weight_units", "weight", GETPOST('weight_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Dim Width x Height x Depth
|
|
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", GETPOST('size_units'), 0, 2);
|
|
$htmltext = $langs->trans("KeepEmptyForAutoCalculation");
|
|
print $form->textwithpicto($text, $htmltext);
|
|
print '</td></tr>';
|
|
|
|
// Delivery method
|
|
print "<tr><td>" . $langs->trans("DeliveryMethod") . "</td>";
|
|
print '<td colspan="3">';
|
|
$expe->fetch_delivery_methods();
|
|
print img_picto('', 'dolly', 'class="pictofixedwidth"');
|
|
print $form->selectarray("shipping_method_id", $expe->meths, GETPOSTINT('shipping_method_id'), 1, 0, 0, "", 1, 0, 0, '', 'widthcentpercentminusxx');
|
|
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";
|
|
|
|
// 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>';
|
|
}
|
|
|
|
// Document model
|
|
include_once DOL_DOCUMENT_ROOT . '/core/modules/expedition/modules_expedition.php';
|
|
$list = ModelePdfExpedition::liste_modeles($db);
|
|
if (is_countable($list) && count($list) > 1) {
|
|
print "<tr><td>" . $langs->trans("DefaultModel") . "</td>";
|
|
print '<td colspan="3">';
|
|
print img_picto('', 'pdf', 'class="pictofixedwidth"');
|
|
print $form->selectarray('model', $list, getDolGlobalString('EXPEDITION_ADDON_PDF'), 0, 0, 0, '', 0, 0, 0, '', 'widthcentpercentminusx');
|
|
print "</td></tr>\n";
|
|
}
|
|
|
|
// Other attributes. Fields from hook formObjectOptions and Extrafields.
|
|
// $objectsrc is Commande|Facture
|
|
$objectsav = $object; // Because Expedition is $expe and not $object that is wrongly a duplicate of $objectsrc.
|
|
$object = $expe;
|
|
// Propagate extrafieldsvalue from source object to shipment object
|
|
if (isset($extrafields->attributes[$object->table_element]['label']) && is_array($extrafields->attributes[$object->table_element]['label']) && !empty($extrafields->attributes[$object->table_element]['label'])) {
|
|
foreach ($extrafields->attributes[$object->table_element]['label'] as $key => $val) {
|
|
if (array_key_exists('options_'.$key, $objectsav->array_options)) { // We take value from order only if extrafield has the same name/key.
|
|
$object->array_options['options_'.$key] = $objectsav->array_options['options_'.$key];
|
|
}
|
|
}
|
|
}
|
|
$parameters = array(
|
|
'objectsrc' => isset($objectsrc) ? $objectsrc : '',
|
|
'cols' => '3',
|
|
'socid' => $socid
|
|
);
|
|
include DOL_DOCUMENT_ROOT.'/core/tpl/extrafields_add.tpl.php';
|
|
$object = $objectsav;
|
|
|
|
print "</table>";
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
|
|
// Shipment lines
|
|
|
|
$numAsked = count($object->lines);
|
|
|
|
print '<script type="text/javascript">' . "\n";
|
|
print 'jQuery(document).ready(function() {' . "\n";
|
|
print 'jQuery("#autofill").click(function() {';
|
|
$i = 0;
|
|
while ($i < $numAsked) {
|
|
print 'jQuery("#qtyl' . $i . '").val(jQuery("#qtyasked' . $i . '").val() - jQuery("#qtydelivered' . $i . '").val());' . "\n";
|
|
if (isModEnabled('productbatch')) {
|
|
print 'jQuery("#qtyl' . $i . '_' . $i . '").val(jQuery("#qtyasked' . $i . '").val() - jQuery("#qtydelivered' . $i . '").val());' . "\n";
|
|
}
|
|
$i++;
|
|
}
|
|
print 'return false; });' . "\n";
|
|
print 'jQuery("#autoreset").click(function() { console.log("Reset values to 0"); jQuery(".qtyl").val(0);' . "\n";
|
|
print 'return false; });' . "\n";
|
|
print '});' . "\n";
|
|
print '</script>' . "\n";
|
|
|
|
print '<br>';
|
|
|
|
print '<div class="div-table-responsive-no-min">';
|
|
print '<table class="noborder centpercent">';
|
|
|
|
// Load shipments already done for same order
|
|
$object->loadExpeditions();
|
|
|
|
$alreadyQtyBatchSetted = $alreadyQtySetted = array();
|
|
|
|
$title_lines_to_disable = array();
|
|
|
|
if ($numAsked) {
|
|
if (isModEnabled('subtotals')) {
|
|
if (!(getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES') || getDolGlobalString('STOCK_SUPPORTS_SERVICES'))) {
|
|
$title_lines_to_disable = $object->getDisabledShippmentSubtotalLines();
|
|
}
|
|
foreach ($object->lines as $line) {
|
|
if ($line->special_code == SUBTOTALS_SPECIAL_CODE) {
|
|
$show_check_add_buttons = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
print '<tr class="liste_titre">';
|
|
print '<td>';
|
|
if (isset($show_check_add_buttons)) {
|
|
print $form->showCheckAddButtons('checkforselect');
|
|
}
|
|
print $langs->trans("Description");
|
|
print '</td>';
|
|
print '<td class="center">' . $langs->trans("QtyOrdered") . '</td>';
|
|
print '<td class="center">' . $langs->trans("QtyShipped") . '</td>';
|
|
print '<td class="center">' . $langs->trans("QtyToShip");
|
|
if (!isModEnabled('productbatch')) {
|
|
print '<br><a href="#" id="autofill" class="opacitymedium link cursor cursorpointer">' . img_picto($langs->trans("Autofill"), 'autofill', 'class="paddingrightonly"') . '</a>';
|
|
print ' / ';
|
|
} else {
|
|
print '<br>';
|
|
}
|
|
print '<span id="autoreset" class="opacitymedium link cursor cursorpointer">' . img_picto($langs->trans("Reset"), 'eraser') . '</span>';
|
|
print '</td>';
|
|
if (isModEnabled('stock')) {
|
|
if (!isModEnabled('productbatch')) {
|
|
print '<td class="left">' . $langs->trans("Warehouse") . ' (' . $langs->trans("Stock") . ')</td>';
|
|
} else {
|
|
print '<td class="left">' . $langs->trans("Warehouse") . ' / ' . $langs->trans("Batch") . ' (' . $langs->trans("Stock") . ')</td>';
|
|
}
|
|
}
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td class="left">' . $langs->trans('StockEntryDate') . '</td>';
|
|
}
|
|
print "</tr>\n";
|
|
}
|
|
|
|
$warehouse_id = GETPOSTINT('entrepot_id');
|
|
$warehousePicking = array();
|
|
// get all warehouse children for picking
|
|
if ($warehouse_id > 0) {
|
|
$warehousePicking[] = $warehouse_id;
|
|
$warehouseObj = new Entrepot($db);
|
|
$warehouseObj->get_children_warehouses($warehouse_id, $warehousePicking);
|
|
}
|
|
|
|
$indiceAsked = 0;
|
|
while ($indiceAsked < $numAsked) {
|
|
$product = new Product($db);
|
|
|
|
$line = $object->lines[$indiceAsked];
|
|
|
|
$parameters = array('i' => $indiceAsked, 'line' => $line, 'num' => $numAsked);
|
|
$reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
}
|
|
|
|
if (empty($reshook) && $line->special_code != SUBTOTALS_SPECIAL_CODE) {
|
|
// 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 for order line ' . $line->id . ' -->' . "\n";
|
|
print '<tr class="oddeven" id="row-' . $line->id . '">' . "\n";
|
|
|
|
$qtyProdCom = $line->qty;
|
|
$productChildrenNb = 0;
|
|
// Product label
|
|
if ($line->fk_product > 0) { // If predefined product
|
|
$res = $product->fetch($line->fk_product);
|
|
if ($res < 0) {
|
|
dol_print_error($db, $product->error, $product->errors);
|
|
}
|
|
if (getDolGlobalInt('PRODUIT_SOUSPRODUITS') && !getDolGlobalInt('PRODUIT_SOUSPRODUITS_ALSO_ENABLE_PARENT_STOCK_MOVE')) {
|
|
$productChildrenNb = $product->hasFatherOrChild(1);
|
|
}
|
|
if ($productChildrenNb > 0) {
|
|
$product->loadStockForVirtualProduct('warehouseopen', $qtyProdCom);
|
|
} else {
|
|
$product->load_stock('warehouseopen'); // Load all $product->stock_warehouse[idwarehouse]->detail_batch
|
|
}
|
|
//var_dump($product->stock_warehouse[1]);
|
|
|
|
print '<td>';
|
|
print '<a name="' . $line->id . '"></a>'; // Anchor to retor to the line
|
|
|
|
// Show product and description
|
|
$product_static->type = $line->fk_product_type;
|
|
$product_static->id = $line->fk_product;
|
|
$product_static->ref = $line->ref;
|
|
$product_static->status = $line->product_tosell;
|
|
$product_static->status_buy = $line->product_tobuy;
|
|
$product_static->status_batch = $line->product_tobatch;
|
|
|
|
$showdescinproductdesc = getDolGlobalString('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE');
|
|
|
|
$text = $product_static->getNomUrl(1);
|
|
$text .= ' - ' . (!empty($line->label) ? $line->label : $line->product_label);
|
|
$description = ($showdescinproductdesc ? '' : dol_htmlentitiesbr($line->desc));
|
|
$description .= empty($product->stockable_product) ? $langs->trans('StockDisabled') : $langs->trans('StockEnabled');
|
|
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 ($showdescinproductdesc) {
|
|
print ($line->desc && $line->desc != $line->product_label) ? '<br>' . dol_htmlentitiesbr($line->desc) : '';
|
|
}
|
|
|
|
$expLine = new ExpeditionLigne($db);
|
|
$srcLine = new OrderLine($db);
|
|
$srcLine->id = $line->id;
|
|
$srcLine->fetch_optionals(); // Fetch source line extrafields so shipment line creation matches order UI.
|
|
$expLine->array_options = array_merge($expLine->array_options, $srcLine->array_options);
|
|
$lineExtrafieldsHtml = $expLine->showOptionals($extrafields, 'edit', array(), (string) $indiceAsked, '', '1', 'line');
|
|
if (!empty($lineExtrafieldsHtml)) {
|
|
print '<div style="padding-top: 10px" id="extrafield_lines_area_create_' . $indiceAsked . '" name="extrafield_lines_area_create_' . $indiceAsked . '">';
|
|
print $lineExtrafieldsHtml;
|
|
print '</div>';
|
|
}
|
|
|
|
print '</td>';
|
|
} else {
|
|
print "<td>";
|
|
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));
|
|
|
|
$expLine = new ExpeditionLigne($db);
|
|
$srcLine = new OrderLine($db);
|
|
$srcLine->id = $line->id;
|
|
$srcLine->fetch_optionals(); // Fetch source line extrafields so shipment line creation matches order UI.
|
|
$expLine->array_options = array_merge($expLine->array_options, $srcLine->array_options);
|
|
$lineExtrafieldsHtml = $expLine->showOptionals($extrafields, 'edit', array(), (string) $indiceAsked, '', '1', 'line');
|
|
if (!empty($lineExtrafieldsHtml)) {
|
|
print '<div style="padding-top: 10px" id="extrafield_lines_area_create_' . $indiceAsked . '" name="extrafield_lines_area_create_' . $indiceAsked . '">';
|
|
print $lineExtrafieldsHtml;
|
|
print '</div>';
|
|
}
|
|
print "</td>\n";
|
|
}
|
|
|
|
// unit of order
|
|
$unit_order = '';
|
|
if (getDolGlobalString('PRODUCT_USE_UNITS')) {
|
|
$unit_order = measuringUnitString($line->fk_unit);
|
|
}
|
|
|
|
// Qty
|
|
print '<td class="center">' . $line->qty;
|
|
print '<input name="qtyasked' . $indiceAsked . '" id="qtyasked' . $indiceAsked . '" type="hidden" value="' . $line->qty . '">';
|
|
if ($line->qty) {
|
|
print ' ' . $unit_order . '</td>';
|
|
}
|
|
|
|
// Qty already shipped
|
|
print '<td class="center">';
|
|
$quantityDelivered = isset($object->expeditions[$line->id]) ? $object->expeditions[$line->id] : '';
|
|
print $quantityDelivered;
|
|
print '<input name="qtydelivered' . $indiceAsked . '" id="qtydelivered' . $indiceAsked . '" type="hidden" value="' . $quantityDelivered . '">';
|
|
if ($quantityDelivered) {
|
|
print ' ' . $unit_order . '</td>';
|
|
}
|
|
|
|
// Qty to ship
|
|
$quantityAsked = $line->qty;
|
|
if ($line->product_type == Product::TYPE_SERVICE && !getDolGlobalString('STOCK_SUPPORTS_SERVICES') && !getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) {
|
|
$quantityToBeDelivered = 0;
|
|
} else {
|
|
if (is_numeric($quantityDelivered)) {
|
|
$quantityToBeDelivered = $quantityAsked - $quantityDelivered;
|
|
} else {
|
|
$quantityToBeDelivered = $quantityAsked;
|
|
}
|
|
}
|
|
|
|
$warehouseObject = null;
|
|
if (count($warehousePicking) == 1 || !($line->fk_product > 0) || !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 -->';
|
|
//ship from preselected location
|
|
$stock = + (isset($product->stock_warehouse[$warehouse_id]->real) ? $product->stock_warehouse[$warehouse_id]->real : 0); // Convert to number
|
|
if (($line->product_type == Product::TYPE_SERVICE && getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) || $product->stockable_product == Product::DISABLED_STOCK) {
|
|
$deliverableQty = $quantityToBeDelivered;
|
|
} else {
|
|
$deliverableQty = min($quantityToBeDelivered, $stock);
|
|
}
|
|
if ($deliverableQty < 0) {
|
|
$deliverableQty = 0;
|
|
}
|
|
if (!isModEnabled('productbatch') || !$product->hasbatch()) {
|
|
// Quantity to send
|
|
print '<td class="center">';
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES') || ($line->product_type == Product::TYPE_SERVICE && getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES'))) {
|
|
if (GETPOSTINT('qtyl' . $indiceAsked)) {
|
|
$deliverableQty = GETPOSTINT('qtyl' . $indiceAsked);
|
|
}
|
|
print '<input name="idl' . $indiceAsked . '" type="hidden" value="' . $line->id . '">';
|
|
$qtylValue = $deliverableQty;
|
|
if (getDolGlobalBool('SHIPMENT_DONT_PREFILL_QTY', false)) {
|
|
$qtylValue = '';
|
|
}
|
|
print '<input name="qtyl' . $indiceAsked . '" id="qtyl' . $indiceAsked . '" class="qtyl right" type="text" size="4" value="' . $qtylValue . '">';
|
|
} else {
|
|
if (getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
|
|
print '<input name="idl' . $indiceAsked . '" type="hidden" value="' . $line->id . '">';
|
|
print '<input name="qtyl' . $indiceAsked . '" id="qtyl' . $indiceAsked . '" type="hidden" value="0">';
|
|
}
|
|
|
|
print $langs->trans("NA");
|
|
}
|
|
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 -->';
|
|
|
|
$stockMin = false;
|
|
if (getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) {
|
|
$stockMin = 0;
|
|
}
|
|
if ($productChildrenNb > 0) {
|
|
print $formproduct->selectWarehouses($tmpentrepot_id, 'entl' . $indiceAsked, '', 1, 0, 0, '', 0, 0, array(), 'minwidth200', array(), 1, $stockMin, 'stock DESC, e.ref');
|
|
} else {
|
|
if ($product->stockable_product == Product::ENABLED_STOCK) {
|
|
print $formproduct->selectWarehouses($tmpentrepot_id, 'entl' . $indiceAsked, '', 1, 0, $line->fk_product, '', 1, 0, array(), 'minwidth200', array(), 1, $stockMin, 'stock DESC, e.ref');
|
|
} else {
|
|
print img_warning() . ' ' . $langs->trans('StockDisabled');
|
|
}
|
|
}
|
|
|
|
if ($tmpentrepot_id > 0 && $tmpentrepot_id == $warehouse_id) {
|
|
//print $stock.' '.$quantityToBeDelivered;
|
|
if ($stock < $quantityToBeDelivered) {
|
|
print ' ' . img_warning($langs->trans("StockTooLow")); // Stock too low for this $warehouse_id but you can change warehouse
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
print '<span class="opacitymedium">(' . $langs->trans("Service") . ')</span><input name="entl' . $indiceAsked . '" id="entl' . $indiceAsked . '" type="hidden" value="0">';
|
|
}
|
|
print '</td>';
|
|
}
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print "</tr>\n";
|
|
|
|
// Show subproducts of product
|
|
if (getDolGlobalString('PRODUIT_SOUSPRODUITS') && $line->fk_product > 0) {
|
|
$product->get_sousproduits_arbo();
|
|
$prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
|
|
if (count($prods_arbo) > 0) {
|
|
foreach ($prods_arbo as $key => $value) {
|
|
//print $value[0];
|
|
$img = '';
|
|
if ($value['stock'] < $value['stock_alert']) {
|
|
$img = img_warning($langs->trans("StockTooLow"));
|
|
}
|
|
print "<tr class=\"oddeven\"><td> ->
|
|
<a href=\"" . DOL_URL_ROOT . "/product/card.php?id=" . $value['id'] . "\">" . $value['fullpath'] . "
|
|
</a> (" . $value['nb'] . ")</td><td class=\"center\"> " . $value['nb_total'] . "</td><td> </td><td> </td>
|
|
<td class=\"center\">" . $value['stock'] . " " . $img . "</td>";
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print "</tr>";
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
// Product need lot
|
|
print '<td></td><td></td>';
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print '</tr>'; // end line and start a new one for lot/serial
|
|
print '<!-- Case product need lot -->';
|
|
|
|
$staticwarehouse = new Entrepot($db);
|
|
if ($warehouse_id > 0) {
|
|
$staticwarehouse->fetch($warehouse_id);
|
|
}
|
|
|
|
$subj = 0;
|
|
// Define nb of lines suggested for this order line
|
|
$nbofsuggested = 0;
|
|
if (is_object($product->stock_warehouse[$warehouse_id]) && !empty($product->stock_warehouse[$warehouse_id]->detail_batch)) {
|
|
foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch) {
|
|
$nbofsuggested++;
|
|
}
|
|
}
|
|
print '<input name="idl'.$indiceAsked.'" type="hidden" value="'.$line->id.'">';
|
|
if (is_object($product->stock_warehouse[$warehouse_id]) && !empty($product->stock_warehouse[$warehouse_id]->detail_batch)) {
|
|
foreach ($product->stock_warehouse[$warehouse_id]->detail_batch as $dbatch) { // $dbatch is instance of Productbatch
|
|
//var_dump($dbatch);
|
|
$batchStock = +$dbatch->qty; // To get a numeric
|
|
$deliverableQty = min($quantityToBeDelivered, $batchStock);
|
|
|
|
// Now we will check if we have to reduce the deliverableQty by taking into account the qty already suggested in previous line
|
|
if (isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) {
|
|
$deliverableQty = min($quantityToBeDelivered, $batchStock - $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)]);
|
|
} else {
|
|
if (!isset($alreadyQtyBatchSetted[$line->fk_product])) {
|
|
$alreadyQtyBatchSetted[$line->fk_product] = array();
|
|
}
|
|
|
|
if (!isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch])) {
|
|
$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch] = array();
|
|
}
|
|
|
|
$deliverableQty = min($quantityToBeDelivered, $batchStock);
|
|
}
|
|
|
|
if ($deliverableQty < 0) {
|
|
$deliverableQty = 0;
|
|
}
|
|
|
|
$inputName = 'qtyl' . $indiceAsked . '_' . $subj;
|
|
if (GETPOSTISSET($inputName)) {
|
|
$deliverableQty = GETPOST($inputName, 'int');
|
|
}
|
|
|
|
$tooltipClass = $tooltipTitle = '';
|
|
if (!empty($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) {
|
|
$tooltipClass = ' classfortooltip';
|
|
$tooltipTitle = $langs->trans('StockQuantitiesAlreadyAllocatedOnPreviousLines') . ' : ' . $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)];
|
|
} else {
|
|
$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)] = 0;
|
|
}
|
|
$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)] = $deliverableQty + $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)];
|
|
|
|
print '<!-- subj=' . $subj . '/' . $nbofsuggested . ' --><tr ' . ((($subj + 1) == $nbofsuggested) ? 'oddeven' : '') . '>';
|
|
print '<td colspan="3" ></td><td class="center">';
|
|
$qtylValue = $deliverableQty;
|
|
if (getDolGlobalBool('SHIPMENT_DONT_PREFILL_QTY', false)) {
|
|
$qtylValue = '';
|
|
}
|
|
print '<input class="qtyl ' . $tooltipClass . ' right" title="' . $tooltipTitle . '" name="qtyl' . $indiceAsked . '_' . $subj . '" id="qtyl' . $indiceAsked . '_' . $subj . '" type="text" size="4" value="' . $qtylValue . '">';
|
|
print '</td>';
|
|
|
|
print '<!-- Show details of lot -->';
|
|
print '<td class="left">';
|
|
|
|
print $staticwarehouse->getNomUrl(0) . ' / ';
|
|
|
|
print '<input name="batchl' . $indiceAsked . '_' . $subj . '" type="hidden" value="' . $dbatch->id . '">';
|
|
|
|
$detail = '';
|
|
$detail .= $langs->trans("Batch") . ': ' . $dbatch->batch;
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY') && !empty($dbatch->sellby)) {
|
|
$detail .= ' - ' . $langs->trans("SellByDate") . ': ' . dol_print_date($dbatch->sellby, "day");
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY') && !empty($dbatch->eatby)) {
|
|
$detail .= ' - ' . $langs->trans("EatByDate") . ': ' . dol_print_date($dbatch->eatby, "day");
|
|
}
|
|
$detail .= ' - ' . $langs->trans("Qty") . ': ' . $dbatch->qty;
|
|
$detail .= '<br>';
|
|
print $detail;
|
|
|
|
$quantityToBeDelivered -= $deliverableQty;
|
|
if ($quantityToBeDelivered < 0) {
|
|
$quantityToBeDelivered = 0;
|
|
}
|
|
$subj++;
|
|
print '</td>';
|
|
if (getDolGlobalInt('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td>' . dol_print_date($dbatch->context['stock_entry_date'], 'day') . '</td>'; //StockEntrydate
|
|
}
|
|
print '</tr>';
|
|
}
|
|
} else {
|
|
print '<!-- Case there is no details of lot at all -->';
|
|
print '<tr class="oddeven"><td colspan="3"></td><td class="center">';
|
|
print '<input class="qtyl right" name="qtyl' . $indiceAsked . '_' . $subj . '" id="qtyl' . $indiceAsked . '_' . $subj . '" type="text" size="4" value="0" disabled="disabled"> ';
|
|
print '</td>';
|
|
|
|
print '<td class="left">';
|
|
print img_warning() . ' ' . $langs->trans("NoProductToShipFoundIntoStock", $staticwarehouse->label);
|
|
print '</td>';
|
|
if (getDolGlobalInt('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print '</tr>';
|
|
}
|
|
}
|
|
} else {
|
|
// ship from multiple locations
|
|
if (!isModEnabled('productbatch') || !$product->hasbatch()) {
|
|
print '<!-- Case warehouse not already known and product does not need lot -->';
|
|
print '<td></td><td></td>';
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print '</tr>' . "\n"; // end line and start a new one for each warehouse
|
|
|
|
print '<input name="idl' . $indiceAsked . '" type="hidden" value="' . $line->id . '">';
|
|
$subj = 0;
|
|
// Define nb of lines suggested for this order line
|
|
$nbofsuggested = 0;
|
|
|
|
foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) {
|
|
if ($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) {
|
|
$nbofsuggested++;
|
|
}
|
|
}
|
|
$tmpwarehouseObject = new Entrepot($db);
|
|
foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) { // $stock_warehouse is product_stock
|
|
$var = $subj % 2;
|
|
if (!empty($warehousePicking) && !in_array($warehouse_id, $warehousePicking)) {
|
|
// if a warehouse was selected by user, picking is limited to this warehouse and his children
|
|
continue;
|
|
}
|
|
|
|
$tmpwarehouseObject->fetch($warehouse_id);
|
|
if ($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) {
|
|
$stock = +$stock_warehouse->real; // Convert it to number
|
|
$deliverableQty = min($quantityToBeDelivered, $stock);
|
|
$deliverableQty = max(0, $deliverableQty);
|
|
// Quantity to send
|
|
print '<!-- subj=' . $subj . '/' . $nbofsuggested . ' --><tr ' . ((($subj + 1) == $nbofsuggested) ? 'oddeven' : '') . '>';
|
|
print '<td colspan="3" ></td><td class="center"><!-- qty to ship (no lot management for product line indiceAsked=' . $indiceAsked . ') -->';
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES') || getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) {
|
|
if (isset($alreadyQtySetted[$line->fk_product][intval($warehouse_id)])) {
|
|
$deliverableQty = min($quantityToBeDelivered, $stock - $alreadyQtySetted[$line->fk_product][intval($warehouse_id)]);
|
|
} else {
|
|
if (!isset($alreadyQtySetted[$line->fk_product])) {
|
|
$alreadyQtySetted[$line->fk_product] = array();
|
|
}
|
|
|
|
$deliverableQty = min($quantityToBeDelivered, $stock);
|
|
}
|
|
|
|
if ($deliverableQty < 0) {
|
|
$deliverableQty = 0;
|
|
}
|
|
|
|
$tooltipClass = $tooltipTitle = '';
|
|
if (!empty($alreadyQtySetted[$line->fk_product][intval($warehouse_id)])) {
|
|
$tooltipClass = ' classfortooltip';
|
|
$tooltipTitle = $langs->trans('StockQuantitiesAlreadyAllocatedOnPreviousLines') . ' : ' . $alreadyQtySetted[$line->fk_product][intval($warehouse_id)];
|
|
} else {
|
|
$alreadyQtySetted[$line->fk_product][intval($warehouse_id)] = 0;
|
|
}
|
|
|
|
$alreadyQtySetted[$line->fk_product][intval($warehouse_id)] = $deliverableQty + $alreadyQtySetted[$line->fk_product][intval($warehouse_id)];
|
|
|
|
$inputName = 'qtyl' . $indiceAsked . '_' . $subj;
|
|
if (GETPOSTISSET($inputName)) {
|
|
$deliverableQty = GETPOSTINT($inputName);
|
|
}
|
|
$qtylValue = $deliverableQty;
|
|
if (getDolGlobalBool('SHIPMENT_DONT_PREFILL_QTY', false)) {
|
|
$qtylValue = '';
|
|
}
|
|
print '<input class="qtyl' . $tooltipClass . ' right" title="' . $tooltipTitle . '" name="qtyl' . $indiceAsked . '_' . $subj . '" id="qtyl' . $indiceAsked . '" type="text" size="4" value="' . $qtylValue . '">';
|
|
print '<input name="ent1' . $indiceAsked . '_' . $subj . '" type="hidden" value="' . $warehouse_id . '">';
|
|
} else {
|
|
if (getDolGlobalString('SHIPMENT_GETS_ALL_ORDER_PRODUCTS')) {
|
|
print '<input name="qtyl' . $indiceAsked . '_' . $subj . '" id="qtyl' . $indiceAsked . '" type="hidden" value="0">';
|
|
}
|
|
|
|
print $langs->trans("NA");
|
|
}
|
|
print '</td>';
|
|
|
|
// Stock
|
|
print '<td class="left">';
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
|
|
if ($product->stockable_product == Product::ENABLED_STOCK || $productChildrenNb > 0) {
|
|
print $tmpwarehouseObject->getNomUrl(0) . ' ';
|
|
if ($productChildrenNb <= 0) {
|
|
print '<!-- Show details of stock -->';
|
|
print '(' . $stock . ')';
|
|
}
|
|
} else {
|
|
print img_warning() . ' ' . $langs->trans('StockDisabled');
|
|
}
|
|
} else {
|
|
print '<span class="opacitymedium">(' . $langs->trans("Service") . ')</span>';
|
|
}
|
|
print '</td>';
|
|
$quantityToBeDelivered -= $deliverableQty;
|
|
if ($quantityToBeDelivered < 0) {
|
|
$quantityToBeDelivered = 0;
|
|
}
|
|
$subj++;
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print "</tr>\n";
|
|
}
|
|
}
|
|
// Show subproducts of product (not recommended)
|
|
if (getDolGlobalString('PRODUIT_SOUSPRODUITS') && $line->fk_product > 0) {
|
|
$product->get_sousproduits_arbo();
|
|
$prods_arbo = $product->get_arbo_each_prod($qtyProdCom);
|
|
if (count($prods_arbo) > 0) {
|
|
foreach ($prods_arbo as $key => $value) {
|
|
//print $value[0];
|
|
$img = '';
|
|
if ($value['stock'] < $value['stock_alert']) {
|
|
$img = img_warning($langs->trans("StockTooLow"));
|
|
}
|
|
print '<tr class"oddeven"><td>';
|
|
print " ->
|
|
<a href=\"" . DOL_URL_ROOT . "/product/card.php?id=" . $value['id'] . "\">" . $value['fullpath'] . "
|
|
</a> (" . $value['nb'] . ")</td><td class=\"center\"> " . $value['nb_total'] . "</td><td> </td><td> </td>
|
|
<td class=\"center\">" . $value['stock'] . " " . $img . "</td>";
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print "</tr>";
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
print '<!-- Case warehouse not already known and product need lot -->';
|
|
print '<td></td><td></td>';
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print '</tr>'; // end line and start a new one for lot/serial
|
|
|
|
$subj = 0;
|
|
print '<input name="idl' . $indiceAsked . '" type="hidden" value="' . $line->id . '">';
|
|
|
|
$tmpwarehouseObject = new Entrepot($db);
|
|
$productlotObject = new Productlot($db);
|
|
|
|
// Define nb of lines suggested for this order line
|
|
$nbofsuggested = 0;
|
|
foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) {
|
|
if (($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) && (!empty($stock_warehouse->detail_batch))) {
|
|
$nbofsuggested += count($stock_warehouse->detail_batch);
|
|
}
|
|
}
|
|
|
|
foreach ($product->stock_warehouse as $warehouse_id => $stock_warehouse) {
|
|
$var = $subj % 2;
|
|
if (!empty($warehousePicking) && !in_array($warehouse_id, $warehousePicking)) {
|
|
// if a warehouse was selected by user, picking is limited to this warehouse and his children
|
|
continue;
|
|
}
|
|
|
|
$tmpwarehouseObject->fetch($warehouse_id);
|
|
if (($stock_warehouse->real > 0 || !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) && (!empty($stock_warehouse->detail_batch))) {
|
|
foreach ($stock_warehouse->detail_batch as $dbatch) {
|
|
$batchStock = +$dbatch->qty; // To get a numeric
|
|
if (isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) {
|
|
$deliverableQty = min($quantityToBeDelivered, $batchStock - $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)]);
|
|
} else {
|
|
if (!isset($alreadyQtyBatchSetted[$line->fk_product])) {
|
|
$alreadyQtyBatchSetted[$line->fk_product] = array();
|
|
}
|
|
|
|
if (!isset($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch])) {
|
|
$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch] = array();
|
|
}
|
|
|
|
$deliverableQty = min($quantityToBeDelivered, $batchStock);
|
|
}
|
|
|
|
if ($deliverableQty < 0) {
|
|
$deliverableQty = 0;
|
|
}
|
|
|
|
$inputName = 'qtyl' . $indiceAsked . '_' . $subj;
|
|
if (GETPOSTISSET($inputName)) {
|
|
$deliverableQty = GETPOSTINT($inputName);
|
|
}
|
|
|
|
$tooltipClass = $tooltipTitle = '';
|
|
if (!empty($alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)])) {
|
|
$tooltipClass = ' classfortooltip';
|
|
$tooltipTitle = $langs->trans('StockQuantitiesAlreadyAllocatedOnPreviousLines') . ' : ' . $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)];
|
|
} else {
|
|
$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)] = 0;
|
|
}
|
|
$alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)] = $deliverableQty + $alreadyQtyBatchSetted[$line->fk_product][$dbatch->batch][intval($warehouse_id)];
|
|
|
|
print '<!-- subj=' . $subj . '/' . $nbofsuggested . ' --><tr ' . ((($subj + 1) == $nbofsuggested) ? 'oddeven' : '') . '><td colspan="3"></td><td class="center">';
|
|
$qtylValue = $deliverableQty;
|
|
if (getDolGlobalBool('SHIPMENT_DONT_PREFILL_QTY', false)) {
|
|
$qtylValue = '';
|
|
}
|
|
print '<input class="qtyl right ' . $tooltipClass . '" title="' . $tooltipTitle . '" name="' . $inputName . '" id="' . $inputName . '" type="text" size="4" value="' . $qtylValue . '">';
|
|
print '</td>';
|
|
|
|
print '<td class="left">';
|
|
|
|
print $tmpwarehouseObject->getNomUrl(0) . ' / ';
|
|
|
|
print '<!-- Show details of lot -->';
|
|
print '<input name="batchl' . $indiceAsked . '_' . $subj . '" type="hidden" value="' . $dbatch->id . '">';
|
|
print '<input name="entl' . $indiceAsked . '_'.$subj.'" type="hidden" value="' . $tmpwarehouseObject->id . '">';
|
|
|
|
//print '|'.$line->fk_product.'|'.$dbatch->batch.'|<br>';
|
|
print $langs->trans("Batch") . ': ';
|
|
$result = $productlotObject->fetch(0, $line->fk_product, $dbatch->batch);
|
|
if ($result > 0) {
|
|
print $productlotObject->getNomUrl(1);
|
|
} else {
|
|
print $langs->trans("TableLotIncompleteRunRepairWithParamStandardEqualConfirmed");
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY') && !empty($dbatch->sellby)) {
|
|
print ' - ' . $langs->trans("SellByDate") . ': ' . dol_print_date($dbatch->sellby, "day");
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY') && !empty($dbatch->eatby)) {
|
|
print ' - ' . $langs->trans("EatByDate") . ': ' . dol_print_date($dbatch->eatby, "day");
|
|
}
|
|
print ' (' . $dbatch->qty . ')';
|
|
$quantityToBeDelivered -= $deliverableQty;
|
|
if ($quantityToBeDelivered < 0) {
|
|
$quantityToBeDelivered = 0;
|
|
}
|
|
//dol_syslog('deliverableQty = '.$deliverableQty.' batchStock = '.$batchStock);
|
|
$subj++;
|
|
print '</td>';
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td class="left">' . dol_print_date($dbatch->context['stock_entry_date'], 'day') . '</td>';
|
|
}
|
|
print '</tr>';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ($subj == 0) { // Line not shown yet, we show it
|
|
$warehouse_selected_id = GETPOSTINT('entrepot_id');
|
|
|
|
print '<!-- line not shown yet, we show it -->';
|
|
print '<tr class="oddeven"><td colspan="3"></td><td class="center">';
|
|
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
|
|
$disabled = '';
|
|
$alt = '';
|
|
if (isModEnabled('productbatch') && $product->hasbatch()) {
|
|
$disabled = 'disabled="disabled"';
|
|
$alt = 'Product need serial or batch number';
|
|
}
|
|
if ($warehouse_selected_id <= 0) { // We did not force a given warehouse, so we won't have no warehouse to change qty.
|
|
$disabled = 'disabled="disabled"';
|
|
}
|
|
// finally we overwrite the input with the product status stockable_product if it's disabled
|
|
if ($product->stockable_product == Product::ENABLED_STOCK) {
|
|
$disabled = '';
|
|
}
|
|
print '<input class="qtyl right" name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="0"'.($disabled ? ' '.$disabled : '').($alt ? ' title="'.dolPrintHTMLForAttribute($alt).'"' : '').'> ';
|
|
if (empty($disabled) && (!getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER') || $product->stockable_product == Product::DISABLED_STOCK)) {
|
|
print '<input name="ent1' . $indiceAsked . '_' . $subj . '" type="hidden" value="' . $warehouse_selected_id . '">';
|
|
}
|
|
} elseif ($line->product_type == Product::TYPE_SERVICE && getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) {
|
|
$disabled = '';
|
|
if (isModEnabled('productbatch') && $product->hasbatch()) {
|
|
$disabled = 'disabled="disabled"';
|
|
}
|
|
if ($warehouse_selected_id <= 0) { // We did not force a given warehouse, so we won't have no warehouse to change qty.
|
|
$disabled = 'disabled="disabled"';
|
|
}
|
|
print '<input class="qtyl right" name="qtyl'.$indiceAsked.'_'.$subj.'" id="qtyl'.$indiceAsked.'_'.$subj.'" type="text" size="4" value="'.$quantityToBeDelivered.'"'.($disabled ? ' '.$disabled : '').'> ';
|
|
if (empty($disabled) && !getDolGlobalInt('STOCK_DISALLOW_NEGATIVE_TRANSFER')) {
|
|
print '<input name="ent1' . $indiceAsked . '_' . $subj . '" type="hidden" value="' . $warehouse_selected_id . '">';
|
|
}
|
|
} else {
|
|
print $langs->trans("NA");
|
|
}
|
|
print '</td>';
|
|
|
|
print '<td class="left">';
|
|
if ($line->product_type == Product::TYPE_PRODUCT || getDolGlobalString('STOCK_SUPPORTS_SERVICES')) {
|
|
// product may use stock management
|
|
if (($warehouse_selected_id > 0 && $product->stockable_product == Product::ENABLED_STOCK)) {
|
|
$warehouseObject = new Entrepot($db);
|
|
$warehouseObject->fetch($warehouse_selected_id);
|
|
print img_warning() . ' ' . $langs->trans("NoProductToShipFoundIntoStock", $warehouseObject->label);
|
|
} else {
|
|
if ($line->fk_product) {
|
|
if ($product->stockable_product != Product::ENABLED_STOCK) {
|
|
print img_warning() . ' ' . $langs->trans('StockDisabled');
|
|
} else {
|
|
print img_warning() . ' ' . $langs->trans('StockTooLow');
|
|
}
|
|
} else {
|
|
print '';
|
|
}
|
|
}
|
|
} else {
|
|
print '<span class="opacitymedium">(' . $langs->trans("Service") . ')</span>';
|
|
}
|
|
print '</td>';
|
|
if (getDolGlobalString('SHIPPING_DISPLAY_STOCK_ENTRY_DATE')) {
|
|
print '<td></td>';
|
|
} //StockEntrydate
|
|
print '</tr>';
|
|
}
|
|
}
|
|
} elseif (empty($reshook) && $line->special_code == SUBTOTALS_SPECIAL_CODE && !in_array($line->id, $title_lines_to_disable)) {
|
|
require dol_buildpath('/core/tpl/subtotalline_select.tpl.php');
|
|
}
|
|
|
|
$indiceAsked++;
|
|
}
|
|
|
|
print "</table>";
|
|
print '</div>';
|
|
|
|
print '<br>';
|
|
|
|
print $form->buttonsSaveCancel("Create");
|
|
|
|
print '</form>';
|
|
|
|
print '<br>';
|
|
} else {
|
|
dol_print_error($db);
|
|
}
|
|
}
|
|
} elseif ($object->id > 0) {
|
|
'@phan-var-force Expedition $object'; // Need to force it (type overridden earlier)
|
|
|
|
// Edit and view mode
|
|
|
|
$lines = $object->lines;
|
|
|
|
$num_prod = count($lines);
|
|
|
|
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 (old $object->commande, $object->propal, ...)
|
|
}
|
|
|
|
$soc = new Societe($db);
|
|
$soc->fetch($object->socid);
|
|
|
|
$res = $object->fetch_optionals();
|
|
|
|
$head = shipping_prepare_head($object);
|
|
print dol_get_fiche_head($head, 'shipping', $langs->trans("Shipment"), -1, $object->picto);
|
|
|
|
$formconfirm = '';
|
|
|
|
// Confirm deletion
|
|
if ($action == 'delete') {
|
|
$formquestion = array();
|
|
if ($object->status == Expedition::STATUS_CLOSED && getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_CLOSE')) {
|
|
$formquestion = array(
|
|
array(
|
|
'label' => $langs->trans('ShipmentIncrementStockOnDelete'),
|
|
'name' => 'alsoUpdateStock',
|
|
'type' => 'checkbox',
|
|
'value' => 0
|
|
),
|
|
);
|
|
}
|
|
$formconfirm = $form->formconfirm(
|
|
$_SERVER['PHP_SELF'] . '?id=' . $object->id,
|
|
$langs->trans('DeleteSending'),
|
|
$langs->trans("ConfirmDeleteSending", $object->ref),
|
|
'confirm_delete',
|
|
$formquestion,
|
|
0,
|
|
1
|
|
);
|
|
}
|
|
|
|
// Confirm delete of subtotal line
|
|
if ($action == 'ask_subtotal_deleteline') {
|
|
$lineid = GETPOSTINT('lineid');
|
|
$langs->load("subtotals");
|
|
$title = "DeleteSubtotalLine";
|
|
$question = "ConfirmDeleteSubtotalLine";
|
|
if (GETPOST('type') == 'title') {
|
|
$formconfirm = array(array('type' => 'checkbox', 'name' => 'deletecorrespondingsubtotalline', 'label' => $langs->trans("DeleteCorrespondingSubtotalLine"), 'value' => 0));
|
|
$title = "DeleteTitleLine";
|
|
$question = "ConfirmDeleteTitleLine";
|
|
}
|
|
$formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans($title), $langs->trans($question), 'confirm_delete_subtotalline', $formconfirm, 'no', 1);
|
|
}
|
|
|
|
// Confirm 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("ConfirmValidateSending", $numref);
|
|
if (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) {
|
|
$text .= '<br>' . img_picto('', 'movement', 'class="pictofixedwidth"') . $langs->trans("StockMovementWillBeRecorded") . '.';
|
|
} elseif (getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT_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('SHIPPING_VALIDATE', $object->socid, $object);
|
|
}
|
|
|
|
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'].'?id='.$object->id, $langs->trans('ValidateSending'), $text, 'confirm_valid', '', 0, 1, 260);
|
|
}
|
|
|
|
// Confirm cancellation
|
|
if ($action == 'cancel') {
|
|
$formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?id=' . $object->id, $langs->trans('CancelSending'), $langs->trans("ConfirmCancelSending", $object->ref), 'confirm_cancel', '', 0, 1);
|
|
}
|
|
|
|
// Confirm sign
|
|
if ($action == 'sign') {
|
|
$text = $langs->trans('ConfirmSignShipping');
|
|
if (isModEnabled('notification')) {
|
|
require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
|
|
$notify = new Notify($db);
|
|
$text .= '<br>';
|
|
$text .= $notify->confirmMessage('SHIPPING_MODIFY', $object->socid, $object);
|
|
}
|
|
$formquestion = [];
|
|
$formquestion[] = [
|
|
'type' => 'select',
|
|
'name' => 'signed_status',
|
|
'select_show_empty' => 0,
|
|
'label' => '<span class="fieldrequired">' . $langs->trans('SignStatus') . '</span>',
|
|
'values' => $object->getSignedStatusLocalisedArray()
|
|
];
|
|
$formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('SignShipping'), $text, 'confirm_sign', $formquestion, 0, 1);
|
|
}
|
|
|
|
// Confirm unsign
|
|
if ($action == 'unsign') {
|
|
$text = $langs->trans('ConfirmUnsignShipping');
|
|
if (isModEnabled('notification')) {
|
|
require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
|
|
$notify = new Notify($db);
|
|
$text .= '<br>';
|
|
$text .= $notify->confirmMessage('SHIPPING_MODIFY', $object->socid, $object);
|
|
}
|
|
$formconfirm = $form->formconfirm(dolBuildUrl($_SERVER["PHP_SELF"], ['id' => $object->id]), $langs->trans('UnsignShipping'), $text, 'confirm_unsign', '', 0, 1);
|
|
}
|
|
|
|
// Call Hook 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 (!empty($typeobject) && $typeobject === 'commande' && is_object($object->origin_object) && $object->origin_object->id && isModEnabled('order')) {
|
|
$objectsrc = new Commande($db);
|
|
$objectsrc->fetch($object->origin_object->id);
|
|
}
|
|
if (!empty($typeobject) && $typeobject === 'propal' && is_object($object->origin_object) && $object->origin_object->id && isModEnabled("propal")) {
|
|
$objectsrc = new Propal($db);
|
|
$objectsrc->fetch($object->origin_object->id);
|
|
}
|
|
|
|
// Shipment card
|
|
$linkback = '<a href="' . DOL_URL_ROOT . '/expedition/list.php?restore_lastsearch_values=1' . (!empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
|
|
$morehtmlref = '<div class="refidno">';
|
|
// Ref customer shipment
|
|
$morehtmlref .= $form->editfieldkey("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('expedition', 'creer'), 'string', '', 0, 1);
|
|
$morehtmlref .= $form->editfieldval("RefCustomer", 'ref_customer', $object->ref_customer, $object, $user->hasRight('expedition', 'creer'), 'string' . (isset($conf->global->THIRDPARTY_REF_INPUT_SIZE) ? ':' . getDolGlobalString('THIRDPARTY_REF_INPUT_SIZE') : ''), '', 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('SHIPMENT_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 tableforfield centpercent">';
|
|
|
|
// Linked documents
|
|
if (!empty($typeobject) && $typeobject == 'commande' && $object->origin_object->id && isModEnabled('order')) {
|
|
print '<tr><td>';
|
|
print $langs->trans("RefOrder") . '</td>';
|
|
print '<td>';
|
|
print $objectsrc->getNomUrl(1, 'commande');
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
}
|
|
if (!empty($typeobject) && $typeobject == 'propal' && $object->origin_object->id && isModEnabled("propal")) {
|
|
print '<tr><td>';
|
|
print $langs->trans("RefProposal") . '</td>';
|
|
print '<td>';
|
|
print $objectsrc->getNomUrl(1, 'expedition');
|
|
print "</td>\n";
|
|
print '</tr>';
|
|
}
|
|
|
|
// Date creation
|
|
print '<tr><td class="titlefieldmiddle">' . $langs->trans("DateCreation") . '</td>';
|
|
print '<td>' . dol_print_date($object->date_creation, "dayhour") . "</td>\n";
|
|
print '</tr>';
|
|
|
|
// Delivery date planned
|
|
print '<tr><td height="10">';
|
|
print '<table class="nobordernopadding centpercent"><tr><td>';
|
|
print $langs->trans('DateDeliveryPlanned');
|
|
print '</td>';
|
|
if ($action != 'editdate_livraison') {
|
|
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>';
|
|
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 smallpaddingimp" value="' . $langs->trans('Modify') . '">';
|
|
print '</form>';
|
|
} else {
|
|
print $object->date_delivery ? dol_print_date($object->date_delivery, 'dayhour') : ' ';
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Delivery sending date
|
|
print '<tr><td height="10">';
|
|
print '<table class="nobordernopadding centpercent"><tr><td>';
|
|
print $langs->trans('DateShipping');
|
|
print '</td>';
|
|
if ($action != 'editdate_shipping') {
|
|
print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editdate_shipping&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->trans('SetShippingDate'), 1) . '</a></td>';
|
|
}
|
|
print '</tr></table>';
|
|
print '</td><td>';
|
|
if ($action == 'editdate_shipping') {
|
|
print '<form name="setdate_shipping" 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_shipping">';
|
|
print $form->selectDate($object->date_shipping ? $object->date_shipping : -1, 'ship_', 1, 1, 0, "setdate_shipping", 1, 0);
|
|
print '<input type="submit" class="button button-edit smallpaddingimp" value="' . $langs->trans('Modify') . '">';
|
|
print '</form>';
|
|
} else {
|
|
print $object->date_shipping ? dol_print_date($object->date_shipping, 'dayhour') : ' ';
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
|
|
// Weight
|
|
print '<tr><td>';
|
|
print $form->editfieldkey("Weight", 'trueWeight', $object->trueWeight, $object, $user->hasRight('expedition', 'creer'));
|
|
print '</td><td>';
|
|
|
|
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" class="width50 valignmiddle">';
|
|
print $formproduct->selectMeasuringUnits("weight_units", "weight", (string) $object->weight_units, 0, 2, 'maxwidth125 valignmiddle');
|
|
print ' <input class="button smallpaddingimp valignmiddle" name="modify" value="' . $langs->trans("Modify") . '" type="submit">';
|
|
print ' <input class="button button-cancel smallpaddingimp valignmiddle" 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', $object->trueWidth, $object, $user->hasRight('expedition', 'creer')) . '</td><td>';
|
|
print $form->editfieldval("Width", 'trueWidth', $object->trueWidth, $object, $user->hasRight('expedition', 'creer'));
|
|
print ($object->trueWidth && $object->width_units != '') ? ' ' . measuringUnitString(0, "size", $object->width_units) : '';
|
|
print '</td></tr>';
|
|
|
|
// Height
|
|
print '<tr><td>' . $form->editfieldkey("Height", 'trueHeight', $object->trueHeight, $object, $user->hasRight('expedition', 'creer')) . '</td><td>';
|
|
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" class="width50">';
|
|
print $formproduct->selectMeasuringUnits("size_units", "size", $object->size_units, 0, 2);
|
|
print ' <input class="button smallpaddingimp" name="modify" value="' . $langs->trans("Modify") . '" type="submit">';
|
|
print ' <input class="button button-cancel smallpaddingimp" 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', $object->trueDepth, $object, $user->hasRight('expedition', 'creer')) . '</td><td>';
|
|
print $form->editfieldval("Depth", 'trueDepth', $object->trueDepth, $object, $user->hasRight('expedition', '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>';
|
|
$calculatedVolume = 0;
|
|
$volumeUnit = 0;
|
|
if ($object->trueWidth && $object->trueHeight && $object->trueDepth) {
|
|
$calculatedVolume = ($object->trueWidth * $object->trueHeight * $object->trueDepth);
|
|
$volumeUnit = $object->size_units * 3;
|
|
}
|
|
// If sending 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">';
|
|
|
|
// Sending method
|
|
print '<tr><td>';
|
|
print '<table class="nobordernopadding centpercent"><tr><td>';
|
|
print $langs->trans('SendingMethod');
|
|
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('SetSendingMethod'), 1) . '</a></td>';
|
|
}
|
|
print '</tr></table>';
|
|
print '</td><td>';
|
|
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 smallpaddingimp" 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="titlefieldmiddle">' . $form->editfieldkey("TrackingNumber", 'tracking_number', $object->tracking_number, $object, $user->hasRight('expedition', 'creer')) . '</td><td>';
|
|
print $form->editfieldval("TrackingNumber", 'tracking_number', $object->tracking_url, $object, $user->hasRight('expedition', 'creer'), 'safehtmlstring', $object->tracking_number);
|
|
print '</td></tr>';
|
|
|
|
// Incoterms
|
|
if (isModEnabled('incoterm')) {
|
|
print '<tr><td>';
|
|
print '<table class="nobordernopadding centpercent"><tr><td>';
|
|
print $langs->trans('IncotermLabel');
|
|
print '<td><td class="right">';
|
|
if ($permissiontoadd) {
|
|
print '<a class="editfielda" href="' . DOL_URL_ROOT . '/expedition/card.php?id=' . $object->id . '&action=editincoterm&token=' . newToken() . '">' . img_edit() . '</a>';
|
|
} else {
|
|
print ' ';
|
|
}
|
|
print '</td></tr></table>';
|
|
print '</td>';
|
|
print '<td>';
|
|
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>';
|
|
}
|
|
|
|
// Other attributes
|
|
$parameters = array();
|
|
$reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
|
|
print $hookmanager->resPrint;
|
|
|
|
print "</table>";
|
|
|
|
print '</div>';
|
|
print '</div>';
|
|
|
|
print '<div class="clearboth"></div>';
|
|
|
|
print dol_get_fiche_end();
|
|
|
|
|
|
/*
|
|
* Lines of simple shipment
|
|
*/
|
|
if (!$origin && getDolGlobalString('SHIPMENT_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 == 0) {
|
|
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'), 1, '/expedition/tpl');
|
|
}
|
|
|
|
// Form to add new line
|
|
if ($object->status == 0 && $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(1, $mysoc, $soc);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!empty($object->lines) || ($object->status == $object::STATUS_DRAFT && $permissiontoadd && $action != 'selectlines' && $action != 'editline')) {
|
|
print '</table>';
|
|
}
|
|
print '</div>';
|
|
|
|
print "</form>\n";
|
|
}
|
|
}
|
|
|
|
// Lines of products of origin
|
|
if (!empty($object->origin) && $object->origin_id > 0) {
|
|
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>';
|
|
if (!empty($conf->use_javascript_ajax) && $object->status == Expedition::STATUS_DRAFT && $usercancreate && $num_prod > 1) {
|
|
include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
|
|
}
|
|
|
|
print '<div class="div-table-responsive-no-min">';
|
|
print '<table class="noborder centpercent" id="tablelines" >';
|
|
print '<thead>';
|
|
print '<tr class="liste_titre">';
|
|
// Adds a line numbering column
|
|
if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
|
|
print '<td width="5" class="center linecolnum"> </td>';
|
|
}
|
|
// Product/Service
|
|
print '<td class="linecoldescription" >' . $langs->trans("Products") . '</td>';
|
|
// Qty
|
|
print '<td class="center linecolqty">' . $langs->trans("QtyOrdered") . '</td>';
|
|
if ($origin_id > 0) {
|
|
print '<td class="center linecolqtyinothershipments">' . $langs->trans("QtyInOtherShipments") . '</td>';
|
|
}
|
|
if ($action == 'editline') {
|
|
$editColspan = 3;
|
|
if (!isModEnabled('stock')) {
|
|
$editColspan--;
|
|
}
|
|
if (!isModEnabled('productbatch')) {
|
|
$editColspan--;
|
|
}
|
|
print '<td class="center linecoleditlineotherinfo" colspan="' . $editColspan . '">';
|
|
if ($object->status <= 1) {
|
|
print $langs->trans("QtyToShip");
|
|
} else {
|
|
print $langs->trans("QtyShipped");
|
|
}
|
|
if (isModEnabled('stock')) {
|
|
print ' - ' . $langs->trans("WarehouseSource");
|
|
}
|
|
if (isModEnabled('productbatch')) {
|
|
print ' - ' . $langs->trans("Batch");
|
|
}
|
|
print '</td>';
|
|
} else {
|
|
if ($object->status <= 1) {
|
|
print '<td class="center linecolqtytoship">' . $langs->trans("QtyToShip") . '</td>';
|
|
} else {
|
|
print '<td class="center linecolqtyshipped">' . $langs->trans("QtyShipped") . '</td>';
|
|
}
|
|
if (isModEnabled('stock')) {
|
|
print '<td class="left linecolwarehousesource">' . $langs->trans("WarehouseSource") . '</td>';
|
|
}
|
|
|
|
if (isModEnabled('productbatch')) {
|
|
print '<td class="left linecolbatch">' . $langs->trans("Batch") . '</td>';
|
|
}
|
|
}
|
|
print '<td class="center linecolweight">' . $langs->trans("CalculatedWeight") . '</td>';
|
|
print '<td class="center linecolvolume">' . $langs->trans("CalculatedVolume") . '</td>';
|
|
//print '<td class="center">'.$langs->trans("Size").'</td>';
|
|
if ($object->status == 0) {
|
|
print '<td class="linecoledit"></td>';
|
|
print '<td class="linecoldelete" width="10"></td>';
|
|
print '<td class="linecolmove"></td>';
|
|
}
|
|
print "</tr>\n";
|
|
print '</thead>';
|
|
|
|
$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 ($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.fk_unit, obj.date_start, obj.date_end, obj.special_code";
|
|
$sql .= ", ed.rowid as shipmentline_id, ed.qty as qty_shipped, ed.fk_expedition as expedition_id, ed.fk_elementdet, ed.fk_entrepot";
|
|
$sql .= ", e.rowid as shipment_id, e.ref as shipment_ref, e.date_creation, e.date_valid, e.date_delivery, e.date_expedition";
|
|
//if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= ", l.rowid as livraison_id, l.ref as livraison_ref, l.date_delivery, ld.qty as qty_received";
|
|
$sql .= ', p.label as product_label, p.ref, p.fk_product_type, p.rowid as prodid, p.tosell as product_tosell, p.tobuy as product_tobuy, p.tobatch as product_tobatch';
|
|
$sql .= ', p.description as product_desc';
|
|
$sql .= " FROM " . MAIN_DB_PREFIX . "expeditiondet as ed";
|
|
$sql .= ", " . MAIN_DB_PREFIX . "expedition as e";
|
|
$sql .= ", " . MAIN_DB_PREFIX . $origin . "det as obj";
|
|
//if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY')) $sql .= " LEFT JOIN ".MAIN_DB_PREFIX."delivery as l ON l.fk_expedition = e.rowid LEFT JOIN ".MAIN_DB_PREFIX."deliverydet as ld ON ld.fk_delivery = l.rowid AND obj.rowid = ld.fk_origin_line";
|
|
$sql .= " LEFT JOIN " . MAIN_DB_PREFIX . "product as p ON obj.fk_product = p.rowid";
|
|
$sql .= " WHERE e.entity IN (" . getEntity('expedition') . ")";
|
|
$sql .= " AND obj.fk_" . $origin . " = " . ((int) $origin_id);
|
|
$sql .= " AND obj.rowid = ed.fk_elementdet";
|
|
$sql .= " AND ed.fk_expedition = e.rowid";
|
|
//if ($filter) $sql.= $filter;
|
|
$sql .= " ORDER BY obj.fk_product";
|
|
|
|
dol_syslog("expedition/card.php get list of shipment 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->shipmentline_id] = array(
|
|
'shipment_ref' => $obj->shipment_ref,
|
|
'shipment_id' => $obj->shipment_id,
|
|
'warehouse' => $obj->fk_entrepot,
|
|
'qty_shipped' => $obj->qty_shipped,
|
|
'product_tosell' => $obj->product_tosell,
|
|
'product_tobuy' => $obj->product_tobuy,
|
|
'product_tobatch' => $obj->product_tobatch,
|
|
'date_valid' => $db->jdate($obj->date_valid),
|
|
'date_delivery' => $db->jdate($obj->date_delivery));
|
|
}
|
|
$i++;
|
|
}
|
|
}
|
|
//var_dump($alreadysent);
|
|
}
|
|
|
|
print '<tbody>';
|
|
|
|
// Loop on each product to send/sent
|
|
$conf->cache['product'] = array();
|
|
$conf->cache['warehouse'] = array();
|
|
for ($i = 0; $i < $num_prod; $i++) {
|
|
$parameters = array('i' => $i, 'line' => $lines[$i], 'line_id' => $line_id, 'num' => $num_prod, 'alreadysent' => $alreadysent, 'editColspan' => !empty($editColspan) ? $editColspan : 0, 'outputlangs' => $outputlangs);
|
|
$reshook = $hookmanager->executeHooks('printObjectLine', $parameters, $object, $action);
|
|
if ($reshook < 0) {
|
|
setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
|
|
}
|
|
|
|
if (empty($reshook) && $lines[$i]->product_type != "9") {
|
|
print '<!-- origin line id = ' . $lines[$i]->origin_line_id . ' -->'; // id of order line
|
|
print '<tr class="oddeven" id="row-' . $lines[$i]->id . '" data-id="' . $lines[$i]->id . '" data-element="' . $lines[$i]->element . '" >';
|
|
$line = $lines[$i];
|
|
$line->fetch_optionals();
|
|
|
|
// #
|
|
if (getDolGlobalString('MAIN_VIEW_LINE_NUMBER')) {
|
|
print '<td class="center linecolnum">' . ($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')) {
|
|
$product_id = $lines[$i]->fk_product;
|
|
if (!isset($conf->cache['product'][$product_id])) {
|
|
$prod = new Product($db);
|
|
$prod->fetch($product_id);
|
|
$conf->cache['product'][$product_id] = $prod;
|
|
} else {
|
|
$prod = $conf->cache['product'][$product_id];
|
|
}
|
|
$label = (!empty($prod->multilangs[$outputlangs->defaultlang]["label"])) ? $prod->multilangs[$outputlangs->defaultlang]["label"] : $lines[$i]->product_label;
|
|
} else {
|
|
$label = (!empty($lines[$i]->label) ? $lines[$i]->label : $lines[$i]->product_label);
|
|
}
|
|
|
|
print '<td class="linecoldescription">';
|
|
|
|
// Show product and description
|
|
$product_static->type = $lines[$i]->fk_product_type;
|
|
$product_static->id = $lines[$i]->fk_product;
|
|
$product_static->ref = $lines[$i]->ref;
|
|
$product_static->status = $lines[$i]->product_tosell;
|
|
$product_static->status_buy = $lines[$i]->product_tobuy;
|
|
$product_static->status_batch = $lines[$i]->product_tobatch;
|
|
|
|
$product_static->weight = $lines[$i]->weight;
|
|
$product_static->weight_units = $lines[$i]->weight_units;
|
|
$product_static->length = $lines[$i]->length;
|
|
$product_static->length_units = $lines[$i]->length_units;
|
|
$product_static->width = !empty($lines[$i]->width) ? $lines[$i]->width : 0;
|
|
$product_static->width_units = !empty($lines[$i]->width_units) ? $lines[$i]->width_units : 0;
|
|
$product_static->height = !empty($lines[$i]->height) ? $lines[$i]->height : 0;
|
|
$product_static->height_units = !empty($lines[$i]->height_units) ? $lines[$i]->height_units : 0;
|
|
$product_static->surface = $lines[$i]->surface;
|
|
$product_static->surface_units = $lines[$i]->surface_units;
|
|
$product_static->volume = $lines[$i]->volume;
|
|
$product_static->volume_units = $lines[$i]->volume_units;
|
|
$product_static->stockable_product = $lines[$i]->stockable_product;
|
|
|
|
$text = $product_static->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 : '', !empty($lines[$i]->date_end) ? $lines[$i]->date_end : '');
|
|
if (getDolGlobalInt('PRODUIT_DESC_IN_FORM_ACCORDING_TO_DEVICE')) {
|
|
print (!empty($lines[$i]->description) && $lines[$i]->description != $lines[$i]->product) ? '<br>' . dol_htmlentitiesbr($lines[$i]->description) : '';
|
|
}
|
|
$lineExtrafieldsHtml = $line->showOptionals($extrafields, ($action == 'editline' && $line->id == $line_id) ? 'edit' : 'view', array(), '', '', '1', 'line');
|
|
if (!empty($lineExtrafieldsHtml)) {
|
|
print '<div style="padding-top: 10px" id="extrafield_lines_area_' . $line->id . '" name="extrafield_lines_area_' . $line->id . '">';
|
|
print $lineExtrafieldsHtml;
|
|
print '</div>';
|
|
}
|
|
print "</td>\n";
|
|
} else {
|
|
print '<td class="linecoldescription" >';
|
|
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);
|
|
$lineExtrafieldsHtml = $line->showOptionals($extrafields, ($action == 'editline' && $line->id == $line_id) ? 'edit' : 'view', array(), '', '', '1', 'line');
|
|
if (!empty($lineExtrafieldsHtml)) {
|
|
print '<div style="padding-top: 10px" id="extrafield_lines_area_' . $line->id . '" name="extrafield_lines_area_' . $line->id . '">';
|
|
print $lineExtrafieldsHtml;
|
|
print '</div>';
|
|
}
|
|
print "</td>\n";
|
|
}
|
|
|
|
$unit_order = '';
|
|
if (getDolGlobalString('PRODUCT_USE_UNITS')) {
|
|
$unit_order = measuringUnitString((int) $lines[$i]->fk_unit);
|
|
}
|
|
|
|
// Qty ordered
|
|
print '<td class="center linecolqty">' . $lines[$i]->qty_asked . ' ' . $unit_order . '</td>';
|
|
|
|
// Qty in other shipments (with shipment and warehouse used)
|
|
if ($origin_id > 0) {
|
|
print '<td class="linecolqtyinothershipments center nowrap">';
|
|
$htmltooltip = '';
|
|
$qtyalreadysent = 0;
|
|
foreach ($alreadysent as $key => $val) {
|
|
if ($lines[$i]->fk_elementdet == $key) {
|
|
$j = 0;
|
|
foreach ($val as $shipmentline_id => $shipmentline_var) {
|
|
if ($shipmentline_var['shipment_id'] == $lines[$i]->fk_expedition) {
|
|
continue; // We want to show only "other shipments"
|
|
}
|
|
|
|
$j++;
|
|
if ($j > 1) {
|
|
$htmltooltip .= '<br>';
|
|
}
|
|
$shipment_static->fetch($shipmentline_var['shipment_id']);
|
|
$htmltooltip .= $shipment_static->getNomUrl(1, '', 0, 0, 1);
|
|
$htmltooltip .= ' - ' . $shipmentline_var['qty_shipped'];
|
|
$htmltooltip .= ' - ' . $langs->trans("DateValidation") . ' : ' . (empty($shipmentline_var['date_valid']) ? $langs->trans("Draft") : dol_print_date($shipmentline_var['date_valid'], 'dayhour'));
|
|
/*if (isModEnabled('stock') && $shipmentline_var['warehouse'] > 0) {
|
|
$warehousestatic->fetch($shipmentline_var['warehouse']);
|
|
$htmltext .= '<br>'.$langs->trans("FromLocation").' : '.$warehousestatic->getNomUrl(1, '', 0, 1);
|
|
}*/
|
|
//print ' '.$form->textwithpicto('', $htmltext, 1);
|
|
|
|
$qtyalreadysent += $shipmentline_var['qty_shipped'];
|
|
}
|
|
if ($j) {
|
|
$htmltooltip = $langs->trans("QtyInOtherShipments") . '...<br><br>' . $htmltooltip . '<br><input type="submit" name="dummyhiddenbuttontogetfocus" style="display:none" autofocus>';
|
|
}
|
|
}
|
|
}
|
|
print $form->textwithpicto((string) $qtyalreadysent, $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 centpercent">';
|
|
if (is_array($lines[$i]->detail_batch) && count($lines[$i]->detail_batch) > 0) {
|
|
print '<!-- case edit 1 -->';
|
|
$line = new ExpeditionLigne($db);
|
|
foreach ($lines[$i]->detail_batch as $detail_batch) {
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl right" name="qtyl' . $detail_batch->fk_expeditiondet . '_' . $detail_batch->id . '" id="qtyl' . $line_id . '_' . $detail_batch->id . '" type="text" size="4" value="' . $detail_batch->qty . '"></td>';
|
|
// Batch number management
|
|
if ($lines[$i]->entrepot_id == 0) {
|
|
// only show lot numbers from src warehouse when shipping from multiple warehouses
|
|
$line->fetch($detail_batch->fk_expeditiondet);
|
|
}
|
|
$entrepot_id = !empty($detail_batch->entrepot_id) ? $detail_batch->entrepot_id : $lines[$i]->entrepot_id;
|
|
print '<td>' . $formproduct->selectLotStock($detail_batch->fk_origin_stock, 'batchl' . $detail_batch->fk_expeditiondet . '_' . $detail_batch->fk_origin_stock, '', 1, 0, $lines[$i]->fk_product, $entrepot_id) . '</td>';
|
|
print '</tr>';
|
|
}
|
|
// add a 0 qty lot row to be able to add a lot
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl" name="qtyl' . $line_id . '_0" id="qtyl' . $line_id . '_0" type="text" size="4" value="0"></td>';
|
|
// Batch number management
|
|
print '<td>' . $formproduct->selectLotStock('', 'batchl' . $line_id . '_0', '', 1, 0, $lines[$i]->fk_product) . '</td>';
|
|
print '</tr>';
|
|
} elseif (isModEnabled('stock')) {
|
|
if ($lines[$i]->fk_product > 0) {
|
|
if ($lines[$i]->entrepot_id > 0) {
|
|
print '<!-- case edit 2 -->';
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl right" name="qtyl' . $line_id . '" id="qtyl' . $line_id . '" type="text" size="4" value="' . $lines[$i]->qty_shipped . '">' . $unit_order . '</td>';
|
|
// Warehouse source
|
|
print '<td>' . $formproduct->selectWarehouses($lines[$i]->entrepot_id, 'entl' . $line_id, '', 1, 0, $lines[$i]->fk_product, '', 1, 0, array(), 'minwidth200') . '</td>';
|
|
// Batch number management
|
|
print '<td>';
|
|
if (isModEnabled('productbatch')) {
|
|
print ' - ' . $langs->trans("NA");
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
} elseif (count($lines[$i]->details_entrepot) > 1) {
|
|
print '<!-- case edit 3 -->';
|
|
foreach ($lines[$i]->details_entrepot as $detail_entrepot) {
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl right" name="qtyl' . $detail_entrepot->line_id . '" id="qtyl' . $detail_entrepot->line_id . '" type="text" size="4" value="' . $detail_entrepot->qty_shipped . '">' . $unit_order . '</td>';
|
|
// Warehouse source
|
|
print '<td>' . $formproduct->selectWarehouses($detail_entrepot->entrepot_id, 'entl' . $detail_entrepot->line_id, '', 1, 0, $lines[$i]->fk_product, '', 1, 0, array(), 'minwidth200') . '</td>';
|
|
// Batch number management
|
|
print '<td>';
|
|
if (isModEnabled('productbatch')) {
|
|
print ' - ' . $langs->trans("NA");
|
|
}
|
|
print '</td>';
|
|
print '</tr>';
|
|
}
|
|
} elseif ($lines[$i]->product_type == Product::TYPE_SERVICE && getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) {
|
|
print '<!-- case edit 4 -->';
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl right" name="qtyl' . $line_id . '" id="qtyl' . $line_id . '" type="text" size="4" value="' . $lines[$i]->qty_shipped . '"></td>';
|
|
print '<td><span class="opacitymedium">(' . $langs->trans("Service") . ')</span></td>';
|
|
print '<td></td>';
|
|
print '</tr>';
|
|
} else {
|
|
print '<!-- case edit 5 -->';
|
|
print '<tr><td colspan="3">' . $langs->trans("ErrorStockIsNotEnough") . '</td></tr>';
|
|
}
|
|
} else {
|
|
print '<!-- case edit 6 -->';
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl right" name="qtyl' . $line_id . '" id="qtyl' . $line_id . '" type="text" size="4" value="' . $lines[$i]->qty_shipped . '">' . $unit_order . '</td>';
|
|
// Warehouse source
|
|
print '<td></td>';
|
|
// Batch number management
|
|
print '<td></td>';
|
|
print '</tr>';
|
|
}
|
|
} else { // both product batch and stock are not activated.
|
|
print '<!-- case edit 7 -->';
|
|
print '<tr>';
|
|
// Qty to ship or shipped
|
|
print '<td><input class="qtyl right" name="qtyl' . $line_id . '" id="qtyl' . $line_id . '" type="text" size="4" value="' . $lines[$i]->qty_shipped . '"></td>';
|
|
// Warehouse source
|
|
print '<td></td>';
|
|
// Batch number management
|
|
print '<td></td>';
|
|
print '</tr>';
|
|
}
|
|
|
|
print '</table></td>';
|
|
} else {
|
|
// Qty to ship or shipped
|
|
print '<td class="linecolqtytoship center">' . $lines[$i]->qty_shipped . ' ' . $unit_order . '</td>';
|
|
|
|
// Warehouse source
|
|
if (isModEnabled('stock')) {
|
|
print '<td class="linecolwarehousesource tdoverflowmax200">';
|
|
if ($lines[$i]->product_type == Product::TYPE_SERVICE && getDolGlobalString('SHIPMENT_SUPPORTS_SERVICES')) {
|
|
print '<span class="opacitymedium">(' . $langs->trans("Service") . ')</span>';
|
|
} elseif ($lines[$i]->entrepot_id > 0 && $lines[$i]->stockable_product == Product::ENABLED_STOCK) {
|
|
$warehouse_id = $lines[$i]->entrepot_id;
|
|
if (!isset($conf->cache['warehouse'][$warehouse_id])) {
|
|
$warehouse = new Entrepot($db);
|
|
$warehouse->fetch($warehouse_id);
|
|
$conf->cache['warehouse'][$warehouse_id] = $warehouse;
|
|
} else {
|
|
$warehouse = $conf->cache['warehouse'][$warehouse_id];
|
|
}
|
|
print $warehouse->getNomUrl(1);
|
|
} elseif (count($lines[$i]->details_entrepot) > 1) {
|
|
$detail = '';
|
|
foreach ($lines[$i]->details_entrepot as $detail_entrepot) {
|
|
$warehouse_id = $detail_entrepot->entrepot_id;
|
|
if ($warehouse_id > 0) {
|
|
if (!isset($conf->cache['warehouse'][$warehouse_id])) {
|
|
$warehouse = new Entrepot($db);
|
|
$warehouse->fetch($warehouse_id);
|
|
$conf->cache['warehouse'][$warehouse_id] = $warehouse;
|
|
} else {
|
|
$warehouse = $conf->cache['warehouse'][$warehouse_id];
|
|
}
|
|
$detail .= $langs->trans("DetailWarehouseFormat", $warehouse->label, $detail_entrepot->qty_shipped) . '<br>';
|
|
}
|
|
}
|
|
print $form->textwithtooltip(img_picto('', 'object_stock') . ' ' . $langs->trans("DetailWarehouseNumber"), $detail);
|
|
} elseif (count($lines[$i]->detail_children ?? []) > 1) {
|
|
$detail = '';
|
|
foreach ($lines[$i]->detail_children as $child_product_id => $child_stock_list) {
|
|
foreach ($child_stock_list as $warehouse_id => $total_qty) {
|
|
// get product from cache
|
|
$child_product_label = '';
|
|
if (!isset($conf->cache['product'][$child_product_id])) {
|
|
$child_product = new Product($db);
|
|
$child_product->fetch($child_product_id);
|
|
$conf->cache['product'][$child_product_id] = $child_product;
|
|
} else {
|
|
$child_product = $conf->cache['product'][$child_product_id];
|
|
}
|
|
$child_product_label = $child_product->ref . ' ' . $child_product->label;
|
|
|
|
// get warehouse from cache
|
|
if (!isset($conf->cache['warehouse'][$warehouse_id])) {
|
|
$child_warehouse = new Entrepot($db);
|
|
$child_warehouse->fetch($warehouse_id);
|
|
$conf->cache['warehouse'][$warehouse_id] = $child_warehouse;
|
|
} else {
|
|
$child_warehouse = $conf->cache['warehouse'][$warehouse_id];
|
|
}
|
|
$detail .= $langs->trans('DetailChildrenFormat', $child_product_label, $child_warehouse->label, price2num($total_qty, 'MS')) . '<br>';
|
|
}
|
|
}
|
|
print $form->textwithtooltip(img_picto('', 'object_stock') . ' ' . $langs->trans('DetailWarehouseNumber'), $detail);
|
|
}
|
|
print '</td>';
|
|
}
|
|
|
|
// Batch number management
|
|
if (isModEnabled('productbatch')) {
|
|
if (isset($lines[$i]->detail_batch)) {
|
|
print '<!-- Detail of lot -->';
|
|
print '<td class="linecolbatch">';
|
|
if ($lines[$i]->product_tobatch) {
|
|
$detail = '';
|
|
foreach ($lines[$i]->detail_batch as $dbatch) { // $dbatch is instance of ExpeditionLineBatch
|
|
$detail .= $langs->trans("Batch") . ': ' . $dbatch->batch;
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_SELLBY')) {
|
|
$detail .= ' - ' . $langs->trans("SellByDate") . ': ' . dol_print_date($dbatch->sellby, "day");
|
|
}
|
|
if (!getDolGlobalString('PRODUCT_DISABLE_EATBY')) {
|
|
$detail .= ' - ' . $langs->trans("EatByDate") . ': ' . dol_print_date($dbatch->eatby, "day");
|
|
}
|
|
$detail .= ' - ' . $langs->trans("Qty") . ': ' . $dbatch->qty;
|
|
$detail .= '<br>';
|
|
}
|
|
print $form->textwithtooltip(img_picto('', 'object_barcode') . ' ' . $langs->trans("DetailBatchNumber"), $detail);
|
|
} else {
|
|
print $langs->trans("NA");
|
|
}
|
|
print '</td>';
|
|
} else {
|
|
print '<td class="linecolbatch" ></td>';
|
|
}
|
|
}
|
|
}
|
|
|
|
// Weight
|
|
print '<td class="center linecolweight">';
|
|
if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
|
|
print $lines[$i]->weight * $lines[$i]->qty_shipped . ' ' . measuringUnitString(0, "weight", $lines[$i]->weight_units);
|
|
} else {
|
|
print ' ';
|
|
}
|
|
print '</td>';
|
|
|
|
// Volume
|
|
print '<td class="center linecolvolume">';
|
|
if ($lines[$i]->fk_product_type == Product::TYPE_PRODUCT) {
|
|
print $lines[$i]->volume * $lines[$i]->qty_shipped . ' ' . measuringUnitString(0, "volume", $lines[$i]->volume_units);
|
|
} else {
|
|
print ' ';
|
|
}
|
|
print '</td>';
|
|
|
|
// Size
|
|
//print '<td class="center">'.$lines[$i]->volume*$lines[$i]->qty_shipped.' '.measuringUnitString(0, "volume", $lines[$i]->volume_units).'</td>';
|
|
|
|
$showmovecol = ($object->status == Expedition::STATUS_DRAFT);
|
|
|
|
if ($action == 'editline' && $lines[$i]->id == $line_id) {
|
|
print '<td class="center" colspan="2" valign="middle">';
|
|
print '<input type="submit" class="button button-save" id="savelinebutton marginbottomonly" name="save" value="' . $langs->trans("Save") . '"><br>';
|
|
print '<input type="submit" class="button button-cancel" id="cancellinebutton" name="cancel" value="' . $langs->trans("Cancel") . '"><br>';
|
|
print '</td>';
|
|
if ($showmovecol) {
|
|
print '<td class="linecolmove tdlineupdown center"></td>';
|
|
}
|
|
} elseif ($showmovecol) {
|
|
$edit_url = $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=editline&token=' . newToken() . '&lineid=' . $lines[$i]->id;
|
|
if (getDolGlobalInt('PRODUIT_SOUSPRODUITS')) {
|
|
$product_id = $lines[$i]->fk_product;
|
|
if (!isset($conf->cache['product'][$product_id])) {
|
|
$product = new Product($db);
|
|
$product->fetch($product_id);
|
|
$conf->cache['product'][$product_id] = $product;
|
|
} else {
|
|
$product = $conf->cache['product'][$product_id];
|
|
}
|
|
|
|
if ($product->hasFatherOrChild(1)) {
|
|
$edit_url = dol_buildpath('/expedition/dispatch.php?id=' . $object->id, 1);
|
|
}
|
|
}
|
|
|
|
// edit-delete buttons
|
|
print '<td class="linecoledit center">';
|
|
print '<a class="editfielda reposition" href="' . $edit_url . '">' . 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>';
|
|
print '<td class="linecolmove tdlineupdown center">';
|
|
if ($usercancreate && $num_prod > 1) {
|
|
if ($i > 0) {
|
|
print '<a class="lineupdown" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=up&token=' . newToken() . '&rowid=' . $lines[$i]->id . '">' . img_up('default', 0, 'imgupforline') . '</a>';
|
|
}
|
|
if ($i < $num_prod - 1) {
|
|
print '<a class="lineupdown" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=down&token=' . newToken() . '&rowid=' . $lines[$i]->id . '">' . img_down('default', 0, 'imgdownforline') . '</a>';
|
|
}
|
|
}
|
|
print '</td>';
|
|
// Display lines extrafields
|
|
if (!empty($rowExtrafieldsStart)) {
|
|
print $rowExtrafieldsStart;
|
|
print $rowExtrafieldsView;
|
|
print $rowEnd;
|
|
}
|
|
}
|
|
print "</tr>";
|
|
} elseif (empty($reshook) && $lines[$i]->product_type == "9") {
|
|
$objectsrc = new OrderLine($db);
|
|
$objectsrc->fetch($lines[$i]->origin_line_id);
|
|
if ($objectsrc->special_code == SUBTOTALS_SPECIAL_CODE) {
|
|
$line = $lines[$i];
|
|
require dol_buildpath('/core/tpl/subtotal_expedition_view.tpl.php');
|
|
}
|
|
}
|
|
}
|
|
// TODO Show also lines ordered but not delivered
|
|
if (empty($num_prod)) {
|
|
print '<tr><td colspan="8"><span class="opacitymedium">' . $langs->trans("NoLineGoOnTabToAddSome", $langs->transnoentitiesnoconv("ShipmentDistribution")) . '</span></td></tr>';
|
|
}
|
|
|
|
print '</tbody>';
|
|
print "</table>\n";
|
|
print '</div>';
|
|
if ($action == 'editline') {
|
|
print "</form>\n";
|
|
}
|
|
|
|
$object->fetchObjectLinked($object->id, $object->element);
|
|
}
|
|
|
|
/*
|
|
* Boutons 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->status == Expedition::STATUS_DRAFT && $num_prod > 0) {
|
|
if ((!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'creer'))
|
|
|| (getDolGlobalString('MAIN_USE_ADVANCED_PERMS') && $user->hasRight('expedition', 'shipping_advance', 'validate'))
|
|
) {
|
|
print dolGetButtonAction('', $langs->trans('Validate'), 'default', $_SERVER["PHP_SELF"] . '?action=valid&token=' . newToken() . '&id=' . $object->id, '');
|
|
} else {
|
|
print dolGetButtonAction($langs->trans('NotAllowed'), $langs->trans('Validate'), 'default', $_SERVER['PHP_SELF'] . '#', '', false);
|
|
}
|
|
}
|
|
|
|
// 0=draft, 1=validated/delivered, 2=closed/delivered
|
|
if ($object->status == Expedition::STATUS_VALIDATED && !getDolGlobalString('STOCK_CALCULATE_ON_SHIPMENT')) {
|
|
if ($user->hasRight('expedition', 'creer')) {
|
|
print dolGetButtonAction('', $langs->trans('SetToDraft'), 'default', $_SERVER["PHP_SELF"] . '?action=setdraft&token=' . newToken() . '&id=' . $object->id, '');
|
|
}
|
|
}
|
|
if ($object->status == Expedition::STATUS_CLOSED) {
|
|
if ($user->hasRight('expedition', 'creer')) {
|
|
print dolGetButtonAction('', $langs->trans('ReOpen'), 'default', $_SERVER["PHP_SELF"] . '?action=reopen&token=' . newToken() . '&id=' . $object->id, '');
|
|
}
|
|
}
|
|
|
|
// Send
|
|
if (empty($user->socid)) {
|
|
if ($object->status > 0) {
|
|
if (!getDolGlobalString('MAIN_USE_ADVANCED_PERMS') || $user->hasRight('expedition', 'shipping_advance', 'send')) {
|
|
print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER["PHP_SELF"] . '?action=presend&token=' . newToken() . '&id=' . $object->id . '&mode=init#formmailbeforetitle', '');
|
|
} else {
|
|
print dolGetButtonAction('', $langs->trans('SendMail'), 'email', $_SERVER['PHP_SELF'] . '#', '', false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// This is just to generate a delivery receipt when option to do this is on
|
|
//var_dump($object->linkedObjectsIds['delivery']);
|
|
if (getDolGlobalInt('MAIN_SUBMODULE_DELIVERY') && ($object->status == Expedition::STATUS_VALIDATED || $object->status == Expedition::STATUS_CLOSED) && $user->hasRight('expedition', 'delivery', 'creer') && empty($object->linkedObjectsIds['delivery'])) {
|
|
print dolGetButtonAction('', $langs->trans('CreateDeliveryOrder'), 'default', $_SERVER["PHP_SELF"] . '?action=create_delivery&token=' . newToken() . '&id=' . $object->id, '');
|
|
}
|
|
|
|
// Sign (to set to status "Signed" without using the online signature page)
|
|
if ($object->status > Expedition::STATUS_DRAFT) {
|
|
if ($object->signed_status != Expedition::$SIGNED_STATUSES['STATUS_SIGNED_ALL']) {
|
|
print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=sign&token=' . newToken() . '">' . $langs->trans("SignShipping") . '</a></div>';
|
|
} else {
|
|
print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=unsign&token=' . newToken() . '">' . $langs->trans("UnsignShipping") . '</a></div>';
|
|
}
|
|
}
|
|
|
|
// Create bill
|
|
if (isModEnabled('invoice') && ($object->status == Expedition::STATUS_VALIDATED || $object->status == Expedition::STATUS_CLOSED)) {
|
|
if ($user->hasRight('facture', 'creer')) {
|
|
if (getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0') {
|
|
print dolGetButtonAction('', $langs->trans('CreateBill'), 'default', DOL_URL_ROOT . '/compta/facture/card.php?action=create&origin=' . $object->element . '&originid=' . $object->id . '&socid=' . $object->socid, '');
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set Billed and Closed
|
|
if ($object->status == Expedition::STATUS_VALIDATED) {
|
|
if ($user->hasRight('expedition', 'creer') && $object->status > 0) {
|
|
if (!$object->billed && getDolGlobalString('WORKFLOW_BILL_ON_SHIPMENT') !== '0') {
|
|
print dolGetButtonAction('', $langs->trans('ClassifyBilled'), 'default', $_SERVER["PHP_SELF"] . '?action=classifybilled&token=' . newToken() . '&id=' . $object->id, '');
|
|
}
|
|
print dolGetButtonAction('', $langs->trans("Close"), 'default', $_SERVER["PHP_SELF"] . '?action=classifyclosed&token=' . newToken() . '&id=' . $object->id, '');
|
|
}
|
|
}
|
|
|
|
// Cancel
|
|
if ($object->status == Expedition::STATUS_VALIDATED) {
|
|
if ($user->hasRight('expedition', 'creer')) {
|
|
print dolGetButtonAction('', $langs->trans('Cancel'), 'danger', $_SERVER["PHP_SELF"] . '?action=cancel&token=' . newToken() . '&id=' . $object->id . '&mode=init#formmailbeforetitle', '');
|
|
}
|
|
}
|
|
|
|
// Delete
|
|
if ($user->hasRight('expedition', 'supprimer')) {
|
|
print dolGetButtonAction('', $langs->trans('Delete'), 'delete', $_SERVER["PHP_SELF"] . '?action=delete&token=' . newToken() . '&id=' . $object->id, '');
|
|
}
|
|
}
|
|
|
|
print '</div>';
|
|
}
|
|
|
|
|
|
/*
|
|
* Documents generated
|
|
*/
|
|
|
|
if ($action != 'presend' && $action != 'editline') {
|
|
print '<div class="fichecenter"><div class="fichehalfleft">';
|
|
|
|
$objectref = dol_sanitizeFileName((string) $object->ref);
|
|
$filedir = $conf->expedition->dir_output . "/sending/" . $objectref;
|
|
|
|
$urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id;
|
|
|
|
$genallowed = $user->hasRight('expedition', 'lire');
|
|
$delallowed = $user->hasRight('expedition', 'creer');
|
|
|
|
print $formfile->showdocuments('expedition', $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, array(), array('shipping'), 1);
|
|
$linktoelem = $tmparray['linktoelem'];
|
|
$htmltoenteralink = $tmparray['htmltoenteralink'];
|
|
print $htmltoenteralink;
|
|
|
|
$somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
|
|
|
|
// Show online signature link
|
|
$useonlinesignature = getDolGlobalInt('EXPEDITION_ALLOW_ONLINESIGN');
|
|
|
|
if ($object->statut != Expedition::STATUS_DRAFT && $useonlinesignature) {
|
|
print '<br><!-- Link to sign -->';
|
|
require_once DOL_DOCUMENT_ROOT . '/core/lib/signature.lib.php';
|
|
print showOnlineSignatureUrl('expedition', $object->ref, $object) . '<br>';
|
|
}
|
|
|
|
print '</div><div class="fichehalfright">';
|
|
|
|
|
|
// List of actions on element
|
|
include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
|
|
$formactions = new FormActions($db);
|
|
|
|
//button to go to messaging from the events box
|
|
$MAXEVENT = 10;
|
|
$morehtmlcenter = dolGetButtonTitle($langs->trans('FullConversation'), '', 'fa fa-comments imgforviewmode', DOL_URL_ROOT . '/expedition/messaging.php?id=' . $object->id);
|
|
|
|
$somethingshown = $formactions->showactions($object, 'shipping', $socid, 1, '', $MAXEVENT, '', $morehtmlcenter);
|
|
print '</div></div>';
|
|
}
|
|
|
|
|
|
/*
|
|
* Action presend
|
|
*/
|
|
|
|
//Select mail models is same action as presend
|
|
if (GETPOST('modelselected')) {
|
|
$action = 'presend';
|
|
}
|
|
|
|
// Presend form
|
|
$modelmail = 'shipping_send';
|
|
$defaulttopic = 'SendShippingRef';
|
|
$diroutput = $conf->expedition->dir_output . '/sending';
|
|
$trackid = 'shi' . $object->id;
|
|
|
|
include DOL_DOCUMENT_ROOT . '/core/tpl/card_presend.tpl.php';
|
|
}
|
|
|
|
// End of page
|
|
llxFooter();
|
|
$db->close();
|