card.php 205 KB

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