Skip to content

Commit d011619

Browse files
[ISSUE-30] La base imponible a nivel de linea difiere de la información consignada en el comprobante (#31)
* Fix issue-30 * add valid xml for onerosa * Fix tests * Add license
1 parent 8bc9134 commit d011619

File tree

13 files changed

+920
-40
lines changed

13 files changed

+920
-40
lines changed

src/main/java/io/github/project/openubl/xmlbuilderlib/factory/DocumentLineOutputModelFactory.java

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,17 +53,27 @@ public static DocumentLineOutputModel getDocumentLineOutput(DocumentLineInputMod
5353
// Precio con/sin impuestos
5454
BigDecimal precioUnitario;
5555
BigDecimal precioConIgv;
56+
BigDecimal valorVentaSinImpuestos;
5657

5758
if (input.getPrecioUnitario() != null) {
5859
precioUnitario = input.getPrecioUnitario();
5960
precioConIgv = input.getPrecioUnitario().multiply(input.getCantidad())
6061
.add(impuestosOutput.getIgv().getImporte())
6162
.divide(input.getCantidad(), 2, RoundingMode.HALF_EVEN);
63+
64+
// Valor de venta (sin impuestos)
65+
valorVentaSinImpuestos = precioUnitario.multiply(input.getCantidad())
66+
.setScale(2, RoundingMode.HALF_EVEN);
6267
} else if (input.getPrecioConIgv() != null) {
6368
precioUnitario = input.getPrecioConIgv().multiply(input.getCantidad())
6469
.subtract(impuestosOutput.getIgv().getImporte())
6570
.divide(input.getCantidad(), 2, RoundingMode.HALF_EVEN);
6671
precioConIgv = input.getPrecioConIgv();
72+
73+
// Valor de venta (sin impuestos)
74+
valorVentaSinImpuestos = precioConIgv.multiply(input.getCantidad())
75+
.subtract(impuestosOutput.getIgv().getImporte())
76+
.setScale(2, RoundingMode.HALF_EVEN);
6777
} else {
6878
throw new IllegalStateException("Precio con impuestos y/o sin impuestos no encontrado, no se pueden calcular el precion con impuestos");
6979
}
@@ -74,10 +84,16 @@ public static DocumentLineOutputModel getDocumentLineOutput(DocumentLineInputMod
7484
impuestosOutput.getIgv().getTipo().isOperacionOnerosa() ? precioUnitario : BigDecimal.ZERO
7585
);
7686

87+
// Valor de venta (sin impuestos)
88+
builder.withValorVentaSinImpuestos(valorVentaSinImpuestos);
7789

7890
// Precio de referencia
7991
builder.withPrecioDeReferencia(DocumentLinePrecioReferenciaOutputModel.Builder.aDetallePrecioReferenciaOutputModel()
80-
.withPrecio(precioConIgv)
92+
.withPrecio(
93+
impuestosOutput.getIgv().getTipo().isOperacionOnerosa()
94+
? precioConIgv
95+
: precioUnitario
96+
)
8197
.withTipoPrecio(
8298
impuestosOutput.getIgv().getTipo().isOperacionOnerosa()
8399
? Catalog16.PRECIO_UNITARIO_INCLUYE_IGV
@@ -86,14 +102,6 @@ public static DocumentLineOutputModel getDocumentLineOutput(DocumentLineInputMod
86102
.build()
87103
);
88104

89-
// Valor de venta (sin impuestos)
90-
BigDecimal valorVentaSinImpuestos = input.getCantidad().multiply(precioConIgv).setScale(2, RoundingMode.HALF_EVEN);
91-
92-
if (impuestosOutput.getIgv().getTipo().isOperacionOnerosa()) {
93-
valorVentaSinImpuestos = valorVentaSinImpuestos.subtract(impuestosOutput.getIgv().getImporte());
94-
}
95-
builder.withValorVentaSinImpuestos(valorVentaSinImpuestos);
96-
97105
return builder.build();
98106
}
99107

src/main/java/io/github/project/openubl/xmlbuilderlib/factory/InvoiceAndNoteOutputModelFactory.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,6 @@ private static void enrichDocument(DocumentInputModel input, DocumentOutputModel
180180
// Gratuito
181181
ImpuestoTotalOutputModel gratuito = getImpuestoTotal(lineOutput, Catalog5.GRATUITO);
182182
if (gratuito.getBaseImponible().compareTo(BigDecimal.ZERO) > 0) {
183-
gratuito.setImporte(BigDecimal.ZERO);
184183
impuestosBuilder.withInafectas(gratuito);
185184
}
186185

Lines changed: 229 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,229 @@
1+
/**
2+
* Copyright 2019 Project OpenUBL, Inc. and/or its affiliates
3+
* and other contributors as indicated by the @author tags.
4+
*
5+
* Licensed under the Eclipse Public License - v 2.0 (the "License");
6+
* you may not use this file except in compliance with the License.
7+
* You may obtain a copy of the License at
8+
*
9+
* https://www.eclipse.org/legal/epl-2.0/
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package io.github.project.openubl.xmlbuilderlib.integrationtest.ubl.invoice.issues;
18+
19+
import io.github.project.openubl.xmlbuilderlib.facade.DocumentManager;
20+
import io.github.project.openubl.xmlbuilderlib.facade.DocumentWrapper;
21+
import io.github.project.openubl.xmlbuilderlib.integrationtest.AbstractUBLTest;
22+
import io.github.project.openubl.xmlbuilderlib.models.catalogs.Catalog6;
23+
import io.github.project.openubl.xmlbuilderlib.models.input.common.ClienteInputModel;
24+
import io.github.project.openubl.xmlbuilderlib.models.input.common.DireccionInputModel;
25+
import io.github.project.openubl.xmlbuilderlib.models.input.common.FirmanteInputModel;
26+
import io.github.project.openubl.xmlbuilderlib.models.input.common.ProveedorInputModel;
27+
import io.github.project.openubl.xmlbuilderlib.models.input.standard.DocumentLineInputModel;
28+
import io.github.project.openubl.xmlbuilderlib.models.input.standard.invoice.InvoiceInputModel;
29+
import io.github.project.openubl.xmlbuilderlib.models.output.standard.invoice.InvoiceOutputModel;
30+
import org.junit.jupiter.api.Test;
31+
32+
import java.math.BigDecimal;
33+
import java.util.Collections;
34+
35+
/**
36+
* Description: La base imponible a nivel de linea difiere de la información consiganada en el comprobante
37+
* Issue: https://github.com/project-openubl/xbuilder/issues/30
38+
*/
39+
public class Issue30 extends AbstractUBLTest {
40+
41+
public Issue30() throws Exception {
42+
}
43+
44+
@Test
45+
void testInvoice_withPrecioUnitario() throws Exception {
46+
// Given
47+
InvoiceInputModel input = InvoiceInputModel.Builder.anInvoiceInputModel()
48+
.withSerie("F001")
49+
.withNumero(1)
50+
.withProveedor(ProveedorInputModel.Builder.aProveedorInputModel()
51+
.withRuc("12345678912")
52+
.withRazonSocial("Project OpenUBL S.A.C.")
53+
.withDireccion(DireccionInputModel.Builder.aDireccionInputModel()
54+
.withDireccion("Jr. las flores 123")
55+
.build()
56+
)
57+
.build()
58+
)
59+
.withCliente(ClienteInputModel.Builder.aClienteInputModel()
60+
.withNombre("Carlos Feria")
61+
.withNumeroDocumentoIdentidad("12121212121")
62+
.withTipoDocumentoIdentidad(Catalog6.RUC.toString())
63+
.build()
64+
)
65+
.withFirmante(FirmanteInputModel.Builder.aFirmanteInputModel()
66+
.withRuc("000000000000")
67+
.withRazonSocial("Wolsnut4 S.A.C.")
68+
.build()
69+
)
70+
.withDetalle(Collections.singletonList(
71+
DocumentLineInputModel.Builder.aDocumentLineInputModel()
72+
.withDescripcion("Item1")
73+
.withCantidad(new BigDecimal("10"))
74+
.withPrecioUnitario(new BigDecimal("6.68"))
75+
.build()
76+
))
77+
.build();
78+
79+
// When
80+
DocumentWrapper<InvoiceOutputModel> result = DocumentManager.createXML(input, config, systemClock);
81+
InvoiceOutputModel output = result.getOutput();
82+
String xml = result.getXml();
83+
84+
// Then
85+
assertOutputHasNoConstraintViolations(validator, output);
86+
assertSnapshot(xml, "xml/invoice/issues/issue-30-with-precioUnitario.xml");
87+
assertSendSunat(xml, PROVIDER_WITHOUT_ADDRESS_NOTE);
88+
}
89+
90+
@Test
91+
void testInvoice_withPrecioConIgv() throws Exception {
92+
// Given
93+
InvoiceInputModel input = InvoiceInputModel.Builder.anInvoiceInputModel()
94+
.withSerie("F001")
95+
.withNumero(1)
96+
.withProveedor(ProveedorInputModel.Builder.aProveedorInputModel()
97+
.withRuc("12345678912")
98+
.withRazonSocial("Project OpenUBL S.A.C.")
99+
.withDireccion(DireccionInputModel.Builder.aDireccionInputModel()
100+
.withDireccion("Jr. las flores 123")
101+
.build()
102+
)
103+
.build()
104+
)
105+
.withCliente(ClienteInputModel.Builder.aClienteInputModel()
106+
.withNombre("Carlos Feria")
107+
.withNumeroDocumentoIdentidad("12121212121")
108+
.withTipoDocumentoIdentidad(Catalog6.RUC.toString())
109+
.build()
110+
)
111+
.withFirmante(FirmanteInputModel.Builder.aFirmanteInputModel()
112+
.withRuc("000000000000")
113+
.withRazonSocial("Wolsnut4 S.A.C.")
114+
.build()
115+
)
116+
.withDetalle(Collections.singletonList(
117+
DocumentLineInputModel.Builder.aDocumentLineInputModel()
118+
.withDescripcion("Item1")
119+
.withCantidad(new BigDecimal("10"))
120+
.withPrecioConIgv(new BigDecimal("7.88"))
121+
.build()
122+
))
123+
.build();
124+
125+
// When
126+
DocumentWrapper<InvoiceOutputModel> result = DocumentManager.createXML(input, config, systemClock);
127+
InvoiceOutputModel output = result.getOutput();
128+
String xml = result.getXml();
129+
130+
// Then
131+
assertOutputHasNoConstraintViolations(validator, output);
132+
assertSnapshot(xml, "xml/invoice/issues/issue-30-with-precioConIgv.xml");
133+
assertSendSunat(xml, PROVIDER_WITHOUT_ADDRESS_NOTE);
134+
}
135+
136+
@Test
137+
void testInvoice_withPrecioUnitario_andICB() throws Exception {
138+
// Given
139+
InvoiceInputModel input = InvoiceInputModel.Builder.anInvoiceInputModel()
140+
.withSerie("F001")
141+
.withNumero(1)
142+
.withProveedor(ProveedorInputModel.Builder.aProveedorInputModel()
143+
.withRuc("12345678912")
144+
.withRazonSocial("Project OpenUBL S.A.C.")
145+
.withDireccion(DireccionInputModel.Builder.aDireccionInputModel()
146+
.withDireccion("Jr. las flores 123")
147+
.build()
148+
)
149+
.build()
150+
)
151+
.withCliente(ClienteInputModel.Builder.aClienteInputModel()
152+
.withNombre("Carlos Feria")
153+
.withNumeroDocumentoIdentidad("12121212121")
154+
.withTipoDocumentoIdentidad(Catalog6.RUC.toString())
155+
.build()
156+
)
157+
.withFirmante(FirmanteInputModel.Builder.aFirmanteInputModel()
158+
.withRuc("000000000000")
159+
.withRazonSocial("Wolsnut4 S.A.C.")
160+
.build()
161+
)
162+
.withDetalle(Collections.singletonList(
163+
DocumentLineInputModel.Builder.aDocumentLineInputModel()
164+
.withDescripcion("Item1")
165+
.withCantidad(new BigDecimal("10"))
166+
.withPrecioUnitario(new BigDecimal("6.68"))
167+
.withIcb(true)
168+
.build()
169+
))
170+
.build();
171+
172+
// When
173+
DocumentWrapper<InvoiceOutputModel> result = DocumentManager.createXML(input, config, systemClock);
174+
InvoiceOutputModel output = result.getOutput();
175+
String xml = result.getXml();
176+
177+
// Then
178+
assertOutputHasNoConstraintViolations(validator, output);
179+
assertSnapshot(xml, "xml/invoice/issues/issue-30-with-precioUnitario_andICB.xml");
180+
assertSendSunat(xml, PROVIDER_WITHOUT_ADDRESS_NOTE);
181+
}
182+
183+
@Test
184+
void testInvoice_withPrecioConIgv_andICB() throws Exception {
185+
// Given
186+
InvoiceInputModel input = InvoiceInputModel.Builder.anInvoiceInputModel()
187+
.withSerie("F001")
188+
.withNumero(1)
189+
.withProveedor(ProveedorInputModel.Builder.aProveedorInputModel()
190+
.withRuc("12345678912")
191+
.withRazonSocial("Project OpenUBL S.A.C.")
192+
.withDireccion(DireccionInputModel.Builder.aDireccionInputModel()
193+
.withDireccion("Jr. las flores 123")
194+
.build()
195+
)
196+
.build()
197+
)
198+
.withCliente(ClienteInputModel.Builder.aClienteInputModel()
199+
.withNombre("Carlos Feria")
200+
.withNumeroDocumentoIdentidad("12121212121")
201+
.withTipoDocumentoIdentidad(Catalog6.RUC.toString())
202+
.build()
203+
)
204+
.withFirmante(FirmanteInputModel.Builder.aFirmanteInputModel()
205+
.withRuc("000000000000")
206+
.withRazonSocial("Wolsnut4 S.A.C.")
207+
.build()
208+
)
209+
.withDetalle(Collections.singletonList(
210+
DocumentLineInputModel.Builder.aDocumentLineInputModel()
211+
.withDescripcion("Item1")
212+
.withCantidad(new BigDecimal("10"))
213+
.withPrecioConIgv(new BigDecimal("7.88"))
214+
.withIcb(true)
215+
.build()
216+
))
217+
.build();
218+
219+
// When
220+
DocumentWrapper<InvoiceOutputModel> result = DocumentManager.createXML(input, config, systemClock);
221+
InvoiceOutputModel output = result.getOutput();
222+
String xml = result.getXml();
223+
224+
// Then
225+
assertOutputHasNoConstraintViolations(validator, output);
226+
assertSnapshot(xml, "xml/invoice/issues/issue-30-with-precioConIgv_andICB.xml");
227+
assertSendSunat(xml, PROVIDER_WITHOUT_ADDRESS_NOTE);
228+
}
229+
}

0 commit comments

Comments
 (0)