| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814 |
- <?php
- /* Copyright (C) 2015 Jean-François Ferry <jfefe@aternatik.fr>
- * Copyright (C) 2020 Thibault FOUCART <support@ptibogxiv.net>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- use Luracast\Restler\RestException;
- require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture.class.php';
- require_once DOL_DOCUMENT_ROOT.'/compta/facture/class/facture-rec.class.php';
- /**
- * API class for invoices
- *
- * @access protected
- * @class DolibarrApiAccess {@requires user,external}
- */
- class Invoices extends DolibarrApi
- {
- /**
- *
- * @var array $FIELDS Mandatory fields, checked when create and update object
- */
- static $FIELDS = array(
- 'socid',
- );
- /**
- * @var Facture $invoice {@type Facture}
- */
- private $invoice;
- /**
- * @var FactureRec $templte_invoice {@type FactureRec}
- */
- private $template_invoice;
- /**
- * Constructor
- */
- public function __construct()
- {
- global $db, $conf;
- $this->db = $db;
- $this->invoice = new Facture($this->db);
- $this->template_invoice = new FactureRec($this->db);
- }
- /**
- * Get properties of a invoice object
- *
- * Return an array with invoice informations
- *
- * @param int $id ID of invoice
- * @param int $contact_list 0:Return array contains all properties, 1:Return array contains just id, -1: Do not return contacts/adddesses
- * @return array|mixed data without useless information
- *
- * @throws RestException
- */
- public function get($id, $contact_list = 1)
- {
- return $this->_fetch($id, '', '', $contact_list);
- }
- /**
- * Get properties of an invoice object by ref
- *
- * Return an array with invoice informations
- *
- * @param string $ref Ref of object
- * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses
- * @return array|mixed data without useless information
- *
- * @url GET ref/{ref}
- *
- * @throws RestException
- */
- public function getByRef($ref, $contact_list = 1)
- {
- return $this->_fetch('', $ref, '', $contact_list);
- }
- /**
- * Get properties of an invoice object by ref_ext
- *
- * Return an array with invoice informations
- *
- * @param string $ref_ext External reference of object
- * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses
- * @return array|mixed data without useless information
- *
- * @url GET ref_ext/{ref_ext}
- *
- * @throws RestException
- */
- public function getByRefExt($ref_ext, $contact_list = 1)
- {
- return $this->_fetch('', '', $ref_ext, $contact_list);
- }
- /**
- * Get properties of an invoice object
- *
- * Return an array with invoice informations
- *
- * @param int $id ID of order
- * @param string $ref Ref of object
- * @param string $ref_ext External reference of object
- * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses
- * @return array|mixed data without useless information
- *
- * @throws RestException
- */
- private function _fetch($id, $ref = '', $ref_ext = '', $contact_list = 1)
- {
- if (!DolibarrApiAccess::$user->rights->facture->lire) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id, $ref, $ref_ext);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- // Get payment details
- $this->invoice->totalpaid = $this->invoice->getSommePaiement();
- $this->invoice->totalcreditnotes = $this->invoice->getSumCreditNotesUsed();
- $this->invoice->totaldeposits = $this->invoice->getSumDepositsUsed();
- $this->invoice->remaintopay = price2num($this->invoice->total_ttc - $this->invoice->totalpaid - $this->invoice->totalcreditnotes - $this->invoice->totaldeposits, 'MT');
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- // Add external contacts ids
- if ($contact_list > -1) {
- $tmparray = $this->invoice->liste_contact(-1, 'external', $contact_list);
- if (is_array($tmparray)) {
- $this->invoice->contacts_ids = $tmparray;
- }
- }
- $this->invoice->fetchObjectLinked();
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * List invoices
- *
- * Get a list of invoices
- *
- * @param string $sortfield Sort field
- * @param string $sortorder Sort order
- * @param int $limit Limit for list
- * @param int $page Page number
- * @param string $thirdparty_ids Thirdparty ids to filter orders of (example '1' or '1,2,3') {@pattern /^[0-9,]*$/i}
- * @param string $status Filter by invoice status : draft | unpaid | paid | cancelled
- * @param string $sqlfilters Other criteria to filter answers separated by a comma. Syntax example "(t.ref:like:'SO-%') and (t.date_creation:<:'20160101')"
- * @return array Array of invoice objects
- *
- * @throws RestException 404 Not found
- * @throws RestException 503 Error
- */
- public function index($sortfield = "t.rowid", $sortorder = 'ASC', $limit = 100, $page = 0, $thirdparty_ids = '', $status = '', $sqlfilters = '')
- {
- global $db, $conf;
- if (!DolibarrApiAccess::$user->rights->facture->lire) {
- throw new RestException(401);
- }
- $obj_ret = array();
- // case of external user, $thirdparty_ids param is ignored and replaced by user's socid
- $socids = DolibarrApiAccess::$user->socid ? DolibarrApiAccess::$user->socid : $thirdparty_ids;
- // If the internal user must only see his customers, force searching by him
- $search_sale = 0;
- if (!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) {
- $search_sale = DolibarrApiAccess::$user->id;
- }
- $sql = "SELECT t.rowid";
- if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) {
- $sql .= ", sc.fk_soc, sc.fk_user"; // We need these fields in order to filter by sale (including the case where the user can only see his prospects)
- }
- $sql .= " FROM ".MAIN_DB_PREFIX."facture as t";
- if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) {
- $sql .= ", ".MAIN_DB_PREFIX."societe_commerciaux as sc"; // We need this table joined to the select in order to filter by sale
- }
- $sql .= ' WHERE t.entity IN ('.getEntity('invoice').')';
- if ((!DolibarrApiAccess::$user->rights->societe->client->voir && !$socids) || $search_sale > 0) {
- $sql .= " AND t.fk_soc = sc.fk_soc";
- }
- if ($socids) {
- $sql .= " AND t.fk_soc IN (".$this->db->sanitize($socids).")";
- }
- if ($search_sale > 0) {
- $sql .= " AND t.rowid = sc.fk_soc"; // Join for the needed table to filter by sale
- }
- // Filter by status
- if ($status == 'draft') {
- $sql .= " AND t.fk_statut IN (0)";
- }
- if ($status == 'unpaid') {
- $sql .= " AND t.fk_statut IN (1)";
- }
- if ($status == 'paid') {
- $sql .= " AND t.fk_statut IN (2)";
- }
- if ($status == 'cancelled') {
- $sql .= " AND t.fk_statut IN (3)";
- }
- // Insert sale filter
- if ($search_sale > 0) {
- $sql .= " AND sc.fk_user = ".((int) $search_sale);
- }
- // Add sql filters
- if ($sqlfilters) {
- $errormessage = '';
- $sql .= forgeSQLFromUniversalSearchCriteria($sqlfilters, $errormessage);
- if ($errormessage) {
- throw new RestException(400, 'Error when validating parameter sqlfilters -> '.$errormessage);
- }
- }
- $sql .= $this->db->order($sortfield, $sortorder);
- if ($limit) {
- if ($page < 0) {
- $page = 0;
- }
- $offset = $limit * $page;
- $sql .= $this->db->plimit($limit + 1, $offset);
- }
- $result = $this->db->query($sql);
- if ($result) {
- $i = 0;
- $num = $this->db->num_rows($result);
- $min = min($num, ($limit <= 0 ? $num : $limit));
- while ($i < $min) {
- $obj = $this->db->fetch_object($result);
- $invoice_static = new Facture($this->db);
- if ($invoice_static->fetch($obj->rowid)) {
- // Get payment details
- $invoice_static->totalpaid = $invoice_static->getSommePaiement();
- $invoice_static->totalcreditnotes = $invoice_static->getSumCreditNotesUsed();
- $invoice_static->totaldeposits = $invoice_static->getSumDepositsUsed();
- $invoice_static->remaintopay = price2num($invoice_static->total_ttc - $invoice_static->totalpaid - $invoice_static->totalcreditnotes - $invoice_static->totaldeposits, 'MT');
- // Add external contacts ids
- $tmparray = $invoice_static->liste_contact(-1, 'external', 1);
- if (is_array($tmparray)) {
- $invoice_static->contacts_ids = $tmparray;
- }
- $obj_ret[] = $this->_cleanObjectDatas($invoice_static);
- }
- $i++;
- }
- } else {
- throw new RestException(503, 'Error when retrieve invoice list : '.$this->db->lasterror());
- }
- if (!count($obj_ret)) {
- throw new RestException(404, 'No invoice found');
- }
- return $obj_ret;
- }
- /**
- * Create invoice object
- *
- * @param array $request_data Request datas
- * @return int ID of invoice
- */
- public function post($request_data = null)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401, "Insuffisant rights");
- }
- // Check mandatory fields
- $result = $this->_validate($request_data);
- foreach ($request_data as $field => $value) {
- if (preg_match('/^array_options/', $field)) {
- $f = str_replace('array_options_', '', $field);
- $this->invoice->array_options[$f] = $value;
- continue;
- }
- $this->invoice->$field = $value;
- }
- if (!array_key_exists('date', $request_data)) {
- $this->invoice->date = dol_now();
- }
- /* We keep lines as an array
- if (isset($request_data["lines"])) {
- $lines = array();
- foreach ($request_data["lines"] as $line) {
- array_push($lines, (object) $line);
- }
- $this->invoice->lines = $lines;
- }*/
- if ($this->invoice->create(DolibarrApiAccess::$user, 0, (empty($request_data["date_lim_reglement"]) ? 0 : $request_data["date_lim_reglement"])) < 0) {
- throw new RestException(500, "Error creating invoice", array_merge(array($this->invoice->error), $this->invoice->errors));
- }
- return $this->invoice->id;
- }
- /**
- * Create an invoice using an existing order.
- *
- *
- * @param int $orderid Id of the order
- *
- * @url POST /createfromorder/{orderid}
- *
- * @return int
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 405
- */
- public function createInvoiceFromOrder($orderid)
- {
- require_once DOL_DOCUMENT_ROOT.'/commande/class/commande.class.php';
- if (!DolibarrApiAccess::$user->rights->commande->lire) {
- throw new RestException(401);
- }
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- if (empty($orderid)) {
- throw new RestException(400, 'Order ID is mandatory');
- }
- $order = new Commande($this->db);
- $result = $order->fetch($orderid);
- if (!$result) {
- throw new RestException(404, 'Order not found');
- }
- $result = $this->invoice->createFromOrder($order, DolibarrApiAccess::$user);
- if ($result < 0) {
- throw new RestException(405, $this->invoice->error);
- }
- $this->invoice->fetchObjectLinked();
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Get lines of an invoice
- *
- * @param int $id Id of invoice
- *
- * @url GET {id}/lines
- *
- * @return int
- */
- public function getLines($id)
- {
- if (!DolibarrApiAccess::$user->rights->facture->lire) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $this->invoice->getLinesArray();
- $result = array();
- foreach ($this->invoice->lines as $line) {
- array_push($result, $this->_cleanObjectDatas($line));
- }
- return $result;
- }
- /**
- * Update a line to a given invoice
- *
- * @param int $id Id of invoice to update
- * @param int $lineid Id of line to update
- * @param array $request_data InvoiceLine data
- *
- * @url PUT {id}/lines/{lineid}
- *
- * @return array
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404 Invoice not found
- */
- public function putLine($id, $lineid, $request_data = null)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $request_data = (object) $request_data;
- $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
- $request_data->label = sanitizeVal($request_data->label);
- $updateRes = $this->invoice->updateline(
- $lineid,
- $request_data->desc,
- $request_data->subprice,
- $request_data->qty,
- $request_data->remise_percent,
- $request_data->date_start,
- $request_data->date_end,
- $request_data->tva_tx,
- $request_data->localtax1_tx,
- $request_data->localtax2_tx,
- $request_data->price_base_type ? $request_data->price_base_type : 'HT',
- $request_data->info_bits,
- $request_data->product_type,
- $request_data->fk_parent_line,
- 0,
- $request_data->fk_fournprice,
- $request_data->pa_ht,
- $request_data->label,
- $request_data->special_code,
- $request_data->array_options,
- $request_data->situation_percent,
- $request_data->fk_unit,
- $request_data->multicurrency_subprice,
- 0,
- $request_data->ref_ext,
- $request_data->rang
- );
- if ($updateRes > 0) {
- $result = $this->get($id);
- unset($result->line);
- return $this->_cleanObjectDatas($result);
- } else {
- throw new RestException(304, $this->invoice->error);
- }
- }
- /**
- * Add a contact type of given invoice
- *
- * @param int $id Id of invoice to update
- * @param int $contactid Id of contact to add
- * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER)
- *
- * @url POST {id}/contact/{contactid}/{type}
- *
- * @return int
- *
- * @throws RestException 401
- * @throws RestException 404
- */
- public function postContact($id, $contactid, $type)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!in_array($type, array('BILLING', 'SHIPPING', 'CUSTOMER'), true)) {
- throw new RestException(500, 'Availables types: BILLING, SHIPPING OR CUSTOMER');
- }
- if (!DolibarrApi::_checkAccessToResource('invoice', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->add_contact($contactid, $type, 'external');
- if (!$result) {
- throw new RestException(500, 'Error when added the contact');
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Delete a contact type of given invoice
- *
- * @param int $id Id of invoice to update
- * @param int $contactid Row key of the contact in the array contact_ids.
- * @param string $type Type of the contact (BILLING, SHIPPING, CUSTOMER).
- *
- * @url DELETE {id}/contact/{contactid}/{type}
- *
- * @return array
- *
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 500 System error
- */
- public function deleteContact($id, $contactid, $type)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('invoice', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $contacts = $this->invoice->liste_contact();
- foreach ($contacts as $contact) {
- if ($contact['id'] == $contactid && $contact['code'] == $type) {
- $result = $this->invoice->delete_contact($contact['rowid']);
- if (!$result) {
- throw new RestException(500, 'Error when deleted the contact');
- }
- }
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Deletes a line of a given invoice
- *
- * @param int $id Id of invoice
- * @param int $lineid Id of the line to delete
- *
- * @url DELETE {id}/lines/{lineid}
- *
- * @return array
- *
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 405
- */
- public function deleteLine($id, $lineid)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- if (empty($lineid)) {
- throw new RestException(400, 'Line ID is mandatory');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- // TODO Check the lineid $lineid is a line of ojbect
- $updateRes = $this->invoice->deleteline($lineid);
- if ($updateRes > 0) {
- return $this->get($id);
- } else {
- throw new RestException(405, $this->invoice->error);
- }
- }
- /**
- * Update invoice
- *
- * @param int $id Id of invoice to update
- * @param array $request_data Datas
- * @return int
- */
- public function put($id, $request_data = null)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- foreach ($request_data as $field => $value) {
- if ($field == 'id') {
- continue;
- }
- $this->invoice->$field = $value;
- }
- // update bank account
- if (!empty($this->invoice->fk_account)) {
- if ($this->invoice->setBankAccount($this->invoice->fk_account) == 0) {
- throw new RestException(400, $this->invoice->error);
- }
- }
- if ($this->invoice->update(DolibarrApiAccess::$user)) {
- return $this->get($id);
- }
- return false;
- }
- /**
- * Delete invoice
- *
- * @param int $id Invoice ID
- * @return array
- */
- public function delete($id)
- {
- if (!DolibarrApiAccess::$user->rights->facture->supprimer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->delete(DolibarrApiAccess::$user);
- if ($result < 0) {
- throw new RestException(500, 'Error when deleting invoice');
- } elseif ($result == 0) {
- throw new RestException(403, 'Invoice not erasable');
- }
- return array(
- 'success' => array(
- 'code' => 200,
- 'message' => 'Invoice deleted'
- )
- );
- }
- /**
- * Add a line to a given invoice
- *
- * Exemple of POST query :
- * {
- * "desc": "Desc", "subprice": "1.00000000", "qty": "1", "tva_tx": "20.000", "localtax1_tx": "0.000", "localtax2_tx": "0.000",
- * "fk_product": "1", "remise_percent": "0", "date_start": "", "date_end": "", "fk_code_ventilation": 0, "info_bits": "0",
- * "fk_remise_except": null, "product_type": "1", "rang": "-1", "special_code": "0", "fk_parent_line": null, "fk_fournprice": null,
- * "pa_ht": "0.00000000", "label": "", "array_options": [], "situation_percent": "100", "fk_prev_id": null, "fk_unit": null
- * }
- *
- * @param int $id Id of invoice
- * @param array $request_data InvoiceLine data
- *
- * @url POST {id}/lines
- *
- * @return int
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 400
- */
- public function postLine($id, $request_data = null)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $request_data = (object) $request_data;
- $request_data->desc = sanitizeVal($request_data->desc, 'restricthtml');
- $request_data->label = sanitizeVal($request_data->label);
- // Reset fk_parent_line for no child products and special product
- if (($request_data->product_type != 9 && empty($request_data->fk_parent_line)) || $request_data->product_type == 9) {
- $request_data->fk_parent_line = 0;
- }
- // calculate pa_ht
- $marginInfos = getMarginInfos($request_data->subprice, $request_data->remise_percent, $request_data->tva_tx, $request_data->localtax1_tx, $request_data->localtax2_tx, $request_data->fk_fournprice, $request_data->pa_ht);
- $pa_ht = $marginInfos[0];
- $updateRes = $this->invoice->addline(
- $request_data->desc,
- $request_data->subprice,
- $request_data->qty,
- $request_data->tva_tx,
- $request_data->localtax1_tx,
- $request_data->localtax2_tx,
- $request_data->fk_product,
- $request_data->remise_percent,
- $request_data->date_start,
- $request_data->date_end,
- $request_data->fk_code_ventilation,
- $request_data->info_bits,
- $request_data->fk_remise_except,
- $request_data->price_base_type ? $request_data->price_base_type : 'HT',
- $request_data->subprice,
- $request_data->product_type,
- $request_data->rang,
- $request_data->special_code,
- $request_data->origin,
- $request_data->origin_id,
- $request_data->fk_parent_line,
- empty($request_data->fk_fournprice) ?null:$request_data->fk_fournprice,
- $pa_ht,
- $request_data->label,
- $request_data->array_options,
- $request_data->situation_percent,
- $request_data->fk_prev_id,
- $request_data->fk_unit,
- 0,
- $request_data->ref_ext
- );
- if ($updateRes < 0) {
- throw new RestException(400, 'Unable to insert the new line. Check your inputs. '.$this->invoice->error);
- }
- return $updateRes;
- }
- /**
- * Adds a contact to an invoice
- *
- * @param int $id Order ID
- * @param int $fk_socpeople Id of thirdparty contact (if source = 'external') or id of user (if souce = 'internal') to link
- * @param string $type_contact Type of contact (code). Must a code found into table llx_c_type_contact. For example: BILLING
- * @param string $source external=Contact extern (llx_socpeople), internal=Contact intern (llx_user)
- * @param int $notrigger Disable all triggers
- *
- * @url POST {id}/contacts
- *
- * @return array
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 500 System error
- *
- */
- public function addContact($id, $fk_socpeople, $type_contact, $source, $notrigger = 0)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->add_contact($fk_socpeople, $type_contact, $source, $notrigger);
- if ($result < 0) {
- throw new RestException(500, 'Error : '.$this->invoice->error);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Sets an invoice as draft
- *
- * @param int $id Order ID
- * @param int $idwarehouse Warehouse ID
- *
- * @url POST {id}/settodraft
- *
- * @return array
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 500 System error
- *
- */
- public function settodraft($id, $idwarehouse = -1)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->setDraft(DolibarrApiAccess::$user, $idwarehouse);
- if ($result == 0) {
- throw new RestException(304, 'Nothing done.');
- }
- if ($result < 0) {
- throw new RestException(500, 'Error : '.$this->invoice->error);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Validate an invoice
- *
- * If you get a bad value for param notrigger check that ou provide this in body
- * {
- * "idwarehouse": 0,
- * "notrigger": 0
- * }
- *
- * @param int $id Invoice ID
- * @param int $idwarehouse Warehouse ID
- * @param int $notrigger 1=Does not execute triggers, 0= execute triggers
- *
- * @url POST {id}/validate
- *
- * @return array
- */
- public function validate($id, $idwarehouse = 0, $notrigger = 0)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->validate(DolibarrApiAccess::$user, '', $idwarehouse, $notrigger);
- if ($result == 0) {
- throw new RestException(304, 'Error nothing done. May be object is already validated');
- }
- if ($result < 0) {
- throw new RestException(500, 'Error when validating Invoice: '.$this->invoice->error);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Sets an invoice as paid
- *
- * @param int $id Order ID
- * @param string $close_code Code filled if we classify to 'Paid completely' when payment is not complete (for escompte for example)
- * @param string $close_note Comment defined if we classify to 'Paid' when payment is not complete (for escompte for example)
- *
- * @url POST {id}/settopaid
- *
- * @return array An invoice object
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 500 System error
- */
- public function settopaid($id, $close_code = '', $close_note = '')
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->setPaid(DolibarrApiAccess::$user, $close_code, $close_note);
- if ($result == 0) {
- throw new RestException(304, 'Error nothing done. May be object is already validated');
- }
- if ($result < 0) {
- throw new RestException(500, 'Error : '.$this->invoice->error);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Sets an invoice as unpaid
- *
- * @param int $id Order ID
- *
- * @url POST {id}/settounpaid
- *
- * @return array An invoice object
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 500 System error
- */
- public function settounpaid($id)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->setUnpaid(DolibarrApiAccess::$user);
- if ($result == 0) {
- throw new RestException(304, 'Nothing done');
- }
- if ($result < 0) {
- throw new RestException(500, 'Error : '.$this->invoice->error);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Get discount from invoice
- *
- * @param int $id Id of invoice
- *
- * @url GET {id}/discount
- *
- * @return mixed
- */
- public function getDiscount($id)
- {
- require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
- if (!DolibarrApiAccess::$user->rights->facture->lire) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $discountcheck = new DiscountAbsolute($this->db);
- $result = $discountcheck->fetch(0, $this->invoice->id);
- if ($result == 0) {
- throw new RestException(404, 'Discount not found');
- }
- if ($result < 0) {
- throw new RestException(500, $discountcheck->error);
- }
- return parent::_cleanObjectDatas($discountcheck);
- }
- /**
- * Create a discount (credit available) for a credit note or a deposit.
- *
- * @param int $id Invoice ID
- * @url POST {id}/markAsCreditAvailable
- *
- * @return array An invoice object
- *
- * @throws RestException 304
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 500 System error
- */
- public function markAsCreditAvailable($id)
- {
- require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- if ($this->invoice->paye) {
- throw new RestException(500, 'Alreay paid');
- }
- $this->invoice->fetch($id);
- $this->invoice->fetch_thirdparty();
- // Check if there is already a discount (protection to avoid duplicate creation when resubmit post)
- $discountcheck = new DiscountAbsolute($this->db);
- $result = $discountcheck->fetch(0, $this->invoice->id);
- $canconvert = 0;
- if ($this->invoice->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)
- }
- if (($this->invoice->type == Facture::TYPE_CREDIT_NOTE || $this->invoice->type == Facture::TYPE_STANDARD) && $this->invoice->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)
- }
- if ($canconvert) {
- $this->db->begin();
- $amount_ht = $amount_tva = $amount_ttc = array();
- $multicurrency_amount_ht = $multicurrency_amount_tva = $multicurrency_amount_ttc = array();
- // Loop on each vat rate
- $i = 0;
- foreach ($this->invoice->lines as $line) {
- if ($line->product_type < 9 && $line->total_ht != 0) { // Remove lines with product_type greater than or equal to 9
- // no need to create discount if amount is null
- $amount_ht[$line->tva_tx] += $line->total_ht;
- $amount_tva[$line->tva_tx] += $line->total_tva;
- $amount_ttc[$line->tva_tx] += $line->total_ttc;
- $multicurrency_amount_ht[$line->tva_tx] += $line->multicurrency_total_ht;
- $multicurrency_amount_tva[$line->tva_tx] += $line->multicurrency_total_tva;
- $multicurrency_amount_ttc[$line->tva_tx] += $line->multicurrency_total_ttc;
- $i++;
- }
- }
- // Insert one discount by VAT rate category
- $discount = new DiscountAbsolute($this->db);
- if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
- $discount->description = '(CREDIT_NOTE)';
- } elseif ($this->invoice->type == Facture::TYPE_DEPOSIT) {
- $discount->description = '(DEPOSIT)';
- } elseif ($this->invoice->type == Facture::TYPE_STANDARD || $this->invoice->type == Facture::TYPE_REPLACEMENT || $this->invoice->type == Facture::TYPE_SITUATION) {
- $discount->description = '(EXCESS RECEIVED)';
- } else {
- throw new RestException(500, 'Cant convert to reduc an Invoice of this type');
- }
- $discount->fk_soc = $this->invoice->socid;
- $discount->fk_facture_source = $this->invoice->id;
- $error = 0;
- if ($this->invoice->type == Facture::TYPE_STANDARD || $this->invoice->type == Facture::TYPE_REPLACEMENT || $this->invoice->type == Facture::TYPE_SITUATION) {
- // If we're on a standard invoice, we have to get excess received to create a discount in TTC without VAT
- // Total payments
- $sql = 'SELECT SUM(pf.amount) as total_payments';
- $sql .= ' FROM '.MAIN_DB_PREFIX.'paiement_facture as pf, '.MAIN_DB_PREFIX.'paiement as p';
- $sql .= ' LEFT JOIN '.MAIN_DB_PREFIX.'c_paiement as c ON p.fk_paiement = c.id';
- $sql .= ' WHERE pf.fk_facture = '.((int) $this->invoice->id);
- $sql .= ' AND pf.fk_paiement = p.rowid';
- $sql .= ' AND p.entity IN ('.getEntity('invoice').')';
- $resql = $this->db->query($sql);
- if (!$resql) {
- dol_print_error($this->db);
- }
- $res = $this->db->fetch_object($resql);
- $total_payments = $res->total_payments;
- // Total credit note and deposit
- $total_creditnote_and_deposit = 0;
- $sql = "SELECT re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc,";
- $sql .= " re.description, re.fk_facture_source";
- $sql .= " FROM ".MAIN_DB_PREFIX."societe_remise_except as re";
- $sql .= " WHERE fk_facture = ".((int) $this->invoice->id);
- $resql = $this->db->query($sql);
- if (!empty($resql)) {
- while ($obj = $this->db->fetch_object($resql)) {
- $total_creditnote_and_deposit += $obj->amount_ttc;
- }
- } else {
- dol_print_error($this->db);
- }
- $discount->amount_ht = $discount->amount_ttc = $total_payments + $total_creditnote_and_deposit - $this->invoice->total_ttc;
- $discount->amount_tva = 0;
- $discount->tva_tx = 0;
- $result = $discount->create(DolibarrApiAccess::$user);
- if ($result < 0) {
- $error++;
- }
- }
- if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE || $this->invoice->type == Facture::TYPE_DEPOSIT) {
- foreach ($amount_ht as $tva_tx => $xxx) {
- $discount->amount_ht = abs($amount_ht[$tva_tx]);
- $discount->amount_tva = abs($amount_tva[$tva_tx]);
- $discount->amount_ttc = abs($amount_ttc[$tva_tx]);
- $discount->multicurrency_amount_ht = abs($multicurrency_amount_ht[$tva_tx]);
- $discount->multicurrency_amount_tva = abs($multicurrency_amount_tva[$tva_tx]);
- $discount->multicurrency_amount_ttc = abs($multicurrency_amount_ttc[$tva_tx]);
- $discount->tva_tx = abs($tva_tx);
- $result = $discount->create(DolibarrApiAccess::$user);
- if ($result < 0) {
- $error++;
- break;
- }
- }
- }
- if (empty($error)) {
- if ($this->invoice->type != Facture::TYPE_DEPOSIT) {
- // Classe facture
- $result = $this->invoice->setPaid(DolibarrApiAccess::$user);
- if ($result >= 0) {
- $this->db->commit();
- } else {
- $this->db->rollback();
- throw new RestException(500, 'Could not set paid');
- }
- } else {
- $this->db->commit();
- }
- } else {
- $this->db->rollback();
- throw new RestException(500, 'Discount creation error');
- }
- }
- return $this->_cleanObjectDatas($this->invoice);
- }
- /**
- * Add a discount line into an invoice (as an invoice line) using an existing absolute discount
- *
- * Note that this consume the discount.
- *
- * @param int $id Id of invoice
- * @param int $discountid Id of discount
- *
- * @url POST {id}/usediscount/{discountid}
- *
- * @return int
- *
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 405
- */
- public function useDiscount($id, $discountid)
- {
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- if (empty($id)) {
- throw new RestException(400, 'Invoice ID is mandatory');
- }
- if (empty($discountid)) {
- throw new RestException(400, 'Discount ID is mandatory');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- $result = $this->invoice->insert_discount($discountid);
- if ($result < 0) {
- throw new RestException(405, $this->invoice->error);
- }
- return $result;
- }
- /**
- * Add an available credit note discount to payments of an existing invoice.
- *
- * Note that this consume the credit note.
- *
- * @param int $id Id of invoice
- * @param int $discountid Id of a discount coming from a credit note
- *
- * @url POST {id}/usecreditnote/{discountid}
- *
- * @return int
- *
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 405
- */
- public function useCreditNote($id, $discountid)
- {
- require_once DOL_DOCUMENT_ROOT.'/core/class/discount.class.php';
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- if (empty($id)) {
- throw new RestException(400, 'Invoice ID is mandatory');
- }
- if (empty($discountid)) {
- throw new RestException(400, 'Credit ID is mandatory');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $discount = new DiscountAbsolute($this->db);
- $result = $discount->fetch($discountid);
- if (!$result) {
- throw new RestException(404, 'Credit not found');
- }
- $result = $discount->link_to_invoice(0, $id);
- if ($result < 0) {
- throw new RestException(405, $discount->error);
- }
- return $result;
- }
- /**
- * Get list of payments of a given invoice
- *
- * @param int $id Id of invoice
- *
- * @url GET {id}/payments
- *
- * @return array
- *
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 404
- * @throws RestException 405
- */
- public function getPayments($id)
- {
- if (!DolibarrApiAccess::$user->rights->facture->lire) {
- throw new RestException(401);
- }
- if (empty($id)) {
- throw new RestException(400, 'Invoice ID is mandatory');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- $result = $this->invoice->getListOfPayments();
- if ($result < 0) {
- throw new RestException(405, $this->invoice->error);
- }
- return $result;
- }
- /**
- * Add payment line to a specific invoice with the remain to pay as amount.
- *
- * @param int $id Id of invoice
- * @param string $datepaye {@from body} Payment date {@type timestamp}
- * @param int $paymentid {@from body} Payment mode Id {@min 1}
- * @param string $closepaidinvoices {@from body} Close paid invoices {@choice yes,no}
- * @param int $accountid {@from body} Account Id {@min 1}
- * @param string $num_payment {@from body} Payment number (optional)
- * @param string $comment {@from body} Note private (optional)
- * @param string $chqemetteur {@from body} Payment issuer (mandatory if paymentcode = 'CHQ')
- * @param string $chqbank {@from body} Issuer bank name (optional)
- *
- * @url POST {id}/payments
- *
- * @return int Payment ID
- *
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 404
- */
- public function addPayment($id, $datepaye, $paymentid, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '')
- {
- global $conf;
- require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(403);
- }
- if (empty($id)) {
- throw new RestException(400, 'Invoice ID is mandatory');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $id)) {
- throw new RestException(403, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- if (isModEnabled("banque")) {
- if (empty($accountid)) {
- throw new RestException(400, 'Account ID is mandatory');
- }
- }
- if (empty($paymentid)) {
- throw new RestException(400, 'Payment ID or Payment Code is mandatory');
- }
- $result = $this->invoice->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Invoice not found');
- }
- // Calculate amount to pay
- $totalpaid = $this->invoice->getSommePaiement();
- $totalcreditnotes = $this->invoice->getSumCreditNotesUsed();
- $totaldeposits = $this->invoice->getSumDepositsUsed();
- $resteapayer = price2num($this->invoice->total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT');
- $this->db->begin();
- $amounts = array();
- $multicurrency_amounts = array();
- // Clean parameters amount if payment is for a credit note
- if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
- $resteapayer = price2num($resteapayer, 'MT');
- $amounts[$id] = -$resteapayer;
- // Multicurrency
- $newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
- $multicurrency_amounts[$id] = -$newvalue;
- } else {
- $resteapayer = price2num($resteapayer, 'MT');
- $amounts[$id] = $resteapayer;
- // Multicurrency
- $newvalue = price2num($this->invoice->multicurrency_total_ttc, 'MT');
- $multicurrency_amounts[$id] = $newvalue;
- }
- // Creation of payment line
- $paymentobj = new Paiement($this->db);
- $paymentobj->datepaye = $datepaye;
- $paymentobj->amounts = $amounts; // Array with all payments dispatching with invoice id
- $paymentobj->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
- $paymentobj->paiementid = $paymentid;
- $paymentobj->paiementcode = dol_getIdFromCode($this->db, $paymentid, 'c_paiement', 'id', 'code', 1);
- $paymentobj->num_payment = $num_payment;
- $paymentobj->note_private = $comment;
- $payment_id = $paymentobj->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
- if ($payment_id < 0) {
- $this->db->rollback();
- throw new RestException(400, 'Payment error : '.$paymentobj->error);
- }
- if (isModEnabled("banque")) {
- $label = '(CustomerInvoicePayment)';
- if ($paymentobj->paiementcode == 'CHQ' && empty($chqemetteur)) {
- throw new RestException(400, 'Emetteur is mandatory when payment code is '.$paymentobj->paiementcode);
- }
- if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
- $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note
- }
- $result = $paymentobj->addPaymentToBank(DolibarrApiAccess::$user, 'payment', $label, $accountid, $chqemetteur, $chqbank);
- if ($result < 0) {
- $this->db->rollback();
- throw new RestException(400, 'Add payment to bank error : '.$paymentobj->error);
- }
- }
- $this->db->commit();
- return $payment_id;
- }
- /**
- * Add a payment to pay partially or completely one or several invoices.
- * Warning: Take care that all invoices are owned by the same customer.
- * Example of value for parameter arrayofamounts: {"1": {"amount": "99.99", "multicurrency_amount": ""}, "2": {"amount": "", "multicurrency_amount": "10"}}
- *
- * @param array $arrayofamounts {@from body} Array with id of invoices with amount to pay for each invoice
- * @param string $datepaye {@from body} Payment date {@type timestamp}
- * @param int $paymentid {@from body} Payment mode Id {@min 1}
- * @param string $closepaidinvoices {@from body} Close paid invoices {@choice yes,no}
- * @param int $accountid {@from body} Account Id {@min 1}
- * @param string $num_payment {@from body} Payment number (optional)
- * @param string $comment {@from body} Note private (optional)
- * @param string $chqemetteur {@from body} Payment issuer (mandatory if paiementcode = 'CHQ')
- * @param string $chqbank {@from body} Issuer bank name (optional)
- * @param string $ref_ext {@from body} External reference (optional)
- * @param bool $accepthigherpayment {@from body} Accept higher payments that it remains to be paid (optional)
- *
- * @url POST /paymentsdistributed
- *
- * @return int Payment ID
- * @throws RestException 400
- * @throws RestException 401
- * @throws RestException 403
- * @throws RestException 404
- */
- public function addPaymentDistributed($arrayofamounts, $datepaye, $paymentid, $closepaidinvoices, $accountid, $num_payment = '', $comment = '', $chqemetteur = '', $chqbank = '', $ref_ext = '', $accepthigherpayment = false)
- {
- global $conf;
- require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(403);
- }
- foreach ($arrayofamounts as $id => $amount) {
- if (empty($id)) {
- throw new RestException(400, 'Invoice ID is mandatory. Fill the invoice id and amount into arrayofamounts parameter. For example: {"1": "99.99", "2": "10"}');
- }
- if (!DolibarrApi::_checkAccessToResource('facture', $id)) {
- throw new RestException(403, 'Access not allowed on invoice ID '.$id.' for login '.DolibarrApiAccess::$user->login);
- }
- }
- if (isModEnabled("banque")) {
- if (empty($accountid)) {
- throw new RestException(400, 'Account ID is mandatory');
- }
- }
- if (empty($paymentid)) {
- throw new RestException(400, 'Payment ID or Payment Code is mandatory');
- }
- $this->db->begin();
- $amounts = array();
- $multicurrency_amounts = array();
- // Loop on each invoice to pay
- foreach ($arrayofamounts as $id => $amountarray) {
- $result = $this->invoice->fetch($id);
- if (!$result) {
- $this->db->rollback();
- throw new RestException(404, 'Invoice ID '.$id.' not found');
- }
- if (($amountarray["amount"] == "remain" || $amountarray["amount"] > 0) && ($amountarray["multicurrency_amount"] == "remain" || $amountarray["multicurrency_amount"] > 0)) {
- $this->db->rollback();
- throw new RestException(400, 'Payment in both currency '.$id.' ( amount: '.$amountarray["amount"].', multicurrency_amount: '.$amountarray["multicurrency_amount"].')');
- }
- $is_multicurrency = 0;
- $total_ttc = $this->invoice->total_ttc;
- if ($amountarray["multicurrency_amount"] > 0 || $amountarray["multicurrency_amount"] == "remain") {
- $is_multicurrency = 1;
- $total_ttc = $this->invoice->multicurrency_total_ttc;
- }
- // Calculate amount to pay
- $totalpaid = $this->invoice->getSommePaiement($is_multicurrency);
- $totalcreditnotes = $this->invoice->getSumCreditNotesUsed($is_multicurrency);
- $totaldeposits = $this->invoice->getSumDepositsUsed($is_multicurrency);
- $remainstopay = $amount = price2num($total_ttc - $totalpaid - $totalcreditnotes - $totaldeposits, 'MT');
- if (!$is_multicurrency && $amountarray["amount"] != 'remain') {
- $amount = price2num($amountarray["amount"], 'MT');
- }
- if ($is_multicurrency && $amountarray["multicurrency_amount"] != 'remain') {
- $amount = price2num($amountarray["multicurrency_amount"], 'MT');
- }
- if ($amount > $remainstopay && !$accepthigherpayment) {
- $this->db->rollback();
- throw new RestException(400, 'Payment amount on invoice ID '.$id.' ('.$amount.') is higher than remain to pay ('.$remainstopay.')');
- }
- if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
- $amount = -$amount;
- }
- if ($is_multicurrency) {
- $amounts[$id] = null;
- // Multicurrency
- $multicurrency_amounts[$id] = $amount;
- } else {
- $amounts[$id] = $amount;
- // Multicurrency
- $multicurrency_amounts[$id] = null;
- }
- }
- // Creation of payment line
- $paymentobj = new Paiement($this->db);
- $paymentobj->datepaye = $datepaye;
- $paymentobj->amounts = $amounts; // Array with all payments dispatching with invoice id
- $paymentobj->multicurrency_amounts = $multicurrency_amounts; // Array with all payments dispatching
- $paymentobj->paiementid = $paymentid;
- $paymentobj->paiementcode = dol_getIdFromCode($this->db, $paymentid, 'c_paiement', 'id', 'code', 1);
- $paymentobj->num_payment = $num_payment;
- $paymentobj->note_private = $comment;
- $paymentobj->ref_ext = $ref_ext;
- $payment_id = $paymentobj->create(DolibarrApiAccess::$user, ($closepaidinvoices == 'yes' ? 1 : 0)); // This include closing invoices
- if ($payment_id < 0) {
- $this->db->rollback();
- throw new RestException(400, 'Payment error : '.$paymentobj->error);
- }
- if (isModEnabled("banque")) {
- $label = '(CustomerInvoicePayment)';
- if ($paymentobj->paiementcode == 'CHQ' && empty($chqemetteur)) {
- throw new RestException(400, 'Emetteur is mandatory when payment code is '.$paymentobj->paiementcode);
- }
- if ($this->invoice->type == Facture::TYPE_CREDIT_NOTE) {
- $label = '(CustomerInvoicePaymentBack)'; // Refund of a credit note
- }
- $result = $paymentobj->addPaymentToBank(DolibarrApiAccess::$user, 'payment', $label, $accountid, $chqemetteur, $chqbank);
- if ($result < 0) {
- $this->db->rollback();
- throw new RestException(400, 'Add payment to bank error : '.$paymentobj->error);
- }
- }
- $this->db->commit();
- return $payment_id;
- }
- /**
- * Update a payment
- *
- * @param int $id Id of payment
- * @param string $num_payment Payment number
- *
- * @url PUT payments/{id}
- *
- * @return array
- * @throws RestException 400 Bad parameters
- * @throws RestException 401 Not allowed
- * @throws RestException 404 Not found
- */
- public function putPayment($id, $num_payment = '')
- {
- require_once DOL_DOCUMENT_ROOT.'/compta/paiement/class/paiement.class.php';
- if (!DolibarrApiAccess::$user->rights->facture->creer) {
- throw new RestException(401);
- }
- if (empty($id)) {
- throw new RestException(400, 'Payment ID is mandatory');
- }
- $paymentobj = new Paiement($this->db);
- $result = $paymentobj->fetch($id);
- if (!$result) {
- throw new RestException(404, 'Payment not found');
- }
- if (!empty($num_payment)) {
- $result = $paymentobj->update_num($num_payment);
- if ($result < 0) {
- throw new RestException(500, 'Error when updating the payment num');
- }
- }
- return [
- 'success' => [
- 'code' => 200,
- 'message' => 'Payment updated'
- ]
- ];
- }
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
- /**
- * Clean sensible object datas
- *
- * @param Object $object Object to clean
- * @return Object Object with cleaned properties
- */
- protected function _cleanObjectDatas($object)
- {
- // phpcs:enable
- $object = parent::_cleanObjectDatas($object);
- unset($object->note);
- unset($object->address);
- unset($object->barcode_type);
- unset($object->barcode_type_code);
- unset($object->barcode_type_label);
- unset($object->barcode_type_coder);
- unset($object->canvas);
- return $object;
- }
- /**
- * Validate fields before create or update object
- *
- * @param array|null $data Datas to validate
- * @return array
- *
- * @throws RestException
- */
- private function _validate($data)
- {
- $invoice = array();
- foreach (Invoices::$FIELDS as $field) {
- if (!isset($data[$field])) {
- throw new RestException(400, "$field field missing");
- }
- $invoice[$field] = $data[$field];
- }
- return $invoice;
- }
- /**
- * Get properties of a template invoice object
- *
- * Return an array with invoice informations
- *
- * @param int $id ID of template invoice
- * @param int $contact_list 0:Return array contains all properties, 1:Return array contains just id, -1: Do not return contacts/adddesses
- * @return array|mixed data without useless information
- *
- * @url GET templates/{id}
- *
- * @throws RestException
- */
- public function getTemplateInvoice($id, $contact_list = 1)
- {
- return $this->_fetchTemplateInvoice($id, '', '', $contact_list);
- }
- /**
- * Get properties of an invoice object
- *
- * Return an array with invoice informations
- *
- * @param int $id ID of order
- * @param string $ref Ref of object
- * @param string $ref_ext External reference of object
- * @param int $contact_list 0: Returned array of contacts/addresses contains all properties, 1: Return array contains just id, -1: Do not return contacts/adddesses
- * @return array|mixed data without useless information
- *
- * @throws RestException
- */
- private function _fetchTemplateInvoice($id, $ref = '', $ref_ext = '', $contact_list = 1)
- {
- if (!DolibarrApiAccess::$user->rights->facture->lire) {
- throw new RestException(401);
- }
- $result = $this->template_invoice->fetch($id, $ref, $ref_ext);
- if (!$result) {
- throw new RestException(404, 'Template invoice not found');
- }
- if (!DolibarrApi::_checkAccessToResource('facturerec', $this->template_invoice->id)) {
- throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login);
- }
- // Add external contacts ids
- if ($contact_list > -1) {
- $tmparray = $this->template_invoice->liste_contact(-1, 'external', $contact_list);
- if (is_array($tmparray)) {
- $this->template_invoice->contacts_ids = $tmparray;
- }
- }
- $this->template_invoice->fetchObjectLinked();
- return $this->_cleanTemplateObjectDatas($this->template_invoice);
- }
- // phpcs:disable PEAR.NamingConventions.ValidFunctionName.PublicUnderscore
- /**
- * Clean sensible object datas
- *
- * @param Object $object Object to clean
- * @return Object Object with cleaned properties
- */
- protected function _cleanTemplateObjectDatas($object)
- {
- // phpcs:enable
- $object = parent::_cleanObjectDatas($object);
- unset($object->note);
- unset($object->address);
- unset($object->barcode_type);
- unset($object->barcode_type_code);
- unset($object->barcode_type_label);
- unset($object->barcode_type_coder);
- unset($object->canvas);
- return $object;
- }
- }
|