diff --git a/htdocs/compta/facture/class/api_invoices.class.php b/htdocs/compta/facture/class/api_invoices.class.php index 5cbf1cc939b..647d9d78e8e 100644 --- a/htdocs/compta/facture/class/api_invoices.class.php +++ b/htdocs/compta/facture/class/api_invoices.class.php @@ -936,7 +936,7 @@ class Invoices extends DolibarrApi */ public function markAsCreditAvailable($id) { - if(! DolibarrApiAccess::$user->rights->facture->creer) { + if( ! DolibarrApiAccess::$user->rights->facture->creer) { throw new RestException(401); } @@ -949,91 +949,147 @@ class Invoices extends DolibarrApi throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); } - $result = $this->invoice->fetch_thirdparty(); - if( ! $result ) { - throw new RestException(404, 'Thirdparty not found'); + if ($this->invoice->paye) { + throw new RestException(500, 'Alreay payed'); } - - if (! $this->invoice->paye) // protection against multiple submit - { - $this->db->begin(); - - $this->invoice->fetch_lines(); - - $amount_ht = $amount_tva = $amount_ttc = array(); - - // Loop on each vat rate - $i=0; - $amount_ht = array(); - $amount_tva = array(); - $amount_ttc = array(); - foreach($this->invoice->lines as $line) - { - $amount_ht[$line->tva_tx]+=$line->total_ht; - $amount_tva[$line->tva_tx]+=$line->total_tva; - $amount_ttc[$line->tva_tx]+=$line->total_ttc; - $i++; - } - - // Insert one discount by VAT rate category - $discount = new DiscountAbsolute($this->db); - if ($this->invoice->type == 2) $discount->description='(CREDIT_NOTE)'; - elseif ($this->invoice->type == 3) $discount->description='(DEPOSIT)'; - else { - $this->error="CantConvertToReducAnInvoiceOfThisType"; - return -1; - } - $discount->tva_tx=abs($this->invoice->total_ttc); - $discount->fk_soc=$this->invoice->socid; - $discount->fk_facture_source=$this->invoice->id; - - $error=0; - 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->tva_tx=abs($tva_tx); - - $result=$discount->create(DolibarrApiAccess::$user); - if ($result < 0) - { - $error++; - break; - } - } - - if (! $error) - { - // Classe facture - $result=$this->invoice->set_paid(DolibarrApiAccess::$user); - if ($result > 0) - { - //$mesg='OK'.$discount->id; - $this->db->commit(); - } - else - { - $this->db->rollback(); - throw new RestException(500, 'Could not set paid'); - } - } - else - { - $this->db->rollback(); - throw new RestException(500, 'Discount creation error'); - } - } - - $result = $this->invoice->fetch($id); - if( ! $result ) { - throw new RestException(404, 'Invoice not found'); + + $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_paiements'; + $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_paiements = $res->total_paiements; + + // 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_paiements + $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->set_paid(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'); + } } - - if( ! DolibarrApi::_checkAccessToResource('facture', $this->invoice->id)) { - throw new RestException(401, 'Access not allowed for login '.DolibarrApiAccess::$user->login); - } - + return $this->_cleanObjectDatas($this->invoice); }