diff --git a/htdocs/langs/en_US/admin.lang b/htdocs/langs/en_US/admin.lang
index 1eb57fb4dae..0214b73292d 100644
--- a/htdocs/langs/en_US/admin.lang
+++ b/htdocs/langs/en_US/admin.lang
@@ -522,6 +522,7 @@ GoIntoTranslationMenuToChangeThis=A translation has been found for the key with
WarningSettingSortOrder=Warning, setting a default sort order may result in a technical error when going on the list page if field is an unknown field. If you experience such an error, come back to this page to remove the default sort order and restore default behavior.
Field=Field
ProductDocumentTemplates=Document templates to generate product document
+ProductBatchDocumentTemplates=Document templates to generate product lots document
FreeLegalTextOnExpenseReports=Free legal text on expense reports
WatermarkOnDraftExpenseReports=Watermark on draft expense reports
ProjectIsRequiredOnExpenseReports=The project is mandatory for entering an expense report
diff --git a/htdocs/product/admin/product_lot.php b/htdocs/product/admin/product_lot.php
index 19b2b32eac6..f28d406b126 100644
--- a/htdocs/product/admin/product_lot.php
+++ b/htdocs/product/admin/product_lot.php
@@ -36,6 +36,9 @@ if (!$user->admin || (empty($conf->productbatch->enabled)))
$action = GETPOST('action', 'alpha');
$value = GETPOST('value', 'alpha');
+$label = GETPOST('label', 'alpha');
+$scandir = GETPOST('scan_dir', 'alpha');
+$type = 'product_batch';
$error = 0;
@@ -88,6 +91,65 @@ if ($action == 'updateMaskLot') {
if ($value == '1' && $conf->global->PRODUCTBATCH_SN_ADDONS !== 'mod_sn_advanced') {
dolibarr_set_const($db, "PRODUCTBATCH_SN_ADDON", 'mod_sn_advanced', 'chaine', 0, '', $conf->entity);
}
+} elseif ($action == 'set') {
+ // Activate a model
+ $ret = addDocumentModel($value, $type, $label, $scandir);
+} elseif ($action == 'del') {
+ $ret = delDocumentModel($value, $type);
+ if ($ret > 0) {
+ if ($conf->global->FACTURE_ADDON_PDF == "$value") {
+ dolibarr_del_const($db, 'FACTURE_ADDON_PDF', $conf->entity);
+ }
+ }
+} elseif ($action == 'specimen') {
+ $modele = GETPOST('module', 'alpha');
+
+ $product_batch = new Productlot($db);
+ $product_batch->initAsSpecimen();
+
+ // Search template files
+ $file = '';
+ $classname = '';
+ $filefound = 0;
+ $dirmodels = array_merge(array('/'), (array)$conf->modules_parts['models']);
+ foreach ($dirmodels as $reldir) {
+ $file = dol_buildpath($reldir . "core/modules/product_batch/doc/pdf_" . $modele . ".modules.php", 0);
+ if (file_exists($file)) {
+ $filefound = 1;
+ $classname = "pdf_" . $modele;
+ break;
+ }
+ }
+
+ if ($filefound) {
+ require_once $file;
+
+ $module = new $classname($db);
+
+ if ($module->write_file($product_batch, $langs) > 0) {
+ header("Location: " . DOL_URL_ROOT . "/document.php?modulepart=product_batch&file=SPECIMEN.pdf");
+ return;
+ } else {
+ setEventMessages($module->error, $module->errors, 'errors');
+ dol_syslog($module->error, LOG_ERR);
+ }
+ } else {
+ setEventMessages($langs->trans("ErrorModuleNotFound"), null, 'errors');
+ dol_syslog($langs->trans("ErrorModuleNotFound"), LOG_ERR);
+ }
+} elseif ($action == 'setdoc') {
+ // Set default model
+ if (dolibarr_set_const($db, "PRODUCT_BATCH_ADDON_PDF", $value, 'chaine', 0, '', $conf->entity)) {
+ // La constante qui a ete lue en avant du nouveau set
+ // on passe donc par une variable pour avoir un affichage coherent
+ $conf->global->PRODUCT_BATCH_ADDON_PDF = $value;
+ }
+
+ // On active le modele
+ $ret = delDocumentModel($value, $type);
+ if ($ret > 0) {
+ $ret = addDocumentModel($value, $type, $label, $scandir);
+ }
}
/*
@@ -299,6 +361,141 @@ if ($conf->global->MAIN_FEATURES_LEVEL < 2) {
print "
\n";
}
+// Module to build doc
+$def = array();
+$sql = "SELECT nom";
+$sql .= " FROM " . MAIN_DB_PREFIX . "document_model";
+$sql .= " WHERE type = '" . $db->escape($type) . "'";
+$sql .= " AND entity = " . $conf->entity;
+$resql = $db->query($sql);
+if ($resql) {
+ $i = 0;
+ $num_rows = $db->num_rows($resql);
+ while ($i < $num_rows) {
+ $array = $db->fetch_array($resql);
+ array_push($def, $array[0]);
+ $i++;
+ }
+} else {
+ dol_print_error($db);
+}
+
+print '
';
+
+print load_fiche_titre($langs->trans("ProductBatchDocumentTemplates"), '', '');
+
+print '
';
+print '
';
+print '';
+print '| ' . $langs->trans("Name") . ' | ';
+print '' . $langs->trans("Description") . ' | ';
+print '' . $langs->trans("Status") . " | \n";
+print '' . $langs->trans("Default") . " | \n";
+print ' | ';
+print '' . $langs->trans("Preview") . ' | ';
+print "
\n";
+
+clearstatcache();
+
+foreach ($dirmodels as $reldir) {
+ foreach (array('', '/doc') as $valdir) {
+ $dir = dol_buildpath($reldir . "core/modules/product_batch" . $valdir);
+ if (is_dir($dir)) {
+ $handle = opendir($dir);
+ if (is_resource($handle)) {
+ while (($file = readdir($handle)) !== false) {
+ $filelist[] = $file;
+ }
+ closedir($handle);
+ arsort($filelist);
+
+ foreach ($filelist as $file) {
+ if (preg_match('/\.modules\.php$/i', $file) && preg_match('/^(pdf_|doc_)/', $file)) {
+ if (file_exists($dir . '/' . $file)) {
+ $name = substr($file, 4, dol_strlen($file) - 16);
+ $classname = substr($file, 0, dol_strlen($file) - 12);
+
+ require_once $dir . '/' . $file;
+ $module = new $classname($db);
+
+ $modulequalified = 1;
+ if ($module->version == 'development' && $conf->global->MAIN_FEATURES_LEVEL < 2) {
+ $modulequalified = 0;
+ }
+ if ($module->version == 'experimental' && $conf->global->MAIN_FEATURES_LEVEL < 1) {
+ $modulequalified = 0;
+ }
+
+ if ($modulequalified) {
+ print '| ';
+ print (empty($module->name) ? $name : $module->name);
+ print " | \n";
+ if (method_exists($module, 'info')) {
+ print $module->info($langs);
+ } else {
+ print $module->description;
+ }
+ print ' | ';
+
+ // Active
+ if (in_array($name, $def)) {
+ print '' . "\n";
+ print '';
+ print img_picto($langs->trans("Enabled"), 'switch_on');
+ print '';
+ print ' | ';
+ } else {
+ print '' . "\n";
+ print 'scandir) . '&label=' . urlencode($module->name) . '">' . img_picto($langs->trans("Disabled"), 'switch_off') . '';
+ print " | ";
+ }
+
+ // Defaut
+ print '';
+ if (getDolGlobalString('PRODUCT_BATCH_ADDON_PDF') == $name) {
+ print img_picto($langs->trans("Default"), 'on');
+ } else {
+ print 'scandir) . '&label=' . urlencode($module->name) . '" alt="' . $langs->trans("Default") . '">' . img_picto($langs->trans("Disabled"), 'off') . '';
+ }
+ print ' | ';
+
+ // Info
+ $htmltooltip = '' . $langs->trans("Name") . ': ' . $module->name;
+ $htmltooltip .= '
' . $langs->trans("Type") . ': ' . ($module->type ? $module->type : $langs->trans("Unknown"));
+ if ($module->type == 'pdf') {
+ $htmltooltip .= '
' . $langs->trans("Width") . '/' . $langs->trans("Height") . ': ' . $module->page_largeur . '/' . $module->page_hauteur;
+ }
+ $htmltooltip .= '
' . $langs->trans("FeaturesSupported") . ':';
+ $htmltooltip .= '
' . $langs->trans("Logo") . ': ' . yn($module->option_logo, 1, 1);
+ $htmltooltip .= '
' . $langs->trans("MultiLanguage") . ': ' . yn($module->option_multilang, 1, 1);
+
+
+ print '';
+ print $form->textwithpicto('', $htmltooltip, 1, 0);
+ print ' | ';
+
+ // Preview
+ print '';
+ if ($module->type == 'pdf') {
+ print '' . img_object($langs->trans("Preview"), 'contract') . '';
+ } else {
+ print img_object($langs->trans("PreviewNotAvailable"), 'generic');
+ }
+ print ' | ';
+
+ print "
\n";
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+print '
';
+print '
';
+
// End of page
llxFooter();
$db->close();
diff --git a/htdocs/product/stock/class/productlot.class.php b/htdocs/product/stock/class/productlot.class.php
index 7d12acae368..da2f412af17 100644
--- a/htdocs/product/stock/class/productlot.class.php
+++ b/htdocs/product/stock/class/productlot.class.php
@@ -98,6 +98,8 @@ class Productlot extends CommonObject
//'commissionning_date' => array('type'=>'date', 'label'=>'FirstUseDate', 'enabled'=>'empty($conf->global->PRODUCT_ENABLE_TRACEABILITY)?0:1', 'visible'=>5, 'position'=>100),
//'qc_frequency' => array('type'=>'varchar(6)', 'label'=>'QCFrequency', 'enabled'=>'empty($conf->global->PRODUCT_ENABLE_QUALITYCONTROL)?1:0', 'visible'=>5, 'position'=>110),
'eatby' => array('type'=>'date', 'label'=>'EatByDate', 'enabled'=>'empty($conf->global->PRODUCT_DISABLE_EATBY)?1:0', 'visible'=>5, 'position'=>62),
+ 'model_pdf' => array('type' => 'varchar(255)', 'label' => 'Model pdf', 'enabled' => 1, 'visible' => 0, 'position' => 215),
+ 'last_main_doc' => array('type' => 'varchar(255)', 'label' => 'LastMainDoc', 'enabled' => 1, 'visible' => -1, 'position' => 310),
'datec' => array('type'=>'datetime', 'label'=>'DateCreation', 'enabled'=>1, 'visible'=>1, 'notnull'=>1, 'position'=>500),
'tms' => array('type'=>'timestamp', 'label'=>'DateModification', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>501),
'fk_user_creat' => array('type'=>'integer:User:user/class/user.class.php', 'label'=>'UserAuthor', 'enabled'=>1, 'visible'=>-2, 'notnull'=>1, 'position'=>510, 'foreignkey'=>'llx_user.rowid'),
@@ -295,6 +297,8 @@ class Productlot extends CommonObject
$sql .= " t.scrapping_date,";
//$sql .= " t.commissionning_date,";
//$sql .= " t.qc_frequency,";
+ $sql .= " t.model_pdf,";
+ $sql .= " t.last_main_doc,";
$sql .= " t.datec,";
$sql .= " t.tms,";
$sql .= " t.fk_user_creat,";
@@ -329,6 +333,8 @@ class Productlot extends CommonObject
$this->scrapping_date = $this->db->jdate($obj->scrapping_date);
//$this->commissionning_date = $this->db->jdate($obj->commissionning_date);
//$this->qc_frequency = $obj->qc_frequency;
+ $this->model_pdf = $obj->model_pdf;
+ $this->last_main_doc = $obj->last_main_doc;
$this->datec = $this->db->jdate($obj->datec);
$this->tms = $this->db->jdate($obj->tms);
@@ -999,9 +1005,14 @@ class Productlot extends CommonObject
*/
public function initAsSpecimen()
{
- $this->id = 0;
+ global $conf;
- $this->entity = null;
+ // Initialise parametres
+ $this->id = 0;
+ $this->ref = 'SPECIMEN';
+ $this->specimen = 1;
+
+ $this->entity = $conf->entity;
$this->fk_product = null;
$this->batch = '';
$this->eatby = '';
@@ -1012,4 +1023,37 @@ class Productlot extends CommonObject
$this->fk_user_modif = null;
$this->import_key = '';
}
+
+ /**
+ * Create a document onto disk according to template module.
+ *
+ * @param string $modele Force model to use ('' to not force)
+ * @param Translate $outputlangs Object langs to use for output
+ * @param int $hidedetails Hide details of lines
+ * @param int $hidedesc Hide description
+ * @param int $hideref Hide ref
+ * @return int 0 if KO, 1 if OK
+ */
+ public function generateDocument($modele, $outputlangs, $hidedetails = 0, $hidedesc = 0, $hideref = 0)
+ {
+ global $conf, $user, $langs;
+
+ $langs->loadLangs(array('stocks', 'productbatch', "products"));
+ $outputlangs->loadLangs(array('stocks', 'productbatch', "products"));
+
+ // Positionne le modele sur le nom du modele a utiliser
+ if (!dol_strlen($modele)) {
+ $modele = '';
+
+ if (!empty($this->model_pdf)) {
+ $modele = $this->model_pdf;
+ } elseif (!empty($conf->global->PRODUCT_BATCH_ADDON_PDF)) {
+ $modele = $conf->global->PRODUCT_BATCH_ADDON_PDF;
+ }
+ }
+
+ $modelpath = "core/modules/product_batch/doc/";
+
+ return $this->commonGenerateDocument($modelpath, $modele, $outputlangs, $hidedetails, $hidedesc, $hideref);
+ }
}
diff --git a/htdocs/product/stock/productlot_card.php b/htdocs/product/stock/productlot_card.php
index a39d92f93aa..c33997010fb 100644
--- a/htdocs/product/stock/productlot_card.php
+++ b/htdocs/product/stock/productlot_card.php
@@ -568,7 +568,7 @@ if ($action != 'presend') {
$urlsource = $_SERVER["PHP_SELF"]."?id=".$object->id;
$genallowed = $usercanread; // If you can read, you can build the PDF to read content
$delallowed = $usercancreate; // If you can create/edit, you can remove a file on card
- print $formfile->showdocuments('product_batch', $objref, $filedir, $urlsource, $genallowed, $delallowed, '', 0, 0, 0, 28, 0, '', 0, '', $langs->default_lang, '', $object);
+ print $formfile->showdocuments('product_batch', $objref, $filedir, $urlsource, $genallowed, $delallowed, $object->model_pdf, 0, 0, 0, 28, 0, '', 0, '', $langs->default_lang, '', $object);
}
print '';