$ 799.02
In-App Purchases| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Discuss (mail) • Contacts (contacts) |
| Community Apps Dependencies | Show |
| Lines of code | 9665 |
| Technical Name |
l10n_pe_sire_sunat |
| License | OPL-1 |
| Website | https://www.ganemo.co |
| Availability |
Odoo Online
Odoo.sh
On Premise
|
| Odoo Apps Dependencies |
•
Invoicing (account)
• Discuss (mail) • Contacts (contacts) |
| Community Apps Dependencies | Show |
| Lines of code | 9665 |
| Technical Name |
l10n_pe_sire_sunat |
| License | OPL-1 |
| Website | https://www.ganemo.co |
Format SIRE
SUNAT Purchase & Sales Electronic Registry
Generate SIRE-compliant TXT and XLSX files for Peruvian RCE (Purchase) and RVIE (Sales) books directly from Odoo. Ready to upload to SUNAT's electronic registry platform.
What We're Solving
----------------
SIRE Compliance
SUNAT requires taxpayers to submit their purchase and sales registries through the SIRE platform in specific TXT formats. This module automates the generation of these files, eliminating manual data entry and reducing errors in your tax filings.
Automated Tax Calculation
Uses PostgreSQL functions to calculate tax amounts per tag (IGV, ISC, ICBP, IVAP, etc.) directly at the database level. High-performance queries ensure accurate results even with thousands of invoices.
Setup & User Manual
Step-by-Step implementation
1. Prerequisites
Ensure these modules are installed before using SIRE:
- PLE Sale Book (ple_sale_book)
- PLE Purchase Book (ple_purchase_book)
- Tax tags must be properly configured via the PLE Tax Config Wizard.
- Invoices must have PLE dates assigned.
2. Generating Reports
How to generate SIRE files step by step:
RVIE (Sales)
Navigate to Accounting > Reports > Reporte SIRE > Reporte RVIE. Select the year, month, and send state. Click Generate Report to download TXT and XLSX files.
RCE - National Purchases
Navigate to Accounting > Reports > Reporte SIRE > Reporte RCE - Compras nacionales. Select period and parameters. Click Generate Report.
RCE - Non-Domiciled
Navigate to Accounting > Reports > Reporte SIRE > Reporte RCE - Compras no domiciliadas. Generates specific formats for non-domiciled supplier transactions.
Multiple Variants
Each report supports variants: General, Complements, Add/Accept/Replace Proposed, and Subsequent Adjustments.
3. Report Column Reference
Complete technical-functional mapping of every column generated in each report.
RVIE — Sales Report Columns
| Column | Source (Model.field / SQL) | Description | Conditions |
|---|---|---|---|
company_vat |
Wizard company_id.vat |
Company's RUC number. Taken from the selected company at wizard level, truncated to 11 chars. | — |
company_name |
res.company.name |
Legal name of the company. Max 1500 chars. | — |
period |
Wizard year + month |
Concatenation of the selected year and month (e.g.,
202601).
6 chars.
|
— |
invoice_date |
account.move.invoice_date |
Invoice emission date, formatted as DD/MM/YYYY. |
— |
document_type_code |
l10n_latam_document_type.code |
SUNAT document type code (e.g., 01=Factura,
03=Boleta, 07=Nota Crédito). Via
account_move.l10n_latam_document_type_id.
|
— |
invoice_serie |
account.move.name |
Serie portion of the invoice number. Extracted by splitting
name at - (first part). Spaces removed.
|
— |
invoice_correlative |
account.move.name |
Correlative portion of the invoice number. Extracted by splitting
name at - (second part).
|
— |
invoice_line_correlative |
account.move.line.ple_correlative |
PLE correlative of the receivable line with the longest maturity
distance. Found via subquery on account_move_line where
account_type = 'asset_receivable', ordered by
ABS(date_maturity - invoice_date) DESC, LIMIT 1.
|
Only lines with asset_receivable account type. |
partner_identification_code |
l10n_latam_identification_type.l10n_pe_vat_code |
Partner identification type code (e.g., 6=RUC,
1=DNI). Via
partner.l10n_latam_identification_type_id.
|
— |
partner_vat |
res.partner.vat |
Partner's tax identification number (RUC/DNI). Max 15 chars. | — |
partner_name |
res.partner.name |
Partner's legal name. Cleaned via validate_string()
PostgreSQL function (removes special chars). Max 1500 chars. |
— |
s_base_exp |
get_tax() → index 0 |
Tax base for export operations. Calculated by the
get_tax PostgreSQL function matching tax tags.
|
— |
s_base_og |
get_tax() → index 1 |
Tax base for taxed operations (operaciones gravadas). IGV base amount. | — |
s_base_ogd |
get_tax() → index 2 |
Tax base for taxed operations with discount. | — |
s_tax_og |
get_tax() → index 3 |
IGV tax amount for taxed operations. | — |
s_tax_ogd |
get_tax() → index 4 |
IGV tax amount for taxed operations with discount. | — |
s_base_oe |
get_tax() → index 5 |
Tax base for exonerated operations. | — |
s_base_ou |
get_tax() → index 6 |
Tax base for unaffected operations (inafectas). | — |
s_tax_isc |
get_tax() → index 7 |
ISC (Selective Consumption Tax) amount. | — |
s_tax_icbp |
get_tax() → index 8 |
ICBP (Plastic Bag Tax) amount. | — |
s_base_ivap |
get_tax() → index 9 |
Base for IVAP (Tax on Sale of Rice). | — |
s_tax_ivap |
get_tax() → index 10 |
IVAP tax amount. | — |
s_tax_other |
get_tax() → index 11 |
Other taxes amount not classified above. | — |
amount_total |
Python: sum(tax_data[:12]) |
Invoice total. Calculated as the sum of all 12 tax data values
returned by get_tax(). |
— |
currency_name |
res.currency.name |
ISO 4217 currency code (e.g., PEN, USD). Via
account_move.currency_id. Max 3 chars.
|
— |
exchange_rate |
account.move.invoice_currency_rate |
Exchange rate = 1 / invoice_currency_rate, rounded to 3
decimals. Represents the direct rate (e.g., 3.750 for
USD→PEN). |
Only for non-PEN currencies. PEN invoices return NULL.
|
origin_invoice_date |
account.move.origin_invoice_date |
Date of the original document (for credit/debit notes). Formatted
DD/MM/YYYY.
|
Populated only for refund-type documents. |
origin_document_type_code |
l10n_latam_document_type.code |
Document type code of the original invoice being modified. Via
account_move.origin_l10n_latam_document_type_id.
|
Populated only for credit/debit notes. |
origin_number_serie |
account.move.origin_number |
Serie of the original document. Extracted from
origin_number splitting at -.
|
— |
origin_number_correlative |
account.move.origin_number |
Correlative of the original document. Second part after
- split.
|
— |
bool_pay_invoice |
account.move.bool_pay_invoice |
Payment indicator. Returns 1 if set, empty otherwise.
|
Only when bool_pay_invoice IS NOT NULL. |
ple_state |
account.move.ple_state |
PLE declaration state indicator. 1 char. | — |
detraction |
account.move.l10n_pe_edi_operation_type |
Detraction marker. Returns TieneDetraccion flag. |
Only when l10n_pe_edi_operation_type is
1001,
1002, 1003, or 1004.
|
RCE — Purchase Report Columns
| Column | Source (Model.field / SQL) | Description | Conditions |
|---|---|---|---|
company_vat |
Wizard company_id.vat |
Company's RUC number. Max 11 chars. | — |
company_name |
res.company.name |
Legal name of the company. Max 1500 chars. | — |
period |
Wizard year + month |
Fiscal period in YYYYMM format (e.g.,
202601).
|
— |
invoice_date |
account.move.invoice_date |
Invoice emission date. DD/MM/YYYY. |
— |
invoice_date_due |
account.move.invoice_date_due |
Invoice due date. DD/MM/YYYY. |
Only for doc types 14, 46, 50, 51, 52, 53, 54. Empty
otherwise. |
document_type_code |
l10n_latam_document_type.code |
SUNAT document type code. Max 2 chars. | — |
ref_serie |
Priority: l10n_latam_document_number → ref
→ name |
Serie (first part before -) of the supplier invoice
number. Uses a 3-level ORM+SQL priority:
(1) l10n_latam_document_number via ORM (only if
journal has l10n_latam_use_documents = True),
(2) account_move.ref (supplier reference),
(3) account_move.name (journal entry name, e.g.
BILL/2024/0001).
Post-processed in Python's _process_query_results().
Applies to both National and Non-Domiciled purchase reports.
|
If doc type = 46, serie is zero-padded to 4 chars. |
ref_correlative |
Same priority as ref_serie |
Correlative (second part after -) of the supplier invoice
number. Same 3-level priority:
l10n_latam_document_number → ref →
name.
In the Non-Domiciled report, leading zeros are stripped via
.lstrip('0').
|
— |
year_aduana |
account.move.year_aduana |
Customs year (DUA/DSI). 4-digit year. Only for import documents. | — |
invoice_line_correlative |
account.move.line.ple_correlative |
PLE correlative of the payable line with the longest maturity
distance. Subquery on account_move_line where
account_type = 'liability_payable', ordered by
maturity distance DESC, LIMIT 1.
|
Only lines with liability_payable account type. |
voucher_payment_date |
account.move.l10n_pe_detraction_date |
Detraction payment voucher date. Formatted DD/MM/YYYY.
Uses the V19 field l10n_pe_detraction_date (migrated
from deprecated voucher_payment_date). |
— |
voucher_number |
account.move.l10n_pe_detraction_number |
Detraction voucher number. Max 24 chars. Uses the V19 field
l10n_pe_detraction_number (migrated from deprecated
voucher_number).
|
— |
igv_withholding_indicator |
account.move.igv_withholding_indicator |
IGV withholding indicator. Returns 1 if true, empty
otherwise. |
Only when igv_withholding_indicator = true. |
country_code |
res.country.l10n_pe_sunat_code |
SUNAT country code of the partner. Via
partner.country_id. Max 4 chars. Used for non-domiciled.
|
— |
partner_identification_code |
l10n_latam_identification_type.l10n_pe_vat_code |
Partner identification type code (e.g., 6=RUC). 1
char. |
— |
partner_vat |
res.partner.vat |
Partner's RUC/DNI. Max 15 chars. | — |
partner_name |
res.partner.name |
Partner's legal name. Cleaned via validate_string(). Max
1500 chars. |
— |
p_base_gdg |
get_tax_purchase() → index 0 |
Tax base for taxed purchases destined to taxed operations (gravadas destinadas a op. gravadas). | — |
p_tax_gdg |
get_tax_purchase() → index 1 |
IGV for taxed purchases destined to taxed operations. | — |
p_base_gdm |
get_tax_purchase() → index 2 |
Tax base for taxed purchases destined to mixed operations (gravadas destinadas a op. mixtas). | — |
p_tax_gdm |
get_tax_purchase() → index 3 |
IGV for taxed purchases destined to mixed operations. | — |
p_base_gdng |
get_tax_purchase() → index 4 |
Tax base for taxed purchases destined to non-taxed operations (gravadas destinadas a op. no gravadas). | — |
p_tax_gdng |
get_tax_purchase() → index 5 |
IGV for taxed purchases destined to non-taxed operations. | — |
p_base_ng |
get_tax_purchase() → index 6 |
Tax base for non-taxed purchases (adquisiciones no gravadas). | — |
p_tax_isc |
get_tax_purchase() → index 7 |
ISC (Selective Consumption Tax) amount. | — |
p_tax_icbp |
get_tax_purchase() → index 8 |
ICBP (Plastic Bag Tax) amount. | — |
p_tax_other |
get_tax_purchase() → index 9 |
Other taxes (not classified in the categories above). | — |
amount_total |
Python: sum(tax_data[:10]) |
Invoice total. Sum of all 10 tax data values. | — |
currency_name |
res.currency.name |
ISO 4217 currency code. Max 3 chars. | — |
exchange_rate |
account.move.invoice_currency_rate |
Exchange rate = 1 / invoice_currency_rate. Rounded 3
decimals. |
Only non-PEN. PEN returns NULL. |
origin_invoice_date |
account.move.origin_invoice_date |
Date of the original document. DD/MM/YYYY. |
For credit/debit notes. |
origin_document_type_code |
l10n_latam_document_type.code |
Document type code of the original invoice. Via
origin_l10n_latam_document_type_id.
|
For credit/debit notes. |
origin_number_serie / correlative |
account.move.origin_number |
Serie and correlative of the original document. Split at
-.
|
— |
code_aduana |
code_aduana.code |
Customs office code (DUA). Via
account_move.code_aduana. Max 3 chars.
|
Only for in_refund move type. Empty otherwise. |
linkage_code |
link_economic.code |
Economic linkage type code. Via
account_move.linkage_id. For non-domiciled.
|
— |
hard_rent / deduccion_cost / neto_rent |
account.move.hard_rent,
.deduccion_cost, .neto_rent
|
Gross rent, deduction cost, and net rent. Decimal amounts.
Post-processed to handle .00 → 0.00
edge case. |
Non-domiciled purchases only. |
retention_rate / tax_withheld |
account.move.retention_rate,
.tax_withheld
|
Retention rate and withheld tax amount. Decimal. | Non-domiciled purchases only. |
type_rent_code |
type_rent.code |
Income type code. Via account_move.type_rent_id. |
Non-domiciled purchases only. |
taken_code |
service_taken.code |
Service utilization marker. Via account_move.taken_id.
1 char. |
Non-domiciled purchases only. |
application_article |
account.move.application_article |
Double taxation agreement article application indicator.
1 if set, empty otherwise.
|
Only when application_article IS NOT NULL. |
cdi |
account.move.cdi |
International double taxation agreement code. Max 2 chars. | Non-domiciled purchases only. |
exoneration_nodomicilied_code |
exoneration_nodomicilied.code |
Non-domiciled exoneration code. Via
account_move.exoneration_nodomicilied_id. 1 char.
|
Non-domiciled purchases only. |
classification_services_code |
classification_services.code |
Classification of goods/services code. Via
account_move.types_goods_services_id.
|
Only when company.exceeds_1500_uit = TRUE. Empty
otherwise. |
detraction |
account.move.detraction_id |
Detraction marker. Returns TieneDetraccion. |
Only when detraction_id IS NOT NULL. |
inv_serie / inv_correlative / inv_year_dua_dsi |
account.move.inv_serie,
.inv_correlative,
.inv_year_dua_dsi
|
Additional invoice reference fields (serie, correlative, DUA/DSI year) for complex document cross-references. | — |
inv_retention_igv |
account.move.inv_retention_igv |
IGV retention amount for the referenced invoice. Decimal(9,2). | — |
inv_type_document_code |
l10n_latam_document_type.code |
Document type code of the referenced invoice. Via
account_move.inv_type_document.
|
— |
country_name |
res.country.name |
Country name of the partner. Post-processed in Python to handle dict-type returns from translated fields. | Non-domiciled purchases only. |
partner_street |
res.partner.street |
Partner's street address. | Non-domiciled purchases only. |
Important Notes
- All tax columns (
get_tax()andget_tax_purchase()) are calculated via PostgreSQL functions that match tax tags on invoice lines. Tags must be configured via the PLE Tax Config Wizard. - The Serie/Correlativo on purchases uses a
3-level ORM+SQL priority:
l10n_latam_document_number(ORM, non-stored) →name(SQL) →ref(SQL). - Exchange rate uses Odoo's
invoice_currency_ratewith inverse formula:1 / rate. PEN invoices show no rate. - Detraction fields use V19 names:
l10n_pe_detraction_dateandl10n_pe_detraction_number. - Non-domiciled specific columns (linkage, rent, withholding, etc.) are only populated for purchase invoices from foreign suppliers.
Global Ready | Multi-Language Support
This module is fully translated into English and Spanish (en_US, es_ES, es_PE, es_MX), ensuring a professional experience for international organizations.
Why Choose Ganemo?
----------------
Ganemo is the world's leading Odoo App developer and a multi-award-winning Gold Partner. For over 5 years, we have been recognized as the #1 seller of high-quality apps on the Odoo App Store. Trusted as the "Best Partner" in USA, Mexico, Chile, Spain, Colombia, Ecuador, and Peru, we deliver robust, secure, and localization-compliant solutions for global businesses.
Get a Quote & Resolve Commercial Doubts
Join thousands of satisfied clients on Odoo. Contact our sales team directly.
Official WhatsApp
Fastest response time.
LINK
+1 (828) 672-6150
Book a Demo
Let's explore your needs.
LINK
Schedule Meeting
Need More? We Do It All
Professional Odoo Services
ERP Implementation
Transform your business with a full Odoo implementation. We analyze, configure, and train your team to maximize productivity. From Accounting to Inventory, we handle the complexity so you can focus on growth.
Module Dev & Migration
Need a custom feature? Or stuck on an older version? We develop high-performance custom modules and migrate your existing code to Odoo 19 with zero data loss. Expert developers at your service.
QA / User Testing Scenarios
Enterprise Validation Plan
Group A — RVIE Sales Report Scenarios
A1: RVIE — Accept Proposal (Opportunity Code 01)
Precondition: Period has posted customer invoices (Facturas, Boletas) with taxes applied. SUNAT proposal is ready to be accepted.
- Go to Accounting › Reports › Reporte SIRE › Reporte RVIE.
- Select Year = current year, Month = current month.
- Set Estado de Envío =
[1] Empresa o entidad operativa. - Set Código de Oportunidad =
[01] RVIE — Cuando acepta la propuesta. - Click Generar Reporte.
Expected Result:
- TXT, XLSX, and ZIP files are generated and available for download.
- TXT file contains pipe-delimited (
|) rows — one per invoice line. - Each row shows: period, CUO, correlative, invoice date, due date, document type, series, number, customer RUC/DNI, customer name, export value, taxable base, IGV amount, exempt amount, non-taxable amount, ISC, tax on plastic bags (ICBP), other taxes, total amount, currency code, and exchange rate.
- XLSX mirrors the TXT content with headers for human review.
A2: RVIE — Replace Proposal (Opportunity Code 02)
Precondition: You have corrections to SUNAT's proposed data. At least one invoice in the period has been modified after the initial proposal.
- Open Reporte RVIE wizard.
- Set Código de oportunidad =
[02] RVIE — Cuando reemplaza la propuesta. - Enter a Correlativo if requested.
- Click Generar Reporte.
Expected Result:
- Generated files use the "Replace Proposed" report format.
- The Correlativo field resets to empty when you change the opportunity code (verify onchange behavior).
- All invoice data matches the corrected values in Odoo.
A3: RVIE — Subsequent Adjustments (Opportunity Code 03)
Precondition: A Credit Note or Debit Note was posted in the period after the original report was submitted. The adjustment needs to be reported.
- Create and post a Credit Note referencing invoice F001-0001.
- Open Reporte RVIE, set opportunity code =
[03] Ajustes posteriores. - Generate the report for the same period.
Expected Result:
- The Credit Note appears in the TXT with corresponding negative amounts.
- The
document_typecolumn reflects the correct type (07 for Credit Note, 08 for Debit Note). - The reference fields (original document type, series, number, and date) are populated correctly.
A4: RVIE — General Format for Prior Periods (Opportunity Code 04)
Precondition: You need to report adjustments for periods that were managed under the old system (before SIRE migration).
- Set Year and Month to an older period (e.g., 2023-06).
- Set opportunity code =
[04] Reporte de ajustes posteriores — Formato general. - Generate the report.
Expected Result:
- Report uses the General Format layout (different from codes 01-03).
- The filename includes the correct period and format identifier.
- Data for old-period invoices is correctly retrieved from Odoo.
A5: RVIE — Add to Proposal from Invoice Selection
Precondition: You have specific invoices that need to be added to the SUNAT proposal but are not included in the automatic batch.
- Go to Accounting › Invoices list view.
- Select 3-5 posted invoices from the same month and year.
- Use the Action menu → Agregar a propuesta RVIE.
- In the wizard, verify that Year and Month are auto-populated and read-only.
- Enter a Correlativo and click Generar Reporte.
Expected Result:
- The wizard only generates data for the explicitly selected invoices.
- Year and Month fields are read-only and match the invoice dates.
- TXT/XLSX/ZIP files are generated containing only the selected records.
A6: RVIE — Add to Proposal with Mixed Months (Error)
Precondition: Test validation of the multi-month guard.
- Select invoices from different months (e.g., January and February).
- Trigger the Agregar a propuesta RVIE action.
Expected Result:
- A UserError is raised: "No todos los movimientos seleccionados son del mismo mes y año."
- No wizard opens; the user must re-select invoices from the same period.
Group B — RCE National Purchases Scenarios
B1: RCE National — Accept Proposal (Code 01)
Precondition: Period has vendor bills with
national suppliers (domiciled, is_nodomicilied = false). Bills have IGV
gravada, mixta, and no gravada taxes.
- Go to Accounting › Reports › Reporte SIRE › Reporte RCE — Compras nacionales.
- Select period, set Estado de Envío and Código de Oportunidad = [01].
- Click Generar Reporte.
Expected Result:
- TXT/XLSX/ZIP generated with all national purchase invoices.
- Tax columns show correct values:
base_gravada,igv_gravada,base_mixta,igv_mixta,base_no_gravada,igv_no_gravada,valor_adquisiciones_no_gravadas,isc,icbp,otros_tributos. - Non-domiciled vendor bills are excluded from this report.
- The SQL function
get_tax_purchase()correctly breaks down taxes by category.
B2: RCE National — Replace Proposal (Code 02)
Precondition: SUNAT's proposal for purchases has errors that need to be overridden.
- Open the RCE — Compras nacionales wizard.
- Set Código de oportunidad = [02] Cuando reemplaza la propuesta.
- Generate the report.
Expected Result:
- Replace Proposed format is used for both TXT and XLSX.
- Correlative resets when switching opportunity codes.
- Data reflects the Odoo-corrected purchase records.
B3: RCE National — Subsequent Adjustments (Code 03)
Precondition: Vendor credit notes or debit notes posted after the purchase book was submitted.
- Post a Vendor Credit Note referencing a purchase invoice.
- Generate RCE National with code
[03].
Expected Result:
- Credit note shows negative tax amounts in the correct columns.
- Reference document fields (original type, series, number, date) are populated.
- The report format matches "Subsequent Adjustments" layout.
B4: RCE National — Full Tax Breakdown Verification
Precondition: Create vendor bills with diverse
tax scenarios to stress the get_tax_purchase() SQL function.
- Create Bill A: Products with only IGV (18%).
- Create Bill B: Mixed tax — some lines with IGV, some exempt (Exonerado).
- Create Bill C: Products with ISC + IGV (e.g., fuel, alcohol).
- Create Bill D: Products with ICBP (Impuesto a las Bolsas Plásticas).
- Create Bill E: Fully non-taxable (Inafecto) purchase.
- Post all bills and generate the RCE National report for the period.
Expected Result:
- Bill A:
base_gravadaandigv_gravadapopulated; all other tax columns empty or zero. - Bill B:
base_mixta+igv_mixtapopulated, plusvalor_adquisiciones_no_gravadas. - Bill C:
isccolumn shows separate ISC amount. - Bill D:
icbpcolumn has the plastic bag tax amount. - Bill E: Only
valor_adquisiciones_no_gravadasis populated. - Total amount (
importe_total) matches the sum of all tax components for each bill.
Group C — RCE Non-Domiciled Purchases Scenarios
C1: RCE Non-Domiciled — Informed Report (Code 00)
Precondition: Create a vendor bill with a
non-domiciled supplier. The partner must have: is_nodomicilied = True, a
foreign country set, and linkage type / rent type configured.
- Create and post a vendor bill with a non-domiciled partner (e.g., a US-based SaaS provider).
- Go to Reporte RCE — Compras no domiciliadas.
- Set Código de oportunidad = [00] No domiciliados informado.
- Generate the report.
Expected Result:
- Report includes the invoice with all non-domiciled specific fields:
country_code,partner_name(foreign entity name),partner_domicile,income_type,linkage_type. - Withholding tax columns are correctly populated if applicable.
- National vendor bills are excluded (filter:
is_nodomicilied = true).
C2: RCE Non-Domiciled — Subsequent Adjustments (Code 03)
Precondition: A credit note was issued against a non-domiciled vendor bill after the report period.
- Post a vendor credit note for the non-domiciled supplier.
- Generate RCE Non-Domiciled with code
[03].
Expected Result:
- Credit note appears with negative amounts in taxable/total columns.
- Non-domiciled fields (country, income type) are still populated.
- Reference to original document is included.
C3: RCE Non-Domiciled — Double Tax Agreement Scenario
Precondition: Your company has transactions with a supplier from a country that has a double tax agreement with Peru (e.g., Chile, Canada, Brazil).
- Create a vendor bill for a Brazilian supplier with appropriate rent type and linkage type.
- Configure the Convenio para evitar la doble imposición flag if applicable.
- Generate the Non-Domiciled report.
Expected Result:
- The double taxation agreement field is correctly reflected in the TXT output.
- Withholding rates may differ from non-agreement countries — verify amounts.
C4: Verify National vs. Non-Domiciled Mutual Exclusion
Precondition: Both national and non-domiciled vendor bills exist in the same period.
- Generate RCE National report for the period.
- Verify that no non-domiciled invoices appear (filter:
is_nodomicilied IS NULL OR is_nodomicilied = false). - Generate RCE Non-Domiciled report for the same period.
- Verify that no national invoices appear (filter:
is_nodomicilied = true).
Expected Result:
- The two reports are mutually exclusive — no invoices appear in both.
- Combined record count = total posted vendor bills for the period.
Group D — Complements & Currency Rates Scenarios
D1: Purchase Complement — Add Data to Proposal
Precondition: You have vendor bills that need to be manually added to the SUNAT proposal (not auto-included).
- Go to Accounting › Vendor Bills list view.
- Select 2-3 vendor bills from the same period.
- Use Action → Complementar propuesta RCE.
- Set Acción a realizar = Agregar datos a la propuesta.
- Enter the Correlativo and generate.
Expected Result:
- Wizard auto-populates Year and Month from the selected bills (read-only).
- Generated report includes only the selected move IDs.
- TXT uses the "Add Proposed" format.
D2: Purchase Complement — Modify Proposal Data
Precondition: Bills already in the SUNAT proposal need corrections.
- Select the bills to modify, open the complement wizard.
- Set Acción a realizar = Modificar datos de la propuesta.
- Generate the report.
Expected Result:
- Report uses the "Modify Proposed" format.
- Correlative resets when switching the
action_takenfield.
D3: Purchase Complement — Include/Exclude from Proposal
Precondition: Specific bills need to be included in or excluded from the existing proposal.
- Select the bills, open the complement wizard.
- Set Acción a realizar = Incluir/Excluir datos de la propuesta.
- Generate the report.
Expected Result:
- Report uses the "Include/Exclude Proposed" format.
- Only selected bills appear in the output. No extra data is included.
D4: Currency Rate Complement — TXT from Exchange Rates
Precondition: Multiple currency rates exist for the same period (e.g., daily USD/PEN rates for January 2025).
- Go to Accounting › Configuration › Currencies › Currency Rates.
- Select 5-10
res.currency.raterecords for USD from the same month. - Use Action → Complementar tasas RCE.
- Enter the Correlativo and generate.
Expected Result:
- TXT file contains one row per rate record:
period,date(dd/mm/yyyy),currency_name(USD),inverse_company_rate(e.g., 3.750). - No XLSX is generated — only TXT + ZIP.
- Rates from different months trigger a UserError.
D5: SIRE Complement Flag on Invoices
Precondition: The
l10n_pe_is_complement_sire field is available on invoices.
- Open a customer invoice form view.
- Locate the SIRE Complement boolean checkbox.
- Enable it and save the invoice.
- Verify the invoice is correctly flagged in the database
(
l10n_pe_is_complement_sire = True).
Expected Result:
- The checkbox is visible and functional on the invoice form.
- Flagged invoices can be identified and included in complement reports.
- The help tooltip explains the purpose clearly.
Group E — Edge Cases, Multi-Currency & Validation
E1: Multi-Currency Invoice — Exchange Rate Rendering
Precondition: Both PEN and USD invoices exist in the same period.
- Create and post a customer invoice in USD (e.g., $1,000.00 with exchange rate 3.750).
- Create and post a customer invoice in PEN (e.g., S/ 5,000.00).
- Generate the RVIE report for the period.
Expected Result:
- USD invoice:
currency_code=USD,exchange_rate=3.750(3 decimal format). - PEN invoice:
currency_code=PEN,exchange_rate= empty or0.000. - Tax amounts are always in PEN regardless of invoice currency.
E2: Empty Period — No Invoices for Report
Precondition: Select a period where no posted invoices exist (e.g., a future month).
- Open any SIRE wizard and select a period with zero invoices.
- Generate the report.
Expected Result:
- The Error Dialog field shows: "No hay contenido que presentar para este periodo."
- TXT file is generated with a single newline character (
\n). - ZIP file is still created (contains the empty TXT).
- No crash or exception occurs — graceful handling.
E3: Document Number Priority Logic (3-Level Fallback)
Precondition: Test the 3-level priority for
Serie and Correlativo extraction: (1) ORM l10n_latam_document_number, (2)
sequence_prefix / sequence_number, (3) SQL split of
name.
- Create Invoice A: Has a valid
l10n_latam_document_number(e.g.,F001-00000123). Post it. - Create Invoice B:
l10n_latam_document_numberis empty, butsequence_prefix=F002-andsequence_number=456. Post it. - Create Invoice C: Both fields empty, but
name=INV/2025/0001. Post it. - Generate the RVIE report.
Expected Result:
- Invoice A: Serie =
F001, Number =00000123(froml10n_latam_document_number). - Invoice B: Serie from
sequence_prefix, Number fromsequence_number. - Invoice C: Parsed via SQL
split_part(name, '-', ...)orsplit_part(name, '/', ...). - No empty Series or Number fields in the output for any invoice.
E4: UIT Threshold (Exceeds 1,500 UIT) Configuration
Precondition: The company may or may not exceed the 1,500 UIT annual income threshold. This affects certain report fields.
- Go to Settings › Companies and open the company form.
- Locate the Exceeds 1,500 UIT boolean field.
- Toggle it to True and save.
- Generate any purchase report with this setting active.
- Toggle back to False and regenerate.
Expected Result:
- When
exceeds_1500_uit = True: Additional detail columns related to cash payment and classification are populated in the purchase TXT. - When
exceeds_1500_uit = False: Those columns remain empty or are omitted. - The field has a clear help tooltip explaining the UIT threshold rule.
E5: File Integrity — ZIP Contains Valid TXT
Precondition: Any successfully generated report.
- Generate any SIRE report.
- Download the ZIP file.
- Extract it and open the contained TXT file.
Expected Result:
- ZIP extracts without errors (valid ZIP_DEFLATED format).
- The TXT filename inside the ZIP matches the expected SUNAT naming convention.
- Content is identical to the standalone TXT download.
- Character encoding is correct (no garbled accents or special characters).
E6: Re-generation — Second Run Clears Previous Files
Precondition: A report has already been generated for a period.
- Generate the RVIE report for January 2025.
- Note the filenames of the generated TXT, XLSX, and ZIP.
- Without closing the wizard, click Generar Reporte again.
Expected Result:
- Before regeneration, previous binary fields are cleared
(
xlsx_binary = False,zip_binary = False). - New files are generated fresh — no stale data from the previous run.
- The wizard view reloads with the new file download links.
E7: XLSX vs. TXT Column Parity
Precondition: A report with multiple invoices has been generated.
- Generate any SIRE report.
- Download both XLSX and TXT files.
- Open the XLSX in a spreadsheet application.
- Open the TXT in a text editor.
- Compare row counts and column values.
Expected Result:
- Both files have the exact same number of data rows.
- Column values are identical in both formats (TXT pipe-delimited vs. XLSX cells).
- XLSX has a header row with descriptive column names; TXT does not.
- Numeric formats (decimals, trailing zeros) match SUNAT specifications.
E8: Multi-Company Isolation
Precondition: Odoo instance has multiple companies set up. Each company has its own invoices.
- Log in as Company A and generate the RVIE report for January.
- Switch to Company B and generate the same report for the same period.
Expected Result:
- Reports are completely isolated — Company A's report only contains Company A's invoices.
- The RUC in the header/filename corresponds to the active company.
- No data leakage between companies.
E9: Invoice with Missing Due Date
Precondition: An invoice may not have a due date set (e.g., immediate payment terms).
- Create an invoice with no due date (Immediate Payment terms).
- Post it and generate the RVIE report.
Expected Result:
- The
due_datecolumn falls back to theinvoice_dateor shows empty — no error. - The SQL query handles NULL
invoice_date_duegracefully. - Report generates successfully without exceptions.
E10: High-Volume Stress Test (500+ Invoices)
Precondition: A period with a large number of posted invoices (500+). Typical for wholesale or retail companies.
- Ensure the period has 500+ posted invoices (mix of Facturas, Boletas, Credit Notes).
- Generate the RVIE report.
- Measure the generation time.
Expected Result:
- Report generates successfully without timeout.
- All 500+ records appear in the TXT/XLSX files.
- SQL query performance is acceptable (under 30 seconds).
- ZIP file size and download work correctly for large files.
FAQ & Troubleshooting
Common Resolutions
Report shows "Error al ejecutar la consulta"?
Reason: A required PostgreSQL function may not be installed yet.
Fix: Update the module to reinstall SQL functions (get_tax, get_tax_purchase, validate_string). Go to Apps > l10n_pe_sire_sunat > Upgrade.
Tax amounts are all zero?
Reason: Tax tags are not linked to your company's taxes.
Fix: Run the PLE Tax Config Wizard from the PLE Sale Book or PLE Purchase Book module to link tags to taxes.
Exchange rate shows 1.000 for USD invoices?
Reason: The invoice was created without a proper currency rate.
Fix: Ensure currency rates are configured in Accounting > Configuration > Currencies before creating invoices.
Is this compatible with Multi-company?
Answer: Yes!
Detail: Each wizard filters by the current company. Reports are generated per-company with correct RUC and company name in the output files.
"Error: function get_tax does not exist"
Reason: The SQL functions (get_tax,
get_tax_purchase, validate_string) were not created in the
database. This typically happens after restoring a backup or migrating databases.
Fix: Go to
Apps, search for l10n_pe_sire_sunat, and click
Upgrade. The module's init hooks will recreate the
functions. Alternatively, run the SQL scripts from the sql/ folder manually
via psql.
Report includes draft or cancelled invoices?
Reason: This should never happen. The SQL query
filters by state = 'posted' and specific move_type values.
Fix: If
you see unexpected records, check whether the invoice state was manually
altered in the database. Re-post or properly cancel the affected invoices and regenerate
the report.
Which dependency modules are required?
Answer: This module depends on
ple_sale_book, ple_purchase_book, and base. These
must be installed first.
Detail: The PLE modules provide the SQL tax functions and the tax tag configuration wizard needed to correctly calculate IGV, ISC, ICBP, etc. Without them, all tax columns will show zeroes.
"No todos los movimientos seleccionados son del mismo mes y año"
Reason: You selected invoices from different months or years when trying to use the Add to Proposal or Complement wizard.
Fix: Go back to the invoice list view, filter by a single month/year using the date filters, then select only invoices within that period. The wizard requires all selected records to share the same month and year.
Non-domiciled fields are empty in the report?
Reason: The partner's non-domiciled configuration is incomplete.
Fix: Open
the vendor's partner form and ensure these fields are configured: (1)
is_nodomicilied = True, (2) A foreign
Country is set, (3) Linkage Type
(Tipo de vínculo) is selected, (4) Rent Type (Tipo de
renta) is selected, (5) Income Type is configured. All
five are required for a complete non-domiciled report row.
Serie or Correlativo shows strange values?
Reason: The document number extraction uses a
3-level priority fallback. If the primary source
(l10n_latam_document_number) is empty, it falls back to
sequence_prefix/sequence_number, then to SQL parsing of the
name field.
Fix:
Ensure invoices have a valid l10n_latam_document_number in the format
F001-00000123. For Peruvian localization, install the
l10n_latam_invoice_document module and configure document types correctly.
What does "Exceeds 1,500 UIT" mean?
Answer: SUNAT requires companies whose annual income exceeds 1,500 UIT (Unidades Impositivas Tributarias) to provide additional detail in purchase reports — specifically cash payment classification and related fields.
Action: Go to Settings › Companies, open your company form, and set the Exceeds 1,500 UIT checkbox accordingly. This should be reviewed annually when UIT values are updated by SUNAT.
SUNAT rejects the TXT file during upload?
Reason: The TXT file format or content doesn't match SUNAT's expected structure for the selected opportunity code.
Fix: (1) Verify you selected the correct Opportunity Code matching what SUNAT expects. (2) Open the TXT and count the pipe-delimited columns — they must match the SUNAT specification exactly. (3) Check for empty mandatory fields (RUC, document type). (4) Ensure no extra blank lines at the end of the file. (5) Upload the ZIP file instead of the raw TXT if SUNAT requires it.
Download button doesn't work or file is empty?
Reason: The Binary field may not have been saved correctly, or the wizard was closed before downloading.
Fix:
(1) Re-open the wizard and click Generar Reporte again
— the files are regenerated fresh each time. (2) If using Odoo.sh or a
reverse proxy, check that the Content-Disposition headers are not being
stripped. (3) Try downloading the ZIP file instead of the XLSX if one
format fails. (4) Check the Errors field — if it shows
"No hay contenido que presentar," the period has no data.
Does this work on Odoo.sh?
Answer: Yes! The module is fully compatible with Odoo.sh.
Detail: SQL
functions are created via module hooks and work in Odoo.sh's managed PostgreSQL. File
downloads (Binary fields) work natively. Just ensure the dependency modules
(ple_sale_book, ple_purchase_book) are also deployed in your
Odoo.sh branch.
What is the relationship between PLE and SIRE modules?
Answer: The PLE (Programa de Libros Electrónicos) modules generate the traditional electronic books format. The SIRE (Sistema Integrado de Registros Electrónicos) module generates the newer SUNAT format that is progressively replacing PLE.
Detail: This SIRE module depends on PLE because it
reuses the tax calculation SQL functions (get_tax,
get_tax_purchase) and tax tag configurations provided by
ple_sale_book and ple_purchase_book. You need both PLE modules
installed even if you only file via SIRE.
Special characters or accents appear garbled in the TXT?
Reason: The TXT file is encoded in UTF-8, but some text editors or SUNAT's platform may expect a different encoding.
Fix:
(1) Open the TXT file with a UTF-8 aware editor (Notepad++, VS Code).
(2) The validate_string() SQL function already strips
problematic characters — check if the partner name itself has unusual Unicode.
(3) If SUNAT requires ASCII-only, review partner names and replace
accented characters (á→a, ñ→n) in the partner form before regenerating.
Report shows invoices from the wrong period?
Reason: The SQL query filters by the
date field of the account.move record, not by
invoice_date.
Fix: Verify
that the Accounting Date of the invoice matches the intended reporting
period. In Odoo, the date field is the accounting date used for fiscal
period assignment. If an invoice has invoice_date = Jan 31 but
date = Feb 01, it will appear in the February report.
How is the "Medio de Pago" (payment method) determined?
Answer: The payment method column in purchase
reports is populated based on the l10n_pe_payment_method field on the
vendor bill.
Detail: If this field is empty, the column will show blank in the TXT. For companies exceeding the 1,500 UIT threshold, SUNAT requires this field. Configure the payment method on each vendor bill before generating the report.
Can I regenerate a report after correcting invoices?
Answer: Yes, absolutely. Reports are generated on-the-fly from live database data.
Detail: Simply correct the invoice data (amounts, taxes, dates, partner info), then re-open the wizard and click Generar Reporte. The previous files are cleared automatically before new ones are generated. There is no "locked" or "submitted" state in Odoo — you can regenerate as many times as needed before uploading to SUNAT.
"No hay contenido que presentar para este periodo" — but I have invoices!
Reason: The invoices exist but are filtered out by the SQL query conditions.
Fix:
Check these common causes: (1) Invoices are in Draft
state — they must be Posted. (2) The
move_type doesn't match the report (e.g., vendor bills won't appear in RVIE
Sales). (3) The company on the invoice doesn't match
your active company. (4) For non-domiciled reports,
is_nodomicilied must be True on the partner.
(5) The accounting date falls outside the selected
Year/Month.
Commercial & Sales
For inquiries about licenses, demos, or partnerships.
Official WhatsApp
Fastest response time.
LINK
+1 (828) 672-6150
Book a Demo
Let's explore your needs.
LINK
Technical Support
Existing customers regarding module functionality.
© 2026 Ganemo. All rights reserved. visit ganemo.com
Odoo Proprietary License v1.0 This software and associated files (the "Software") may only be used (executed, modified, executed after modifications) if you have purchased a valid license from the authors, typically via Odoo Apps, or if you have received a written agreement from the authors of the Software (see the COPYRIGHT file). You may develop Odoo modules that use the Software as a library (typically by depending on it, importing it and using its resources), but without copying any source code or material from the Software. You may distribute those modules under the license of your choice, provided that this license is compatible with the terms of the Odoo Proprietary License (For example: LGPL, MIT, or proprietary licenses similar to this one). It is forbidden to publish, distribute, sublicense, or sell copies of the Software or modified copies of the Software. The above copyright notice and this permission notice must be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Please log in to comment on this module