From 4597e78a9dfdfde7a348c28f1e4ae0669d789ab6 Mon Sep 17 00:00:00 2001 From: Dan Rusu Date: Sat, 6 Apr 2019 20:10:11 +0300 Subject: [PATCH] Re synchronized the UI action button "Mark as credit available" with API At some point we will need to move this code into common location (maybe facture.class.php) and call as function from both places --- .../facture/class/api_invoices.class.php | 224 +++++++++++------- 1 file changed, 140 insertions(+), 84 deletions(-) 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); }