Skip to content

Commit ceb5d4d

Browse files
Add support to perception and retention (#153)
* Add support to perception and retention * Add lombok annotations for super * Add BasePerceptionRetention to quarkus extension reflection
1 parent 130fc2d commit ceb5d4d

File tree

26 files changed

+932
-240
lines changed

26 files changed

+932
-240
lines changed
Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,22 @@
1414
* See the License for the specific language governing permissions and
1515
* limitations under the License.
1616
*/
17-
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;
17+
package io.github.project.openubl.xbuilder.content.models.common;
1818

19+
import lombok.AllArgsConstructor;
20+
import lombok.Builder;
1921
import lombok.Data;
22+
import lombok.NoArgsConstructor;
2023

2124
import java.math.BigDecimal;
25+
import java.time.LocalDate;
2226

2327
@Data
24-
public class PercepcionRetencionDetalle {
28+
@Builder
29+
@NoArgsConstructor
30+
@AllArgsConstructor
31+
public class TipoCambio {
2532

26-
private Integer numeroCobroPago;
27-
private Long fechaCobroPago;
28-
private BigDecimal importeCobroPago;
29-
private ComprobanteAfectado comprobante;
33+
private LocalDate fecha;
34+
private BigDecimal valor;
3035
}

core/src/main/java/io/github/project/openubl/xbuilder/content/models/sunat/percepcionretencion/BasePercepcionRetencion.java

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -17,22 +17,38 @@
1717
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;
1818

1919
import io.github.project.openubl.xbuilder.content.models.common.Cliente;
20-
import io.github.project.openubl.xbuilder.content.models.common.Firmante;
21-
import io.github.project.openubl.xbuilder.content.models.common.Proveedor;
20+
import io.github.project.openubl.xbuilder.content.models.common.Document;
21+
import io.github.project.openubl.xbuilder.content.models.common.TipoCambio;
22+
import io.swagger.v3.oas.annotations.media.Schema;
2223
import lombok.Data;
24+
import lombok.EqualsAndHashCode;
2325
import lombok.experimental.SuperBuilder;
2426

27+
import java.math.BigDecimal;
2528
import java.util.List;
2629

2730
@Data
2831
@SuperBuilder
29-
public abstract class BasePercepcionRetencion {
32+
@EqualsAndHashCode(callSuper = true)
33+
public abstract class BasePercepcionRetencion extends Document {
3034

35+
/**
36+
* Número del comprobante
37+
*/
38+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "1", maximum = "99999999")
3139
private Integer numero;
32-
private Long fechaEmision;
40+
41+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0", maximum = "100", exclusiveMinimum = true)
42+
private BigDecimal tipoRegimenPorcentaje;
43+
3344
private String observacion;
34-
private Proveedor proveedor;
45+
46+
/**
47+
* Cliente
48+
*/
49+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
3550
private Cliente cliente;
36-
private Firmante firmante;
37-
private List<PercepcionRetencionDetalle> detalle;
51+
52+
private PercepcionRetencionOperacion operacion;
53+
3854
}

core/src/main/java/io/github/project/openubl/xbuilder/content/models/sunat/percepcionretencion/ComprobanteAfectado.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,31 @@
1616
*/
1717
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;
1818

19+
import io.swagger.v3.oas.annotations.media.Schema;
20+
import lombok.AllArgsConstructor;
21+
import lombok.Builder;
1922
import lombok.Data;
23+
import lombok.NoArgsConstructor;
2024

2125
import java.math.BigDecimal;
26+
import java.time.LocalDate;
2227

2328
@Data
29+
@Builder
30+
@NoArgsConstructor
31+
@AllArgsConstructor
2432
public class ComprobanteAfectado {
25-
2633
private String moneda;
27-
private String tipo;
34+
35+
@Schema(description = "Catalogo 01")
36+
private String tipoComprobante;
37+
38+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
2839
private String serieNumero;
29-
private Long fechaEmision;
40+
41+
@Schema(description = "Format: \"YYYY-MM-SS\". Ejemplo: 2022-12-25", pattern = "^\\d{4}-\\d{2}-\\d{2}$")
42+
private LocalDate fechaEmision;
43+
44+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
3045
private BigDecimal importeTotal;
3146
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
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 Apache License - 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.apache.org/licenses/LICENSE-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.xbuilder.content.models.sunat.percepcionretencion;
18+
19+
import io.github.project.openubl.xbuilder.content.models.common.TipoCambio;
20+
import io.swagger.v3.oas.annotations.media.Schema;
21+
import lombok.AllArgsConstructor;
22+
import lombok.Builder;
23+
import lombok.Data;
24+
import lombok.NoArgsConstructor;
25+
26+
import java.math.BigDecimal;
27+
import java.time.LocalDate;
28+
29+
@Data
30+
@Builder
31+
@NoArgsConstructor
32+
@AllArgsConstructor
33+
public class PercepcionRetencionOperacion {
34+
35+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Numero de cobro o pago")
36+
private Integer numeroOperacion;
37+
38+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Fecha en la que se realiza el cobro o pago")
39+
private LocalDate fechaOperacion;
40+
41+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Importe del cobro o pago")
42+
private BigDecimal importeOperacion;
43+
44+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
45+
private ComprobanteAfectado comprobante;
46+
47+
private TipoCambio tipoCambio;
48+
}
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,33 @@
1616
*/
1717
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;
1818

19+
import io.swagger.v3.oas.annotations.media.Schema;
1920
import lombok.Data;
2021
import lombok.EqualsAndHashCode;
2122
import lombok.ToString;
2223
import lombok.experimental.SuperBuilder;
24+
import lombok.extern.jackson.Jacksonized;
2325

26+
import java.math.BigDecimal;
27+
28+
@Jacksonized
2429
@Data
2530
@SuperBuilder
2631
@EqualsAndHashCode(callSuper = true)
2732
@ToString(callSuper = true)
28-
public class Retencion extends BasePercepcionRetencion {
29-
33+
public class Perception extends BasePercepcionRetencion {
34+
/**
35+
* Serie del comprobante
36+
*/
37+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minLength = 4, pattern = "^[P|p].*$")
3038
private String serie;
31-
private String regimen;
39+
40+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Catalog 22")
41+
private String tipoRegimen;
42+
43+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
44+
private BigDecimal importeTotalPercibido;
45+
46+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
47+
private BigDecimal importeTotalCobrado;
3248
}
Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,33 @@
1616
*/
1717
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;
1818

19+
import io.swagger.v3.oas.annotations.media.Schema;
1920
import lombok.Data;
2021
import lombok.EqualsAndHashCode;
2122
import lombok.ToString;
2223
import lombok.experimental.SuperBuilder;
24+
import lombok.extern.jackson.Jacksonized;
2325

26+
import java.math.BigDecimal;
27+
28+
@Jacksonized
2429
@Data
2530
@SuperBuilder
2631
@EqualsAndHashCode(callSuper = true)
2732
@ToString(callSuper = true)
28-
public class Percepcion extends BasePercepcionRetencion {
29-
33+
public class Retention extends BasePercepcionRetencion {
34+
/**
35+
* Serie del comprobante
36+
*/
37+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minLength = 4, pattern = "^[R|r].*$")
3038
private String serie;
31-
private String regimen;
39+
40+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Catalog 23")
41+
private String tipoRegimen;
42+
43+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
44+
private BigDecimal importeTotalRetenido;
45+
46+
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
47+
private BigDecimal importeTotalPagado;
3248
}

core/src/main/java/io/github/project/openubl/xbuilder/enricher/ContentEnricher.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
import io.github.project.openubl.xbuilder.content.models.standard.general.Invoice;
2222
import io.github.project.openubl.xbuilder.content.models.standard.general.Note;
2323
import io.github.project.openubl.xbuilder.content.models.sunat.baja.VoidedDocuments;
24+
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Perception;
25+
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Retention;
2426
import io.github.project.openubl.xbuilder.content.models.sunat.resumen.SummaryDocuments;
2527
import io.github.project.openubl.xbuilder.enricher.config.DateProvider;
2628
import io.github.project.openubl.xbuilder.enricher.config.Defaults;
@@ -117,6 +119,40 @@ public void enrich(SummaryDocuments input) {
117119
});
118120
}
119121

122+
public void enrich(Perception input) {
123+
LocalDate systemLocalDate = dateProvider.now();
124+
125+
Stream
126+
.of(RulePhase.PhaseType.ENRICH, RulePhase.PhaseType.PROCESS, RulePhase.PhaseType.SUMMARY)
127+
.forEach(phaseType -> {
128+
// Header
129+
HeaderRuleContext ruleContextHeader = HeaderRuleContext.builder()
130+
.localDate(systemLocalDate)
131+
.build();
132+
RuleUnit ruleUnitHeader = new HeaderRuleUnit(phaseType, defaults, ruleContextHeader);
133+
ruleUnitHeader.modify(input);
134+
135+
// Body
136+
});
137+
}
138+
139+
public void enrich(Retention input) {
140+
LocalDate systemLocalDate = dateProvider.now();
141+
142+
Stream
143+
.of(RulePhase.PhaseType.ENRICH, RulePhase.PhaseType.PROCESS, RulePhase.PhaseType.SUMMARY)
144+
.forEach(phaseType -> {
145+
// Header
146+
HeaderRuleContext ruleContextHeader = HeaderRuleContext.builder()
147+
.localDate(systemLocalDate)
148+
.build();
149+
RuleUnit ruleUnitHeader = new HeaderRuleUnit(phaseType, defaults, ruleContextHeader);
150+
ruleUnitHeader.modify(input);
151+
152+
// Body
153+
});
154+
}
155+
120156
private void enrichNote(Note input) {
121157
LocalDate systemLocalDate = dateProvider.now();
122158

core/src/main/java/io/github/project/openubl/xbuilder/enricher/kie/rules/utils/Helpers.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@
2626
import io.github.project.openubl.xbuilder.content.models.standard.general.SalesDocument;
2727
import io.github.project.openubl.xbuilder.content.models.sunat.baja.VoidedDocuments;
2828
import io.github.project.openubl.xbuilder.content.models.sunat.baja.VoidedDocumentsItem;
29+
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Perception;
30+
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Retention;
2931
import io.github.project.openubl.xbuilder.content.models.sunat.resumen.SummaryDocuments;
3032
import io.github.project.openubl.xbuilder.content.models.sunat.resumen.SummaryDocumentsItem;
3133

@@ -45,7 +47,12 @@ public class Helpers {
4547
public static final Predicate<Object> isSummaryDocuments = o -> o instanceof SummaryDocuments;
4648
public static final Predicate<Object> isSummaryDocumentsItem = o -> o instanceof SummaryDocumentsItem;
4749

48-
public static final Predicate<Object> isDocument = isInvoice.or(isCreditNote).or(isDebitNote).or(isVoidedDocuments).or(isSummaryDocuments);
50+
public static final Predicate<Object> isPerception = o -> o instanceof Perception;
51+
public static final Predicate<Object> isRetention = o -> o instanceof Retention;
52+
53+
public static final Predicate<Object> isDocument = isInvoice.or(isCreditNote).or(isDebitNote)
54+
.or(isVoidedDocuments).or(isSummaryDocuments)
55+
.or(isPerception).or(isRetention);
4956

5057
public static final Predicate<Object> isSalesDocument = isInvoice.or(isCreditNote).or(isDebitNote);
5158
public static final Predicate<Object> isSalesDocumentItem = o -> o instanceof DocumentoVentaDetalle;

core/src/main/java/io/github/project/openubl/xbuilder/renderer/TemplateProducer.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,14 @@ public Template getSummaryDocuments() {
4040
return EngineProducer.getInstance().getEngine().getTemplate("Renderer/summaryDocuments.xml");
4141
}
4242

43+
public Template getPerception() {
44+
return EngineProducer.getInstance().getEngine().getTemplate("Renderer/perception.xml");
45+
}
46+
47+
public Template getRetention() {
48+
return EngineProducer.getInstance().getEngine().getTemplate("Renderer/retention.xml");
49+
}
50+
4351
private static class TemplateProducerHolder {
4452

4553
private static final TemplateProducer INSTANCE = new TemplateProducer();
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?xml version="1.0" encoding="ISO-8859-1"?>
2+
<Perception xmlns="urn:sunat:names:specification:ubl:peru:schema:xsd:Perception-1"
3+
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
4+
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
5+
xmlns:ccts="urn:un:unece:uncefact:documentation:2"
6+
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
7+
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
8+
xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2"
9+
xmlns:sac="urn:sunat:names:specification:ubl:peru:schema:xsd:SunatAggregateComponents-1"
10+
xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2"
11+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
12+
<ext:UBLExtensions>
13+
<ext:UBLExtension>
14+
<ext:ExtensionContent />
15+
</ext:UBLExtension>
16+
</ext:UBLExtensions>
17+
<cbc:UBLVersionID>2.0</cbc:UBLVersionID>
18+
<cbc:CustomizationID>1.0</cbc:CustomizationID>
19+
{#include ubl/common/signature.xml firmante=this.firmante /}
20+
<cbc:ID>{serie}-{numero}</cbc:ID>
21+
<cbc:IssueDate>{fechaEmision}</cbc:IssueDate>
22+
{#include ubl/sunat/include/agent-party.xml proveedor=this.proveedor /}
23+
{#include ubl/sunat/include/receiver-party.xml cliente=this.cliente /}
24+
<sac:SUNATPerceptionSystemCode>{tipoRegimen}</sac:SUNATPerceptionSystemCode>
25+
<sac:SUNATPerceptionPercent>{tipoRegimenPorcentaje}</sac:SUNATPerceptionPercent>
26+
{#if observacion}
27+
<cbc:Note><![CDATA[{observacion}]]></cbc:Note>
28+
{/if}
29+
<cbc:TotalInvoiceAmount currencyID="{moneda}">{importeTotalPercibido}</cbc:TotalInvoiceAmount>
30+
<sac:SUNATTotalCashed currencyID="{moneda}">{importeTotalCobrado}</sac:SUNATTotalCashed>
31+
<sac:SUNATPerceptionDocumentReference>
32+
<cbc:ID schemeID="{operacion.comprobante.tipoComprobante}">{operacion.comprobante.serieNumero}</cbc:ID>
33+
<cbc:IssueDate>{operacion.comprobante.fechaEmision}</cbc:IssueDate>
34+
<cbc:TotalInvoiceAmount currencyID="{operacion.comprobante.moneda}">{operacion.comprobante.importeTotal}</cbc:TotalInvoiceAmount>
35+
<cac:Payment>
36+
<cbc:ID>{operacion.numeroOperacion}</cbc:ID>
37+
<cbc:PaidAmount currencyID="{operacion.comprobante.moneda}">{operacion.importeOperacion}</cbc:PaidAmount>
38+
<cbc:PaidDate>{operacion.fechaOperacion}</cbc:PaidDate>
39+
</cac:Payment>
40+
<sac:SUNATPerceptionInformation>
41+
<sac:SUNATPerceptionAmount currencyID="{moneda}">{importeTotalPercibido}</sac:SUNATPerceptionAmount>
42+
<sac:SUNATPerceptionDate>{fechaEmision}</sac:SUNATPerceptionDate>
43+
<sac:SUNATNetTotalCashed currencyID="{moneda}">{importeTotalCobrado}</sac:SUNATNetTotalCashed>
44+
{#if operacion.tipoCambio}
45+
<cac:ExchangeRate>
46+
<cbc:SourceCurrencyCode>{moneda}</cbc:SourceCurrencyCode>
47+
<cbc:TargetCurrencyCode>{operacion.comprobante.moneda}</cbc:TargetCurrencyCode>
48+
<cbc:CalculationRate>{operacion.tipoCambio.valor}</cbc:CalculationRate>
49+
<cbc:Date>{operacion.tipoCambio.fecha}</cbc:Date>
50+
</cac:ExchangeRate>
51+
{/if}
52+
</sac:SUNATPerceptionInformation>
53+
</sac:SUNATPerceptionDocumentReference>
54+
</Perception>

0 commit comments

Comments
 (0)