123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683 |
- <?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';
- /**
- * 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}
- */
- public $invoice;
- /**
- * Constructor
- */
- public function __construct()
- {
- global $db, $conf;
- $this->db = $db;
- $this->invoice = new Facture($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
- * @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
- * @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
- * @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
- * @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
- $this->invoice->contacts_ids = $this->invoice->liste_contact(-1, 'external', $contact_list);
- $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;
- $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 (".$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 = ".$search_sale;
- }
- // Add sql filters
- if ($sqlfilters)
- {
- if (!DolibarrApi::_checkFilters($sqlfilters))
- {
- throw new RestException(503, 'Error when validating parameter sqlfilters '.$sqlfilters);
- }
- $regexstring = '\(([^:\'\(\)]+:[^:\'\(\)]+:[^:\(\)]+)\)';
- $sql .= " AND (".preg_replace_callback('/'.$regexstring.'/', 'DolibarrApi::_forge_criteria_callback', $sqlfilters).")";
- }
- $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
- $invoice_static->contacts_ids = $invoice_static->liste_contact(-1, 'external', 1);
- $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) {
- $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;
- $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,
- '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
- );
- 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
- */
- 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);
- }
- 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;
- // 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,
- 'HT',
- 0,
- $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
- *
- */
- 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
- *
- */
- 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
- */
- 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
- */
- 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
- */
- 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 = '.$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 = ".$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 (!empty($conf->banque->enabled)) {
- 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
- $totalpaye = $this->invoice->getSommePaiement();
- $totalcreditnotes = $this->invoice->getSumCreditNotesUsed();
- $totaldeposits = $this->invoice->getSumDepositsUsed();
- $resteapayer = price2num($this->invoice->total_ttc - $totalpaye - $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 (!empty($conf->banque->enabled)) {
- $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 (!empty($conf->banque->enabled)) {
- 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
- $totalpaye = $this->invoice->getSommePaiement($is_multicurrency);
- $totalcreditnotes = $this->invoice->getSumCreditNotesUsed($is_multicurrency);
- $totaldeposits = $this->invoice->getSumDepositsUsed($is_multicurrency);
- $remainstopay = $amount = price2num($total_ttc - $totalpaye - $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 (!empty($conf->banque->enabled)) {
- $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);
- 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;
- }
- }
|