Initial commit: L10N_Europe packages

This commit is contained in:
Ernad Husremovic 2025-08-29 15:20:52 +02:00
commit 9803722600
2377 changed files with 380711 additions and 0 deletions

View file

@ -0,0 +1,45 @@
# Argentinean eCommerce
Be able to see Identification Type and AFIP Responsibility in ecommerce checkout form.
## Installation
```bash
pip install odoo-bringout-oca-ocb-l10n_ar_website_sale
```
## Dependencies
This addon depends on:
- website_sale
- l10n_ar
## Manifest Information
- **Name**: Argentinean eCommerce
- **Version**: 1.0
- **Category**: Accounting/Localizations/Website
- **License**: LGPL-3
- **Installable**: True
## Source
Based on [OCA/OCB](https://github.com/OCA/OCB) branch 16.0, addon `l10n_ar_website_sale`.
## License
This package maintains the original LGPL-3 license from the upstream Odoo project.
## Documentation
- Overview: doc/OVERVIEW.md
- Architecture: doc/ARCHITECTURE.md
- Models: doc/MODELS.md
- Controllers: doc/CONTROLLERS.md
- Wizards: doc/WIZARDS.md
- Install: doc/INSTALL.md
- Usage: doc/USAGE.md
- Configuration: doc/CONFIGURATION.md
- Dependencies: doc/DEPENDENCIES.md
- Troubleshooting: doc/TROUBLESHOOTING.md
- FAQ: doc/FAQ.md

View file

@ -0,0 +1,32 @@
# Architecture
```mermaid
flowchart TD
U[Users] -->|HTTP| V[Views and QWeb Templates]
V --> C[Controllers]
V --> W[Wizards Transient Models]
C --> M[Models and ORM]
W --> M
M --> R[Reports]
DX[Data XML] --> M
S[Security ACLs and Groups] -. enforces .-> M
subgraph L10n_ar_website_sale Module - l10n_ar_website_sale
direction LR
M:::layer
W:::layer
C:::layer
V:::layer
R:::layer
S:::layer
DX:::layer
end
classDef layer fill:#eef8ff,stroke:#6ea8fe,stroke-width:1px
```
Notes
- Views include tree/form/kanban templates and report templates.
- Controllers provide website/portal routes when present.
- Wizards are UI flows implemented with `models.TransientModel`.
- Data XML loads data/demo records; Security defines groups and access.

View file

@ -0,0 +1,3 @@
# Configuration
Refer to Odoo settings for l10n_ar_website_sale. Configure related models, access rights, and options as needed.

View file

@ -0,0 +1,17 @@
# Controllers
HTTP routes provided by this module.
```mermaid
sequenceDiagram
participant U as User/Client
participant C as Module Controllers
participant O as ORM/Views
U->>C: HTTP GET/POST (routes)
C->>O: ORM operations, render templates
O-->>U: HTML/JSON/PDF
```
Notes
- See files in controllers/ for route definitions.

View file

@ -0,0 +1,6 @@
# Dependencies
This addon depends on:
- [website_sale](../../odoo-bringout-oca-ocb-website_sale)
- [l10n_ar](../../odoo-bringout-oca-ocb-l10n_ar)

View file

@ -0,0 +1,4 @@
# FAQ
- Q: Which Odoo version? A: 16.0 (OCA/OCB packaged).
- Q: How to enable? A: Start server with --addon l10n_ar_website_sale or install in UI.

View file

@ -0,0 +1,7 @@
# Install
```bash
pip install odoo-bringout-oca-ocb-l10n_ar_website_sale"
# or
uv pip install odoo-bringout-oca-ocb-l10n_ar_website_sale"
```

View file

@ -0,0 +1,13 @@
# Models
Detected core models and extensions in l10n_ar_website_sale.
```mermaid
classDiagram
class sale_order
class website
```
Notes
- Classes show model technical names; fields omitted for brevity.
- Items listed under _inherit are extensions of existing models.

View file

@ -0,0 +1,6 @@
# Overview
Packaged Odoo addon: l10n_ar_website_sale. Provides features documented in upstream Odoo 16 under this addon.
- Source: OCA/OCB 16.0, addon l10n_ar_website_sale
- License: LGPL-3

View file

@ -0,0 +1,3 @@
# Reports
This module does not define custom reports.

View file

@ -0,0 +1,8 @@
# Security
This module does not define custom security rules or access controls beyond Odoo defaults.
Default Odoo security applies:
- Base user access through standard groups
- Model access inherited from dependencies
- No custom row-level security rules

View file

@ -0,0 +1,5 @@
# Troubleshooting
- Ensure Python and Odoo environment matches repo guidance.
- Check database connectivity and logs if startup fails.
- Validate that dependent addons listed in DEPENDENCIES.md are installed.

View file

@ -0,0 +1,7 @@
# Usage
Start Odoo including this addon (from repo root):
```bash
python3 scripts/nix_odoo_web_server.py --db-name mydb --addon l10n_ar_website_sale
```

View file

@ -0,0 +1,3 @@
# Wizards
This module does not include UI wizards.

View file

@ -0,0 +1,4 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import controllers
from . import models
from . import tests

View file

@ -0,0 +1,23 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name': 'Argentinean eCommerce',
'version': '1.0',
'category': 'Accounting/Localizations/Website',
'sequence': 14,
'author': 'Odoo, ADHOC SA',
'description': """Be able to see Identification Type and AFIP Responsibility in ecommerce checkout form.""",
'depends': [
'website_sale',
'l10n_ar',
],
'data': [
'data/ir_model_fields.xml',
'views/templates.xml',
],
'demo': [
'demo/website_demo.xml',
],
'installable': True,
'auto_install': True,
'license': 'LGPL-3',
}

View file

@ -0,0 +1,2 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import main

View file

@ -0,0 +1,59 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import _
from odoo.addons.website_sale.controllers.main import WebsiteSale
from odoo.http import request
class L10nARWebsiteSale(WebsiteSale):
def _get_mandatory_fields_billing(self, country_id=False):
"""Extend mandatory fields to add new identification and responsibility fields when company is argentina"""
res = super()._get_mandatory_fields_billing(country_id)
if request.website.sudo().company_id.country_id.code == "AR":
res += ["l10n_latam_identification_type_id", "l10n_ar_afip_responsibility_type_id", "vat"]
return res
def _get_country_related_render_values(self, kw, render_values):
res = super()._get_country_related_render_values(kw, render_values)
if request.website.sudo().company_id.country_id.code == "AR":
res.update({'identification': kw.get('l10n_latam_identification_type_id'),
'responsibility': kw.get('l10n_ar_afip_responsibility_type_id'),
'responsibility_types': request.env['l10n_ar.afip.responsibility.type'].search([]),
'identification_types': request.env['l10n_latam.identification.type'].search(
['|', ('country_id', '=', False), ('country_id.code', '=', 'AR')])})
return res
def _get_vat_validation_fields(self, data):
res = super()._get_vat_validation_fields(data)
if request.website.sudo().company_id.country_id.code == "AR":
res.update({'l10n_latam_identification_type_id': int(data['l10n_latam_identification_type_id'])
if data.get('l10n_latam_identification_type_id') else False})
res.update({'name': data['name'] if data.get('name') else False})
return res
def checkout_form_validate(self, mode, all_form_values, data):
""" We extend the method to add a new validation. If AFIP Resposibility is:
* Final Consumer or Foreign Customer: then it can select any identification type.
* Any other (Monotributista, RI, etc): should select always "CUIT" identification type"""
error, error_message = super().checkout_form_validate(mode, all_form_values, data)
# Identification type and AFIP Responsibility Combination
if request.website.sudo().company_id.country_id.code == "AR":
if mode[1] == 'billing':
if error and any(field in error for field in ['l10n_latam_identification_type_id', 'l10n_ar_afip_responsibility_type_id']):
return error, error_message
id_type_id = data.get("l10n_latam_identification_type_id")
afip_resp_id = data.get("l10n_ar_afip_responsibility_type_id")
id_type = request.env['l10n_latam.identification.type'].browse(id_type_id) if id_type_id else False
afip_resp = request.env['l10n_ar.afip.responsibility.type'].browse(afip_resp_id) if afip_resp_id else False
cuit_id_type = request.env.ref('l10n_ar.it_cuit')
# Check if the AFIP responsibility is different from Final Consumer or Foreign Customer,
# and if the identification type is different from CUIT
if afip_resp.code not in ['5', '9'] and id_type != cuit_id_type:
error["l10n_latam_identification_type_id"] = 'error'
error_message.append(_('For the selected AFIP Responsibility you will need to set CUIT Identification Type'))
return error, error_message

View file

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<function model="ir.model.fields" name="formbuilder_whitelist">
<value>res.partner</value>
<value eval="[
'l10n_ar_afip_responsibility_type_id', 'l10n_latam_identification_type_id',
]"/>
</function>
</odoo>

View file

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="default_website_ri" model="website">
<field name="name">(AR) Responsable Inscripto Website</field>
<field name="company_id" ref="l10n_ar.company_ri"/>
<field name="logo" type="base64" file="l10n_ar_website_sale/static/description/icon.png"/>
<field name="domain" model="ir.config_parameter" eval="obj().env['ir.config_parameter'].sudo().get_param('web.base.url')"/>
</record>
<function model="payment.provider" name="copy">
<value eval="[ref('payment.payment_provider_transfer')]"/>
<value eval="{'company_id': ref('l10n_ar.company_ri'), 'state': 'enabled'}"/>
</function>
<function model="product.pricelist" name="write">
<value model="product.pricelist" eval="obj().search([('currency_id', '=', ref('base.ARS')), ('company_id', '=', ref('l10n_ar.company_ri'))]).id"/>
<value model="website" eval="{'sequence': 1, 'website_id': ref('l10n_ar_website_sale.default_website_ri')}"/>
</function>
<function model="product.product" name="write">
<value model="product.product" eval="obj().search([('taxes_id', '=', False)]).ids"/>
<value model="account.tax" eval="{'taxes_id': [(4, obj().search([('type_tax_use', '=', 'sale'), ('tax_group_id', '=', ref('l10n_ar.tax_group_iva_21')), ('company_id', '=', ref('l10n_ar.company_ri'))]).id)]}"/>
</function>
</odoo>

View file

@ -0,0 +1,86 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_ar_website_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-15 10:56+0000\n"
"PO-Revision-Date: 2024-11-15 10:56+0000\n"
"Last-Translator: María Fernanda Alvarez Ramírez <mfar@odoo.com>\n"
"Language-Team: \n"
"Language: es\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
#. module: l10n_ar_website_sale
#: model:website,contact_us_button_url:l10n_ar_website_sale.default_website_ri
msgid "/contactus"
msgstr "/contacto"
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "<option value=\"\">AFIP Responsibility...</option>"
msgstr "<option value=\"\">Responsabilidad AFIP...</option>"
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "<option value=\"\">Identification Type...</option>"
msgstr "<option value=\"\">Tipo de identificación...</option>"
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "AFIP Responsibility"
msgstr "Responsabilidad AFIP"
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid ""
"Changing AFIP Responsibility type is not allowed once document(s) have been "
"issued for your account. Please contact us directly for this operation."
msgstr ""
"No puede cambiar el tipo de responsabilidad AFIP después de que haya emitido "
"documentos para su cuenta. Contáctenos para realizar esta operación."
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid ""
"Changing Identification type is not allowed once document(s) have been "
"issued for your account. Please contact us directly for this operation."
msgstr ""
"No puede cambiar el tipo de identificación después de que haya emitido "
"documentos para su cuenta. Contáctenos para realizar esta operación."
#. module: l10n_ar_website_sale
#. odoo-python
#: code:addons/l10n_ar_website_sale/controllers/main.py:0
#, python-format
msgid ""
"For the selected AFIP Responsibility you will need to set CUIT "
"Identification Type"
msgstr ""
"Para la responsabilidad AFIP seleccionada debe elegir el tipo de "
"identificación CUIT"
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "Identification Type"
msgstr "Tipo de identificación"
#. module: l10n_ar_website_sale
#: model:website,prevent_zero_price_sale_text:l10n_ar_website_sale.default_website_ri
msgid "Not Available For Sale"
msgstr "No está disponible para la venta"
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.address
msgid "Number"
msgstr "Número"
#. module: l10n_ar_website_sale
#: model:ir.model,name:l10n_ar_website_sale.model_website
msgid "Website"
msgstr "Sitio web"

View file

@ -0,0 +1,79 @@
# Translation of Odoo Server.
# This file contains the translation of the following modules:
# * l10n_ar_website_sale
#
msgid ""
msgstr ""
"Project-Id-Version: Odoo Server 16.0+e\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2024-11-15 10:56+0000\n"
"PO-Revision-Date: 2024-11-15 10:56+0000\n"
"Last-Translator: \n"
"Language-Team: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: \n"
"Plural-Forms: \n"
#. module: l10n_ar_website_sale
#: model:website,contact_us_button_url:l10n_ar_website_sale.default_website_ri
msgid "/contactus"
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "<option value=\"\">AFIP Responsibility...</option>"
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "<option value=\"\">Identification Type...</option>"
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "AFIP Responsibility"
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid ""
"Changing AFIP Responsibility type is not allowed once document(s) have been "
"issued for your account. Please contact us directly for this operation."
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid ""
"Changing Identification type is not allowed once document(s) have been "
"issued for your account. Please contact us directly for this operation."
msgstr ""
#. module: l10n_ar_website_sale
#. odoo-python
#: code:addons/l10n_ar_website_sale/controllers/main.py:0
#, python-format
msgid ""
"For the selected AFIP Responsibility you will need to set CUIT "
"Identification Type"
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.partner_info
msgid "Identification Type"
msgstr ""
#. module: l10n_ar_website_sale
#: model:website,prevent_zero_price_sale_text:l10n_ar_website_sale.default_website_ri
msgid "Not Available For Sale"
msgstr ""
#. module: l10n_ar_website_sale
#: model_terms:ir.ui.view,arch_db:l10n_ar_website_sale.address
msgid "Number"
msgstr ""
#. module: l10n_ar_website_sale
#: model:ir.model,name:l10n_ar_website_sale.model_website
msgid "Website"
msgstr ""

View file

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from . import website
from . import sale_order

View file

@ -0,0 +1,25 @@
import pytz
from odoo import fields, models
class SaleOrder(models.Model):
_inherit = "sale.order"
def _create_invoices(self, grouped=False, final=False, date=None):
""" EXTENDS 'sale'
Necessary because if someone creates an invoice after 9 pm Argentina time, if the invoice is created
automatically, then it is created with the date of the next day (UTC date) instead of today.
This fix is necessary because it causes problems validating invoices in ARCA (ex AFIP), since when generating
the invoice with the date of the next day, no more invoices could be generated with today's date.
We took the same approach that was used in the POS module to set the date, in this case always forcing the
Argentina timezone """
invoices = super()._create_invoices(grouped=grouped, final=final, date=date)
for invoice in invoices:
if invoice.country_code == 'AR':
timezone = pytz.timezone('America/Buenos_Aires')
context_today_ar = fields.Datetime.now().astimezone(timezone).date()
invoice.invoice_date = context_today_ar
return invoices

View file

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import models
class Website(models.Model):
_inherit = "website"
def _display_partner_b2b_fields(self):
""" Argentinean localization must always display b2b fields """
self.ensure_one()
return self.company_id.country_id.code == "AR" or super()._display_partner_b2b_fields()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -0,0 +1 @@
from . import test_invoice

View file

@ -0,0 +1,45 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields
from odoo.tests import tagged
from odoo.tools import mute_logger
from freezegun import freeze_time
from odoo.addons.account_payment.tests.common import AccountPaymentCommon
from odoo.addons.sale.tests.common import SaleCommon
from odoo.addons.l10n_ar.tests.common import TestAr
@tagged('-at_install', 'post_install', 'post_install_l10n')
class TestWebsiteSaleInvoice(AccountPaymentCommon, SaleCommon, TestAr):
@classmethod
def setUpClass(cls):
super().setUpClass()
cls.website = cls.env['website'].create({'name': 'Test AR Website'})
def test_website_automatic_invoice_date(self):
# Set automatic invoice
self.env['ir.config_parameter'].sudo().set_param('sale.automatic_invoice', 'True')
self.frozen_today = "2025-01-24T21:10:00"
with freeze_time(self.frozen_today, tz_offset=3):
# Prepare values needed for AR invoice generation: Tax in all lines, and AFIP responsibility partner
self.sale_order.order_line.write({'tax_id': self.company_data['default_tax_sale']})
self.sale_order.partner_id = self.partner_cf
self.sale_order.currency_id = self.env.ref('base.ARS')
# Create SO on Test Website
self.sale_order.website_id = self.website.id
# Create the payment and invoices
self.amount = self.sale_order.amount_total
tx = self._create_transaction(flow='redirect', sale_order_ids=[self.sale_order.id], state='done')
with mute_logger('odoo.addons.sale.models.payment_transaction'):
tx.with_context(l10n_ar_invoice_skip_commit=True)._reconcile_after_done()
invoice = self.sale_order.invoice_ids
self.assertTrue(invoice, "Do not create the invoice")
self.assertEqual(invoice.state, "posted", "the invoice was not posted")
self.assertEqual(fields.Datetime.now().date().strftime("%Y-%m-%d"), '2025-01-25', "UCT should be next day")
self.assertEqual(invoice.invoice_date.strftime('%Y-%m-%d'), '2025-01-24', "Should be AR current date")

View file

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="partner_info" name="Argentinean partner">
<!-- show afip responsibility -->
<div t-attf-class="mb-3 #{error.get('l10n_ar_afip_responsibility_type_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="l10n_ar_afip_responsibility_type_id">AFIP Responsibility</label>
<t t-if="partner.can_edit_vat()">
<select name="l10n_ar_afip_responsibility_type_id" t-attf-class="form-select #{error.get('l10n_ar_afip_responsibility_type_id') and 'is-invalid' or ''}">
<option value="">AFIP Responsibility...</option>
<t t-foreach="responsibility_types or []" t-as="resp_type">
<option t-att-value="resp_type.id" t-att-selected="resp_type.id == int(responsibility) if responsibility else resp_type.id == partner.l10n_ar_afip_responsibility_type_id.id">
<t t-esc="resp_type.name"/>
</option>
</t>
</select>
</t>
<t t-else="">
<p class="form-control" t-esc="partner.l10n_ar_afip_responsibility_type_id.name" readonly="1" title="Changing AFIP Responsibility type is not allowed once document(s) have been issued for your account. Please contact us directly for this operation."/>
<input name="l10n_ar_afip_responsibility_type_id" class="form-control" t-att-value="partner.l10n_ar_afip_responsibility_type_id.id" type='hidden'/>
</t>
</div>
<!-- show identification type -->
<div t-attf-class="mb-3 #{error.get('l10n_latam_identification_type_id') and 'o_has_error' or ''} col-xl-6">
<label class="col-form-label" for="l10n_latam_identification_type_id">Identification Type</label>
<t t-if="partner.can_edit_vat()">
<select name="l10n_latam_identification_type_id" t-attf-class="form-select #{error.get('l10n_latam_identification_type_id') and 'is-invalid' or ''}">
<option value="">Identification Type...</option>
<t t-foreach="identification_types or []" t-as="id_type">
<option t-att-value="id_type.id" t-att-selected="id_type.id == int(identification) if identification else id_type.id == partner.l10n_latam_identification_type_id.id">
<t t-esc="id_type.name"/>
</option>
</t>
</select>
</t>
<t t-else="">
<p class="form-control" t-esc="partner.l10n_latam_identification_type_id.name" readonly="1" title="Changing Identification type is not allowed once document(s) have been issued for your account. Please contact us directly for this operation."/>
<input name="l10n_latam_identification_type_id" class="form-control" t-att-value="partner.l10n_latam_identification_type_id.id" type='hidden'/>
</t>
</div>
</template>
<template id="address" inherit_id="website_sale.address">
<xpath expr="//input[@name='vat']/.." position="before">
<t t-if="mode[1] == 'billing'" positon="inside">
<t t-if="res_company.country_id.code == 'AR'">
<t t-set="partner" t-value="website_sale_order.partner_id"/>
<t t-call="l10n_ar_website_sale.partner_info"/>
</t>
</t>
</xpath>
<label for="vat" position="attributes">
<attribute name="t-if">res_company.country_id.code != 'AR'</attribute>
</label>
<label for="vat" position="after">
<label t-if="res_company.country_id.code == 'AR'" class="col-form-label label-optional" for="vat">Number</label>
</label>
</template>
</odoo>

View file

@ -0,0 +1,43 @@
[project]
name = "odoo-bringout-oca-ocb-l10n_ar_website_sale"
version = "16.0.0"
description = "Argentinean eCommerce - Odoo addon"
authors = [
{ name = "Ernad Husremovic", email = "hernad@bring.out.ba" }
]
dependencies = [
"odoo-bringout-oca-ocb-website_sale>=16.0.0",
"odoo-bringout-oca-ocb-l10n_ar>=16.0.0",
"requests>=2.25.1"
]
readme = "README.md"
requires-python = ">= 3.11"
classifiers = [
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Topic :: Office/Business",
]
[project.urls]
homepage = "https://github.com/bringout/0"
repository = "https://github.com/bringout/0"
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"
[tool.hatch.metadata]
allow-direct-references = true
[tool.hatch.build.targets.wheel]
packages = ["l10n_ar_website_sale"]
[tool.rye]
managed = true
dev-dependencies = [
"pytest>=8.4.1",
]