TIP: You can type at any time to perform a new search.
TicketBAI - API
l10n_es_ticketbai_api · OCA/l10n-spain
- Repository
- OCA/l10n-spain · module folder · Try on Runboat
- Module version
- 1.1.4
- Category
- Accounting & Finance
- Folder size
- 5.2 MB
- License
- AGPL-3
- Application
- No
- Auto-installable
- No
- Website
- https://github.com/OCA/l10n-spain
- Last tracking update
- 2026-08-07 08:09:10
- Authors
- Odoo Community Association (OCA), Binovo
- Maintainers
- Odoo Community Association (OCA), Binovo
- Committers
- Pedro M. Baeza, Weblate, OCA-git-bot, oca-ci, Aritz Olea, Andrii9090-tecnativa, luciaavanzosc, r.perez
- Odoo dependencies
- Python dependencies
- qrcode, xmlsig, xmltodict
- System dependencies
- None
- Required by
- l10n_es_ticketbai, l10n_es_ticketbai_api_batuz
- Description
Code Analysis ⓘ
Views touched (8)
| XML ID | Name | Model | Type | Status |
|---|---|---|---|---|
res_config_settings_view_form_inherit_l10n_es_ticketbai_api |
res.config.settings.view.form.inherit.base.setup.inherit.ticketbai_api | res.config.settings | form | Inherits base_setup.res_config_settings_view_form |
tbai_certificate_form_view |
tbai.certificate.view.form | tbai.certificate | form | New |
tbai_certificate_search_view |
tbai.certificate.view.search | tbai.certificate | search | New |
tbai_certificate_tree_view |
tbai.certificate.view.tree | tbai.certificate | tree | New |
tbai_installation_form_view |
tbai.installation.view.form | tbai.installation | form | New |
tbai_installation_search_view |
tbai.installation.view.search | tbai.installation | search | New |
tbai_installation_tree_view |
tbai.installation.view.tree | tbai.installation | tree | New |
view_company_form_inherit |
res.company.form.inherit | res.company | form | Inherits base.view_company_form |
HTTP endpoints (0)
No HTTP endpoints found for this module.
Models touched (14)
New fields (14)
-
tbai_certificate_idMany2one → tbai.certificatecomodel_name='tbai.certificate'copy=Falsedomain="[('company_id', '=', id)]"string='Certificate' -
tbai_developer_idMany2one → res.partnercomodel_name='res.partner'readonly=Truerelated='tbai_installation_id.developer_id'string='Developer' -
tbai_device_serial_numberCharcopy=Falsedefault='' args: 'Device Serial Number' -
tbai_enabledBooleancopy=False args: 'Enable TicketBAI' -
tbai_installation_idMany2one → tbai.installationcomodel_name='tbai.installation'copy=False -
tbai_last_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'copy=Falsestring='Last TicketBAI Invoice sent' -
tbai_license_keyCharreadonly=Truerelated='tbai_installation_id.license_key' args: 'License Key' -
tbai_pro_availableBooleancopy=False args: 'Are Production URLs Available' -
tbai_software_nameCharhelp='Registered name at the Tax Agency.'readonly=Truerelated='tbai_installation_id.name'string='Software Name' -
tbai_software_versionCharcopy=Falsehelp='Version of the software.'related='tbai_installation_id.version'string='Software Version' -
tbai_tax_agency_idMany2one → tbai.tax.agencycomodel_name='tbai.tax.agency'copy=Falsestring='TBAI Tax Agency' -
tbai_test_availableBooleancopy=False args: 'Are Tests URLs Available' -
tbai_test_enabledBooleancopy=False args: 'Enable testing' -
tbai_vat_regime_simplifiedBooleancopy=False args: 'Regime Simplified'
-
is_operation_in_surcharge_equivalence_or_simplified_regime(self) -
onchange_tbai_enabled(self)@api.onchange('tbai_enabled') -
onchange_tbai_tax_agency(self)@api.onchange('tbai_tax_agency_id') -
tbai_build_software(self) -
tbai_certificate_get_p12(self) -
tbai_certificate_get_p12_buffer(self) -
tbai_certificate_get_p12_password(self)
New fields (2)
-
tbai_device_serial_numberCharreadonly=Falserelated='company_id.tbai_device_serial_number'string='Device Serial Number' -
tbai_enabledBooleanreadonly=Truerelated='company_id.tbai_enabled'
No public methods.
New fields (3)
-
tbai_enabledBooleancompute='_compute_tbai_enabled' -
tbai_partner_identification_numberChardefault=''help='Used when the identification type code is not VAT identification number.' args: 'TicketBAI Partner Identification Number' -
tbai_partner_idtypeSelectiondefault=TicketBaiCustomerIdType.T02.valueselection=[(TicketBaiCustomerIdType.T02.value, 'VAT identification number'), (TicketBaiCustomerIdType.T03.value, 'Passport'), (TicketBaiCustomerIdType.T04.value, 'Official identification document issued by the country or territory of residence'), (TicketBaiCustomerIdType.T05.value, 'Residence certificate'), (TicketBaiCustomerIdType.T06.value, 'Other document')]string='TicketBAI Identification Type Code'
-
tbai_get_partner_country_code(self) -
tbai_get_partner_vat_number(self) -
tbai_get_value_apellidos_nombre_razon_social(self)V 1.2 <element name="ApellidosNombreRazonSocial" type="T:TextMax120Type"/> <maxLength value="120"/> :return: Name and surname, or business name -
tbai_get_value_direccion(self)V 1.2 <element name="Direccion" type="T:TextMax250Type" minOccurs="0"/> <maxLength value="250"/> -
tbai_get_value_nif(self)V 1.2 <element name="NIF" type="T:NIFType"/> <length value="9" /> <pattern value="(([a-z|A-Z]{1}\d{7}[a-z|A-Z]{1})|(\d{8}[a-z|A-Z]{1})| ([a-z|A-Z]{1}\d{8}))" /> :return: VAT Number for Customers from Spain or the Company associated partner.
New fields (4)
-
company_idMany2one → res.companycomodel_name='res.company'default=<expr>required=Truestring='Company' -
datasBinaryattachment=Truerequired=True args: 'P12 Certificate' -
nameCharrequired=True -
passwordChardefault=''
-
get_p12(self):return: cryptography.pkcs12 -
get_p12_buffer(self):return: p12 Buffer
New fields (5)
-
developer_idMany2one → res.partnercomodel_name='res.partner'copy=Falserequired=Truestring='Developer' -
license_keyCharcopy=Falserequired=True -
nameCharcopy=Falsehelp='Registered name at the Tax Agency.'required=Truestring='Software Name' -
vatCharrelated='developer_id.vat' args: 'TIN' -
versionCharcopy=Falsehelp='Version of the software.'required=Truestring='Software Version'
No public methods.
New fields (36)
-
amount_totalChardefault='' -
api_urlCharcompute='_compute_api_url' args: 'TicketBAI API URL' -
company_idMany2one → res.companycomodel_name='res.company'required=True -
datasBinaryattachment=Truecopy=False -
datas_fnameCharcopy=False args: 'File Name' -
descriptionChardefault='/' -
expedition_dateCharrequired=True -
expedition_hourChardefault='' -
file_sizeIntegercopy=False -
is_invoice_refundBooleanhelp='TicketBAI Invoice is a refund (Substitution or Differences).' -
nameCharrequired=True -
numberCharrequired=True -
number_prefixChardefault='' -
operation_dateChardefault='' -
previous_tbai_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'copy=False -
qrBinaryattachment=Truecompute='_compute_tbai_qr'copy=Falsestore=Truestring='QR' -
qr_urlCharcompute='_compute_tbai_qr'copy=Falsestore=True args: 'URL' -
refund_codeSelectionhelp='BOE-A-1992-28740. Ley 37/1992, de 28 de diciembre, del Impuesto sobre el Valor Añadido. ArtÃculo 80. Modificación de la base imponible.'selection=[(RefundCode.R1.value, 'Art. 80.1, 80.2, 80.6 and rights founded error'), (RefundCode.R2.value, 'Art. 80.3'), (RefundCode.R3.value, 'Art. 80.4'), (RefundCode.R4.value, 'Art. 80 - other'), (RefundCode.R5.value, 'Simplified Invoice')]string='Invoice Refund Reason Code' -
refund_typeSelectionhelp='Refund Invoice Type (S/Substitution or I/Differences).'selection=[(RefundType.substitution.value, 'S'), (RefundType.differences.value, 'I')] -
schemaSelectionhelp='\n * TicketBai: Invoice\n * AnulaTicketBai: Invoice Cancellation\n 'required=Trueselection=[(TicketBaiSchema.TicketBai.value, 'TicketBai'), (TicketBaiSchema.AnulaTicketBai.value, 'AnulaTicketBai')] -
signature_valueCharcopy=Falsedefault='' -
simplified_invoiceSelectionhelp='S/Yes or N/No'selection=[(SiNoType.S.value, 'S'), (SiNoType.N.value, 'N')] -
stateSelectioncopy=Falsedefault=TicketBaiInvoiceState.draft.valueindex=Truerequired=Trueselection=[(TicketBaiInvoiceState.draft.value, 'Draft'), (TicketBaiInvoiceState.pending.value, 'Pending'), (TicketBaiInvoiceState.sent.value, 'Sent'), (TicketBaiInvoiceState.cancel.value, 'Cancelled'), (TicketBaiInvoiceState.error.value, 'Error')]string='Status' -
substituted_invoice_amount_total_untaxedChardefault=''help='\n Original Invoice Total Amount without Taxes. E.g.:\n - Amount Total: 121.0 €\n - Tax Amount: 21 %\n - Total Tax Amount: 21 €\n * Amount Total Untaxed: 100 €\n ' -
substituted_invoice_total_tax_amountChardefault=''help='\n Original Invoice Total Tax Amount. E.g.:\n - Amount Total: 121.0 €\n - Tax Amount: 21 %\n * Total Tax Amount: 21 €\n ' -
substitutes_simplified_invoiceSelectionhelp='S/Yes or N/No'selection=[(SiNoType.S.value, 'S'), (SiNoType.N.value, 'N')] -
tax_retention_amount_totalChardefault='' args: 'Invoice Tax Retention Total Amount' -
tbai_customer_idsOne2many → tbai.invoice.customercomodel_name='tbai.invoice.customer'copy=Trueinverse_name='tbai_invoice_id'string='TicketBAI Invoice Recipients' -
tbai_identifierCharcompute='_compute_tbai_identifier'copy=Falsestore=True args: 'TBAI Identifier' -
tbai_invoice_line_idsOne2many → tbai.invoice.linecomodel_name='tbai.invoice.line'copy=Trueinverse_name='tbai_invoice_id'string='TicketBAI Invoice Details' -
tbai_invoice_refund_idsOne2many → tbai.invoice.refundcomodel_name='tbai.invoice.refund'copy=Trueinverse_name='tbai_invoice_id'string='Refunded Invoices' -
tbai_response_idsOne2many → tbai.responsecomodel_name='tbai.response'inverse_name='tbai_invoice_id'string='Responses' -
tbai_tax_idsOne2many → tbai.invoice.taxcomodel_name='tbai.invoice.tax'copy=Trueinverse_name='tbai_invoice_id'string='TicketBAI Invoice Taxes' -
vat_regime_keyChardefault='' args: 'VAT Regime Key' -
vat_regime_key2Chardefault='' args: 'Second VAT Regime Key' -
vat_regime_key3Chardefault='' args: 'Third VAT Regime Key'
-
build_cabecera(self)V 1.2 Get TicketBAI version from the Company Tax Agency. <element name="Cabecera" type="T:Cabecera"/> <complexType name="Cabecera"> <sequence> <element name="IDVersionTBAI" type="T:IDVersionTicketBaiType"/> <enumeration value="1.2"/> </sequence> </complexType> :return: Tax Agency -
build_cabecera_factura(self) -
build_cancellation(self) -
build_claves(self)V 1.2 The specification document indicates that at least 1 regime key is required. <element name="IDClave" type="T:IDClaveType" maxOccurs="3"/> <sequence> <element name="ClaveRegimenIvaOpTrascendencia" type="T:IdOperacionesTrascendenciaTributariaType"/> </sequence> :return: dict -
build_datos_factura(self) -
build_destinatarios(self)Support only for one customer. -
build_detalle_exenta(self)V 1.2 <element name="DetalleExenta" type="T:DetalleExentaType" minOccurs="1" maxOccurs="7" /> <sequence> <element name="CausaExencion" type="T:CausaExencionType" /> <restriction base="string"> <enumeration value="E1"> ... <element name="BaseImponible" type="T:ImporteSgn12.2Type"/> </sequence> :return: list<OrderedDict> -
build_detalle_no_exenta(self)V 1.2 1. Inversión del Sujeto Pasivo (ISP) taxes (tax is paid by the customer). 2. Other taxes <element name="DetalleNoExenta" type="T:DetalleNoExentaType" minOccurs="1" maxOccurs="2" /> <sequence> <element name="TipoNoExenta" type="T:TipoOperacionSujetaNoExentaType"/> <restriction base="string"> <enumeration value="S1"> <enumeration value="S2"> <element name="DesgloseIVA" type="T:DesgloseIVAType"/> <element name="DetalleIVA" type="T:DetalleIVAType" maxOccurs="6" /> <sequence> <element name="BaseImponible" type="T:ImporteSgn12.2Type"/> <element name="TipoImpositivo" type="T:Tipo3.2Type" minOccurs="0"/> <element name="CuotaImpuesto" type="T:ImporteSgn12.2Type" minOccurs="0" /> <element name="TipoRecargoEquivalencia" type="T:Tipo3.2Type" minOccurs="0"/> <element name="CuotaRecargoEquivalencia" type="T:ImporteSgn12.2Type" minOccurs="0"/> <element name="OperacionEnRecargoDeEquivalenciaORegimenSimplificado" type="T:SiNoType" minOccurs="0"/> :return: list<OrderedDict> -
build_detalle_no_sujeta(self)V 1.2 <element name="DetalleNoSujeta" type="T:DetalleNoSujeta" minOccurs="1" maxOccurs="2" /> <sequence> <element name="Causa" type="T:CausaNoSujetaType"/> <element name="Importe" type="T:ImporteSgn12.2Type"/> </sequence> :return: list<OrderedDict> -
build_detalles_factura(self) -
build_emisor(self) -
build_encadenamiento_factura_anterior(self) -
build_entrega(self)V 1.2 <element name="Entrega" type="T:Entrega" minOccurs="0"/> <sequence> <element name="Sujeta" type="T:SujetaType" minOccurs="0" /> <element name="NoSujeta" type="T:NoSujetaType" minOccurs="0" /> </sequence> :return: OrderedDict -
build_exenta(self)V 1.2 <element name="DetalleExenta" type="T:DetalleExentaType" minOccurs="1" maxOccurs="7" /> :return: dict -
build_factura(self) -
build_factura_rectificativa(self) -
build_facturas_rectificadas_sustituidas(self) -
build_huella_tbai(self) -
build_id_detalle_factura(self) -
build_id_factura(self) -
build_importe_rectificacion_sustitutiva(self) -
build_invoice(self) -
build_no_exenta(self)V 1.2 <element name="DetalleNoExenta" type="T:DetalleNoExentaType" minOccurs="1" maxOccurs="2" /> :return: dict -
build_no_sujeta(self)V 1.2 <element name="NoSujeta" type="T:NoSujetaType" minOccurs="0" /> <sequence> <element name="DetalleNoSujeta" type="T:DetalleNoSujeta" minOccurs="1" maxOccurs="2" /> </sequence> :return: OrderedDict -
build_prestacion_servicios(self)V 1.2 <element name="PrestacionServicios" type="T:PrestacionServicios" minOccurs="0"/> <sequence> <element name="Sujeta" type="T:SujetaType" minOccurs="0" /> <element name="NoSujeta" type="T:NoSujetaType" minOccurs="0" /> </sequence> :return: OrderedDict -
build_sujeta(self)V 1.2 <element name="Sujeta" type="T:SujetaType" minOccurs="0" /> <sequence> <element name="Exenta" type="T:ExentaType" minOccurs="0" /> <element name="NoExenta" type="T:NoExentaType" minOccurs="0" /> :return: OrderedDict -
build_sujetos(self) -
build_tbai_invoice(self) -
build_tipo_desglose(self) -
cancel(self) -
error(self) -
get_exempted_taxes(self)* Subject to: - Exempted :return: Recordset of tbai.invoice.tax -
get_next_pending_invoice(self, company_id=False, limit=1)@api.model -
get_not_exempted_taxes(self)* Subject to: - Not exempted :return: Recordset of tbai.invoice.tax -
get_not_subject_to_taxes(self)* Not subject to :return: Recordset of tbai.invoice.tax -
get_subject_to_taxes(self)* Subject to :return: Recordset of tbai.invoice.tax -
get_taxes(self)Filter TicketBai Taxes when Customer is not from Spain. * DesgloseTipoOperacion - PrestacionServicios - Entrega :return: Recordset of tbai.invoice.tax -
get_tbai_xml_signed_and_signature_value(self) -
get_tbai_xml_unsigned(self) -
get_ticketbai_api(self, **kwargs) -
mark_as_pending(self) -
mark_as_sent(self) -
mark_chain_as_error(self, invoice_to_error)@api.model -
send(self, **kwargs) -
send_pending_invoices(self)@api.model
New fields (8)
-
addressChardefault='' -
country_codeCharrequired=True -
identification_numberChardefault=''help='Required Identification Number for non spanish customers.' -
idtypeSelectiondefault=TicketBaiCustomerIdType.T02.valuehelp='Required for non spanish customers.'selection=[(TicketBaiCustomerIdType.T02.value, 'VAT identification number'), (TicketBaiCustomerIdType.T03.value, 'Passport'), (TicketBaiCustomerIdType.T04.value, 'Official identification document issued by the country or territory of residence'), (TicketBaiCustomerIdType.T05.value, 'Residence certificate'), (TicketBaiCustomerIdType.T06.value, 'Other document')]string='Identification Type Code' -
nameCharhelp='Name and surname, or business name.'required=True -
nifChardefault=''help='Spanish Fiscal Identification Number' args: 'NIF' -
tbai_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'ondelete='cascade'required=True -
zipChardefault='' args: 'ZIP Code'
No public methods.
New fields (6)
-
amount_totalCharhelp='String of float with 12 digits and 2 decimal points.'required=True -
descriptionCharrequired=True -
discount_amountChardefault='0.00'help='String of float with 12 digits and 2 decimal points.' -
price_unitCharhelp='String of float with 12 digits and 8 decimal points.'required=True -
quantityCharhelp='String of float with 12 digits and 2 decimal points.'required=True -
tbai_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'ondelete='cascade'required=True
No public methods.
New fields (4)
-
expedition_dateCharrequired=True -
numberCharrequired=True -
number_prefixChardefault='' -
tbai_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'ondelete='cascade'required=True
No public methods.
New fields (13)
-
amountChardefault=''help='String of float with 3 digits and 2 decimal points.' args: 'Amount (%)' -
amount_totalChardefault=''help='String of float with 12 digits and 2 decimal points.' -
baseChardefault=''help='String of float with 12 digits and 3 decimal points.' -
exempted_causeSelectionhelp='\n E1: Exenta por el artÃculo 20 de la Norma Foral del IVA.\n E2: Exenta por el artÃculo 21 de la Norma Foral del IVA.\n E3: Exenta por el artÃculo 22 de la Norma Foral del IVA.\n E4: Exenta por el artÃculo 23 y 24 de la Norma Foral del IVA.\n E5: Exenta por el artÃculo 25 de la Norma Foral del IVA.\n E6: Exenta por otra causa.\n 'selection=[(ExemptedCause.E1.value, 'E1'), (ExemptedCause.E2.value, 'E2'), (ExemptedCause.E3.value, 'E3'), (ExemptedCause.E4.value, 'E4'), (ExemptedCause.E5.value, 'E5'), (ExemptedCause.E6.value, 'E6')] -
is_exemptedBoolean -
is_subject_toBooleanargs: 'Is Subject to' -
not_exempted_typeSelectionhelp='\n S1: Sin inversión del sujeto pasivo.\n S2: Con inversión del sujeto pasivo.\n 'selection=[(NotExemptedType.S1.value, 'S1'), (NotExemptedType.S2.value, 'S2')] -
not_subject_to_causeSelectionhelp='\n OT:\n - No sujeto por el artÃculo 7 de la Norma Foral de IVA Otros supuestos de no\n sujeción.\n RL:\n - No sujeto por reglas de localización.\n 'selection=[(NotSubjectToCause.OT.value, 'OT'), (NotSubjectToCause.RL.value, 'RL')]string='Not Subject to Cause' -
re_amountChardefault=''help='String of float with 3 digits and 2 decimal points.' args: 'Surcharge Amount (%)' -
re_amount_totalChardefault=''help='String of float with 12 digits and 2 decimal points.' args: 'Surcharge Amount Total' -
surcharge_or_simplified_regimeSelectiondefault=SurchargeOrSimplifiedRegimeType.N.valueselection=[(SurchargeOrSimplifiedRegimeType.N.value, 'N'), (SurchargeOrSimplifiedRegimeType.S.value, 'S')]string='Surcharge or Simplified Regime' -
tbai_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'ondelete='cascade'required=True -
typeSelectionselection=[(TicketBaiTaxType.service.value, 'Service'), (TicketBaiTaxType.provision_of_goods.value, 'Provision of goods')]
No public methods.
New fields (5)
-
stateSelectionrequired=Trueselection=[(TicketBaiResponseState.RECEIVED.value, 'Received'), (TicketBaiResponseState.REJECTED.value, 'Rejected'), (TicketBaiResponseState.REQUEST_ERROR.value, 'Request error'), (TicketBaiResponseState.BUILD_ERROR.value, 'Build error')]string='Status' -
tbai_invoice_idMany2one → tbai.invoicecomodel_name='tbai.invoice'ondelete='cascade'required=True -
tbai_response_message_idsOne2many → tbai.response.messagecomodel_name='tbai.response.message'inverse_name='tbai_response_id' -
xmlBinaryattachment=Truestring='XML Response' -
xml_fnameCharargs: 'File Name'
-
prepare_tbai_api_error_values(self, msg)@api.model -
prepare_tbai_response_values(self, response)@api.model
New fields (3)
-
codeCharrequired=True -
descriptionCharrequired=Truetranslate=True -
tbai_response_idMany2one → tbai.responsecomodel_name='tbai.response'ondelete='cascade'required=True
-
create(self, vals_list)@api.model_create_multi -
name_get(self)@api.depends('code', 'description')
New fields (11)
-
nameCharrequired=Truestring='Tax Agency name' -
qr_base_urlCharcompute='_compute_ticketbai_version'store=Truestring='QR Base URL' -
rest_url_cancellationCharcompute='_compute_ticketbai_version'store=Truestring='REST API URL for Invoice Cancellations' -
rest_url_invoiceCharcompute='_compute_ticketbai_version'store=Truestring='REST API URL for Invoices' -
sign_file_hashCharrequired=Truestring='Sign File HASH' -
sign_file_urlCharrequired=Truestring='Sign File URL' -
tax_agency_version_idsOne2many → tbai.tax.agency.versioncomodel_name='tbai.tax.agency.version'inverse_name='tbai_tax_agency_id' -
test_qr_base_urlCharcompute='_compute_ticketbai_version'store=Truestring='Test QR Base URL' -
test_rest_url_cancellationCharcompute='_compute_ticketbai_version'store=Truestring='Test - REST API URL for Invoice Cancellations' -
test_rest_url_invoiceCharcompute='_compute_ticketbai_version'store=Truestring='Test - REST API URL for Invoices' -
versionCharcompute='_compute_ticketbai_version'store=Truestring='TicketBAI version'
-
get_current_version(self)
New fields (10)
-
date_fromDate -
date_toDate -
qr_base_urlCharrequired=Truestring='QR Base URL' -
rest_url_cancellationCharstring='REST API URL for Invoice Cancellations' -
rest_url_invoiceCharstring='REST API URL for Invoices' -
tbai_tax_agency_idMany2one → tbai.tax.agencycomodel_name='tbai.tax.agency'ondelete='restrict'required=True -
test_qr_base_urlCharstring='Test - QR Base URL' -
test_rest_url_cancellationCharstring='Test - REST API URL for Invoice Cancellations' -
test_rest_url_invoiceCharstring='Test - REST API URL for Invoices' -
versionCharrequired=Truestring='TicketBAI version'
No public methods.
Loading…
Loading…
Loading…
Loading…
Loading…