card-rec.php 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643
  1. <?php
  2. /* Copyright (C) 2002-2003 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@inodbox.com>
  5. * Copyright (C) 2013 Florian Henry <florian.henry@open-concept.pro>
  6. * Copyright (C) 2013 Juanjo Menent <jmenent@2byte.es>
  7. * Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
  8. * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
  9. * Copyright (C) 2015 Alexandre Spangaro <aspangaro@open-dsi.fr>
  10. * Copyright (C) 2016 Meziane Sof <virtualsof@yahoo.fr>
  11. * Copyright (C) 2017-2018 Frédéric France <frederic.france@netlogic.fr>
  12. *
  13. * This program is free software; you can redistribute it and/or modify
  14. * it under the terms of the GNU General Public License as published by
  15. * the Free Software Foundation; either version 3 of the License, or
  16. * (at your option) any later version.
  17. *
  18. * This program is distributed in the hope that it will be useful,
  19. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  20. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  21. * GNU General Public License for more details.
  22. *
  23. * You should have received a copy of the GNU General Public License
  24. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  25. */
  26. /**
  27. * \file htdocs/fourn/facture/card-rec.php
  28. * \ingroup facture fournisseurs
  29. * \brief Page to show predefined invoice
  30. */
  31. // Load Dolibarr environment
  32. require '../../main.inc.php';
  33. require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.facture-rec.class.php';
  34. require_once DOL_DOCUMENT_ROOT . '/fourn/class/fournisseur.product.class.php';
  35. require_once DOL_DOCUMENT_ROOT . '/product/class/product.class.php';
  36. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
  37. if (isModEnabled('project')) {
  38. include_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
  39. }
  40. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
  41. require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  42. require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
  43. require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
  44. // Load translation files required by the page
  45. $langs->loadLangs(array('bills', 'companies', 'compta', 'admin', 'other', 'products', 'banks', 'suppliers'));
  46. $action = GETPOST('action', 'alpha');
  47. $massaction = GETPOST('massaction', 'alpha');
  48. $show_files = GETPOST('show_files', 'int');
  49. $confirm = GETPOST('confirm', 'alpha');
  50. $cancel = GETPOST('cancel', 'alpha');
  51. $toselect = GETPOST('toselect', 'array');
  52. $contextpage = GETPOST('contextpage', 'aZ') ? GETPOST('contextpage', 'aZ') : 'supplierinvoicetemplatelist'; // To manage different context of search
  53. $limit = GETPOST('limit', 'int') ? GETPOST('limit', 'int') : $conf->liste_limit;
  54. $sortfield = GETPOST("sortfield", 'alpha');
  55. $sortorder = GETPOST("sortorder", 'alpha');
  56. $page = GETPOSTISSET('pageplusone') ? (GETPOST('pageplusone') - 1) : GETPOST("page", 'int');
  57. // Security check
  58. $id = (GETPOST('facid', 'int') ? GETPOST('facid', 'int') : GETPOST('id', 'int'));
  59. $lineid = GETPOST('lineid', 'int');
  60. $title = GETPOST('title', 'alpha');
  61. $ref_supplier = GETPOST('ref_supplier', 'alpha');
  62. $projectid = GETPOST('projectid', 'int');
  63. $year_date_when = GETPOST('year_date_when');
  64. $month_date_when = GETPOST('month_date_when');
  65. if ($user->socid) {
  66. $socid = $user->socid;
  67. }
  68. $objecttype = 'facturefournisseur_rec';
  69. if ($action == "create" || $action == "add") {
  70. $objecttype = '';
  71. }
  72. if (empty($page) || $page == -1) {
  73. $page = 0;
  74. } // If $page is not defined, or '' or -1
  75. $offset = $limit * $page;
  76. if (! $sortorder) {
  77. $sortorder = 'DESC';
  78. }
  79. if (! $sortfield) {
  80. $sortfield = 'f.titre';
  81. }
  82. $pageprev = $page - 1;
  83. $pagenext = $page + 1;
  84. $object = new FactureFournisseurRec($db);
  85. if (($id > 0 || $title) && $action != 'create' && $action != 'add') {
  86. $ret = $object->fetch($id, $title);
  87. if (! $ret) {
  88. setEventMessages($langs->trans("ErrorRecordNotFound"), null, 'errors');
  89. }
  90. }
  91. // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
  92. $hookmanager->initHooks(array('supplierinvoicereccard', 'globalcard'));
  93. $extrafields = new ExtraFields($db);
  94. // fetch optionals attributes and labels
  95. $extrafields->fetch_name_optionals_label($object->table_element);
  96. $search_array_options = $extrafields->getOptionalsFromPost($object->table_element, '', 'search_');
  97. $permissionnote = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer; // Used by the include of actions_setnotes.inc.php
  98. $permissiondellink = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer;; // Used by the include of actions_dellink.inc.php
  99. $permissiontoedit = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer;; // Used by the include of actions_lineupdonw.inc.php
  100. $usercanread = $user->rights->fournisseur->facture->lire || $user->rights->supplier_invoice->lire;
  101. $usercancreate = $user->rights->fournisseur->facture->creer || $user->rights->supplier_invoice->creer;
  102. $usercandelete = $user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer;
  103. $usercanvalidate = ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($usercancreate)) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && !empty($user->rights->fournisseur->supplier_invoice_advance->validate)));
  104. $usercansend = (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->fournisseur->supplier_invoice_advance->send);
  105. $usercanproductignorepricemin = ((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS));
  106. $usercancreatemargin = $user->rights->margins->creer;
  107. $usercanreadallmargin = $user->rights->margins->liretous;
  108. $usercancreatewithdrarequest = $user->rights->prelevement->bons->creer;
  109. $now = dol_now();
  110. $error = 0;
  111. $result = restrictedArea($user, 'facture', $object->id, $objecttype);
  112. /*
  113. * Actions
  114. */
  115. if (GETPOST('cancel', 'alpha')) {
  116. $action = 'list';
  117. $massaction = '';
  118. }
  119. if (! GETPOST('confirmmassaction', 'alpha') && $massaction != 'presend' && $massaction != 'confirm_presend') {
  120. $massaction = '';
  121. }
  122. $parameters = array('socid' => $socid);
  123. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  124. if ($reshook < 0) {
  125. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  126. }
  127. if (empty($reshook)) {
  128. if (GETPOST('cancel', 'alpha')) {
  129. $action = '';
  130. }
  131. // Selection of new fields
  132. include DOL_DOCUMENT_ROOT . '/core/actions_changeselectedfields.inc.php';
  133. // Set note
  134. include DOL_DOCUMENT_ROOT . '/core/actions_setnotes.inc.php'; // Must be include, not include_once
  135. include DOL_DOCUMENT_ROOT . '/core/actions_dellink.inc.php'; // Must be include, not include_once
  136. include DOL_DOCUMENT_ROOT . '/core/actions_lineupdown.inc.php'; // Must be include, not include_once
  137. // Create predefined invoice
  138. if ($action == 'add') {
  139. if (! GETPOST('title', 'alphanohtml')) {
  140. setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Title")), null, 'errors');
  141. $action = "create";
  142. $error++;
  143. }
  144. $frequency = GETPOST('frequency', 'int');
  145. $reyear = GETPOST('reyear', 'int');
  146. $remonth = GETPOST('remonth', 'int');
  147. $reday = GETPOST('reday', 'int');
  148. $rehour = GETPOST('rehour', 'int');
  149. $remin = GETPOST('remin', 'int');
  150. $nb_gen_max = GETPOST('nb_gen_max', 'int');
  151. //if (empty($nb_gen_max)) $nb_gen_max =0;
  152. if (GETPOST('frequency', 'int')) {
  153. if (empty($reyear) || empty($remonth) || empty($reday)) {
  154. setEventMessages($langs->transnoentities("ErrorFieldRequired", $langs->trans("Date")), null, 'errors');
  155. $action = "create";
  156. $error++;
  157. }
  158. }
  159. if (! $error) {
  160. $object->titre = GETPOST('title', 'alphanohtml'); // deprecated
  161. $object->title = GETPOST('title', 'alphanohtml');
  162. $object->fk_project = GETPOST('projectid', 'int');
  163. $object->ref_supplier = GETPOST('ref_supplier', 'alphanohtml');
  164. $object->note_private = GETPOST('note_private', 'restricthtml');
  165. $object->note_public = GETPOST('note_public', 'restricthtml');
  166. $object->model_pdf = GETPOST('modelpdf', 'alpha');
  167. $object->usenewprice = GETPOST('usenewprice', 'alpha');
  168. $object->frequency = $frequency;
  169. $object->unit_frequency = GETPOST('unit_frequency', 'alpha');
  170. $object->nb_gen_max = $nb_gen_max;
  171. $object->auto_validate = GETPOST('auto_validate', 'int');
  172. $object->generate_pdf = GETPOST('generate_pdf', 'int');
  173. $date_next_execution = dol_mktime($rehour, $remin, 0, $remonth, $reday, $reyear);
  174. $object->date_when = $date_next_execution;
  175. $db->begin();
  176. $oldinvoice = new FactureFournisseur($db);
  177. $oldinvoice->fetch(GETPOST('facid', 'int'));
  178. $object->cond_reglement_id = $oldinvoice->cond_reglement_id;
  179. $object->cond_reglement_code = $oldinvoice->cond_reglement_code;
  180. $object->cond_reglement_label = $oldinvoice->cond_reglement_label;
  181. $object->cond_reglement_doc = $oldinvoice->cond_reglement_doc;
  182. $object->mode_reglement_id = $oldinvoice->mode_reglement_id;
  183. $object->mode_reglement_code = $oldinvoice->mode_reglement_code;
  184. $result = $object->create($user, $oldinvoice->id);
  185. if ($result > 0) {
  186. $result = $oldinvoice->delete($user, 1);
  187. if ($result < 0) {
  188. $error++;
  189. setEventMessages($oldinvoice->error, $oldinvoice->errors, 'errors');
  190. $action = "create";
  191. }
  192. } else {
  193. $error++;
  194. setEventMessages($object->error, $object->errors, 'errors');
  195. $action = "create";
  196. }
  197. if (! $error) {
  198. $db->commit();
  199. header("Location: " . $_SERVER['PHP_SELF'] . '?facid=' . $object->id);
  200. exit;
  201. } else {
  202. $db->rollback();
  203. $error++;
  204. setEventMessages($object->error, $object->errors, 'errors');
  205. $action = "create";
  206. }
  207. }
  208. }
  209. // Delete
  210. //TODO : Droits
  211. if ($action == 'confirm_deleteinvoice' && $confirm == 'yes' && ($user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer)) {
  212. $object->delete($user);
  213. header('Location: ' . DOL_URL_ROOT . '/fourn/facture/list-rec.php');
  214. exit;
  215. }
  216. // Update field
  217. // Set condition
  218. if ($action == 'setconditions' && $usercancreate) {
  219. $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
  220. } elseif ($action == 'setmode' && $usercancreate) {
  221. // Set mode
  222. $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
  223. } elseif ($action == 'classin' && $usercancreate) {
  224. // Set project
  225. $object->setProject(GETPOST('projectid', 'int'));
  226. } elseif ($action == 'setref_supplier' && $usercancreate) {
  227. $result = $object->setValueFrom('ref_supplier', $ref_supplier, '', null, 'text', '', $user);
  228. if ($result <= 0) {
  229. $error++;
  230. if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
  231. $langs->load("errors");
  232. setEventMessages($langs->trans('ErrorRefAlreadyExists', $ref_supplier), null, 'errors');
  233. } else {
  234. setEventMessages($object->error, $object->errors, 'errors');
  235. }
  236. }
  237. } elseif ($action == 'settitle' && $usercancreate) {
  238. $result = $object->setValueFrom('titre', $title, '', null, 'text', '', $user);
  239. if ($result > 0) {
  240. $object->titre = $title;
  241. $object->title = $title;
  242. $object->ref = $object->title;
  243. } else {
  244. $error++;
  245. if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
  246. $langs->load("errors");
  247. setEventMessages($langs->trans('ErrorTitreAlreadyExists', $title), null, 'errors');
  248. } else {
  249. setEventMessages($object->error, $object->errors, 'errors');
  250. }
  251. }
  252. } elseif ($action == 'setbankaccount' && $usercancreate) {
  253. // Set bank account
  254. $result = $object->setBankAccount(GETPOST('fk_account', 'int'));
  255. } elseif ($action == 'setfrequency' && $usercancreate) {
  256. // Set frequency and unit frequency
  257. $object->setFrequencyAndUnit(GETPOST('frequency', 'int'), GETPOST('unit_frequency', 'alpha'));
  258. } elseif ($action == 'setdate_when' && $usercancreate) {
  259. // Set next date of execution
  260. $date = dol_mktime(GETPOST('date_whenhour'), GETPOST('date_whenmin'), 0, GETPOST('date_whenmonth'), GETPOST('date_whenday'), GETPOST('date_whenyear'));
  261. if (!empty($date)) {
  262. $object->setNextDate($date);
  263. }
  264. } elseif ($action == 'setnb_gen_max' && $usercancreate) {
  265. // Set max period
  266. $object->setMaxPeriod(GETPOST('nb_gen_max', 'int'));
  267. } elseif ($action == 'setauto_validate' && $usercancreate) {
  268. // Set auto validate
  269. $object->setAutoValidate(GETPOST('auto_validate', 'int'));
  270. } elseif ($action == 'setgenerate_pdf' && $usercancreate) {
  271. // Set generate pdf
  272. $object->setGeneratepdf(GETPOST('generate_pdf', 'int'));
  273. } elseif ($action == 'setmodelpdf' && $usercancreate) {
  274. // Set model pdf
  275. $object->setModelpdf(GETPOST('modelpdf', 'alpha'));
  276. } elseif ($action == 'disable' && $usercancreate) {
  277. // Set status disabled
  278. $db->begin();
  279. $object->fetch($id);
  280. $res = $object->setValueFrom('suspended', 1);
  281. if ($res <= 0) {
  282. $error++;
  283. }
  284. if (! $error) {
  285. $db->commit();
  286. } else {
  287. $db->rollback();
  288. setEventMessages($object->error, $object->errors, 'errors');
  289. }
  290. } elseif ($action == 'enable' && $usercancreate) {
  291. // Set status enabled
  292. $db->begin();
  293. $object->fetch($id);
  294. $res = $object->setValueFrom('suspended', 0);
  295. if ($res <= 0) {
  296. $error++;
  297. }
  298. if (! $error) {
  299. $db->commit();
  300. } else {
  301. $db->rollback();
  302. setEventMessages($object->error, $object->errors, 'errors');
  303. }
  304. } elseif ($action == 'setmulticurrencycode' && $usercancreate) {
  305. // Multicurrency Code
  306. $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
  307. } elseif ($action == 'setmulticurrencyrate' && $usercancreate) {
  308. // Multicurrency rate
  309. $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOST('calculation_mode', 'int'));
  310. } elseif ($action == 'setlibelle' && $usercancreate) {
  311. // Set label
  312. $object->fetch($id);
  313. $object->libelle = GETPOST('libelle');
  314. $result = $object->update($user);
  315. if ($result < 0) {
  316. dol_print_error($db);
  317. }
  318. }
  319. // Delete line
  320. if ($action == 'confirm_deleteline' && $confirm == 'yes' && $usercancreate) {
  321. $object->fetch($id);
  322. $object->fetch_thirdparty();
  323. $db->begin();
  324. $line = new FactureFournisseurLigneRec($db);
  325. // For triggers
  326. $line->id = $lineid;
  327. if ($line->delete($user) > 0) {
  328. $result = $object->update_price(1);
  329. if ($result > 0) {
  330. $db->commit();
  331. $object->fetch($object->id); // Reload lines
  332. } else {
  333. $db->rollback();
  334. setEventMessages($db->lasterror(), null, 'errors');
  335. }
  336. } else {
  337. $db->rollback();
  338. setEventMessages($line->error, $line->errors, 'errors');
  339. }
  340. } elseif ($action == 'update_extras') {
  341. $object->oldcopy = dol_clone($object);
  342. // Fill array 'array_options' with data from update form
  343. $ret = $extrafields->setOptionalsFromPost(null, $object, GETPOST('attribute', 'restricthtml'));
  344. if ($ret < 0) {
  345. $error++;
  346. }
  347. if (! $error) {
  348. $result = $object->insertExtraFields('BILLREC_MODIFY');
  349. if ($result < 0) {
  350. setEventMessages($object->error, $object->errors, 'errors');
  351. $error++;
  352. }
  353. }
  354. }
  355. // Add a new line
  356. if ($action == 'addline' && $usercancreate) {
  357. $langs->load('errors');
  358. $error = 0;
  359. // Set if we used free entry or predefined product
  360. $product_desc = (GETPOSTISSET('dp_desc') ? GETPOST('dp_desc', 'restricthtml') : '');
  361. $price_ht = price2num(GETPOST('price_ht'), 'MU', 2);
  362. $price_ht_devise = price2num(GETPOST('multicurrency_price_ht'), 'CU', 2);
  363. $prod_entry_mode = GETPOST('prod_entry_mode', 'alpha');
  364. if ($prod_entry_mode == 'free') {
  365. $idprod = 0;
  366. $tva_tx = (GETPOST('tva_tx', 'alpha') ? GETPOST('tva_tx', 'alpha') : 0);
  367. $ref_fournisseur = (GETPOSTISSET('fourn_ref') ? GETPOST('fourn_ref', 'restricthtml') : '');
  368. } else {
  369. $idprod = GETPOST('idprod', 'int');
  370. $tva_tx = '';
  371. }
  372. $qty = price2num(GETPOST('qty' . $predef, 'alpha'), 'MS', 2);
  373. $remise_percent = price2num(GETPOST('remise_percent' . $predef), '', 2);
  374. // Extrafields
  375. $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
  376. $array_options = $extrafields->getOptionalsFromPost($object->table_element_line, $predef);
  377. // Unset extrafield
  378. if (is_array($extralabelsline)) {
  379. // Get extra fields
  380. foreach ($extralabelsline as $key => $value) {
  381. unset($_POST["options_" . $key . $predef]);
  382. }
  383. }
  384. if ((empty($idprod) || $idprod < 0) && ($price_ht < 0) && ($qty < 0)) {
  385. setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
  386. $error++;
  387. }
  388. if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && GETPOST('type') < 0) {
  389. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
  390. $error++;
  391. }
  392. if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && (! ($price_ht >= 0) || $price_ht == '')) { // Unit price can be 0 but not ''
  393. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
  394. $error++;
  395. }
  396. if ($qty == '') {
  397. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
  398. $error++;
  399. }
  400. if ($prod_entry_mode == 'free' && (empty($idprod) || $idprod < 0) && empty($product_desc)) {
  401. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
  402. $error++;
  403. }
  404. if ($qty < 0) {
  405. $langs->load("errors");
  406. setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
  407. $error++;
  408. }
  409. if ($prod_entry_mode != 'free' && empty($error)) { // With combolist mode idprodfournprice is > 0 or -1. With autocomplete, idprodfournprice is > 0 or ''
  410. $productsupplier = new ProductFournisseur($db);
  411. $idprod = 0;
  412. if (GETPOST('idprodfournprice', 'alpha') == -1 || GETPOST('idprodfournprice', 'alpha') == '') {
  413. $idprod = -99; // Same behaviour than with combolist. When not select idprodfournprice is now -99 (to avoid conflict with next action that may return -1, -2, ...)
  414. }
  415. $reg = array();
  416. if (preg_match('/^idprod_([0-9]+)$/', GETPOST('idprodfournprice', 'alpha'), $reg)) {
  417. $idprod = (int) $reg[1];
  418. $res = $productsupplier->fetch($idprod); // Load product from its id
  419. // Call to init some price properties of $productsupplier
  420. // So if a supplier price already exists for another thirdparty (first one found), we use it as reference price
  421. if (!empty($conf->global->SUPPLIER_TAKE_FIRST_PRICE_IF_NO_PRICE_FOR_CURRENT_SUPPLIER)) {
  422. $fksoctosearch = 0;
  423. $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
  424. if ($productsupplier->fourn_socid != $socid) { // The price we found is for another supplier, so we clear supplier price
  425. $productsupplier->ref_supplier = '';
  426. }
  427. } else {
  428. $fksoctosearch = $object->thirdparty->id;
  429. $productsupplier->get_buyprice(0, -1, $idprod, 'none', $fksoctosearch); // We force qty to -1 to be sure to find if a supplier price exist
  430. }
  431. } elseif (GETPOST('idprodfournprice', 'alpha') > 0) {
  432. $qtytosearch = $qty; // Just to see if a price exists for the quantity. Not used to found vat.
  433. $idprod = $productsupplier->get_buyprice(GETPOST('idprodfournprice', 'alpha'), $qtytosearch);
  434. $res = $productsupplier->fetch($idprod);
  435. $ref_fournisseur = $productsupplier->ref_supplier;
  436. }
  437. }
  438. if (! $error && ($qty >= 0) && (!empty($product_desc) || (!empty($idprod) && $idprod > 0))) {
  439. $ret = $object->fetch($id);
  440. if ($ret < 0) {
  441. dol_print_error($db, $object->error);
  442. exit();
  443. }
  444. $ret = $object->fetch_thirdparty();
  445. // Clean parameters
  446. $date_start = dol_mktime(GETPOST('date_start' . $predef . 'hour'), GETPOST('date_start' . $predef . 'min'), GETPOST('date_start' . $predef . 'sec'), GETPOST('date_start' . $predef . 'month'), GETPOST('date_start' . $predef . 'day'), GETPOST('date_start' . $predef . 'year'));
  447. $date_end = dol_mktime(GETPOST('date_end' . $predef . 'hour'), GETPOST('date_end' . $predef . 'min'), GETPOST('date_end' . $predef . 'sec'), GETPOST('date_end' . $predef . 'month'), GETPOST('date_end' . $predef . 'day'), GETPOST('date_end' . $predef . 'year'));
  448. $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
  449. // Define special_code for special lines
  450. $special_code = 0;
  451. // if (empty($_POST['qty'])) $special_code=3; // Options should not exists on invoices
  452. // Ecrase $pu par celui du produit
  453. // Ecrase $desc par celui du produit
  454. // Ecrase $tva_tx par celui du produit
  455. // Ecrase $base_price_type par celui du produit
  456. // Replaces $fk_unit with the product's
  457. if (!empty($idprod) && $idprod > 0) {
  458. $prod = new Product($db);
  459. $prod->fetch($idprod);
  460. $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
  461. // Update if prices fields are defined
  462. $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
  463. $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
  464. if (empty($tva_tx)) {
  465. $tva_npr = 0;
  466. }
  467. // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
  468. $pqp = (GETPOST('pbq', 'int') ? GETPOST('pbq', 'int') : 0);
  469. $datapriceofproduct = $prod->getSellPrice($mysoc, $object->thirdparty, $pqp);
  470. $pu_ht = $datapriceofproduct['pu_ht'];
  471. $pu_ttc = $datapriceofproduct['pu_ttc'];
  472. $price_min = $datapriceofproduct['price_min'];
  473. $price_base_type = $datapriceofproduct['price_base_type'];
  474. $tva_tx = $datapriceofproduct['tva_tx'];
  475. $tva_npr = $datapriceofproduct['tva_npr'];
  476. $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
  477. $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
  478. // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
  479. if (!empty($price_ht)) {
  480. $pu_ht = price2num($price_ht, 'MU');
  481. $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
  482. } elseif ($tmpvat != $tmpprodvat) {
  483. // On reevalue prix selon taux tva car taux tva transaction peut etre different
  484. // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
  485. if ($price_base_type != 'HT') {
  486. $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
  487. } else {
  488. $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
  489. }
  490. }
  491. $desc = '';
  492. // Define output language
  493. if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
  494. $outputlangs = $langs;
  495. $newlang = '';
  496. if (empty($newlang) && GETPOST('lang_id', 'aZ09')) {
  497. $newlang = GETPOST('lang_id', 'aZ09');
  498. }
  499. if (empty($newlang)) {
  500. $newlang = $object->thirdparty->default_lang;
  501. }
  502. if (!empty($newlang)) {
  503. $outputlangs = new Translate("", $conf);
  504. $outputlangs->setDefaultLang($newlang);
  505. }
  506. $desc = (!empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
  507. } else {
  508. $desc = $prod->description;
  509. }
  510. $desc = dol_concatdesc($desc, $product_desc);
  511. // Add custom code and origin country into description
  512. if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (!empty($prod->customcode) || !empty($prod->country_code))) {
  513. $tmptxt = '(';
  514. // Define output language
  515. if (getDolGlobalInt('MAIN_MULTILANGS') && !empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
  516. $outputlangs = $langs;
  517. $newlang = '';
  518. if (empty($newlang) && GETPOST('lang_id', 'alpha')) {
  519. $newlang = GETPOST('lang_id', 'alpha');
  520. }
  521. if (empty($newlang)) {
  522. $newlang = $object->thirdparty->default_lang;
  523. }
  524. if (!empty($newlang)) {
  525. $outputlangs = new Translate("", $conf);
  526. $outputlangs->setDefaultLang($newlang);
  527. $outputlangs->load('products');
  528. }
  529. if (!empty($prod->customcode)) {
  530. $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
  531. }
  532. if (!empty($prod->customcode) && !empty($prod->country_code)) {
  533. $tmptxt .= ' - ';
  534. }
  535. if (!empty($prod->country_code)) {
  536. $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $outputlangs, 0);
  537. }
  538. } else {
  539. if (!empty($prod->customcode)) {
  540. $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
  541. }
  542. if (!empty($prod->customcode) && !empty($prod->country_code)) {
  543. $tmptxt .= ' - ';
  544. }
  545. if (!empty($prod->country_code)) {
  546. $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
  547. }
  548. }
  549. $tmptxt .= ')';
  550. $desc = dol_concatdesc($desc, $tmptxt);
  551. }
  552. $type = $prod->type;
  553. $fk_unit = $prod->fk_unit;
  554. } else {
  555. $pu_ht = price2num($price_ht, 'MU');
  556. $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
  557. $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
  558. $tva_tx = str_replace('*', '', $tva_tx);
  559. if (empty($tva_tx)) {
  560. $tva_npr = 0;
  561. }
  562. $desc = $product_desc;
  563. $type = GETPOST('type');
  564. $fk_unit = GETPOST('units', 'alpha');
  565. }
  566. $date_start_fill = !empty(GETPOST('date_start_fill', 'int')) ? GETPOST('date_start_fill', 'int') : null;
  567. $date_end_fill = !empty(GETPOST('date_end_fill', 'int')) ? GETPOST('date_end_fill', 'int') : null;
  568. // Margin
  569. $fournprice = price2num(GETPOST('fournprice' . $predef) ? GETPOST('fournprice' . $predef) : '');
  570. $buyingprice = price2num(GETPOST('buying_price' . $predef) != '' ? GETPOST('buying_price' . $predef) : ''); // If buying_price is '0', we must keep this value
  571. // Local Taxes
  572. $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
  573. $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
  574. $info_bits = 0;
  575. if ($tva_npr) {
  576. $info_bits |= 0x01;
  577. }
  578. //To set vars in float type to avoid non-numeric warnings
  579. $pu_ht = (float) price2num($pu_ht);
  580. $remise_percent = (float) price2num($remise_percent);
  581. $price_min = (float) price2num($price_min);
  582. if ($usercanproductignorepricemin && (!empty($price_min) && ($pu_ht * (1 - $remise_percent / 100) < $price_min))) {
  583. $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency));
  584. setEventMessages($mesg, null, 'errors');
  585. } else {
  586. // Insert line
  587. $result = $object->addline($idprod, $ref_fournisseur, $label, $desc, $pu_ht, $pu_ttc, $qty, $remise_percent, $tva_tx, $localtax1_tx, $localtax2_tx, $price_base_type, $type, $date_start_fill, $date_end_fill, $info_bits, $special_code, -1, $fk_unit);
  588. if ($result > 0) {
  589. $object->fetch($object->id); // Reload lines
  590. unset($_POST['prod_entry_mode']);
  591. unset($_POST['qty']);
  592. unset($_POST['type']);
  593. unset($_POST['remise_percent']);
  594. unset($_POST['price_ht']);
  595. unset($_POST['multicurrency_price_ht']);
  596. unset($_POST['price_ttc']);
  597. unset($_POST['tva_tx']);
  598. unset($_POST['product_ref']);
  599. unset($_POST['product_label']);
  600. unset($_POST['product_desc']);
  601. unset($_POST['fournprice']);
  602. unset($_POST['buying_price']);
  603. unset($_POST['np_marginRate']);
  604. unset($_POST['np_markRate']);
  605. unset($_POST['dp_desc']);
  606. unset($_POST['idprod']);
  607. unset($_POST['units']);
  608. unset($_POST['date_starthour']);
  609. unset($_POST['date_startmin']);
  610. unset($_POST['date_startsec']);
  611. unset($_POST['date_startday']);
  612. unset($_POST['date_startmonth']);
  613. unset($_POST['date_startyear']);
  614. unset($_POST['date_endhour']);
  615. unset($_POST['date_endmin']);
  616. unset($_POST['date_endsec']);
  617. unset($_POST['date_endday']);
  618. unset($_POST['date_endmonth']);
  619. unset($_POST['date_endyear']);
  620. unset($_POST['date_start_fill']);
  621. unset($_POST['date_end_fill']);
  622. unset($_POST['situations']);
  623. unset($_POST['progress']);
  624. } else {
  625. setEventMessages($object->error, $object->errors, 'errors');
  626. }
  627. $action = '';
  628. }
  629. }
  630. } elseif ($action == 'updateline' && $usercancreate && ! GETPOST('cancel', 'alpha')) {
  631. if (! $object->fetch($id) > 0) {
  632. dol_print_error($db);
  633. }
  634. $object->fetch_thirdparty();
  635. // Clean parameters
  636. $date_start = '';
  637. $date_end = '';
  638. $description = dol_htmlcleanlastbr(GETPOST('product_desc', 'restricthtml') ? GETPOST('product_desc', 'restricthtml') : GETPOST('desc', 'restricthtml'));
  639. $ref_fourn = GETPOST('fourn_ref', 'alpha');
  640. $pu_ht = price2num(GETPOST('price_ht'), '', 2);
  641. $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
  642. $qty = GETPOST('qty');
  643. $pu_ht_devise = price2num(GETPOST('multicurrency_subprice'), '', 2);
  644. // Define info_bits
  645. $info_bits = 0;
  646. if (preg_match('/\*/', $vat_rate)) {
  647. $info_bits |= 0x01;
  648. }
  649. // Define vat_rate
  650. $vat_rate = str_replace('*', '', $vat_rate);
  651. $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
  652. $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
  653. // Extrafields
  654. $extralabelsline = $extrafields->fetch_name_optionals_label($object->table_element_line);
  655. $array_options = $extrafields->getOptionalsFromPost($object->table_element_line);
  656. $objectline = new FactureFournisseurLigneRec($db);
  657. if ($objectline->fetch(GETPOST('lineid', 'int'))) {
  658. $objectline->array_options = $array_options;
  659. $result = $objectline->insertExtraFields();
  660. if ($result < 0) {
  661. setEventMessages($langs->trans('Error') . $result, null, 'errors');
  662. }
  663. }
  664. $position = ($objectline->rang >= 0 ? $objectline->rang : 0);
  665. // Unset extrafield
  666. if (is_array($extralabelsline)) {
  667. // Get extra fields
  668. foreach ($extralabelsline as $key => $value) {
  669. unset($_POST["options_" . $key]);
  670. }
  671. }
  672. // Define special_code for special lines
  673. $special_code = GETPOST('special_code', 'int');
  674. if (! GETPOST('qty', 'alpha')) {
  675. $special_code = 3;
  676. }
  677. $remise_percent = price2num(GETPOST('remise_percent'), '', 2);
  678. // Check minimum price
  679. $productid = GETPOST('productid', 'int');
  680. if (!empty($productid)) {
  681. $product = new Product($db);
  682. $product->fetch($productid);
  683. $type = $product->type;
  684. $price_min = $product->price_min;
  685. if (!empty($conf->global->PRODUIT_MULTIPRICES) && !empty($object->thirdparty->price_level)) {
  686. $price_min = $product->multiprices_min[$object->thirdparty->price_level];
  687. }
  688. $label = $product->label;
  689. // Check price is not lower than minimum (check is done only for standard or replacement invoices)
  690. if (((!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && empty($user->rights->produit->ignore_price_min_advance)) || empty($conf->global->MAIN_USE_ADVANCED_PERMS)) && $price_min && (price2num($pu_ht) * (1 - $remise_percent / 100) < price2num($price_min))) {
  691. setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, -1, $conf->currency)), null, 'errors');
  692. $error++;
  693. }
  694. } else {
  695. $type = GETPOST('type', 'int');
  696. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  697. // Check parameters
  698. if (GETPOST('type', 'int') < 0) {
  699. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
  700. $error++;
  701. }
  702. }
  703. if ($qty < 0) {
  704. $langs->load("errors");
  705. setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
  706. $error++;
  707. }
  708. $date_start_fill = !empty(GETPOST('date_start_fill', 'int')) ? GETPOST('date_start_fill', 'int') : 'NULL';
  709. $date_end_fill = !empty(GETPOST('date_end_fill', 'int')) ? GETPOST('date_end_fill', 'int') : 'NULL';
  710. // Update line
  711. if (! $error) {
  712. $result = $object->updateline(GETPOST('lineid', 'int'), GETPOST('productid', 'int'), $ref_fourn, $label, $description, $pu_ht, $qty, $remise_percent, $vat_rate, $localtax1_rate, $localtax1_rate, 'HT', $type, $date_start_fill, $date_end_fill, $info_bits, $special_code, -1);
  713. if ($result >= 0) {
  714. $object->fetch($object->id); // Reload lines
  715. unset($_POST['qty']);
  716. unset($_POST['type']);
  717. unset($_POST['productid']);
  718. unset($_POST['remise_percent']);
  719. unset($_POST['price_ht']);
  720. unset($_POST['multicurrency_price_ht']);
  721. unset($_POST['price_ttc']);
  722. unset($_POST['tva_tx']);
  723. unset($_POST['product_ref']);
  724. unset($_POST['product_label']);
  725. unset($_POST['product_desc']);
  726. unset($_POST['fournprice']);
  727. unset($_POST['buying_price']);
  728. unset($_POST['np_marginRate']);
  729. unset($_POST['np_markRate']);
  730. unset($_POST['dp_desc']);
  731. unset($_POST['idprod']);
  732. unset($_POST['units']);
  733. unset($_POST['date_starthour']);
  734. unset($_POST['date_startmin']);
  735. unset($_POST['date_startsec']);
  736. unset($_POST['date_startday']);
  737. unset($_POST['date_startmonth']);
  738. unset($_POST['date_startyear']);
  739. unset($_POST['date_endhour']);
  740. unset($_POST['date_endmin']);
  741. unset($_POST['date_endsec']);
  742. unset($_POST['date_endday']);
  743. unset($_POST['date_endmonth']);
  744. unset($_POST['date_endyear']);
  745. unset($_POST['situations']);
  746. unset($_POST['progress']);
  747. } else {
  748. setEventMessages($object->error, $object->errors, 'errors');
  749. }
  750. }
  751. }
  752. }
  753. /*
  754. * View
  755. */
  756. $help_url = '';
  757. llxHeader('', $langs->trans("RepeatableSupplierInvoice"), $help_url);
  758. $form = new Form($db);
  759. $formother = new FormOther($db);
  760. if (isModEnabled('project')) {
  761. $formproject = new FormProjets($db);
  762. }
  763. $companystatic = new Societe($db);
  764. $invoicerectmp = new FactureFournisseurRec($db);
  765. $now = dol_now();
  766. $nowlasthour = dol_get_last_hour($now);
  767. /*
  768. * Create mode
  769. */
  770. if ($action == 'create') {
  771. print load_fiche_titre($langs->trans("CreateRepeatableInvoice"), '', 'bill');
  772. $object = new FactureFournisseur($db); // Source invoice
  773. $product_static = new Product($db);
  774. if ($object->fetch($id) > 0) {
  775. $result = $object->fetch_lines();
  776. print '<form action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
  777. print '<input type="hidden" name="token" value="' . newToken() . '">';
  778. print '<input type="hidden" name="action" value="add">';
  779. print '<input type="hidden" name="facid" value="' . $object->id . '">';
  780. print dol_get_fiche_head(null, '', '', 0);
  781. $rowspan = 4;
  782. if (isModEnabled('project')) $rowspan++;
  783. if ($object->fk_account > 0) $rowspan++;
  784. print '<table class="border centpercent">';
  785. $object->fetch_thirdparty();
  786. // Title
  787. print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans("Title") . '</td><td>';
  788. print '<input class="flat quatrevingtpercent" type="text" name="title" value="' . dol_escape_htmltag(GETPOST("title", 'alphanohtml')) . '">';
  789. print '</td></tr>';
  790. // Ref supplier
  791. print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans("SupplierRef") . '</td><td>';
  792. print '<input class="flat quatrevingtpercent" type="text" name="ref_supplier" value="' . $object->ref_supplier . '">';
  793. print '</td></tr>';
  794. // Third party
  795. print '<tr><td class="titlefieldcreate">' . $langs->trans("Customer") . '</td><td>' . $object->thirdparty->getNomUrl(1, 'customer') . '</td>';
  796. print '</tr>';
  797. $note_public = GETPOSTISSET('note_public') ? GETPOST('note_public', 'restricthtml') : $object->note_public;
  798. $note_private = GETPOSTISSET('note_private') ? GETPOST('note_private', 'restricthtml') : $object->note_private;
  799. // Help of substitution key
  800. $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
  801. $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%m') . ')';
  802. $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($object->date, '%m') . ')';
  803. $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%m') . ')';
  804. $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date, -1, 'm'), '%B') . ')';
  805. $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($object->date, '%B') . ')';
  806. $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date, 1, 'm'), '%B') . ')';
  807. $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date, -1, 'y'), '%Y') . ')';
  808. $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($object->date, '%Y') . ')';
  809. $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date, 1, 'y'), '%Y') . ')';
  810. // Only on template invoices
  811. $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = $langs->trans("DateNextInvoiceBeforeGen") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($object->date_when, 'dayhour') . ')';
  812. $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = $langs->trans("DateNextInvoiceAfterGen") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($object->date_when, $object->frequency, $object->unit_frequency), 'dayhour') . ')';
  813. $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $langs->trans("Count");
  814. $substitutionarray['__INVOICE_COUNTER_MAX__'] = $langs->trans("MaxPeriodNumber");
  815. $htmltext = '<i>' . $langs->trans("FollowingConstantsWillBeSubstituted") . ':<br>';
  816. foreach ($substitutionarray as $key => $val) {
  817. $htmltext .= $key . ' = ' . $langs->trans($val) . '<br>';
  818. }
  819. $htmltext .= '</i>';
  820. // Libelle
  821. print '<tr><td class="titlefieldcreate">' . $langs->trans("Label") . '</td><td>';
  822. print '<input class="flat quatrevingtpercent" type="text" name="libelle" value="' . $object->label . '">';
  823. print '</td></tr>';
  824. // Public note
  825. print '<tr>';
  826. print '<td class="tdtop">';
  827. print $form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic');
  828. print '</td>';
  829. print '<td>';
  830. $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PUBLIC) ? 0 : 1, ROWS_3, '90%');
  831. print $doleditor->Create(1);
  832. // Private note
  833. if (empty($user->socid)) {
  834. print '<tr>';
  835. print '<td class="tdtop">';
  836. print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext, 1, 'help', '', 0, 2, 'noteprivate');
  837. print '</td>';
  838. print '<td>';
  839. $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, empty($conf->global->FCKEDITOR_ENABLE_NOTE_PRIVATE) ? 0 : 1, ROWS_3, '90%');
  840. print $doleditor->Create(1);
  841. print '</td></tr>';
  842. }
  843. // Author
  844. print "<tr><td>" . $langs->trans("Author") . "</td><td>" . $user->getFullName($langs) . "</td></tr>";
  845. // Payment term
  846. print "<tr><td>" . $langs->trans("PaymentConditions") . "</td><td>";
  847. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->cond_reglement_id, 'none');
  848. print "</td></tr>";
  849. // Payment mode
  850. print "<tr><td>" . $langs->trans("PaymentMode") . "</td><td>";
  851. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'none', '', 1);
  852. print "</td></tr>";
  853. // Project
  854. if (isModEnabled('project') && is_object($object->thirdparty) && $object->thirdparty->id > 0) {
  855. $projectid = GETPOST('projectid') ? GETPOST('projectid') : $object->fk_project;
  856. $langs->load('projects');
  857. print '<tr><td>' . $langs->trans('Project') . '</td><td>';
  858. $numprojet = $formproject->select_projects($object->thirdparty->id, $projectid, 'projectid', 0, 0, 1, 0, 0, 0, 0, '', 0, 0, '');
  859. print ' &nbsp; <a href="' . DOL_URL_ROOT . '/projet/card.php?socid=' . $object->thirdparty->id . '&action=create&status=1&backtopage=' . urlencode($_SERVER["PHP_SELF"] . '?action=create&socid=' . $object->thirdparty->id . (!empty($id) ? '&id=' . $id : '')) . '">' . $langs->trans("AddProject") . '</a>';
  860. print '</td></tr>';
  861. }
  862. // Bank account
  863. if ($object->fk_account > 0) {
  864. print "<tr><td>" . $langs->trans('BankAccount') . "</td><td>";
  865. $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_account, 'none');
  866. print "</td></tr>";
  867. }
  868. // Model pdf
  869. print "<tr><td>" . $langs->trans('Model') . "</td><td>";
  870. include_once DOL_DOCUMENT_ROOT . '/core/modules/supplier_invoice/modules_facturefournisseur.php';
  871. $list = ModelePDFSuppliersInvoices::liste_modeles($db);
  872. print $form->selectarray('modelpdf', $list, $conf->global->INVOICE_SUPPLIER_ADDON_PDF);
  873. print "</td></tr>";
  874. print "</table>";
  875. print dol_get_fiche_end();
  876. // Autogeneration
  877. $title = $langs->trans("Recurrence");
  878. print load_fiche_titre(img_picto('', 'recurring', 'class="pictofixedwidth"') . $title, '', '');
  879. print dol_get_fiche_head(null, '', '', 0);
  880. print '<table class="border centpercent">';
  881. // Frequency + unit
  882. print '<tr><td class="titlefieldcreate">' . $form->textwithpicto($langs->trans("Frequency"), $langs->transnoentitiesnoconv('toolTipFrequency')) . "</td><td>";
  883. print "<input type='text' name='frequency' value='" . GETPOST('frequency', 'int') . "' size='4' />&nbsp;" . $form->selectarray('unit_frequency', array('d' => $langs->trans('Day'), 'm' => $langs->trans('Month'), 'y' => $langs->trans('Year')), (GETPOST('unit_frequency') ? GETPOST('unit_frequency') : 'm'));
  884. print "</td></tr>";
  885. // Date next run
  886. print "<tr><td>" . $langs->trans('NextDateToExecution') . "</td><td>";
  887. $date_next_execution = isset($date_next_execution) ? $date_next_execution : (GETPOST('remonth') ? dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear')) : -1);
  888. print $form->selectDate($date_next_execution, '', 1, 1, '', "add", 1, 1);
  889. print "</td></tr>";
  890. // Number max of generation
  891. print "<tr><td>" . $langs->trans("MaxPeriodNumber") . "</td><td>";
  892. print '<input type="text" name="nb_gen_max" value="' . GETPOST('nb_gen_max') . '" size="5" />';
  893. print "</td></tr>";
  894. // Auto validate the invoice
  895. print "<tr><td>" . $langs->trans("StatusOfGeneratedInvoices") . "</td><td>";
  896. $select = array('0' => $langs->trans('BillStatusDraft'), '1' => $langs->trans('BillStatusValidated'));
  897. print $form->selectarray('auto_validate', $select, GETPOST('auto_validate'));
  898. print "</td></tr>";
  899. // Auto generate document
  900. if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
  901. print "<tr><td>" . $langs->trans("StatusOfGeneratedDocuments") . "</td><td>";
  902. $select = array('0' => $langs->trans('DoNotGenerateDoc'), '1' => $langs->trans('AutoGenerateDoc'));
  903. print $form->selectarray('generate_pdf', $select, GETPOST('generate_pdf'));
  904. print "</td></tr>";
  905. } else {
  906. print '<input type="hidden" name="generate_pdf" value="1">';
  907. }
  908. print "</table>";
  909. print dol_get_fiche_end();
  910. $title = $langs->trans("ProductsAndServices");
  911. if (empty($conf->service->enabled)) {
  912. $title = $langs->trans("Products");
  913. } elseif (empty($conf->product->enabled)) {
  914. $title = $langs->trans("Services");
  915. }
  916. print load_fiche_titre($title, '', '');
  917. /*
  918. * Invoice lines
  919. */
  920. print '<div class="div-table-responsive-no-min">';
  921. print '<table id="tablelines" class="noborder noshadow" width="100%">';
  922. // Show object lines
  923. if (!empty($object->lines)) {
  924. $disableedit = 1;
  925. $disablemove = 1;
  926. $disableremove = 1;
  927. $object->printObjectLines('', $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
  928. }
  929. print "</table>\n";
  930. print '<div>';
  931. print '</td></tr>';
  932. print "</table>\n";
  933. print $form->buttonsSaveCancel("Create");
  934. print "</form>\n";
  935. } else {
  936. dol_print_error('', "Error, no invoice " . $object->id);
  937. }
  938. } else {
  939. /*
  940. * View mode
  941. */
  942. if ($object->id > 0) {
  943. $object->fetch($object->id);
  944. $object->fetch_thirdparty();
  945. // Confirmation de la suppression d'une ligne produit
  946. if ($action == 'ask_deleteline') {
  947. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
  948. }
  949. // Confirm delete of repeatable invoice
  950. if ($action == 'ask_deleteinvoice') {
  951. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteRepeatableInvoice'), $langs->trans('ConfirmDeleteRepeatableInvoice'), 'confirm_deleteinvoice', '', 'no', 1);
  952. }
  953. print $formconfirm;
  954. $author = new User($db);
  955. $author->fetch($object->user_author);
  956. $head = supplier_invoice_rec_prepare_head($object);
  957. print dol_get_fiche_head($head, 'card', $langs->trans('RepeatableInvoice'), -1, 'bill'); // Add a div
  958. // Recurring invoice content
  959. $linkback = '<a href="' . DOL_URL_ROOT . '/fourn/facture/list-rec.php?restore_lastsearch_values=1' . (!empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans('BackToList') . '</a>';
  960. $morehtmlref = '';
  961. if ($action != 'edittitle') {
  962. $morehtmlref .= $form->editfieldkey($object->titre, 'title', $object->titre, $object, $usercancreate, '', '', 0, 2);
  963. } else {
  964. $morehtmlref .= $form->editfieldval('', 'title', $object->titre, $object, $usercancreate, 'string');
  965. }
  966. $morehtmlref .= '<div class="refidno">';
  967. //Ref supplier
  968. $morehtmlref .= $form->editfieldkey("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string', '', 0, 1);
  969. $morehtmlref .= $form->editfieldval("RefSupplier", 'ref_supplier', $object->ref_supplier, $object, $usercancreate, 'string', '', null, null, '', 1);
  970. // Thirdparty
  971. $morehtmlref .= '<br>' . $langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1);
  972. // Project
  973. if (isModEnabled('project')) {
  974. $langs->load('projects');
  975. $morehtmlref .= '<br>' . $langs->trans('Project') . ' ';
  976. if ($usercancreate) {
  977. if ($action != 'classify') {
  978. $morehtmlref .= '<a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=classify&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
  979. }
  980. if ($action == 'classify') {
  981. $morehtmlref .= '<form method="post" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '">';
  982. $morehtmlref .= '<input type="hidden" name="action" value="classin">';
  983. $morehtmlref .= '<input type="hidden" name="token" value="' . newToken() . '">';
  984. $morehtmlref .= $formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
  985. $morehtmlref .= '<input type="submit" class="button valignmiddle" value="' . $langs->trans("Modify") . '">';
  986. $morehtmlref .= '</form>';
  987. } else {
  988. $morehtmlref .= $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1, '', 'maxwidth300');
  989. }
  990. } else {
  991. if (!empty($object->fk_project)) {
  992. $project = new Project($db);
  993. $project->fetch($object->fk_project);
  994. $morehtmlref .= ' : ' . $project->getNomUrl(1);
  995. if ($project->title) {
  996. $morehtmlref .= ' - ' . $project->title;
  997. }
  998. } else {
  999. $morehtmlref .= '';
  1000. }
  1001. }
  1002. }
  1003. $morehtmlref .= '</div>';
  1004. $morehtmlright = '';
  1005. dol_banner_tab($object, 'ref', $linkback, 1, 'title', 'none', $morehtmlref, '', 0, '', $morehtmlright);
  1006. print '<div class="fichecenter">';
  1007. print '<div class="fichehalfleft">';
  1008. print '<div class="underbanner clearboth"></div>';
  1009. print '<table class="border centpercent tableforfield">';
  1010. print '<tr><td class="titlefield">' . $langs->trans('Author') . '</td><td>';
  1011. print $author->getNomUrl(-1);
  1012. print "</td></tr>";
  1013. // Label
  1014. print '<tr>';
  1015. print '<td>' . $form->editfieldkey("Label", 'libelle', $object->libelle, $object, $usercancreate) . '</td>';
  1016. print '<td>' . $form->editfieldval("Label", 'libelle', $object->libelle, $object, $usercancreate) . '</td>';
  1017. print '</tr>';
  1018. print '<tr><td>' . $langs->trans('AmountHT') . '</td>';
  1019. print '<td>' . price($object->total_ht, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
  1020. print '</tr>';
  1021. print '<tr><td>' . $langs->trans("AmountVAT") . '</td><td>' . price($object->total_tva, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
  1022. print '</tr>';
  1023. // Amount Local Taxes
  1024. if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) { // Localtax1
  1025. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
  1026. print '<td class="nowrap">' . price($object->total_localtax1, 1, '', 1, -1, -1, $conf->currency) . '</td></tr>';
  1027. }
  1028. if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) { // Localtax2
  1029. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
  1030. print '<td class=nowrap">' . price($object->total_localtax2, 1, '', 1, -1, -1, $conf->currency) . '</td></tr>';
  1031. }
  1032. print '<tr><td>' . $langs->trans("AmountTTC") . '</td><td colspan="3">' . price($object->total_ttc, '', $langs, 1, -1, -1, $conf->currency) . '</td>';
  1033. print '</tr>';
  1034. // Payment term
  1035. print '<tr><td>';
  1036. print '<table class="nobordernopadding centpercent"><tr><td>';
  1037. print $langs->trans('PaymentConditionsShort');
  1038. print '</td>';
  1039. if ($action != 'editconditions' && $usercancreate) {
  1040. print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editconditions&token=' . newToken() . '&facid=' . $object->id . '">' . img_edit($langs->trans('SetConditions'), 1) . '</a></td>';
  1041. }
  1042. print '</tr></table>';
  1043. print '</td><td>';
  1044. if ($action == 'editconditions') {
  1045. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id');
  1046. } else {
  1047. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'none');
  1048. }
  1049. print '</td></tr>';
  1050. // Payment mode
  1051. print '<tr><td>';
  1052. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1053. print $langs->trans('PaymentMode');
  1054. print '</td>';
  1055. if ($action != 'editmode' && $usercancreate) {
  1056. print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editmode&token=' . newToken() . '&facid=' . $object->id . '">' . img_edit($langs->trans('SetMode'), 1) . '</a></td>';
  1057. }
  1058. print '</tr></table>';
  1059. print '</td><td>';
  1060. if ($action == 'editmode') {
  1061. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT', 1, 1);
  1062. } else {
  1063. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->mode_reglement_id, 'none');
  1064. }
  1065. print '</td></tr>';
  1066. // Multicurrency
  1067. if (isModEnabled("multicurrency")) {
  1068. // Multicurrency code
  1069. print '<tr>';
  1070. print '<td>';
  1071. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1072. print $form->editfieldkey('Currency', 'multicurrency_code', '', $object, 0);
  1073. print '</td>';
  1074. if ($usercancreate && $action != 'editmulticurrencycode' && !empty($object->brouillon)) {
  1075. print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencycode&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
  1076. }
  1077. print '</tr></table>';
  1078. print '</td><td>';
  1079. $htmlname = (($usercancreate && $action == 'editmulticurrencycode') ? 'multicurrency_code' : 'none');
  1080. $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, $htmlname);
  1081. print '</td></tr>';
  1082. // Multicurrency rate
  1083. if ($object->multicurrency_code != $conf->currency || $object->multicurrency_tx != 1) {
  1084. print '<tr>';
  1085. print '<td>';
  1086. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1087. print $form->editfieldkey('CurrencyRate', 'multicurrency_tx', '', $object, 0);
  1088. print '</td>';
  1089. if ($usercancreate && $action != 'editmulticurrencyrate' && !empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
  1090. print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
  1091. }
  1092. print '</tr></table>';
  1093. print '</td><td>';
  1094. if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
  1095. if ($action == 'actualizemulticurrencyrate') {
  1096. list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
  1097. }
  1098. $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, ($usercancreate ? 'multicurrency_tx' : 'none'), $object->multicurrency_code);
  1099. } else {
  1100. $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
  1101. if ($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
  1102. print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
  1103. print '<a href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&action=actualizemulticurrencyrate">' . $langs->trans("ActualizeCurrency") . '</a>';
  1104. print '</div>';
  1105. }
  1106. }
  1107. print '</td></tr>';
  1108. }
  1109. }
  1110. // Help of substitution key
  1111. $dateexample = dol_now();
  1112. if (!empty($object->frequency) && !empty($object->date_when)) {
  1113. $dateexample = $object->date_when;
  1114. }
  1115. $substitutionarray = getCommonSubstitutionArray($langs, 2, null, $object);
  1116. $substitutionarray['__INVOICE_PREVIOUS_MONTH__'] = $langs->trans("PreviousMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%m') . ')';
  1117. $substitutionarray['__INVOICE_MONTH__'] = $langs->trans("MonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($dateexample, '%m') . ')';
  1118. $substitutionarray['__INVOICE_NEXT_MONTH__'] = $langs->trans("NextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%m') . ')';
  1119. $substitutionarray['__INVOICE_PREVIOUS_MONTH_TEXT__'] = $langs->trans("TextPreviousMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'), '%B') . ')';
  1120. $substitutionarray['__INVOICE_MONTH_TEXT__'] = $langs->trans("TextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($dateexample, '%B') . ')';
  1121. $substitutionarray['__INVOICE_NEXT_MONTH_TEXT__'] = $langs->trans("TextNextMonthOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B') . ')';
  1122. $substitutionarray['__INVOICE_PREVIOUS_YEAR__'] = $langs->trans("PreviousYearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'), '%Y') . ')';
  1123. $substitutionarray['__INVOICE_YEAR__'] = $langs->trans("YearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date($dateexample, '%Y') . ')';
  1124. $substitutionarray['__INVOICE_NEXT_YEAR__'] = $langs->trans("NextYearOfInvoice") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'), '%Y') . ')';
  1125. // Only on template invoices
  1126. $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_BEFORE_GEN__'] = $langs->trans("DateNextInvoiceBeforeGen") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(($object->date_when ? $object->date_when : dol_now()), 'dayhour') . ')';
  1127. $substitutionarray['__INVOICE_DATE_NEXT_INVOICE_AFTER_GEN__'] = $langs->trans("DateNextInvoiceAfterGen") . ' (' . $langs->trans("Example") . ': ' . dol_print_date(dol_time_plus_duree(($object->date_when ? $object->date_when : dol_now()), $object->frequency, $object->unit_frequency), 'dayhour') . ')';
  1128. $substitutionarray['__INVOICE_COUNTER_CURRENT__'] = $object->nb_gen_done;
  1129. $substitutionarray['__INVOICE_COUNTER_MAX__'] = $object->nb_gen_max;
  1130. $htmltext = '<i>' . $langs->trans("FollowingConstantsWillBeSubstituted") . ':<br>';
  1131. foreach ($substitutionarray as $key => $val) {
  1132. $htmltext .= $key . ' = ' . $langs->trans($val) . '<br>';
  1133. }
  1134. $htmltext .= '</i>';
  1135. // Note public
  1136. print '<tr><td>';
  1137. print $form->editfieldkey($form->textwithpicto($langs->trans('NotePublic'), $htmltext, 1, 'help', '', 0, 2, 'notepublic'), 'note_public', $object->note_public, $object, $usercancreate);
  1138. print '</td><td class="wordbreak">';
  1139. print $form->editfieldval($langs->trans("NotePublic"), 'note_public', $object->note_public, $object, $usercancreate, 'textarea:' . ROWS_4 . ':90%', '', null, null, '', 1);
  1140. print '</td>';
  1141. print '</tr>';
  1142. // Note private
  1143. print '<tr><td>';
  1144. print $form->editfieldkey($form->textwithpicto($langs->trans("NotePrivate"), $htmltext, 1, 'help', '', 0, 2, 'noteprivate'), 'note_private', $object->note_private, $object, $usercancreate);
  1145. print '</td><td class="wordbreak">';
  1146. print $form->editfieldval($langs->trans("NotePrivate"), 'note_private', $object->note_private, $object, $usercancreate, 'textarea:' . ROWS_4 . ':90%', '', null, null, '', 1);
  1147. print '</td>';
  1148. print '</tr>';
  1149. // Bank Account
  1150. print '<tr><td class="nowrap">';
  1151. print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
  1152. print $langs->trans('BankAccount');
  1153. print '<td>';
  1154. if ($action != 'editbankaccount' && $usercancreate && $object->statut == FactureFournisseurRec::STATUS_NOTSUSPENDED) {
  1155. print '<td class="right"><a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=editbankaccount&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->trans('SetBankAccount'), 1) . '</a></td>';
  1156. }
  1157. print '</tr></table>';
  1158. print '</td><td>';
  1159. if ($action == 'editbankaccount') {
  1160. $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_account, 'fk_account', 1);
  1161. } else {
  1162. $form->formSelectAccount($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->fk_account, 'none');
  1163. }
  1164. print "</td>";
  1165. print '</tr>';
  1166. // Model pdf
  1167. print '<tr><td class="nowrap">';
  1168. print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
  1169. print $langs->trans('Model');
  1170. print '<td>';
  1171. if ($action != 'editmodelpdf' && $usercancreate && $object->statut == FactureFournisseurRec::STATUS_NOTSUSPENDED) {
  1172. print '<td class="right"><a class="editfielda" href="' . $_SERVER['PHP_SELF'] . '?action=editmodelpdf&token=' . newToken() . '&id=' . $object->id . '">' . img_edit($langs->trans('SetModel'), 1) . '</a></td>';
  1173. }
  1174. print '</tr></table>';
  1175. print '</td><td>';
  1176. if ($action == 'editmodelpdf') {
  1177. include_once DOL_DOCUMENT_ROOT . '/core/modules/supplier_invoice/modules_facturefournisseur.php';
  1178. $list = array();
  1179. $models = ModelePDFSuppliersInvoices::liste_modeles($db);
  1180. foreach ($models as $k => $model) {
  1181. $list[] = str_replace(':', '|', $k) . ':' . $model;
  1182. }
  1183. $select = 'select;' . implode(',', $list);
  1184. //TODO : Droits
  1185. print $form->editfieldval($langs->trans('Model'), 'modelpdf', $object->model_pdf, $object, $usercancreate, $select);
  1186. } else {
  1187. print $object->model_pdf;
  1188. }
  1189. print "</td>";
  1190. print '</tr>';
  1191. // Other attributes
  1192. $cols = 2;
  1193. include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
  1194. print '</table>';
  1195. print '</div>';
  1196. print '<div class="fichehalfright">';
  1197. print '<div class="underbanner clearboth"></div>';
  1198. /*
  1199. * Recurrence
  1200. */
  1201. $title = $langs->trans("Recurrence");
  1202. //print load_fiche_titre($title, '', 'calendar');
  1203. print '<table class="border centpercent tableforfield">';
  1204. print '<tr><td colspan="2">' . img_picto('', 'recurring', 'class="pictofixedwidth"') . $title . '</td></tr>';
  1205. // if "frequency" is empty or = 0, the reccurence is disabled
  1206. print '<tr><td style="width: 50%">';
  1207. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1208. print $langs->trans('Frequency');
  1209. print '</td>';
  1210. if ($action != 'editfrequency' && $usercancreate) {
  1211. print '<td class="right"><a class="editfielda" href="' . $_SERVER["PHP_SELF"] . '?action=editfrequency&token=' . newToken() . '&facid=' . $object->id . '">' . img_edit($langs->trans('Edit'), 1) . '</a></td>';
  1212. }
  1213. print '</tr></table>';
  1214. print '</td><td>';
  1215. if ($action == 'editfrequency') {
  1216. print '<form method="post" action="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '">';
  1217. print '<input type="hidden" name="action" value="setfrequency">';
  1218. print '<input type="hidden" name="token" value="' . newToken() . '">';
  1219. print '<table class="nobordernopadding">';
  1220. print '<tr><td>';
  1221. print "<input type='text' name='frequency' value='" . $object->frequency . "' size='5' />&nbsp;" . $form->selectarray('unit_frequency', array('d' => $langs->trans('Day'), 'm' => $langs->trans('Month'), 'y' => $langs->trans('Year')), ($object->unit_frequency ? $object->unit_frequency : 'm'));
  1222. print '</td>';
  1223. print '<td class="left"><input type="submit" class="button button-edit" value="' . $langs->trans("Modify") . '"></td>';
  1224. print '</tr></table></form>';
  1225. } else {
  1226. if ($object->frequency > 0) {
  1227. print $langs->trans('FrequencyPer_' . $object->unit_frequency, $object->frequency);
  1228. } else {
  1229. print $langs->trans("NotARecurringInvoiceTemplate");
  1230. }
  1231. }
  1232. print '</td></tr>';
  1233. // Date when (next invoice generation)
  1234. print '<tr><td>';
  1235. if ($action == 'date_when' || $object->frequency > 0) {
  1236. print $form->editfieldkey($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $usercancreate, 'day');
  1237. } else {
  1238. print $langs->trans("NextDateToExecution");
  1239. }
  1240. print '</td><td>';
  1241. if ($action == 'date_when' || $object->frequency > 0) {
  1242. print $form->editfieldval($langs->trans("NextDateToExecution"), 'date_when', $object->date_when, $object, $usercancreate, 'day', $object->date_when, null, '', '', 0, 'strikeIfMaxNbGenReached');
  1243. }
  1244. //var_dump(dol_print_date($object->date_when+60, 'dayhour').' - '.dol_print_date($now, 'dayhour'));
  1245. if (! $object->isMaxNbGenReached()) {
  1246. if (! $object->suspended && $action != 'editdate_when' && $object->frequency > 0 && $object->date_when && $object->date_when < $now) {
  1247. print img_warning($langs->trans("Late"));
  1248. }
  1249. } else {
  1250. print img_info($langs->trans("MaxNumberOfGenerationReached"));
  1251. }
  1252. print '</td>';
  1253. print '</tr>';
  1254. // Max period / Rest period
  1255. print '<tr><td>';
  1256. if ($action == 'nb_gen_max' || $object->frequency > 0) {
  1257. print $form->editfieldkey($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max, $object, $usercancreate);
  1258. } else {
  1259. print $langs->trans("MaxPeriodNumber");
  1260. }
  1261. print '</td><td>';
  1262. if ($action == 'nb_gen_max' || $object->frequency > 0) {
  1263. print $form->editfieldval($langs->trans("MaxPeriodNumber"), 'nb_gen_max', $object->nb_gen_max ? $object->nb_gen_max : '', $object, $usercancreate);
  1264. } else {
  1265. print '';
  1266. }
  1267. print '</td>';
  1268. print '</tr>';
  1269. // Status of generated invoices
  1270. print '<tr><td>';
  1271. if ($action == 'auto_validate' || $object->frequency > 0) {
  1272. print $form->editfieldkey($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $usercancreate);
  1273. } else {
  1274. print $langs->trans("StatusOfGeneratedInvoices");
  1275. }
  1276. print '</td><td>';
  1277. $select = 'select;0:' . $langs->trans('BillStatusDraft') . ',1:' . $langs->trans('BillStatusValidated');
  1278. if ($action == 'auto_validate' || $object->frequency > 0) {
  1279. print $form->editfieldval($langs->trans("StatusOfGeneratedInvoices"), 'auto_validate', $object->auto_validate, $object, $usercancreate, $select);
  1280. }
  1281. print '</td>';
  1282. // Auto generate documents
  1283. if (!empty($conf->global->INVOICE_REC_CAN_DISABLE_DOCUMENT_FILE_GENERATION)) {
  1284. print '<tr>';
  1285. print '<td>';
  1286. if ($action == 'generate_pdf' || $object->frequency > 0) {
  1287. print $form->editfieldkey($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $usercancreate);
  1288. } else {
  1289. print $langs->trans("StatusOfGeneratedDocuments");
  1290. }
  1291. print '</td>';
  1292. print '<td>';
  1293. $select = 'select;0:' . $langs->trans('DoNotGenerateDoc') . ',1:' . $langs->trans('AutogenerateDoc');
  1294. if ($action == 'generate_pdf' || $object->frequency > 0) {
  1295. print $form->editfieldval($langs->trans("StatusOfGeneratedDocuments"), 'generate_pdf', $object->generate_pdf, $object, $usercancreate, $select);
  1296. }
  1297. print '</td>';
  1298. print '</tr>';
  1299. } else {
  1300. print '<input type="hidden" name="generate_pdf" value="1">';
  1301. }
  1302. print '</table>';
  1303. // Frequencry/Recurring section
  1304. if ($object->frequency > 0) {
  1305. print '<br>';
  1306. if (empty($conf->cron->enabled)) {
  1307. print info_admin($langs->trans("EnableAndSetupModuleCron", $langs->transnoentitiesnoconv("Module2300Name")));
  1308. }
  1309. print '<div class="underbanner clearboth"></div>';
  1310. print '<table class="border centpercent tableforfield">';
  1311. // Nb of generation already done
  1312. print '<tr><td style="width: 50%">' . $langs->trans("NbOfGenerationDone") . '</td>';
  1313. print '<td>';
  1314. print $object->nb_gen_done ? $object->nb_gen_done : '0';
  1315. print '</td>';
  1316. print '</tr>';
  1317. // Date last
  1318. print '<tr><td>';
  1319. print $langs->trans("DateLastGeneration");
  1320. print '</td><td>';
  1321. print dol_print_date($object->date_last_gen, 'dayhour');
  1322. print '</td>';
  1323. print '</tr>';
  1324. print '</table>';
  1325. print '<br>';
  1326. }
  1327. print '</div>';
  1328. print '</div>';
  1329. print '<div class="clearboth"></div><br>';
  1330. // Lines
  1331. print ' <form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '#add' : '#line_' . GETPOST('lineid', 'int')) . '" method="POST">
  1332. <input type="hidden" name="token" value="' . newToken() . '">
  1333. <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateline') . '">
  1334. <input type="hidden" name="mode" value="">
  1335. <input type="hidden" name="id" value="' . $object->id . '">
  1336. ';
  1337. if (!empty($conf->use_javascript_ajax) && $object->statut == 0) {
  1338. include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
  1339. }
  1340. print '<div class="div-table-responsive-no-min">';
  1341. print '<table id="tablelines" class="noborder noshadow" width="100%">';
  1342. $object->fetch_lines();
  1343. // Show object lines
  1344. if (!empty($object->lines)) {
  1345. $canchangeproduct = 1;
  1346. // To set ref for getNomURL function
  1347. foreach ($object->lines as $line) {
  1348. $line->ref = $line->label;
  1349. $line->product_label = $line->label;
  1350. $line->subprice = $line->pu_ht;
  1351. }
  1352. global $canchangeproduct;
  1353. $canchangeproduct = 0;
  1354. $object->statut = $object->suspended;
  1355. $object->printObjectLines($action, $mysoc, $object->thirdparty, $lineid, 0); // No date selector for template invoice
  1356. }
  1357. // Form to add new line
  1358. //TODO : Droits
  1359. if ($object->statut == $object::STATUS_DRAFT && $usercancreate && $action != 'valid' && $action != 'editline') {
  1360. if ($action != 'editline') {
  1361. // Add free products/services
  1362. $parameters = array();
  1363. $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1364. if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  1365. if (empty($reshook))
  1366. global $senderissupplier;
  1367. $senderissupplier = 2;
  1368. $object->formAddObjectLine(0, $object->thirdparty, $mysoc); // No date selector for template invoice
  1369. }
  1370. }
  1371. print "</table>\n";
  1372. print '</div>';
  1373. print "</form>\n";
  1374. print dol_get_fiche_end();
  1375. /*
  1376. * Action bar
  1377. */
  1378. print '<div class="tabsAction">';
  1379. if (empty($object->suspended)) {
  1380. if ($usercancreate) {
  1381. if (!empty($object->frequency) && $object->nb_gen_max > 0 && ($object->nb_gen_done >= $object->nb_gen_max)) {
  1382. print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("MaxGenerationReached")) . '">' . $langs->trans("CreateBill") . '</a></div>';
  1383. } else {
  1384. if (empty($object->frequency) || $object->date_when <= $nowlasthour) {
  1385. print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/fourn/facture/card.php?action=create&socid=' . $object->thirdparty->id . '&fac_rec=' . $object->id . '">' . $langs->trans("CreateBill") . '</a></div>';
  1386. } else {
  1387. print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#" title="' . dol_escape_htmltag($langs->trans("DateIsNotEnough")) . '">' . $langs->trans("CreateBill") . '</a></div>';
  1388. }
  1389. }
  1390. } else {
  1391. print '<div class="inline-block divButAction"><a class="butActionRefused classfortooltip" href="#">' . $langs->trans("CreateBill") . '</a></div>';
  1392. }
  1393. }
  1394. if ($usercancreate) {
  1395. if (empty($object->suspended)) {
  1396. print '<div class="inline-block divButAction"><a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?action=disable&id=' . $object->id . '&token=' . newToken() . '">' . $langs->trans("Disable") . '</a></div>';
  1397. } else {
  1398. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?action=enable&id=' . $object->id . '&token=' . newToken() . '">' . $langs->trans("Enable") . '</a></div>';
  1399. }
  1400. }
  1401. // Delete
  1402. print dolGetButtonAction($langs->trans("Delete"), '', 'delete', $_SERVER["PHP_SELF"].'?id='.$object->id.'&action=ask_deleteinvoice&token='.newToken(), 'delete', ($user->rights->fournisseur->facture->supprimer || $user->rights->supplier_invoice->supprimer));
  1403. print '</div>';
  1404. print '<div class="fichecenter"><div class="fichehalfleft">';
  1405. print '<a name="builddoc"></a>'; // ancre
  1406. // Show links to link elements
  1407. $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
  1408. $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem);
  1409. print '</div></div>';
  1410. }
  1411. }
  1412. // End of page
  1413. llxFooter();
  1414. $db->close();