Skip to content
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 @@ -73,6 +73,28 @@
<cbc:ItemClassificationCode listID="UNSPSC" listAgencyName="GS1 US" listName="Item Classification">{{item.codigo_sunat}}</cbc:ItemClassificationCode>
</cac:CommodityClassification>
{%- endif %}
{%- for atributo in item.atributos %}
<cac:AdditionalItemProperty>
<cbc:Name>{{atributo.nombre}}</cbc:Name>
<cbc:NameCode>{{atributo.codigo}}</cbc:NameCode>
{%- if atributo.valor %}
<cbc:Value>{{atributo.valor}}</cbc:Value>
{%- endif %}
{%- if atributo.fecha_inicio or atributo.fecha_fin or atributo.duracion %}
<cac:UsabilityPeriod>
{%- if atributo.fecha_inicio %}
<cbc:StartDate>{{atributo.fecha_inicio}}</cbc:StartDate>
{%- endif %}
{%- if atributo.fecha_fin %}
<cbc:EndDate>{{atributo.fecha_fin}}</cbc:EndDate>
{%- endif %}
{%- if atributo.duracion %}
<cbc:DurationMeasure unitCode="DAY">{{atributo.duracion}}</cbc:DurationMeasure>
{%- endif %}
</cac:UsabilityPeriod>
{%- endif %}
</cac:AdditionalItemProperty>
{%- endfor %}
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="{{moneda}}">{{item.precio | round_decimal}}</cbc:PriceAmount>
Expand Down
13 changes: 13 additions & 0 deletions xbuilder/src/models/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,17 @@ pub struct CodigoGS1 {
pub tipo: &'static str,
}

/// Atributo adicional de un detalle
#[derive(Clone, Debug, Serialize, Default)]
pub struct Atributo {
pub nombre: &'static str,
pub codigo: &'static str,
pub valor: Option<&'static str>,
pub fecha_inicio: Option<NaiveDate>,
pub fecha_fin: Option<NaiveDate>,
pub duracion: Option<u32>,
}

/// Detalle de las ventas en Boleta/Factura/Nota Credito/Nota Debito
#[derive(Clone, Debug, Serialize, Default)]
pub struct Detalle {
Expand Down Expand Up @@ -190,6 +201,8 @@ pub struct Detalle {
pub isc_base_imponible: Option<Decimal>,

pub total_impuestos: Option<Decimal>,

pub atributos: Vec<Atributo>,
}

/// Total Importe Invoice
Expand Down
43 changes: 43 additions & 0 deletions xbuilder/tests/credit_note_atributos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use rust_decimal_macros::dec;

use xbuilder::prelude::*;

use crate::common::{assert_credit_note, credit_note_base};

mod common;

const BASE: &str = "tests/resources/e2e/renderer/creditnote/CreditNoteAtributosTest";

#[serial_test::serial]
#[tokio::test]
async fn credit_note_with_atributos() {
let mut credit_note = CreditNote {
detalles: vec![Detalle {
descripcion: "Item1",
cantidad: dec!(10),
precio: Some(dec!(100)),
atributos: vec![
Atributo {
nombre: "Marca",
codigo: "BRA",
valor: Some("Samsung"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
Atributo {
nombre: "Color",
codigo: "COL",
valor: Some("Negro"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
],
..Default::default()
}],
..credit_note_base()
};

assert_credit_note(&mut credit_note, &format!("{BASE}/atributosSimple.xml")).await;
}
43 changes: 43 additions & 0 deletions xbuilder/tests/debit_note_atributos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
use rust_decimal_macros::dec;

use xbuilder::prelude::*;

use crate::common::{assert_debit_note, debit_note_base};

mod common;

const BASE: &str = "tests/resources/e2e/renderer/debitnote/DebitNoteAtributosTest";

#[serial_test::serial]
#[tokio::test]
async fn debit_note_with_atributos() {
let mut debit_note = DebitNote {
detalles: vec![Detalle {
descripcion: "Item1",
cantidad: dec!(10),
precio: Some(dec!(100)),
atributos: vec![
Atributo {
nombre: "Marca",
codigo: "BRA",
valor: Some("Samsung"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
Atributo {
nombre: "Color",
codigo: "COL",
valor: Some("Negro"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
],
..Default::default()
}],
..debit_note_base()
};

assert_debit_note(&mut debit_note, &format!("{BASE}/atributosSimple.xml")).await;
}
79 changes: 79 additions & 0 deletions xbuilder/tests/invoice_atributos.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
use chrono::NaiveDate;
use rust_decimal_macros::dec;

use xbuilder::prelude::*;

use crate::common::assert_invoice;
use crate::common::invoice_base;

mod common;

const BASE: &str = "tests/resources/e2e/renderer/invoice/InvoiceAtributosTest";

#[serial_test::serial]
#[tokio::test]
async fn invoice_with_atributos_simple() {
let mut invoice = Invoice {
detalles: vec![Detalle {
descripcion: "Item1",
cantidad: dec!(2),
precio: Some(dec!(100)),
atributos: vec![
Atributo {
nombre: "Marca",
codigo: "BRA",
valor: Some("Samsung"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
Atributo {
nombre: "Color",
codigo: "COL",
valor: Some("Negro"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
],
..Default::default()
}],
..invoice_base()
};

assert_invoice(&mut invoice, &format!("{BASE}/atributosSimple.xml")).await;
}

#[serial_test::serial]
#[tokio::test]
async fn invoice_with_atributos_con_periodo() {
let mut invoice = Invoice {
detalles: vec![Detalle {
descripcion: "Item1",
cantidad: dec!(2),
precio: Some(dec!(100)),
atributos: vec![
Atributo {
nombre: "Garantia",
codigo: "WAR",
valor: Some("12 meses"),
fecha_inicio: Some(NaiveDate::from_ymd_opt(2019, 12, 24).unwrap()),
fecha_fin: Some(NaiveDate::from_ymd_opt(2020, 12, 24).unwrap()),
duracion: Some(365),
},
Atributo {
nombre: "Modelo",
codigo: "MOD",
valor: Some("Galaxy S10"),
fecha_inicio: None,
fecha_fin: None,
duracion: None,
},
],
..Default::default()
}],
..invoice_base()
};

assert_invoice(&mut invoice, &format!("{BASE}/atributosConPeriodo.xml")).await;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
<?xml version="1.0" encoding="ISO-8859-1"?>
<CreditNote xmlns="urn:oasis:names:specification:ubl:schema:xsd:CreditNote-2"
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:cec="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-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:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
>
<ext:UBLExtensions>
<ext:UBLExtension>
<ext:ExtensionContent/>
</ext:UBLExtension>
</ext:UBLExtensions>
<cbc:UBLVersionID>2.1</cbc:UBLVersionID>
<cbc:CustomizationID>2.0</cbc:CustomizationID>
<cbc:ID>FC01-1</cbc:ID>
<cbc:IssueDate>2019-12-24</cbc:IssueDate>
<cbc:DocumentCurrencyCode listID="ISO 4217 Alpha" listAgencyName="United Nations Economic Commission for Europe" listName="Currency">PEN</cbc:DocumentCurrencyCode>
<cac:DiscrepancyResponse>
<cbc:ReferenceID>F001-1</cbc:ReferenceID>
<cbc:ResponseCode>01</cbc:ResponseCode>
<cbc:Description><![CDATA[mi sustento]]></cbc:Description>
</cac:DiscrepancyResponse>
<cac:BillingReference>
<cac:InvoiceDocumentReference>
<cbc:ID>F001-1</cbc:ID>
<cbc:DocumentTypeCode listAgencyName="PE:SUNAT" listName="Tipo de Documento" listURI="urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo01">01</cbc:DocumentTypeCode>
</cac:InvoiceDocumentReference>
</cac:BillingReference>
<cac:Signature>
<cbc:ID>12345678912</cbc:ID>
<cac:SignatoryParty>
<cac:PartyIdentification>
<cbc:ID>12345678912</cbc:ID>
</cac:PartyIdentification>
<cac:PartyName>
<cbc:Name><![CDATA[Softgreen S.A.C.]]></cbc:Name>
</cac:PartyName>
</cac:SignatoryParty>
<cac:DigitalSignatureAttachment>
<cac:ExternalReference>
<cbc:URI>#PROJECT-OPENUBL-SIGN</cbc:URI>
</cac:ExternalReference>
</cac:DigitalSignatureAttachment>
</cac:Signature>
<cac:AccountingSupplierParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID schemeID="6" schemeAgencyName="PE:SUNAT" schemeName="Documento de Identidad" schemeURI="urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06">12345678912</cbc:ID>
</cac:PartyIdentification>
<cac:PartyLegalEntity>
<cbc:RegistrationName><![CDATA[Softgreen S.A.C.]]></cbc:RegistrationName>
<cac:RegistrationAddress>
<cbc:AddressTypeCode>0000</cbc:AddressTypeCode>
</cac:RegistrationAddress>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingSupplierParty>
<cac:AccountingCustomerParty>
<cac:Party>
<cac:PartyIdentification>
<cbc:ID schemeID="6" schemeAgencyName="PE:SUNAT" schemeName="Documento de Identidad" schemeURI="urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo06">12121212121</cbc:ID>
</cac:PartyIdentification>
<cac:PartyLegalEntity>
<cbc:RegistrationName><![CDATA[Carlos Feria]]></cbc:RegistrationName>
</cac:PartyLegalEntity>
</cac:Party>
</cac:AccountingCustomerParty>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="PEN">180.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="PEN">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="PEN">180.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID schemeAgencyName="United Nations Economic Commission for Europe" schemeID="UN/ECE 5305" schemeName="Tax Category Identifie">S</cbc:ID>
<cac:TaxScheme>
<cbc:ID schemeAgencyName="PE:SUNAT" schemeID="UN/ECE 5153" schemeName="Codigo de tributos">1000</cbc:ID>
<cbc:Name>IGV</cbc:Name>
<cbc:TaxTypeCode>VAT</cbc:TaxTypeCode>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:LegalMonetaryTotal>
<cbc:LineExtensionAmount currencyID="PEN">1000.00</cbc:LineExtensionAmount>
<cbc:TaxInclusiveAmount currencyID="PEN">1180.00</cbc:TaxInclusiveAmount>
<cbc:PayableAmount currencyID="PEN">1180.00</cbc:PayableAmount>
</cac:LegalMonetaryTotal>
<cac:CreditNoteLine>
<cbc:ID>1</cbc:ID>
<cbc:CreditedQuantity unitCode="NIU" unitCodeListAgencyName="United Nations Economic Commission for Europe" unitCodeListID="UN/ECE rec 20">10</cbc:CreditedQuantity>
<cbc:LineExtensionAmount currencyID="PEN">1000.00</cbc:LineExtensionAmount>
<cac:PricingReference>
<cac:AlternativeConditionPrice>
<cbc:PriceAmount currencyID="PEN">118.00</cbc:PriceAmount>
<cbc:PriceTypeCode listAgencyName="PE:SUNAT" listName="Tipo de Precio" listURI="urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo16">01</cbc:PriceTypeCode>
</cac:AlternativeConditionPrice>
</cac:PricingReference>
<cac:TaxTotal>
<cbc:TaxAmount currencyID="PEN">180.00</cbc:TaxAmount>
<cac:TaxSubtotal>
<cbc:TaxableAmount currencyID="PEN">1000.00</cbc:TaxableAmount>
<cbc:TaxAmount currencyID="PEN">180.00</cbc:TaxAmount>
<cac:TaxCategory>
<cbc:ID schemeAgencyName="United Nations Economic Commission for Europe" schemeID="UN/ECE 5305" schemeName="Tax Category Identifier">S</cbc:ID>
<cbc:Percent>18.00</cbc:Percent>
<cbc:TaxExemptionReasonCode listAgencyName="PE:SUNAT" listName="Afectacion del IGV" listURI="urn:pe:gob:sunat:cpe:see:gem:catalogos:catalogo07">10</cbc:TaxExemptionReasonCode>
<cac:TaxScheme>
<cbc:ID schemeAgencyName="PE:SUNAT" schemeID="UN/ECE 5153" schemeName="Codigo de tributos">1000</cbc:ID>
<cbc:Name>IGV</cbc:Name>
<cbc:TaxTypeCode>VAT</cbc:TaxTypeCode>
</cac:TaxScheme>
</cac:TaxCategory>
</cac:TaxSubtotal>
</cac:TaxTotal>
<cac:Item>
<cbc:Description><![CDATA[Item1]]></cbc:Description>
<cac:AdditionalItemProperty>
<cbc:Name>Marca</cbc:Name>
<cbc:NameCode>BRA</cbc:NameCode>
<cbc:Value>Samsung</cbc:Value>
</cac:AdditionalItemProperty>
<cac:AdditionalItemProperty>
<cbc:Name>Color</cbc:Name>
<cbc:NameCode>COL</cbc:NameCode>
<cbc:Value>Negro</cbc:Value>
</cac:AdditionalItemProperty>
</cac:Item>
<cac:Price>
<cbc:PriceAmount currencyID="PEN">100.00</cbc:PriceAmount>
</cac:Price>
</cac:CreditNoteLine>
</CreditNote>
Loading