diff --git a/Core/Model/Base/BusinessDocument.php b/Core/Model/Base/BusinessDocument.php index f4b1527547..39b72e7465 100644 --- a/Core/Model/Base/BusinessDocument.php +++ b/Core/Model/Base/BusinessDocument.php @@ -310,6 +310,28 @@ public function getEUDiscount(): float return $eud; } + /** + * Devuelve el descuento total de todo el documento. + * Este cálculo tiene en cuenta tanto los descuentos globales aplicados al documento + * como los descuentos individuales aplicados en cada una de las líneas. + * + * OJO, sin tener en cuenta impuestos. + * Se redondea el resultado con los decimales configurados por el sistema para evitar problemas de precisión en coma flotante. + * + * @return float Descuento total calculado. + */ + public function getTotalDiscounts(): float + { + $netoNoDto = 0.0; + foreach ($this->getLines() as $line) { + // sumar las lineas sin descuentos + $netoNoDto += $line->pvpsindto; + } + + // devolver el neto (total con descuento sin impuestos) - sumaLineasSinDto + return Tools::round($netoNoDto - $this->neto); + } + /** * Esta función se ejecuta al crear la tabla del modelo. Devuelve el SQL * que se ejecutará después de la creación de la tabla. Útil para insertar valores diff --git a/Test/Core/Model/PresupuestoClienteTest.php b/Test/Core/Model/PresupuestoClienteTest.php index 9fe41ec38f..dee1fbc2cb 100644 --- a/Test/Core/Model/PresupuestoClienteTest.php +++ b/Test/Core/Model/PresupuestoClienteTest.php @@ -511,6 +511,91 @@ public function testSplitDocument(): void $this->assertTrue($subject->delete(), 'cliente-cant-delete'); } + // testear la función de obtener el descuento total + public function testGetTotalDiscounts(): void + { + // creamos un cliente + $subject = $this->getRandomCustomer(); + $this->assertTrue($subject->save()); + + // creamos un presupuesto y le asignamos el cliente + $doc = new PresupuestoCliente(); + $this->assertTrue($doc->setSubject($subject)); + $this->assertTrue($doc->save(), 'can-not-create-presupuesto-cliente'); + + // añadimos una línea + $line = $doc->getNewLine(); + $line->cantidad = 1; + $line->descripcion = 'Linea de prueba'; + $line->pvpunitario = 100; + $this->assertTrue($line->save(), 'can-not-save-line'); + + // 1. Caso sin descuentos + $doc->dtopor1 = 0; + $line->dtopor = 0; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(0, $doc->getTotalDiscounts(), 'bad-total-discounts-none'); + + // 2. Caso con descuentos globales solamente + $doc->dtopor1 = 10; + $line->dtopor = 0; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(10, $doc->getTotalDiscounts(), 'bad-total-discounts-global'); + + // 3. Caso con descuentos en lineas solamente + $doc->dtopor1 = 0; + $line->dtopor = 10; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(10, $doc->getTotalDiscounts(), 'bad-total-discounts-line'); + + // 4. Caso con descuentos en lineas y globales + $doc->dtopor1 = 10; + $doc->dtopor2 = 0; + $line->dtopor = 10; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(19, $doc->getTotalDiscounts(), 'bad-total-discounts-both'); + + // 5. Caso con segundo descuento global solamente + $doc->dtopor1 = 0; + $doc->dtopor2 = 10; + $line->dtopor = 0; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(10, $doc->getTotalDiscounts(), 'bad-total-discounts-global-2'); + + // 6. Caso con ambos descuentos globales + $doc->dtopor1 = 10; + $doc->dtopor2 = 10; + $line->dtopor = 0; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(19, $doc->getTotalDiscounts(), 'bad-total-discounts-global-both'); + + // 7. Caso con todos los descuentos (ambos globales y en línea) + $doc->dtopor1 = 10; + $doc->dtopor2 = 10; + $line->dtopor = 10; + $this->assertTrue($line->save()); + $lines = $doc->getLines(); + $this->assertTrue(Calculator::calculate($doc, $lines, true)); + $this->assertEquals(27.1, $doc->getTotalDiscounts(), 'bad-total-discounts-all'); + + // eliminamos + $this->assertTrue($doc->delete(), 'presupuesto-cant-delete'); + $this->assertTrue($subject->getDefaultAddress()->delete(), 'contacto-cant-delete'); + $this->assertTrue($subject->delete(), 'cliente-cant-delete'); + } + protected function setUp(): void { $this->logErrors();