diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 28157085270..cc5db388af7 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -77,21 +77,6 @@ class Invoices extends DolibarrApi $this->invoice->totaldeposits = $this->invoice->getSumDepositsUsed(); $this->invoice->resteapayer = price2num($this->invoice->total_ttc - $this->invoice->totalpaye - $this->invoice->totalcreditnotes - $this->invoice->totaldeposits, 'MT'); - // get available discounts of customer - /* TODO Move this into thirdparty API - $soc = new Societe($this->db); - if ($this->invoice->socid > 0) - $res = $soc->fetch($this->invoice->socid); - if($res) { - $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%'))"; - $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')"; - $absolute_discount = $soc->getAvailableDiscounts('', $filterabsolutediscount); - $absolute_creditnote = $soc->getAvailableDiscounts('', $filtercreditnote); - $this->invoice->absolute_discount = price2num($absolute_discount, 'MT'); - $this->invoice->absolute_creditnote = price2num($absolute_creditnote, 'MT'); - } - */ - if( ! DolibarrApi::_checkAccessToResource('facture',$this->invoice->id)) { throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } @@ -667,8 +652,96 @@ class Invoices extends DolibarrApi } + /** + * Add a discount line into an invoice (as an invoice line) using an existing absolute discount (Consume the discount) + * + * @param int $id Id of invoice + * @param int $discountid Id of discount + * + * @url POST {id}/usediscount/{discountid} + * + * @return int + * @throws 400 + * @throws 401 + * @throws 404 + * @throws 405 + */ + 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 (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/{creditnoteid} + * + * @return int + * @throws 400 + * @throws 401 + * @throws 404 + * @throws 405 + */ + 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($creditId)) { + 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 a payment list of a given invoice + * Get list of payments of a given invoice * * @param int $id Id of invoice * @@ -706,8 +779,6 @@ class Invoices extends DolibarrApi return $result; } - - /** * Clean sensible object datas * diff --git a/htdocs/compta/facture/class/facture.class.php b/htdocs/compta/facture/class/facture.class.php index 69e956b7434..fe5ebeaa57f 100644 --- a/htdocs/compta/facture/class/facture.class.php +++ b/htdocs/compta/facture/class/facture.class.php @@ -3505,11 +3505,12 @@ class Facture extends CommonInvoice /** - * Renvoi liste des factures remplacables - * Statut validee ou abandonnee pour raison autre + non payee + aucun paiement + pas deja remplacee + * Return list of invoices qualified to be replaced by another invoice. + * Invoices matching the following rules are returned: + * (Status validated or abandonned for a reason 'other') + not payed + no payment at all + not already replaced * - * @param int $socid Id societe - * @return array Tableau des factures ('id'=>id, 'ref'=>ref, 'status'=>status, 'paymentornot'=>0/1) + * @param int $socid Id thirdparty + * @return array Array of invoices ('id'=>id, 'ref'=>ref, 'status'=>status, 'paymentornot'=>0/1) */ function list_replacable_invoices($socid=0) { @@ -3553,7 +3554,7 @@ class Facture extends CommonInvoice /** * Return list of invoices qualified to be corrected by a credit note. - * Invoices matching the following rules are returned + * Invoices matching the following rules are returned: * (validated + payment on process) or classified (payed completely or payed partiely) + not already replaced + not already a credit note * * @param int $socid Id thirdparty diff --git a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php index c73fcfb3e8e..7d937341b21 100644 --- a/htdocs/modulebuilder/template/core/modules/modMyModule.class.php +++ b/htdocs/modulebuilder/template/core/modules/modMyModule.class.php @@ -56,10 +56,10 @@ class modMyModule extends DolibarrModules // Family can be 'crm','financial','hr','projects','products','ecm','technic','interface','other' // It is used to group modules by family in module setup page $this->family = "other"; - // Module position in the family - $this->module_position = 500; + // Module position in the family on 2 digits ('01', '10', '20', ...) + $this->module_position = '90'; // Gives the possibility to the module, to provide his own family info and position of this family (Overwrite $this->family and $this->module_position. Avoid this) - //$this->familyinfo = array('myownfamily' => array('position' => '001', 'label' => $langs->trans("MyOwnFamily"))); + //$this->familyinfo = array('myownfamily' => array('position' => '01', 'label' => $langs->trans("MyOwnFamily"))); // Module label (no space allowed), used if translation string 'ModuleMyModuleName' not found (MyModue is name of module). $this->name = preg_replace('/^mod/i','',get_class($this)); diff --git a/htdocs/societe/class/api_thirdparties.class.php b/htdocs/societe/class/api_thirdparties.class.php index dd743984044..1dc0eeb334b 100644 --- a/htdocs/societe/class/api_thirdparties.class.php +++ b/htdocs/societe/class/api_thirdparties.class.php @@ -83,6 +83,13 @@ class Thirdparties extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } + $filterabsolutediscount = "fk_facture_source IS NULL OR (fk_facture_source IS NOT NULL AND (description LIKE '(DEPOSIT)%' AND description NOT LIKE '(EXCESS RECEIVED)%'))"; + $filtercreditnote = "fk_facture_source IS NOT NULL AND (description NOT LIKE '(DEPOSIT)%' OR description LIKE '(EXCESS RECEIVED)%')"; + $absolute_discount = $this->company->getAvailableDiscounts('', $filterabsolutediscount); + $absolute_creditnote = $this->company->getAvailableDiscounts('', $filtercreditnote); + $this->company->absolute_discount = price2num($absolute_discount, 'MT'); + $this->company->absolute_creditnote = price2num($absolute_creditnote, 'MT'); + return $this->_cleanObjectDatas($this->company); } @@ -331,6 +338,152 @@ class Thirdparties extends DolibarrApi return $this->company; } + + /** + * Get fixed amount discount of a thirdparty (all sources: deposit, credit note, commercial offers...) + * + * @param int $id ID of the thirdparty + * @param string $filter Filter exceptional discount. "none" will return every discount, "available" returns unapplied discounts, "used" returns applied discounts {@choice none,available,used} + * @param string $sortfield Sort field + * @param string $sortorder Sort order + * + * @url GET {id}/fixedamountdiscounts + * + * @return array List of fixed discount of thirdparty + * + * @throws 400 + * @throws 401 + * @throws 404 + * @throws 503 + */ + function getFixedAmountDiscounts($id, $filter="none", $sortfield = "f.type", $sortorder = 'ASC') + { + $obj_ret = array(); + + if(! DolibarrApiAccess::$user->rights->societe->lire) { + throw new RestException(401); + } + + if(empty($id)) { + throw new RestException(400, 'Thirdparty ID is mandatory'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + $result = $this->company->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + } + + + $sql = "SELECT f.facnumber, f.type as factype, re.fk_facture_source, re.rowid, re.amount_ht, re.amount_tva, re.amount_ttc, re.description, re.fk_facture, re.fk_facture_line"; + $sql .= " FROM llx_societe_remise_except as re, llx_facture as f"; + $sql .= " WHERE f.rowid = re.fk_facture_source AND re.fk_soc = ".$id; + if ($filter == "available") $sql .= " AND re.fk_facture IS NULL AND re.fk_facture_line IS NULL"; + if ($filter == "used") $sql .= " AND (re.fk_facture IS NOT NULL OR re.fk_facture_line IS NOT NULL)"; + + $sql.= $this->db->order($sortfield, $sortorder); + + $result = $this->db->query($sql); + if( ! $result ) { + throw new RestException(503, $this->db->lasterror()); + } else { + $num = $this->db->num_rows($result); + while ( $obj = $this->db->fetch_object($result) ) { + $obj_ret[] = $obj; + } + } + + return $obj_ret; + } + + + + /** + * Return list of invoices qualified to be replaced by another invoice. + * + * @param int $id Id of thirdparty + * + * @url GET {id}/getinvoicesqualifiedforreplacement + * + * @return array + * @throws 400 + * @throws 401 + * @throws 404 + * @throws 405 + */ + function getInvoicesQualifiedForReplacement($id) { + + if(! DolibarrApiAccess::$user->rights->facture->lire) { + throw new RestException(401); + } + if(empty($id)) { + throw new RestException(400, 'Thirdparty ID is mandatory'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + /*$result = $this->thirdparty->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + }*/ + + $invoice = new Facture($this->db); + $result = $invoice->list_replacable_invoices($id); + if( $result < 0) { + throw new RestException(405, $this->thirdparty->error); + } + + return $result; + } + + /** + * Return list of invoices qualified to be corrected by a credit note. + * Invoices matching the following rules are returned + * (validated + payment on process) or classified (payed completely or payed partialy) + not already replaced + not already a credit note + * + * @param int $id Id of thirdparty + * + * @url GET {id}/getinvoicesqualifiedforcreditnote + * + * @return array + * @throws 400 + * @throws 401 + * @throws 404 + * @throws 405 + */ + function getInvoicesQualifiedForCreditNote($id) { + + if(! DolibarrApiAccess::$user->rights->facture->lire) { + throw new RestException(401); + } + if(empty($id)) { + throw new RestException(400, 'Thirdparty ID is mandatory'); + } + + if( ! DolibarrApi::_checkAccessToResource('societe',$id)) { + throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); + } + + /*$result = $this->thirdparty->fetch($id); + if( ! $result ) { + throw new RestException(404, 'Thirdparty not found'); + }*/ + + $invoice = new Facture($this->db); + $result = $invoice->list_qualified_avoir_invoices($id); + if( $result < 0) { + throw new RestException(405, $this->thirdparty->error); + } + + return $result; + } + + /** * Clean sensible object datas *