card.php 96 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461
  1. <?php
  2. /* Copyright (C) 2001-2007 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004-2014 Laurent Destailleur <eldy@users.sourceforge.net>
  4. * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
  5. * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
  6. * Copyright (C) 2005-2012 Regis Houssin <regis.houssin@capnetworks.com>
  7. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  8. * Copyright (C) 2010-2014 Juanjo Menent <jmenent@2byte.es>
  9. * Copyright (C) 2010-2015 Philippe Grand <philippe.grand@atoo-net.com>
  10. * Copyright (C) 2012-2013 Christophe Battarel <christophe.battarel@altairis.fr>
  11. * Copyright (C) 2012 Cedric Salvador <csalvador@gpcsolutions.fr>
  12. * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
  13. * Copyright (C) 2014 Ferran Marcet <fmarcet@2byte.es>
  14. *
  15. * This program is free software; you can redistribute it and/or modify
  16. * it under the terms of the GNU General Public License as published by
  17. * the Free Software Foundation; either version 3 of the License, or
  18. * (at your option) any later version.
  19. *
  20. * This program is distributed in the hope that it will be useful,
  21. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  22. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  23. * GNU General Public License for more details.
  24. *
  25. * You should have received a copy of the GNU General Public License
  26. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  27. */
  28. /**
  29. * \file htdocs/comm/propal/card.php
  30. * \ingroup propale
  31. * \brief Page of commercial proposals card and list
  32. */
  33. require '../../main.inc.php';
  34. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
  35. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
  36. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formpropal.class.php';
  37. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmargin.class.php';
  38. require_once DOL_DOCUMENT_ROOT . '/comm/propal/class/propal.class.php';
  39. require_once DOL_DOCUMENT_ROOT . '/comm/action/class/actioncomm.class.php';
  40. require_once DOL_DOCUMENT_ROOT . '/core/modules/propale/modules_propale.php';
  41. require_once DOL_DOCUMENT_ROOT . '/core/lib/propal.lib.php';
  42. require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
  43. require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
  44. require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  45. if (! empty($conf->projet->enabled)) {
  46. require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
  47. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
  48. }
  49. $langs->load('companies');
  50. $langs->load('propal');
  51. $langs->load('compta');
  52. $langs->load('bills');
  53. $langs->load('orders');
  54. $langs->load('products');
  55. $langs->load("deliveries");
  56. $langs->load('sendings');
  57. if (!empty($conf->incoterm->enabled)) $langs->load('incoterm');
  58. if (! empty($conf->margin->enabled))
  59. $langs->load('margins');
  60. $error = 0;
  61. $id = GETPOST('id', 'int');
  62. $ref = GETPOST('ref', 'alpha');
  63. $socid = GETPOST('socid', 'int');
  64. $action = GETPOST('action', 'alpha');
  65. $cancel = GETPOST('cancel', 'alpha');
  66. $origin = GETPOST('origin', 'alpha');
  67. $originid = GETPOST('originid', 'int');
  68. $confirm = GETPOST('confirm', 'alpha');
  69. $lineid = GETPOST('lineid', 'int');
  70. $contactid = GETPOST('contactid','int');
  71. // PDF
  72. $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
  73. $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
  74. $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
  75. // Nombre de ligne pour choix de produit/service predefinis
  76. $NBLINES = 4;
  77. // Security check
  78. if (! empty($user->societe_id)) $socid = $user->societe_id;
  79. $result = restrictedArea($user, 'propal', $id);
  80. $object = new Propal($db);
  81. $extrafields = new ExtraFields($db);
  82. // fetch optionals attributes and labels
  83. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  84. // Load object
  85. if ($id > 0 || ! empty($ref)) {
  86. $ret = $object->fetch($id, $ref);
  87. if ($ret > 0)
  88. $ret = $object->fetch_thirdparty();
  89. if ($ret < 0)
  90. dol_print_error('', $object->error);
  91. }
  92. // Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
  93. $hookmanager->initHooks(array('propalcard','globalcard'));
  94. $permissionnote = $user->rights->propale->creer; // Used by the include of actions_setnotes.inc.php
  95. $permissiondellink=$user->rights->propale->creer; // Used by the include of actions_dellink.inc.php
  96. $permissiontoedit = $user->rights->propale->creer; // Used by the include of actions_lineupdown.inc.php
  97. /*
  98. * Actions
  99. */
  100. $parameters = array('socid' => $socid);
  101. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  102. if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  103. if (empty($reshook))
  104. {
  105. if ($cancel) $action = '';
  106. include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not includ_once
  107. include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
  108. include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once
  109. // Action clone object
  110. if ($action == 'confirm_clone' && $confirm == 'yes')
  111. {
  112. if (! GETPOST('socid', 3))
  113. {
  114. setEventMessages($langs->trans("NoCloneOptionsSpecified"), null, 'errors');
  115. }
  116. else
  117. {
  118. if ($object->id > 0) {
  119. $result = $object->createFromClone($socid);
  120. if ($result > 0) {
  121. header("Location: " . $_SERVER['PHP_SELF'] . '?id=' . $result);
  122. exit();
  123. } else {
  124. if (count($object->errors) > 0) setEventMessages($object->error, $object->errors, 'errors');
  125. $action = '';
  126. }
  127. }
  128. }
  129. }
  130. // Delete proposal
  131. else if ($action == 'confirm_delete' && $confirm == 'yes' && $user->rights->propal->supprimer)
  132. {
  133. $result = $object->delete($user);
  134. if ($result > 0) {
  135. header('Location: ' . DOL_URL_ROOT . '/comm/propal/list.php');
  136. exit();
  137. } else {
  138. $langs->load("errors");
  139. setEventMessages($object->error, $object->errors, 'errors');
  140. }
  141. }
  142. // Remove line
  143. else if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->propal->creer)
  144. {
  145. $result = $object->deleteline($lineid);
  146. // reorder lines
  147. if ($result)
  148. $object->line_order(true);
  149. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  150. // Define output language
  151. $outputlangs = $langs;
  152. if (! empty($conf->global->MAIN_MULTILANGS)) {
  153. $outputlangs = new Translate("", $conf);
  154. $newlang = (GETPOST('lang_id') ? GETPOST('lang_id') : $object->thirdparty->default_lang);
  155. $outputlangs->setDefaultLang($newlang);
  156. }
  157. $ret = $object->fetch($id); // Reload to get new records
  158. $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  159. }
  160. header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $object->id);
  161. exit();
  162. }
  163. // Validation
  164. else if ($action == 'confirm_validate' && $confirm == 'yes' &&
  165. ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->propal->creer))
  166. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->propal->propal_advance->validate)))
  167. )
  168. {
  169. $result = $object->valid($user);
  170. if ($result >= 0)
  171. {
  172. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  173. {
  174. $outputlangs = $langs;
  175. $newlang = '';
  176. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha');
  177. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  178. if (! empty($newlang)) {
  179. $outputlangs = new Translate("", $conf);
  180. $outputlangs->setDefaultLang($newlang);
  181. }
  182. $model=$object->modelpdf;
  183. $ret = $object->fetch($id); // Reload to get new records
  184. $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
  185. }
  186. } else {
  187. $langs->load("errors");
  188. if (count($object->errors) > 0) setEventMessages($object->error, $object->errors, 'errors');
  189. else setEventMessages($langs->trans($object->error), null, 'errors');
  190. }
  191. }
  192. else if ($action == 'setdate' && $user->rights->propal->creer)
  193. {
  194. $datep = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  195. if (empty($datep)) {
  196. $error ++;
  197. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
  198. }
  199. if (! $error) {
  200. $result = $object->set_date($user, $datep);
  201. if ($result < 0)
  202. dol_print_error($db, $object->error);
  203. }
  204. }
  205. else if ($action == 'setecheance' && $user->rights->propal->creer)
  206. {
  207. $result = $object->set_echeance($user, dol_mktime(12, 0, 0, $_POST['echmonth'], $_POST['echday'], $_POST['echyear']));
  208. if ($result < 0)
  209. dol_print_error($db, $object->error);
  210. }
  211. else if ($action == 'setdate_livraison' && $user->rights->propal->creer)
  212. {
  213. $result = $object->set_date_livraison($user, dol_mktime(12, 0, 0, $_POST['date_livraisonmonth'], $_POST['date_livraisonday'], $_POST['date_livraisonyear']));
  214. if ($result < 0)
  215. dol_print_error($db, $object->error);
  216. }
  217. // Positionne ref client
  218. else if ($action == 'set_ref_client' && $user->rights->propal->creer)
  219. {
  220. $object->set_ref_client($user, $_POST['ref_client']);
  221. }
  222. // Set incoterm
  223. elseif ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
  224. {
  225. $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
  226. }
  227. // Create proposal
  228. else if ($action == 'add' && $user->rights->propal->creer)
  229. {
  230. $object->socid = $socid;
  231. $object->fetch_thirdparty();
  232. $datep = dol_mktime(12, 0, 0, GETPOST('remonth'), GETPOST('reday'), GETPOST('reyear'));
  233. $date_delivery = dol_mktime(12, 0, 0, GETPOST('date_livraisonmonth'), GETPOST('date_livraisonday'), GETPOST('date_livraisonyear'));
  234. $duration = GETPOST('duree_validite');
  235. if (empty($datep)) {
  236. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
  237. $action = 'create';
  238. $error ++;
  239. }
  240. if (empty($duration)) {
  241. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ValidityDuration")), null, 'errors');
  242. $action = 'create';
  243. $error ++;
  244. }
  245. if ($socid < 1) {
  246. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Customer")), null, 'errors');
  247. $action = 'create';
  248. $error ++;
  249. }
  250. if (! $error)
  251. {
  252. $db->begin();
  253. // If we select proposal to clone during creation (when option PROPAL_CLONE_ON_CREATE_PAGE is on)
  254. if (GETPOST('createmode') == 'copy' && GETPOST('copie_propal'))
  255. {
  256. if ($object->fetch(GETPOST('copie_propal')) > 0) {
  257. $object->ref = GETPOST('ref');
  258. $object->datep = $datep;
  259. $object->date_livraison = $date_delivery;
  260. $object->availability_id = GETPOST('availability_id');
  261. $object->demand_reason_id = GETPOST('demand_reason_id');
  262. $object->fk_delivery_address = GETPOST('fk_address');
  263. $object->shipping_method_id = GETPOST('shipping_method_id', 'int');
  264. $object->duree_validite = $duration;
  265. $object->cond_reglement_id = GETPOST('cond_reglement_id');
  266. $object->mode_reglement_id = GETPOST('mode_reglement_id');
  267. $object->fk_account = GETPOST('fk_account', 'int');
  268. $object->remise_percent = GETPOST('remise_percent');
  269. $object->remise_absolue = GETPOST('remise_absolue');
  270. $object->socid = GETPOST('socid');
  271. $object->contactid = GETPOST('contactid');
  272. $object->fk_project = GETPOST('projectid');
  273. $object->modelpdf = GETPOST('model');
  274. $object->author = $user->id; // deprecated
  275. $object->note_private = GETPOST('note_private');
  276. $object->note_public = GETPOST('note_public');
  277. $object->statut = Propal::STATUS_DRAFT;
  278. $object->fk_incoterms = GETPOST('incoterm_id', 'int');
  279. $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
  280. // the create is done below and further more the existing create_from function is quite hilarating
  281. //$id = $object->create_from($user);
  282. } else {
  283. setEventMessages($langs->trans("ErrorFailedToCopyProposal", GETPOST('copie_propal')), null, 'errors');
  284. }
  285. } else {
  286. $object->ref = GETPOST('ref');
  287. $object->ref_client = GETPOST('ref_client');
  288. $object->datep = $datep;
  289. $object->date_livraison = $date_delivery;
  290. $object->availability_id = GETPOST('availability_id');
  291. $object->demand_reason_id = GETPOST('demand_reason_id');
  292. $object->fk_delivery_address = GETPOST('fk_address');
  293. $object->shipping_method_id = GETPOST('shipping_method_id', 'int');
  294. $object->duree_validite = GETPOST('duree_validite');
  295. $object->cond_reglement_id = GETPOST('cond_reglement_id');
  296. $object->mode_reglement_id = GETPOST('mode_reglement_id');
  297. $object->fk_account = GETPOST('fk_account', 'int');
  298. $object->contactid = GETPOST('contactid');
  299. $object->fk_project = GETPOST('projectid');
  300. $object->modelpdf = GETPOST('model');
  301. $object->author = $user->id; // deprecated
  302. $object->note_private = GETPOST('note_private');
  303. $object->note_public = GETPOST('note_public');
  304. $object->fk_incoterms = GETPOST('incoterm_id', 'int');
  305. $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
  306. $object->origin = GETPOST('origin');
  307. $object->origin_id = GETPOST('originid');
  308. // Multicurrency
  309. if (!empty($conf->multicurrency->enabled))
  310. {
  311. $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
  312. }
  313. for($i = 1; $i <= $conf->global->PRODUCT_SHOW_WHEN_CREATE; $i ++)
  314. {
  315. if ($_POST['idprod' . $i]) {
  316. $xid = 'idprod' . $i;
  317. $xqty = 'qty' . $i;
  318. $xremise = 'remise' . $i;
  319. $object->add_product($_POST[$xid], $_POST[$xqty], $_POST[$xremise]);
  320. }
  321. }
  322. // Fill array 'array_options' with data from add form
  323. $ret = $extrafields->setOptionalsFromPost($extralabels, $object);
  324. if ($ret < 0) {
  325. $error ++;
  326. $action = 'create';
  327. }
  328. }
  329. if (! $error)
  330. {
  331. if ($origin && $originid)
  332. {
  333. // Parse element/subelement (ex: project_task)
  334. $element = $subelement = $origin;
  335. if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
  336. $element = $regs [1];
  337. $subelement = $regs [2];
  338. }
  339. // For compatibility
  340. if ($element == 'order') {
  341. $element = $subelement = 'commande';
  342. }
  343. if ($element == 'propal') {
  344. $element = 'comm/propal';
  345. $subelement = 'propal';
  346. }
  347. if ($element == 'contract') {
  348. $element = $subelement = 'contrat';
  349. }
  350. if ($element == 'inter') {
  351. $element = $subelement = 'ficheinter';
  352. }
  353. if ($element == 'shipping') {
  354. $element = $subelement = 'expedition';
  355. }
  356. $object->origin = $origin;
  357. $object->origin_id = $originid;
  358. // Possibility to add external linked objects with hooks
  359. $object->linked_objects [$object->origin] = $object->origin_id;
  360. if (is_array($_POST['other_linked_objects']) && ! empty($_POST['other_linked_objects'])) {
  361. $object->linked_objects = array_merge($object->linked_objects, $_POST['other_linked_objects']);
  362. }
  363. $id = $object->create($user);
  364. if ($id > 0)
  365. {
  366. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  367. $classname = ucfirst($subelement);
  368. $srcobject = new $classname($db);
  369. dol_syslog("Try to find source object origin=" . $object->origin . " originid=" . $object->origin_id . " to add lines");
  370. $result = $srcobject->fetch($object->origin_id);
  371. if ($result > 0)
  372. {
  373. $lines = $srcobject->lines;
  374. if (empty($lines) && method_exists($srcobject, 'fetch_lines'))
  375. {
  376. $srcobject->fetch_lines();
  377. $lines = $srcobject->lines;
  378. }
  379. $fk_parent_line=0;
  380. $num=count($lines);
  381. for ($i=0;$i<$num;$i++)
  382. {
  383. $label=(! empty($lines[$i]->label)?$lines[$i]->label:'');
  384. $desc=(! empty($lines[$i]->desc)?$lines[$i]->desc:$lines[$i]->libelle);
  385. // Positive line
  386. $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
  387. // Date start
  388. $date_start = false;
  389. if ($lines[$i]->date_debut_prevue)
  390. $date_start = $lines[$i]->date_debut_prevue;
  391. if ($lines[$i]->date_debut_reel)
  392. $date_start = $lines[$i]->date_debut_reel;
  393. if ($lines[$i]->date_start)
  394. $date_start = $lines[$i]->date_start;
  395. // Date end
  396. $date_end = false;
  397. if ($lines[$i]->date_fin_prevue)
  398. $date_end = $lines[$i]->date_fin_prevue;
  399. if ($lines[$i]->date_fin_reel)
  400. $date_end = $lines[$i]->date_fin_reel;
  401. if ($lines[$i]->date_end)
  402. $date_end = $lines[$i]->date_end;
  403. // Reset fk_parent_line for no child products and special product
  404. if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
  405. $fk_parent_line = 0;
  406. }
  407. // Extrafields
  408. if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines[$i], 'fetch_optionals')) {
  409. $lines[$i]->fetch_optionals($lines[$i]->rowid);
  410. $array_options = $lines[$i]->array_options;
  411. }
  412. $result = $object->addline($desc, $lines[$i]->subprice, $lines[$i]->qty, $lines[$i]->tva_tx, $lines[$i]->localtax1_tx, $lines[$i]->localtax2_tx, $lines[$i]->fk_product, $lines[$i]->remise_percent, 'HT', 0, $lines[$i]->info_bits, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label, $date_start, $date_end, $array_options, $lines[$i]->fk_unit);
  413. if ($result > 0) {
  414. $lineid = $result;
  415. } else {
  416. $lineid = 0;
  417. $error ++;
  418. break;
  419. }
  420. // Defined the new fk_parent_line
  421. if ($result > 0 && $lines[$i]->product_type == 9) {
  422. $fk_parent_line = $result;
  423. }
  424. }
  425. // Hooks
  426. $parameters = array('objFrom' => $srcobject);
  427. $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
  428. // modified by hook
  429. if ($reshook < 0)
  430. $error ++;
  431. } else {
  432. setEventMessages($srcobject->error, $srcobject->errors, 'errors');
  433. $error ++;
  434. }
  435. } else {
  436. setEventMessages($object->error, $object->errors, 'errors');
  437. $error ++;
  438. }
  439. } // Standard creation
  440. else
  441. {
  442. $id = $object->create($user);
  443. }
  444. if ($id > 0)
  445. {
  446. // Insertion contact par defaut si defini
  447. if (GETPOST('contactid') > 0)
  448. {
  449. $result = $object->add_contact(GETPOST('contactid'), 'CUSTOMER', 'external');
  450. if ($result < 0)
  451. {
  452. $error++;
  453. setEventMessages($langs->trans("ErrorFailedToAddContact"), null, 'errors');
  454. }
  455. }
  456. if (! $error)
  457. {
  458. $db->commit();
  459. // Define output language
  460. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  461. {
  462. $outputlangs = $langs;
  463. $newlang = '';
  464. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id')) $newlang = GETPOST('lang_id','alpha');
  465. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  466. if (! empty($newlang)) {
  467. $outputlangs = new Translate("", $conf);
  468. $outputlangs->setDefaultLang($newlang);
  469. }
  470. $model=$object->modelpdf;
  471. $ret = $object->fetch($id); // Reload to get new records
  472. $result=$object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
  473. if ($result < 0) dol_print_error($db,$result);
  474. }
  475. header('Location: ' . $_SERVER["PHP_SELF"] . '?id=' . $id);
  476. exit();
  477. }
  478. else
  479. {
  480. $db->rollback();
  481. $action='create';
  482. }
  483. }
  484. else
  485. {
  486. setEventMessages($object->error, $object->errors, 'errors');
  487. $db->rollback();
  488. $action='create';
  489. }
  490. }
  491. }
  492. }
  493. // Classify billed
  494. else if ($action == 'classifybilled' && $user->rights->propal->cloturer)
  495. {
  496. $result=$object->cloture($user, 4, '');
  497. if ($result < 0)
  498. {
  499. setEventMessages($object->error, $object->errors, 'errors');
  500. $error++;
  501. }
  502. }
  503. // Close proposal
  504. else if ($action == 'setstatut' && $user->rights->propal->cloturer && ! GETPOST('cancel'))
  505. {
  506. if (! GETPOST('statut')) {
  507. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CloseAs")), null, 'errors');
  508. $action = 'statut';
  509. } else {
  510. // prevent browser refresh from closing proposal several times
  511. if ($object->statut == Propal::STATUS_VALIDATED)
  512. {
  513. $result=$object->cloture($user, GETPOST('statut'), GETPOST('note'));
  514. if ($result < 0)
  515. {
  516. setEventMessages($object->error, $object->errors, 'errors');
  517. $error++;
  518. }
  519. }
  520. }
  521. }
  522. // Reopen proposal
  523. else if ($action == 'confirm_reopen' && $user->rights->propal->cloturer && ! GETPOST('cancel'))
  524. {
  525. // prevent browser refresh from reopening proposal several times
  526. if ($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED)
  527. {
  528. $result=$object->reopen($user, 1);
  529. if ($result < 0)
  530. {
  531. setEventMessages($object->error, $object->errors, 'errors');
  532. $error++;
  533. }
  534. }
  535. }
  536. include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
  537. /*
  538. * Send mail
  539. */
  540. // Actions to send emails
  541. $actiontypecode='AC_PROP';
  542. $trigger_name='PROPAL_SENTBYMAIL';
  543. $paramname='id';
  544. $mode='emailfromproposal';
  545. include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
  546. // Go back to draft
  547. if ($action == 'modif' && $user->rights->propal->creer)
  548. {
  549. $object->set_draft($user);
  550. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  551. {
  552. // Define output language
  553. $outputlangs = $langs;
  554. if (! empty($conf->global->MAIN_MULTILANGS)) {
  555. $outputlangs = new Translate("", $conf);
  556. $newlang = (GETPOST('lang_id') ? GETPOST('lang_id') : $object->thirdparty->default_lang);
  557. $outputlangs->setDefaultLang($newlang);
  558. }
  559. $ret = $object->fetch($id); // Reload to get new records
  560. $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  561. }
  562. }
  563. else if ($action == "setabsolutediscount" && $user->rights->propal->creer) {
  564. if ($_POST["remise_id"]) {
  565. if ($object->id > 0) {
  566. $result = $object->insert_discount($_POST["remise_id"]);
  567. if ($result < 0) {
  568. setEventMessages($object->error, $object->errors, 'errors');
  569. }
  570. }
  571. }
  572. }
  573. // Add line
  574. else if ($action == 'addline' && $user->rights->propal->creer) {
  575. // Set if we used free entry or predefined product
  576. $predef='';
  577. $product_desc=(GETPOST('dp_desc')?GETPOST('dp_desc'):'');
  578. $price_ht = GETPOST('price_ht');
  579. if (GETPOST('prod_entry_mode') == 'free')
  580. {
  581. $idprod=0;
  582. $tva_tx = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
  583. }
  584. else
  585. {
  586. $idprod=GETPOST('idprod', 'int');
  587. $tva_tx = '';
  588. }
  589. $qty = GETPOST('qty' . $predef);
  590. $remise_percent = GETPOST('remise_percent' . $predef);
  591. // Extrafields
  592. $extrafieldsline = new ExtraFields($db);
  593. $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
  594. $array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline, $predef);
  595. // Unset extrafield
  596. if (is_array($extralabelsline)) {
  597. // Get extra fields
  598. foreach ($extralabelsline as $key => $value) {
  599. unset($_POST["options_" . $key]);
  600. }
  601. }
  602. if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && GETPOST('type') < 0) {
  603. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
  604. $error ++;
  605. }
  606. if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && $price_ht == '') // Unit price can be 0 but not ''. Also price can be negative for proposal.
  607. {
  608. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
  609. $error ++;
  610. }
  611. if (GETPOST('prod_entry_mode') == 'free' && empty($idprod) && empty($product_desc)) {
  612. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Description")), null, 'errors');
  613. $error ++;
  614. }
  615. if (! $error && ($qty >= 0) && (! empty($product_desc) || ! empty($idprod))) {
  616. $pu_ht = 0;
  617. $pu_ttc = 0;
  618. $price_min = 0;
  619. $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
  620. $db->begin();
  621. // Ecrase $pu par celui du produit
  622. // Ecrase $desc par celui du produit
  623. // Ecrase $txtva par celui du produit
  624. // Replaces $fk_unit with the product unit
  625. if (! empty($idprod)) {
  626. $prod = new Product($db);
  627. $prod->fetch($idprod);
  628. $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
  629. // If prices fields are update
  630. $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
  631. $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
  632. if (empty($tva_tx)) $tva_npr=0;
  633. $pu_ht = $prod->price;
  634. $pu_ttc = $prod->price_ttc;
  635. $price_min = $prod->price_min;
  636. $price_base_type = $prod->price_base_type;
  637. // On defini prix unitaire
  638. if (! empty($conf->global->PRODUIT_MULTIPRICES) && $object->thirdparty->price_level)
  639. {
  640. $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
  641. $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
  642. $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
  643. $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
  644. if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility
  645. {
  646. if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
  647. if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
  648. }
  649. }
  650. elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
  651. {
  652. require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
  653. $prodcustprice = new Productcustomerprice($db);
  654. $filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
  655. $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
  656. if ($result) {
  657. if (count($prodcustprice->lines) > 0) {
  658. $pu_ht = price($prodcustprice->lines [0]->price);
  659. $pu_ttc = price($prodcustprice->lines [0]->price_ttc);
  660. $price_base_type = $prodcustprice->lines [0]->price_base_type;
  661. $prod->tva_tx = $prodcustprice->lines [0]->tva_tx;
  662. }
  663. }
  664. }
  665. // if price ht is forced (ie: calculated by margin rate and cost price)
  666. if (! empty($price_ht)) {
  667. $pu_ht = price2num($price_ht, 'MU');
  668. $pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
  669. }
  670. // On reevalue prix selon taux tva car taux tva transaction peut etre different
  671. // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
  672. elseif ($tva_tx != $prod->tva_tx) {
  673. if ($price_base_type != 'HT') {
  674. $pu_ht = price2num($pu_ttc / (1 + ($tva_tx / 100)), 'MU');
  675. } else {
  676. $pu_ttc = price2num($pu_ht * (1 + ($tva_tx / 100)), 'MU');
  677. }
  678. }
  679. $desc = '';
  680. // Define output language
  681. if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
  682. $outputlangs = $langs;
  683. $newlang = '';
  684. if (empty($newlang) && GETPOST('lang_id'))
  685. $newlang = GETPOST('lang_id');
  686. if (empty($newlang))
  687. $newlang = $object->thirdparty->default_lang;
  688. if (! empty($newlang)) {
  689. $outputlangs = new Translate("", $conf);
  690. $outputlangs->setDefaultLang($newlang);
  691. }
  692. $desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
  693. } else {
  694. $desc = $prod->description;
  695. }
  696. $desc = dol_concatdesc($desc, $product_desc);
  697. // Add dimensions into product description
  698. /*if (empty($conf->global->MAIN_PRODUCT_DISABLE_AUTOADD_DIM))
  699. {
  700. $text='';
  701. if ($prod->weight) $text.=($text?"\n":"").$outputlangs->trans("Weight").': '.$prod->weight.' '.$prod->weight_units;
  702. if ($prod->length) $text.=($text?"\n":"").$outputlangs->trans("Length").': '.$prod->length.' '.$prod->length_units;
  703. if ($prod->surface) $text.=($text?"\n":"").$outputlangs->trans("Surface").': '.$prod->surface.' '.$prod->surface_units;
  704. if ($prod->volume) $text.=($text?"\n":"").$outputlangs->trans("Volume").': '.$prod->volume.' '.$prod->volume_units;
  705. $desc = dol_concatdesc($desc, $text);
  706. }*/
  707. // Add custom code and origin country into description
  708. if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code)))
  709. {
  710. $tmptxt = '(';
  711. if (! empty($prod->customcode))
  712. $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
  713. if (! empty($prod->customcode) && ! empty($prod->country_code))
  714. $tmptxt .= ' - ';
  715. if (! empty($prod->country_code))
  716. $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
  717. $tmptxt .= ')';
  718. $desc = dol_concatdesc($desc, $tmptxt);
  719. }
  720. $type = $prod->type;
  721. $fk_unit = $prod->fk_unit;
  722. } else {
  723. $pu_ht = price2num($price_ht, 'MU');
  724. $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
  725. $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
  726. $tva_tx = str_replace('*', '', $tva_tx);
  727. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  728. $desc = $product_desc;
  729. $type = GETPOST('type');
  730. $fk_unit = GETPOST('units', 'alpha');
  731. }
  732. // Margin
  733. $fournprice = price2num(GETPOST('fournprice' . $predef) ? GETPOST('fournprice' . $predef) : '');
  734. $buyingprice = price2num(GETPOST('buying_price' . $predef) != '' ? GETPOST('buying_price' . $predef) : ''); // If buying_price is '0', we muste keep this value
  735. $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'));
  736. $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'));
  737. // Local Taxes
  738. $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $tva_npr);
  739. $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $tva_npr);
  740. $info_bits = 0;
  741. if ($tva_npr)
  742. $info_bits |= 0x01;
  743. if (! empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min))) {
  744. $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency));
  745. setEventMessages($mesg, null, 'errors');
  746. } else {
  747. // Insert line
  748. $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $price_base_type, $pu_ttc, $info_bits, $type, - 1, 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $date_start, $date_end, $array_options, $fk_unit);
  749. if ($result > 0) {
  750. $db->commit();
  751. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  752. // Define output language
  753. $outputlangs = $langs;
  754. if (! empty($conf->global->MAIN_MULTILANGS)) {
  755. $outputlangs = new Translate("", $conf);
  756. $newlang = (GETPOST('lang_id') ? GETPOST('lang_id') : $object->thirdparty->default_lang);
  757. $outputlangs->setDefaultLang($newlang);
  758. }
  759. $ret = $object->fetch($id); // Reload to get new records
  760. $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  761. }
  762. unset($_POST['prod_entry_mode']);
  763. unset($_POST['qty']);
  764. unset($_POST['type']);
  765. unset($_POST['remise_percent']);
  766. unset($_POST['price_ht']);
  767. unset($_POST['multicurrency_price_ht']);
  768. unset($_POST['price_ttc']);
  769. unset($_POST['tva_tx']);
  770. unset($_POST['product_ref']);
  771. unset($_POST['product_label']);
  772. unset($_POST['product_desc']);
  773. unset($_POST['fournprice']);
  774. unset($_POST['buying_price']);
  775. unset($_POST['np_marginRate']);
  776. unset($_POST['np_markRate']);
  777. unset($_POST['dp_desc']);
  778. unset($_POST['idprod']);
  779. unset($_POST['units']);
  780. unset($_POST['date_starthour']);
  781. unset($_POST['date_startmin']);
  782. unset($_POST['date_startsec']);
  783. unset($_POST['date_startday']);
  784. unset($_POST['date_startmonth']);
  785. unset($_POST['date_startyear']);
  786. unset($_POST['date_endhour']);
  787. unset($_POST['date_endmin']);
  788. unset($_POST['date_endsec']);
  789. unset($_POST['date_endday']);
  790. unset($_POST['date_endmonth']);
  791. unset($_POST['date_endyear']);
  792. } else {
  793. $db->rollback();
  794. setEventMessages($object->error, $object->errors, 'errors');
  795. }
  796. }
  797. }
  798. }
  799. // Update a line within proposal
  800. else if ($action == 'updateligne' && $user->rights->propal->creer && GETPOST('save'))
  801. {
  802. // Define info_bits
  803. $info_bits = 0;
  804. if (preg_match('/\*/', GETPOST('tva_tx')))
  805. $info_bits |= 0x01;
  806. // Clean parameters
  807. $description = dol_htmlcleanlastbr(GETPOST('product_desc'));
  808. // Define vat_rate
  809. $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
  810. $vat_rate = str_replace('*', '', $vat_rate);
  811. $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty, $mysoc);
  812. $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty, $mysoc);
  813. $pu_ht = GETPOST('price_ht');
  814. // Add buying price
  815. $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
  816. $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
  817. $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
  818. $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
  819. // Extrafields
  820. $extrafieldsline = new ExtraFields($db);
  821. $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
  822. $array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline);
  823. // Unset extrafield
  824. if (is_array($extralabelsline)) {
  825. // Get extra fields
  826. foreach ($extralabelsline as $key => $value) {
  827. unset($_POST["options_" . $key]);
  828. }
  829. }
  830. // Define special_code for special lines
  831. $special_code=GETPOST('special_code');
  832. if (! GETPOST('qty')) $special_code=3;
  833. // Check minimum price
  834. $productid = GETPOST('productid', 'int');
  835. if (! empty($productid)) {
  836. $product = new Product($db);
  837. $res = $product->fetch($productid);
  838. $type = $product->type;
  839. $price_min = $product->price_min;
  840. if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
  841. $price_min = $product->multiprices_min [$object->thirdparty->price_level];
  842. $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
  843. if ($price_min && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) {
  844. setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors');
  845. $error ++;
  846. }
  847. } else {
  848. $type = GETPOST('type');
  849. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  850. // Check parameters
  851. if (GETPOST('type') < 0) {
  852. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
  853. $error ++;
  854. }
  855. }
  856. if (! $error) {
  857. $db->begin();
  858. $result = $object->updateline(GETPOST('lineid'), $pu_ht, GETPOST('qty'), GETPOST('remise_percent'), $vat_rate, $localtax1_rate, $localtax2_rate, $description, 'HT', $info_bits, $special_code, GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $type, $date_start, $date_end, $array_options, $_POST["units"]);
  859. if ($result >= 0) {
  860. $db->commit();
  861. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  862. // Define output language
  863. $outputlangs = $langs;
  864. if (! empty($conf->global->MAIN_MULTILANGS)) {
  865. $outputlangs = new Translate("", $conf);
  866. $newlang = (GETPOST('lang_id') ? GETPOST('lang_id') : $object->thirdparty->default_lang);
  867. $outputlangs->setDefaultLang($newlang);
  868. }
  869. $ret = $object->fetch($id); // Reload to get new records
  870. $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  871. }
  872. unset($_POST['qty']);
  873. unset($_POST['type']);
  874. unset($_POST['productid']);
  875. unset($_POST['remise_percent']);
  876. unset($_POST['price_ht']);
  877. unset($_POST['multicurrency_price_ht']);
  878. unset($_POST['price_ttc']);
  879. unset($_POST['tva_tx']);
  880. unset($_POST['product_ref']);
  881. unset($_POST['product_label']);
  882. unset($_POST['product_desc']);
  883. unset($_POST['fournprice']);
  884. unset($_POST['buying_price']);
  885. unset($_POST['date_starthour']);
  886. unset($_POST['date_startmin']);
  887. unset($_POST['date_startsec']);
  888. unset($_POST['date_startday']);
  889. unset($_POST['date_startmonth']);
  890. unset($_POST['date_startyear']);
  891. unset($_POST['date_endhour']);
  892. unset($_POST['date_endmin']);
  893. unset($_POST['date_endsec']);
  894. unset($_POST['date_endday']);
  895. unset($_POST['date_endmonth']);
  896. unset($_POST['date_endyear']);
  897. } else {
  898. $db->rollback();
  899. setEventMessages($object->error, $object->errors, 'errors');
  900. }
  901. }
  902. }
  903. else if ($action == 'updateligne' && $user->rights->propal->creer && GETPOST('cancel'))
  904. {
  905. header('Location: ' . $_SERVER['PHP_SELF'] . '?id=' . $object->id); // Pour reaffichage de la fiche en cours d'edition
  906. exit();
  907. }
  908. // Set project
  909. else if ($action == 'classin' && $user->rights->propal->creer) {
  910. $object->setProject($_POST['projectid']);
  911. }
  912. // Delai de livraison
  913. else if ($action == 'setavailability' && $user->rights->propal->creer) {
  914. $result = $object->availability($_POST['availability_id']);
  915. }
  916. // Origine de la propale
  917. else if ($action == 'setdemandreason' && $user->rights->propal->creer) {
  918. $result = $object->demand_reason($_POST['demand_reason_id']);
  919. }
  920. // Conditions de reglement
  921. else if ($action == 'setconditions' && $user->rights->propal->creer) {
  922. $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
  923. }
  924. else if ($action == 'setremisepercent' && $user->rights->propal->creer) {
  925. $result = $object->set_remise_percent($user, $_POST['remise_percent']);
  926. }
  927. else if ($action == 'setremiseabsolue' && $user->rights->propal->creer) {
  928. $result = $object->set_remise_absolue($user, $_POST['remise_absolue']);
  929. }
  930. // Mode de reglement
  931. else if ($action == 'setmode' && $user->rights->propal->creer) {
  932. $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
  933. }
  934. // Multicurrency Code
  935. else if ($action == 'setmulticurrencycode' && $user->rights->propal->creer) {
  936. $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
  937. }
  938. // Multicurrency rate
  939. else if ($action == 'setmulticurrencyrate' && $user->rights->propal->creer) {
  940. $result = $object->setMulticurrencyRate(GETPOST('multicurrency_tx', 'int'));
  941. }
  942. // bank account
  943. else if ($action == 'setbankaccount' && $user->rights->propal->creer) {
  944. $result=$object->setBankAccount(GETPOST('fk_account', 'int'));
  945. }
  946. // shipping method
  947. else if ($action == 'setshippingmethod' && $user->rights->propal->creer) {
  948. $result=$object->setShippingMethod(GETPOST('shipping_method_id', 'int'));
  949. }
  950. else if ($action == 'update_extras') {
  951. // Fill array 'array_options' with data from update form
  952. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  953. $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute'));
  954. if ($ret < 0) $error++;
  955. if (! $error)
  956. {
  957. // Actions on extra fields (by external module or standard code)
  958. // TODO le hook fait double emploi avec le trigger !!
  959. $hookmanager->initHooks(array('propaldao'));
  960. $parameters = array('id' => $object->id);
  961. $reshook = $hookmanager->executeHooks('insertExtraFields', $parameters, $object, $action); // Note that $action and $object may have been
  962. // modified by
  963. // some hooks
  964. if (empty($reshook)) {
  965. $result = $object->insertExtraFields();
  966. if ($result < 0) {
  967. $error ++;
  968. }
  969. } else if ($reshook < 0)
  970. $error ++;
  971. }
  972. if ($error)
  973. $action = 'edit_extras';
  974. }
  975. if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->propal->creer)
  976. {
  977. if ($action == 'addcontact')
  978. {
  979. if ($object->id > 0) {
  980. $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
  981. $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]);
  982. }
  983. if ($result >= 0) {
  984. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  985. exit();
  986. } else {
  987. if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
  988. $langs->load("errors");
  989. setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
  990. } else {
  991. setEventMessages($object->error, $object->errors, 'errors');
  992. }
  993. }
  994. }
  995. // Bascule du statut d'un contact
  996. else if ($action == 'swapstatut') {
  997. if ($object->fetch($id) > 0) {
  998. $result = $object->swapContactStatus(GETPOST('ligne'));
  999. } else {
  1000. dol_print_error($db);
  1001. }
  1002. }
  1003. // Efface un contact
  1004. else if ($action == 'deletecontact') {
  1005. $object->fetch($id);
  1006. $result = $object->delete_contact($lineid);
  1007. if ($result >= 0) {
  1008. header("Location: " . $_SERVER['PHP_SELF'] . "?id=" . $object->id);
  1009. exit();
  1010. } else {
  1011. dol_print_error($db);
  1012. }
  1013. }
  1014. }
  1015. // Actions to build doc
  1016. $upload_dir = $conf->propal->dir_output;
  1017. $permissioncreate=$user->rights->propal->creer;
  1018. include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
  1019. }
  1020. /*
  1021. * View
  1022. */
  1023. llxHeader('', $langs->trans('Proposal'), 'EN:Commercial_Proposals|FR:Proposition_commerciale|ES:Presupuestos');
  1024. $form = new Form($db);
  1025. $formother = new FormOther($db);
  1026. $formfile = new FormFile($db);
  1027. $formpropal = new FormPropal($db);
  1028. $formmargin = new FormMargin($db);
  1029. $companystatic = new Societe($db);
  1030. if (! empty($conf->projet->enabled)) { $formproject = new FormProjets($db); }
  1031. $now = dol_now();
  1032. // Add new proposal
  1033. if ($action == 'create')
  1034. {
  1035. print load_fiche_titre($langs->trans("NewProp"));
  1036. $soc = new Societe($db);
  1037. if ($socid > 0)
  1038. $res = $soc->fetch($socid);
  1039. // Load objectsrc
  1040. if (! empty($origin) && ! empty($originid))
  1041. {
  1042. // Parse element/subelement (ex: project_task)
  1043. $element = $subelement = $origin;
  1044. if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
  1045. $element = $regs [1];
  1046. $subelement = $regs [2];
  1047. }
  1048. if ($element == 'project') {
  1049. $projectid = $originid;
  1050. } else {
  1051. // For compatibility
  1052. if ($element == 'order' || $element == 'commande') {
  1053. $element = $subelement = 'commande';
  1054. }
  1055. if ($element == 'propal') {
  1056. $element = 'comm/propal';
  1057. $subelement = 'propal';
  1058. }
  1059. if ($element == 'contract') {
  1060. $element = $subelement = 'contrat';
  1061. }
  1062. if ($element == 'shipping') {
  1063. $element = $subelement = 'expedition';
  1064. }
  1065. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  1066. $classname = ucfirst($subelement);
  1067. $objectsrc = new $classname($db);
  1068. $objectsrc->fetch($originid);
  1069. if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines'))
  1070. {
  1071. $objectsrc->fetch_lines();
  1072. }
  1073. $objectsrc->fetch_thirdparty();
  1074. $projectid = (! empty($objectsrc->fk_project) ? $objectsrc->fk_project : '');
  1075. $ref_client = (! empty($objectsrc->ref_client) ? $objectsrc->ref_client : '');
  1076. $ref_int = (! empty($objectsrc->ref_int) ? $objectsrc->ref_int : '');
  1077. $soc = $objectsrc->thirdparty;
  1078. $cond_reglement_id = (! empty($objectsrc->cond_reglement_id)?$objectsrc->cond_reglement_id:(! empty($soc->cond_reglement_id)?$soc->cond_reglement_id:1));
  1079. $mode_reglement_id = (! empty($objectsrc->mode_reglement_id)?$objectsrc->mode_reglement_id:(! empty($soc->mode_reglement_id)?$soc->mode_reglement_id:0));
  1080. $remise_percent = (! empty($objectsrc->remise_percent)?$objectsrc->remise_percent:(! empty($soc->remise_percent)?$soc->remise_percent:0));
  1081. $remise_absolue = (! empty($objectsrc->remise_absolue)?$objectsrc->remise_absolue:(! empty($soc->remise_absolue)?$soc->remise_absolue:0));
  1082. $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice);
  1083. // Replicate extrafields
  1084. $objectsrc->fetch_optionals($originid);
  1085. $object->array_options = $objectsrc->array_options;
  1086. }
  1087. }
  1088. $object = new Propal($db);
  1089. print '<form name="addprop" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
  1090. print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  1091. print '<input type="hidden" name="action" value="add">';
  1092. if ($origin != 'project' && $originid) {
  1093. print '<input type="hidden" name="origin" value="' . $origin . '">';
  1094. print '<input type="hidden" name="originid" value="' . $originid . '">';
  1095. }
  1096. dol_fiche_head();
  1097. print '<table class="border" width="100%">';
  1098. // Reference
  1099. print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans("Draft") . '</td></tr>';
  1100. // Ref customer
  1101. print '<tr><td>' . $langs->trans('RefCustomer') . '</td><td colspan="2">';
  1102. print '<input type="text" name="ref_client" value="'.GETPOST('ref_client').'"></td>';
  1103. print '</tr>';
  1104. // Third party
  1105. print '<tr>';
  1106. print '<td class="fieldrequired">' . $langs->trans('Customer') . '</td>';
  1107. if ($socid > 0) {
  1108. print '<td colspan="2">';
  1109. print $soc->getNomUrl(1);
  1110. print '<input type="hidden" name="socid" value="' . $soc->id . '">';
  1111. print '</td>';
  1112. if (! empty($conf->global->SOCIETE_ASK_FOR_SHIPPING_METHOD) && ! empty($soc->shipping_method_id)) {
  1113. $shipping_method_id = $soc->shipping_method_id;
  1114. }
  1115. } else {
  1116. print '<td colspan="2">';
  1117. print $form->select_company('', 'socid', '(s.client = 1 OR s.client = 2 OR s.client = 3) AND status=1', 'SelectThirdParty');
  1118. // reload page to retrieve customer informations
  1119. if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
  1120. {
  1121. print '<script type="text/javascript">
  1122. $(document).ready(function() {
  1123. $("#socid").change(function() {
  1124. var socid = $(this).val();
  1125. // reload page
  1126. window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&ref_client="+$("input[name=ref_client]").val();
  1127. });
  1128. });
  1129. </script>';
  1130. }
  1131. print '</td>';
  1132. }
  1133. print '</tr>' . "\n";
  1134. // Contacts (ask contact only if thirdparty already defined). TODO do this also into order and invoice.
  1135. if ($socid > 0)
  1136. {
  1137. print "<tr><td>" . $langs->trans("DefaultContact") . '</td><td colspan="2">';
  1138. $form->select_contacts($soc->id, $contactid, 'contactid', 1, $srccontactslist);
  1139. print '</td></tr>';
  1140. }
  1141. if ($socid > 0)
  1142. {
  1143. // Ligne info remises tiers
  1144. print '<tr><td>' . $langs->trans('Discounts') . '</td><td colspan="2">';
  1145. if ($soc->remise_percent)
  1146. print $langs->trans("CompanyHasRelativeDiscount", $soc->remise_percent);
  1147. else
  1148. print $langs->trans("CompanyHasNoRelativeDiscount");
  1149. $absolute_discount = $soc->getAvailableDiscounts();
  1150. print '. ';
  1151. if ($absolute_discount)
  1152. print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount, 0, $langs, 1, -1, -1, $conf->currency));
  1153. else
  1154. print $langs->trans("CompanyHasNoAbsoluteDiscount");
  1155. print '.';
  1156. print '</td></tr>';
  1157. }
  1158. // Date
  1159. print '<tr><td class="fieldrequired">' . $langs->trans('Date') . '</td><td colspan="2">';
  1160. $form->select_date('', '', '', '', '', "addprop", 1, 1);
  1161. print '</td></tr>';
  1162. // Validaty duration
  1163. print '<tr><td class="fieldrequired">' . $langs->trans("ValidityDuration") . '</td><td colspan="2"><input name="duree_validite" size="5" value="' . $conf->global->PROPALE_VALIDITY_DURATION . '"> ' . $langs->trans("days") . '</td></tr>';
  1164. // Terms of payment
  1165. print '<tr><td class="nowrap fieldrequired">' . $langs->trans('PaymentConditionsShort') . '</td><td colspan="2">';
  1166. $form->select_conditions_paiements($soc->cond_reglement_id, 'cond_reglement_id');
  1167. print '</td></tr>';
  1168. // Mode of payment
  1169. print '<tr><td>' . $langs->trans('PaymentMode') . '</td><td colspan="2">';
  1170. $form->select_types_paiements($soc->mode_reglement_id, 'mode_reglement_id');
  1171. print '</td></tr>';
  1172. // Bank Account
  1173. if (! empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && $conf->banque->enabled) {
  1174. print '<tr><td>' . $langs->trans('BankAccount') . '</td><td colspan="2">';
  1175. $form->select_comptes($fk_account, 'fk_account', 0, '', 1);
  1176. print '</td></tr>';
  1177. }
  1178. // What trigger creation
  1179. print '<tr><td>' . $langs->trans('Source') . '</td><td>';
  1180. $form->selectInputReason('', 'demand_reason_id', "SRC_PROP", 1);
  1181. print '</td></tr>';
  1182. // Delivery delay
  1183. print '<tr class="fielddeliverydelay"><td>' . $langs->trans('AvailabilityPeriod') . '</td><td colspan="2">';
  1184. $form->selectAvailabilityDelay('', 'availability_id', '', 1);
  1185. print '</td></tr>';
  1186. // Shipping Method
  1187. if (! empty($conf->expedition->enabled)) {
  1188. print '<tr><td>' . $langs->trans('SendingMethod') . '</td><td colspan="2">';
  1189. print $form->selectShippingMethod($shipping_method_id, 'shipping_method_id', '', 1);
  1190. print '</td></tr>';
  1191. }
  1192. // Delivery date (or manufacturing)
  1193. print '<tr><td>' . $langs->trans("DeliveryDate") . '</td>';
  1194. print '<td colspan="2">';
  1195. if ($conf->global->DATE_LIVRAISON_WEEK_DELAY != "") {
  1196. $tmpdte = time() + ((7 * $conf->global->DATE_LIVRAISON_WEEK_DELAY) * 24 * 60 * 60);
  1197. $syear = date("Y", $tmpdte);
  1198. $smonth = date("m", $tmpdte);
  1199. $sday = date("d", $tmpdte);
  1200. $form->select_date($syear."-".$smonth."-".$sday, 'date_livraison', '', '', '', "addprop");
  1201. } else {
  1202. $form->select_date(-1, 'date_livraison', '', '', '', "addprop", 1, 1);
  1203. }
  1204. print '</td></tr>';
  1205. // Project
  1206. if (! empty($conf->projet->enabled) && $socid > 0)
  1207. {
  1208. $projectid = GETPOST('projectid')?GETPOST('projectid'):0;
  1209. if ($origin == 'project') $projectid = ($originid ? $originid : 0);
  1210. $langs->load("projects");
  1211. print '<tr>';
  1212. print '<td>' . $langs->trans("Project") . '</td><td colspan="2">';
  1213. $numprojet = $formproject->select_projects($soc->id, $projectid, 'projectid', 0);
  1214. print ' &nbsp; <a href="'.DOL_URL_ROOT.'/projet/card.php?socid=' . $soc->id . '&action=create&status=1&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create&socid='.$soc->id).'">' . $langs->trans("AddProject") . '</a>';
  1215. print '</td>';
  1216. print '</tr>';
  1217. }
  1218. // Incoterms
  1219. if (!empty($conf->incoterm->enabled))
  1220. {
  1221. print '<tr>';
  1222. print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $soc->libelle_incoterms, 1).'</label></td>';
  1223. print '<td colspan="3" class="maxwidthonsmartphone">';
  1224. print $form->select_incoterms((!empty($soc->fk_incoterms) ? $soc->fk_incoterms : ''), (!empty($soc->location_incoterms)?$soc->location_incoterms:''));
  1225. print '</td></tr>';
  1226. }
  1227. // Template to use by default
  1228. print '<tr>';
  1229. print '<td>' . $langs->trans("DefaultModel") . '</td>';
  1230. print '<td colspan="2">';
  1231. $liste = ModelePDFPropales::liste_modeles($db);
  1232. print $form->selectarray('model', $liste, ($conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT ? $conf->global->PROPALE_ADDON_PDF_ODT_DEFAULT : $conf->global->PROPALE_ADDON_PDF));
  1233. print "</td></tr>";
  1234. // Multicurrency
  1235. if (! empty($conf->multicurrency->enabled))
  1236. {
  1237. print '<tr>';
  1238. print '<td>'.fieldLabel('Currency','multicurrency_code').'</td>';
  1239. print '<td colspan="3" class="maxwidthonsmartphone">';
  1240. $currency_code = (!empty($soc->multicurrency_code) ? $soc->multicurrency_code : ($object->multicurrency_code ? $object->multicurrency_code : $conf->currency));
  1241. print $form->selectMultiCurrency($currency_code, 'multicurrency_code', 0);
  1242. print '</td></tr>';
  1243. }
  1244. // Public note
  1245. print '<tr>';
  1246. print '<td class="border" valign="top">' . $langs->trans('NotePublic') . '</td>';
  1247. print '<td valign="top" colspan="2">';
  1248. $note_public = $object->getDefaultCreateValueFor('note_public', (is_object($objectsrc)?$objectsrc->note_public:null));
  1249. $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
  1250. print $doleditor->Create(1);
  1251. // Private note
  1252. if (empty($user->societe_id))
  1253. {
  1254. print '<tr>';
  1255. print '<td class="border" valign="top">' . $langs->trans('NotePrivate') . '</td>';
  1256. print '<td valign="top" colspan="2">';
  1257. $note_private = $object->getDefaultCreateValueFor('note_private', ((! empty($origin) && ! empty($originid) && is_object($objectsrc))?$objectsrc->note_private:null));
  1258. $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
  1259. print $doleditor->Create(1);
  1260. // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
  1261. print '</td></tr>';
  1262. }
  1263. // Other attributes
  1264. $parameters = array('colspan' => ' colspan="3"');
  1265. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified
  1266. // by
  1267. // hook
  1268. if (empty($reshook) && ! empty($extrafields->attribute_label)) {
  1269. print $object->showOptionals($extrafields, 'edit');
  1270. }
  1271. // Lines from source
  1272. if (! empty($origin) && ! empty($originid) && is_object($objectsrc))
  1273. {
  1274. // TODO for compatibility
  1275. if ($origin == 'contrat') {
  1276. // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
  1277. $objectsrc->remise_absolue = $remise_absolue;
  1278. $objectsrc->remise_percent = $remise_percent;
  1279. $objectsrc->update_price(1, - 1, 1);
  1280. }
  1281. print "\n<!-- " . $classname . " info -->";
  1282. print "\n";
  1283. print '<input type="hidden" name="amount" value="' . $objectsrc->total_ht . '">' . "\n";
  1284. print '<input type="hidden" name="total" value="' . $objectsrc->total_ttc . '">' . "\n";
  1285. print '<input type="hidden" name="tva" value="' . $objectsrc->total_tva . '">' . "\n";
  1286. print '<input type="hidden" name="origin" value="' . $objectsrc->element . '">';
  1287. print '<input type="hidden" name="originid" value="' . $objectsrc->id . '">';
  1288. $newclassname = $classname;
  1289. if ($newclassname == 'Propal')
  1290. $newclassname = 'CommercialProposal';
  1291. elseif ($newclassname == 'Commande')
  1292. $newclassname = 'Order';
  1293. elseif ($newclassname == 'Expedition')
  1294. $newclassname = 'Sending';
  1295. elseif ($newclassname == 'Fichinter')
  1296. $newclassname = 'Intervention';
  1297. print '<tr><td>' . $langs->trans($newclassname) . '</td><td colspan="2">' . $objectsrc->getNomUrl(1) . '</td></tr>';
  1298. print '<tr><td>' . $langs->trans('TotalHT') . '</td><td colspan="2">' . price($objectsrc->total_ht, 0, $langs, 1, -1, -1, $conf->currency) . '</td></tr>';
  1299. print '<tr><td>' . $langs->trans('TotalVAT') . '</td><td colspan="2">' . price($objectsrc->total_tva, 0, $langs, 1, -1, -1, $conf->currency) . "</td></tr>";
  1300. if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0 ) // Localtax1
  1301. {
  1302. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax1, 0, $langs, 1, -1, -1, $conf->currency) . "</td></tr>";
  1303. }
  1304. if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) // Localtax2
  1305. {
  1306. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax2, 0, $langs, 1, -1, -1, $conf->currency) . "</td></tr>";
  1307. }
  1308. print '<tr><td>' . $langs->trans('TotalTTC') . '</td><td colspan="2">' . price($objectsrc->total_ttc, 0, $langs, 1, -1, -1, $conf->currency) . "</td></tr>";
  1309. }
  1310. print "</table>\n";
  1311. /*
  1312. * Combobox pour la fonction de copie
  1313. */
  1314. if (empty($conf->global->PROPAL_CLONE_ON_CREATE_PAGE)) print '<input type="hidden" name="createmode" value="empty">';
  1315. if (! empty($conf->global->PROPAL_CLONE_ON_CREATE_PAGE) || ! empty($conf->global->PRODUCT_SHOW_WHEN_CREATE)) print '<br><table>';
  1316. if (! empty($conf->global->PROPAL_CLONE_ON_CREATE_PAGE))
  1317. {
  1318. // For backward compatibility
  1319. print '<tr>';
  1320. print '<td><input type="radio" name="createmode" value="copy"></td>';
  1321. print '<td>' . $langs->trans("CopyPropalFrom") . ' </td>';
  1322. print '<td>';
  1323. $liste_propal = array();
  1324. $liste_propal [0] = '';
  1325. $sql = "SELECT p.rowid as id, p.ref, s.nom";
  1326. $sql .= " FROM " . MAIN_DB_PREFIX . "propal p";
  1327. $sql .= ", " . MAIN_DB_PREFIX . "societe s";
  1328. $sql .= " WHERE s.rowid = p.fk_soc";
  1329. $sql .= " AND p.entity IN (".getEntity('propal', 1).")";
  1330. $sql .= " AND p.fk_statut <> 0";
  1331. $sql .= " ORDER BY Id";
  1332. $resql = $db->query($sql);
  1333. if ($resql) {
  1334. $num = $db->num_rows($resql);
  1335. $i = 0;
  1336. while ($i < $num) {
  1337. $row = $db->fetch_row($resql);
  1338. $propalRefAndSocName = $row [1] . " - " . $row [2];
  1339. $liste_propal [$row [0]] = $propalRefAndSocName;
  1340. $i ++;
  1341. }
  1342. print $form->selectarray("copie_propal", $liste_propal, 0);
  1343. } else {
  1344. dol_print_error($db);
  1345. }
  1346. print '</td></tr>';
  1347. if (! empty($conf->global->PRODUCT_SHOW_WHEN_CREATE))
  1348. print '<tr><td colspan="3">&nbsp;</td></tr>';
  1349. print '<tr><td valign="top"><input type="radio" name="createmode" value="empty" checked></td>';
  1350. print '<td valign="top" colspan="2">' . $langs->trans("CreateEmptyPropal") . '</td></tr>';
  1351. }
  1352. if (! empty($conf->global->PRODUCT_SHOW_WHEN_CREATE))
  1353. {
  1354. print '<tr><td colspan="3">';
  1355. if (! empty($conf->product->enabled) || ! empty($conf->service->enabled)) {
  1356. $lib = $langs->trans("ProductsAndServices");
  1357. print '<table class="border" width="100%">';
  1358. print '<tr>';
  1359. print '<td>' . $lib . '</td>';
  1360. print '<td>' . $langs->trans("Qty") . '</td>';
  1361. print '<td>' . $langs->trans("ReductionShort") . '</td>';
  1362. print '</tr>';
  1363. for($i = 1; $i <= $conf->global->PRODUCT_SHOW_WHEN_CREATE; $i ++) {
  1364. print '<tr><td>';
  1365. // multiprix
  1366. if ($conf->global->PRODUIT_MULTIPRICES && $soc->price_level)
  1367. $form->select_produits('', "idprod" . $i, '', $conf->product->limit_size, $soc->price_level);
  1368. else
  1369. $form->select_produits('', "idprod" . $i, '', $conf->product->limit_size);
  1370. print '</td>';
  1371. print '<td><input type="text" size="2" name="qty' . $i . '" value="1"></td>';
  1372. print '<td><input type="text" size="2" name="remise' . $i . '" value="' . $soc->remise_percent . '">%</td>';
  1373. print '</tr>';
  1374. }
  1375. print "</table>";
  1376. }
  1377. print '</td></tr>';
  1378. }
  1379. if (! empty($conf->global->PROPAL_CLONE_ON_CREATE_PAGE) || ! empty($conf->global->PRODUCT_SHOW_WHEN_CREATE)) print '</table>';
  1380. dol_fiche_end();
  1381. $langs->load("bills");
  1382. print '<div class="center">';
  1383. print '<input type="submit" class="button" value="' . $langs->trans("CreateDraft") . '">';
  1384. print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
  1385. print '<input type="button" class="button" value="' . $langs->trans("Cancel") . '" onClick="javascript:history.go(-1)">';
  1386. print '</div>';
  1387. print "</form>";
  1388. // Show origin lines
  1389. if (! empty($origin) && ! empty($originid) && is_object($objectsrc)) {
  1390. print '<br>';
  1391. $title = $langs->trans('ProductsAndServices');
  1392. print load_fiche_titre($title);
  1393. print '<table class="noborder" width="100%">';
  1394. $objectsrc->printOriginLinesList();
  1395. print '</table>';
  1396. }
  1397. } else {
  1398. /*
  1399. * Show object in view mode
  1400. */
  1401. $soc = new Societe($db);
  1402. $soc->fetch($object->socid);
  1403. $head = propal_prepare_head($object);
  1404. dol_fiche_head($head, 'comm', $langs->trans('Proposal'), 0, 'propal');
  1405. $formconfirm = '';
  1406. // Clone confirmation
  1407. if ($action == 'clone') {
  1408. // Create an array for form
  1409. $formquestion = array(
  1410. // 'text' => $langs->trans("ConfirmClone"),
  1411. // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
  1412. // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' =>
  1413. // 1),
  1414. array('type' => 'other','name' => 'socid','label' => $langs->trans("SelectThirdParty"),'value' => $form->select_company(GETPOST('socid', 'int'), 'socid', '(s.client=1 OR s.client=2 OR s.client=3)')));
  1415. // Paiement incomplet. On demande si motif = escompte ou autre
  1416. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ClonePropal'), $langs->trans('ConfirmClonePropal', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
  1417. }
  1418. // Confirm delete
  1419. else if ($action == 'delete') {
  1420. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteProp'), $langs->trans('ConfirmDeleteProp', $object->ref), 'confirm_delete', '', 0, 1);
  1421. }
  1422. // Confirm reopen
  1423. else if ($action == 'reopen') {
  1424. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ReOpen'), $langs->trans('ConfirmReOpenProp', $object->ref), 'confirm_reopen', '', 0, 1);
  1425. }
  1426. // Confirmation delete product/service line
  1427. else if ($action == 'ask_deleteline') {
  1428. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 0, 1);
  1429. }
  1430. // Confirm validate proposal
  1431. else if ($action == 'validate') {
  1432. $error = 0;
  1433. // We verifie whether the object is provisionally numbering
  1434. $ref = substr($object->ref, 1, 4);
  1435. if ($ref == 'PROV') {
  1436. $numref = $object->getNextNumRef($soc);
  1437. if (empty($numref)) {
  1438. $error ++;
  1439. setEventMessages($object->error, $object->errors, 'errors');
  1440. }
  1441. } else {
  1442. $numref = $object->ref;
  1443. }
  1444. $text = $langs->trans('ConfirmValidateProp', $numref);
  1445. if (! empty($conf->notification->enabled)) {
  1446. require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
  1447. $notify = new Notify($db);
  1448. $text .= '<br>';
  1449. $text .= $notify->confirmMessage('PROPAL_VALIDATE', $object->socid, $object);
  1450. }
  1451. if (! $error)
  1452. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('ValidateProp'), $text, 'confirm_validate', '', 0, 1);
  1453. }
  1454. if (! $formconfirm) {
  1455. $parameters = array('lineid' => $lineid);
  1456. $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1457. if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
  1458. elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
  1459. }
  1460. // Print form confirm
  1461. print $formconfirm;
  1462. print '<table class="border" width="100%">';
  1463. $linkback = '<a href="' . DOL_URL_ROOT . '/comm/propal/list.php' . (! empty($socid) ? '?socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
  1464. // Ref
  1465. print '<tr><td>' . $langs->trans('Ref') . '</td><td colspan="5">';
  1466. print $form->showrefnav($object, 'ref', $linkback, 1, 'ref', 'ref', '');
  1467. print '</td></tr>';
  1468. // Ref customer
  1469. print '<tr><td>';
  1470. print '<table class="nobordernopadding" width="100%"><tr><td class="nowrap">';
  1471. print $langs->trans('RefCustomer') . '</td>';
  1472. if ($action != 'refclient' && ! empty($object->brouillon))
  1473. print '<td align="right"><a href="' . $_SERVER['PHP_SELF'] . '?action=refclient&amp;id=' . $object->id . '">' . img_edit($langs->trans('Modify')) . '</a></td>';
  1474. print '</td>';
  1475. print '</tr></table>';
  1476. print '</td><td colspan="5">';
  1477. if ($user->rights->propal->creer && $action == 'refclient') {
  1478. print '<form action="propal.php?id=' . $object->id . '" method="post">';
  1479. print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  1480. print '<input type="hidden" name="action" value="set_ref_client">';
  1481. print '<input type="text" class="flat" size="20" name="ref_client" value="' . $object->ref_client . '">';
  1482. print ' <input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
  1483. print '</form>';
  1484. } else {
  1485. print $object->ref_client;
  1486. }
  1487. print '</td>';
  1488. print '</tr>';
  1489. // Company
  1490. print '<tr><td>' . $langs->trans('Company') . '</td><td colspan="5">' . $soc->getNomUrl(1) . '</td>';
  1491. print '</tr>';
  1492. // Lin for thirdparty discounts
  1493. print '<tr><td>' . $langs->trans('Discounts') . '</td><td colspan="5">';
  1494. if ($soc->remise_percent)
  1495. print $langs->trans("CompanyHasRelativeDiscount", $soc->remise_percent);
  1496. else
  1497. print $langs->trans("CompanyHasNoRelativeDiscount");
  1498. print '. ';
  1499. $absolute_discount = $soc->getAvailableDiscounts('', 'fk_facture_source IS NULL');
  1500. $absolute_creditnote = $soc->getAvailableDiscounts('', 'fk_facture_source IS NOT NULL');
  1501. $absolute_discount = price2num($absolute_discount, 'MT');
  1502. $absolute_creditnote = price2num($absolute_creditnote, 'MT');
  1503. if ($absolute_discount) {
  1504. if ($object->statut > Propal::STATUS_DRAFT) {
  1505. print $langs->trans("CompanyHasAbsoluteDiscount", price($absolute_discount, 0, $langs, 0, 0, -1, $conf->currency));
  1506. } else {
  1507. // Remise dispo de type non avoir
  1508. $filter = 'fk_facture_source IS NULL';
  1509. print '<br>';
  1510. $form->form_remise_dispo($_SERVER["PHP_SELF"] . '?id=' . $object->id, 0, 'remise_id', $soc->id, $absolute_discount, $filter);
  1511. }
  1512. }
  1513. if ($absolute_creditnote) {
  1514. print $langs->trans("CompanyHasCreditNote", price($absolute_creditnote, 0, $langs, 0, 0, -1, $conf->currency)) . '. ';
  1515. }
  1516. if (! $absolute_discount && ! $absolute_creditnote)
  1517. print $langs->trans("CompanyHasNoAbsoluteDiscount") . '.';
  1518. print '</td></tr>';
  1519. // Date of proposal
  1520. print '<tr>';
  1521. print '<td>';
  1522. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1523. print $langs->trans('Date');
  1524. print '</td>';
  1525. if ($action != 'editdate' && ! empty($object->brouillon))
  1526. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdate&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
  1527. print '</tr></table>';
  1528. print '</td><td colspan="5">';
  1529. if (! empty($object->brouillon) && $action == 'editdate') {
  1530. print '<form name="editdate" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
  1531. print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  1532. print '<input type="hidden" name="action" value="setdate">';
  1533. $form->select_date($object->date, 're', '', '', 0, "editdate");
  1534. print '<input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
  1535. print '</form>';
  1536. } else {
  1537. if ($object->date) {
  1538. print dol_print_date($object->date, 'daytext');
  1539. } else {
  1540. print '&nbsp;';
  1541. }
  1542. }
  1543. print '</td>';
  1544. // Date end proposal
  1545. print '<tr>';
  1546. print '<td>';
  1547. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1548. print $langs->trans('DateEndPropal');
  1549. print '</td>';
  1550. if ($action != 'editecheance' && ! empty($object->brouillon))
  1551. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editecheance&amp;id=' . $object->id . '">' . img_edit($langs->trans('SetConditions'), 1) . '</a></td>';
  1552. print '</tr></table>';
  1553. print '</td><td colspan="5">';
  1554. if (! empty($object->brouillon) && $action == 'editecheance') {
  1555. print '<form name="editecheance" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
  1556. print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  1557. print '<input type="hidden" name="action" value="setecheance">';
  1558. $form->select_date($object->fin_validite, 'ech', '', '', '', "editecheance");
  1559. print '<input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
  1560. print '</form>';
  1561. } else {
  1562. if (! empty($object->fin_validite)) {
  1563. print dol_print_date($object->fin_validite, 'daytext');
  1564. if ($object->statut == Propal::STATUS_VALIDATED && $object->fin_validite < ($now - $conf->propal->cloture->warning_delay))
  1565. print img_warning($langs->trans("Late"));
  1566. } else {
  1567. print '&nbsp;';
  1568. }
  1569. }
  1570. print '</td>';
  1571. print '</tr>';
  1572. // Payment term
  1573. print '<tr><td>';
  1574. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1575. print $langs->trans('PaymentConditionsShort');
  1576. print '</td>';
  1577. if ($action != 'editconditions' && ! empty($object->brouillon))
  1578. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editconditions&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetConditions'), 1) . '</a></td>';
  1579. print '</tr></table>';
  1580. print '</td><td colspan="5">';
  1581. if ($action == 'editconditions') {
  1582. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id');
  1583. } else {
  1584. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->cond_reglement_id, 'none');
  1585. }
  1586. print '</td>';
  1587. print '</tr>';
  1588. // Delivery date
  1589. $langs->load('deliveries');
  1590. print '<tr><td>';
  1591. print $form->editfieldkey($langs->trans('DeliveryDate'), 'date_livraison', $object->date_livraison, $object, $user->rights->propal->creer);
  1592. print '</td><td colspan="5">';
  1593. print $form->editfieldval($langs->trans('DeliveryDate'), 'date_livraison', $object->date_livraison, $object, $user->rights->propal->creer, 'day');
  1594. print '</td>';
  1595. print '</tr>';
  1596. // Delivery delay
  1597. print '<tr class="fielddeliverydelay"><td>';
  1598. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1599. print $langs->trans('AvailabilityPeriod');
  1600. if (! empty($conf->commande->enabled))
  1601. print ' (' . $langs->trans('AfterOrder') . ')';
  1602. print '</td>';
  1603. if ($action != 'editavailability' && ! empty($object->brouillon))
  1604. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editavailability&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetAvailability'), 1) . '</a></td>';
  1605. print '</tr></table>';
  1606. print '</td><td colspan="5">';
  1607. if ($action == 'editavailability') {
  1608. $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'availability_id', 1);
  1609. } else {
  1610. $form->form_availability($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->availability_id, 'none', 1);
  1611. }
  1612. print '</td>';
  1613. print '</tr>';
  1614. // Shipping Method
  1615. if (! empty($conf->expedition->enabled)) {
  1616. print '<tr><td>';
  1617. print '<table width="100%" class="nobordernopadding"><tr><td>';
  1618. print $langs->trans('SendingMethod');
  1619. print '</td>';
  1620. if ($action != 'editshippingmethod' && $user->rights->propal->creer)
  1621. print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editshippingmethod&amp;id='.$object->id.'">'.img_edit($langs->trans('SetShippingMode'),1).'</a></td>';
  1622. print '</tr></table>';
  1623. print '</td><td colspan="5">';
  1624. if ($action == 'editshippingmethod') {
  1625. $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'shipping_method_id', 1);
  1626. } else {
  1627. $form->formSelectShippingMethod($_SERVER['PHP_SELF'].'?id='.$object->id, $object->shipping_method_id, 'none');
  1628. }
  1629. print '</td>';
  1630. print '</tr>';
  1631. }
  1632. // Origin of demand
  1633. print '<tr><td>';
  1634. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1635. print $langs->trans('Source');
  1636. print '</td>';
  1637. if ($action != 'editdemandreason' && ! empty($object->brouillon))
  1638. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdemandreason&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetDemandReason'), 1) . '</a></td>';
  1639. print '</tr></table>';
  1640. print '</td><td colspan="5">';
  1641. if ($action == 'editdemandreason') {
  1642. $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'demand_reason_id', 1);
  1643. } else {
  1644. $form->formInputReason($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->demand_reason_id, 'none');
  1645. }
  1646. print '</td>';
  1647. print '</tr>';
  1648. // Payment mode
  1649. print '<tr>';
  1650. print '<td width="25%">';
  1651. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1652. print $langs->trans('PaymentMode');
  1653. print '</td>';
  1654. if ($action != 'editmode' && ! empty($object->brouillon))
  1655. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmode&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMode'), 1) . '</a></td>';
  1656. print '</tr></table>';
  1657. print '</td><td colspan="5">';
  1658. if ($action == 'editmode') {
  1659. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'mode_reglement_id');
  1660. } else {
  1661. $form->form_modes_reglement($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->mode_reglement_id, 'none');
  1662. }
  1663. print '</td></tr>';
  1664. // Multicurrency
  1665. if (! empty($conf->multicurrency->enabled))
  1666. {
  1667. // Multicurrency code
  1668. print '<tr>';
  1669. print '<td width="25%">';
  1670. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1671. print fieldLabel('Currency','multicurrency_code');
  1672. print '</td>';
  1673. if ($action != 'editmulticurrencycode' && ! empty($object->brouillon))
  1674. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencycode&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
  1675. print '</tr></table>';
  1676. print '</td><td colspan="5">';
  1677. if ($action == 'editmulticurrencycode') {
  1678. $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'multicurrency_code');
  1679. } else {
  1680. $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'none');
  1681. }
  1682. print '</td></tr>';
  1683. // Multicurrency rate
  1684. print '<tr>';
  1685. print '<td width="25%">';
  1686. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1687. print fieldLabel('Rate','multicurrency_tx');
  1688. print '</td>';
  1689. if ($action != 'editmulticurrencyrate' && ! empty($object->brouillon))
  1690. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
  1691. print '</tr></table>';
  1692. print '</td><td colspan="5">';
  1693. if ($action == 'editmulticurrencyrate') {
  1694. $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
  1695. } else {
  1696. $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
  1697. }
  1698. print '</td></tr>';
  1699. }
  1700. // Project
  1701. if (! empty($conf->projet->enabled))
  1702. {
  1703. $langs->load("projects");
  1704. print '<tr><td>';
  1705. print '<table class="nobordernopadding" width="100%"><tr><td>';
  1706. print $langs->trans('Project') . '</td>';
  1707. if ($user->rights->propal->creer)
  1708. {
  1709. if ($action != 'classify')
  1710. print '<td align="right"><a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a></td>';
  1711. print '</tr></table>';
  1712. print '</td><td colspan="5">';
  1713. if ($action == 'classify') {
  1714. $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1);
  1715. } else {
  1716. $form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0);
  1717. }
  1718. print '</td></tr>';
  1719. } else {
  1720. print '</td></tr></table>';
  1721. if (! empty($object->fk_project)) {
  1722. print '<td colspan="3">';
  1723. $proj = new Project($db);
  1724. $proj->fetch($object->fk_project);
  1725. print '<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
  1726. print $proj->ref;
  1727. print '</a>';
  1728. print '</td>';
  1729. } else {
  1730. print '<td colspan="3">&nbsp;</td>';
  1731. }
  1732. }
  1733. print '</tr>';
  1734. }
  1735. if ($soc->outstanding_limit)
  1736. {
  1737. // Outstanding Bill
  1738. print '<tr><td>';
  1739. print $langs->trans('OutstandingBill');
  1740. print '</td><td align="right" colspan="5">';
  1741. print price($soc->get_OutstandingBill()) . ' / ';
  1742. print price($soc->outstanding_limit, 0, $langs, 1, - 1, - 1, $conf->currency);
  1743. print '</td>';
  1744. print '</tr>';
  1745. }
  1746. if (! empty($conf->global->BANK_ASK_PAYMENT_BANK_DURING_PROPOSAL) && $conf->banque->enabled)
  1747. {
  1748. // Bank Account
  1749. print '<tr><td>';
  1750. print '<table width="100%" class="nobordernopadding"><tr><td>';
  1751. print $langs->trans('BankAccount');
  1752. print '</td>';
  1753. if ($action != 'editbankaccount' && $user->rights->propal->creer)
  1754. print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&amp;id='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'),1).'</a></td>';
  1755. print '</tr></table>';
  1756. print '</td><td colspan="5">';
  1757. if ($action == 'editbankaccount') {
  1758. $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
  1759. } else {
  1760. $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
  1761. }
  1762. print '</td>';
  1763. print '</tr>';
  1764. }
  1765. // Incoterms
  1766. if (!empty($conf->incoterm->enabled))
  1767. {
  1768. print '<tr><td>';
  1769. print '<table width="100%" class="nobordernopadding"><tr><td>';
  1770. print $langs->trans('IncotermLabel');
  1771. print '<td><td align="right">';
  1772. if ($user->rights->propal->creer) print '<a href="'.DOL_URL_ROOT.'/comm/propal/card.php?id='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
  1773. else print '&nbsp;';
  1774. print '</td></tr></table>';
  1775. print '</td>';
  1776. print '<td colspan="5">';
  1777. if ($action != 'editincoterm')
  1778. {
  1779. print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
  1780. }
  1781. else
  1782. {
  1783. print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
  1784. }
  1785. print '</td></tr>';
  1786. }
  1787. // Other attributes
  1788. $cols = 5;
  1789. include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
  1790. // Amount HT
  1791. print '<tr><td height="10">' . $langs->trans('AmountHT') . '</td>';
  1792. print '<td class="nowrap" colspan="2">' . price($object->total_ht, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
  1793. // Margin Infos
  1794. if (! empty($conf->margin->enabled))
  1795. {
  1796. $rowspan=4;
  1797. if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) $rowspan++;
  1798. if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) $rowspan++;
  1799. print '<td valign="top" width="50%" colspan="3" rowspan="'.$rowspan.'">';
  1800. $formmargin->displayMarginInfos($object);
  1801. print '</td>';
  1802. }
  1803. print '</tr>';
  1804. // Amount VAT
  1805. print '<tr><td height="10">' . $langs->trans('AmountVAT') . '</td>';
  1806. print '<td class="nowrap" colspan="2">' . price($object->total_tva, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
  1807. print '</tr>';
  1808. // Amount Local Taxes
  1809. if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0) // Localtax1
  1810. {
  1811. print '<tr><td height="10">' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
  1812. print '<td class="nowrap" colspan="2">' . price($object->total_localtax1, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
  1813. print '</tr>';
  1814. }
  1815. if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0) // Localtax2
  1816. {
  1817. print '<tr><td height="10">' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
  1818. print '<td class="nowrap" colspan="2">' . price($object->total_localtax2, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
  1819. print '</tr>';
  1820. }
  1821. // Amount TTC
  1822. print '<tr><td height="10">' . $langs->trans('AmountTTC') . '</td>';
  1823. print '<td class="nowrap" colspan="2">' . price($object->total_ttc, '', $langs, 0, - 1, - 1, $conf->currency) . '</td>';
  1824. print '</tr>';
  1825. if (!empty($conf->multicurrency->enabled))
  1826. {
  1827. // Multicurrency Amount HT
  1828. print '<tr><td height="10">' . fieldLabel('MulticurrencyAmountHT','multicurrency_total_ht') . '</td>';
  1829. print '<td class="nowrap" colspan="2">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  1830. print '</tr>';
  1831. // Multicurrency Amount VAT
  1832. print '<tr><td height="10">' . fieldLabel('MulticurrencyAmountVAT','multicurrency_total_tva') . '</td>';
  1833. print '<td class="nowrap" colspan="2">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  1834. print '</tr>';
  1835. // Multicurrency Amount TTC
  1836. print '<tr><td height="10">' . fieldLabel('MulticurrencyAmountTTC','multicurrency_total_ttc') . '</td>';
  1837. print '<td class="nowrap" colspan="2">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  1838. print '</tr>';
  1839. }
  1840. // Statut
  1841. print '<tr><td height="10">' . $langs->trans('Status') . '</td><td align="left" colspan="2">' . $object->getLibStatut(4) . '</td></tr>';
  1842. print '</table><br>';
  1843. if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
  1844. $blocname = 'contacts';
  1845. $title = $langs->trans('ContactsAddresses');
  1846. include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
  1847. }
  1848. if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
  1849. $blocname = 'notes';
  1850. $title = $langs->trans('Notes');
  1851. include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
  1852. }
  1853. /*
  1854. * Lines
  1855. */
  1856. // Show object lines
  1857. $result = $object->getLinesArray();
  1858. print ' <form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '#add' : '#line_' . GETPOST('lineid')) . '" method="POST">
  1859. <input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">
  1860. <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateligne') . '">
  1861. <input type="hidden" name="mode" value="">
  1862. <input type="hidden" name="id" value="' . $object->id . '">
  1863. ';
  1864. if (! empty($conf->use_javascript_ajax) && $object->statut == Propal::STATUS_DRAFT) {
  1865. include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
  1866. }
  1867. print '<table id="tablelines" class="noborder noshadow" width="100%">';
  1868. if (! empty($object->lines))
  1869. $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
  1870. // Form to add new line
  1871. if ($object->statut == Propal::STATUS_DRAFT && $user->rights->propal->creer)
  1872. {
  1873. if ($action != 'editline')
  1874. {
  1875. $var = true;
  1876. // Add products/services form
  1877. $object->formAddObjectLine(1, $mysoc, $soc);
  1878. $parameters = array();
  1879. $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  1880. }
  1881. }
  1882. print '</table>';
  1883. print "</form>\n";
  1884. dol_fiche_end();
  1885. if ($action == 'statut')
  1886. {
  1887. /*
  1888. * Form to close proposal (signed or not)
  1889. */
  1890. $form_close = '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
  1891. $form_close .= '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  1892. $form_close .= '<table class="border" width="100%">';
  1893. $form_close .= '<tr><td width="150" align="left">' . $langs->trans("CloseAs") . '</td><td align="left">';
  1894. $form_close .= '<input type="hidden" name="action" value="setstatut">';
  1895. $form_close .= '<select id="statut" name="statut" class="flat">';
  1896. $form_close .= '<option value="0">&nbsp;</option>';
  1897. $form_close .= '<option value="2">' . $object->labelstatut [2] . '</option>';
  1898. $form_close .= '<option value="3">' . $object->labelstatut [3] . '</option>';
  1899. $form_close .= '</select>';
  1900. $form_close .= '</td></tr>';
  1901. $form_close .= '<tr><td width="150" align="left">' . $langs->trans('Note') . '</td><td align="left"><textarea cols="70" rows="' . ROWS_3 . '" wrap="soft" name="note">';
  1902. $form_close .= $object->note;
  1903. $form_close .= '</textarea></td></tr>';
  1904. $form_close .= '<tr><td align="center" colspan="2">';
  1905. $form_close .= '<input type="submit" class="button" name="validate" value="' . $langs->trans('Save') . '">';
  1906. $form_close .= ' &nbsp; <input type="submit" class="button" name="cancel" value="' . $langs->trans('Cancel') . '">';
  1907. $form_close .= '<a name="close">&nbsp;</a>';
  1908. $form_close .= '</td>';
  1909. $form_close .= '</tr></table></form>';
  1910. print $form_close;
  1911. }
  1912. /*
  1913. * Boutons Actions
  1914. */
  1915. if ($action != 'presend') {
  1916. print '<div class="tabsAction">';
  1917. $parameters = array();
  1918. $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been
  1919. // modified by hook
  1920. if (empty($reshook))
  1921. {
  1922. if ($action != 'statut' && $action != 'editline')
  1923. {
  1924. // Validate
  1925. if ($object->statut == Propal::STATUS_DRAFT && $object->total_ttc >= 0 && count($object->lines) > 0)
  1926. {
  1927. if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->propal->creer))
  1928. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->propal->propal_advance->validate)))
  1929. {
  1930. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=validate">' . $langs->trans('Validate') . '</a></div>';
  1931. }
  1932. else
  1933. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('Validate') . '</a></div>';
  1934. }
  1935. // Create event
  1936. if ($conf->agenda->enabled && ! empty($conf->global->MAIN_ADD_EVENT_ON_ELEMENT_CARD)) // Add hidden condition because this is not a "workflow" action so should appears somewhere else on page.
  1937. {
  1938. print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/comm/action/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans("AddAction") . '</a></div>';
  1939. }
  1940. // Edit
  1941. if ($object->statut == Propal::STATUS_VALIDATED && $user->rights->propal->creer) {
  1942. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=modif">' . $langs->trans('Modify') . '</a></div>';
  1943. }
  1944. // ReOpen
  1945. if (($object->statut == Propal::STATUS_SIGNED || $object->statut == Propal::STATUS_NOTSIGNED || $object->statut == Propal::STATUS_BILLED) && $user->rights->propal->cloturer) {
  1946. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=reopen' . (empty($conf->global->MAIN_JUMP_TAG) ? '' : '#reopen') . '"';
  1947. print '>' . $langs->trans('ReOpen') . '</a></div>';
  1948. }
  1949. // Send
  1950. if ($object->statut == Propal::STATUS_VALIDATED || $object->statut == Propal::STATUS_SIGNED) {
  1951. if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->propal->propal_advance->send) {
  1952. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=presend&amp;mode=init">' . $langs->trans('SendByMail') . '</a></div>';
  1953. } else
  1954. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('SendByMail') . '</a></div>';
  1955. }
  1956. // Create an order
  1957. if (! empty($conf->commande->enabled) && $object->statut == Propal::STATUS_SIGNED) {
  1958. if ($user->rights->commande->creer) {
  1959. print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/commande/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans("AddOrder") . '</a></div>';
  1960. }
  1961. }
  1962. // Create contract
  1963. if ($conf->contrat->enabled && $object->statut == Propal::STATUS_SIGNED) {
  1964. $langs->load("contracts");
  1965. if ($user->rights->contrat->creer) {
  1966. print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/contrat/card.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans('AddContract') . '</a></div>';
  1967. }
  1968. }
  1969. // Create an invoice and classify billed
  1970. if ($object->statut == Propal::STATUS_SIGNED)
  1971. {
  1972. if (! empty($conf->facture->enabled) && $user->rights->facture->creer)
  1973. {
  1974. print '<div class="inline-block divButAction"><a class="butAction" href="' . DOL_URL_ROOT . '/compta/facture.php?action=create&amp;origin=' . $object->element . '&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '">' . $langs->trans("AddBill") . '</a></div>';
  1975. }
  1976. $arrayofinvoiceforpropal = $object->getInvoiceArrayList();
  1977. if ((is_array($arrayofinvoiceforpropal) && count($arrayofinvoiceforpropal) > 0) || empty($conf->global->WORKFLOW_PROPAL_NEED_INVOICE_TO_BE_CLASSIFIED_BILLED))
  1978. {
  1979. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=classifybilled&amp;socid=' . $object->socid . '">' . $langs->trans("ClassifyBilled") . '</a></div>';
  1980. }
  1981. }
  1982. // Set accepted/refused
  1983. if ($object->statut == Propal::STATUS_VALIDATED && $user->rights->propal->cloturer) {
  1984. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=statut' . (empty($conf->global->MAIN_JUMP_TAG) ? '' : '#close') . '"';
  1985. print '>' . $langs->trans('SetAcceptedRefused') . '</a></div>';
  1986. }
  1987. // Clone
  1988. if ($user->rights->propal->creer) {
  1989. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '&amp;socid=' . $object->socid . '&amp;action=clone&amp;object=' . $object->element . '">' . $langs->trans("ToClone") . '</a></div>';
  1990. }
  1991. // Delete
  1992. if ($user->rights->propal->supprimer) {
  1993. print '<div class="inline-block divButAction"><a class="butActionDelete" href="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '&amp;action=delete"';
  1994. print '>' . $langs->trans('Delete') . '</a></div>';
  1995. }
  1996. }
  1997. }
  1998. print '</div>';
  1999. }
  2000. print "<br>\n";
  2001. //Select mail models is same action as presend
  2002. if (GETPOST('modelselected')) $action = 'presend';
  2003. if ($action != 'presend')
  2004. {
  2005. print '<div class="fichecenter"><div class="fichehalfleft">';
  2006. // print '<table width="100%"><tr><td width="50%" valign="top">';
  2007. // print '<a name="builddoc"></a>'; // ancre
  2008. /*
  2009. * Documents generes
  2010. */
  2011. $filename = dol_sanitizeFileName($object->ref);
  2012. $filedir = $conf->propal->dir_output . "/" . dol_sanitizeFileName($object->ref);
  2013. $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id;
  2014. $genallowed = $user->rights->propal->creer;
  2015. $delallowed = $user->rights->propal->supprimer;
  2016. $var = true;
  2017. $somethingshown = $formfile->show_documents('propal', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', 0, '', $soc->default_lang);
  2018. // Linked object block
  2019. $somethingshown = $form->showLinkedObjectBlock($object);
  2020. // Show links to link elements
  2021. $linktoelem = $form->showLinkToObjectBlock($object);
  2022. if ($linktoelem) print '<br>'.$linktoelem;
  2023. print '</div><div class="fichehalfright"><div class="ficheaddleft">';
  2024. // print '</td><td valign="top" width="50%">';
  2025. // List of actions on element
  2026. include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
  2027. $formactions = new FormActions($db);
  2028. $somethingshown = $formactions->showactions($object, 'propal', $socid);
  2029. // print '</td></tr></table>';
  2030. print '</div></div></div>';
  2031. }
  2032. /*
  2033. * Action presend
  2034. */
  2035. if ($action == 'presend')
  2036. {
  2037. $object->fetch_projet();
  2038. $ref = dol_sanitizeFileName($object->ref);
  2039. include_once DOL_DOCUMENT_ROOT . '/core/lib/files.lib.php';
  2040. $fileparams = dol_most_recent_file($conf->propal->dir_output . '/' . $ref, preg_quote($ref, '/').'[^\-]+');
  2041. $file = $fileparams['fullname'];
  2042. // Define output language
  2043. $outputlangs = $langs;
  2044. $newlang = '';
  2045. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id']))
  2046. $newlang = $_REQUEST['lang_id'];
  2047. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  2048. $newlang = $object->thirdparty->default_lang;
  2049. if (!empty($newlang))
  2050. {
  2051. $outputlangs = new Translate('', $conf);
  2052. $outputlangs->setDefaultLang($newlang);
  2053. $outputlangs->load('commercial');
  2054. }
  2055. // Build document if it not exists
  2056. if (! $file || ! is_readable($file)) {
  2057. $result = $object->generateDocument(GETPOST('model') ? GETPOST('model') : $object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  2058. if ($result <= 0) {
  2059. dol_print_error($db, $object->error, $object->errors);
  2060. exit();
  2061. }
  2062. $fileparams = dol_most_recent_file($conf->propal->dir_output . '/' . $ref, preg_quote($ref, '/').'[^\-]+');
  2063. $file = $fileparams['fullname'];
  2064. }
  2065. print '<div class="clearboth"></div>';
  2066. print '<br>';
  2067. print load_fiche_titre($langs->trans('SendPropalByMail'));
  2068. dol_fiche_head('');
  2069. // Create form object
  2070. include_once DOL_DOCUMENT_ROOT . '/core/class/html.formmail.class.php';
  2071. $formmail = new FormMail($db);
  2072. $formmail->param['langsmodels']=(empty($newlang)?$langs->defaultlang:$newlang);
  2073. $formmail->fromtype = 'user';
  2074. $formmail->fromid = $user->id;
  2075. $formmail->fromname = $user->getFullName($langs);
  2076. $formmail->frommail = $user->email;
  2077. $formmail->trackid='pro'.$object->id;
  2078. if (! empty($conf->global->MAIN_EMAIL_ADD_TRACK_ID) && ($conf->global->MAIN_EMAIL_ADD_TRACK_ID & 2)) // If bit 2 is set
  2079. {
  2080. include DOL_DOCUMENT_ROOT.'/core/lib/functions2.lib.php';
  2081. $formmail->frommail=dolAddEmailTrackId($formmail->frommail, 'pro'.$object->id);
  2082. }
  2083. $formmail->withfrom = 1;
  2084. $liste = array();
  2085. foreach ($object->thirdparty->thirdparty_and_contact_email_array(1) as $key => $value)
  2086. $liste [$key] = $value;
  2087. $formmail->withto = GETPOST("sendto") ? GETPOST("sendto") : $liste;
  2088. $formmail->withtocc = $liste;
  2089. $formmail->withtoccc = (! empty($conf->global->MAIN_EMAIL_USECCC) ? $conf->global->MAIN_EMAIL_USECCC : false);
  2090. if (empty($object->ref_client)) {
  2091. $formmail->withtopic = $outputlangs->trans('SendPropalRef', '__PROPREF__');
  2092. } else if (! empty($object->ref_client)) {
  2093. $formmail->withtopic = $outputlangs->trans('SendPropalRef', '__PROPREF__ (__REFCLIENT__)');
  2094. }
  2095. $formmail->withfile = 2;
  2096. $formmail->withbody = 1;
  2097. $formmail->withdeliveryreceipt = 1;
  2098. $formmail->withcancel = 1;
  2099. // Tableau des substitutions
  2100. $formmail->setSubstitFromObject($object);
  2101. $formmail->substit['__PROPREF__'] = $object->ref; // For backward compatibility
  2102. // Find the good contact adress
  2103. $custcontact = '';
  2104. $contactarr = array();
  2105. $contactarr = $object->liste_contact(- 1, 'external');
  2106. if (is_array($contactarr) && count($contactarr) > 0) {
  2107. foreach ($contactarr as $contact) {
  2108. if ($contact ['libelle'] == $langs->trans('TypeContact_propal_external_CUSTOMER')) { // TODO Use code and not label
  2109. $contactstatic = new Contact($db);
  2110. $contactstatic->fetch($contact ['id']);
  2111. $custcontact = $contactstatic->getFullName($langs, 1);
  2112. }
  2113. }
  2114. if (! empty($custcontact)) {
  2115. $formmail->substit['__CONTACTCIVNAME__'] = $custcontact;
  2116. }
  2117. }
  2118. // Tableau des parametres complementaires
  2119. $formmail->param['action'] = 'send';
  2120. $formmail->param['models'] = 'propal_send';
  2121. $formmail->param['models_id']=GETPOST('modelmailselected','int');
  2122. $formmail->param['id'] = $object->id;
  2123. $formmail->param['returnurl'] = $_SERVER["PHP_SELF"] . '?id=' . $object->id;
  2124. // Init list of files
  2125. if (GETPOST("mode") == 'init') {
  2126. $formmail->clear_attached_files();
  2127. $formmail->add_attached_files($file, basename($file), dol_mimetype($file));
  2128. }
  2129. print $formmail->get_form();
  2130. dol_fiche_end();
  2131. }
  2132. }
  2133. // End of page
  2134. llxFooter();
  2135. $db->close();