card.php 207 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936
  1. <?php
  2. /* Copyright (C) 2002-2006 Rodolphe Quiedeville <rodolphe@quiedeville.org>
  3. * Copyright (C) 2004 Eric Seigne <eric.seigne@ryxeo.com>
  4. * Copyright (C) 2004-2016 Laurent Destailleur <eldy@users.sourceforge.net>
  5. * Copyright (C) 2005 Marc Barilley / Ocebo <marc@ocebo.com>
  6. * Copyright (C) 2005-2015 Regis Houssin <regis.houssin@capnetworks.com>
  7. * Copyright (C) 2006 Andre Cianfarani <acianfa@free.fr>
  8. * Copyright (C) 2010-2015 Juanjo Menent <jmenent@2byte.es>
  9. * Copyright (C) 2012-2013 Christophe Battarel <christophe.battarel@altairis.fr>
  10. * Copyright (C) 2012-2013 Cédric Salvador <csalvador@gpcsolutions.fr>
  11. * Copyright (C) 2012-2014 Raphaël Doursenaud <rdoursenaud@gpcsolutions.fr>
  12. * Copyright (C) 2013 Jean-Francois FERRY <jfefe@aternatik.fr>
  13. * Copyright (C) 2013-2014 Florian Henry <florian.henry@open-concept.pro>
  14. * Copyright (C) 2013 Cédric Salvador <csalvador@gpcsolutions.fr>
  15. * Copyright (C) 2014-2018 Ferran Marcet <fmarcet@2byte.es>
  16. * Copyright (C) 2015-2016 Marcos García <marcosgdf@gmail.com>
  17. *
  18. * This program is free software; you can redistribute it and/or modify
  19. * it under the terms of the GNU General Public License as published by
  20. * the Free Software Foundation; either version 3 of the License, or
  21. * (at your option) any later version.
  22. *
  23. * This program is distributed in the hope that it will be useful,
  24. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. * GNU General Public License for more details.
  27. *
  28. * You should have received a copy of the GNU General Public License
  29. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  30. */
  31. /**
  32. * \file htdocs/compta/facture/card.php
  33. * \ingroup facture
  34. * \brief Page to create/see an invoice
  35. */
  36. require '../../main.inc.php';
  37. require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture.class.php';
  38. require_once DOL_DOCUMENT_ROOT . '/compta/facture/class/facture-rec.class.php';
  39. require_once DOL_DOCUMENT_ROOT . '/compta/bank/class/account.class.php';
  40. require_once DOL_DOCUMENT_ROOT . '/compta/paiement/class/paiement.class.php';
  41. require_once DOL_DOCUMENT_ROOT . '/core/modules/facture/modules_facture.php';
  42. require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  43. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formfile.class.php';
  44. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formother.class.php';
  45. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formmargin.class.php';
  46. require_once DOL_DOCUMENT_ROOT . '/core/lib/invoice.lib.php';
  47. require_once DOL_DOCUMENT_ROOT . '/core/lib/functions2.lib.php';
  48. require_once DOL_DOCUMENT_ROOT . '/core/lib/date.lib.php';
  49. require_once DOL_DOCUMENT_ROOT . '/core/class/extrafields.class.php';
  50. if (! empty($conf->commande->enabled))
  51. require_once DOL_DOCUMENT_ROOT . '/commande/class/commande.class.php';
  52. if (! empty($conf->projet->enabled)) {
  53. require_once DOL_DOCUMENT_ROOT . '/projet/class/project.class.php';
  54. require_once DOL_DOCUMENT_ROOT . '/core/class/html.formprojet.class.php';
  55. }
  56. require_once DOL_DOCUMENT_ROOT . '/core/class/doleditor.class.php';
  57. if (!empty($conf->variants->enabled)) {
  58. require_once DOL_DOCUMENT_ROOT.'/variants/class/ProductCombination.class.php';
  59. }
  60. if (! empty($conf->accounting->enabled)) {
  61. require_once DOL_DOCUMENT_ROOT . '/accountancy/class/accountingjournal.class.php';
  62. }
  63. // Load translation files required by the page
  64. $langs->loadLangs(array('bills','companies','compta','products','banks','main','withdrawals'));
  65. if (! empty($conf->incoterm->enabled)) $langs->load('incoterm');
  66. if (! empty($conf->margin->enabled)) $langs->load('margins');
  67. $projectid = (GETPOST('projectid','int') ? GETPOST('projectid', 'int') : 0);
  68. $id = (GETPOST('id', 'int') ? GETPOST('id', 'int') : GETPOST('facid', 'int')); // For backward compatibility
  69. $ref = GETPOST('ref', 'alpha');
  70. $socid = GETPOST('socid', 'int');
  71. $action = GETPOST('action', 'alpha');
  72. $confirm = GETPOST('confirm', 'alpha');
  73. $cancel = GETPOST('cancel', 'alpha');
  74. $lineid = GETPOST('lineid', 'int');
  75. $userid = GETPOST('userid', 'int');
  76. $search_ref = GETPOST('sf_ref','alpha') ? GETPOST('sf_ref', 'alpha') : GETPOST('search_ref', 'alpha');
  77. $search_societe = GETPOST('search_societe', 'alpha');
  78. $search_montant_ht = GETPOST('search_montant_ht', 'alpha');
  79. $search_montant_ttc = GETPOST('search_montant_ttc', 'alpha');
  80. $origin = GETPOST('origin', 'alpha');
  81. $originid = (GETPOST('originid', 'int') ? GETPOST('originid', 'int') : GETPOST('origin_id', 'int')); // For backward compatibility
  82. $fac_rec=GETPOST('fac_rec','int');
  83. // PDF
  84. $hidedetails = (GETPOST('hidedetails', 'int') ? GETPOST('hidedetails', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DETAILS) ? 1 : 0));
  85. $hidedesc = (GETPOST('hidedesc', 'int') ? GETPOST('hidedesc', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_DESC) ? 1 : 0));
  86. $hideref = (GETPOST('hideref', 'int') ? GETPOST('hideref', 'int') : (! empty($conf->global->MAIN_GENERATE_DOCUMENTS_HIDE_REF) ? 1 : 0));
  87. // Nombre de ligne pour choix de produit/service predefinis
  88. $NBLINES = 4;
  89. $usehm = (! empty($conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE) ? $conf->global->MAIN_USE_HOURMIN_IN_DATE_RANGE : 0);
  90. $object = new Facture($db);
  91. $extrafields = new ExtraFields($db);
  92. // Load object
  93. if ($id > 0 || ! empty($ref)) {
  94. $ret = $object->fetch($id, $ref, '', '', $conf->global->INVOICE_USE_SITUATION);
  95. }
  96. // Initialize technical object to manage hooks of page. Note that conf->hooks_modules contains array of hook context
  97. $hookmanager->initHooks(array('invoicecard','globalcard'));
  98. $permissionnote = $user->rights->facture->creer; // Used by the include of actions_setnotes.inc.php
  99. $permissiondellink=$user->rights->facture->creer; // Used by the include of actions_dellink.inc.php
  100. $permissiontoedit = $user->rights->facture->creer; // Used by the include of actions_lineupdonw.inc.php
  101. // Security check
  102. $fieldid = (! empty($ref) ? 'facnumber' : 'rowid');
  103. if ($user->societe_id) $socid = $user->societe_id;
  104. $isdraft = (($object->statut == Facture::STATUS_DRAFT) ? 1 : 0);
  105. $result = restrictedArea($user, 'facture', $id, '', '', 'fk_soc', $fieldid, null, $isdraft);
  106. /*
  107. * Actions
  108. */
  109. $parameters = array('socid' => $socid);
  110. $reshook = $hookmanager->executeHooks('doActions', $parameters, $object, $action); // Note that $action and $object may have been modified by some hooks
  111. if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  112. if (empty($reshook))
  113. {
  114. if ($cancel)
  115. {
  116. if (! empty($backtopage))
  117. {
  118. header("Location: ".$backtopage);
  119. exit;
  120. }
  121. $action='';
  122. }
  123. include DOL_DOCUMENT_ROOT.'/core/actions_setnotes.inc.php'; // Must be include, not include_once
  124. include DOL_DOCUMENT_ROOT.'/core/actions_dellink.inc.php'; // Must be include, not include_once
  125. include DOL_DOCUMENT_ROOT.'/core/actions_lineupdown.inc.php'; // Must be include, not include_once
  126. // Action clone object
  127. if ($action == 'confirm_clone' && $confirm == 'yes' && $user->rights->facture->creer) {
  128. // if (1 == 0 && empty($_REQUEST["clone_content"]) && empty($_REQUEST["clone_receivers"])) {
  129. // $mesgs [] = '<div class="error">' . $langs->trans("NoCloneOptionsSpecified") . '</div>';
  130. // } else {
  131. if ($object->fetch($id) > 0) {
  132. $result = $object->createFromClone($socid);
  133. if ($result > 0) {
  134. header("Location: " . $_SERVER['PHP_SELF'] . '?facid=' . $result);
  135. exit();
  136. } else {
  137. setEventMessages($object->error, $object->errors, 'errors');
  138. $action = '';
  139. }
  140. }
  141. // }
  142. }
  143. // Change status of invoice
  144. else if ($action == 'reopen' && $user->rights->facture->creer) {
  145. $result = $object->fetch($id);
  146. if ($object->statut == 2 || ($object->statut == 3 && $object->close_code != 'replaced') || ($object->statut == 1 && $object->paye == 1)) { // ($object->statut == 1 && $object->paye == 1) should not happened but can be found when data are corrupted
  147. $result = $object->set_unpaid($user);
  148. if ($result > 0) {
  149. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  150. exit();
  151. } else {
  152. setEventMessages($object->error, $object->errors, 'errors');
  153. }
  154. }
  155. }
  156. // Delete invoice
  157. else if ($action == 'confirm_delete' && $confirm == 'yes') {
  158. $result = $object->fetch($id);
  159. $object->fetch_thirdparty();
  160. $idwarehouse = GETPOST('idwarehouse');
  161. $qualified_for_stock_change = 0;
  162. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
  163. $qualified_for_stock_change = $object->hasProductsOrServices(2);
  164. } else {
  165. $qualified_for_stock_change = $object->hasProductsOrServices(1);
  166. }
  167. $isErasable=$object->is_erasable();
  168. if (($user->rights->facture->supprimer && $isErasable > 0)
  169. || ($user->rights->facture->creer && $isErasable == 1))
  170. {
  171. $result = $object->delete($user, 0, $idwarehouse);
  172. if ($result > 0) {
  173. header('Location: ' . DOL_URL_ROOT . '/compta/facture/list.php?restore_lastsearch_values=1');
  174. exit();
  175. } else {
  176. setEventMessages($object->error, $object->errors, 'errors');
  177. $action='';
  178. }
  179. }
  180. }
  181. // Delete line
  182. else if ($action == 'confirm_deleteline' && $confirm == 'yes' && $user->rights->facture->creer)
  183. {
  184. $object->fetch($id);
  185. $object->fetch_thirdparty();
  186. $result = $object->deleteline(GETPOST('lineid'));
  187. if ($result > 0) {
  188. // Define output language
  189. $outputlangs = $langs;
  190. $newlang = '';
  191. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && ! empty($_REQUEST['lang_id']))
  192. $newlang = $_REQUEST['lang_id'];
  193. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  194. $newlang = $object->thirdparty->default_lang;
  195. if (! empty($newlang)) {
  196. $outputlangs = new Translate("", $conf);
  197. $outputlangs->setDefaultLang($newlang);
  198. $outputlangs->load('products');
  199. }
  200. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  201. $ret = $object->fetch($id); // Reload to get new records
  202. $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  203. }
  204. if ($result >= 0) {
  205. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  206. exit();
  207. }
  208. } else {
  209. setEventMessages($object->error, $object->errors, 'errors');
  210. $action = '';
  211. }
  212. }
  213. // Delete link of credit note to invoice
  214. else if ($action == 'unlinkdiscount' && $user->rights->facture->creer)
  215. {
  216. $discount = new DiscountAbsolute($db);
  217. $result = $discount->fetch(GETPOST("discountid"));
  218. $discount->unlink_invoice();
  219. }
  220. // Validation
  221. else if ($action == 'valid' && $user->rights->facture->creer)
  222. {
  223. $object->fetch($id);
  224. // On verifie signe facture
  225. if ($object->type == Facture::TYPE_CREDIT_NOTE) {
  226. // Si avoir, le signe doit etre negatif
  227. if ($object->total_ht >= 0) {
  228. setEventMessages($langs->trans("ErrorInvoiceAvoirMustBeNegative"), null, 'errors');
  229. $action = '';
  230. }
  231. } else {
  232. // Si non avoir, le signe doit etre positif
  233. if (empty($conf->global->FACTURE_ENABLE_NEGATIVE) && $object->total_ht < 0) {
  234. setEventMessages($langs->trans("ErrorInvoiceOfThisTypeMustBePositive"), null, 'errors');
  235. $action = '';
  236. }
  237. }
  238. }
  239. else if ($action == 'set_thirdparty' && $user->rights->facture->creer)
  240. {
  241. $object->fetch($id);
  242. $object->setValueFrom('fk_soc', $socid, '', null, 'int', '', $user, 'BILL_MODIFY');
  243. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  244. exit();
  245. }
  246. else if ($action == 'classin' && $user->rights->facture->creer)
  247. {
  248. $object->fetch($id);
  249. $object->setProject($_POST['projectid']);
  250. }
  251. else if ($action == 'setmode' && $user->rights->facture->creer)
  252. {
  253. $object->fetch($id);
  254. $result = $object->setPaymentMethods(GETPOST('mode_reglement_id', 'int'));
  255. if ($result < 0)
  256. dol_print_error($db, $object->error);
  257. }
  258. // Multicurrency Code
  259. else if ($action == 'setmulticurrencycode' && $user->rights->facture->creer) {
  260. $result = $object->setMulticurrencyCode(GETPOST('multicurrency_code', 'alpha'));
  261. }
  262. // Multicurrency rate
  263. else if ($action == 'setmulticurrencyrate' && $user->rights->facture->creer) {
  264. $result = $object->setMulticurrencyRate(price2num(GETPOST('multicurrency_tx')), GETPOST('calculation_mode', 'int'));
  265. }
  266. else if ($action == 'setinvoicedate' && $user->rights->facture->creer)
  267. {
  268. $object->fetch($id);
  269. $old_date_lim_reglement = $object->date_lim_reglement;
  270. $date = dol_mktime(12, 0, 0, $_POST['invoicedatemonth'], $_POST['invoicedateday'], $_POST['invoicedateyear']);
  271. if (empty($date))
  272. {
  273. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
  274. header('Location: '.$_SERVER["PHP_SELF"].'?facid='.$id.'&action=editinvoicedate');
  275. exit;
  276. }
  277. $object->date=$date;
  278. $new_date_lim_reglement = $object->calculate_date_lim_reglement();
  279. if ($new_date_lim_reglement > $old_date_lim_reglement) $object->date_lim_reglement = $new_date_lim_reglement;
  280. if ($object->date_lim_reglement < $object->date) $object->date_lim_reglement = $object->date;
  281. $result = $object->update($user);
  282. if ($result < 0) dol_print_error($db, $object->error);
  283. }
  284. else if ($action == 'setdate_pointoftax' && $user->rights->facture->creer)
  285. {
  286. $object->fetch($id);
  287. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  288. $object->date_pointoftax=$date_pointoftax;
  289. $result = $object->update($user);
  290. if ($result < 0) dol_print_error($db, $object->error);
  291. }
  292. else if ($action == 'setconditions' && $user->rights->facture->creer)
  293. {
  294. $object->fetch($id);
  295. $object->cond_reglement_code = 0; // To clean property
  296. $object->cond_reglement_id = 0; // To clean property
  297. $result = $object->setPaymentTerms(GETPOST('cond_reglement_id', 'int'));
  298. if ($result < 0) dol_print_error($db, $object->error);
  299. $old_date_lim_reglement = $object->date_lim_reglement;
  300. $new_date_lim_reglement = $object->calculate_date_lim_reglement();
  301. if ($new_date_lim_reglement > $old_date_lim_reglement) $object->date_lim_reglement = $new_date_lim_reglement;
  302. if ($object->date_lim_reglement < $object->date) $object->date_lim_reglement = $object->date;
  303. $result = $object->update($user);
  304. if ($result < 0) dol_print_error($db, $object->error);
  305. }
  306. else if ($action == 'setpaymentterm' && $user->rights->facture->creer)
  307. {
  308. $object->fetch($id);
  309. $object->date_lim_reglement = dol_mktime(12, 0, 0, $_POST['paymenttermmonth'], $_POST['paymenttermday'], $_POST['paymenttermyear']);
  310. if ($object->date_lim_reglement < $object->date) {
  311. $object->date_lim_reglement = $object->calculate_date_lim_reglement();
  312. setEventMessages($langs->trans("DatePaymentTermCantBeLowerThanObjectDate"), null, 'warnings');
  313. }
  314. $result = $object->update($user);
  315. if ($result < 0)
  316. dol_print_error($db, $object->error);
  317. }
  318. else if ($action == 'setrevenuestamp' && $user->rights->facture->creer)
  319. {
  320. $object->fetch($id);
  321. $object->revenuestamp = GETPOST('revenuestamp');
  322. $result = $object->update($user);
  323. $object->update_price(1);
  324. if ($result < 0)
  325. dol_print_error($db, $object->error);
  326. }
  327. // Set incoterm
  328. elseif ($action == 'set_incoterms' && !empty($conf->incoterm->enabled))
  329. {
  330. $result = $object->setIncoterms(GETPOST('incoterm_id', 'int'), GETPOST('location_incoterms', 'alpha'));
  331. }
  332. // bank account
  333. else if ($action == 'setbankaccount' && $user->rights->facture->creer)
  334. {
  335. $result=$object->setBankAccount(GETPOST('fk_account', 'int'));
  336. }
  337. else if ($action == 'setremisepercent' && $user->rights->facture->creer)
  338. {
  339. $object->fetch($id);
  340. $result = $object->set_remise($user, $_POST['remise_percent']);
  341. }
  342. else if ($action == "setabsolutediscount" && $user->rights->facture->creer)
  343. {
  344. // POST[remise_id] or POST[remise_id_for_payment]
  345. // We use the credit to reduce amount of invoice
  346. if (! empty($_POST["remise_id"])) {
  347. $ret = $object->fetch($id);
  348. if ($ret > 0) {
  349. $result = $object->insert_discount($_POST["remise_id"]);
  350. if ($result < 0) {
  351. setEventMessages($object->error, $object->errors, 'errors');
  352. }
  353. } else {
  354. dol_print_error($db, $object->error);
  355. }
  356. }
  357. // We use the credit to reduce remain to pay
  358. if (! empty($_POST["remise_id_for_payment"]))
  359. {
  360. require_once DOL_DOCUMENT_ROOT . '/core/class/discount.class.php';
  361. $discount = new DiscountAbsolute($db);
  362. $discount->fetch($_POST["remise_id_for_payment"]);
  363. //var_dump($object->getRemainToPay(0));
  364. //var_dump($discount->amount_ttc);exit;
  365. if (price2num($discount->amount_ttc) > price2num($object->getRemainToPay(0)))
  366. {
  367. // TODO Split the discount in 2 automatically
  368. $error++;
  369. setEventMessages($langs->trans("ErrorDiscountLargerThanRemainToPaySplitItBefore"), null, 'errors');
  370. }
  371. if (! $error)
  372. {
  373. $result = $discount->link_to_invoice(0, $id);
  374. if ($result < 0) {
  375. setEventMessages($discount->error, $discount->errors, 'errors');
  376. }
  377. }
  378. }
  379. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  380. {
  381. $outputlangs = $langs;
  382. $newlang = '';
  383. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
  384. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  385. if (! empty($newlang)) {
  386. $outputlangs = new Translate("", $conf);
  387. $outputlangs->setDefaultLang($newlang);
  388. }
  389. $ret = $object->fetch($id); // Reload to get new records
  390. $result = $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  391. if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
  392. }
  393. }
  394. else if ($action == 'setref_client' && $user->rights->facture->creer)
  395. {
  396. $object->fetch($id);
  397. $object->set_ref_client(GETPOST('ref_client'));
  398. }
  399. // Classify to validated
  400. else if ($action == 'confirm_valid' && $confirm == 'yes' &&
  401. ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  402. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->validate)))
  403. )
  404. {
  405. $idwarehouse = GETPOST('idwarehouse','int');
  406. $object->fetch($id);
  407. $object->fetch_thirdparty();
  408. // Check parameters
  409. // Check for mandatory fields defined into setup
  410. $array_to_check=array('IDPROF1','IDPROF2','IDPROF3','IDPROF4','IDPROF5','IDPROF6','EMAIL');
  411. foreach($array_to_check as $key)
  412. {
  413. $keymin=strtolower($key);
  414. $i=(int) preg_replace('/[^0-9]/','',$key);
  415. $vallabel=$object->thirdparty->$keymin;
  416. if ($i > 0)
  417. {
  418. if ($object->thirdparty->isACompany())
  419. {
  420. // Check for mandatory prof id (but only if country is other than ours)
  421. if ($mysoc->country_id > 0 && $object->thirdparty->country_id == $mysoc->country_id)
  422. {
  423. $idprof_mandatory ='SOCIETE_'.$key.'_INVOICE_MANDATORY';
  424. if (! $vallabel && ! empty($conf->global->$idprof_mandatory))
  425. {
  426. $langs->load("errors");
  427. $error++;
  428. setEventMessages($langs->trans('ErrorProdIdIsMandatory', $langs->transcountry('ProfId'.$i, $object->thirdparty->country_code)).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors');
  429. }
  430. }
  431. }
  432. }
  433. else
  434. {
  435. //var_dump($conf->global->SOCIETE_EMAIL_MANDATORY);
  436. if ($key == 'EMAIL')
  437. {
  438. // Check for mandatory
  439. if (! empty($conf->global->SOCIETE_EMAIL_INVOICE_MANDATORY) && ! isValidEMail($object->thirdparty->email))
  440. {
  441. $langs->load("errors");
  442. $error++;
  443. setEventMessages($langs->trans("ErrorBadEMail", $object->thirdparty->email).' ('.$langs->trans("ForbiddenBySetupRules").')', null, 'errors');
  444. }
  445. }
  446. }
  447. }
  448. $qualified_for_stock_change = 0;
  449. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
  450. $qualified_for_stock_change = $object->hasProductsOrServices(2);
  451. } else {
  452. $qualified_for_stock_change = $object->hasProductsOrServices(1);
  453. }
  454. // Check for warehouse
  455. if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change)
  456. {
  457. if (! $idwarehouse || $idwarehouse == - 1) {
  458. $error++;
  459. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
  460. $action = '';
  461. }
  462. }
  463. if (! $error)
  464. {
  465. $result = $object->validate($user, '', $idwarehouse);
  466. if ($result >= 0)
  467. {
  468. // Define output language
  469. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  470. {
  471. $outputlangs = $langs;
  472. $newlang = '';
  473. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
  474. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  475. if (! empty($newlang)) {
  476. $outputlangs = new Translate("", $conf);
  477. $outputlangs->setDefaultLang($newlang);
  478. $outputlangs->load('products');
  479. }
  480. $model=$object->modelpdf;
  481. $ret = $object->fetch($id); // Reload to get new records
  482. $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
  483. if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
  484. }
  485. }
  486. else
  487. {
  488. if (count($object->errors)) setEventMessages(null, $object->errors, 'errors');
  489. else setEventMessages($object->error, $object->errors, 'errors');
  490. }
  491. }
  492. }
  493. // Go back to draft status (unvalidate)
  494. else if ($action == 'confirm_modif' &&
  495. ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  496. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
  497. )
  498. {
  499. $idwarehouse = GETPOST('idwarehouse','int');
  500. $object->fetch($id);
  501. $object->fetch_thirdparty();
  502. $qualified_for_stock_change = 0;
  503. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
  504. $qualified_for_stock_change = $object->hasProductsOrServices(2);
  505. } else {
  506. $qualified_for_stock_change = $object->hasProductsOrServices(1);
  507. }
  508. // Check parameters
  509. if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change)
  510. {
  511. if (! $idwarehouse || $idwarehouse == - 1) {
  512. $error++;
  513. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv("Warehouse")), null, 'errors');
  514. $action = '';
  515. }
  516. }
  517. if (! $error) {
  518. // On verifie si la facture a des paiements
  519. $sql = 'SELECT pf.amount';
  520. $sql .= ' FROM ' . MAIN_DB_PREFIX . 'paiement_facture as pf';
  521. $sql .= ' WHERE pf.fk_facture = ' . $object->id;
  522. $result = $db->query($sql);
  523. if ($result) {
  524. $i = 0;
  525. $num = $db->num_rows($result);
  526. while ($i < $num) {
  527. $objp = $db->fetch_object($result);
  528. $totalpaye += $objp->amount;
  529. $i ++;
  530. }
  531. } else {
  532. dol_print_error($db, '');
  533. }
  534. $resteapayer = $object->total_ttc - $totalpaye;
  535. // On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
  536. $ventilExportCompta = $object->getVentilExportCompta();
  537. // On verifie si aucun paiement n'a ete effectue
  538. if ($ventilExportCompta == 0)
  539. {
  540. if (! empty($conf->global->INVOICE_CAN_ALWAYS_BE_EDITED) || ($resteapayer == $object->total_ttc && empty($object->paye)))
  541. {
  542. $result=$object->set_draft($user, $idwarehouse);
  543. if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
  544. // Define output language
  545. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  546. {
  547. $outputlangs = $langs;
  548. $newlang = '';
  549. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
  550. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  551. if (! empty($newlang)) {
  552. $outputlangs = new Translate("", $conf);
  553. $outputlangs->setDefaultLang($newlang);
  554. $outputlangs->load('products');
  555. }
  556. $model=$object->modelpdf;
  557. $ret = $object->fetch($id); // Reload to get new records
  558. $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
  559. }
  560. }
  561. }
  562. }
  563. }
  564. // Classify "paid"
  565. else if ($action == 'confirm_paid' && $confirm == 'yes' && $user->rights->facture->paiement)
  566. {
  567. $object->fetch($id);
  568. $result = $object->set_paid($user);
  569. if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
  570. } // Classif "paid partialy"
  571. else if ($action == 'confirm_paid_partially' && $confirm == 'yes' && $user->rights->facture->paiement)
  572. {
  573. $object->fetch($id);
  574. $close_code = GETPOST("close_code",'none');
  575. $close_note = GETPOST("close_note",'none');
  576. if ($close_code) {
  577. $result = $object->set_paid($user, $close_code, $close_note);
  578. if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
  579. } else {
  580. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Reason")), null, 'errors');
  581. }
  582. } // Classify "abandoned"
  583. else if ($action == 'confirm_canceled' && $confirm == 'yes') {
  584. $object->fetch($id);
  585. $close_code = GETPOST("close_code",'none');
  586. $close_note = GETPOST("close_note",'none');
  587. if ($close_code) {
  588. $result = $object->set_canceled($user, $close_code, $close_note);
  589. if ($result<0) setEventMessages($object->error, $object->errors, 'errors');
  590. } else {
  591. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Reason")), null, 'errors');
  592. }
  593. }
  594. // Convertir en reduc
  595. else if ($action == 'confirm_converttoreduc' && $confirm == 'yes' && $user->rights->facture->creer)
  596. {
  597. $object->fetch($id);
  598. $object->fetch_thirdparty();
  599. //$object->fetch_lines(); // Already done into fetch
  600. // Check if there is already a discount (protection to avoid duplicate creation when resubmit post)
  601. $discountcheck=new DiscountAbsolute($db);
  602. $result=$discountcheck->fetch(0,$object->id);
  603. $canconvert=0;
  604. if ($object->type == Facture::TYPE_DEPOSIT && empty($discountcheck->id)) $canconvert=1; // we can convert deposit into discount if deposit is payed (completely, partially or not at all) and not already converted (see real condition into condition used to show button converttoreduc)
  605. if (($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_STANDARD) && $object->paye == 0 && empty($discountcheck->id)) $canconvert=1; // we can convert credit note into discount if credit note is not payed back and not already converted and amount of payment is 0 (see real condition into condition used to show button converttoreduc)
  606. if ($canconvert)
  607. {
  608. $db->begin();
  609. $amount_ht = $amount_tva = $amount_ttc = array();
  610. // Loop on each vat rate
  611. $i = 0;
  612. foreach ($object->lines as $line)
  613. {
  614. if ($line->product_type < 9 && $line->total_ht != 0) // Remove lines with product_type greater than or equal to 9
  615. { // no need to create discount if amount is null
  616. $amount_ht[$line->tva_tx] += $line->total_ht;
  617. $amount_tva[$line->tva_tx] += $line->total_tva;
  618. $amount_ttc[$line->tva_tx] += $line->total_ttc;
  619. $multicurrency_amount_ht[$line->tva_tx] += $line->multicurrency_total_ht;
  620. $multicurrency_amount_tva[$line->tva_tx] += $line->multicurrency_total_tva;
  621. $multicurrency_amount_ttc[$line->tva_tx] += $line->multicurrency_total_ttc;
  622. $i ++;
  623. }
  624. }
  625. // Insert one discount by VAT rate category
  626. $discount = new DiscountAbsolute($db);
  627. if ($object->type == Facture::TYPE_CREDIT_NOTE)
  628. $discount->description = '(CREDIT_NOTE)';
  629. elseif ($object->type == Facture::TYPE_DEPOSIT)
  630. $discount->description = '(DEPOSIT)';
  631. elseif ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_SITUATION)
  632. $discount->description = '(EXCESS RECEIVED)';
  633. else {
  634. setEventMessages($langs->trans('CantConvertToReducAnInvoiceOfThisType'), null, 'errors');
  635. }
  636. $discount->fk_soc = $object->socid;
  637. $discount->fk_facture_source = $object->id;
  638. $error = 0;
  639. if ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_SITUATION)
  640. {
  641. // If we're on a standard invoice, we have to get excess received to create a discount in TTC without VAT
  642. // Total payments
  643. $sql = 'SELECT SUM(pf.amount) as total_paiements';
  644. $sql.= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf, '.MAIN_DB_PREFIX.'paiement as p';
  645. $sql.= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
  646. $sql.= ' WHERE pf.fk_facture = '.$object->id;
  647. $sql.= ' AND pf.fk_paiement = p.rowid';
  648. $sql.= ' AND p.entity IN (' . getEntity('facture').')';
  649. $resql = $db->query($sql);
  650. if (! $resql) dol_print_error($db);
  651. $res = $db->fetch_object($resql);
  652. $total_paiements = $res->total_paiements;
  653. // Total credit note and deposit
  654. $total_creditnote_and_deposit = 0;
  655. $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
  656. $sql .= " re.description, re.fk_facture_source";
  657. $sql .= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re";
  658. $sql .= " WHERE fk_facture = " . $object->id;
  659. $resql = $db->query($sql);
  660. if (!empty($resql)) {
  661. while ($obj = $db->fetch_object($resql)) $total_creditnote_and_deposit += $obj->amount_ttc;
  662. } else dol_print_error($db);
  663. $discount->amount_ht = $discount->amount_ttc = $total_paiements + $total_creditnote_and_deposit - $object->total_ttc;
  664. $discount->amount_tva = 0;
  665. $discount->tva_tx = 0;
  666. $result = $discount->create($user);
  667. if ($result < 0)
  668. {
  669. $error++;
  670. }
  671. }
  672. if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT)
  673. {
  674. foreach ($amount_ht as $tva_tx => $xxx)
  675. {
  676. $discount->amount_ht = abs($amount_ht[$tva_tx]);
  677. $discount->amount_tva = abs($amount_tva[$tva_tx]);
  678. $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
  679. $discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$tva_tx]);
  680. $discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$tva_tx]);
  681. $discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
  682. $discount->tva_tx = abs($tva_tx);
  683. $result = $discount->create($user);
  684. if ($result < 0)
  685. {
  686. $error++;
  687. break;
  688. }
  689. }
  690. }
  691. if (empty($error))
  692. {
  693. if($object->type != Facture::TYPE_DEPOSIT) {
  694. // Classe facture
  695. $result = $object->set_paid($user);
  696. if ($result >= 0)
  697. {
  698. $db->commit();
  699. }
  700. else
  701. {
  702. setEventMessages($object->error, $object->errors, 'errors');
  703. $db->rollback();
  704. }
  705. } else {
  706. $db->commit();
  707. }
  708. }
  709. else
  710. {
  711. setEventMessages($discount->error, $discount->errors, 'errors');
  712. $db->rollback();
  713. }
  714. }
  715. }
  716. // Delete payment
  717. elseif ($action == 'confirm_delete_paiement' && $confirm == 'yes' && $user->rights->facture->creer)
  718. {
  719. $object->fetch($id);
  720. if ($object->statut == Facture::STATUS_VALIDATED && $object->paye == 0)
  721. {
  722. $paiement = new Paiement($db);
  723. $result=$paiement->fetch(GETPOST('paiement_id'));
  724. if ($result > 0) {
  725. $result=$paiement->delete(); // If fetch ok and found
  726. header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
  727. }
  728. if ($result < 0) {
  729. setEventMessages($paiement->error, $paiement->errors, 'errors');
  730. }
  731. }
  732. }
  733. /*
  734. * Insert new invoice in database
  735. */
  736. else if ($action == 'add' && $user->rights->facture->creer)
  737. {
  738. if ($socid > 0) $object->socid = GETPOST('socid', 'int');
  739. $db->begin();
  740. $error = 0;
  741. // Fill array 'array_options' with data from add form
  742. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  743. $ret = $extrafields->setOptionalsFromPost($extralabels, $object);
  744. if ($ret < 0) $error++;
  745. // Replacement invoice
  746. if ($_POST['type'] == Facture::TYPE_REPLACEMENT)
  747. {
  748. $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  749. if (empty($dateinvoice))
  750. {
  751. $error++;
  752. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
  753. }
  754. if (! ($_POST['fac_replacement'] > 0)) {
  755. $error++;
  756. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("ReplaceInvoice")), null, 'errors');
  757. }
  758. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  759. if (! $error) {
  760. // This is a replacement invoice
  761. $result = $object->fetch($_POST['fac_replacement']);
  762. $object->fetch_thirdparty();
  763. $object->date = $dateinvoice;
  764. $object->date_pointoftax = $date_pointoftax;
  765. $object->note_public = trim(GETPOST('note_public','none'));
  766. // We do not copy the private note
  767. $object->ref_client = $_POST['ref_client'];
  768. $object->ref_int = $_POST['ref_int'];
  769. $object->modelpdf = $_POST['model'];
  770. $object->fk_project = $_POST['projectid'];
  771. $object->cond_reglement_id = $_POST['cond_reglement_id'];
  772. $object->mode_reglement_id = $_POST['mode_reglement_id'];
  773. $object->fk_account = GETPOST('fk_account', 'int');
  774. $object->remise_absolue = $_POST['remise_absolue'];
  775. $object->remise_percent = $_POST['remise_percent'];
  776. $object->fk_incoterms = GETPOST('incoterm_id', 'int');
  777. $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
  778. $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
  779. $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
  780. // Proprietes particulieres a facture de remplacement
  781. $object->fk_facture_source = $_POST['fac_replacement'];
  782. $object->type = Facture::TYPE_REPLACEMENT;
  783. $id = $object->createFromCurrent($user);
  784. if ($id <= 0) {
  785. setEventMessages($object->error, $object->errors, 'errors');
  786. }
  787. }
  788. }
  789. // Credit note invoice
  790. if ($_POST['type'] == Facture::TYPE_CREDIT_NOTE)
  791. {
  792. $sourceinvoice = GETPOST('fac_avoir');
  793. if (! ($sourceinvoice > 0) && empty($conf->global->INVOICE_CREDIT_NOTE_STANDALONE))
  794. {
  795. $error++;
  796. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("CorrectInvoice")), null, 'errors');
  797. }
  798. $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  799. if (empty($dateinvoice))
  800. {
  801. $error++;
  802. setEventMessages($langs->trans("ErrorFieldRequired", $langs->trans("Date")), null, 'errors');
  803. }
  804. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  805. if (! $error)
  806. {
  807. $object->socid = GETPOST('socid','int');
  808. $object->number = $_POST['facnumber'];
  809. $object->date = $dateinvoice;
  810. $object->date_pointoftax = $date_pointoftax;
  811. $object->note_public = trim(GETPOST('note_public','none'));
  812. // We do not copy the private note
  813. $object->ref_client = $_POST['ref_client'];
  814. $object->ref_int = $_POST['ref_int'];
  815. $object->modelpdf = $_POST['model'];
  816. $object->fk_project = $_POST['projectid'];
  817. $object->cond_reglement_id = 0;
  818. $object->mode_reglement_id = $_POST['mode_reglement_id'];
  819. $object->fk_account = GETPOST('fk_account', 'int');
  820. $object->remise_absolue = $_POST['remise_absolue'];
  821. $object->remise_percent = $_POST['remise_percent'];
  822. $object->fk_incoterms = GETPOST('incoterm_id', 'int');
  823. $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
  824. $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
  825. $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
  826. // Proprietes particulieres a facture avoir
  827. $object->fk_facture_source = $sourceinvoice > 0 ? $sourceinvoice : '';
  828. $object->type = Facture::TYPE_CREDIT_NOTE;
  829. $facture_source = new Facture($db); // fetch origin object
  830. if ($facture_source->fetch($object->fk_facture_source)>0)
  831. {
  832. if ($facture_source->type == Facture::TYPE_SITUATION)
  833. {
  834. $object->situation_counter = $facture_source->situation_counter;
  835. $object->situation_cycle_ref = $facture_source->situation_cycle_ref;
  836. $facture_source->fetchPreviousNextSituationInvoice();
  837. }
  838. }
  839. $id = $object->create($user);
  840. if (GETPOST('invoiceAvoirWithLines', 'int')==1 && $id>0)
  841. {
  842. if (!empty($facture_source->lines))
  843. {
  844. $fk_parent_line = 0;
  845. foreach($facture_source->lines as $line)
  846. {
  847. // Extrafields
  848. if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($line, 'fetch_optionals')) {
  849. // load extrafields
  850. $line->fetch_optionals();
  851. }
  852. // Reset fk_parent_line for no child products and special product
  853. if (($line->product_type != 9 && empty($line->fk_parent_line)) || $line->product_type == 9) {
  854. $fk_parent_line = 0;
  855. }
  856. if($facture_source->type == Facture::TYPE_SITUATION)
  857. {
  858. $source_fk_prev_id = $line->fk_prev_id; // temporary storing situation invoice fk_prev_id
  859. $line->fk_prev_id = $line->id; // Credit note line need to be linked to the situation invoice it is create from
  860. if(!empty($facture_source->tab_previous_situation_invoice))
  861. {
  862. // search the last invoice in cycle
  863. $lineIndex = count($facture_source->tab_previous_situation_invoice) - 1;
  864. $searchPreviousInvoice = true;
  865. while( $searchPreviousInvoice )
  866. {
  867. if($facture_source->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1)
  868. {
  869. $searchPreviousInvoice=false; // find, exit;
  870. break;
  871. }
  872. else
  873. {
  874. $lineIndex--; // go to previous invoice in cycle
  875. }
  876. }
  877. $maxPrevSituationPercent = 0;
  878. foreach($facture_source->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine)
  879. {
  880. if($prevLine->id == $source_fk_prev_id)
  881. {
  882. $maxPrevSituationPercent = max($maxPrevSituationPercent,$prevLine->situation_percent);
  883. //$line->subprice = $line->subprice - $prevLine->subprice;
  884. $line->total_ht = $line->total_ht - $prevLine->total_ht;
  885. $line->total_tva = $line->total_tva - $prevLine->total_tva;
  886. $line->total_ttc = $line->total_ttc - $prevLine->total_ttc;
  887. $line->total_localtax1 = $line->total_localtax1 - $prevLine->total_localtax1;
  888. $line->total_localtax2 = $line->total_localtax2 - $prevLine->total_localtax2;
  889. $line->multicurrency_subprice = $line->multicurrency_subprice - $prevLine->multicurrency_subprice;
  890. $line->multicurrency_total_ht = $line->multicurrency_total_ht - $prevLine->multicurrency_total_ht;
  891. $line->multicurrency_total_tva = $line->multicurrency_total_tva - $prevLine->multicurrency_total_tva;
  892. $line->multicurrency_total_ttc = $line->multicurrency_total_ttc - $prevLine->multicurrency_total_ttc;
  893. }
  894. }
  895. // prorata
  896. $line->situation_percent = $maxPrevSituationPercent - $line->situation_percent;
  897. }
  898. }
  899. $line->fk_facture = $object->id;
  900. $line->fk_parent_line = $fk_parent_line;
  901. $line->subprice = -$line->subprice; // invert price for object
  902. $line->pa_ht = $line->pa_ht; // we choosed to have buy/cost price always positive, so no revert of sign here
  903. $line->total_ht = -$line->total_ht;
  904. $line->total_tva = -$line->total_tva;
  905. $line->total_ttc = -$line->total_ttc;
  906. $line->total_localtax1 = -$line->total_localtax1;
  907. $line->total_localtax2 = -$line->total_localtax2;
  908. $line->multicurrency_subprice = -$line->multicurrency_subprice;
  909. $line->multicurrency_total_ht = -$line->multicurrency_total_ht;
  910. $line->multicurrency_total_tva = -$line->multicurrency_total_tva;
  911. $line->multicurrency_total_ttc = -$line->multicurrency_total_ttc;
  912. $result = $line->insert(0, 1); // When creating credit note with same lines than source, we must ignore error if discount alreayd linked
  913. $object->lines[] = $line; // insert new line in current object
  914. // Defined the new fk_parent_line
  915. if ($result > 0 && $line->product_type == 9) {
  916. $fk_parent_line = $result;
  917. }
  918. }
  919. $object->update_price(1);
  920. }
  921. }
  922. if(GETPOST('invoiceAvoirWithPaymentRestAmount', 'int')==1 && $id>0)
  923. {
  924. if ($facture_source->fetch($object->fk_facture_source)>0)
  925. {
  926. $totalpaye = $facture_source->getSommePaiement();
  927. $totalcreditnotes = $facture_source->getSumCreditNotesUsed();
  928. $totaldeposits = $facture_source->getSumDepositsUsed();
  929. $remain_to_pay = abs($facture_source->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits);
  930. $object->addline($langs->trans('invoiceAvoirLineWithPaymentRestAmount'),$remain_to_pay,1,0,0,0,0,0,'','','TTC');
  931. }
  932. }
  933. // Add link between credit note and origin
  934. if(! empty($object->fk_facture_source)) {
  935. $facture_source->fetch($object->fk_facture_source);
  936. $facture_source->fetchObjectLinked();
  937. if(! empty($facture_source->linkedObjectsIds)) {
  938. foreach($facture_source->linkedObjectsIds as $sourcetype => $TIds) {
  939. $object->add_object_linked($sourcetype, current($TIds));
  940. }
  941. }
  942. }
  943. }
  944. }
  945. // Standard invoice or Deposit invoice, created from a Predefined template invoice
  946. if (($_POST['type'] == Facture::TYPE_STANDARD || $_POST['type'] == Facture::TYPE_DEPOSIT) && GETPOST('fac_rec') > 0)
  947. {
  948. $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  949. if (empty($dateinvoice))
  950. {
  951. $error++;
  952. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
  953. }
  954. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  955. if (! $error)
  956. {
  957. $object->socid = GETPOST('socid','int');
  958. $object->type = $_POST['type'];
  959. $object->number = $_POST['facnumber'];
  960. $object->date = $dateinvoice;
  961. $object->date_pointoftax = $date_pointoftax;
  962. $object->note_public = trim(GETPOST('note_public','none'));
  963. $object->note_private = trim(GETPOST('note_private','none'));
  964. $object->ref_client = $_POST['ref_client'];
  965. $object->ref_int = $_POST['ref_int'];
  966. $object->modelpdf = $_POST['model'];
  967. $object->fk_project = $_POST['projectid'];
  968. $object->cond_reglement_id = ($_POST['type'] == 3?1:$_POST['cond_reglement_id']);
  969. $object->mode_reglement_id = $_POST['mode_reglement_id'];
  970. $object->fk_account = GETPOST('fk_account', 'int');
  971. $object->amount = $_POST['amount'];
  972. $object->remise_absolue = $_POST['remise_absolue'];
  973. $object->remise_percent = $_POST['remise_percent'];
  974. $object->fk_incoterms = GETPOST('incoterm_id', 'int');
  975. $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
  976. $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
  977. $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
  978. // Source facture
  979. $object->fac_rec = GETPOST('fac_rec', 'int');
  980. $id = $object->create($user); // This include recopy of links from recurring invoice and invoice lines
  981. }
  982. }
  983. // Standard or deposit or proforma invoice, not from a Predefined template invoice
  984. if (($_POST['type'] == Facture::TYPE_STANDARD || $_POST['type'] == Facture::TYPE_DEPOSIT || $_POST['type'] == Facture::TYPE_PROFORMA || ($_POST['type'] == Facture::TYPE_SITUATION && empty($_POST['situations']))) && GETPOST('fac_rec') <= 0)
  985. {
  986. if (GETPOST('socid', 'int') < 1)
  987. {
  988. $error++;
  989. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Customer")), null, 'errors');
  990. }
  991. $dateinvoice = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  992. if (empty($dateinvoice))
  993. {
  994. $error++;
  995. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Date")), null, 'errors');
  996. }
  997. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  998. if (! $error)
  999. {
  1000. // Si facture standard
  1001. $object->socid = GETPOST('socid','int');
  1002. $object->type = GETPOST('type');
  1003. $object->number = $_POST['facnumber'];
  1004. $object->date = $dateinvoice;
  1005. $object->date_pointoftax = $date_pointoftax;
  1006. $object->note_public = trim(GETPOST('note_public','none'));
  1007. $object->note_private = trim(GETPOST('note_private','none'));
  1008. $object->ref_client = $_POST['ref_client'];
  1009. $object->ref_int = $_POST['ref_int'];
  1010. $object->modelpdf = $_POST['model'];
  1011. $object->fk_project = $_POST['projectid'];
  1012. $object->cond_reglement_id = ($_POST['type'] == 3?1:$_POST['cond_reglement_id']);
  1013. $object->mode_reglement_id = $_POST['mode_reglement_id'];
  1014. $object->fk_account = GETPOST('fk_account', 'int');
  1015. $object->amount = $_POST['amount'];
  1016. $object->remise_absolue = $_POST['remise_absolue'];
  1017. $object->remise_percent = $_POST['remise_percent'];
  1018. $object->fk_incoterms = GETPOST('incoterm_id', 'int');
  1019. $object->location_incoterms = GETPOST('location_incoterms', 'alpha');
  1020. $object->multicurrency_code = GETPOST('multicurrency_code', 'alpha');
  1021. $object->multicurrency_tx = GETPOST('originmulticurrency_tx', 'int');
  1022. if (GETPOST('type') == Facture::TYPE_SITUATION)
  1023. {
  1024. $object->situation_counter = 1;
  1025. $object->situation_final = 0;
  1026. $object->situation_cycle_ref = $object->newCycle();
  1027. }
  1028. $object->fetch_thirdparty();
  1029. // If creation from another object of another module (Example: origin=propal, originid=1)
  1030. if (! empty($origin) && ! empty($originid))
  1031. {
  1032. // Parse element/subelement (ex: project_task)
  1033. $element = $subelement = $origin;
  1034. if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
  1035. $element = $regs [1];
  1036. $subelement = $regs [2];
  1037. }
  1038. // For compatibility
  1039. if ($element == 'order') {
  1040. $element = $subelement = 'commande';
  1041. }
  1042. if ($element == 'propal') {
  1043. $element = 'comm/propal';
  1044. $subelement = 'propal';
  1045. }
  1046. if ($element == 'contract') {
  1047. $element = $subelement = 'contrat';
  1048. }
  1049. if ($element == 'inter') {
  1050. $element = $subelement = 'ficheinter';
  1051. }
  1052. if ($element == 'shipping') {
  1053. $element = $subelement = 'expedition';
  1054. }
  1055. $object->origin = $origin;
  1056. $object->origin_id = $originid;
  1057. // Possibility to add external linked objects with hooks
  1058. $object->linked_objects[$object->origin] = $object->origin_id;
  1059. // link with order if it is a shipping invoice
  1060. if ($object->origin == 'shipping')
  1061. {
  1062. require_once DOL_DOCUMENT_ROOT . '/expedition/class/expedition.class.php';
  1063. $exp = new Expedition($db);
  1064. $exp->fetch($object->origin_id);
  1065. $exp->fetchObjectLinked();
  1066. if (is_array($exp->linkedObjectsIds['commande']) && count($exp->linkedObjectsIds['commande']) > 0) {
  1067. foreach ($exp->linkedObjectsIds['commande'] as $key => $value){
  1068. $object->linked_objects['commande'] = $value;
  1069. }
  1070. }
  1071. }
  1072. if (is_array($_POST['other_linked_objects']) && ! empty($_POST['other_linked_objects']))
  1073. {
  1074. $object->linked_objects = array_merge($object->linked_objects, $_POST['other_linked_objects']);
  1075. }
  1076. $id = $object->create($user); // This include class to add_object_linked() and add add_contact()
  1077. if ($id > 0)
  1078. {
  1079. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  1080. $classname = ucfirst($subelement);
  1081. $srcobject = new $classname($db);
  1082. dol_syslog("Try to find source object origin=" . $object->origin . " originid=" . $object->origin_id . " to add lines or deposit lines");
  1083. $result = $srcobject->fetch($object->origin_id);
  1084. // If deposit invoice
  1085. if ($_POST['type'] == Facture::TYPE_DEPOSIT)
  1086. {
  1087. $typeamount = GETPOST('typedeposit', 'alpha');
  1088. $valuedeposit = GETPOST('valuedeposit', 'int');
  1089. $amountdeposit = array();
  1090. if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA))
  1091. {
  1092. if ($typeamount == 'amount') $amount = $valuedeposit;
  1093. else $amount = $srcobject->total_ttc * ($valuedeposit / 100);
  1094. $TTotalByTva = array();
  1095. foreach ($srcobject->lines as &$line)
  1096. {
  1097. if(! empty($line->special_code)) continue;
  1098. $TTotalByTva[$line->tva_tx] += $line->total_ttc ;
  1099. }
  1100. $amount_to_diff = 0;
  1101. foreach ($TTotalByTva as $tva => &$total)
  1102. {
  1103. $coef = $total / $srcobject->total_ttc; // Calc coef
  1104. $am = $amount * $coef;
  1105. $amount_ttc_diff += $am;
  1106. $amountdeposit[$tva] += $am / (1 + $tva / 100); // Convert into HT for the addline
  1107. }
  1108. }
  1109. else
  1110. {
  1111. if ($typeamount == 'amount')
  1112. {
  1113. $amountdeposit[0] = $valuedeposit;
  1114. }
  1115. else
  1116. {
  1117. if ($result > 0)
  1118. {
  1119. $totalamount = 0;
  1120. $lines = $srcobject->lines;
  1121. $numlines=count($lines);
  1122. for ($i=0; $i<$numlines; $i++)
  1123. {
  1124. $qualified=1;
  1125. if (empty($lines[$i]->qty)) $qualified=0; // We discard qty=0, it is an option
  1126. if (! empty($lines[$i]->special_code)) $qualified=0; // We discard special_code (frais port, ecotaxe, option, ...)
  1127. if ($qualified) $totalamount += $lines[$i]->total_ht; // Fixme : is it not for the customer ? Shouldn't we take total_ttc ?
  1128. }
  1129. if ($totalamount != 0) {
  1130. if ($numlines > 0) $numlines = $numlines-1;
  1131. $tva_tx = $lines[$numlines]->tva_tx;
  1132. if (! empty($lines[$numlines]->vat_src_code) && ! preg_match('/\(/', $tva_tx)) $tva_tx .= ' ('.$lines[$numlines]->vat_src_code.')';
  1133. $amountdeposit[$tva_tx] = ($totalamount * $valuedeposit) / 100;
  1134. } else {
  1135. $amountdeposit[0] = 0;
  1136. }
  1137. } else {
  1138. setEventMessages($srcobject->error, $srcobject->errors, 'errors');
  1139. $error++;
  1140. }
  1141. }
  1142. $amount_ttc_diff = $amountdeposit[0];
  1143. }
  1144. foreach ($amountdeposit as $tva => $amount)
  1145. {
  1146. $arraylist = array('amount' => 'FixAmount','variable' => 'VarAmount');
  1147. $descline = $langs->trans('Deposit');
  1148. //$descline.= ' - '.$langs->trans($arraylist[$typeamount]);
  1149. if ($typeamount=='amount') {
  1150. $descline.= ' ('. price($valuedeposit, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)).')';
  1151. } elseif ($typeamount=='variable') {
  1152. $descline.= ' ('. $valuedeposit.'%)';
  1153. }
  1154. $descline.= ' - '.$srcobject->ref;
  1155. $result = $object->addline(
  1156. $descline,
  1157. $amount, // subprice
  1158. 1, // quantity
  1159. $tva, // vat rate
  1160. 0, // localtax1_tx
  1161. 0, // localtax2_tx
  1162. (empty($conf->global->INVOICE_PRODUCTID_DEPOSIT)?0:$conf->global->INVOICE_PRODUCTID_DEPOSIT), // fk_product
  1163. 0, // remise_percent
  1164. 0, // date_start
  1165. 0, // date_end
  1166. 0,
  1167. $lines[$i]->info_bits, // info_bits
  1168. 0,
  1169. 'HT',
  1170. 0,
  1171. 0, // product_type
  1172. 1,
  1173. $lines[$i]->special_code,
  1174. $object->origin,
  1175. 0,
  1176. 0,
  1177. 0,
  1178. 0
  1179. //,$langs->trans('Deposit') //Deprecated
  1180. );
  1181. }
  1182. $diff = $object->total_ttc - $amount_ttc_diff;
  1183. if (!empty($conf->global->MAIN_DEPOSIT_MULTI_TVA) && $diff != 0)
  1184. {
  1185. $object->fetch_lines();
  1186. $subprice_diff = $object->lines[0]->subprice - $diff / (1 + $object->lines[0]->tva_tx / 100);
  1187. $object->updateline($object->lines[0]->id, $object->lines[0]->desc, $subprice_diff, $object->lines[0]->qty, $object->lines[0]->remise_percent, $object->lines[0]->date_start, $object->lines[0]->date_end, $object->lines[0]->tva_tx, 0, 0, 'HT', $object->lines[0]->info_bits, $object->lines[0]->product_type, 0, 0, 0, $object->lines[0]->pa_ht, $object->lines[0]->label, 0, array(), 100);
  1188. }
  1189. }
  1190. else
  1191. {
  1192. if ($result > 0)
  1193. {
  1194. $lines = $srcobject->lines;
  1195. if (empty($lines) && method_exists($srcobject, 'fetch_lines'))
  1196. {
  1197. $srcobject->fetch_lines();
  1198. $lines = $srcobject->lines;
  1199. }
  1200. $fk_parent_line=0;
  1201. $num=count($lines);
  1202. for ($i=0;$i<$num;$i++)
  1203. {
  1204. // Don't add lines with qty 0 when coming from a shipment including all order lines
  1205. if($srcobject->element == 'shipping' && $conf->global->SHIPMENT_GETS_ALL_ORDER_PRODUCTS && $lines[$i]->qty == 0) continue;
  1206. // Don't add closed lines when coming from a contract
  1207. if($srcobject->element == 'contrat' && $lines[$i]->statut == 5) continue;
  1208. $label=(! empty($lines[$i]->label)?$lines[$i]->label:'');
  1209. $desc=(! empty($lines[$i]->desc)?$lines[$i]->desc:$lines[$i]->libelle);
  1210. if ($object->situation_counter == 1) $lines[$i]->situation_percent = 0;
  1211. if ($lines[$i]->subprice < 0)
  1212. {
  1213. // Negative line, we create a discount line
  1214. $discount = new DiscountAbsolute($db);
  1215. $discount->fk_soc = $object->socid;
  1216. $discount->amount_ht = abs($lines[$i]->total_ht);
  1217. $discount->amount_tva = abs($lines[$i]->total_tva);
  1218. $discount->amount_ttc = abs($lines[$i]->total_ttc);
  1219. $discount->tva_tx = $lines[$i]->tva_tx;
  1220. $discount->fk_user = $user->id;
  1221. $discount->description = $desc;
  1222. $discountid = $discount->create($user);
  1223. if ($discountid > 0) {
  1224. $result = $object->insert_discount($discountid); // This include link_to_invoice
  1225. } else {
  1226. setEventMessages($discount->error, $discount->errors, 'errors');
  1227. $error++;
  1228. break;
  1229. }
  1230. } else {
  1231. // Positive line
  1232. $product_type = ($lines[$i]->product_type ? $lines[$i]->product_type : 0);
  1233. // Date start
  1234. $date_start = false;
  1235. if ($lines[$i]->date_debut_prevue)
  1236. $date_start = $lines[$i]->date_debut_prevue;
  1237. if ($lines[$i]->date_debut_reel)
  1238. $date_start = $lines[$i]->date_debut_reel;
  1239. if ($lines[$i]->date_start)
  1240. $date_start = $lines[$i]->date_start;
  1241. // Date end
  1242. $date_end = false;
  1243. if ($lines[$i]->date_fin_prevue)
  1244. $date_end = $lines[$i]->date_fin_prevue;
  1245. if ($lines[$i]->date_fin_reel)
  1246. $date_end = $lines[$i]->date_fin_reel;
  1247. if ($lines[$i]->date_end)
  1248. $date_end = $lines[$i]->date_end;
  1249. // Reset fk_parent_line for no child products and special product
  1250. if (($lines[$i]->product_type != 9 && empty($lines[$i]->fk_parent_line)) || $lines[$i]->product_type == 9) {
  1251. $fk_parent_line = 0;
  1252. }
  1253. // Extrafields
  1254. if (empty($conf->global->MAIN_EXTRAFIELDS_DISABLED) && method_exists($lines[$i], 'fetch_optionals')) {
  1255. $lines[$i]->fetch_optionals($lines[$i]->rowid);
  1256. $array_options = $lines[$i]->array_options;
  1257. }
  1258. $tva_tx = $lines[$i]->tva_tx;
  1259. if (! empty($lines[$i]->vat_src_code) && ! preg_match('/\(/', $tva_tx)) $tva_tx .= ' ('.$lines[$i]->vat_src_code.')';
  1260. // View third's localtaxes for NOW and do not use value from origin.
  1261. // TODO Is this really what we want ? Yes if source if template invoice but what if proposal or order ?
  1262. $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty);
  1263. $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty);
  1264. $result = $object->addline(
  1265. $desc, $lines[$i]->subprice, $lines[$i]->qty, $tva_tx, $localtax1_tx, $localtax2_tx, $lines[$i]->fk_product,
  1266. $lines[$i]->remise_percent, $date_start, $date_end, 0, $lines[$i]->info_bits, $lines[$i]->fk_remise_except,
  1267. 'HT', 0, $product_type, $lines[$i]->rang, $lines[$i]->special_code, $object->origin, $lines[$i]->rowid,
  1268. $fk_parent_line, $lines[$i]->fk_fournprice, $lines[$i]->pa_ht, $label, $array_options,
  1269. $lines[$i]->situation_percent, $lines[$i]->fk_prev_id, $lines[$i]->fk_unit
  1270. );
  1271. if ($result > 0) {
  1272. $lineid = $result;
  1273. } else {
  1274. $lineid = 0;
  1275. $error++;
  1276. break;
  1277. }
  1278. // Defined the new fk_parent_line
  1279. if ($result > 0 && $lines[$i]->product_type == 9) {
  1280. $fk_parent_line = $result;
  1281. }
  1282. }
  1283. }
  1284. } else {
  1285. setEventMessages($srcobject->error, $srcobject->errors, 'errors');
  1286. $error++;
  1287. }
  1288. }
  1289. // Now we create same links to contact than the ones found on origin object
  1290. /* Useless, already into the create
  1291. if (! empty($conf->global->MAIN_PROPAGATE_CONTACTS_FROM_ORIGIN))
  1292. {
  1293. $originforcontact = $object->origin;
  1294. $originidforcontact = $object->origin_id;
  1295. if ($originforcontact == 'shipping') // shipment and order share the same contacts. If creating from shipment we take data of order
  1296. {
  1297. $originforcontact=$srcobject->origin;
  1298. $originidforcontact=$srcobject->origin_id;
  1299. }
  1300. $sqlcontact = "SELECT code, fk_socpeople FROM ".MAIN_DB_PREFIX."element_contact as ec, ".MAIN_DB_PREFIX."c_type_contact as ctc";
  1301. $sqlcontact.= " WHERE element_id = ".$originidforcontact." AND ec.fk_c_type_contact = ctc.rowid AND ctc.element = '".$originforcontact."'";
  1302. $resqlcontact = $db->query($sqlcontact);
  1303. if ($resqlcontact)
  1304. {
  1305. while($objcontact = $db->fetch_object($resqlcontact))
  1306. {
  1307. //print $objcontact->code.'-'.$objcontact->fk_socpeople."\n";
  1308. $object->add_contact($objcontact->fk_socpeople, $objcontact->code);
  1309. }
  1310. }
  1311. else dol_print_error($resqlcontact);
  1312. }*/
  1313. // Hooks
  1314. $parameters = array('objFrom' => $srcobject);
  1315. $reshook = $hookmanager->executeHooks('createFrom', $parameters, $object, $action); // Note that $action and $object may have been
  1316. // modified by hook
  1317. if ($reshook < 0)
  1318. {
  1319. setEventMessages($hookmanager->error, $hookmanager->errors, 'errors');
  1320. $error++;
  1321. }
  1322. } else {
  1323. setEventMessages($object->error, $object->errors, 'errors');
  1324. $error++;
  1325. }
  1326. }
  1327. else
  1328. { // If some invoice's lines coming from page
  1329. $id = $object->create($user);
  1330. for ($i = 1; $i <= $NBLINES; $i ++) {
  1331. if ($_POST['idprod' . $i]) {
  1332. $product = new Product($db);
  1333. $product->fetch($_POST['idprod' . $i]);
  1334. $startday = dol_mktime(12, 0, 0, $_POST['date_start' . $i . 'month'], $_POST['date_start' . $i . 'day'], $_POST['date_start' . $i . 'year']);
  1335. $endday = dol_mktime(12, 0, 0, $_POST['date_end' . $i . 'month'], $_POST['date_end' . $i . 'day'], $_POST['date_end' . $i . 'year']);
  1336. $result = $object->addline($product->description, $product->price, $_POST['qty' . $i], $product->tva_tx, $product->localtax1_tx, $product->localtax2_tx, $_POST['idprod' . $i], $_POST['remise_percent' . $i], $startday, $endday, 0, 0, '', $product->price_base_type, $product->price_ttc, $product->type, -1, 0, '', 0, 0, null, 0, '', 0, 100, '', $product->fk_unit);
  1337. }
  1338. }
  1339. }
  1340. }
  1341. }
  1342. // Situation invoices
  1343. if (GETPOST('type') == Facture::TYPE_SITUATION && (!empty($_POST['situations'])))
  1344. {
  1345. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  1346. if (empty($datefacture)) {
  1347. $error++;
  1348. $mesg = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("Date")) . '</div>';
  1349. }
  1350. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  1351. if (!($_POST['situations'] > 0)) {
  1352. $error++;
  1353. $mesg = '<div class="error">' . $langs->trans("ErrorFieldRequired", $langs->trans("InvoiceSituation")) . '</div>';
  1354. }
  1355. if (!$error) {
  1356. $result = $object->fetch($_POST['situations']);
  1357. $object->fk_facture_source = $_POST['situations'];
  1358. $object->type = Facture::TYPE_SITUATION;
  1359. if (!empty($origin) && !empty($originid))
  1360. {
  1361. $object->origin = $origin;
  1362. $object->origin_id = $originid;
  1363. foreach ($object->lines as $i => &$line)
  1364. {
  1365. $line->origin = $object->origin;
  1366. $line->origin_id = $line->id;
  1367. $line->fk_prev_id = $line->id;
  1368. $line->fetch_optionals($line->id);
  1369. $line->situation_percent = $line->get_prev_progress($object->id); // get good progress including credit note
  1370. // Si fk_remise_except defini on vérifie si la réduction à déjà été appliquée
  1371. if ($line->fk_remise_except)
  1372. {
  1373. $discount=new DiscountAbsolute($line->db);
  1374. $result=$discount->fetch($line->fk_remise_except);
  1375. if ($result > 0)
  1376. {
  1377. // Check if discount not already affected to another invoice
  1378. if ($discount->fk_facture_line > 0)
  1379. {
  1380. $line->fk_remise_except = 0;
  1381. }
  1382. }
  1383. }
  1384. }
  1385. }
  1386. $object->fetch_thirdparty();
  1387. $object->date = $datefacture;
  1388. $object->date_pointoftax = $date_pointoftax;
  1389. $object->note_public = trim(GETPOST('note_public','none'));
  1390. $object->note = trim(GETPOST('note','none'));
  1391. $object->ref_client = GETPOST('ref_client','alpha');
  1392. $object->ref_int = GETPOST('ref_int','alpha');
  1393. $object->modelpdf = GETPOST('model','alpha');
  1394. $object->fk_project = GETPOST('projectid','int');
  1395. $object->cond_reglement_id = GETPOST('cond_reglement_id','int');
  1396. $object->mode_reglement_id = GETPOST('mode_reglement_id','int');
  1397. $object->remise_absolue = GETPOST('remise_absolue','int');
  1398. $object->remise_percent = GETPOST('remise_percent','int');
  1399. // Proprietes particulieres a facture de remplacement
  1400. $object->situation_counter = $object->situation_counter + 1;
  1401. $id = $object->createFromCurrent($user);
  1402. if ($id <= 0)
  1403. {
  1404. $mesg = $object->error;
  1405. }
  1406. else
  1407. {
  1408. $nextSituationInvoice = new Facture($db);
  1409. $nextSituationInvoice->fetch($id);
  1410. // create extrafields with data from create form
  1411. $extralabels = $extrafields->fetch_name_optionals_label($nextSituationInvoice->table_element);
  1412. $ret = $extrafields->setOptionalsFromPost($extralabels, $nextSituationInvoice);
  1413. if ($ret > 0) {
  1414. $nextSituationInvoice->insertExtraFields();
  1415. }
  1416. }
  1417. }
  1418. }
  1419. // End of object creation, we show it
  1420. if ($id > 0 && ! $error)
  1421. {
  1422. $db->commit();
  1423. // Define output language
  1424. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE) && count($object->lines))
  1425. {
  1426. $outputlangs = $langs;
  1427. $newlang = '';
  1428. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
  1429. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  1430. if (! empty($newlang)) {
  1431. $outputlangs = new Translate("", $conf);
  1432. $outputlangs->setDefaultLang($newlang);
  1433. $outputlangs->load('products');
  1434. }
  1435. $model=$object->modelpdf;
  1436. $ret = $object->fetch($id); // Reload to get new records
  1437. $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
  1438. if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
  1439. }
  1440. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id);
  1441. exit();
  1442. }
  1443. else
  1444. {
  1445. $db->rollback();
  1446. $action = 'create';
  1447. $_GET["origin"] = $_POST["origin"];
  1448. $_GET["originid"] = $_POST["originid"];
  1449. setEventMessages($object->error, $object->errors, 'errors');
  1450. }
  1451. }
  1452. // Add a new line
  1453. else if ($action == 'addline' && $user->rights->facture->creer)
  1454. {
  1455. $langs->load('errors');
  1456. $error = 0;
  1457. // Set if we used free entry or predefined product
  1458. $predef='';
  1459. $product_desc=(GETPOST('dp_desc','none')?GETPOST('dp_desc','none'):'');
  1460. $price_ht = GETPOST('price_ht');
  1461. $price_ht_devise = GETPOST('multicurrency_price_ht');
  1462. $prod_entry_mode = GETPOST('prod_entry_mode','alpha');
  1463. if ($prod_entry_mode == 'free')
  1464. {
  1465. $idprod=0;
  1466. $tva_tx = (GETPOST('tva_tx','alpha') ? GETPOST('tva_tx','alpha') : 0);
  1467. }
  1468. else
  1469. {
  1470. $idprod=GETPOST('idprod', 'int');
  1471. $tva_tx = '';
  1472. }
  1473. $qty = GETPOST('qty' . $predef);
  1474. $remise_percent = GETPOST('remise_percent' . $predef);
  1475. // Extrafields
  1476. $extrafieldsline = new ExtraFields($db);
  1477. $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
  1478. $array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline, $predef);
  1479. // Unset extrafield
  1480. if (is_array($extralabelsline)) {
  1481. // Get extra fields
  1482. foreach ($extralabelsline as $key => $value) {
  1483. unset($_POST["options_" . $key . $predef]);
  1484. }
  1485. }
  1486. if (empty($idprod) && ($price_ht < 0) && ($qty < 0)) {
  1487. setEventMessages($langs->trans('ErrorBothFieldCantBeNegative', $langs->transnoentitiesnoconv('UnitPriceHT'), $langs->transnoentitiesnoconv('Qty')), null, 'errors');
  1488. $error++;
  1489. }
  1490. if (!$prod_entry_mode)
  1491. {
  1492. if (GETPOST('type') < 0 && ! GETPOST('search_idprod'))
  1493. {
  1494. setEventMessages($langs->trans('ErrorChooseBetweenFreeEntryOrPredefinedProduct'), null, 'errors');
  1495. $error++;
  1496. }
  1497. }
  1498. if ($prod_entry_mode == 'free' && empty($idprod) && GETPOST('type') < 0) {
  1499. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Type')), null, 'errors');
  1500. $error++;
  1501. }
  1502. if (($prod_entry_mode == 'free' && empty($idprod) && (($price_ht < 0 && empty($conf->global->FACTURE_ENABLE_NEGATIVE_LINES)) || $price_ht == '') && $price_ht_devise == '') && $object->type != Facture::TYPE_CREDIT_NOTE) // Unit price can be 0 but not ''
  1503. {
  1504. if ($price_ht < 0 && empty($conf->global->FACTURE_ENABLE_NEGATIVE_LINES))
  1505. {
  1506. $langs->load("errors");
  1507. setEventMessages($langs->trans("ErrorFieldCantBeNegativeOnInvoice", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
  1508. $error++;
  1509. }
  1510. else
  1511. {
  1512. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
  1513. $error++;
  1514. }
  1515. }
  1516. if ($qty == '') {
  1517. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Qty')), null, 'errors');
  1518. $error++;
  1519. }
  1520. if ($prod_entry_mode == 'free' && empty($idprod) && empty($product_desc)) {
  1521. setEventMessages($langs->trans('ErrorFieldRequired', $langs->transnoentitiesnoconv('Description')), null, 'errors');
  1522. $error++;
  1523. }
  1524. if ($qty < 0) {
  1525. $langs->load("errors");
  1526. setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
  1527. $error++;
  1528. }
  1529. if (!$error && !empty($conf->variants->enabled) && $prod_entry_mode != 'free') {
  1530. if ($combinations = GETPOST('combinations', 'array')) {
  1531. //Check if there is a product with the given combination
  1532. $prodcomb = new ProductCombination($db);
  1533. if ($res = $prodcomb->fetchByProductCombination2ValuePairs($idprod, $combinations)) {
  1534. $idprod = $res->fk_product_child;
  1535. } else {
  1536. setEventMessage($langs->trans('ErrorProductCombinationNotFound'), 'errors');
  1537. $error++;
  1538. }
  1539. }
  1540. }
  1541. if (! $error && ($qty >= 0) && (! empty($product_desc) || ! empty($idprod))) {
  1542. $ret = $object->fetch($id);
  1543. if ($ret < 0) {
  1544. dol_print_error($db, $object->error);
  1545. exit();
  1546. }
  1547. $ret = $object->fetch_thirdparty();
  1548. // Clean parameters
  1549. $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'));
  1550. $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'));
  1551. $price_base_type = (GETPOST('price_base_type', 'alpha') ? GETPOST('price_base_type', 'alpha') : 'HT');
  1552. // Define special_code for special lines
  1553. $special_code = 0;
  1554. // if (empty($_POST['qty'])) $special_code=3; // Options should not exists on invoices
  1555. // Ecrase $pu par celui du produit
  1556. // Ecrase $desc par celui du produit
  1557. // Ecrase $tva_tx par celui du produit
  1558. // Ecrase $base_price_type par celui du produit
  1559. // Replaces $fk_unit with the product's
  1560. if (! empty($idprod))
  1561. {
  1562. $prod = new Product($db);
  1563. $prod->fetch($idprod);
  1564. $label = ((GETPOST('product_label') && GETPOST('product_label') != $prod->label) ? GETPOST('product_label') : '');
  1565. // Update if prices fields are defined
  1566. $tva_tx = get_default_tva($mysoc, $object->thirdparty, $prod->id);
  1567. $tva_npr = get_default_npr($mysoc, $object->thirdparty, $prod->id);
  1568. if (empty($tva_tx)) $tva_npr=0;
  1569. $pu_ht = $prod->price;
  1570. $pu_ttc = $prod->price_ttc;
  1571. $price_min = $prod->price_min;
  1572. $price_base_type = $prod->price_base_type;
  1573. // If price per segment
  1574. if (! empty($conf->global->PRODUIT_MULTIPRICES) && ! empty($object->thirdparty->price_level))
  1575. {
  1576. $pu_ht = $prod->multiprices[$object->thirdparty->price_level];
  1577. $pu_ttc = $prod->multiprices_ttc[$object->thirdparty->price_level];
  1578. $price_min = $prod->multiprices_min[$object->thirdparty->price_level];
  1579. $price_base_type = $prod->multiprices_base_type[$object->thirdparty->price_level];
  1580. if (! empty($conf->global->PRODUIT_MULTIPRICES_USE_VAT_PER_LEVEL)) // using this option is a bug. kept for backward compatibility
  1581. {
  1582. if (isset($prod->multiprices_tva_tx[$object->thirdparty->price_level])) $tva_tx=$prod->multiprices_tva_tx[$object->thirdparty->price_level];
  1583. if (isset($prod->multiprices_recuperableonly[$object->thirdparty->price_level])) $tva_npr=$prod->multiprices_recuperableonly[$object->thirdparty->price_level];
  1584. if (empty($tva_tx)) $tva_npr=0;
  1585. }
  1586. }
  1587. // If price per customer
  1588. elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES))
  1589. {
  1590. require_once DOL_DOCUMENT_ROOT . '/product/class/productcustomerprice.class.php';
  1591. $prodcustprice = new Productcustomerprice($db);
  1592. $filter = array('t.fk_product' => $prod->id,'t.fk_soc' => $object->thirdparty->id);
  1593. $result = $prodcustprice->fetch_all('', '', 0, 0, $filter);
  1594. if ($result) {
  1595. if (count($prodcustprice->lines) > 0) {
  1596. $pu_ht = price($prodcustprice->lines[0]->price);
  1597. $pu_ttc = price($prodcustprice->lines[0]->price_ttc);
  1598. $price_base_type = $prodcustprice->lines[0]->price_base_type;
  1599. $tva_tx = $prodcustprice->lines[0]->tva_tx;
  1600. if ($prodcustprice->lines[0]->default_vat_code && ! preg_match('/\(.*\)/', $tva_tx)) $tva_tx.= ' ('.$prodcustprice->lines[0]->default_vat_code.')';
  1601. $tva_npr = $prodcustprice->lines[0]->recuperableonly;
  1602. if (empty($tva_tx)) $tva_npr=0;
  1603. }
  1604. }
  1605. }
  1606. // If price per quantity
  1607. elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY))
  1608. {
  1609. if ($prod->prices_by_qty[0]) // yes, this product has some prices per quantity
  1610. {
  1611. // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
  1612. $pqp = GETPOST('pbq','int');
  1613. // Search price into product_price_by_qty from $prod->id
  1614. foreach($prod->prices_by_qty_list[0] as $priceforthequantityarray)
  1615. {
  1616. if ($priceforthequantityarray['rowid'] != $pqp) continue;
  1617. // We found the price
  1618. if ($priceforthequantityarray['price_base_type'] == 'HT')
  1619. {
  1620. $pu_ht = $priceforthequantityarray['unitprice'];
  1621. }
  1622. else
  1623. {
  1624. $pu_ttc = $priceforthequantityarray['unitprice'];
  1625. }
  1626. // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
  1627. break;
  1628. }
  1629. }
  1630. }
  1631. // If price per quantity and customer
  1632. elseif (! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES))
  1633. {
  1634. if ($prod->prices_by_qty[$object->thirdparty->price_level]) // yes, this product has some prices per quantity
  1635. {
  1636. // Search the correct price into loaded array product_price_by_qty using id of array retrieved into POST['pqp'].
  1637. $pqp = GETPOST('pbq','int');
  1638. // Search price into product_price_by_qty from $prod->id
  1639. foreach($prod->prices_by_qty_list[$object->thirdparty->price_level] as $priceforthequantityarray)
  1640. {
  1641. if ($priceforthequantityarray['rowid'] != $pqp) continue;
  1642. // We found the price
  1643. if ($priceforthequantityarray['price_base_type'] == 'HT')
  1644. {
  1645. $pu_ht = $priceforthequantityarray['unitprice'];
  1646. }
  1647. else
  1648. {
  1649. $pu_ttc = $priceforthequantityarray['unitprice'];
  1650. }
  1651. // Note: the remise_percent or price by qty is used to set data on form, so we will use value from POST.
  1652. break;
  1653. }
  1654. }
  1655. }
  1656. $tmpvat = price2num(preg_replace('/\s*\(.*\)/', '', $tva_tx));
  1657. $tmpprodvat = price2num(preg_replace('/\s*\(.*\)/', '', $prod->tva_tx));
  1658. // if price ht was forced (ie: from gui when calculated by margin rate and cost price). TODO Why this ?
  1659. if (! empty($price_ht))
  1660. {
  1661. $pu_ht = price2num($price_ht, 'MU');
  1662. $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
  1663. }
  1664. // On reevalue prix selon taux tva car taux tva transaction peut etre different
  1665. // de ceux du produit par defaut (par exemple si pays different entre vendeur et acheteur).
  1666. elseif ($tmpvat != $tmpprodvat)
  1667. {
  1668. if ($price_base_type != 'HT')
  1669. {
  1670. $pu_ht = price2num($pu_ttc / (1 + ($tmpvat / 100)), 'MU');
  1671. }
  1672. else
  1673. {
  1674. $pu_ttc = price2num($pu_ht * (1 + ($tmpvat / 100)), 'MU');
  1675. }
  1676. }
  1677. $desc = '';
  1678. // Define output language
  1679. if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
  1680. $outputlangs = $langs;
  1681. $newlang = '';
  1682. if (empty($newlang) && GETPOST('lang_id','aZ09'))
  1683. $newlang = GETPOST('lang_id','aZ09');
  1684. if (empty($newlang))
  1685. $newlang = $object->thirdparty->default_lang;
  1686. if (! empty($newlang)) {
  1687. $outputlangs = new Translate("", $conf);
  1688. $outputlangs->setDefaultLang($newlang);
  1689. $outputlangs->load('products');
  1690. }
  1691. $desc = (! empty($prod->multilangs [$outputlangs->defaultlang] ["description"])) ? $prod->multilangs [$outputlangs->defaultlang] ["description"] : $prod->description;
  1692. } else {
  1693. $desc = $prod->description;
  1694. }
  1695. $desc = dol_concatdesc($desc, $product_desc);
  1696. // Add custom code and origin country into description
  1697. if (empty($conf->global->MAIN_PRODUCT_DISABLE_CUSTOMCOUNTRYCODE) && (! empty($prod->customcode) || ! empty($prod->country_code))) {
  1698. $tmptxt = '(';
  1699. // Define output language
  1700. if (! empty($conf->global->MAIN_MULTILANGS) && ! empty($conf->global->PRODUIT_TEXTS_IN_THIRDPARTY_LANGUAGE)) {
  1701. $outputlangs = $langs;
  1702. $newlang = '';
  1703. if (empty($newlang) && GETPOST('lang_id','alpha'))
  1704. $newlang = GETPOST('lang_id','alpha');
  1705. if (empty($newlang))
  1706. $newlang = $object->thirdparty->default_lang;
  1707. if (! empty($newlang)) {
  1708. $outputlangs = new Translate("", $conf);
  1709. $outputlangs->setDefaultLang($newlang);
  1710. $outputlangs->load('products');
  1711. }
  1712. if (! empty($prod->customcode))
  1713. $tmptxt .= $outputlangs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
  1714. if (! empty($prod->customcode) && ! empty($prod->country_code))
  1715. $tmptxt .= ' - ';
  1716. if (! empty($prod->country_code))
  1717. $tmptxt .= $outputlangs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $outputlangs, 0);
  1718. } else {
  1719. if (! empty($prod->customcode))
  1720. $tmptxt .= $langs->transnoentitiesnoconv("CustomCode") . ': ' . $prod->customcode;
  1721. if (! empty($prod->customcode) && ! empty($prod->country_code))
  1722. $tmptxt .= ' - ';
  1723. if (! empty($prod->country_code))
  1724. $tmptxt .= $langs->transnoentitiesnoconv("CountryOrigin") . ': ' . getCountry($prod->country_code, 0, $db, $langs, 0);
  1725. }
  1726. $tmptxt .= ')';
  1727. $desc = dol_concatdesc($desc, $tmptxt);
  1728. }
  1729. $type = $prod->type;
  1730. $fk_unit = $prod->fk_unit;
  1731. } else {
  1732. $pu_ht = price2num($price_ht, 'MU');
  1733. $pu_ttc = price2num(GETPOST('price_ttc'), 'MU');
  1734. $tva_npr = (preg_match('/\*/', $tva_tx) ? 1 : 0);
  1735. $tva_tx = str_replace('*', '', $tva_tx);
  1736. if (empty($tva_tx)) $tva_npr=0;
  1737. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  1738. $desc = $product_desc;
  1739. $type = GETPOST('type');
  1740. $fk_unit= GETPOST('units', 'alpha');
  1741. $pu_ht_devise = price2num($price_ht_devise, 'MU');
  1742. }
  1743. // Margin
  1744. $fournprice = price2num(GETPOST('fournprice' . $predef) ? GETPOST('fournprice' . $predef) : '');
  1745. $buyingprice = price2num(GETPOST('buying_price' . $predef) != '' ? GETPOST('buying_price' . $predef) : ''); // If buying_price is '0', we must keep this value
  1746. // Local Taxes
  1747. $localtax1_tx = get_localtax($tva_tx, 1, $object->thirdparty, $mysoc, $tva_npr);
  1748. $localtax2_tx = get_localtax($tva_tx, 2, $object->thirdparty, $mysoc, $tva_npr);
  1749. $info_bits = 0;
  1750. if ($tva_npr)
  1751. $info_bits |= 0x01;
  1752. if (! empty($price_min) && (price2num($pu_ht) * (1 - price2num($remise_percent) / 100) < price2num($price_min))) {
  1753. $mesg = $langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency));
  1754. setEventMessages($mesg, null, 'errors');
  1755. } else {
  1756. // Insert line
  1757. $result = $object->addline($desc, $pu_ht, $qty, $tva_tx, $localtax1_tx, $localtax2_tx, $idprod, $remise_percent, $date_start, $date_end, 0, $info_bits, '', $price_base_type, $pu_ttc, $type, - 1, $special_code, '', 0, GETPOST('fk_parent_line'), $fournprice, $buyingprice, $label, $array_options, $_POST['progress'], '', $fk_unit, $pu_ht_devise);
  1758. if ($result > 0)
  1759. {
  1760. // Define output language
  1761. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE))
  1762. {
  1763. $outputlangs = $langs;
  1764. $newlang = '';
  1765. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09')) $newlang = GETPOST('lang_id','aZ09');
  1766. if ($conf->global->MAIN_MULTILANGS && empty($newlang)) $newlang = $object->thirdparty->default_lang;
  1767. if (! empty($newlang)) {
  1768. $outputlangs = new Translate("", $conf);
  1769. $outputlangs->setDefaultLang($newlang);
  1770. $outputlangs->load('products');
  1771. }
  1772. $model=$object->modelpdf;
  1773. $ret = $object->fetch($id); // Reload to get new records
  1774. $result = $object->generateDocument($model, $outputlangs, $hidedetails, $hidedesc, $hideref);
  1775. if ($result < 0) setEventMessages($object->error, $object->errors, 'errors');
  1776. }
  1777. unset($_POST['prod_entry_mode']);
  1778. unset($_POST['qty']);
  1779. unset($_POST['type']);
  1780. unset($_POST['remise_percent']);
  1781. unset($_POST['price_ht']);
  1782. unset($_POST['multicurrency_price_ht']);
  1783. unset($_POST['price_ttc']);
  1784. unset($_POST['tva_tx']);
  1785. unset($_POST['product_ref']);
  1786. unset($_POST['product_label']);
  1787. unset($_POST['product_desc']);
  1788. unset($_POST['fournprice']);
  1789. unset($_POST['buying_price']);
  1790. unset($_POST['np_marginRate']);
  1791. unset($_POST['np_markRate']);
  1792. unset($_POST['dp_desc']);
  1793. unset($_POST['idprod']);
  1794. unset($_POST['units']);
  1795. unset($_POST['date_starthour']);
  1796. unset($_POST['date_startmin']);
  1797. unset($_POST['date_startsec']);
  1798. unset($_POST['date_startday']);
  1799. unset($_POST['date_startmonth']);
  1800. unset($_POST['date_startyear']);
  1801. unset($_POST['date_endhour']);
  1802. unset($_POST['date_endmin']);
  1803. unset($_POST['date_endsec']);
  1804. unset($_POST['date_endday']);
  1805. unset($_POST['date_endmonth']);
  1806. unset($_POST['date_endyear']);
  1807. unset($_POST['situations']);
  1808. unset($_POST['progress']);
  1809. } else {
  1810. setEventMessages($object->error, $object->errors, 'errors');
  1811. }
  1812. $action = '';
  1813. }
  1814. }
  1815. }
  1816. elseif ($action == 'updateligne' && $user->rights->facture->creer && ! GETPOST('cancel','alpha'))
  1817. {
  1818. if (! $object->fetch($id) > 0) dol_print_error($db);
  1819. $object->fetch_thirdparty();
  1820. // Clean parameters
  1821. $date_start = '';
  1822. $date_end = '';
  1823. $date_start = dol_mktime(GETPOST('date_starthour'), GETPOST('date_startmin'), GETPOST('date_startsec'), GETPOST('date_startmonth'), GETPOST('date_startday'), GETPOST('date_startyear'));
  1824. $date_end = dol_mktime(GETPOST('date_endhour'), GETPOST('date_endmin'), GETPOST('date_endsec'), GETPOST('date_endmonth'), GETPOST('date_endday'), GETPOST('date_endyear'));
  1825. $description = dol_htmlcleanlastbr(GETPOST('product_desc','none') ? GETPOST('product_desc','none') : GETPOST('desc','none'));
  1826. $pu_ht = GETPOST('price_ht');
  1827. $vat_rate = (GETPOST('tva_tx') ? GETPOST('tva_tx') : 0);
  1828. $qty = GETPOST('qty');
  1829. $pu_ht_devise = GETPOST('multicurrency_subprice');
  1830. // Define info_bits
  1831. $info_bits = 0;
  1832. if (preg_match('/\*/', $vat_rate)) $info_bits |= 0x01;
  1833. // Define vat_rate
  1834. $vat_rate = str_replace('*', '', $vat_rate);
  1835. $localtax1_rate = get_localtax($vat_rate, 1, $object->thirdparty);
  1836. $localtax2_rate = get_localtax($vat_rate, 2, $object->thirdparty);
  1837. // Add buying price
  1838. $fournprice = price2num(GETPOST('fournprice') ? GETPOST('fournprice') : '');
  1839. $buyingprice = price2num(GETPOST('buying_price') != '' ? GETPOST('buying_price') : ''); // If buying_price is '0', we muste keep this value
  1840. // Extrafields
  1841. $extrafieldsline = new ExtraFields($db);
  1842. $extralabelsline = $extrafieldsline->fetch_name_optionals_label($object->table_element_line);
  1843. $array_options = $extrafieldsline->getOptionalsFromPost($extralabelsline);
  1844. // Unset extrafield
  1845. if (is_array($extralabelsline)) {
  1846. // Get extra fields
  1847. foreach ($extralabelsline as $key => $value) {
  1848. unset($_POST["options_" . $key]);
  1849. }
  1850. }
  1851. // Define special_code for special lines
  1852. $special_code=GETPOST('special_code');
  1853. if (! GETPOST('qty')) $special_code=3;
  1854. $line = new FactureLigne($db);
  1855. $line->fetch(GETPOST('lineid'));
  1856. $percent = $line->get_prev_progress($object->id);
  1857. if($object->type == Facture::TYPE_CREDIT_NOTE && $object->situation_cycle_ref>0)
  1858. {
  1859. // in case of situation credit note
  1860. if(GETPOST('progress') >= 0 )
  1861. {
  1862. $mesg = $langs->trans("CantBeNullOrPositive");
  1863. setEventMessages($mesg, null, 'warnings');
  1864. $error++;
  1865. $result = -1;
  1866. }
  1867. elseif (GETPOST('progress') < $line->situation_percent) // TODO : use a modified $line->get_prev_progress($object->id) result
  1868. {
  1869. $mesg = $langs->trans("CantBeLessThanMinPercent");
  1870. setEventMessages($mesg, null, 'warnings');
  1871. $error++;
  1872. $result = -1;
  1873. }
  1874. }
  1875. elseif (GETPOST('progress') < $percent)
  1876. {
  1877. $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
  1878. setEventMessages($mesg, null, 'warnings');
  1879. $error++;
  1880. $result = -1;
  1881. }
  1882. // Check minimum price
  1883. $productid = GETPOST('productid', 'int');
  1884. if (! empty($productid))
  1885. {
  1886. $product = new Product($db);
  1887. $product->fetch($productid);
  1888. $type = $product->type;
  1889. $price_min = $product->price_min;
  1890. if ((! empty($conf->global->PRODUIT_MULTIPRICES) || ! empty($conf->global->PRODUIT_CUSTOMER_PRICES_BY_QTY_MULTIPRICES)) && ! empty($object->thirdparty->price_level))
  1891. $price_min = $product->multiprices_min [$object->thirdparty->price_level];
  1892. $label = ((GETPOST('update_label') && GETPOST('product_label')) ? GETPOST('product_label') : '');
  1893. // Check price is not lower than minimum (check is done only for standard or replacement invoices)
  1894. if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT) && $price_min && (price2num($pu_ht) * (1 - price2num(GETPOST('remise_percent')) / 100) < price2num($price_min))) {
  1895. setEventMessages($langs->trans("CantBeLessThanMinPrice", price(price2num($price_min, 'MU'), 0, $langs, 0, 0, - 1, $conf->currency)), null, 'errors');
  1896. $error++;
  1897. }
  1898. } else {
  1899. $type = GETPOST('type');
  1900. $label = (GETPOST('product_label') ? GETPOST('product_label') : '');
  1901. // Check parameters
  1902. if (GETPOST('type') < 0) {
  1903. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("Type")), null, 'errors');
  1904. $error++;
  1905. }
  1906. }
  1907. if ($qty < 0) {
  1908. $langs->load("errors");
  1909. setEventMessages($langs->trans('ErrorQtyForCustomerInvoiceCantBeNegative'), null, 'errors');
  1910. $error++;
  1911. }
  1912. if ((empty($productid) && (($pu_ht < 0 && empty($conf->global->FACTURE_ENABLE_NEGATIVE_LINES)) || $pu_ht == '') && $pu_ht_devise == '') && $object->type != Facture::TYPE_CREDIT_NOTE) // Unit price can be 0 but not ''
  1913. {
  1914. if ($pu_ht < 0 && empty($conf->global->FACTURE_ENABLE_NEGATIVE_LINES))
  1915. {
  1916. $langs->load("errors");
  1917. setEventMessages($langs->trans("ErrorFieldCantBeNegativeOnInvoice", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
  1918. $error++;
  1919. }
  1920. else
  1921. {
  1922. setEventMessages($langs->trans("ErrorFieldRequired", $langs->transnoentitiesnoconv("UnitPriceHT")), null, 'errors');
  1923. $error++;
  1924. }
  1925. }
  1926. // Update line
  1927. if (! $error) {
  1928. if (empty($user->rights->margins->creer))
  1929. {
  1930. foreach ($object->lines as &$line)
  1931. {
  1932. if ($line->id == GETPOST('lineid'))
  1933. {
  1934. $fournprice = $line->fk_fournprice;
  1935. $buyingprice = $line->pa_ht;
  1936. break;
  1937. }
  1938. }
  1939. }
  1940. $result = $object->updateline(GETPOST('lineid'), $description, $pu_ht, $qty, GETPOST('remise_percent'),
  1941. $date_start, $date_end, $vat_rate, $localtax1_rate, $localtax2_rate, 'HT', $info_bits, $type,
  1942. GETPOST('fk_parent_line'), 0, $fournprice, $buyingprice, $label, $special_code, $array_options, GETPOST('progress'),
  1943. $_POST['units'],$pu_ht_devise);
  1944. if ($result >= 0) {
  1945. if (empty($conf->global->MAIN_DISABLE_PDF_AUTOUPDATE)) {
  1946. // Define output language
  1947. $outputlangs = $langs;
  1948. $newlang = '';
  1949. if ($conf->global->MAIN_MULTILANGS && empty($newlang) && GETPOST('lang_id','aZ09'))
  1950. $newlang = GETPOST('lang_id','aZ09');
  1951. if ($conf->global->MAIN_MULTILANGS && empty($newlang))
  1952. $newlang = $object->thirdparty->default_lang;
  1953. if (! empty($newlang)) {
  1954. $outputlangs = new Translate("", $conf);
  1955. $outputlangs->setDefaultLang($newlang);
  1956. $outputlangs->load('products');
  1957. }
  1958. $ret = $object->fetch($id); // Reload to get new records
  1959. $object->generateDocument($object->modelpdf, $outputlangs, $hidedetails, $hidedesc, $hideref);
  1960. }
  1961. unset($_POST['qty']);
  1962. unset($_POST['type']);
  1963. unset($_POST['productid']);
  1964. unset($_POST['remise_percent']);
  1965. unset($_POST['price_ht']);
  1966. unset($_POST['multicurrency_price_ht']);
  1967. unset($_POST['price_ttc']);
  1968. unset($_POST['tva_tx']);
  1969. unset($_POST['product_ref']);
  1970. unset($_POST['product_label']);
  1971. unset($_POST['product_desc']);
  1972. unset($_POST['fournprice']);
  1973. unset($_POST['buying_price']);
  1974. unset($_POST['np_marginRate']);
  1975. unset($_POST['np_markRate']);
  1976. unset($_POST['dp_desc']);
  1977. unset($_POST['idprod']);
  1978. unset($_POST['units']);
  1979. unset($_POST['date_starthour']);
  1980. unset($_POST['date_startmin']);
  1981. unset($_POST['date_startsec']);
  1982. unset($_POST['date_startday']);
  1983. unset($_POST['date_startmonth']);
  1984. unset($_POST['date_startyear']);
  1985. unset($_POST['date_endhour']);
  1986. unset($_POST['date_endmin']);
  1987. unset($_POST['date_endsec']);
  1988. unset($_POST['date_endday']);
  1989. unset($_POST['date_endmonth']);
  1990. unset($_POST['date_endyear']);
  1991. unset($_POST['situations']);
  1992. unset($_POST['progress']);
  1993. } else {
  1994. setEventMessages($object->error, $object->errors, 'errors');
  1995. }
  1996. }
  1997. }
  1998. else if ($action == 'updatealllines' && $user->rights->facture->creer && $_POST['all_percent'] == $langs->trans('Modifier'))
  1999. {
  2000. if (!$object->fetch($id) > 0) dol_print_error($db);
  2001. if (!is_null(GETPOST('all_progress')) && GETPOST('all_progress') != "")
  2002. {
  2003. foreach ($object->lines as $line)
  2004. {
  2005. $percent = $line->get_prev_progress($object->id);
  2006. if (GETPOST('all_progress') < $percent) {
  2007. $mesg = '<div class="warning">' . $langs->trans("CantBeLessThanMinPercent") . '</div>';
  2008. $result = -1;
  2009. } else
  2010. $object->update_percent($line, $_POST['all_progress']);
  2011. }
  2012. }
  2013. }
  2014. else if ($action == 'updateligne' && $user->rights->facture->creer && $_POST['cancel'] == $langs->trans('Cancel')) {
  2015. header('Location: ' . $_SERVER["PHP_SELF"] . '?facid=' . $id); // Pour reaffichage de la fiche en cours d'edition
  2016. exit();
  2017. }
  2018. // Outing situation invoice from cycle
  2019. elseif ($action == 'confirm_situationout' && $confirm == 'yes' && $user->rights->facture->creer)
  2020. {
  2021. $object->fetch($id,'', '','', true);
  2022. if ($object->statut == Facture::STATUS_VALIDATED
  2023. && $object->type == Facture::TYPE_SITUATION
  2024. && $user->rights->facture->creer
  2025. && !$objectidnext
  2026. && $object->is_last_in_cycle()
  2027. && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  2028. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
  2029. )
  2030. {
  2031. $outingError = 0;
  2032. $newCycle = $object->newCycle(); // we need to keep the "situation behavior" so we place it on a new situation cycle
  2033. if($newCycle > 1)
  2034. {
  2035. // Search credit notes
  2036. $lastCycle = $object->situation_cycle_ref;
  2037. $lastSituationCounter = $object->situation_counter;
  2038. $linkedCreditNotesList = array();
  2039. if (count($object->tab_next_situation_invoice) > 0) {
  2040. foreach ($object->tab_next_situation_invoice as $next_invoice) {
  2041. if($next_invoice->type == Facture::TYPE_CREDIT_NOTE
  2042. && $next_invoice->situation_counter == $object->situation_counter
  2043. && $next_invoice->fk_facture_source == $object->id
  2044. )
  2045. {
  2046. $linkedCreditNotesList[] = $next_invoice->id ;
  2047. }
  2048. }
  2049. }
  2050. $object->situation_cycle_ref = $newCycle;
  2051. $object->situation_counter = 1;
  2052. $object->situation_final = 0;
  2053. if($object->update($user) > 0)
  2054. {
  2055. $errors = 0;
  2056. if(count($linkedCreditNotesList) > 0)
  2057. {
  2058. // now, credit note must follow
  2059. $sql = 'UPDATE '.MAIN_DB_PREFIX.'facture ';
  2060. $sql.= ' SET situation_cycle_ref='.$newCycle;
  2061. $sql.= ' , situation_final=0';
  2062. $sql.= ' , situation_counter='.$object->situation_counter;
  2063. $sql.= ' WHERE rowid IN ('.implode(',',$linkedCreditNotesList).')';
  2064. $resql=$db->query($sql);
  2065. if (!$resql) $errors++;
  2066. // Change each progression persent on each lines
  2067. foreach($object->lines as $line)
  2068. {
  2069. // no traitement for special product
  2070. if ($line->product_type == 9 ) continue;
  2071. if(!empty($object->tab_previous_situation_invoice))
  2072. {
  2073. // search the last invoice in cycle
  2074. $lineIndex = count($object->tab_previous_situation_invoice) - 1;
  2075. $searchPreviousInvoice = true;
  2076. while( $searchPreviousInvoice )
  2077. {
  2078. if($object->tab_previous_situation_invoice[$lineIndex]->type == Facture::TYPE_SITUATION || $lineIndex < 1)
  2079. {
  2080. $searchPreviousInvoice=false; // find, exit;
  2081. break;
  2082. }
  2083. else
  2084. {
  2085. $lineIndex--; // go to previous invoice in cycle
  2086. }
  2087. }
  2088. $maxPrevSituationPercent = 0;
  2089. foreach($object->tab_previous_situation_invoice[$lineIndex]->lines as $prevLine)
  2090. {
  2091. if($prevLine->id == $line->fk_prev_id)
  2092. {
  2093. $maxPrevSituationPercent = max($maxPrevSituationPercent,$prevLine->situation_percent);
  2094. }
  2095. }
  2096. $line->situation_percent = $line->situation_percent - $maxPrevSituationPercent;
  2097. if($line->update()<0) $errors++;
  2098. }
  2099. }
  2100. }
  2101. if (!$errors)
  2102. {
  2103. setEventMessages($langs->trans('Updated'), '', 'mesgs');
  2104. header("Location: ".$_SERVER['PHP_SELF']."?id=".$id);
  2105. }
  2106. else
  2107. {
  2108. setEventMessages($langs->trans('ErrorOutingSituationInvoiceCreditNote'), array(), 'errors');
  2109. }
  2110. }
  2111. else
  2112. {
  2113. setEventMessages($langs->trans('ErrorOutingSituationInvoiceOnUpdate'), array(), 'errors');
  2114. }
  2115. }
  2116. else
  2117. {
  2118. setEventMessages($langs->trans('ErrorFindNextSituationInvoice'), array(), 'errors');
  2119. }
  2120. }
  2121. }
  2122. // add lines from objectlinked
  2123. elseif($action == 'import_lines_from_object'
  2124. && $user->rights->facture->creer
  2125. && $object->statut == Facture::STATUS_DRAFT
  2126. && ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA || $object->type == Facture::TYPE_SITUATION))
  2127. {
  2128. $fromElement = GETPOST('fromelement');
  2129. $fromElementid = GETPOST('fromelementid');
  2130. $importLines = GETPOST('line_checkbox');
  2131. if(!empty($importLines) && is_array($importLines) && !empty($fromElement) && ctype_alpha($fromElement) && !empty($fromElementid))
  2132. {
  2133. if($fromElement == 'commande')
  2134. {
  2135. dol_include_once('/'.$fromElement.'/class/'.$fromElement.'.class.php');
  2136. $lineClassName = 'OrderLine';
  2137. }
  2138. elseif($fromElement == 'propal')
  2139. {
  2140. dol_include_once('/comm/'.$fromElement.'/class/'.$fromElement.'.class.php');
  2141. $lineClassName = 'PropaleLigne';
  2142. }
  2143. $nextRang = count($object->lines) + 1;
  2144. $importCount = 0;
  2145. $error = 0;
  2146. foreach($importLines as $lineId)
  2147. {
  2148. $lineId = intval($lineId);
  2149. $originLine = new $lineClassName($db);
  2150. if(intval($fromElementid) > 0 && $originLine->fetch( $lineId ) > 0)
  2151. {
  2152. $originLine->fetch_optionals($lineId);
  2153. $desc = $originLine->desc;
  2154. $pu_ht = $originLine->subprice;
  2155. $qty = $originLine->qty;
  2156. $txtva = $originLine->tva_tx;
  2157. $txlocaltax1 = $originLine->localtax1_tx;
  2158. $txlocaltax2 = $originLine->localtax2_tx;
  2159. $fk_product = $originLine->fk_product;
  2160. $remise_percent = $originLine->remise_percent;
  2161. $date_start = $originLine->date_start;
  2162. $date_end = $originLine->date_end;
  2163. $ventil = 0;
  2164. $info_bits = $originLine->info_bits;
  2165. $fk_remise_except = $originLine->fk_remise_except;
  2166. $price_base_type='HT';
  2167. $pu_ttc=0;
  2168. $type = $originLine->product_type;
  2169. $rang=$nextRang++;
  2170. $special_code = $originLine->special_code;
  2171. $origin = $originLine->element;
  2172. $origin_id = $originLine->id;
  2173. $fk_parent_line=0;
  2174. $fk_fournprice=$originLine->fk_fournprice;
  2175. $pa_ht = $originLine->pa_ht;
  2176. $label = $originLine->label;
  2177. $array_options = $originLine->array_options;
  2178. $situation_percent = 100;
  2179. $fk_prev_id = '';
  2180. $fk_unit = $originLine->fk_unit;
  2181. $pu_ht_devise = $originLine->multicurrency_subprice;
  2182. $res = $object->addline($desc, $pu_ht, $qty, $txtva, $txlocaltax1, $txlocaltax2, $fk_product, $remise_percent, $date_start, $date_end, $ventil, $info_bits, $fk_remise_except, $price_base_type, $pu_ttc, $type, $rang, $special_code, $origin, $origin_id, $fk_parent_line, $fk_fournprice, $pa_ht, $label, $array_options, $situation_percent, $fk_prev_id, $fk_unit,$pu_ht_devise);
  2183. if($res > 0){
  2184. $importCount++;
  2185. }else{
  2186. $error++;
  2187. }
  2188. }
  2189. else{
  2190. $error++;
  2191. }
  2192. }
  2193. if($error)
  2194. {
  2195. setEventMessage($langs->trans('ErrorsOnXLines',$error), 'errors');
  2196. }
  2197. }
  2198. }
  2199. // Actions when printing a doc from card
  2200. include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php';
  2201. // Actions to send emails
  2202. if (empty($id)) $id=$facid;
  2203. $trigger_name='BILL_SENTBYMAIL';
  2204. $paramname='id';
  2205. $autocopy='MAIN_MAIL_AUTOCOPY_INVOICE_TO';
  2206. $trackid='inv'.$object->id;
  2207. include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php';
  2208. // Actions to build doc
  2209. $upload_dir = $conf->facture->dir_output;
  2210. $permissioncreate=$user->rights->facture->creer;
  2211. include DOL_DOCUMENT_ROOT.'/core/actions_builddoc.inc.php';
  2212. if ($action == 'update_extras') {
  2213. $object->oldcopy = dol_clone($object);
  2214. // Fill array 'array_options' with data from add form
  2215. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  2216. $ret = $extrafields->setOptionalsFromPost($extralabels, $object, GETPOST('attribute','none'));
  2217. if ($ret < 0) $error++;
  2218. if (! $error)
  2219. {
  2220. // Actions on extra fields
  2221. $result = $object->insertExtraFields('BILL_MODIFY');
  2222. if ($result < 0)
  2223. {
  2224. setEventMessages($object->error, $object->errors, 'errors');
  2225. $error++;
  2226. }
  2227. }
  2228. if ($error)
  2229. $action = 'edit_extras';
  2230. }
  2231. if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB) && $user->rights->facture->creer) {
  2232. if ($action == 'addcontact') {
  2233. $result = $object->fetch($id);
  2234. if ($result > 0 && $id > 0) {
  2235. $contactid = (GETPOST('userid') ? GETPOST('userid') : GETPOST('contactid'));
  2236. $result = $object->add_contact($contactid, $_POST["type"], $_POST["source"]);
  2237. }
  2238. if ($result >= 0) {
  2239. header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
  2240. exit();
  2241. } else {
  2242. if ($object->error == 'DB_ERROR_RECORD_ALREADY_EXISTS') {
  2243. $langs->load("errors");
  2244. setEventMessages($langs->trans("ErrorThisContactIsAlreadyDefinedAsThisType"), null, 'errors');
  2245. } else {
  2246. setEventMessages($object->error, $object->errors, 'errors');
  2247. }
  2248. }
  2249. } // bascule du statut d'un contact
  2250. elseif ($action == 'swapstatut') {
  2251. if ($object->fetch($id)) {
  2252. $result = $object->swapContactStatus(GETPOST('ligne'));
  2253. } else {
  2254. dol_print_error($db);
  2255. }
  2256. } // Efface un contact
  2257. elseif ($action == 'deletecontact') {
  2258. $object->fetch($id);
  2259. $result = $object->delete_contact($lineid);
  2260. if ($result >= 0) {
  2261. header("Location: ".$_SERVER['PHP_SELF']."?id=".$object->id);
  2262. exit();
  2263. } else {
  2264. dol_print_error($db);
  2265. }
  2266. }
  2267. if ($error)
  2268. $action = 'edit_extras';
  2269. }
  2270. }
  2271. /*
  2272. * View
  2273. */
  2274. $form = new Form($db);
  2275. $formother = new FormOther($db);
  2276. $formfile = new FormFile($db);
  2277. $formmargin = new FormMargin($db);
  2278. $paymentstatic=new Paiement($db);
  2279. $bankaccountstatic = new Account($db);
  2280. if (! empty($conf->projet->enabled)) { $formproject = new FormProjets($db); }
  2281. $now = dol_now();
  2282. $title = $langs->trans('InvoiceCustomer') . " - " . $langs->trans('Card');
  2283. $helpurl = "EN:Customers_Invoices|FR:Factures_Clients|ES:Facturas_a_clientes";
  2284. llxHeader('', $title, $helpurl);
  2285. // Mode creation
  2286. if ($action == 'create')
  2287. {
  2288. $facturestatic = new Facture($db);
  2289. $extralabels = $extrafields->fetch_name_optionals_label($facturestatic->table_element);
  2290. print load_fiche_titre($langs->trans('NewBill'));
  2291. $soc = new Societe($db);
  2292. if ($socid > 0)
  2293. $res = $soc->fetch($socid);
  2294. $currency_code = $conf->currency;
  2295. // Load objectsrc
  2296. $remise_absolue = 0;
  2297. if (! empty($origin) && ! empty($originid))
  2298. {
  2299. // Parse element/subelement (ex: project_task)
  2300. $element = $subelement = $origin;
  2301. if (preg_match('/^([^_]+)_([^_]+)/i', $origin, $regs)) {
  2302. $element = $regs [1];
  2303. $subelement = $regs [2];
  2304. }
  2305. if ($element == 'project') {
  2306. $projectid = $originid;
  2307. if (!$cond_reglement_id) {
  2308. $cond_reglement_id = $soc->cond_reglement_id;
  2309. }
  2310. if (!$mode_reglement_id) {
  2311. $mode_reglement_id = $soc->mode_reglement_id;
  2312. }
  2313. if (!$remise_percent) {
  2314. $remise_percent = $soc->remise_percent;
  2315. }
  2316. if (!$dateinvoice) {
  2317. // Do not set 0 here (0 for a date is 1970)
  2318. $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice);
  2319. }
  2320. } else {
  2321. // For compatibility
  2322. if ($element == 'order' || $element == 'commande') {
  2323. $element = $subelement = 'commande';
  2324. }
  2325. if ($element == 'propal') {
  2326. $element = 'comm/propal';
  2327. $subelement = 'propal';
  2328. }
  2329. if ($element == 'contract') {
  2330. $element = $subelement = 'contrat';
  2331. }
  2332. if ($element == 'shipping') {
  2333. $element = $subelement = 'expedition';
  2334. }
  2335. dol_include_once('/' . $element . '/class/' . $subelement . '.class.php');
  2336. $classname = ucfirst($subelement);
  2337. $objectsrc = new $classname($db);
  2338. $objectsrc->fetch($originid);
  2339. if (empty($objectsrc->lines) && method_exists($objectsrc, 'fetch_lines'))
  2340. $objectsrc->fetch_lines();
  2341. $objectsrc->fetch_thirdparty();
  2342. $projectid = (! empty($projectid) ? $projectid : $objectsrc->fk_project);
  2343. $ref_client = (! empty($objectsrc->ref_client) ? $objectsrc->ref_client : (! empty($objectsrc->ref_customer) ? $objectsrc->ref_customer:''));
  2344. $ref_int = (! empty($objectsrc->ref_int) ? $objectsrc->ref_int : '');
  2345. // only if socid not filled else it's allready done upper
  2346. if (empty($socid))
  2347. $soc = $objectsrc->thirdparty;
  2348. $cond_reglement_id = (! empty($objectsrc->cond_reglement_id)?$objectsrc->cond_reglement_id:(! empty($soc->cond_reglement_id)?$soc->cond_reglement_id:0));
  2349. $mode_reglement_id = (! empty($objectsrc->mode_reglement_id)?$objectsrc->mode_reglement_id:(! empty($soc->mode_reglement_id)?$soc->mode_reglement_id:0));
  2350. $fk_account = (! empty($objectsrc->fk_account)?$objectsrc->fk_account:(! empty($soc->fk_account)?$soc->fk_account:0));
  2351. $remise_percent = (! empty($objectsrc->remise_percent)?$objectsrc->remise_percent:(! empty($soc->remise_percent)?$soc->remise_percent:0));
  2352. $remise_absolue = (! empty($objectsrc->remise_absolue)?$objectsrc->remise_absolue:(! empty($soc->remise_absolue)?$soc->remise_absolue:0));
  2353. $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice);
  2354. if (!empty($conf->multicurrency->enabled))
  2355. {
  2356. if (!empty($objectsrc->multicurrency_code)) $currency_code = $objectsrc->multicurrency_code;
  2357. if (!empty($conf->global->MULTICURRENCY_USE_ORIGIN_TX) && !empty($objectsrc->multicurrency_tx)) $currency_tx = $objectsrc->multicurrency_tx;
  2358. }
  2359. // Replicate extrafields
  2360. $objectsrc->fetch_optionals($originid);
  2361. $object->array_options = $objectsrc->array_options;
  2362. }
  2363. }
  2364. else
  2365. {
  2366. $cond_reglement_id = $soc->cond_reglement_id;
  2367. $mode_reglement_id = $soc->mode_reglement_id;
  2368. $fk_account = $soc->fk_account;
  2369. $remise_percent = $soc->remise_percent;
  2370. $remise_absolue = 0;
  2371. $dateinvoice = (empty($dateinvoice)?(empty($conf->global->MAIN_AUTOFILL_DATE)?-1:''):$dateinvoice); // Do not set 0 here (0 for a date is 1970)
  2372. if (!empty($conf->multicurrency->enabled) && !empty($soc->multicurrency_code)) $currency_code = $soc->multicurrency_code;
  2373. }
  2374. if (!empty($soc->id)) $absolute_discount = $soc->getAvailableDiscounts();
  2375. $note_public = $object->getDefaultCreateValueFor('note_public', (is_object($objectsrc)?$objectsrc->note_public:null));
  2376. $note_private = $object->getDefaultCreateValueFor('note_private', ((! empty($origin) && ! empty($originid) && is_object($objectsrc))?$objectsrc->note_private:null));
  2377. if (! empty($conf->use_javascript_ajax))
  2378. {
  2379. require_once DOL_DOCUMENT_ROOT . '/core/lib/ajax.lib.php';
  2380. print ajax_combobox('fac_replacement');
  2381. print ajax_combobox('fac_avoir');
  2382. print ajax_combobox('situations');
  2383. }
  2384. if ($origin == 'contrat')
  2385. {
  2386. $langs->load("admin");
  2387. $text=$langs->trans("ToCreateARecurringInvoice");
  2388. $text.=' '.$langs->trans("ToCreateARecurringInvoiceGene", $langs->transnoentitiesnoconv("MenuFinancial"), $langs->transnoentitiesnoconv("BillsCustomers"), $langs->transnoentitiesnoconv("ListOfTemplates"));
  2389. if (empty($conf->global->INVOICE_DISABLE_AUTOMATIC_RECURRING_INVOICE))
  2390. {
  2391. $text.=' '.$langs->trans("ToCreateARecurringInvoiceGeneAuto", $langs->transnoentitiesnoconv('Module2300Name'));
  2392. }
  2393. print info_admin($text, 0, 0, 0).'<br>';
  2394. }
  2395. print '<form name="add" action="' . $_SERVER["PHP_SELF"] . '" method="POST">';
  2396. print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  2397. print '<input type="hidden" name="action" value="add">';
  2398. if ($soc->id > 0) print '<input type="hidden" name="socid" value="' . $soc->id . '">' . "\n";
  2399. print '<input name="facnumber" type="hidden" value="provisoire">';
  2400. print '<input name="ref_client" type="hidden" value="' . $ref_client . '">';
  2401. print '<input name="ref_int" type="hidden" value="' . $ref_int . '">';
  2402. print '<input type="hidden" name="origin" value="' . $origin . '">';
  2403. print '<input type="hidden" name="originid" value="' . $originid . '">';
  2404. if (!empty($currency_tx)) print '<input type="hidden" name="originmulticurrency_tx" value="' . $currency_tx . '">';
  2405. dol_fiche_head('');
  2406. print '<table class="border" width="100%">';
  2407. // Ref
  2408. print '<tr><td class="titlefieldcreate fieldrequired">' . $langs->trans('Ref') . '</td><td colspan="2">' . $langs->trans('Draft') . '</td></tr>';
  2409. // Thirdparty
  2410. print '<td class="fieldrequired">' . $langs->trans('Customer') . '</td>';
  2411. if ($soc->id > 0 && ! GETPOST('fac_rec','alpha'))
  2412. {
  2413. print '<td colspan="2">';
  2414. print $soc->getNomUrl(1);
  2415. print '<input type="hidden" name="socid" value="' . $soc->id . '">';
  2416. // Outstanding Bill
  2417. $outstandingBills = $soc->get_OutstandingBill();
  2418. print ' (' . $langs->trans('CurrentOutstandingBill') . ': ';
  2419. print price($outstandingBills, '', $langs, 0, 0, -1, $conf->currency);
  2420. if ($soc->outstanding_limit != '')
  2421. {
  2422. if ($outstandingBills > $soc->outstanding_limit) print img_warning($langs->trans("OutstandingBillReached"));
  2423. print ' / ' . price($soc->outstanding_limit, '', $langs, 0, 0, -1, $conf->currency);
  2424. }
  2425. print ')';
  2426. print '</td>';
  2427. }
  2428. else
  2429. {
  2430. print '<td colspan="2">';
  2431. print $form->select_company($soc->id, 'socid', '(s.client = 1 OR s.client = 3) AND status=1', 'SelectThirdParty', 0, 0, null, 0, 'minwidth300');
  2432. // Option to reload page to retrieve customer informations. Note, this clear other input
  2433. if (!empty($conf->global->RELOAD_PAGE_ON_CUSTOMER_CHANGE))
  2434. {
  2435. print '<script type="text/javascript">
  2436. $(document).ready(function() {
  2437. $("#socid").change(function() {
  2438. var socid = $(this).val();
  2439. var fac_rec = $(\'#fac_rec\').val();
  2440. // reload page
  2441. window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&fac_rec="+fac_rec;
  2442. });
  2443. });
  2444. </script>';
  2445. }
  2446. print ' <a href="'.DOL_URL_ROOT.'/societe/card.php?action=create&client=3&fournisseur=0&backtopage='.urlencode($_SERVER["PHP_SELF"].'?action=create').'">'.$langs->trans("AddThirdParty").'</a>';
  2447. print '</td>';
  2448. }
  2449. print '</tr>' . "\n";
  2450. $exampletemplateinvoice=new FactureRec($db);
  2451. // Overwrite value if creation of invoice is from a predefined invoice
  2452. if (empty($origin) && empty($originid) && GETPOST('fac_rec','int') > 0)
  2453. {
  2454. $invoice_predefined = new FactureRec($db);
  2455. $invoice_predefined->fetch(GETPOST('fac_rec','int'));
  2456. $dateinvoice = $invoice_predefined->date_when; // To use next gen date by default later
  2457. if (empty($projectid)) $projectid = $invoice_predefined->fk_project;
  2458. $cond_reglement_id = $invoice_predefined->cond_reglement_id;
  2459. $mode_reglement_id = $invoice_predefined->mode_reglement_id;
  2460. $fk_account = $invoice_predefined->fk_account;
  2461. $note_public = $invoice_predefined->note_public;
  2462. $note_private = $invoice_predefined->note_private;
  2463. $sql = 'SELECT r.rowid, r.titre, r.total_ttc';
  2464. $sql .= ' FROM ' . MAIN_DB_PREFIX . 'facture_rec as r';
  2465. $sql .= ' WHERE r.fk_soc = ' . $invoice_predefined->socid;
  2466. $resql = $db->query($sql);
  2467. if ($resql)
  2468. {
  2469. $num = $db->num_rows($resql);
  2470. $i = 0;
  2471. if ($num > 0)
  2472. {
  2473. print '<tr><td>' . $langs->trans('CreateFromRepeatableInvoice') . '</td><td>';
  2474. print '<select class="flat" id="fac_rec" name="fac_rec">';
  2475. print '<option value="0" selected></option>';
  2476. while ($i < $num)
  2477. {
  2478. $objp = $db->fetch_object($resql);
  2479. print '<option value="' . $objp->rowid . '"';
  2480. if (GETPOST('fac_rec') == $objp->rowid)
  2481. {
  2482. print ' selected';
  2483. $exampletemplateinvoice->fetch(GETPOST('fac_rec'));
  2484. }
  2485. print '>' . $objp->titre . ' (' . price($objp->total_ttc) . ' ' . $langs->trans("TTC") . ')</option>';
  2486. $i ++;
  2487. }
  2488. print '</select>';
  2489. // Option to reload page to retrieve customer informations. Note, this clear other input
  2490. if (!empty($conf->global->RELOAD_PAGE_ON_TEMPLATE_CHANGE))
  2491. {
  2492. print '<script type="text/javascript">
  2493. $(document).ready(function() {
  2494. $("#fac_rec").change(function() {
  2495. var fac_rec = $(this).val();
  2496. var socid = $(\'#socid\').val();
  2497. // reload page
  2498. window.location.href = "'.$_SERVER["PHP_SELF"].'?action=create&socid="+socid+"&fac_rec="+fac_rec;
  2499. });
  2500. });
  2501. </script>';
  2502. }
  2503. print '</td></tr>';
  2504. }
  2505. $db->free($resql);
  2506. } else {
  2507. dol_print_error($db);
  2508. }
  2509. }
  2510. // Type de facture
  2511. $facids = $facturestatic->list_replacable_invoices($soc->id);
  2512. if ($facids < 0) {
  2513. dol_print_error($db, $facturestatic);
  2514. exit();
  2515. }
  2516. $options = "";
  2517. foreach ($facids as $facparam)
  2518. {
  2519. $options .= '<option value="' . $facparam ['id'] . '"';
  2520. if ($facparam ['id'] == $_POST['fac_replacement'])
  2521. $options .= ' selected';
  2522. $options .= '>' . $facparam ['ref'];
  2523. $options .= ' (' . $facturestatic->LibStatut(0, $facparam ['status']) . ')';
  2524. $options .= '</option>';
  2525. }
  2526. // Show link for credit note
  2527. $facids=$facturestatic->list_qualified_avoir_invoices($soc->id);
  2528. if ($facids < 0)
  2529. {
  2530. dol_print_error($db,$facturestatic);
  2531. exit;
  2532. }
  2533. $optionsav = "";
  2534. $newinvoice_static = new Facture($db);
  2535. foreach ($facids as $key => $valarray)
  2536. {
  2537. $newinvoice_static->id = $key;
  2538. $newinvoice_static->ref = $valarray ['ref'];
  2539. $newinvoice_static->statut = $valarray ['status'];
  2540. $newinvoice_static->type = $valarray ['type'];
  2541. $newinvoice_static->paye = $valarray ['paye'];
  2542. $optionsav .= '<option value="' . $key . '"';
  2543. if ($key == GETPOST('fac_avoir'))
  2544. $optionsav .= ' selected';
  2545. $optionsav .= '>';
  2546. $optionsav .= $newinvoice_static->ref;
  2547. $optionsav .= ' (' . $newinvoice_static->getLibStatut(1, $valarray ['paymentornot']) . ')';
  2548. $optionsav .= '</option>';
  2549. }
  2550. print '<tr><td class="tdtop fieldrequired">' . $langs->trans('Type') . '</td><td colspan="2">';
  2551. print '<div class="tagtable">' . "\n";
  2552. // Standard invoice
  2553. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2554. $tmp='<input type="radio" id="radio_standard" name="type" value="0"' . (GETPOST('type') == 0 ? ' checked' : '') . '> ';
  2555. $desc = $form->textwithpicto($tmp.$langs->trans("InvoiceStandardAsk"), $langs->transnoentities("InvoiceStandardDesc"), 1, 'help', '', 0, 3);
  2556. print $desc;
  2557. print '</div></div>';
  2558. if ((empty($origin)) || ((($origin == 'propal') || ($origin == 'commande')) && (! empty($originid))))
  2559. {
  2560. // Deposit
  2561. if (empty($conf->global->INVOICE_DISABLE_DEPOSIT))
  2562. {
  2563. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2564. $tmp='<input type="radio" id="radio_deposit" name="type" value="3"' . (GETPOST('type') == 3 ? ' checked' : '') . '> ';
  2565. print '<script type="text/javascript" language="javascript">
  2566. jQuery(document).ready(function() {
  2567. jQuery("#typedeposit, #valuedeposit").click(function() {
  2568. jQuery("#radio_deposit").prop("checked", true);
  2569. });
  2570. });
  2571. </script>';
  2572. $desc = $form->textwithpicto($tmp.$langs->trans("InvoiceDeposit"), $langs->transnoentities("InvoiceDepositDesc"), 1, 'help', '', 0, 3);
  2573. print '<table class="nobordernopadding"><tr><td>';
  2574. print $desc;
  2575. print '</td>';
  2576. if (($origin == 'propal') || ($origin == 'commande'))
  2577. {
  2578. print '<td class="nowrap" style="padding-left: 5px">';
  2579. $arraylist = array('amount' => $langs->transnoentitiesnoconv('FixAmount'), 'variable' => $langs->transnoentitiesnoconv('VarAmountOneLine', $langs->transnoentitiesnoconv('Deposit')));
  2580. print $form->selectarray('typedeposit', $arraylist, GETPOST('typedeposit'), 0, 0, 0, '', 1);
  2581. print '</td>';
  2582. print '<td class="nowrap" style="padding-left: 5px">' . $langs->trans('Value') . ':<input type="text" id="valuedeposit" name="valuedeposit" size="3" value="' . GETPOST('valuedeposit', 'int') . '"/>';
  2583. }
  2584. print '</td></tr></table>';
  2585. print '</div></div>';
  2586. }
  2587. }
  2588. if ($socid > 0)
  2589. {
  2590. if (! empty($conf->global->INVOICE_USE_SITUATION))
  2591. {
  2592. // First situation invoice
  2593. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2594. $tmp='<input type="radio" name="type" value="5"' . (GETPOST('type') == 5 ? ' checked' : '') . '> ';
  2595. $desc = $form->textwithpicto($tmp.$langs->trans("InvoiceFirstSituationAsk"), $langs->transnoentities("InvoiceFirstSituationDesc"), 1, 'help', '', 0, 3);
  2596. print $desc;
  2597. print '</div></div>';
  2598. // Next situation invoice
  2599. $opt = $form->selectSituationInvoices(GETPOST('originid'), $socid);
  2600. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2601. $tmp='<input type="radio" name="type" value="5"' . (GETPOST('type') == 5 && GETPOST('originid') ? ' checked' : '');
  2602. if ($opt == ('<option value ="0" selected>' . $langs->trans('NoSituations') . '</option>') || (GETPOST('origin') && GETPOST('origin') != 'facture' && GETPOST('origin') != 'commande')) $tmp.=' disabled';
  2603. $tmp.= '> ';
  2604. $text = $tmp.$langs->trans("InvoiceSituationAsk") . ' ';
  2605. $text .= '<select class="flat" id="situations" name="situations">';
  2606. $text .= $opt;
  2607. $text .= '</select>';
  2608. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceSituationDesc"), 1, 'help', '', 0, 3);
  2609. print $desc;
  2610. print '</div></div>';
  2611. }
  2612. // Replacement
  2613. if (empty($conf->global->INVOICE_DISABLE_REPLACEMENT))
  2614. {
  2615. print '<!-- replacement line -->';
  2616. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2617. $tmp='<input type="radio" name="type" id="radio_replacement" value="1"' . (GETPOST('type') == 1 ? ' checked' : '');
  2618. if (! $options) $tmp.=' disabled';
  2619. $tmp.='> ';
  2620. print '<script type="text/javascript" language="javascript">
  2621. jQuery(document).ready(function() {
  2622. jQuery("#fac_replacement").change(function() {
  2623. jQuery("#radio_replacement").prop("checked", true);
  2624. });
  2625. });
  2626. </script>';
  2627. $text = $tmp.$langs->trans("InvoiceReplacementAsk") . ' ';
  2628. $text .= '<select class="flat" name="fac_replacement" id="fac_replacement"';
  2629. if (! $options)
  2630. $text .= ' disabled';
  2631. $text .= '>';
  2632. if ($options) {
  2633. $text .= '<option value="-1">&nbsp;</option>';
  2634. $text .= $options;
  2635. } else {
  2636. $text .= '<option value="-1">' . $langs->trans("NoReplacableInvoice") . '</option>';
  2637. }
  2638. $text .= '</select>';
  2639. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1, 'help', '', 0, 3);
  2640. print $desc;
  2641. print '</div></div>';
  2642. }
  2643. }
  2644. else
  2645. {
  2646. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2647. $tmp='<input type="radio" name="type" id="radio_replacement" value="0" disabled> ';
  2648. $text = $tmp.$langs->trans("InvoiceReplacement") . ' ';
  2649. $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') ';
  2650. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceReplacementDesc"), 1, 'help', '', 0, 3);
  2651. print $desc;
  2652. print '</div></div>';
  2653. }
  2654. if (empty($origin))
  2655. {
  2656. if ($socid > 0)
  2657. {
  2658. // Credit note
  2659. if (empty($conf->global->INVOICE_DISABLE_CREDIT_NOTE))
  2660. {
  2661. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2662. $tmp='<input type="radio" id="radio_creditnote" name="type" value="2"' . (GETPOST('type') == 2 ? ' checked' : '');
  2663. if (! $optionsav) $tmp.=' disabled';
  2664. $tmp.= '> ';
  2665. // Show credit note options only if we checked credit note
  2666. print '<script type="text/javascript" language="javascript">
  2667. jQuery(document).ready(function() {
  2668. if (! jQuery("#radio_creditnote").is(":checked"))
  2669. {
  2670. jQuery("#credit_note_options").hide();
  2671. }
  2672. jQuery("#radio_creditnote").click(function() {
  2673. jQuery("#credit_note_options").show();
  2674. });
  2675. jQuery("#radio_standard, #radio_replacement, #radio_deposit").click(function() {
  2676. jQuery("#credit_note_options").hide();
  2677. });
  2678. });
  2679. </script>';
  2680. $text = $tmp.$langs->transnoentities("InvoiceAvoirAsk") . ' ';
  2681. // $text.='<input type="text" value="">';
  2682. $text .= '<select class="flat valignmiddle" name="fac_avoir" id="fac_avoir"';
  2683. if (! $optionsav)
  2684. $text .= ' disabled';
  2685. $text .= '>';
  2686. if ($optionsav) {
  2687. $text .= '<option value="-1"></option>';
  2688. $text .= $optionsav;
  2689. } else {
  2690. $text .= '<option value="-1">' . $langs->trans("NoInvoiceToCorrect") . '</option>';
  2691. }
  2692. $text .= '</select>';
  2693. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3);
  2694. print $desc;
  2695. print '<div id="credit_note_options" class="clearboth">';
  2696. print '&nbsp;&nbsp;&nbsp; <input type="checkbox" name="invoiceAvoirWithLines" id="invoiceAvoirWithLines" value="1" onclick="$(\'#credit_note_options input[type=checkbox]\').not(this).prop(\'checked\', false);" '.(GETPOST('invoiceAvoirWithLines','int')>0 ? 'checked':'').' /> <label for="invoiceAvoirWithLines">'.$langs->trans('invoiceAvoirWithLines')."</label>";
  2697. print '<br>&nbsp;&nbsp;&nbsp; <input type="checkbox" name="invoiceAvoirWithPaymentRestAmount" id="invoiceAvoirWithPaymentRestAmount" value="1" onclick="$(\'#credit_note_options input[type=checkbox]\').not(this).prop(\'checked\', false);" '.(GETPOST('invoiceAvoirWithPaymentRestAmount','int')>0 ? 'checked':'').' /> <label for="invoiceAvoirWithPaymentRestAmount">'.$langs->trans('invoiceAvoirWithPaymentRestAmount')."</label>";
  2698. print '</div>';
  2699. print '</div></div>';
  2700. }
  2701. }
  2702. else
  2703. {
  2704. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2705. if (empty($conf->global->INVOICE_CREDIT_NOTE_STANDALONE)) $tmp='<input type="radio" name="type" id="radio_creditnote" value="0" disabled> ';
  2706. else $tmp='<input type="radio" name="type" id="radio_creditnote" value="2" > ';
  2707. $text = $tmp.$langs->trans("InvoiceAvoir") . ' ';
  2708. $text.= '('.$langs->trans("YouMustCreateInvoiceFromThird").') ';
  2709. $desc = $form->textwithpicto($text, $langs->transnoentities("InvoiceAvoirDesc"), 1, 'help', '', 0, 3);
  2710. print $desc;
  2711. print '</div></div>' . "\n";
  2712. }
  2713. }
  2714. // Template invoice
  2715. print '<div class="tagtr listofinvoicetype"><div class="tagtd listofinvoicetype">';
  2716. $tmp='<input type="radio" name="type" id="radio_template" value="0" disabled> ';
  2717. $text = $tmp.$langs->trans("RepeatableInvoice") . ' ';
  2718. //$text.= '('.$langs->trans("YouMustCreateStandardInvoiceFirst").') ';
  2719. $desc = $form->textwithpicto($text, $langs->transnoentities("YouMustCreateStandardInvoiceFirstDesc"), 1, 'help', '', 0, 3);
  2720. print $desc;
  2721. print '</div></div>';
  2722. print '</div>';
  2723. print '</td></tr>';
  2724. if ($socid > 0)
  2725. {
  2726. // Discounts for third party
  2727. print '<tr><td>' . $langs->trans('Discounts') . '</td><td colspan="2">';
  2728. $thirdparty = $soc;
  2729. $discount_type = 0;
  2730. $backtopage = urlencode($_SERVER["PHP_SELF"] . '?socid=' . $thirdparty->id . '&action=' . $action . '&origin=' . GETPOST('origin') . '&originid=' . GETPOST('originid'));
  2731. include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
  2732. print '</td></tr>';
  2733. }
  2734. $datefacture = dol_mktime(12, 0, 0, $_POST['remonth'], $_POST['reday'], $_POST['reyear']);
  2735. // Date invoice
  2736. print '<tr><td class="fieldrequired">' . $langs->trans('DateInvoice') . '</td><td colspan="2">';
  2737. print $form->select_date($datefacture?$datefacture:$dateinvoice, '', '', '', '', "add", 1, 1, 1);
  2738. print '</td></tr>';
  2739. // Date point of tax
  2740. if (! empty($conf->global->INVOICE_POINTOFTAX_DATE))
  2741. {
  2742. print '<tr><td class="fieldrequired">' . $langs->trans('DatePointOfTax') . '</td><td colspan="2">';
  2743. $date_pointoftax = dol_mktime(12, 0, 0, $_POST['date_pointoftaxmonth'], $_POST['date_pointoftaxday'], $_POST['date_pointoftaxyear']);
  2744. print $form->select_date($date_pointoftax?$date_pointoftax:-1, 'date_pointoftax', '', '', '', "add", 1, 1, 1);
  2745. print '</td></tr>';
  2746. }
  2747. // Payment term
  2748. print '<tr><td class="nowrap fieldrequired">' . $langs->trans('PaymentConditionsShort') . '</td><td colspan="2">';
  2749. $form->select_conditions_paiements(isset($_POST['cond_reglement_id']) ? $_POST['cond_reglement_id'] : $cond_reglement_id, 'cond_reglement_id');
  2750. print '</td></tr>';
  2751. // Payment mode
  2752. print '<tr><td>' . $langs->trans('PaymentMode') . '</td><td colspan="2">';
  2753. $form->select_types_paiements(isset($_POST['mode_reglement_id']) ? $_POST['mode_reglement_id'] : $mode_reglement_id, 'mode_reglement_id', 'CRDT');
  2754. print '</td></tr>';
  2755. // Bank Account
  2756. if (isset($_POST['fk_account'])) {
  2757. $fk_account = $_POST['fk_account'];
  2758. }
  2759. print '<tr><td>' . $langs->trans('BankAccount') . '</td><td colspan="2">';
  2760. $form->select_comptes($fk_account, 'fk_account', 0, '', 1);
  2761. print '</td></tr>';
  2762. // Project
  2763. if (! empty($conf->projet->enabled))
  2764. {
  2765. $langs->load('projects');
  2766. print '<tr><td>' . $langs->trans('Project') . '</td><td colspan="2">';
  2767. $numprojet = $formproject->select_projects(($socid > 0 ? $socid : -1), $projectid, 'projectid', 0, 0, 1, 1);
  2768. 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.($fac_rec?'&fac_rec='.$fac_rec:'')).'">' . $langs->trans("AddProject") . '</a>';
  2769. print '</td></tr>';
  2770. }
  2771. // Incoterms
  2772. if (!empty($conf->incoterm->enabled))
  2773. {
  2774. print '<tr>';
  2775. print '<td><label for="incoterm_id">'.$form->textwithpicto($langs->trans("IncotermLabel"), $objectsrc->libelle_incoterms, 1).'</label></td>';
  2776. print '<td colspan="2" class="maxwidthonsmartphone">';
  2777. $incoterm_id = GETPOST('incoterm_id');
  2778. $incoterm_location = GETPOST('location_incoterms');
  2779. if (empty($incoterm_id))
  2780. {
  2781. $incoterm_id = (!empty($objectsrc->fk_incoterms) ? $objectsrc->fk_incoterms : $soc->fk_incoterms);
  2782. $incoterm_location = (!empty($objectsrc->location_incoterms) ? $objectsrc->location_incoterms : $soc->location_incoterms);
  2783. }
  2784. print $form->select_incoterms($incoterm_id, $incoterm_location);
  2785. print '</td></tr>';
  2786. }
  2787. // Other attributes
  2788. $parameters = array('objectsrc' => $objectsrc,'colspan' => ' colspan="2"', 'cols'=>2);
  2789. $reshook = $hookmanager->executeHooks('formObjectOptions', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  2790. print $hookmanager->resPrint;
  2791. if (empty($reshook)) {
  2792. print $object->showOptionals($extrafields, 'edit');
  2793. }
  2794. // Template to use by default
  2795. print '<tr><td>' . $langs->trans('Model') . '</td>';
  2796. print '<td colspan="2">';
  2797. include_once DOL_DOCUMENT_ROOT . '/core/modules/facture/modules_facture.php';
  2798. $liste = ModelePDFFactures::liste_modeles($db);
  2799. print $form->selectarray('model', $liste, $conf->global->FACTURE_ADDON_PDF);
  2800. print "</td></tr>";
  2801. // Multicurrency
  2802. if (! empty($conf->multicurrency->enabled))
  2803. {
  2804. print '<tr>';
  2805. print '<td>'.fieldLabel('Currency','multicurrency_code').'</td>';
  2806. print '<td colspan="2" class="maxwidthonsmartphone">';
  2807. print $form->selectMultiCurrency($currency_code, 'multicurrency_code');
  2808. print '</td></tr>';
  2809. }
  2810. // Help of substitution key
  2811. $htmltext='';
  2812. if (GETPOST('fac_rec','int') > 0)
  2813. {
  2814. $dateexample=($datefacture ? $datefacture : $dateinvoice);
  2815. if (empty($dateexample)) $dateexample=dol_now();
  2816. $substitutionarray=array(
  2817. '__TOTAL_HT__' => $langs->trans("AmountHT").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ht).')',
  2818. '__TOTAL_TTC__' => $langs->trans("AmountTTC").' ('.$langs->trans("Example").': '.price($exampletemplateinvoice->total_ttc).')',
  2819. '__INVOICE_PREVIOUS_MONTH__' => $langs->trans("PreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'),'%m').')',
  2820. '__INVOICE_MONTH__' => $langs->trans("MonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample,'%m').')',
  2821. '__INVOICE_NEXT_MONTH__' => $langs->trans("NextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'),'%m').')',
  2822. '__INVOICE_PREVIOUS_MONTH_TEXT__' => $langs->trans("TextPreviousMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'm'),'%B').')',
  2823. '__INVOICE_MONTH_TEXT__' => $langs->trans("TextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample,'%B').')',
  2824. '__INVOICE_NEXT_MONTH_TEXT__' => $langs->trans("TextNextMonthOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'm'), '%B').')',
  2825. '__INVOICE_PREVIOUS_YEAR__' => $langs->trans("YearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, -1, 'y'),'%Y').')',
  2826. '__INVOICE_YEAR__' => $langs->trans("PreviousYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date($dateexample,'%Y').')',
  2827. '__INVOICE_NEXT_YEAR__' => $langs->trans("NextYearOfInvoice").' ('.$langs->trans("Example").': '.dol_print_date(dol_time_plus_duree($dateexample, 1, 'y'),'%Y').')'
  2828. );
  2829. $htmltext = '<i>'.$langs->trans("FollowingConstantsWillBeSubstituted").':<br>';
  2830. foreach($substitutionarray as $key => $val)
  2831. {
  2832. $htmltext.=$key.' = '.$langs->trans($val).'<br>';
  2833. }
  2834. $htmltext.='</i>';
  2835. }
  2836. // Public note
  2837. print '<tr>';
  2838. print '<td class="tdtop">';
  2839. print $form->textwithpicto($langs->trans('NotePublic'), $htmltext);
  2840. print '</td>';
  2841. print '<td valign="top" colspan="2">';
  2842. $doleditor = new DolEditor('note_public', $note_public, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
  2843. print $doleditor->Create(1);
  2844. // Private note
  2845. if (empty($user->societe_id))
  2846. {
  2847. print '<tr>';
  2848. print '<td class="tdtop">';
  2849. print $form->textwithpicto($langs->trans('NotePrivate'), $htmltext);
  2850. print '</td>';
  2851. print '<td valign="top" colspan="2">';
  2852. $doleditor = new DolEditor('note_private', $note_private, '', 80, 'dolibarr_notes', 'In', 0, false, true, ROWS_3, '90%');
  2853. print $doleditor->Create(1);
  2854. // print '<textarea name="note_private" wrap="soft" cols="70" rows="'.ROWS_3.'">'.$note_private.'.</textarea>
  2855. print '</td></tr>';
  2856. }
  2857. // Lines from source
  2858. if (! empty($origin) && ! empty($originid) && is_object($objectsrc))
  2859. {
  2860. // TODO for compatibility
  2861. if ($origin == 'contrat') {
  2862. // Calcul contrat->price (HT), contrat->total (TTC), contrat->tva
  2863. $objectsrc->remise_absolue = $remise_absolue;
  2864. $objectsrc->remise_percent = $remise_percent;
  2865. $objectsrc->update_price(1, - 1, 1);
  2866. }
  2867. print "\n<!-- " . $classname . " info -->";
  2868. print "\n";
  2869. print '<input type="hidden" name="amount" value="' . $objectsrc->total_ht . '">' . "\n";
  2870. print '<input type="hidden" name="total" value="' . $objectsrc->total_ttc . '">' . "\n";
  2871. print '<input type="hidden" name="tva" value="' . $objectsrc->total_tva . '">' . "\n";
  2872. print '<input type="hidden" name="origin" value="' . $objectsrc->element . '">';
  2873. print '<input type="hidden" name="originid" value="' . $objectsrc->id . '">';
  2874. switch (get_class($objectsrc)) {
  2875. case 'Propal':
  2876. $newclassname = 'CommercialProposal';
  2877. break;
  2878. case 'Commande':
  2879. $newclassname = 'Order';
  2880. break;
  2881. case 'Expedition':
  2882. $newclassname = 'Sending';
  2883. break;
  2884. case 'Contrat':
  2885. $newclassname = 'Contract';
  2886. break;
  2887. case 'Fichinter':
  2888. $newclassname = 'Intervention';
  2889. break;
  2890. default:
  2891. $newclassname = get_class($objectsrc);
  2892. }
  2893. print '<tr><td>' . $langs->trans($newclassname) . '</td><td colspan="2">' . $objectsrc->getNomUrl(1);
  2894. // We check if Origin document (id and type is known) has already at least one invoice attached to it
  2895. $objectsrc->fetchObjectLinked($originid,$origin,'','facture');
  2896. if (is_array($objectsrc->linkedObjects['facture']) && count($objectsrc->linkedObjects['facture']) >= 1)
  2897. {
  2898. setEventMessages('WarningBillExist', null, 'warnings');
  2899. echo ' ('.$langs->trans('LatestRelatedBill').end($objectsrc->linkedObjects['facture'])->getNomUrl(1).')';
  2900. }
  2901. echo '</td></tr>';
  2902. print '<tr><td>' . $langs->trans('TotalHT') . '</td><td colspan="2">' . price($objectsrc->total_ht) . '</td></tr>';
  2903. print '<tr><td>' . $langs->trans('TotalVAT') . '</td><td colspan="2">' . price($objectsrc->total_tva) . "</td></tr>";
  2904. if ($mysoc->localtax1_assuj == "1" || $objectsrc->total_localtax1 != 0) // Localtax1
  2905. {
  2906. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax1) . "</td></tr>";
  2907. }
  2908. if ($mysoc->localtax2_assuj == "1" || $objectsrc->total_localtax2 != 0) // Localtax2
  2909. {
  2910. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td><td colspan="2">' . price($objectsrc->total_localtax2) . "</td></tr>";
  2911. }
  2912. print '<tr><td>' . $langs->trans('TotalTTC') . '</td><td colspan="2">' . price($objectsrc->total_ttc) . "</td></tr>";
  2913. if (!empty($conf->multicurrency->enabled))
  2914. {
  2915. print '<tr><td>' . $langs->trans('MulticurrencyAmountHT') . '</td><td colspan="2">' . price($objectsrc->multicurrency_total_ht) . '</td></tr>';
  2916. print '<tr><td>' . $langs->trans('MulticurrencyAmountVAT') . '</td><td colspan="2">' . price($objectsrc->multicurrency_total_tva) . "</td></tr>";
  2917. print '<tr><td>' . $langs->trans('MulticurrencyAmountTTC') . '</td><td colspan="2">' . price($objectsrc->multicurrency_total_ttc) . "</td></tr>";
  2918. }
  2919. }
  2920. print "</table>\n";
  2921. dol_fiche_end();
  2922. // Button "Create Draft"
  2923. print '<div class="center">';
  2924. print '<input type="submit" class="button" name="bouton" value="' . $langs->trans('CreateDraft') . '">';
  2925. print '&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;';
  2926. print '<input type="button" class="button" value="' . $langs->trans("Cancel") . '" onClick="javascript:history.go(-1)">';
  2927. print '</div>';
  2928. print "</form>\n";
  2929. // Show origin lines
  2930. if (! empty($origin) && ! empty($originid) && is_object($objectsrc)) {
  2931. print '<br>';
  2932. $title = $langs->trans('ProductsAndServices');
  2933. print load_fiche_titre($title);
  2934. print '<table class="noborder" width="100%">';
  2935. $objectsrc->printOriginLinesList();
  2936. print '</table>';
  2937. }
  2938. print '<br>';
  2939. }
  2940. else if ($id > 0 || ! empty($ref))
  2941. {
  2942. /*
  2943. * Show object in view mode
  2944. */
  2945. $result = $object->fetch($id, $ref);
  2946. if ($result <= 0) {
  2947. dol_print_error($db, $object->error);
  2948. exit();
  2949. }
  2950. // fetch optionals attributes and labels
  2951. $extralabels = $extrafields->fetch_name_optionals_label($object->table_element);
  2952. if ($user->societe_id > 0 && $user->societe_id != $object->socid)
  2953. accessforbidden('', 0);
  2954. $result = $object->fetch_thirdparty();
  2955. $soc = new Societe($db);
  2956. $result=$soc->fetch($object->socid);
  2957. if ($result < 0) dol_print_error($db);
  2958. $selleruserevenustamp = $mysoc->useRevenueStamp();
  2959. $totalpaye = $object->getSommePaiement();
  2960. $totalcreditnotes = $object->getSumCreditNotesUsed();
  2961. $totaldeposits = $object->getSumDepositsUsed();
  2962. // print "totalpaye=".$totalpaye." totalcreditnotes=".$totalcreditnotes." totaldeposts=".$totaldeposits."
  2963. // selleruserrevenuestamp=".$selleruserevenustamp;
  2964. // We can also use bcadd to avoid pb with floating points
  2965. // For example print 239.2 - 229.3 - 9.9; does not return 0.
  2966. // $resteapayer=bcadd($object->total_ttc,$totalpaye,$conf->global->MAIN_MAX_DECIMALS_TOT);
  2967. // $resteapayer=bcadd($resteapayer,$totalavoir,$conf->global->MAIN_MAX_DECIMALS_TOT);
  2968. $resteapayer = price2num($object->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits, 'MT');
  2969. if ($object->paye)
  2970. {
  2971. $resteapayer = 0;
  2972. }
  2973. $resteapayeraffiche = $resteapayer;
  2974. if (! empty($conf->global->FACTURE_DEPOSITS_ARE_JUST_PAYMENTS)) { // Never use this
  2975. $filterabsolutediscount = "fk_facture_source IS NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
  2976. $filtercreditnote = "fk_facture_source IS NOT NULL"; // If we want deposit to be substracted to payments only and not to total of final invoice
  2977. } else {
  2978. $filterabsolutediscount = "fk_facture_source IS NULL OR (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%')";
  2979. $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')";
  2980. }
  2981. $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount);
  2982. $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote);
  2983. $absolute_discount = price2num($absolute_discount, 'MT');
  2984. $absolute_creditnote = price2num($absolute_creditnote, 'MT');
  2985. $author = new User($db);
  2986. if ($object->user_author) {
  2987. $author->fetch($object->user_author);
  2988. }
  2989. $objectidnext = $object->getIdReplacingInvoice();
  2990. $head = facture_prepare_head($object);
  2991. dol_fiche_head($head, 'compta', $langs->trans('InvoiceCustomer'), -1, 'bill');
  2992. $formconfirm = '';
  2993. // Confirmation de la conversion de l'avoir en reduc
  2994. if ($action == 'converttoreduc') {
  2995. if($object->type == Facture::TYPE_STANDARD) $type_fac = 'ExcessReceived';
  2996. elseif($object->type == Facture::TYPE_CREDIT_NOTE) $type_fac = 'CreditNote';
  2997. elseif($object->type == Facture::TYPE_DEPOSIT) $type_fac = 'Deposit';
  2998. $text = $langs->trans('ConfirmConvertToReduc', strtolower($langs->transnoentities($type_fac)));
  2999. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('ConvertToReduc'), $text, 'confirm_converttoreduc', '', "yes", 2);
  3000. }
  3001. // Confirmation to delete invoice
  3002. if ($action == 'delete') {
  3003. $text = $langs->trans('ConfirmDeleteBill', $object->ref);
  3004. $formquestion = array();
  3005. $qualified_for_stock_change = 0;
  3006. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
  3007. $qualified_for_stock_change = $object->hasProductsOrServices(2);
  3008. } else {
  3009. $qualified_for_stock_change = $object->hasProductsOrServices(1);
  3010. }
  3011. if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change && $object->statut >= 1)
  3012. {
  3013. $langs->load("stocks");
  3014. require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
  3015. $formproduct = new FormProduct($db);
  3016. $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockDecrease") : $langs->trans("SelectWarehouseForStockIncrease");
  3017. $forcecombo=0;
  3018. if ($conf->browser->name == 'ie') $forcecombo = 1; // There is a bug in IE10 that make combo inside popup crazy
  3019. $formquestion = array(
  3020. // 'text' => $langs->trans("ConfirmClone"),
  3021. // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1),
  3022. // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1),
  3023. array('type' => 'other','name' => 'idwarehouse','label' => $label,'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1, 0, 0, $langs->trans("NoStockAction"), 0, $forcecombo))
  3024. );
  3025. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('DeleteBill'), $text, 'confirm_delete', $formquestion, "yes", 1);
  3026. } else {
  3027. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('DeleteBill'), $text, 'confirm_delete', '', 'no', 1);
  3028. }
  3029. }
  3030. // Confirmation to remove invoice from cycle
  3031. if ($action == 'situationout') {
  3032. $text = $langs->trans('ConfirmRemoveSituationFromCycle', $object->ref);
  3033. $label = $langs->trans("ConfirmOuting");
  3034. $formquestion = array();
  3035. // remove situation from cycle
  3036. if ($object->statut == Facture::STATUS_VALIDATED
  3037. && $user->rights->facture->creer
  3038. && !$objectidnext
  3039. && $object->is_last_in_cycle()
  3040. && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  3041. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
  3042. )
  3043. {
  3044. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $label, $text, 'confirm_situationout', $formquestion, "yes", 1);
  3045. }
  3046. }
  3047. // Confirmation of validation
  3048. if ($action == 'valid')
  3049. {
  3050. // we check object has a draft number
  3051. $objectref = substr($object->ref, 1, 4);
  3052. if ($objectref == 'PROV') {
  3053. $savdate = $object->date;
  3054. if (! empty($conf->global->FAC_FORCE_DATE_VALIDATION)) {
  3055. $object->date = dol_now();
  3056. $object->date_lim_reglement = $object->calculate_date_lim_reglement();
  3057. }
  3058. $numref = $object->getNextNumRef($soc);
  3059. // $object->date=$savdate;
  3060. } else {
  3061. $numref = $object->ref;
  3062. }
  3063. $text = $langs->trans('ConfirmValidateBill', $numref);
  3064. if (! empty($conf->notification->enabled)) {
  3065. require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php';
  3066. $notify = new Notify($db);
  3067. $text .= '<br>';
  3068. $text .= $notify->confirmMessage('BILL_VALIDATE', $object->socid, $object);
  3069. }
  3070. $formquestion = array();
  3071. $qualified_for_stock_change = 0;
  3072. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
  3073. $qualified_for_stock_change = $object->hasProductsOrServices(2);
  3074. } else {
  3075. $qualified_for_stock_change = $object->hasProductsOrServices(1);
  3076. }
  3077. if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change)
  3078. {
  3079. $langs->load("stocks");
  3080. require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
  3081. require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
  3082. $formproduct = new FormProduct($db);
  3083. $warehouse = new Entrepot($db);
  3084. $warehouse_array = $warehouse->list_array();
  3085. if (count($warehouse_array) == 1) {
  3086. $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockIncrease", current($warehouse_array)) : $langs->trans("WarehouseForStockDecrease", current($warehouse_array));
  3087. $value = '<input type="hidden" id="idwarehouse" name="idwarehouse" value="' . key($warehouse_array) . '">';
  3088. } else {
  3089. $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockIncrease") : $langs->trans("SelectWarehouseForStockDecrease");
  3090. $value = $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1);
  3091. }
  3092. $formquestion = array(
  3093. // 'text' => $langs->trans("ConfirmClone"),
  3094. // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' =>
  3095. // 1),
  3096. // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value'
  3097. // => 1),
  3098. array('type' => 'other','name' => 'idwarehouse','label' => $label,'value' => $value));
  3099. }
  3100. if ($object->type != Facture::TYPE_CREDIT_NOTE && $object->total_ttc < 0) // Can happen only if $conf->global->FACTURE_ENABLE_NEGATIVE is on
  3101. {
  3102. $text .= '<br>' . img_warning() . ' ' . $langs->trans("ErrorInvoiceOfThisTypeMustBePositive");
  3103. }
  3104. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ValidateBill'), $text, 'confirm_valid', $formquestion, (($object->type != Facture::TYPE_CREDIT_NOTE && $object->total_ttc < 0) ? "no" : "yes"), 2);
  3105. }
  3106. // Confirm back to draft status
  3107. if ($action == 'modif') {
  3108. $text = $langs->trans('ConfirmUnvalidateBill', $object->ref);
  3109. $formquestion = array();
  3110. $qualified_for_stock_change = 0;
  3111. if (empty($conf->global->STOCK_SUPPORTS_SERVICES)) {
  3112. $qualified_for_stock_change = $object->hasProductsOrServices(2);
  3113. } else {
  3114. $qualified_for_stock_change = $object->hasProductsOrServices(1);
  3115. }
  3116. if ($object->type != Facture::TYPE_DEPOSIT && ! empty($conf->global->STOCK_CALCULATE_ON_BILL) && $qualified_for_stock_change) {
  3117. $langs->load("stocks");
  3118. require_once DOL_DOCUMENT_ROOT . '/product/class/html.formproduct.class.php';
  3119. require_once DOL_DOCUMENT_ROOT . '/product/stock/class/entrepot.class.php';
  3120. $formproduct = new FormProduct($db);
  3121. $warehouse = new Entrepot($db);
  3122. $warehouse_array = $warehouse->list_array();
  3123. if (count($warehouse_array) == 1) {
  3124. $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("WarehouseForStockDecrease", current($warehouse_array)) : $langs->trans("WarehouseForStockIncrease", current($warehouse_array));
  3125. $value = '<input type="hidden" id="idwarehouse" name="idwarehouse" value="' . key($warehouse_array) . '">';
  3126. } else {
  3127. $label = $object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("SelectWarehouseForStockDecrease") : $langs->trans("SelectWarehouseForStockIncrease");
  3128. $value = $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1);
  3129. }
  3130. $formquestion = array(
  3131. // 'text' => $langs->trans("ConfirmClone"),
  3132. // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' =>
  3133. // 1),
  3134. // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value'
  3135. // => 1),
  3136. array('type' => 'other','name' => 'idwarehouse','label' => $label,'value' => $value));
  3137. }
  3138. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('UnvalidateBill'), $text, 'confirm_modif', $formquestion, "yes", 1);
  3139. }
  3140. // Confirmation du classement paye
  3141. if ($action == 'paid' && $resteapayer <= 0) {
  3142. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidBill', $object->ref), 'confirm_paid', '', "yes", 1);
  3143. }
  3144. if ($action == 'paid' && $resteapayer > 0) {
  3145. // Code
  3146. $i = 0;
  3147. $close [$i]['code'] = 'discount_vat'; // escompte
  3148. $i ++;
  3149. $close [$i]['code'] = 'badcustomer';
  3150. $i ++;
  3151. // Help
  3152. $i = 0;
  3153. $close [$i]['label'] = $langs->trans("HelpEscompte") . '<br><br>' . $langs->trans("ConfirmClassifyPaidPartiallyReasonDiscountVatDesc");
  3154. $i ++;
  3155. $close [$i]['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadCustomerDesc");
  3156. $i ++;
  3157. // Texte
  3158. $i = 0;
  3159. $close [$i]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonDiscount", $resteapayer, $langs->trans("Currency" . $conf->currency)), $close[$i]['label'], 1);
  3160. $i ++;
  3161. $close [$i]['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $resteapayer, $langs->trans("Currency" . $conf->currency)), $close[$i]['label'], 1);
  3162. $i ++;
  3163. // arrayreasons[code]=reason
  3164. foreach ($close as $key => $val) {
  3165. $arrayreasons[$close [$key]['code']] = $close[$key]['reason'];
  3166. }
  3167. // Cree un tableau formulaire
  3168. $formquestion = array('text' => $langs->trans("ConfirmClassifyPaidPartiallyQuestion"),array('type' => 'radio','name' => 'close_code','label' => $langs->trans("Reason"),'values' => $arrayreasons),array('type' => 'text','name' => 'close_note','label' => $langs->trans("Comment"),'value' => '','morecss' => 'minwidth300'));
  3169. // Paiement incomplet. On demande si motif = escompte ou autre
  3170. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('ClassifyPaid'), $langs->trans('ConfirmClassifyPaidPartially', $object->ref), 'confirm_paid_partially', $formquestion, "yes", 1, 310);
  3171. }
  3172. // Confirmation du classement abandonne
  3173. if ($action == 'canceled') {
  3174. // S'il y a une facture de remplacement pas encore validee (etat brouillon),
  3175. // on ne permet pas de classer abandonner la facture.
  3176. if ($objectidnext) {
  3177. $facturereplacement = new Facture($db);
  3178. $facturereplacement->fetch($objectidnext);
  3179. $statusreplacement = $facturereplacement->statut;
  3180. }
  3181. if ($objectidnext && $statusreplacement == 0) {
  3182. print '<div class="error">' . $langs->trans("ErrorCantCancelIfReplacementInvoiceNotValidated") . '</div>';
  3183. } else {
  3184. // Code
  3185. $close [1] ['code'] = 'badcustomer';
  3186. $close [2] ['code'] = 'abandon';
  3187. // Help
  3188. $close [1] ['label'] = $langs->trans("ConfirmClassifyPaidPartiallyReasonBadCustomerDesc");
  3189. $close [2] ['label'] = $langs->trans("ConfirmClassifyAbandonReasonOtherDesc");
  3190. // Texte
  3191. $close [1] ['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyPaidPartiallyReasonBadCustomer", $object->ref), $close [1] ['label'], 1);
  3192. $close [2] ['reason'] = $form->textwithpicto($langs->transnoentities("ConfirmClassifyAbandonReasonOther"), $close [2] ['label'], 1);
  3193. // arrayreasons
  3194. $arrayreasons [$close [1] ['code']] = $close [1] ['reason'];
  3195. $arrayreasons [$close [2] ['code']] = $close [2] ['reason'];
  3196. // Cree un tableau formulaire
  3197. $formquestion = array('text' => $langs->trans("ConfirmCancelBillQuestion"),array('type' => 'radio','name' => 'close_code','label' => $langs->trans("Reason"),'values' => $arrayreasons),array('type' => 'text','name' => 'close_note','label' => $langs->trans("Comment"),'value' => '','morecss' => 'minwidth300'));
  3198. $formconfirm = $form->formconfirm($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $langs->trans('CancelBill'), $langs->trans('ConfirmCancelBill', $object->ref), 'confirm_canceled', $formquestion, "yes", 1, 250);
  3199. }
  3200. }
  3201. if ($action == 'deletepaiement')
  3202. {
  3203. $payment_id = GETPOST('paiement_id');
  3204. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"].'?id='.$object->id.'&paiement_id='.$payment_id, $langs->trans('DeletePayment'), $langs->trans('ConfirmDeletePayment'), 'confirm_delete_paiement', '', 'no', 1);
  3205. }
  3206. // Confirmation de la suppression d'une ligne produit
  3207. if ($action == 'ask_deleteline') {
  3208. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&lineid=' . $lineid, $langs->trans('DeleteProductLine'), $langs->trans('ConfirmDeleteProductLine'), 'confirm_deleteline', '', 'no', 1);
  3209. }
  3210. // Clone confirmation
  3211. if ($action == 'clone')
  3212. {
  3213. // Create an array for form
  3214. $formquestion = array(
  3215. // 'text' => $langs->trans("ConfirmClone"),
  3216. // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1)
  3217. array('type' => 'other','name' => 'socid','label' => $langs->trans("SelectThirdParty"),'value' => $form->select_company($object->socid, 'socid', '(s.client=1 OR s.client=2 OR s.client=3)', 1)));
  3218. // Paiement incomplet. On demande si motif = escompte ou autre
  3219. $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?facid=' . $object->id, $langs->trans('CloneInvoice'), $langs->trans('ConfirmCloneInvoice', $object->ref), 'confirm_clone', $formquestion, 'yes', 1);
  3220. }
  3221. if (! $formconfirm)
  3222. {
  3223. $parameters = array('lineid' => $lineid);
  3224. $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  3225. if (empty($reshook)) $formconfirm.=$hookmanager->resPrint;
  3226. elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint;
  3227. }
  3228. // Print form confirm
  3229. print $formconfirm;
  3230. // Invoice content
  3231. $linkback = '<a href="' . DOL_URL_ROOT . '/compta/facture/list.php?restore_lastsearch_values=1' . (! empty($socid) ? '&socid=' . $socid : '') . '">' . $langs->trans("BackToList") . '</a>';
  3232. $morehtmlref='<div class="refidno">';
  3233. // Ref customer
  3234. $morehtmlref.=$form->editfieldkey("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', 0, 1);
  3235. $morehtmlref.=$form->editfieldval("RefCustomer", 'ref_client', $object->ref_client, $object, $user->rights->facture->creer, 'string', '', null, null, '', 1);
  3236. // Thirdparty
  3237. $morehtmlref.='<br>'.$langs->trans('ThirdParty') . ' : ' . $object->thirdparty->getNomUrl(1,'customer');
  3238. if (empty($conf->global->MAIN_DISABLE_OTHER_LINK) && $object->thirdparty->id > 0) $morehtmlref.=' (<a href="'.DOL_URL_ROOT.'/compta/facture/list.php?socid='.$object->thirdparty->id.'&search_societe='.urlencode($object->thirdparty->name).'">'.$langs->trans("OtherBills").'</a>)';
  3239. // Project
  3240. if (! empty($conf->projet->enabled))
  3241. {
  3242. $langs->load("projects");
  3243. $morehtmlref.='<br>'.$langs->trans('Project') . ' ';
  3244. if ($user->rights->facture->creer)
  3245. {
  3246. if ($action != 'classify')
  3247. $morehtmlref.='<a href="' . $_SERVER['PHP_SELF'] . '?action=classify&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetProject')) . '</a> : ';
  3248. if ($action == 'classify') {
  3249. //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1);
  3250. $morehtmlref.='<form method="post" action="'.$_SERVER['PHP_SELF'].'?id='.$object->id.'">';
  3251. $morehtmlref.='<input type="hidden" name="action" value="classin">';
  3252. $morehtmlref.='<input type="hidden" name="token" value="'.$_SESSION['newtoken'].'">';
  3253. $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1);
  3254. $morehtmlref.='<input type="submit" class="button valignmiddle" value="'.$langs->trans("Modify").'">';
  3255. $morehtmlref.='</form>';
  3256. } else {
  3257. $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1);
  3258. }
  3259. } else {
  3260. if (! empty($object->fk_project)) {
  3261. $proj = new Project($db);
  3262. $proj->fetch($object->fk_project);
  3263. $morehtmlref.='<a href="'.DOL_URL_ROOT.'/projet/card.php?id=' . $object->fk_project . '" title="' . $langs->trans('ShowProject') . '">';
  3264. $morehtmlref.=$proj->ref;
  3265. $morehtmlref.='</a>';
  3266. } else {
  3267. $morehtmlref.='';
  3268. }
  3269. }
  3270. }
  3271. $morehtmlref.='</div>';
  3272. $object->totalpaye = $totalpaye; // To give a chance to dol_banner_tab to use already paid amount to show correct status
  3273. dol_banner_tab($object, 'ref', $linkback, 1, 'facnumber', 'ref', $morehtmlref, '', 0, '', '');
  3274. print '<div class="fichecenter">';
  3275. print '<div class="fichehalfleft">';
  3276. print '<div class="underbanner clearboth"></div>';
  3277. print '<table class="border" width="100%">';
  3278. // Type
  3279. print '<tr><td class="titlefield">' . $langs->trans('Type') . '</td><td>';
  3280. print $object->getLibType();
  3281. if ($object->type == Facture::TYPE_REPLACEMENT) {
  3282. $facreplaced = new Facture($db);
  3283. $facreplaced->fetch($object->fk_facture_source);
  3284. print ' (' . $langs->transnoentities("ReplaceInvoice", $facreplaced->getNomUrl(1)) . ')';
  3285. }
  3286. if ($object->type == Facture::TYPE_CREDIT_NOTE && !empty($object->fk_facture_source)) {
  3287. $facusing = new Facture($db);
  3288. $facusing->fetch($object->fk_facture_source);
  3289. print ' (' . $langs->transnoentities("CorrectInvoice", $facusing->getNomUrl(1)) . ')';
  3290. }
  3291. $facidavoir = $object->getListIdAvoirFromInvoice();
  3292. if (count($facidavoir) > 0) {
  3293. print ' (' . $langs->transnoentities("InvoiceHasAvoir");
  3294. $i = 0;
  3295. foreach ($facidavoir as $id) {
  3296. if ($i == 0)
  3297. print ' ';
  3298. else
  3299. print ',';
  3300. $facavoir = new Facture($db);
  3301. $facavoir->fetch($id);
  3302. print $facavoir->getNomUrl(1);
  3303. }
  3304. print ')';
  3305. }
  3306. if ($objectidnext > 0) {
  3307. $facthatreplace = new Facture($db);
  3308. $facthatreplace->fetch($objectidnext);
  3309. print ' (' . $langs->transnoentities("ReplacedByInvoice", $facthatreplace->getNomUrl(1)) . ')';
  3310. }
  3311. if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT) {
  3312. $discount = new DiscountAbsolute($db);
  3313. $result = $discount->fetch(0, $object->id);
  3314. if ($result > 0){
  3315. print '. '.$langs->trans("CreditNoteConvertedIntoDiscount", $object->getLibType(1), $discount->getNomUrl(1, 'discount')).'<br>';
  3316. }
  3317. }
  3318. print '</td></tr>';
  3319. // Relative and absolute discounts
  3320. print '<!-- Discounts --><tr><td>' . $langs->trans('Discounts');
  3321. print '</td><td>';
  3322. $thirdparty = $soc;
  3323. $discount_type = 0;
  3324. $backtopage = urlencode($_SERVER["PHP_SELF"] . '?facid=' . $object->id);
  3325. include DOL_DOCUMENT_ROOT.'/core/tpl/object_discounts.tpl.php';
  3326. print '</td></tr>';
  3327. // Date invoice
  3328. print '<tr><td>';
  3329. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3330. print $langs->trans('DateInvoice');
  3331. print '</td>';
  3332. if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editinvoicedate' && ! empty($object->brouillon) && $user->rights->facture->creer && empty($conf->global->FAC_FORCE_DATE_VALIDATION))
  3333. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editinvoicedate&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
  3334. print '</tr></table>';
  3335. print '</td><td>';
  3336. if ($object->type != Facture::TYPE_CREDIT_NOTE) {
  3337. if ($action == 'editinvoicedate') {
  3338. $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date, 'invoicedate');
  3339. } else {
  3340. print dol_print_date($object->date, 'day');
  3341. }
  3342. } else {
  3343. print dol_print_date($object->date, 'day');
  3344. }
  3345. print '</td>';
  3346. print '</tr>';
  3347. if (! empty($conf->global->INVOICE_POINTOFTAX_DATE))
  3348. {
  3349. // Date invoice
  3350. print '<tr><td>';
  3351. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3352. print $langs->trans('DatePointOfTax');
  3353. print '</td>';
  3354. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editdate_pointoftax&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
  3355. print '</tr></table>';
  3356. print '</td><td>';
  3357. if ($action == 'editdate_pointoftax') {
  3358. $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date_pointoftax, 'date_pointoftax');
  3359. } else {
  3360. print dol_print_date($object->date_pointoftax, 'day');
  3361. }
  3362. print '</td></tr>';
  3363. }
  3364. // Payment term
  3365. print '<tr><td>';
  3366. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3367. print $langs->trans('PaymentConditionsShort');
  3368. print '</td>';
  3369. if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editconditions' && $user->rights->facture->creer)
  3370. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editconditions&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetConditions'), 1) . '</a></td>';
  3371. print '</tr></table>';
  3372. print '</td><td>';
  3373. if ($object->type != Facture::TYPE_CREDIT_NOTE)
  3374. {
  3375. if ($action == 'editconditions') {
  3376. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'cond_reglement_id');
  3377. } else {
  3378. $form->form_conditions_reglement($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->cond_reglement_id, 'none');
  3379. }
  3380. } else {
  3381. print '&nbsp;';
  3382. }
  3383. print '</td></tr>';
  3384. // Date payment term
  3385. print '<tr><td>';
  3386. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3387. print $langs->trans('DateMaxPayment');
  3388. print '</td>';
  3389. if ($object->type != Facture::TYPE_CREDIT_NOTE && $action != 'editpaymentterm' && $user->rights->facture->creer)
  3390. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editpaymentterm&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetDate'), 1) . '</a></td>';
  3391. print '</tr></table>';
  3392. print '</td><td>';
  3393. if ($object->type != Facture::TYPE_CREDIT_NOTE)
  3394. {
  3395. if ($action == 'editpaymentterm') {
  3396. $form->form_date($_SERVER['PHP_SELF'] . '?facid=' . $object->id, $object->date_lim_reglement, 'paymentterm');
  3397. } else {
  3398. print dol_print_date($object->date_lim_reglement, 'day');
  3399. if ($object->hasDelay()) {
  3400. print img_warning($langs->trans('Late'));
  3401. }
  3402. }
  3403. } else {
  3404. print '&nbsp;';
  3405. }
  3406. print '</td></tr>';
  3407. // Payment mode
  3408. print '<tr><td>';
  3409. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3410. print $langs->trans('PaymentMode');
  3411. print '</td>';
  3412. if ($action != 'editmode' && $user->rights->facture->creer)
  3413. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmode&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetMode'), 1) . '</a></td>';
  3414. print '</tr></table>';
  3415. print '</td><td>';
  3416. if ($action == 'editmode')
  3417. {
  3418. $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'mode_reglement_id', 'CRDT');
  3419. }
  3420. else
  3421. {
  3422. $form->form_modes_reglement($_SERVER['PHP_SELF'].'?facid='.$object->id, $object->mode_reglement_id, 'none', 'CRDT');
  3423. }
  3424. print '</td></tr>';
  3425. // Multicurrency
  3426. if (! empty($conf->multicurrency->enabled))
  3427. {
  3428. // Multicurrency code
  3429. print '<tr>';
  3430. print '<td>';
  3431. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3432. print fieldLabel('Currency','multicurrency_code');
  3433. print '</td>';
  3434. if ($action != 'editmulticurrencycode' && ! empty($object->brouillon))
  3435. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencycode&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
  3436. print '</tr></table>';
  3437. print '</td><td>';
  3438. if ($action == 'editmulticurrencycode') {
  3439. $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'multicurrency_code');
  3440. } else {
  3441. $form->form_multicurrency_code($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_code, 'none');
  3442. }
  3443. print '</td></tr>';
  3444. print '<tr>';
  3445. print '<td>';
  3446. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3447. print fieldLabel('CurrencyRate','multicurrency_tx');
  3448. print '</td>';
  3449. if ($action != 'editmulticurrencyrate' && ! empty($object->brouillon) && $object->multicurrency_code && $object->multicurrency_code != $conf->currency)
  3450. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editmulticurrencyrate&amp;id=' . $object->id . '">' . img_edit($langs->transnoentitiesnoconv('SetMultiCurrencyCode'), 1) . '</a></td>';
  3451. print '</tr></table>';
  3452. print '</td><td>';
  3453. if ($action == 'editmulticurrencyrate' || $action == 'actualizemulticurrencyrate') {
  3454. if($action == 'actualizemulticurrencyrate') {
  3455. list($object->fk_multicurrency, $object->multicurrency_tx) = MultiCurrency::getIdAndTxFromCode($object->db, $object->multicurrency_code);
  3456. }
  3457. $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'multicurrency_tx', $object->multicurrency_code);
  3458. } else {
  3459. $form->form_multicurrency_rate($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->multicurrency_tx, 'none', $object->multicurrency_code);
  3460. if($object->statut == $object::STATUS_DRAFT && $object->multicurrency_code && $object->multicurrency_code != $conf->currency) {
  3461. print '<div class="inline-block"> &nbsp; &nbsp; &nbsp; &nbsp; ';
  3462. print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=actualizemulticurrencyrate">'.$langs->trans("ActualizeCurrency").'</a>';
  3463. print '</div>';
  3464. }
  3465. }
  3466. print '</td></tr>';
  3467. }
  3468. // Bank Account
  3469. print '<tr><td class="nowrap">';
  3470. print '<table width="100%" class="nobordernopadding"><tr><td class="nowrap">';
  3471. print $langs->trans('BankAccount');
  3472. print '<td>';
  3473. if (($action != 'editbankaccount') && $user->rights->facture->creer)
  3474. print '<td align="right"><a href="'.$_SERVER["PHP_SELF"].'?action=editbankaccount&amp;id='.$object->id.'">'.img_edit($langs->trans('SetBankAccount'),1).'</a></td>';
  3475. print '</tr></table>';
  3476. print '</td><td>';
  3477. if ($action == 'editbankaccount')
  3478. {
  3479. $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'fk_account', 1);
  3480. }
  3481. else
  3482. {
  3483. $form->formSelectAccount($_SERVER['PHP_SELF'].'?id='.$object->id, $object->fk_account, 'none');
  3484. }
  3485. print "</td>";
  3486. print '</tr>';
  3487. // Incoterms
  3488. if (!empty($conf->incoterm->enabled))
  3489. {
  3490. print '<tr><td>';
  3491. print '<table width="100%" class="nobordernopadding"><tr><td>';
  3492. print $langs->trans('IncotermLabel');
  3493. print '<td><td align="right">';
  3494. if ($user->rights->facture->creer) print '<a href="'.DOL_URL_ROOT.'/compta/facture/card.php?facid='.$object->id.'&action=editincoterm">'.img_edit().'</a>';
  3495. else print '&nbsp;';
  3496. print '</td></tr></table>';
  3497. print '</td>';
  3498. print '<td>';
  3499. if ($action != 'editincoterm')
  3500. {
  3501. print $form->textwithpicto($object->display_incoterms(), $object->libelle_incoterms, 1);
  3502. }
  3503. else
  3504. {
  3505. print $form->select_incoterms((!empty($object->fk_incoterms) ? $object->fk_incoterms : ''), (!empty($object->location_incoterms)?$object->location_incoterms:''), $_SERVER['PHP_SELF'].'?id='.$object->id);
  3506. }
  3507. print '</td></tr>';
  3508. }
  3509. // Other attributes
  3510. $cols = 2;
  3511. include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php';
  3512. print '</table>';
  3513. print '</div>';
  3514. print '<div class="fichehalfright">';
  3515. print '<div class="ficheaddleft">';
  3516. print '<div class="underbanner clearboth"></div>';
  3517. print '<table class="border centpercent">';
  3518. if (!empty($conf->multicurrency->enabled) && ($object->multicurrency_code != $conf->currency))
  3519. {
  3520. // Multicurrency Amount HT
  3521. print '<tr><td class="titlefieldmiddle">' . fieldLabel('MulticurrencyAmountHT','multicurrency_total_ht') . '</td>';
  3522. print '<td class="nowrap amountcard">' . price($object->multicurrency_total_ht, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  3523. print '</tr>';
  3524. // Multicurrency Amount VAT
  3525. print '<tr><td>' . fieldLabel('MulticurrencyAmountVAT','multicurrency_total_tva') . '</td>';
  3526. print '<td class="nowrap amountcard">' . price($object->multicurrency_total_tva, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  3527. print '</tr>';
  3528. // Multicurrency Amount TTC
  3529. print '<tr><td>' . fieldLabel('MulticurrencyAmountTTC','multicurrency_total_ttc') . '</td>';
  3530. print '<td class="nowrap amountcard">' . price($object->multicurrency_total_ttc, '', $langs, 0, - 1, - 1, (!empty($object->multicurrency_code) ? $object->multicurrency_code : $conf->currency)) . '</td>';
  3531. print '</tr>';
  3532. }
  3533. // Amount
  3534. print '<tr><td class="titlefieldmiddle">' . $langs->trans('AmountHT') . '</td>';
  3535. print '<td class="nowrap amountcard">' . price($object->total_ht, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  3536. // Vat
  3537. print '<tr><td>' . $langs->trans('AmountVAT') . '</td><td colspan="3" class="nowrap amountcard">' . price($object->total_tva, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  3538. print '</tr>';
  3539. // Amount Local Taxes
  3540. if (($mysoc->localtax1_assuj == "1" && $mysoc->useLocalTax(1)) || $object->total_localtax1 != 0) // Localtax1
  3541. {
  3542. print '<tr><td>' . $langs->transcountry("AmountLT1", $mysoc->country_code) . '</td>';
  3543. print '<td class="nowrap amountcard">' . price($object->total_localtax1, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  3544. }
  3545. if (($mysoc->localtax2_assuj == "1" && $mysoc->useLocalTax(2)) || $object->total_localtax2 != 0) // Localtax2
  3546. {
  3547. print '<tr><td>' . $langs->transcountry("AmountLT2", $mysoc->country_code) . '</td>';
  3548. print '<td class=nowrap amountcard">' . price($object->total_localtax2, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  3549. }
  3550. // Revenue stamp
  3551. if ($selleruserevenustamp) // Test company use revenue stamp
  3552. {
  3553. print '<tr><td>';
  3554. print '<table class="nobordernopadding" width="100%"><tr><td>';
  3555. print $langs->trans('RevenueStamp');
  3556. print '</td>';
  3557. if ($action != 'editrevenuestamp' && ! empty($object->brouillon) && $user->rights->facture->creer)
  3558. {
  3559. print '<td align="right"><a href="' . $_SERVER["PHP_SELF"] . '?action=editrevenuestamp&amp;facid=' . $object->id . '">' . img_edit($langs->trans('SetRevenuStamp'), 1) . '</a></td>';
  3560. }
  3561. print '</tr></table>';
  3562. print '</td><td>';
  3563. if ($action == 'editrevenuestamp') {
  3564. print '<form action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . '" method="post">';
  3565. print '<input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">';
  3566. print '<input type="hidden" name="action" value="setrevenuestamp">';
  3567. print '<input type="hidden" name="revenuestamp" id="revenuestamp_val" value="'.price2num($object->revenuestamp).'">';
  3568. print $formother->select_revenue_stamp('', 'revenuestamp_type', $mysoc->country_code);
  3569. print ' &rarr; <span id="revenuestamp_span"></span>';
  3570. print ' <input type="submit" class="button" value="' . $langs->trans('Modify') . '">';
  3571. print '</form>';
  3572. print " <script>
  3573. $(document).ready(function(){
  3574. js_recalculate_revenuestamp();
  3575. $('select[name=revenuestamp_type]').on('change',function(){
  3576. js_recalculate_revenuestamp();
  3577. });
  3578. });
  3579. function js_recalculate_revenuestamp(){
  3580. var valselected = $('select[name=revenuestamp_type]').val();
  3581. console.log('Calculate revenue stamp from '+valselected);
  3582. var revenue = 0;
  3583. if (valselected.indexOf('%') == -1)
  3584. {
  3585. revenue = valselected;
  3586. }
  3587. else
  3588. {
  3589. var revenue_type = parseFloat(valselected);
  3590. var amount_net = ".round($object->total_ht, 2).";
  3591. revenue = revenue_type * amount_net / 100;
  3592. revenue = revenue.toFixed(2);
  3593. }
  3594. $('#revenuestamp_val').val(revenue);
  3595. $('#revenuestamp_span').html(revenue);
  3596. }
  3597. </script>";
  3598. } else {
  3599. print price($object->revenuestamp, 1, '', 1, - 1, - 1, $conf->currency);
  3600. }
  3601. print '</td></tr>';
  3602. }
  3603. // Total with tax
  3604. print '<tr><td>' . $langs->trans('AmountTTC') . '</td><td class="nowrap amountcard">' . price($object->total_ttc, 1, '', 1, - 1, - 1, $conf->currency) . '</td></tr>';
  3605. print '</table>';
  3606. $sign = 1;
  3607. if ($object->type == Facture::TYPE_CREDIT_NOTE) $sign = - 1;
  3608. $nbrows = 8;
  3609. $nbcols = 3;
  3610. if (! empty($conf->projet->enabled))
  3611. $nbrows ++;
  3612. if (! empty($conf->banque->enabled)) {
  3613. $nbrows ++;
  3614. $nbcols ++;
  3615. }
  3616. if ($mysoc->localtax1_assuj == "1" || $object->total_localtax1 != 0)
  3617. $nbrows ++;
  3618. if ($mysoc->localtax2_assuj == "1" || $object->total_localtax2 != 0)
  3619. $nbrows ++;
  3620. if ($selleruserevenustamp)
  3621. $nbrows ++;
  3622. if (! empty($conf->multicurrency->enabled))
  3623. $nbrows += 5;
  3624. if (! empty($conf->incoterm->enabled))
  3625. $nbrows += 1;
  3626. // List of previous situation invoices
  3627. if (($object->situation_cycle_ref > 0) && ! empty($conf->global->INVOICE_USE_SITUATION))
  3628. {
  3629. print '<table class="noborder situationstable" width="100%">';
  3630. print '<tr class="liste_titre">';
  3631. print '<td>' . $langs->trans('ListOfSituationInvoices') . '</td>';
  3632. print '<td></td>';
  3633. print '<td align="center">' . $langs->trans('Situation') . '</td>';
  3634. if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
  3635. print '<td align="right">' . $langs->trans('AmountHT') . '</td>';
  3636. print '<td align="right">' . $langs->trans('AmountTTC') . '</td>';
  3637. print '<td width="18">&nbsp;</td>';
  3638. print '</tr>';
  3639. $total_prev_ht = $total_prev_ttc = 0;
  3640. $total_global_ht = $total_global_ttc = 0;
  3641. if (count($object->tab_previous_situation_invoice) > 0) {
  3642. // List of previous invoices
  3643. $current_situation_counter = array();
  3644. foreach ($object->tab_previous_situation_invoice as $prev_invoice) {
  3645. $totalpaye = $prev_invoice->getSommePaiement();
  3646. $total_prev_ht += $prev_invoice->total_ht;
  3647. $total_prev_ttc += $prev_invoice->total_ttc;
  3648. $current_situation_counter[] = (($prev_invoice->type == Facture::TYPE_CREDIT_NOTE)?-1:1) * $prev_invoice->situation_counter;
  3649. print '<tr class="oddeven">';
  3650. print '<td>' . $prev_invoice->getNomUrl(1) . '</td>';
  3651. print '<td></td>';
  3652. print '<td align="center" >'.(($prev_invoice->type == Facture::TYPE_CREDIT_NOTE)?$langs->trans('situationInvoiceShortcode_AS'):$langs->trans('situationInvoiceShortcode_S')) . $prev_invoice->situation_counter.'</td>';
  3653. if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
  3654. print '<td align="right">' . price($prev_invoice->total_ht) . '</td>';
  3655. print '<td align="right">' . price($prev_invoice->total_ttc) . '</td>';
  3656. print '<td align="right">' . $prev_invoice->getLibStatut(3, $totalpaye) . '</td>';
  3657. print '</tr>';
  3658. }
  3659. }
  3660. $total_global_ht += $total_prev_ht ;
  3661. $total_global_ttc += $total_prev_ttc ;
  3662. $total_global_ht += $object->total_ht;
  3663. $total_global_ttc += $object->total_ttc;
  3664. $current_situation_counter[] = (($object->type == Facture::TYPE_CREDIT_NOTE)?-1:1) * $object->situation_counter;
  3665. print '<tr class="oddeven">';
  3666. print '<td>' . $object->getNomUrl(1) . '</td>';
  3667. print '<td></td>';
  3668. print '<td align="center">'.(($object->type == Facture::TYPE_CREDIT_NOTE)?$langs->trans('situationInvoiceShortcode_AS'):$langs->trans('situationInvoiceShortcode_S')) . $object->situation_counter.'</td>';
  3669. if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
  3670. print '<td align="right">' . price($object->total_ht) . '</td>';
  3671. print '<td align="right">' . price($object->total_ttc) . '</td>';
  3672. print '<td align="right">' . $object->getLibStatut(3, $object->getSommePaiement()) . '</td>';
  3673. print '</tr>';
  3674. print '<tr class="oddeven">';
  3675. print '<td colspan="2" align="left"><b>' . $langs->trans('CurrentSituationTotal') . '</b></td>';
  3676. print '<td>';
  3677. $i =0;
  3678. foreach ($current_situation_counter as $sit)
  3679. {
  3680. $curSign = $sit>0?'+':'-';
  3681. $curType = $sit>0?$langs->trans('situationInvoiceShortcode_S'):$langs->trans('situationInvoiceShortcode_AS');
  3682. if($i>0) print ' '.$curSign.' ';
  3683. print $curType . abs($sit);
  3684. $i++;
  3685. }
  3686. print '</td>';
  3687. if (! empty($conf->banque->enabled)) print '<td></td>';
  3688. print '<td align="right"><b>' . price($total_global_ht) . '</b></td>';
  3689. print '<td align="right"><b>' . price($total_global_ttc) . '</b></td>';
  3690. print '<td width="18">&nbsp;</td>';
  3691. print '</tr>';
  3692. if (count($object->tab_next_situation_invoice) > 0) {
  3693. // List of next invoices
  3694. /*print '<tr class="liste_titre">';
  3695. print '<td>' . $langs->trans('ListOfNextSituationInvoices') . '</td>';
  3696. print '<td></td>';
  3697. print '<td></td>';
  3698. if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
  3699. print '<td align="right">' . $langs->trans('AmountHT') . '</td>';
  3700. print '<td align="right">' . $langs->trans('AmountTTC') . '</td>';
  3701. print '<td width="18">&nbsp;</td>';
  3702. print '</tr>';*/
  3703. $total_next_ht = $total_next_ttc = 0;
  3704. foreach ($object->tab_next_situation_invoice as $next_invoice) {
  3705. $totalpaye = $next_invoice->getSommePaiement();
  3706. $total_next_ht += $next_invoice->total_ht;
  3707. $total_next_ttc += $next_invoice->total_ttc;
  3708. print '<tr class="oddeven">';
  3709. print '<td>' . $next_invoice->getNomUrl(1) . '</td>';
  3710. print '<td></td>';
  3711. print '<td align="center">'.(($next_invoice->type == Facture::TYPE_CREDIT_NOTE)?$langs->trans('situationInvoiceShortcode_AS'):$langs->trans('situationInvoiceShortcode_S')) . $next_invoice->situation_counter.'</td>';
  3712. if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
  3713. print '<td align="right">' . price($next_invoice->total_ht) . '</td>';
  3714. print '<td align="right">' . price($next_invoice->total_ttc) . '</td>';
  3715. print '<td align="right">' . $next_invoice->getLibStatut(3, $totalpaye) . '</td>';
  3716. print '</tr>';
  3717. }
  3718. $total_global_ht += $total_next_ht;
  3719. $total_global_ttc += $total_next_ttc;
  3720. print '<tr class="oddeven">';
  3721. print '<td colspan="3" align="right"></td>';
  3722. if (! empty($conf->banque->enabled)) print '<td align="right"></td>';
  3723. print '<td align="right"><b>' . price($total_global_ht) . '</b></td>';
  3724. print '<td align="right"><b>' . price($total_global_ttc) . '</b></td>';
  3725. print '<td width="18">&nbsp;</td>';
  3726. print '</tr>';
  3727. }
  3728. print '</table>';
  3729. }
  3730. // List of payments already done
  3731. print '<div class="div-table-responsive-no-min">';
  3732. print '<table class="noborder paymenttable" width="100%">';
  3733. print '<tr class="liste_titre">';
  3734. print '<td class="liste_titre">' . ($object->type == Facture::TYPE_CREDIT_NOTE ? $langs->trans("PaymentsBack") : $langs->trans('Payments')) . '</td>';
  3735. print '<td class="liste_titre">' . $langs->trans('Date') . '</td>';
  3736. print '<td class="liste_titre">' . $langs->trans('Type') . '</td>';
  3737. if (! empty($conf->banque->enabled)) {
  3738. print '<td class="liste_titre" align="right">' . $langs->trans('BankAccount') . '</td>';
  3739. }
  3740. print '<td class="liste_titre" align="right">' . $langs->trans('Amount') . '</td>';
  3741. print '<td class="liste_titre" width="18">&nbsp;</td>';
  3742. print '</tr>';
  3743. // Payments already done (from payment on this invoice)
  3744. $sql = 'SELECT p.datep as dp, p.ref, p.num_paiement, p.rowid, p.fk_bank,';
  3745. $sql .= ' c.code as payment_code, c.libelle as payment_label,';
  3746. $sql .= ' pf.amount,';
  3747. $sql .= ' ba.rowid as baid, ba.ref as baref, ba.label, ba.number as banumber, ba.account_number, ba.fk_accountancy_journal';
  3748. $sql .= ' FROM ' . MAIN_DB_PREFIX . 'paiement_facture as pf, ' . MAIN_DB_PREFIX . 'paiement as p';
  3749. $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'c_paiement as c ON p.fk_paiement = c.id' ;
  3750. $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'bank as b ON p.fk_bank = b.rowid';
  3751. $sql .= ' LEFT JOIN ' . MAIN_DB_PREFIX . 'bank_account as ba ON b.fk_account = ba.rowid';
  3752. $sql .= ' WHERE pf.fk_facture = ' . $object->id . ' AND pf.fk_paiement = p.rowid';
  3753. $sql .= ' AND p.entity IN (' . getEntity('facture').')';
  3754. $sql .= ' ORDER BY p.datep, p.tms';
  3755. $result = $db->query($sql);
  3756. if ($result) {
  3757. $num = $db->num_rows($result);
  3758. $i = 0;
  3759. // if ($object->type != 2)
  3760. // {
  3761. if ($num > 0) {
  3762. while ($i < $num) {
  3763. $objp = $db->fetch_object($result);
  3764. $paymentstatic->id = $objp->rowid;
  3765. $paymentstatic->datepaye = $db->jdate($objp->dp);
  3766. $paymentstatic->ref = $objp->ref;
  3767. $paymentstatic->num_paiement = $objp->num_paiement;
  3768. $paymentstatic->payment_code = $objp->payment_code;
  3769. print '<tr class="oddeven"><td>';
  3770. print $paymentstatic->getNomUrl(1);
  3771. print '</td>';
  3772. print '<td>' . dol_print_date($db->jdate($objp->dp), 'day') . '</td>';
  3773. $label = ($langs->trans("PaymentType" . $objp->payment_code) != ("PaymentType" . $objp->payment_code)) ? $langs->trans("PaymentType" . $objp->payment_code) : $objp->payment_label;
  3774. print '<td>' . $label . ' ' . $objp->num_paiement . '</td>';
  3775. if (! empty($conf->banque->enabled))
  3776. {
  3777. $bankaccountstatic->id = $objp->baid;
  3778. $bankaccountstatic->ref = $objp->baref;
  3779. $bankaccountstatic->label = $objp->baref;
  3780. $bankaccountstatic->number = $objp->banumber;
  3781. if (! empty($conf->accounting->enabled)) {
  3782. $bankaccountstatic->account_number = $objp->account_number;
  3783. $accountingjournal = new AccountingJournal($db);
  3784. $accountingjournal->fetch($objp->fk_accountancy_journal);
  3785. $bankaccountstatic->accountancy_journal = $accountingjournal->getNomUrl(0,1,1,'',1);
  3786. }
  3787. print '<td align="right">';
  3788. if ($bankaccountstatic->id)
  3789. print $bankaccountstatic->getNomUrl(1, 'transactions');
  3790. print '</td>';
  3791. }
  3792. print '<td align="right">' . price($sign * $objp->amount) . '</td>';
  3793. print '<td align="center">';
  3794. if ($object->statut == Facture::STATUS_VALIDATED && $object->paye == 0 && $user->societe_id == 0)
  3795. {
  3796. print '<a href="'.$_SERVER["PHP_SELF"].'?id='.$object->id.'&action=deletepaiement&paiement_id='.$objp->rowid.'">';
  3797. print img_delete();
  3798. print '</a>';
  3799. }
  3800. print '</td>';
  3801. print '</tr>';
  3802. $i ++;
  3803. }
  3804. }
  3805. /*else {
  3806. print '<tr class="oddeven"><td colspan="' . $nbcols . '" class="opacitymedium">' . $langs->trans("None") . '</td><td></td><td></td></tr>';
  3807. }*/
  3808. // }
  3809. $db->free($result);
  3810. } else {
  3811. dol_print_error($db);
  3812. }
  3813. if ($object->type != Facture::TYPE_CREDIT_NOTE) {
  3814. // Total already paid
  3815. print '<tr><td colspan="' . $nbcols . '" align="right">';
  3816. if ($object->type != Facture::TYPE_DEPOSIT)
  3817. print $langs->trans('AlreadyPaidNoCreditNotesNoDeposits');
  3818. else
  3819. print $langs->trans('AlreadyPaid');
  3820. print ' :</td><td align="right"'.(($totalpaye > 0)?' class="amountalreadypaid"':'').'>' . price($totalpaye) . '</td><td>&nbsp;</td></tr>';
  3821. $resteapayeraffiche = $resteapayer;
  3822. $cssforamountpaymentcomplete = 'amountpaymentcomplete';
  3823. // Loop on each credit note or deposit amount applied
  3824. $creditnoteamount = 0;
  3825. $depositamount = 0;
  3826. $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
  3827. $sql .= " re.description, re.fk_facture_source";
  3828. $sql .= " FROM " . MAIN_DB_PREFIX . "societe_remise_except as re";
  3829. $sql .= " WHERE fk_facture = " . $object->id;
  3830. $resql = $db->query($sql);
  3831. if ($resql) {
  3832. $num = $db->num_rows($resql);
  3833. $i = 0;
  3834. $invoice = new Facture($db);
  3835. while ($i < $num) {
  3836. $obj = $db->fetch_object($resql);
  3837. $invoice->fetch($obj->fk_facture_source);
  3838. print '<tr><td colspan="' . $nbcols . '" align="right">';
  3839. if ($invoice->type == Facture::TYPE_CREDIT_NOTE)
  3840. print $langs->trans("CreditNote") . ' ';
  3841. if ($invoice->type == Facture::TYPE_DEPOSIT)
  3842. print $langs->trans("Deposit") . ' ';
  3843. print $invoice->getNomUrl(0);
  3844. print ' :</td>';
  3845. print '<td align="right">' . price($obj->amount_ttc) . '</td>';
  3846. print '<td align="right">';
  3847. print '<a href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&action=unlinkdiscount&discountid=' . $obj->rowid . '">' . img_delete() . '</a>';
  3848. print '</td></tr>';
  3849. $i ++;
  3850. if ($invoice->type == Facture::TYPE_CREDIT_NOTE)
  3851. $creditnoteamount += $obj->amount_ttc;
  3852. if ($invoice->type == Facture::TYPE_DEPOSIT)
  3853. $depositamount += $obj->amount_ttc;
  3854. }
  3855. } else {
  3856. dol_print_error($db);
  3857. }
  3858. // Paye partiellement 'escompte'
  3859. if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'discount_vat') {
  3860. print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
  3861. print $form->textwithpicto($langs->trans("Discount") . ':', $langs->trans("HelpEscompte"), - 1);
  3862. print '</td><td align="right">' . price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye, 'MT')) . '</td><td>&nbsp;</td></tr>';
  3863. $resteapayeraffiche = 0;
  3864. $cssforamountpaymentcomplete = 'amountpaymentneutral';
  3865. }
  3866. // Paye partiellement ou Abandon 'badcustomer'
  3867. if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'badcustomer') {
  3868. print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
  3869. print $form->textwithpicto($langs->trans("Abandoned") . ':', $langs->trans("HelpAbandonBadCustomer"), - 1);
  3870. print '</td><td align="right">' . price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye, 'MT')) . '</td><td>&nbsp;</td></tr>';
  3871. // $resteapayeraffiche=0;
  3872. $cssforamountpaymentcomplete = 'amountpaymentneutral';
  3873. }
  3874. // Paye partiellement ou Abandon 'product_returned'
  3875. if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'product_returned') {
  3876. print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
  3877. print $form->textwithpicto($langs->trans("ProductReturned") . ':', $langs->trans("HelpAbandonProductReturned"), - 1);
  3878. print '</td><td align="right">' . price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye, 'MT')) . '</td><td>&nbsp;</td></tr>';
  3879. $resteapayeraffiche = 0;
  3880. $cssforamountpaymentcomplete = 'amountpaymentneutral';
  3881. }
  3882. // Paye partiellement ou Abandon 'abandon'
  3883. if (($object->statut == Facture::STATUS_CLOSED || $object->statut == Facture::STATUS_ABANDONED) && $object->close_code == 'abandon') {
  3884. print '<tr><td colspan="' . $nbcols . '" align="right" class="nowrap">';
  3885. $text = $langs->trans("HelpAbandonOther");
  3886. if ($object->close_note)
  3887. $text .= '<br><br><b>' . $langs->trans("Reason") . '</b>:' . $object->close_note;
  3888. print $form->textwithpicto($langs->trans("Abandoned") . ':', $text, - 1);
  3889. print '</td><td align="right">' . price(price2num($object->total_ttc - $creditnoteamount - $depositamount - $totalpaye, 'MT')) . '</td><td>&nbsp;</td></tr>';
  3890. $resteapayeraffiche = 0;
  3891. $cssforamountpaymentcomplete = 'amountpaymentneutral';
  3892. }
  3893. // Billed
  3894. print '<tr><td colspan="' . $nbcols . '" align="right">' . $langs->trans("Billed") . ' :</td><td align="right">' . price($object->total_ttc) . '</td><td>&nbsp;</td></tr>';
  3895. // Remainder to pay
  3896. print '<tr><td colspan="' . $nbcols . '" align="right">';
  3897. if ($resteapayeraffiche >= 0)
  3898. print $langs->trans('RemainderToPay');
  3899. else
  3900. print $langs->trans('ExcessReceived');
  3901. print ' :</td>';
  3902. print '<td align="right"'.($resteapayeraffiche?' class="amountremaintopay"':(' class="'.$cssforamountpaymentcomplete.'"')).'>' . price($resteapayeraffiche) . '</td>';
  3903. print '<td class="nowrap">&nbsp;</td></tr>';
  3904. }
  3905. else // Credit note
  3906. {
  3907. $cssforamountpaymentcomplete='amountpaymentneutral';
  3908. // Total already paid back
  3909. print '<tr><td colspan="' . $nbcols . '" align="right">';
  3910. print $langs->trans('AlreadyPaidBack');
  3911. print ' :</td><td align="right">' . price($sign * $totalpaye) . '</td><td>&nbsp;</td></tr>';
  3912. // Billed
  3913. print '<tr><td colspan="' . $nbcols . '" align="right">' . $langs->trans("Billed") . ' :</td><td align="right">' . price($sign * $object->total_ttc) . '</td><td>&nbsp;</td></tr>';
  3914. // Remainder to pay back
  3915. print '<tr><td colspan="' . $nbcols . '" align="right">';
  3916. if ($resteapayeraffiche <= 0)
  3917. print $langs->trans('RemainderToPayBack');
  3918. else
  3919. print $langs->trans('ExcessPaid');
  3920. print ' :</td>';
  3921. print '<td align="right"'.($resteapayeraffiche?' class="amountremaintopayback"':(' class="'.$cssforamountpaymentcomplete.'"')).'>' . price($sign * $resteapayeraffiche) . '</td>';
  3922. print '<td class="nowrap">&nbsp;</td></tr>';
  3923. // Sold credit note
  3924. // print '<tr><td colspan="'.$nbcols.'" align="right">'.$langs->trans('TotalTTC').' :</td>';
  3925. // print '<td align="right" style="border: 1px solid;" bgcolor="#f0f0f0"><b>'.price($sign *
  3926. // $object->total_ttc).'</b></td><td>&nbsp;</td></tr>';
  3927. }
  3928. print '</table>';
  3929. print '</div>';
  3930. // Margin Infos
  3931. if (! empty($conf->margin->enabled)) {
  3932. $formmargin->displayMarginInfos($object);
  3933. }
  3934. print '</div>';
  3935. print '</div>';
  3936. print '</div>';
  3937. print '<div class="clearboth"></div><br>';
  3938. if (! empty($conf->global->MAIN_DISABLE_CONTACTS_TAB)) {
  3939. $blocname = 'contacts';
  3940. $title = $langs->trans('ContactsAddresses');
  3941. include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
  3942. }
  3943. if (! empty($conf->global->MAIN_DISABLE_NOTES_TAB)) {
  3944. $blocname = 'notes';
  3945. $title = $langs->trans('Notes');
  3946. include DOL_DOCUMENT_ROOT . '/core/tpl/bloc_showhide.tpl.php';
  3947. }
  3948. // Lines
  3949. $result = $object->getLinesArray();
  3950. // Show global modifiers
  3951. if (! empty($conf->global->INVOICE_USE_SITUATION))
  3952. {
  3953. if ($object->situation_cycle_ref && $object->statut == 0) {
  3954. print '<div class="div-table-responsive">';
  3955. print '<form name="updatealllines" id="updatealllines" action="' . $_SERVER['PHP_SELF'] . '?id=' . $object->id . '#updatealllines" method="POST">';
  3956. print '<input type="hidden" name="token" value="' . $_SESSION['newtoken'] . '" />';
  3957. print '<input type="hidden" name="action" value="updatealllines" />';
  3958. print '<input type="hidden" name="id" value="' . $object->id . '" />';
  3959. print '<table id="tablelines_all_progress" class="noborder noshadow" width="100%">';
  3960. print '<tr class="liste_titre nodrag nodrop">';
  3961. if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
  3962. print '<td align="center" width="5">&nbsp;</td>';
  3963. }
  3964. print '<td>' . $langs->trans('ModifyAllLines') . '</td>';
  3965. print '<td align="right" width="50">&nbsp;</td>';
  3966. print '<td align="right" width="80">&nbsp;</td>';
  3967. if ($inputalsopricewithtax) print '<td align="right" width="80">&nbsp;</td>';
  3968. print '<td align="right" width="50">&nbsp</td>';
  3969. print '<td align="right" width="50">&nbsp</td>';
  3970. print '<td align="right" width="50">' . $langs->trans('Progress') . '</td>';
  3971. if (! empty($conf->margin->enabled) && empty($user->societe_id))
  3972. {
  3973. print '<td align="right" class="margininfos" width="80">&nbsp;</td>';
  3974. if ((! empty($conf->global->DISPLAY_MARGIN_RATES) || ! empty($conf->global->DISPLAY_MARK_RATES)) && $user->rights->margins->liretous) {
  3975. print '<td align="right" class="margininfos" width="50">&nbsp;</td>';
  3976. }
  3977. }
  3978. print '<td align="right" width="50">&nbsp;</td>';
  3979. print '<td>&nbsp;</td>';
  3980. print '<td width="10">&nbsp;</td>';
  3981. print '<td width="10">&nbsp;</td>';
  3982. print "</tr>\n";
  3983. if (!empty($conf->global->MAIN_VIEW_LINE_NUMBER)) {
  3984. print '<td align="center" width="5">&nbsp;</td>';
  3985. }
  3986. print '<tr width="100%" class="nodrag nodrop">';
  3987. print '<td>&nbsp;</td>';
  3988. print '<td width="50">&nbsp;</td>';
  3989. print '<td width="80">&nbsp;</td>';
  3990. print '<td width="50">&nbsp;</td>';
  3991. print '<td width="50">&nbsp;</td>';
  3992. print '<td align="right" class="nowrap"><input type="text" size="1" value="" name="all_progress">%</td>';
  3993. print '<td colspan="4" align="right"><input class="button" type="submit" name="all_percent" value="Modifier" /></td>';
  3994. print '</tr>';
  3995. print '</table>';
  3996. print '</form>';
  3997. print '</div>';
  3998. }
  3999. }
  4000. print ' <form name="addproduct" id="addproduct" action="' . $_SERVER["PHP_SELF"] . '?id=' . $object->id . (($action != 'editline') ? '#addline' : '#line_' . GETPOST('lineid')) . '" method="POST">
  4001. <input type="hidden" name="token" value="' . $_SESSION ['newtoken'] . '">
  4002. <input type="hidden" name="action" value="' . (($action != 'editline') ? 'addline' : 'updateligne') . '">
  4003. <input type="hidden" name="mode" value="">
  4004. <input type="hidden" name="id" value="' . $object->id . '">
  4005. ';
  4006. if (! empty($conf->use_javascript_ajax) && $object->statut == 0) {
  4007. include DOL_DOCUMENT_ROOT . '/core/tpl/ajaxrow.tpl.php';
  4008. }
  4009. print '<div class="div-table-responsive-no-min">';
  4010. print '<table id="tablelines" class="noborder noshadow" width="100%">';
  4011. // Show object lines
  4012. if (! empty($object->lines))
  4013. $ret = $object->printObjectLines($action, $mysoc, $soc, $lineid, 1);
  4014. // Form to add new line
  4015. if ($object->statut == 0 && $usercancreate && $action != 'valid' && $action != 'editline')
  4016. {
  4017. if ($action != 'editline' && $action != 'selectlines')
  4018. {
  4019. // Add free products/services
  4020. $object->formAddObjectLine(1, $mysoc, $soc);
  4021. $parameters = array();
  4022. $reshook = $hookmanager->executeHooks('formAddObjectLine', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  4023. }
  4024. }
  4025. print "</table>\n";
  4026. print "</div>";
  4027. print "</form>\n";
  4028. dol_fiche_end();
  4029. // Actions buttons
  4030. if ($action != 'prerelance' && $action != 'presend' && $action != 'valid' && $action != 'editline')
  4031. {
  4032. print '<div class="tabsAction">';
  4033. $parameters = array();
  4034. $reshook = $hookmanager->executeHooks('addMoreActionsButtons', $parameters, $object, $action); // Note that $action and $object may have been modified by hook
  4035. if (empty($reshook)) {
  4036. // Editer une facture deja validee, sans paiement effectue et pas exporte en compta
  4037. if ($object->statut == Facture::STATUS_VALIDATED)
  4038. {
  4039. // On verifie si les lignes de factures ont ete exportees en compta et/ou ventilees
  4040. $ventilExportCompta = $object->getVentilExportCompta();
  4041. if ($ventilExportCompta == 0)
  4042. {
  4043. if (! empty($conf->global->INVOICE_CAN_ALWAYS_BE_EDITED) || ($resteapayer == $object->total_ttc && empty($object->paye)))
  4044. {
  4045. if (! $objectidnext && $object->is_last_in_cycle())
  4046. {
  4047. if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  4048. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
  4049. {
  4050. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=modif">' . $langs->trans('Modify') . '</a></div>';
  4051. } else {
  4052. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("NotEnoughPermissions") . '">' . $langs->trans('Modify') . '</span></div>';
  4053. }
  4054. } else if (!$object->is_last_in_cycle()) {
  4055. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("NotLastInCycle") . '">' . $langs->trans('Modify') . '</span></div>';
  4056. } else {
  4057. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('Modify') . '</span></div>';
  4058. }
  4059. }
  4060. }
  4061. else
  4062. {
  4063. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseDispatchedInAccounting") . '">' . $langs->trans('Modify') . '</span></div>';
  4064. }
  4065. }
  4066. $discount = new DiscountAbsolute($db);
  4067. $result = $discount->fetch(0, $object->id);
  4068. // Reopen a standard paid invoice
  4069. if ((($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT)
  4070. || ($object->type == Facture::TYPE_CREDIT_NOTE && empty($discount->id))
  4071. || ($object->type == Facture::TYPE_DEPOSIT && empty($discount->id)))
  4072. && ($object->statut == 2 || $object->statut == 3 || ($object->statut == 1 && $object->paye == 1)) // Condition ($object->statut == 1 && $object->paye == 1) should not happened but can be found due to corrupted data
  4073. && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->facture->creer) || (!empty($conf->global->MAIN_USE_ADVANCED_PERMS) && $user->rights->facture->invoice_advance->reopen))) // A paid invoice (partially or completely)
  4074. {
  4075. if (! $objectidnext && $object->close_code != 'replaced') // Not replaced by another invoice
  4076. {
  4077. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=reopen">' . $langs->trans('ReOpen') . '</a></div>';
  4078. } else {
  4079. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ReOpen') . '</span></div>';
  4080. }
  4081. }
  4082. // Validate
  4083. if ($object->statut == Facture::STATUS_DRAFT && count($object->lines) > 0 && ((($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA || $object->type == Facture::TYPE_SITUATION) && (! empty($conf->global->FACTURE_ENABLE_NEGATIVE) || $object->total_ttc >= 0)) || ($object->type == Facture::TYPE_CREDIT_NOTE && $object->total_ttc <= 0))) {
  4084. if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  4085. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->validate)))
  4086. {
  4087. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=valid">' . $langs->trans('Validate') . '</a></div>';
  4088. }
  4089. }
  4090. // Send by mail
  4091. if (($object->statut == Facture::STATUS_VALIDATED || $object->statut == Facture::STATUS_CLOSED) || ! empty($conf->global->FACTURE_SENDBYEMAIL_FOR_ALL_STATUS)) {
  4092. if ($objectidnext) {
  4093. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('SendMail') . '</span></div>';
  4094. } else {
  4095. if (empty($conf->global->MAIN_USE_ADVANCED_PERMS) || $user->rights->facture->invoice_advance->send) {
  4096. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&action=presend&mode=init#formmailbeforetitle">' . $langs->trans('SendMail') . '</a></div>';
  4097. } else
  4098. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#">' . $langs->trans('SendMail') . '</a></div>';
  4099. }
  4100. }
  4101. // Request a direct debit order
  4102. if ($object->statut > Facture::STATUS_DRAFT && $object->paye == 0 && $num == 0)
  4103. {
  4104. if ($resteapayer > 0)
  4105. {
  4106. if ($user->rights->prelevement->bons->creer)
  4107. {
  4108. if (! $objectidnext && $object->close_code != 'replaced') // Not replaced by another invoice
  4109. {
  4110. print '<a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/prelevement.php?facid='.$object->id.'" title="'.dol_escape_htmltag($langs->trans("MakeWithdrawRequest")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
  4111. } else {
  4112. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('MakeWithdrawRequest') . '</span></div>';
  4113. }
  4114. }
  4115. else
  4116. {
  4117. //print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("NotEnoughPermissions")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
  4118. }
  4119. }
  4120. else
  4121. {
  4122. //print '<a class="butActionRefused" href="#" title="'.dol_escape_htmltag($langs->trans("AmountMustBePositive")).'">'.$langs->trans("MakeWithdrawRequest").'</a>';
  4123. }
  4124. }
  4125. // Create payment
  4126. if ($object->type != Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement) {
  4127. if ($objectidnext) {
  4128. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('DoPayment') . '</span></div>';
  4129. } else {
  4130. //if ($resteapayer == 0) { // Sometimes we can receive more, so we accept to enter more and will offer a button to convert into discount (but it is not a credit note, just a prepayment done)
  4131. // print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseRemainderToPayIsZero") . '">' . $langs->trans('DoPayment') . '</span></div>';
  4132. //} else {
  4133. print '<div class="inline-block divButAction"><a class="butAction" href="'. DOL_URL_ROOT .'/compta/paiement.php?facid=' . $object->id . '&amp;action=create&amp;accountid='.$object->fk_account.'">' . $langs->trans('DoPayment') . '</a></div>';
  4134. //}
  4135. }
  4136. }
  4137. // Reverse back money or convert to reduction
  4138. if ($object->type == Facture::TYPE_CREDIT_NOTE || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_STANDARD) {
  4139. // For credit note only
  4140. if ($object->type == Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement)
  4141. {
  4142. if ($resteapayer == 0)
  4143. {
  4144. print '<div class="inline-block divButAction"><span class="butActionRefused" title="'.$langs->trans("DisabledBecauseRemainderToPayIsZero").'">'.$langs->trans('DoPaymentBack').'</span></div>';
  4145. }
  4146. else
  4147. {
  4148. print '<div class="inline-block divButAction"><a class="butAction" href="'. DOL_URL_ROOT .'/compta/paiement.php?facid='.$object->id.'&amp;action=create&amp;accountid='.$object->fk_account.'">'.$langs->trans('DoPaymentBack').'</a></div>';
  4149. }
  4150. }
  4151. // For standard invoice with excess received
  4152. if ($object->type == Facture::TYPE_STANDARD && empty($object->paye) && ($object->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits) < 0 && $user->rights->facture->creer && empty($discount->id))
  4153. {
  4154. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&amp;action=converttoreduc">'.$langs->trans('ConvertExcessReceivedToReduc').'</a></div>';
  4155. }
  4156. // For credit note
  4157. if ($object->type == Facture::TYPE_CREDIT_NOTE && $object->statut == 1 && $object->paye == 0 && $user->rights->facture->creer && $object->getSommePaiement() == 0) {
  4158. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=converttoreduc">' . $langs->trans('ConvertToReduc') . '</a></div>';
  4159. }
  4160. // For deposit invoice
  4161. if ($object->type == Facture::TYPE_DEPOSIT && $user->rights->facture->creer && $object->statut > 0 && empty($discount->id))
  4162. {
  4163. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="'.$_SERVER["PHP_SELF"].'?facid='.$object->id.'&amp;action=converttoreduc">'.$langs->trans('ConvertToReduc').'</a></div>';
  4164. }
  4165. }
  4166. // Classify paid
  4167. if ($object->statut == 1 && $object->paye == 0 && $user->rights->facture->paiement && (($object->type != Facture::TYPE_CREDIT_NOTE && $object->type != Facture::TYPE_DEPOSIT && $resteapayer <= 0) || ($object->type == Facture::TYPE_CREDIT_NOTE && $resteapayer >= 0))
  4168. || ($object->type == Facture::TYPE_DEPOSIT && $object->paye == 0 && $object->total_ttc > 0 && $resteapayer == 0 && $user->rights->facture->paiement && empty($discount->id))
  4169. )
  4170. {
  4171. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="'.$_SERVER['PHP_SELF'].'?facid='.$object->id.'&amp;action=paid">'.$langs->trans('ClassifyPaid').'</a></div>';
  4172. }
  4173. // Classify 'closed not completely paid' (possible si validee et pas encore classee payee)
  4174. if ($object->statut == 1 && $object->paye == 0 && $resteapayer > 0 && $user->rights->facture->paiement)
  4175. {
  4176. if ($totalpaye > 0 || $totalcreditnotes > 0)
  4177. {
  4178. // If one payment or one credit note was linked to this invoice
  4179. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=paid">' . $langs->trans('ClassifyPaidPartially') . '</a></div>';
  4180. }
  4181. else
  4182. {
  4183. if ( empty($conf->global->INVOICE_CAN_NEVER_BE_CANCELED))
  4184. {
  4185. if ($objectidnext)
  4186. {
  4187. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('ClassifyCanceled') . '</span></div>';
  4188. }
  4189. else
  4190. {
  4191. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=canceled">' . $langs->trans('ClassifyCanceled') . '</a></div>';
  4192. }
  4193. }
  4194. }
  4195. }
  4196. // Clone
  4197. if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $user->rights->facture->creer)
  4198. {
  4199. print '<div class="inline-block divButAction"><a class="butAction'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=clone&amp;object=invoice">' . $langs->trans("ToClone") . '</a></div>';
  4200. }
  4201. // Clone as predefined / Create template
  4202. if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $object->statut == 0 && $user->rights->facture->creer)
  4203. {
  4204. if (! $objectidnext && count($object->lines) > 0)
  4205. {
  4206. print '<div class="inline-block divButAction"><a class="butAction" href="'.DOL_URL_ROOT.'/compta/facture/fiche-rec.php?facid=' . $object->id . '&amp;action=create">' . $langs->trans("ChangeIntoRepeatableInvoice") . '</a></div>';
  4207. }
  4208. }
  4209. // Create a credit note
  4210. if (($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA) && $object->statut > 0 && $user->rights->facture->creer)
  4211. {
  4212. if (! $objectidnext)
  4213. {
  4214. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?socid=' . $object->socid .'&amp;fac_avoir=' . $object->id . '&amp;action=create&amp;type=2'.($object->fk_project > 0 ? '&amp;projectid='.$object->fk_project : '').'">' . $langs->trans("CreateCreditNote") . '</a></div>';
  4215. }
  4216. }
  4217. // For situation invoice with excess received
  4218. if ($object->statut > Facture::STATUS_DRAFT
  4219. && ($object->total_ttc - $totalpaye - $totalcreditnotes - $totaldeposits) > 0
  4220. && $user->rights->facture->creer
  4221. && !$objectidnext
  4222. && $object->is_last_in_cycle()
  4223. && $conf->global->INVOICE_USE_SITUATION_CREDIT_NOTE
  4224. )
  4225. {
  4226. if ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  4227. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
  4228. {
  4229. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?socid=' . $object->socid .'&amp;fac_avoir=' . $object->id . '&amp;invoiceAvoirWithLines=1&amp;action=create&amp;type=2'.($object->fk_project > 0 ? '&amp;projectid='.$object->fk_project : '').'">' . $langs->trans("CreateCreditNote") . '</a></div>';
  4230. } else {
  4231. print '<div class="inline-block divButAction"><span class="butActionRefused" title="' . $langs->trans("NotEnoughPermissions") . '">' . $langs->trans("CreateCreditNote") . '</span></div>';
  4232. }
  4233. }
  4234. // remove situation from cycle
  4235. if ($object->statut > Facture::STATUS_DRAFT
  4236. && $object->type == Facture::TYPE_SITUATION
  4237. && $user->rights->facture->creer
  4238. && !$objectidnext
  4239. && $object->situation_counter > 1
  4240. && $object->is_last_in_cycle()
  4241. && ((empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->creer))
  4242. || (! empty($conf->global->MAIN_USE_ADVANCED_PERMS) && ! empty($user->rights->facture->invoice_advance->unvalidate)))
  4243. )
  4244. {
  4245. if(($object->total_ttc - $totalcreditnotes ) == 0 )
  4246. {
  4247. print '<div class="inline-block divButAction"><a id="butSituationOut" class="butAction" href="' . $_SERVER['PHP_SELF'] . '?facid=' . $object->id . '&amp;action=situationout">' . $langs->trans("RemoveSituationFromCycle") . '</a></div>';
  4248. }
  4249. else
  4250. {
  4251. print '<div class="inline-block divButAction"><a id="butSituationOutRefused" class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotEnouthCreditNote") . '" >' . $langs->trans("RemoveSituationFromCycle") . '</a></div>';
  4252. }
  4253. }
  4254. // Create next situation invoice
  4255. if ($user->rights->facture->creer && ($object->type == 5) && ($object->statut == 1 || $object->statut == 2)) {
  4256. if ($object->is_last_in_cycle() && $object->situation_final != 1) {
  4257. print '<div class="inline-block divButAction"><a class="butAction" href="' . $_SERVER['PHP_SELF'] . '?action=create&amp;type=5&amp;origin=facture&amp;originid=' . $object->id . '&amp;socid=' . $object->socid . '" >' . $langs->trans('CreateNextSituationInvoice') . '</a></div>';
  4258. } else if (!$object->is_last_in_cycle()) {
  4259. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotLastInCycle") . '">' . $langs->trans('CreateNextSituationInvoice') . '</a></div>';
  4260. } else {
  4261. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseFinal") . '">' . $langs->trans('CreateNextSituationInvoice') . '</a></div>';
  4262. }
  4263. }
  4264. // Delete
  4265. $isErasable = $object->is_erasable();
  4266. if ($user->rights->facture->supprimer || ($user->rights->facture->creer && $isErasable == 1)) // isErasable = 1 means draft with temporary ref (draft can always be deleted with no need of permissions)
  4267. {
  4268. //var_dump($isErasable);
  4269. if ($isErasable == -4) {
  4270. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecausePayments") . '">' . $langs->trans('Delete') . '</a></div>';
  4271. }
  4272. elseif ($isErasable == -3) {
  4273. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotLastSituationInvoice") . '">' . $langs->trans('Delete') . '</a></div>';
  4274. }
  4275. elseif ($isErasable == -2) {
  4276. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotLastInvoice") . '">' . $langs->trans('Delete') . '</a></div>';
  4277. }
  4278. elseif ($isErasable == -1) {
  4279. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseDispatchedInBookkeeping") . '">' . $langs->trans('Delete') . '</a></div>';
  4280. }
  4281. elseif ($isErasable <= 0) // Any other cases
  4282. {
  4283. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseNotErasable") . '">' . $langs->trans('Delete') . '</a></div>';
  4284. }
  4285. elseif ($objectidnext)
  4286. {
  4287. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("DisabledBecauseReplacedInvoice") . '">' . $langs->trans('Delete') . '</a></div>';
  4288. }
  4289. else
  4290. {
  4291. print '<div class="inline-block divButAction"><a class="butActionDelete'.($conf->use_javascript_ajax?' reposition':'').'" href="' . $_SERVER["PHP_SELF"] . '?facid=' . $object->id . '&amp;action=delete">' . $langs->trans('Delete') . '</a></div>';
  4292. }
  4293. } else {
  4294. print '<div class="inline-block divButAction"><a class="butActionRefused" href="#" title="' . $langs->trans("NotAllowed") . '">' . $langs->trans('Delete') . '</a></div>';
  4295. }
  4296. }
  4297. print '</div>';
  4298. }
  4299. // Select mail models is same action as presend
  4300. if (GETPOST('modelselected','alpha')) {
  4301. $action = 'presend';
  4302. }
  4303. if ($action != 'prerelance' && $action != 'presend')
  4304. {
  4305. print '<div class="fichecenter"><div class="fichehalfleft">';
  4306. print '<a name="builddoc"></a>'; // ancre
  4307. // Documents generes
  4308. $filename = dol_sanitizeFileName($object->ref);
  4309. $filedir = $conf->facture->dir_output . '/' . dol_sanitizeFileName($object->ref);
  4310. $urlsource = $_SERVER['PHP_SELF'] . '?facid=' . $object->id;
  4311. $genallowed = $user->rights->facture->lire;
  4312. $delallowed = $user->rights->facture->creer;
  4313. print $formfile->showdocuments('facture', $filename, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang);
  4314. $somethingshown = $formfile->numoffiles;
  4315. // Show links to link elements
  4316. $linktoelem = $form->showLinkToObjectBlock($object, null, array('invoice'));
  4317. $compatibleImportElementsList = false;
  4318. if($user->rights->facture->creer
  4319. && $object->statut == Facture::STATUS_DRAFT
  4320. && ($object->type == Facture::TYPE_STANDARD || $object->type == Facture::TYPE_REPLACEMENT || $object->type == Facture::TYPE_DEPOSIT || $object->type == Facture::TYPE_PROFORMA || $object->type == Facture::TYPE_SITUATION) )
  4321. {
  4322. $compatibleImportElementsList = array('commande','propal'); // import from linked elements
  4323. }
  4324. $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem,$compatibleImportElementsList);
  4325. // Show online payment link
  4326. $useonlinepayment = (! empty($conf->paypal->enabled) || ! empty($conf->stripe->enabled) || ! empty($conf->paybox->enabled));
  4327. if ($object->statut != Facture::STATUS_DRAFT && $useonlinepayment)
  4328. {
  4329. print '<br><!-- Link to pay -->'."\n";
  4330. require_once DOL_DOCUMENT_ROOT.'/core/lib/payments.lib.php';
  4331. print showOnlinePaymentUrl('invoice', $object->ref).'<br>';
  4332. }
  4333. // Show direct download link
  4334. if ($object->statut != Facture::STATUS_DRAFT && ! empty($conf->global->INVOICE_ALLOW_EXTERNAL_DOWNLOAD))
  4335. {
  4336. print '<br><!-- Link to download main doc -->'."\n";
  4337. print showDirectDownloadLink($object).'<br>';
  4338. }
  4339. print '</div><div class="fichehalfright"><div class="ficheaddleft">';
  4340. // List of actions on element
  4341. include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php';
  4342. $formactions = new FormActions($db);
  4343. $somethingshown = $formactions->showactions($object, 'invoice', $socid, 1);
  4344. print '</div></div></div>';
  4345. }
  4346. // Presend form
  4347. $modelmail='facture_send';
  4348. $defaulttopic='SendBillRef';
  4349. $diroutput = $conf->facture->dir_output;
  4350. $trackid = 'inv'.$object->id;
  4351. include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php';
  4352. }
  4353. llxFooter();
  4354. $db->close();