Public release from ruodoo-project: 19.0 - 2026-05-10 21:19:01 UTC

This commit is contained in:
CI Publish Bot
2026-05-10 21:19:11 +00:00
commit cbf9e6e6d6
1213 changed files with 183945 additions and 0 deletions

View File

@ -0,0 +1,3 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from . import report_report_xml_abstract

View File

@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="demo_report_xml_view">
<t t-foreach="docs" t-as="o">
<!-- Multicompany -->
<t t-if="o and 'company_id' in o">
<t t-set="company" t-value="o.company_id"></t>
</t>
<t t-if="not o or not 'company_id' in o">
<t t-set="company" t-value="res_company"></t>
</t>
<t t-set="context" t-value="o._context"></t>
<Файл t-att="{'ИдФайл':o.edi or '','ВерсПрог':'[bi-cons.ru] v.1.6','ВерсФорм':'5.01'}">
<СвУчДокОбор t-att="{'ИдОтпр':company.edi,'ИдПол':o.partner_id.edi}">
</СвУчДокОбор>
<Документ t-att="{'КНД':'1115125','Функция':'СЧФДОП','ПоФактХЖ':'Документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)','НаимДокОпр':'Счет-фактура и документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)','ДатаИнфПр':datetime.datetime.now().strftime('%d.%m.%Y'),'ВремИнфПр':datetime.datetime.now().strftime('%H.%M.%S'),'НаимЭконСубСост':company.name or ''}">
<СвСчФакт t-att="{'НомерСчФ':o.name or '','ДатаСчФ':o.invoice_date.strftime('%d.%m.%Y'),'КодОКВ':'643'}">
<СвПрод t-att="{'ОКПО':company.okpo or '','КраткНазв':company.name or ''}">
<ИдСв>
<СвЮЛУч t-att="{'НаимОрг':company.name or '','ИННЮЛ':company.inn or '','КПП':company.kpp or ''}"/>
</ИдСв>
<Адрес>
<АдрРФ t-att="{'КодРегион':company.state_id.code or '','Город':company.city or ''}"/>
</Адрес>
</СвПрод>
<ГрузОт>
<ОнЖе>он же</ОнЖе>
</ГрузОт>
<ГрузПолуч t-att="{'ОКПО':o.partner_id.okpo or '','КраткНазв':o.partner_id.name or ''}">
<ИдСв>
<СвЮЛУч t-att="{'НаимОрг':o.partner_id.name or '','ИННЮЛ':o.partner_id.inn or '','КПП':o.partner_id.kpp or ''}"/>
</ИдСв>
<Адрес>
<АдрРФ t-att="{'КодРегион':o.partner_id.state_id.code or '','Город':o.partner_id.city or ''}"/>
</Адрес>
</ГрузПолуч>
<СвПокуп t-att="{'ОКПО':o.partner_id.okpo or '','КраткНазв':o.partner_id.name or ''}">
<ИдСв>
<СвЮЛУч t-att="{'НаимОрг':o.partner_id.name or '','ИННЮЛ':o.partner_id.inn or '','КПП':o.partner_id.kpp or ''}"/>
</ИдСв>
<Адрес>
<АдрРФ t-att="{'КодРегион':o.partner_id.state_id.code or '','Город':o.partner_id.city or ''}"/>
</Адрес>
</СвПокуп>
</СвСчФакт>
<ТаблСчФакт>
<t t-set="total_price_tax_subtotal" t-value="sum([line.price_unit*line.quantity for line in o.invoice_line_ids])"/>
<t t-set="total_tax_subtotal" t-value="sum([line.price_unit*line.quantity*(line.tax_ids.amount/100) for line in o.invoice_line_ids])"/>
<t t-foreach="o.invoice_line_ids" t-as="line">
<СведТов t-att="{'НомСтр':line_index+1,'НаимТов':line.name or '','ОКЕИ_Тов':line.product_uom_id.okei or '','КолТов':line.quantity or '','ЦенаТов':(('%.2f')%(line.price_subtotal/line.quantity)).replace('.',',') or '','СтТовБезНДС':(('%.2f')%(line.price_subtotal)).replace('.',',') or '','НалСт':(('%.0f')%(line.tax_ids.amount)).replace('.',',')+'%' or 'без НДС','СтТовУчНал':(('%.2f')%(line.price_subtotal*(1+(line.tax_ids.amount/100)))).replace('.',',') or ''}">
<Акциз>
<БезАкциз>без акциза</БезАкциз>
</Акциз>
<СумНал>
<СумНал><t t-esc="(('%.2f')%(line.price_subtotal*(line.tax_ids.amount/100))).replace('.',',') or ''"/></СумНал>
</СумНал>
</СведТов>
</t>
<ВсегоОпл t-att="{'СтТовБезНДСВсего':(('%.2f')%(total_price_tax_subtotal)).replace('.',',') or '','СтТовУчНалВсего':(('%.2f')%(total_price_tax_subtotal+total_tax_subtotal)).replace('.',',') or ''}">
<СумНалВсего>
<СумНал><t t-esc="(('%.2f')%(total_tax_subtotal)).replace('.',',') or ''"/></СумНал>
</СумНалВсего>
</ВсегоОпл>
</ТаблСчФакт>
<Подписант t-att="{'ОблПолн':'0','Статус':'1','ОснПолн':'Должностные обязанности'}">
<ЮЛ t-att="{'ИННЮЛ':company.inn or '','НаимОрг':company.name or '','Должн':company.chief_id.function or ''}">
<ФИО t-att="{'Фамилия':company.chief_id.last_name or '','Имя':company.chief_id.first_name or '','Отчество':company.chief_id.second_name or ''}"/>
</ЮЛ>
</Подписант>
</Документ>
</Файл>
</t>
</template>
</odoo>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<record id="upd_xml_report" model="ir.actions.report">
<field name="name">УПД xml</field>
<field name="model">account.move</field>
<field name="report_type">qweb-xml</field>
<field name="report_name">l10n_ru_upd_xml.demo_report_xml_view</field>
<field name="report_file">l10n_ru_upd_xml.demo_report_xml_view</field>
<field name="print_report_name">'%s' % (object.edi)</field>
<field name="binding_model_id" ref="account.model_account_move"/>
<field name="binding_type">report</field>
</record>
</odoo>

View File

@ -0,0 +1,177 @@
# License AGPL-3.0 or later (https://www.gnuorg/licenses/agpl.html).
from xml.dom import minidom
from odoo.exceptions import UserError
from odoo.tools.translate import _
from lxml import etree
from odoo import api, models
class ReportXmlAbstract(models.AbstractModel):
_name = "report.upd_xml.abstract"
_description = "Abstract XML Report"
@api.model
def generate_report(self, ir_report, docids, data=None):
data = data or {}
data.setdefault("report_type", "text")
records = self.env[ir_report.model].browse(docids)
for s in records:
mes = ""
company = s.company_id or self.env.company
# --- базовые проверки ---
if s.name == '/':
mes += "Отсутствует наименование документа. Проведите документ.\n"
if not s.only_service:
get_delivery = getattr(s, "get_delivery_doc_name", lambda: '0')
if get_delivery() == '0':
mes += "Отсутствуют связанные отгрузки.\n"
# --- компания ---
if not company:
mes += "Не указана компания.\n"
else:
if not company.edi:
mes += "Не указан идентификатор компании для Diadoc.\n"
if not company.name:
mes += "Не указано наименование компании.\n"
if not company.okpo:
mes += "Не указано ОКПО компании.\n"
if not company.inn:
mes += "Не указан ИНН компании.\n"
else:
if len(company.inn) == 12:
if not company.partner_id.last_name_IP:
mes += "Не указана фамилия ИП компании.\n"
if not company.partner_id.first_name_IP:
mes += "Не указано имя ИП компании.\n"
if not company.partner_id.middle_name_IP:
mes += "Не указано отчество ИП компании.\n"
elif len(company.inn) == 10:
if not company.kpp:
mes += "Не указан КПП компании.\n"
else:
mes += "Некорректный ИНН компании.\n"
if not company.city:
mes += "Не указан город компании.\n"
if not company.street:
mes += "Не указан адрес компании.\n"
if not company.chief_id:
mes += "Не указан руководитель компании.\n"
else:
if not company.chief_id.function:
mes += "Не указана должность руководителя.\n"
if not company.chief_id.last_name:
mes += "Не указана фамилия руководителя.\n"
if not company.chief_id.first_name:
mes += "Не указано имя руководителя.\n"
if not company.chief_id.second_name:
mes += "Не указано отчество руководителя.\n"
# --- контрагент ---
pid = s.partner_id.parent_id or s.partner_id
if not pid:
mes += "Не указан контрагент.\n"
else:
if not pid.edi:
mes += "Не указан идентификатор контрагента.\n"
if not pid.name:
mes += "Не указано наименование контрагента.\n"
if not pid.okpo:
mes += "Не указано ОКПО контрагента.\n"
if not pid.inn:
mes += "Не указан ИНН контрагента.\n"
else:
if len(pid.inn) == 12:
if not pid.last_name_IP:
mes += "Не указана фамилия ИП контрагента.\n"
if not pid.first_name_IP:
mes += "Не указано имя ИП контрагента.\n"
if not pid.middle_name_IP:
mes += "Не указано отчество ИП контрагента.\n"
elif len(pid.inn) == 10:
if not pid.kpp:
mes += "Не указан КПП контрагента.\n"
else:
mes += "Некорректный ИНН контрагента.\n"
if not pid.city:
mes += "Не указан город контрагента.\n"
if not pid.street:
mes += "Не указан адрес контрагента.\n"
# --- документ ---
if not s.edi:
mes += "Не указан идентификатор документа.\n"
if not s.name:
mes += "Не указано наименование документа.\n"
if not s.invoice_date:
mes += "Не указана дата документа.\n"
# --- строки ---
if not s.invoice_line_ids:
mes += "Отсутствуют строки.\n"
else:
for line in s.invoice_line_ids:
if not line.price_unit:
mes += f"Нет цены: {line.name}\n"
if not line.quantity:
mes += f"Нет количества: {line.name}\n"
if not line.product_uom_id.okei:
mes += f"Нет ОКЕИ: {line.product_uom_id.name}\n"
# --- договор ---
# if not s.mt_contract_id:
# mes += "Не указан договор.\n"
# else:
# if not s.mt_contract_id.name:
# mes += "Нет названия договора.\n"
# if not s.mt_contract_id.date_start:
# mes += "Нет даты договора.\n"
# --- ответственный ---
if not s.kladov:
mes += "Не указано ответственное лицо.\n"
else:
if not s.kladov.partner_id.function:
mes += "Не указана должность ответственного.\n"
# ❗ если есть ошибки → стоп
if mes:
raise UserError(_(
"Не удалось сформировать УПД. Выявлены следующие ошибки:\n%s"
) % mes)
data = ir_report._get_rendering_context(ir_report, docids, data)
result_bin = ir_report._render_template(ir_report.report_name, data)
parsed_result_bin = minidom.parseString(result_bin)
result = parsed_result_bin.toprettyxml(indent=" ")
result = "\n".join(
line for line in result.splitlines() if line and not line.isspace()
).encode("utf8")
content = etree.tostring(
etree.fromstring(result),
encoding=ir_report.xml_encoding or "WINDOWS-1251",
xml_declaration=True,
pretty_print=True,
)
return content, "xml"
@api.model
def _get_report_values(self, docids, data=None):
return data or {}

View File

@ -0,0 +1,344 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<template id="demo_report_xml_view">
<t t-foreach="docs" t-as="o">
<!-- Multicompany -->
<t t-if="o and o.company_id">
<t t-set="company" t-value="o.company_id"/>
</t>
<t t-elif="not o or not o.company_id">
<t t-set="company" t-value="res_company"/>
</t>
<t t-set="pid" t-value="o and o.partner_id and (o.partner_id.parent_id or o.partner_id) or False"/>
<Файл t-att="{
'ИдФайл': o and o.edi and (o.edi + '_0_0_0_0_0_00') or '',
'ВерсФорм': '5.03',
'ВерсПрог': 'Odoo19'
}">
<Документ t-att="{
'КНД': '1115131',
'Функция': 'СЧФДОП',
'ПоФактХЖ': 'Документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)',
'НаимДокОпр': 'Счет-фактура и документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)',
'ДатаИнфПр': time.strftime('%d.%m.%Y'),
'ВремИнфПр': time.strftime('%H.%M.%S'),
'НаимЭконСубСост': company and company.name or ''
}">
<СвСчФакт t-att="{
'НомерДок': o and (o.invoice_origin or o.name) or '',
'ДатаДок': o and o.invoice_date and o.invoice_date.strftime('%d.%m.%Y') or ''
}">
<СвПрод t-att="{'ОКПО': company and company.okpo or ''}">
<ИдСв>
<t t-if="company and company.inn and len(company.inn) == 10">
<СвЮЛУч t-att="{
'НаимОрг': company.name or '',
'ИННЮЛ': company.inn or '',
'КПП': company.kpp or ''
}"/>
</t>
<t t-elif="company and company.inn and len(company.inn) == 12">
<СвИП t-att="{
'ИННФЛ': company.inn or '',
'ИныеСвед': company.name or ''
}">
<ФИО t-att="{
'Фамилия': company.partner_id and company.partner_id.last_name_IP or '',
'Имя': company.partner_id and company.partner_id.first_name_IP or '',
'Отчество': company.partner_id and company.partner_id.middle_name_IP or ''
}"/>
</СвИП>
</t>
</ИдСв>
<Адрес>
<АдрИнф t-att="{
'КодСтр': '643',
'НаимСтран': 'Российская Федерация',
'АдрТекст': (company.city or '') + ', ' + (company.street or '')
}"/>
</Адрес>
</СвПрод>
<t t-if="o and o.only_service == False">
<ГрузОт>
<ГрузОтпр>
<t t-set="gruzootpr" t-value="o.gruzootpr or company.partner_id"/>
<t t-set="gruzootpr" t-value="gruzootpr and (gruzootpr.parent_id or gruzootpr)"/>
<ИдСв>
<t t-if="gruzootpr and gruzootpr.inn and len(gruzootpr.inn) == 10">
<СвЮЛУч t-att="{
'НаимОрг': gruzootpr.name or '',
'ИННЮЛ': gruzootpr.inn or '',
'КПП': gruzootpr.kpp or ''
}"/>
</t>
<t t-elif="gruzootpr and gruzootpr.inn and len(gruzootpr.inn) == 12">
<СвИП t-att="{
'ИННФЛ': gruzootpr.inn or '',
'ИныеСвед': gruzootpr.name or ''
}">
<ФИО t-att="{
'Фамилия': gruzootpr.last_name_IP or '',
'Имя': gruzootpr.first_name_IP or '',
'Отчество': gruzootpr.middle_name_IP or ''
}"/>
</СвИП>
</t>
</ИдСв>
<Адрес>
<АдрИнф t-att="{
'КодСтр': '643',
'НаимСтран': 'Российская Федерация',
'АдрТекст': (gruzootpr.city or '') + ', ' + (gruzootpr.street or '')
}"/>
</Адрес>
</ГрузОтпр>
</ГрузОт>
<t t-set="gruzopol" t-value="o.gruzopol or pid"/>
<t t-set="gruzopol" t-value="gruzopol and (gruzopol.parent_id or gruzopol)"/>
<ГрузПолуч t-att="{'ОКПО': gruzopol and gruzopol.okpo or ''}">
<ИдСв>
<t t-if="gruzopol and gruzopol.inn and len(gruzopol.inn) == 10">
<СвЮЛУч t-att="{
'НаимОрг': gruzopol.name or '',
'ИННЮЛ': gruzopol.inn or '',
'КПП': gruzopol.kpp or ''
}"/>
</t>
<t t-elif="gruzopol and gruzopol.inn and len(gruzopol.inn) == 12">
<СвИП t-att="{
'ИННФЛ': gruzopol.inn or '',
'ИныеСвед': gruzopol.name or ''
}">
<ФИО t-att="{
'Фамилия': gruzopol.last_name_IP or '',
'Имя': gruzopol.first_name_IP or '',
'Отчество': gruzopol.middle_name_IP or ''
}"/>
</СвИП>
</t>
</ИдСв>
<Адрес>
<АдрИнф t-att="{
'КодСтр': '643',
'НаимСтран': 'Российская Федерация',
'АдрТекст': (gruzopol.city or '') + ', ' + (gruzopol.street or '')
}"/>
</Адрес>
</ГрузПолуч>
</t>
<t t-if="o and o.payment_num and o.payment_num != ''">
<СвПРД t-att="{
'НомерПРД': o.payment_num,
'ДатаПРД': o.payment_date or ''
}"/>
</t>
<t t-if="o and o.only_service == False">
<ДокПодтвОтгрНом
РеквНаимДок="Счет-фактура и документ об отгрузке товаров (выполнении работ), передаче имущественных прав (документ об оказании услуг)"
t-att="{
'РеквНомерДок': o.invoice_origin or o.name or '',
'РеквДатаДок': o.invoice_date and o.invoice_date.strftime('%d.%m.%Y') or ''
}"/>
</t>
<СвПокуп t-att="{'ОКПО': pid and pid.okpo or ''}">
<ИдСв>
<t t-if="pid and pid.inn and len(pid.inn) == 10">
<СвЮЛУч t-att="{
'НаимОрг': pid.name or '',
'ИННЮЛ': pid.inn or '',
'КПП': pid.kpp or ''
}"/>
</t>
<t t-elif="pid and pid.inn and len(pid.inn) == 12">
<СвИП t-att="{
'ИННФЛ': pid.inn or '',
'ИныеСвед': pid.name or ''
}">
<ФИО t-att="{
'Фамилия': pid.last_name_IP or '',
'Имя': pid.first_name_IP or '',
'Отчество': pid.middle_name_IP or ''
}"/>
</СвИП>
</t>
</ИдСв>
<Адрес>
<АдрИнф t-att="{
'КодСтр': '643',
'НаимСтран': 'Российская Федерация',
'АдрТекст': (pid.city or '') + ', ' + (pid.street or '')
}"/>
</Адрес>
</СвПокуп>
<ДенИзм КодОКВ="643" НаимОКВ="Российский рубль" />
</СвСчФакт>
<ТаблСчФакт>
<t t-set="total_price_subtotal" t-value="sum(line.price_subtotal for line in o.invoice_line_ids)"/>
<t t-set="total_price_total" t-value="sum(line.price_total for line in o.invoice_line_ids)"/>
<t t-set="total_tax_amount" t-value="total_price_total - total_price_subtotal"/>
<t t-foreach="o.invoice_line_ids" t-as="line">
<t t-set="tax_rate_raw">
<t t-if="line.tax_ids">
<t t-set="first_tax" t-value="line.tax_ids[0]"/>
<t t-if="first_tax.amount != 0">
<t t-esc="str(int(first_tax.amount)) + '%'"/>
</t>
<t t-else="">
<t t-esc="'без НДС'"/>
</t>
</t>
<t t-else="">
<t t-esc="'без НДС'"/>
</t>
</t>
<t t-set="tax_rate" t-value="tax_rate_raw.replace(' ', '').replace('\n', '').replace('\t', '')"/>
<t t-set="line_tax_amount" t-value="line.price_total - line.price_subtotal"/>
<СведТов t-att="{
'НомСтр': line_index+1,
'НаимТов': line.name or '',
'НаимЕдИзм': line.product_uom_id.name or '',
'КолТов': line.quantity or '',
'ЦенаТов': ('%.2f' % (line.price_subtotal / line.quantity if line.quantity else 0)) if line.quantity else '0.00',
'СтТовБезНДС': ('%.2f' % (line.price_subtotal or 0)),
'НалСт': tax_rate,
'СтТовУчНал': ('%.2f' % (line.price_total or 0))
}">
<ДопСведТов t-att="{
'КодТов': line.product_id and line.product_id.default_code or '',
'ГТИН': '0' + (line.product_id and line.product_id.barcode or '') if line.product_id and line.product_id.barcode else '',
'КодВидТов': line.product_id and line.product_id.hs_code or ''
}">
<t t-if="line.product_id and line.product_id.tracking == 'serial'">
<КрНаимСтрПр>Китай</КрНаимСтрПр>
<НомСредИдентТов>
<t t-foreach="line.sale_line_ids" t-as="line_order">
<t t-foreach="line_order.move_ids" t-as="line_move">
<t t-foreach="line_move.move_line_ids.filtered(lambda km: km.state=='done')" t-as="lot">
<t t-if="lot.lot_id and lot.lot_id.cz_code_id">
<КИЗ><t t-esc="lot.lot_id.cz_code_id.code_without_characters"/></КИЗ>
</t>
</t>
</t>
</t>
</НомСредИдентТов>
</t>
</ДопСведТов>
<Акциз>
<БезАкциз>без акциза</БезАкциз>
</Акциз>
<СумНал>
<t t-if="line_tax_amount != 0">
<СумНал><t t-esc="('%.2f' % line_tax_amount)"/></СумНал>
</t>
<t t-else="">
<БезНДС>без НДС</БезНДС>
</t>
</СумНал>
</СведТов>
</t>
<ВсегоОпл t-att="{
'СтТовБезНДСВсего': ('%.2f' % total_price_subtotal),
'СтТовУчНалВсего': ('%.2f' % total_price_total)
}">
<СумНалВсего>
<t t-if="total_tax_amount != 0">
<СумНал><t t-esc="('%.2f' % total_tax_amount)"/></СумНал>
</t>
<t t-else="">
<БезНДС>без НДС</БезНДС>
</t>
</СумНалВсего>
</ВсегоОпл>
</ТаблСчФакт>
<СвПродПер>
<СвПер t-att="{
'СодОпер': 'Товары или услуги по документу',
'ДатаПер': o.invoice_date and o.invoice_date.strftime('%d.%m.%Y') or ''
}">
<ОснПер t-att="{
'РеквНаимДок': 'Счет-фактура',
'РеквНомерДок': o.invoice_origin or o.name or '',
'РеквДатаДок': o.invoice_date and o.invoice_date.strftime('%d.%m.%Y') or ''
}"/>
<СвЛицПер>
<РабОргПрод t-att="{'Должность': o.kladov and o.kladov.partner_id and o.kladov.partner_id.function or ''}">
<t t-if="o.kladov and o.kladov.partner_id and o.kladov.partner_id.name">
<t t-set="name_parts" t-value="o.kladov.partner_id.name.split()"/>
<t t-if="len(name_parts) == 3">
<ФИО t-att="{
'Фамилия': name_parts[0],
'Имя': name_parts[1],
'Отчество': name_parts[2]
}"/>
</t>
<t t-else="">
<ФИО t-att="{
'Фамилия': name_parts[0] if name_parts else '',
'Имя': name_parts[1] if len(name_parts) > 1 else ''
}"/>
</t>
</t>
</РабОргПрод>
</СвЛицПер>
<Тран t-att="{'СвТран': o.transport or 'Без квитанции'}"/>
</СвПер>
</СвПродПер>
<Подписант t-att="{
'СпосПодтПолном': '1',
'Должн': company.chief_id and company.chief_id.function or ''
}">
<t t-if="company.inn and len(company.inn) == 10">
<t t-if="company.chief_id and company.chief_id.second_name">
<ФИО t-att="{
'Фамилия': company.chief_id.last_name or '',
'Имя': company.chief_id.first_name or '',
'Отчество': company.chief_id.second_name or ''
}"/>
</t>
<t t-else="">
<ФИО t-att="{
'Фамилия': company.chief_id and company.chief_id.last_name or '',
'Имя': company.chief_id and company.chief_id.first_name or ''
}"/>
</t>
</t>
<t t-elif="company.inn and len(company.inn) == 12">
<t t-if="company.partner_id and company.partner_id.middle_name_IP">
<ФИО t-att="{
'Фамилия': company.partner_id.last_name_IP or '',
'Имя': company.partner_id.first_name_IP or '',
'Отчество': company.partner_id.middle_name_IP or ''
}"/>
</t>
<t t-else="">
<ФИО t-att="{
'Фамилия': company.partner_id and company.partner_id.last_name_IP or '',
'Имя': company.partner_id and company.partner_id.first_name_IP or ''
}"/>
</t>
</t>
</Подписант>
</Документ>
</Файл>
</t>
</template>
</odoo>