Skip to content

Add support to perception and retention #153

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,22 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;
package io.github.project.openubl.xbuilder.content.models.common;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.time.LocalDate;

@Data
public class PercepcionRetencionDetalle {
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class TipoCambio {

private Integer numeroCobroPago;
private Long fechaCobroPago;
private BigDecimal importeCobroPago;
private ComprobanteAfectado comprobante;
private LocalDate fecha;
private BigDecimal valor;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,38 @@
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;

import io.github.project.openubl.xbuilder.content.models.common.Cliente;
import io.github.project.openubl.xbuilder.content.models.common.Firmante;
import io.github.project.openubl.xbuilder.content.models.common.Proveedor;
import io.github.project.openubl.xbuilder.content.models.common.Document;
import io.github.project.openubl.xbuilder.content.models.common.TipoCambio;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.SuperBuilder;

import java.math.BigDecimal;
import java.util.List;

@Data
@SuperBuilder
public abstract class BasePercepcionRetencion {
@EqualsAndHashCode(callSuper = true)
public abstract class BasePercepcionRetencion extends Document {

/**
* Número del comprobante
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "1", maximum = "99999999")
private Integer numero;
private Long fechaEmision;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0", maximum = "100", exclusiveMinimum = true)
private BigDecimal tipoRegimenPorcentaje;

private String observacion;
private Proveedor proveedor;

/**
* Cliente
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private Cliente cliente;
private Firmante firmante;
private List<PercepcionRetencionDetalle> detalle;

private PercepcionRetencionOperacion operacion;

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,31 @@
*/
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.time.LocalDate;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class ComprobanteAfectado {

private String moneda;
private String tipo;

@Schema(description = "Catalogo 01")
private String tipoComprobante;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private String serieNumero;
private Long fechaEmision;

@Schema(description = "Format: \"YYYY-MM-SS\". Ejemplo: 2022-12-25", pattern = "^\\d{4}-\\d{2}-\\d{2}$")
private LocalDate fechaEmision;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private BigDecimal importeTotal;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* Copyright 2019 Project OpenUBL, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License - 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;

import io.github.project.openubl.xbuilder.content.models.common.TipoCambio;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.math.BigDecimal;
import java.time.LocalDate;

@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class PercepcionRetencionOperacion {

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Numero de cobro o pago")
private Integer numeroOperacion;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Fecha en la que se realiza el cobro o pago")
private LocalDate fechaOperacion;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Importe del cobro o pago")
private BigDecimal importeOperacion;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED)
private ComprobanteAfectado comprobante;

private TipoCambio tipoCambio;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,33 @@
*/
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;

import java.math.BigDecimal;

@Jacksonized
@Data
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Retencion extends BasePercepcionRetencion {

public class Perception extends BasePercepcionRetencion {
/**
* Serie del comprobante
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minLength = 4, pattern = "^[P|p].*$")
private String serie;
private String regimen;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Catalog 22")
private String tipoRegimen;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
private BigDecimal importeTotalPercibido;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
private BigDecimal importeTotalCobrado;
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,33 @@
*/
package io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion;

import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
import lombok.extern.jackson.Jacksonized;

import java.math.BigDecimal;

@Jacksonized
@Data
@SuperBuilder
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class Percepcion extends BasePercepcionRetencion {

public class Retention extends BasePercepcionRetencion {
/**
* Serie del comprobante
*/
@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minLength = 4, pattern = "^[R|r].*$")
private String serie;
private String regimen;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, description = "Catalog 23")
private String tipoRegimen;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
private BigDecimal importeTotalRetenido;

@Schema(requiredMode = Schema.RequiredMode.REQUIRED, minimum = "0")
private BigDecimal importeTotalPagado;
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
import io.github.project.openubl.xbuilder.content.models.standard.general.Invoice;
import io.github.project.openubl.xbuilder.content.models.standard.general.Note;
import io.github.project.openubl.xbuilder.content.models.sunat.baja.VoidedDocuments;
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Perception;
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Retention;
import io.github.project.openubl.xbuilder.content.models.sunat.resumen.SummaryDocuments;
import io.github.project.openubl.xbuilder.enricher.config.DateProvider;
import io.github.project.openubl.xbuilder.enricher.config.Defaults;
Expand Down Expand Up @@ -117,6 +119,40 @@ public void enrich(SummaryDocuments input) {
});
}

public void enrich(Perception input) {
LocalDate systemLocalDate = dateProvider.now();

Stream
.of(RulePhase.PhaseType.ENRICH, RulePhase.PhaseType.PROCESS, RulePhase.PhaseType.SUMMARY)
.forEach(phaseType -> {
// Header
HeaderRuleContext ruleContextHeader = HeaderRuleContext.builder()
.localDate(systemLocalDate)
.build();
RuleUnit ruleUnitHeader = new HeaderRuleUnit(phaseType, defaults, ruleContextHeader);
ruleUnitHeader.modify(input);

// Body
});
}

public void enrich(Retention input) {
LocalDate systemLocalDate = dateProvider.now();

Stream
.of(RulePhase.PhaseType.ENRICH, RulePhase.PhaseType.PROCESS, RulePhase.PhaseType.SUMMARY)
.forEach(phaseType -> {
// Header
HeaderRuleContext ruleContextHeader = HeaderRuleContext.builder()
.localDate(systemLocalDate)
.build();
RuleUnit ruleUnitHeader = new HeaderRuleUnit(phaseType, defaults, ruleContextHeader);
ruleUnitHeader.modify(input);

// Body
});
}

private void enrichNote(Note input) {
LocalDate systemLocalDate = dateProvider.now();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@
import io.github.project.openubl.xbuilder.content.models.standard.general.SalesDocument;
import io.github.project.openubl.xbuilder.content.models.sunat.baja.VoidedDocuments;
import io.github.project.openubl.xbuilder.content.models.sunat.baja.VoidedDocumentsItem;
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Perception;
import io.github.project.openubl.xbuilder.content.models.sunat.percepcionretencion.Retention;
import io.github.project.openubl.xbuilder.content.models.sunat.resumen.SummaryDocuments;
import io.github.project.openubl.xbuilder.content.models.sunat.resumen.SummaryDocumentsItem;

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

public static final Predicate<Object> isDocument = isInvoice.or(isCreditNote).or(isDebitNote).or(isVoidedDocuments).or(isSummaryDocuments);
public static final Predicate<Object> isPerception = o -> o instanceof Perception;
public static final Predicate<Object> isRetention = o -> o instanceof Retention;

public static final Predicate<Object> isDocument = isInvoice.or(isCreditNote).or(isDebitNote)
.or(isVoidedDocuments).or(isSummaryDocuments)
.or(isPerception).or(isRetention);

public static final Predicate<Object> isSalesDocument = isInvoice.or(isCreditNote).or(isDebitNote);
public static final Predicate<Object> isSalesDocumentItem = o -> o instanceof DocumentoVentaDetalle;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,14 @@ public Template getSummaryDocuments() {
return EngineProducer.getInstance().getEngine().getTemplate("Renderer/summaryDocuments.xml");
}

public Template getPerception() {
return EngineProducer.getInstance().getEngine().getTemplate("Renderer/perception.xml");
}

public Template getRetention() {
return EngineProducer.getInstance().getEngine().getTemplate("Renderer/retention.xml");
}

private static class TemplateProducerHolder {

private static final TemplateProducer INSTANCE = new TemplateProducer();
Expand Down
54 changes: 54 additions & 0 deletions core/src/main/resources/templates/Renderer/perception.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<Perception xmlns="urn:sunat:names:specification:ubl:peru:schema:xsd:Perception-1"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:ccts="urn:un:unece:uncefact:documentation:2"
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:qdt="urn:oasis:names:specification:ubl:schema:xsd:QualifiedDatatypes-2"
xmlns:sac="urn:sunat:names:specification:ubl:peru:schema:xsd:SunatAggregateComponents-1"
xmlns:udt="urn:un:unece:uncefact:data:specification:UnqualifiedDataTypesSchemaModule:2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionContent />
</ext:UBLExtension>
</ext:UBLExtensions>
<cbc:UBLVersionID>2.0</cbc:UBLVersionID>
<cbc:CustomizationID>1.0</cbc:CustomizationID>
{#include ubl/common/signature.xml firmante=this.firmante /}
<cbc:ID>{serie}-{numero}</cbc:ID>
<cbc:IssueDate>{fechaEmision}</cbc:IssueDate>
{#include ubl/sunat/include/agent-party.xml proveedor=this.proveedor /}
{#include ubl/sunat/include/receiver-party.xml cliente=this.cliente /}
<sac:SUNATPerceptionSystemCode>{tipoRegimen}</sac:SUNATPerceptionSystemCode>
<sac:SUNATPerceptionPercent>{tipoRegimenPorcentaje}</sac:SUNATPerceptionPercent>
{#if observacion}
<cbc:Note><![CDATA[{observacion}]]></cbc:Note>
{/if}
<cbc:TotalInvoiceAmount currencyID="{moneda}">{importeTotalPercibido}</cbc:TotalInvoiceAmount>
<sac:SUNATTotalCashed currencyID="{moneda}">{importeTotalCobrado}</sac:SUNATTotalCashed>
<sac:SUNATPerceptionDocumentReference>
<cbc:ID schemeID="{operacion.comprobante.tipoComprobante}">{operacion.comprobante.serieNumero}</cbc:ID>
<cbc:IssueDate>{operacion.comprobante.fechaEmision}</cbc:IssueDate>
<cbc:TotalInvoiceAmount currencyID="{operacion.comprobante.moneda}">{operacion.comprobante.importeTotal}</cbc:TotalInvoiceAmount>
<cac:Payment>
<cbc:ID>{operacion.numeroOperacion}</cbc:ID>
<cbc:PaidAmount currencyID="{operacion.comprobante.moneda}">{operacion.importeOperacion}</cbc:PaidAmount>
<cbc:PaidDate>{operacion.fechaOperacion}</cbc:PaidDate>
</cac:Payment>
<sac:SUNATPerceptionInformation>
<sac:SUNATPerceptionAmount currencyID="{moneda}">{importeTotalPercibido}</sac:SUNATPerceptionAmount>
<sac:SUNATPerceptionDate>{fechaEmision}</sac:SUNATPerceptionDate>
<sac:SUNATNetTotalCashed currencyID="{moneda}">{importeTotalCobrado}</sac:SUNATNetTotalCashed>
{#if operacion.tipoCambio}
<cac:ExchangeRate>
<cbc:SourceCurrencyCode>{moneda}</cbc:SourceCurrencyCode>
<cbc:TargetCurrencyCode>{operacion.comprobante.moneda}</cbc:TargetCurrencyCode>
<cbc:CalculationRate>{operacion.tipoCambio.valor}</cbc:CalculationRate>
<cbc:Date>{operacion.tipoCambio.fecha}</cbc:Date>
</cac:ExchangeRate>
{/if}
</sac:SUNATPerceptionInformation>
</sac:SUNATPerceptionDocumentReference>
</Perception>
Loading