Using the new api of account_invoice_facturae, it generates xml files using the correct Facturaev3_2 format (Required by Electronet).
#035013
This commit is contained in:
parent
5296b45583
commit
7bad0a0b85
File diff suppressed because it is too large
Load Diff
|
@ -3,9 +3,12 @@
|
|||
# the full copyright notices and license terms.
|
||||
from trytond.pool import Pool
|
||||
from . import invoice
|
||||
from . import party
|
||||
|
||||
|
||||
def register():
|
||||
Pool.register(
|
||||
invoice.Invoice,
|
||||
invoice.GenerateFacturaeStart,
|
||||
party.Party,
|
||||
module='account_invoice_facturae_electronet', type_='model')
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
Account Invoice Factura-e Electronet Module
|
||||
###########################################
|
||||
|
||||
Módulo que permite el comercio electrónico a través de la plataforma Electronet utilizando el formato de archivo Factura-e.
|
||||
|
|
|
@ -1,2 +1,4 @@
|
|||
Account Invoice Factura-e Electronet Module
|
||||
###########################################
|
||||
|
||||
Module that allows the e-commerce throught Electronet platform using the Factura-e file format.
|
62
invoice.py
62
invoice.py
|
@ -2,35 +2,75 @@
|
|||
# this repository contains the full copyright notices and license terms.
|
||||
from trytond.pool import PoolMeta
|
||||
from trytond.config import config
|
||||
from trytond import backend
|
||||
from trytond.transaction import Transaction
|
||||
import os
|
||||
from jinja2 import Environment, FileSystemLoader
|
||||
|
||||
__all__ = ['Invoice', 'GenerateFacturaeStart']
|
||||
|
||||
ELECTRONET = config.get('electronet', 'facturae_path', default='/tmp')
|
||||
ELECTRONET_TEMPLATE = 'template_facturae_3.2.xml'
|
||||
ELECTRONET_TEMPLATE_SCHEMA = 'Facturaev3_2.xsd'
|
||||
MODULE_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class Invoice:
|
||||
__metaclass__ = PoolMeta
|
||||
__name__ = 'account.invoice'
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super(Invoice, cls).__setup__()
|
||||
cls._error_messages.update({
|
||||
'missing_facturae_party_info': (
|
||||
'Missing Factura-e info in party "%(party)s", '
|
||||
'review the tab Factura-e of this party: "%(field)s"')
|
||||
})
|
||||
|
||||
@classmethod
|
||||
def generate_facturae_electronet(cls, invoices, certificate_password=None):
|
||||
to_save = []
|
||||
to_write = ([],)
|
||||
for invoice in invoices:
|
||||
if invoice.invoice_facturae:
|
||||
continue
|
||||
facturae_content = invoice.get_facturae()
|
||||
invoice._validate_facturae(facturae_content)
|
||||
invoice.invoice_facturae = facturae_content
|
||||
to_save.append(invoice)
|
||||
if to_save:
|
||||
cls.save(to_save)
|
||||
# TODO
|
||||
# Two phase commit
|
||||
for inv in to_save:
|
||||
schema_file_path = os.path.join(MODULE_PATH,
|
||||
ELECTRONET_TEMPLATE_SCHEMA)
|
||||
invoice._validate_facturae(facturae_content, schema_file_path)
|
||||
invoice_facturae = facturae_content
|
||||
fname = '%s/%s' % (ELECTRONET,
|
||||
inv.invoice_facturae_filename.replace('.xsig', '.xml'))
|
||||
invoice.invoice_facturae_filename.replace('.xsig', '.xml'))
|
||||
with open(fname, 'w') as output_file:
|
||||
output_file.write(inv.invoice_facturae)
|
||||
output_file.write(invoice_facturae)
|
||||
to_write[0].append(invoice)
|
||||
to_write += ({'invoice_facturae': invoice_facturae},)
|
||||
if to_write:
|
||||
cls.write(*to_write)
|
||||
|
||||
def get_facturae(self):
|
||||
for party in (self.party, self.company.party):
|
||||
if not (party.oficina_contable or party.organo_gestor or
|
||||
party.unidad_tramitadora or party.organo_proponente):
|
||||
self.raise_user_error('missing_facturae_party_info', {
|
||||
'party': party.rec_name,
|
||||
'field': '',
|
||||
})
|
||||
elif not party.id_electronet:
|
||||
self.raise_user_error('missing_facturae_party_info', {
|
||||
'party': party.rec_name,
|
||||
'field': 'ID Electronet'
|
||||
})
|
||||
|
||||
jinja_env = Environment(
|
||||
loader=FileSystemLoader(MODULE_PATH),
|
||||
trim_blocks=True,
|
||||
lstrip_blocks=True,
|
||||
)
|
||||
jinja_template = self._get_jinja_template(jinja_env,
|
||||
ELECTRONET_TEMPLATE)
|
||||
return jinja_template.render(
|
||||
self._get_content_to_render(), ).encode('utf-8')
|
||||
|
||||
|
||||
class GenerateFacturaeStart:
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains the full
|
||||
# copyright notices and license terms.
|
||||
from trytond.model import fields
|
||||
from trytond.pool import PoolMeta
|
||||
|
||||
__all__ = ['Party']
|
||||
|
||||
|
||||
class Party:
|
||||
__metaclass__ = PoolMeta
|
||||
__name__ = 'party.party'
|
||||
|
||||
id_electronet = fields.Char('Id Electronet')
|
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data>
|
||||
<record model="ir.ui.view" id="party_view_form">
|
||||
<field name="model">party.party</field>
|
||||
<field name="inherit" ref="party.party_view_form"/>
|
||||
<field name="name">party_form</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
|
@ -0,0 +1,336 @@
|
|||
{% from "template_facturae_macros.xml" import administrative_center, address, contact %}<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
|
||||
<namespace:Facturae xmlns:namespace2="http://uri.etsi.org/01903/v1.2.2#" xmlns:namespace3="http://www.w3.org/2000/09/xmldsig#" xmlns:namespace="http://www.facturae.es/Facturae/2009/v3.2/Facturae">
|
||||
<FileHeader>
|
||||
<SchemaVersion>3.2</SchemaVersion>
|
||||
<Modality>I</Modality>
|
||||
{# The invoice is signed by Issuer (the company, only supported out invoices) #}
|
||||
<InvoiceIssuerType>EM</InvoiceIssuerType>
|
||||
{# As InvoiceIssuerType != TE, ThirdParty element is not generated #}
|
||||
<Batch>
|
||||
<BatchIdentifier>{{ ('%s%s' % (invoice.company.party.vat_code, invoice.number))[:70] }}</BatchIdentifier>
|
||||
<InvoicesCount>1</InvoicesCount>
|
||||
<TotalInvoicesAmount>
|
||||
<TotalAmount>{{ invoice.total_amount }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TotalInvoicesAmount>
|
||||
<TotalOutstandingAmount>
|
||||
{# TODO: it must to get amount_to_pay? #}
|
||||
<TotalAmount>{{ invoice.total_amount }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TotalOutstandingAmount>
|
||||
<TotalExecutableAmount>
|
||||
{# TODO: it must to get amount_to_pay? #}
|
||||
<TotalAmount>{{ invoice.total_amount }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice.total_amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TotalExecutableAmount>
|
||||
<InvoiceCurrencyCode>EUR</InvoiceCurrencyCode>
|
||||
</Batch>
|
||||
{# FactoryAssignmentData optional: not supported (factoring not supported) #}
|
||||
</FileHeader>
|
||||
|
||||
<Parties>
|
||||
<SellerParty>
|
||||
<TaxIdentification>
|
||||
<PersonTypeCode>{{ invoice.company.party.facturae_person_type }}</PersonTypeCode>
|
||||
<ResidenceTypeCode>R</ResidenceTypeCode>
|
||||
<TaxIdentificationNumber>{{ invoice.company.party.vat_code[:30] }}</TaxIdentificationNumber>
|
||||
</TaxIdentification>
|
||||
{# Optional. It could be the ID or the code #}
|
||||
<PartyIdentification>{{ invoice.company.party.id_electronet }}</PartyIdentification>
|
||||
<AdministrativeCentres>
|
||||
{% if invoice.company.party.oficina_contable and invoice.company.party.addresses %}{{ administrative_center(invoice.company.party.oficina_contable.rstrip(), '01', invoice.company.party) }}{% endif %}
|
||||
{% if invoice.company.party.organo_gestor and invoice.company.party.addresses %}{{ administrative_center(invoice.company.party.organo_gestor.rstrip(), '02', invoice.company.party) }}{% endif %}
|
||||
{% if invoice.company.party.unidad_tramitadora and invoice.company.party.addresses %}{{ administrative_center(invoice.company.party.unidad_tramitadora.rstrip(), '03', invoice.company.party) }}{% endif %}
|
||||
{% if invoice.company.party.organo_proponente and invoice.company.party.addresses %}{{ administrative_center(invoice.company.party.organo_proponente.replace('\n', '').rstrip(), '04', invoice.company.party) }}{% endif %}
|
||||
</AdministrativeCentres>
|
||||
<LegalEntity>
|
||||
<CorporateName>{{ invoice.company.party.name[:80] }}</CorporateName>
|
||||
{{ address(invoice.company.party.addresses[0]) }}
|
||||
{% if invoice.company.party.contact_mechanisms %}
|
||||
{{ contact(invoice.company.party) }}
|
||||
{% endif %}
|
||||
</LegalEntity>
|
||||
</SellerParty>
|
||||
|
||||
<BuyerParty>
|
||||
<TaxIdentification>
|
||||
<PersonTypeCode>{{ invoice.party.facturae_person_type }}</PersonTypeCode>
|
||||
<ResidenceTypeCode>R</ResidenceTypeCode>
|
||||
<TaxIdentificationNumber>{{ invoice.party.vat_code[:30] }}</TaxIdentificationNumber>
|
||||
</TaxIdentification>
|
||||
{# Optional. It could be the ID or the code #}
|
||||
<PartyIdentification>{{ invoice.party.id_electronet }}</PartyIdentification>
|
||||
<AdministrativeCentres>
|
||||
{% if invoice.party.oficina_contable %}{{ administrative_center(invoice.party.oficina_contable, '01', invoice.party) }}{% endif %}
|
||||
{% if invoice.party.organo_gestor %}{{ administrative_center(invoice.party.organo_gestor, '02', invoice.party) }}{% endif %}
|
||||
{% if invoice.party.unidad_tramitadora %}{{ administrative_center(invoice.party.unidad_tramitadora, '03', invoice.party) }}{% endif %}
|
||||
{% if invoice.party.organo_proponente %}{{ administrative_center(invoice.party.organo_proponente, '04', invoice.party) }}{% endif %}
|
||||
</AdministrativeCentres>
|
||||
<LegalEntity>
|
||||
<CorporateName>{{ invoice.party.name and invoice.party.name[:80] or invoice.party.code[:80] }}</CorporateName>
|
||||
{% if invoice.party.trade_name %}
|
||||
<TradeName>{{ invoice.party.trade_name[:40] }}</TradeName>
|
||||
{% endif %}
|
||||
{# RegistrationData optional: not supported #}
|
||||
{{ address(invoice.invoice_address) }}
|
||||
{% if invoice.party.contact_mechanisms %}
|
||||
{{ contact(invoice.party) }}
|
||||
{% endif %}
|
||||
</LegalEntity>
|
||||
</BuyerParty>
|
||||
</Parties>
|
||||
|
||||
<Invoices>
|
||||
<Invoice>
|
||||
<InvoiceHeader>
|
||||
<InvoiceNumber>{{ invoice.number[:20] }}</InvoiceNumber>
|
||||
{# InvoiceSeriesCode optional: not supported #}
|
||||
{# TODO: FA (Factura Simplificada) not supported #}
|
||||
<InvoiceDocumentType>FC</InvoiceDocumentType>
|
||||
{# TODO: Types not supported:
|
||||
- OC (O. Recapitulativa)
|
||||
- CO (Duplicado Original)
|
||||
- CR, (D. Rectificativa)
|
||||
- CC (D. Recapitulativa)
|
||||
#}
|
||||
<InvoiceClass>{{ 'OO' if not invoice.credited_invoices else 'OR' }}</InvoiceClass>
|
||||
{% if invoice.credited_invoices %}
|
||||
<Corrective>
|
||||
<InvoiceNumber>{{ invoice.credited_invoices and invoice.credited_invoices[0].number[:20] }}</InvoiceNumber>
|
||||
{# InvoiceSeriesCode Optional: not supported #}
|
||||
<ReasonCode>{{ invoice.rectificative_reason_code }}</ReasonCode>
|
||||
<ReasonDescription>{{ invoice.rectificative_reason_spanish_description }}</ReasonDescription>
|
||||
{# TODO: Methods not supported:
|
||||
- 02 (solo se
|
||||
anotan los detalles ya rectificados)
|
||||
- 03 (Rectificación por
|
||||
descuento por volumen de operaciones durante un periodo)
|
||||
- 04 (Autorizadas por la Agencia Tributaria)
|
||||
#}
|
||||
<CorrectionMethod>01</CorrectionMethod>
|
||||
<CorrectionMethodDescription>Rectificación Íntegra</CorrectionMethodDescription>
|
||||
{# AdditionalReasonDescription optional: not supported #}
|
||||
</Corrective>
|
||||
{% endif %}
|
||||
</InvoiceHeader>
|
||||
<InvoiceIssueData>
|
||||
<IssueDate>{{ invoice.invoice_date.isoformat() }}</IssueDate>
|
||||
{# OperationDate required only if is different to IssueDate, but we consider OperatinDate==invoice_date: not supported #}
|
||||
{# PlaceOfIssue optional: not supported #}
|
||||
{# InvoicingPeriod required only for Recapitulativas or temporary service: not supported #}
|
||||
<InvoiceCurrencyCode>EUR</InvoiceCurrencyCode>
|
||||
<TaxCurrencyCode>EUR</TaxCurrencyCode>
|
||||
<LanguageName>es</LanguageName>
|
||||
</InvoiceIssueData>
|
||||
<TaxesOutputs>
|
||||
{% for invoice_tax in invoice.taxes_outputs %}
|
||||
<Tax>
|
||||
<TaxTypeCode>{{ invoice_tax.tax.report_type }}</TaxTypeCode>
|
||||
<TaxRate>{{ invoice_tax.tax.rate * 100 }}</TaxRate>
|
||||
<TaxableBase>
|
||||
<TotalAmount>{{ invoice_tax.base }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.base, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxableBase>
|
||||
<TaxAmount>
|
||||
<TotalAmount>{{ invoice_tax.amount }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxAmount>
|
||||
{# TODO: special taxes not supported
|
||||
- SpecialTaxableBase
|
||||
- SpecialTaxAmount
|
||||
#}
|
||||
{% if invoice_tax.tax.recargo_equivalencia %}
|
||||
{# TODO: EquivalenceSurchace must to have its own Tax entry or it must to go to the IVA line? TaxRate == EquivalenceSurcharge and TaxAmount == EquivalenceSurchargeAmount? #}
|
||||
<EquivalenceSurcharge>{{ (invoice_tax.tax.rate * 100).quantize(Decimal('0.01')) }}</EquivalenceSurcharge>
|
||||
<EquivalenceSurchargeAmount>
|
||||
<TotalAmount>{{ invoice_tax.amount }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</EquivalenceSurchargeAmount>
|
||||
{% endif %}
|
||||
</Tax>
|
||||
{% endfor %}
|
||||
</TaxesOutputs>
|
||||
{% if invoice.taxes_withheld %}
|
||||
<TaxesWithheld>
|
||||
{% for invoice_tax in invoice.taxes_withheld %}
|
||||
<Tax>
|
||||
<TaxTypeCode>{{ invoice_tax.tax.report_type }}</TaxTypeCode>
|
||||
<TaxRate>{{ invoice_tax.tax.rate * 100 }}</TaxRate>
|
||||
<TaxableBase>
|
||||
<TotalAmount>{{ invoice_tax.base }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.base, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxableBase>
|
||||
<TaxAmount>
|
||||
<TotalAmount>{{ invoice_tax.amount }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, invoice_tax.amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxAmount>
|
||||
</Tax>
|
||||
{% endfor %}
|
||||
</TaxesWithheld>
|
||||
{% endif %}
|
||||
<InvoiceTotals>
|
||||
<TotalGrossAmount>{{ invoice.untaxed_amount }}</TotalGrossAmount>
|
||||
{# TODO: GeneralDiscounts and TotalGeneralDiscounts (account_invoice_discount_global) not supported #}
|
||||
{# TODO: GeneralSurcharges and TotalGeneralSurcharges not supported #}
|
||||
<TotalGrossAmountBeforeTaxes>{{ invoice.untaxed_amount }}</TotalGrossAmountBeforeTaxes>
|
||||
<TotalTaxOutputs>{{ invoice.taxes_outputs | sum(attribute='amount', start=Decimal('0.00')) }}</TotalTaxOutputs>
|
||||
<TotalTaxesWithheld>{{ invoice.taxes_withheld | sum(attribute='amount', start=Decimal('0.00')) }}</TotalTaxesWithheld>
|
||||
<InvoiceTotal>{{ invoice.total_amount }}</InvoiceTotal>
|
||||
{# TODO: optional, not supported
|
||||
- Subsidies
|
||||
- PaymentsOnAccount, TotalPaymentsOnAccount
|
||||
- ReimbursableExpenses, TotalReimbursableExpenses (suplidos?)
|
||||
- TotalFinancialExpenses (account_payment_type_cost?)
|
||||
- AmountsWithheld
|
||||
#}
|
||||
<TotalOutstandingAmount>{{ invoice.total_amount }}</TotalOutstandingAmount>
|
||||
<TotalExecutableAmount>{{ invoice.total_amount }}</TotalExecutableAmount>
|
||||
</InvoiceTotals>
|
||||
<Items>
|
||||
{% for line in invoice.lines if line.type == 'line' %}
|
||||
<InvoiceLine>
|
||||
{# TODO: optional, not supported
|
||||
- Issuer/ReceiverContractReference, Issuer/ReceiverContractDate (contract)
|
||||
- Issuer/ReceiverTransactionReference, Issuer/ReceiverTransactionDate (sale, contract...)
|
||||
- FileReference, FileDate
|
||||
- SequenceNumber
|
||||
- DeliveryNotesReferences (account_invoice_stock)
|
||||
- LineItemPeriod
|
||||
- TransactionDate
|
||||
- Extensions
|
||||
#}
|
||||
<ItemDescription>{{ line.description and line.description[:2500] or '' }}</ItemDescription>
|
||||
<Quantity>{{ line.quantity }}</Quantity>
|
||||
<UnitOfMeasure>{{ UOM_CODE2TYPE.get(line.unit.symbol, '05') if line.unit else '05' }}</UnitOfMeasure>
|
||||
<UnitPriceWithoutTax>{{ '%0.6f'|format(line.unit_price) }}</UnitPriceWithoutTax>
|
||||
<TotalCost>{{ '%0.6f'|format(line.amount) }}</TotalCost>
|
||||
{# TODO: optional, not supported
|
||||
- DiscountsAndRebates (account_invoice_discount)
|
||||
- Charges
|
||||
#}
|
||||
<GrossAmount>{{ '%0.6f'|format(line.amount) }}</GrossAmount>
|
||||
{% if line.taxes_withheld %}
|
||||
<TaxesWithheld>
|
||||
{% for line_tax in invoice.taxes_withheld %}
|
||||
<Tax>
|
||||
<TaxTypeCode>{{ line_tax.tax.report_type }}</TaxTypeCode>
|
||||
<TaxRate>{{ line_tax.tax.rate * 100 }}</TaxRate>
|
||||
<TaxableBase>
|
||||
<TotalAmount>{{ '%0.2f'|format(line.amount) }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, line.amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxableBase>
|
||||
<TaxAmount>
|
||||
<TotalAmount>{{ '%0.2f'|format(line.amount * line_tax.tax.rate) }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, line.amount * line_tax.tax.rate, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxAmount>
|
||||
</Tax>
|
||||
{% endfor %}
|
||||
</TaxesWithheld>
|
||||
{% endif %}
|
||||
<TaxesOutputs>
|
||||
{% for line_tax in line.taxes_outputs %}
|
||||
<Tax>
|
||||
<TaxTypeCode>{{ line_tax.tax.report_type }}</TaxTypeCode>
|
||||
<TaxRate>{{ line_tax.tax.rate * 100 }}</TaxRate>
|
||||
<TaxableBase>
|
||||
<TotalAmount>{{ '%0.2f'|format(line.amount) }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, line.amount, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxableBase>
|
||||
<TaxAmount>
|
||||
<TotalAmount>{{ '%0.2f'|format(line.amount * line_tax.tax.rate) }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, line.amount * line_tax.tax.rate, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</TaxAmount>
|
||||
{# TODO: special taxes not supported
|
||||
- SpecialTaxableBase
|
||||
- SpecialTaxAmount
|
||||
#}
|
||||
{% if line_tax.tax.recargo_equivalencia %}
|
||||
{# TODO: EquivalenceSurchace must to have its own Tax entry or it must to go to the IVA line? TaxRate == EquivalenceSurcharge and TaxAmount == EquivalenceSurchargeAmount? #}
|
||||
<EquivalenceSurcharge>{{ (line_tax.tax.rate * 100).quantize(Decimal('0.01')) }}</EquivalenceSurcharge>
|
||||
<EquivalenceSurchargeAmount>
|
||||
<TotalAmount>{{ '%0.2f'|format(line.amount * line_tax.tax.rate) }}</TotalAmount>
|
||||
{% if invoice.currency != euro %}
|
||||
<EquivalentInEuros>{{ Currency.compute(invoice.currency, line.amount * line_tax.tax.rate, euro) }}</EquivalentInEuros>
|
||||
{% endif %}
|
||||
</EquivalenceSurchargeAmount>
|
||||
{% endif %}
|
||||
</Tax>
|
||||
{% endfor %}
|
||||
</TaxesOutputs>
|
||||
{% if line.taxes_additional_line_item_information %}
|
||||
<AdditionalLineItemInformation>
|
||||
{% for key, description in line.taxes_additional_line_item_information.items() %}
|
||||
{{ key }} = {{ description }}
|
||||
{% endfor %}
|
||||
</AdditionalLineItemInformation>
|
||||
{% endif %}
|
||||
{# TODO: SpecialTaxableEvent not supported #}
|
||||
{% if line.product and line.product.code %}
|
||||
<ArticleCode>{{ line.product.code }}</ArticleCode>
|
||||
{% endif %}
|
||||
</InvoiceLine>
|
||||
{% endfor %}
|
||||
</Items>
|
||||
{% if invoice.payment_details %}
|
||||
<PaymentDetails>
|
||||
{% for move_line in invoice.payment_details %}
|
||||
<Installment>
|
||||
<InstallmentDueDate>{{ move_line.maturity_date.isoformat() }}</InstallmentDueDate>
|
||||
<InstallmentAmount>{{ ((move_line.debit - move_line.credit) | abs).quantize(Decimal('0.01')) }}</InstallmentAmount>
|
||||
<PaymentMeans>{{ move_line.payment_type.facturae_type }}</PaymentMeans>
|
||||
{% if move_line.payment_type.facturae_type == '04' %}
|
||||
<AccountToBeCredited>
|
||||
<IBAN>{% for number in (move_line.bank_account.numbers|selectattr('type', 'equalto', 'iban')) %}{% if loop.first %}{{ number.number_compact }}{% endif %}{% endfor %}</IBAN>
|
||||
{# Unnecessary if IBAN is supplied: AccountNumber, BankCode, BranchCode, BranchInSpainAddress, OverseasBranchAddress, BIC #}
|
||||
</AccountToBeCredited>
|
||||
{% elif move_line.payment_type.facturae_type == '02' %}
|
||||
<AccountToBeDebited>
|
||||
<IBAN>{% for number in (move_line.bank_account.numbers|selectattr('type', 'equalto', 'iban')) %}{% if loop.first %}{{ number.number_compact }}{% endif %}{% endfor %}</IBAN>
|
||||
{# Unnecessary if IBAN is supplied: AccountNumber, BankCode, BranchCode, BranchInSpainAddress, OverseasBranchAddress, BIC #}
|
||||
</AccountToBeDebited>
|
||||
{# optional, not supported:
|
||||
- PaymentReconciliationReference
|
||||
- CollectionAdditionalInformation
|
||||
- RegulatoryReportingData (for international operations)
|
||||
- DebitReconciliationReference
|
||||
#}
|
||||
{% endif %}
|
||||
</Installment>
|
||||
{% endfor %}
|
||||
</PaymentDetails>
|
||||
{% endif %}
|
||||
<LegalLiterals>
|
||||
{% for inv_tax in invoice.taxes %}
|
||||
{% if inv_tax.tax and inv_tax.tax.report_description %}
|
||||
<LegalReference>{{ inv_tax.tax.report_description[:250] }}</LegalReference>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</LegalLiterals>
|
||||
</Invoice>
|
||||
</Invoices>
|
||||
{# Extensions optional, not supported #}
|
||||
</namespace:Facturae>
|
|
@ -0,0 +1,36 @@
|
|||
{% macro administrative_center(centre_code, role_type_code, party) %}
|
||||
<AdministrativeCentre>
|
||||
<CentreCode>{{ centre_code }}</CentreCode>
|
||||
<RoleTypeCode>{{ role_type_code }}</RoleTypeCode>
|
||||
{{ address(party.addresses[0]) }}
|
||||
{{ contact(party) }}
|
||||
<LogicalOperationalPoint/>
|
||||
</AdministrativeCentre>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro address(address) %}
|
||||
<AddressInSpain>
|
||||
<Address>{{ address.street[:80] }}</Address>
|
||||
<PostCode>{{ address.zip[:5] }}</PostCode>
|
||||
<Town>{{ address.city[:50] }}</Town>
|
||||
<Province>{{ address.subdivision.name[:20] }}</Province>
|
||||
<CountryCode>{{ address.country.code3 }}</CountryCode>
|
||||
</AddressInSpain>
|
||||
{% endmacro %}
|
||||
|
||||
{% macro contact(party) %}
|
||||
<ContactDetails>
|
||||
{% if party.phone or party.mobile %}
|
||||
<Telephone>{{ (party.phone or party.mobile)[:15] }}</Telephone>
|
||||
{% endif %}
|
||||
{% if party.fax %}
|
||||
<TeleFax>{{ party.fax[:15] }}</TeleFax>
|
||||
{% endif %}
|
||||
{% if party.email %}
|
||||
<ElectronicMail>{{ party.email[:60] }}</ElectronicMail>
|
||||
{% endif %}
|
||||
{% if party.addresses[0].name %}
|
||||
<ContactPersons>if party.addresses[0].name</ContactPersons>
|
||||
{% endif %}
|
||||
</ContactDetails>
|
||||
{% endmacro %}
|
|
@ -2,17 +2,215 @@
|
|||
# The COPYRIGHT file at the top level of this repository contains
|
||||
# the full copyright notices and license terms.
|
||||
import unittest
|
||||
import doctest
|
||||
from trytond.tests.test_tryton import ModuleTestCase
|
||||
import os.path
|
||||
from decimal import Decimal
|
||||
from trytond.pool import Pool
|
||||
from trytond.transaction import Transaction
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
from trytond.tests.test_tryton import suite as test_suite
|
||||
from trytond.tests.test_tryton import doctest_teardown
|
||||
from trytond.tests.test_tryton import doctest_checker
|
||||
from trytond.modules.account.tests import get_fiscalyear, create_chart
|
||||
from trytond.modules.company.tests import create_company, set_company
|
||||
from trytond.modules.account_invoice.tests import set_invoice_sequences
|
||||
from trytond.modules.currency.tests import create_currency, add_currency_rate
|
||||
CURRENT_PATH = os.path.dirname(os.path.abspath(__file__))
|
||||
|
||||
|
||||
class AccountInvoiceFacturaeElectronetTestCase(ModuleTestCase):
|
||||
'Test Account Invoice Facturae Electronet module'
|
||||
module = 'account_invoice_facturae_electronet'
|
||||
|
||||
@with_transaction()
|
||||
def test_invoice_generation(self):
|
||||
'Test invoice generation'
|
||||
pool = Pool()
|
||||
Account = pool.get('account.account')
|
||||
FiscalYear = pool.get('account.fiscalyear')
|
||||
Invoice = pool.get('account.invoice')
|
||||
InvoiceLine = pool.get('account.invoice.line')
|
||||
Party = pool.get('party.party')
|
||||
PaymentTerm = pool.get('account.invoice.payment_term')
|
||||
ProductUom = pool.get('product.uom')
|
||||
ProductTemplate = pool.get('product.template')
|
||||
Product = pool.get('product.product')
|
||||
Tax = pool.get('account.tax')
|
||||
Address = pool.get('party.address')
|
||||
PartyIdentifier = pool.get('party.identifier')
|
||||
Country = pool.get('country.country')
|
||||
Subdivision = pool.get('country.subdivision')
|
||||
PaymentType = pool.get('account.payment.type')
|
||||
|
||||
country = Country(name='Country', code='ES', code3='ESP')
|
||||
country.save()
|
||||
subdivision = Subdivision(name='Subdivision', country=country,
|
||||
code='SUB', type='area')
|
||||
subdivision.save()
|
||||
|
||||
company = create_company()
|
||||
currency = create_currency('EUR')
|
||||
add_currency_rate(currency, Decimal(1.0))
|
||||
|
||||
tax_identifier = PartyIdentifier()
|
||||
tax_identifier.type = 'eu_vat'
|
||||
tax_identifier.code = 'BE0897290877'
|
||||
company.header = 'Report Header'
|
||||
company.party.name = 'Seller'
|
||||
company.party.identifiers = [tax_identifier]
|
||||
company.party.facturae_person_type = 'J'
|
||||
company.party.facturae_residence_type = 'R'
|
||||
company.party.organo_proponente = 'Test Organo Proponente'
|
||||
company.party.id_electronet = '100_SELLER'
|
||||
company.party.save()
|
||||
company.save()
|
||||
|
||||
payment_term, = PaymentTerm.create([{
|
||||
'name': '20 days, 40 days',
|
||||
'lines': [
|
||||
('create', [{
|
||||
'sequence': 0,
|
||||
'type': 'percent',
|
||||
'divisor': 2,
|
||||
'ratio': Decimal('.5'),
|
||||
'relativedeltas': [('create', [{
|
||||
'days': 20,
|
||||
},
|
||||
]),
|
||||
],
|
||||
}, {
|
||||
'sequence': 1,
|
||||
'type': 'remainder',
|
||||
'relativedeltas': [('create', [{
|
||||
'days': 40,
|
||||
},
|
||||
]),
|
||||
],
|
||||
}])]
|
||||
}])
|
||||
|
||||
with set_company(company):
|
||||
fiscalyear = set_invoice_sequences(get_fiscalyear(company))
|
||||
fiscalyear.save()
|
||||
FiscalYear.create_period([fiscalyear])
|
||||
create_chart(company, tax=True)
|
||||
|
||||
with Transaction().set_user(0), \
|
||||
Transaction().set_context(company=company.id, user=0,
|
||||
_check_access=False):
|
||||
|
||||
payment_receivable, = PaymentType.create([{
|
||||
'name': 'Payment Receivable',
|
||||
'kind': 'receivable',
|
||||
'company': company.id,
|
||||
'facturae_type': '01',
|
||||
}])
|
||||
revenue, = Account.search([('kind', '=', 'revenue')])
|
||||
expense, = Account.search([('kind', '=', 'expense')])
|
||||
tax_account, = Account.search([
|
||||
('name', '=', 'Main Tax'),
|
||||
])
|
||||
vat21 = Tax()
|
||||
vat21.name = vat21.description = '21% VAT'
|
||||
vat21.type = 'percentage'
|
||||
vat21.rate = Decimal('0.21')
|
||||
vat21.invoice_account = tax_account
|
||||
vat21.report_type = '05'
|
||||
vat21.credit_note_account = tax_account
|
||||
|
||||
vat21.save()
|
||||
|
||||
company_address, = company.party.addresses
|
||||
company_address.street = 'street'
|
||||
company_address.zip = '08201'
|
||||
company_address.city = 'City'
|
||||
company_address.subdivision = subdivision
|
||||
company_address.country = country
|
||||
company_address.save()
|
||||
party = Party(name='Buyer')
|
||||
party.facturae_person_type = 'J'
|
||||
party.facturae_residence_type = 'R'
|
||||
party.id_electronet = '100_BUYER'
|
||||
party.organo_proponente = 'Test Organo Proponente'
|
||||
tax_identifier = PartyIdentifier()
|
||||
tax_identifier.type = 'eu_vat'
|
||||
tax_identifier.code = 'BE0897290877'
|
||||
party.identifiers = [tax_identifier]
|
||||
party.save()
|
||||
|
||||
address_dict = {
|
||||
'party': party.id,
|
||||
'street': 'St sample, 15',
|
||||
'city': 'City',
|
||||
'zip': '08201',
|
||||
'subdivision': subdivision.id,
|
||||
'country': country.id,
|
||||
}
|
||||
|
||||
address, = Address.create([address_dict])
|
||||
|
||||
term, = PaymentTerm.create([{
|
||||
'name': 'Payment term',
|
||||
'lines': [
|
||||
('create', [{
|
||||
'type': 'remainder',
|
||||
'relativedeltas': [
|
||||
('create', [{
|
||||
'sequence': 0,
|
||||
'days': 0,
|
||||
'months': 0,
|
||||
'weeks': 0,
|
||||
}])],
|
||||
}])],
|
||||
}])
|
||||
|
||||
unit, = ProductUom.search([('name', '=', 'Unit')])
|
||||
template = ProductTemplate()
|
||||
template.name = 'product'
|
||||
template.default_uom = unit
|
||||
template.type = 'service'
|
||||
template.list_price = Decimal('40')
|
||||
template.cost_price = Decimal('25')
|
||||
template.account_expense = expense
|
||||
template.account_revenue = revenue
|
||||
template.customer_taxes = [vat21]
|
||||
template.save()
|
||||
product = Product()
|
||||
product.template = template
|
||||
product.save()
|
||||
|
||||
invoice = Invoice()
|
||||
invoice.type = 'out'
|
||||
invoice.on_change_type()
|
||||
invoice.party = party
|
||||
invoice.on_change_party()
|
||||
invoice.payment_type = payment_receivable
|
||||
invoice.payment_term = term
|
||||
invoice.currency = currency
|
||||
invoice.company = company
|
||||
|
||||
line1 = InvoiceLine()
|
||||
line1.account = revenue
|
||||
line1.product = product
|
||||
line1.on_change_product()
|
||||
line1.on_change_account()
|
||||
line1.description = 'TestLine2'
|
||||
line1.quantity = 5
|
||||
line1.unit_price = Decimal('40')
|
||||
|
||||
line2 = InvoiceLine()
|
||||
line2.account = revenue
|
||||
line2.product = product
|
||||
line2.on_change_product()
|
||||
line2.on_change_account()
|
||||
line2.description = 'TestLine2'
|
||||
line2.quantity = 1
|
||||
line2.unit_price = Decimal(20)
|
||||
|
||||
invoice.lines = [line1, line2]
|
||||
invoice.on_change_lines()
|
||||
invoice.save()
|
||||
|
||||
Invoice.post([invoice])
|
||||
Invoice.generate_facturae_electronet([invoice])
|
||||
|
||||
|
||||
def suite():
|
||||
suite = test_suite()
|
||||
|
|
|
@ -4,3 +4,4 @@ depends:
|
|||
ir
|
||||
account_invoice_facturae
|
||||
xml:
|
||||
party.xml
|
|
@ -0,0 +1,9 @@
|
|||
<?xml version="1.0"?>
|
||||
<!-- The COPYRIGHT file at the top level of this repository contains the full
|
||||
copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="/form/notebook/page[@id='facturae']" position="inside">
|
||||
<label name="id_electronet"/>
|
||||
<field name="id_electronet"/>
|
||||
</xpath>
|
||||
</data>
|
|
@ -0,0 +1,318 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!DOCTYPE schema
|
||||
PUBLIC "-//W3C//DTD XMLSchema 200102//EN" "http://www.w3.org/2001/XMLSchema.dtd"
|
||||
[
|
||||
<!ATTLIST schema
|
||||
xmlns:ds CDATA #FIXED "http://www.w3.org/2000/09/xmldsig#">
|
||||
<!ENTITY dsig 'http://www.w3.org/2000/09/xmldsig#'>
|
||||
<!ENTITY % p ''>
|
||||
<!ENTITY % s ''>
|
||||
]>
|
||||
|
||||
<!-- Schema for XML Signatures
|
||||
http://www.w3.org/2000/09/xmldsig#
|
||||
$Revision: 1.1 $ on $Date: 2002/02/08 20:32:26 $ by $Author: reagle $
|
||||
|
||||
Copyright 2001 The Internet Society and W3C (Massachusetts Institute
|
||||
of Technology, Institut National de Recherche en Informatique et en
|
||||
Automatique, Keio University). All Rights Reserved.
|
||||
http://www.w3.org/Consortium/Legal/
|
||||
|
||||
This document is governed by the W3C Software License [1] as described
|
||||
in the FAQ [2].
|
||||
|
||||
[1] http://www.w3.org/Consortium/Legal/copyright-software-19980720
|
||||
[2] http://www.w3.org/Consortium/Legal/IPR-FAQ-20000620.html#DTD
|
||||
-->
|
||||
|
||||
|
||||
<schema xmlns="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
|
||||
targetNamespace="http://www.w3.org/2000/09/xmldsig#"
|
||||
version="0.1" elementFormDefault="qualified">
|
||||
|
||||
<!-- Basic Types Defined for Signatures -->
|
||||
|
||||
<simpleType name="CryptoBinary">
|
||||
<restriction base="base64Binary">
|
||||
</restriction>
|
||||
</simpleType>
|
||||
|
||||
<!-- Start Signature -->
|
||||
|
||||
<element name="Signature" type="ds:SignatureType"/>
|
||||
<complexType name="SignatureType">
|
||||
<sequence>
|
||||
<element ref="ds:SignedInfo"/>
|
||||
<element ref="ds:SignatureValue"/>
|
||||
<element ref="ds:KeyInfo" minOccurs="0"/>
|
||||
<element ref="ds:Object" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="SignatureValue" type="ds:SignatureValueType"/>
|
||||
<complexType name="SignatureValueType">
|
||||
<simpleContent>
|
||||
<extension base="base64Binary">
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</extension>
|
||||
</simpleContent>
|
||||
</complexType>
|
||||
|
||||
<!-- Start SignedInfo -->
|
||||
|
||||
<element name="SignedInfo" type="ds:SignedInfoType"/>
|
||||
<complexType name="SignedInfoType">
|
||||
<sequence>
|
||||
<element ref="ds:CanonicalizationMethod"/>
|
||||
<element ref="ds:SignatureMethod"/>
|
||||
<element ref="ds:Reference" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="CanonicalizationMethod" type="ds:CanonicalizationMethodType"/>
|
||||
<complexType name="CanonicalizationMethodType" mixed="true">
|
||||
<sequence>
|
||||
<any namespace="##any" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!-- (0,unbounded) elements from (1,1) namespace -->
|
||||
</sequence>
|
||||
<attribute name="Algorithm" type="anyURI" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<element name="SignatureMethod" type="ds:SignatureMethodType"/>
|
||||
<complexType name="SignatureMethodType" mixed="true">
|
||||
<sequence>
|
||||
<element name="HMACOutputLength" minOccurs="0" type="ds:HMACOutputLengthType"/>
|
||||
<any namespace="##other" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<!-- (0,unbounded) elements from (1,1) external namespace -->
|
||||
</sequence>
|
||||
<attribute name="Algorithm" type="anyURI" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<!-- Start Reference -->
|
||||
|
||||
<element name="Reference" type="ds:ReferenceType"/>
|
||||
<complexType name="ReferenceType">
|
||||
<sequence>
|
||||
<element ref="ds:Transforms" minOccurs="0"/>
|
||||
<element ref="ds:DigestMethod"/>
|
||||
<element ref="ds:DigestValue"/>
|
||||
</sequence>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
<attribute name="URI" type="anyURI" use="optional"/>
|
||||
<attribute name="Type" type="anyURI" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="Transforms" type="ds:TransformsType"/>
|
||||
<complexType name="TransformsType">
|
||||
<sequence>
|
||||
<element ref="ds:Transform" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<element name="Transform" type="ds:TransformType"/>
|
||||
<complexType name="TransformType" mixed="true">
|
||||
<choice minOccurs="0" maxOccurs="unbounded">
|
||||
<any namespace="##other" processContents="lax"/>
|
||||
<!-- (1,1) elements from (0,unbounded) namespaces -->
|
||||
<element name="XPath" type="string"/>
|
||||
</choice>
|
||||
<attribute name="Algorithm" type="anyURI" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<!-- End Reference -->
|
||||
|
||||
<element name="DigestMethod" type="ds:DigestMethodType"/>
|
||||
<complexType name="DigestMethodType" mixed="true">
|
||||
<sequence>
|
||||
<any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="Algorithm" type="anyURI" use="required"/>
|
||||
</complexType>
|
||||
|
||||
<element name="DigestValue" type="ds:DigestValueType"/>
|
||||
<simpleType name="DigestValueType">
|
||||
<restriction base="base64Binary"/>
|
||||
</simpleType>
|
||||
|
||||
<!-- End SignedInfo -->
|
||||
|
||||
<!-- Start KeyInfo -->
|
||||
|
||||
<element name="KeyInfo" type="ds:KeyInfoType"/>
|
||||
<complexType name="KeyInfoType" mixed="true">
|
||||
<choice maxOccurs="unbounded">
|
||||
<element ref="ds:KeyName"/>
|
||||
<element ref="ds:KeyValue"/>
|
||||
<element ref="ds:RetrievalMethod"/>
|
||||
<element ref="ds:X509Data"/>
|
||||
<element ref="ds:PGPData"/>
|
||||
<element ref="ds:SPKIData"/>
|
||||
<element ref="ds:MgmtData"/>
|
||||
<any processContents="lax" namespace="##other"/>
|
||||
<!-- (1,1) elements from (0,unbounded) namespaces -->
|
||||
</choice>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="KeyName" type="string"/>
|
||||
<element name="MgmtData" type="string"/>
|
||||
|
||||
<element name="KeyValue" type="ds:KeyValueType"/>
|
||||
<complexType name="KeyValueType" mixed="true">
|
||||
<choice>
|
||||
<element ref="ds:DSAKeyValue"/>
|
||||
<element ref="ds:RSAKeyValue"/>
|
||||
<any namespace="##other" processContents="lax"/>
|
||||
</choice>
|
||||
</complexType>
|
||||
|
||||
<element name="RetrievalMethod" type="ds:RetrievalMethodType"/>
|
||||
<complexType name="RetrievalMethodType">
|
||||
<sequence>
|
||||
<element ref="ds:Transforms" minOccurs="0"/>
|
||||
</sequence>
|
||||
<attribute name="URI" type="anyURI"/>
|
||||
<attribute name="Type" type="anyURI" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<!-- Start X509Data -->
|
||||
|
||||
<element name="X509Data" type="ds:X509DataType"/>
|
||||
<complexType name="X509DataType">
|
||||
<sequence maxOccurs="unbounded">
|
||||
<choice>
|
||||
<element name="X509IssuerSerial" type="ds:X509IssuerSerialType"/>
|
||||
<element name="X509SKI" type="base64Binary"/>
|
||||
<element name="X509SubjectName" type="string"/>
|
||||
<element name="X509Certificate" type="base64Binary"/>
|
||||
<element name="X509CRL" type="base64Binary"/>
|
||||
<any namespace="##other" processContents="lax"/>
|
||||
</choice>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<complexType name="X509IssuerSerialType">
|
||||
<sequence>
|
||||
<element name="X509IssuerName" type="string"/>
|
||||
<element name="X509SerialNumber" type="integer"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- End X509Data -->
|
||||
|
||||
<!-- Begin PGPData -->
|
||||
|
||||
<element name="PGPData" type="ds:PGPDataType"/>
|
||||
<complexType name="PGPDataType">
|
||||
<choice>
|
||||
<sequence>
|
||||
<element name="PGPKeyID" type="base64Binary"/>
|
||||
<element name="PGPKeyPacket" type="base64Binary" minOccurs="0"/>
|
||||
<any namespace="##other" processContents="lax" minOccurs="0"
|
||||
maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<sequence>
|
||||
<element name="PGPKeyPacket" type="base64Binary"/>
|
||||
<any namespace="##other" processContents="lax" minOccurs="0"
|
||||
maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
</choice>
|
||||
</complexType>
|
||||
|
||||
<!-- End PGPData -->
|
||||
|
||||
<!-- Begin SPKIData -->
|
||||
|
||||
<element name="SPKIData" type="ds:SPKIDataType"/>
|
||||
<complexType name="SPKIDataType">
|
||||
<sequence maxOccurs="unbounded">
|
||||
<element name="SPKISexp" type="base64Binary"/>
|
||||
<any namespace="##other" processContents="lax" minOccurs="0"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- End SPKIData -->
|
||||
|
||||
<!-- End KeyInfo -->
|
||||
|
||||
<!-- Start Object (Manifest, SignatureProperty) -->
|
||||
|
||||
<element name="Object" type="ds:ObjectType"/>
|
||||
<complexType name="ObjectType" mixed="true">
|
||||
<sequence minOccurs="0" maxOccurs="unbounded">
|
||||
<any namespace="##any" processContents="lax"/>
|
||||
</sequence>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
<attribute name="MimeType" type="string" use="optional"/> <!-- add a grep facet -->
|
||||
<attribute name="Encoding" type="anyURI" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="Manifest" type="ds:ManifestType"/>
|
||||
<complexType name="ManifestType">
|
||||
<sequence>
|
||||
<element ref="ds:Reference" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="SignatureProperties" type="ds:SignaturePropertiesType"/>
|
||||
<complexType name="SignaturePropertiesType">
|
||||
<sequence>
|
||||
<element ref="ds:SignatureProperty" maxOccurs="unbounded"/>
|
||||
</sequence>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<element name="SignatureProperty" type="ds:SignaturePropertyType"/>
|
||||
<complexType name="SignaturePropertyType" mixed="true">
|
||||
<choice maxOccurs="unbounded">
|
||||
<any namespace="##other" processContents="lax"/>
|
||||
<!-- (1,1) elements from (1,unbounded) namespaces -->
|
||||
</choice>
|
||||
<attribute name="Target" type="anyURI" use="required"/>
|
||||
<attribute name="Id" type="ID" use="optional"/>
|
||||
</complexType>
|
||||
|
||||
<!-- End Object (Manifest, SignatureProperty) -->
|
||||
|
||||
<!-- Start Algorithm Parameters -->
|
||||
|
||||
<simpleType name="HMACOutputLengthType">
|
||||
<restriction base="integer"/>
|
||||
</simpleType>
|
||||
|
||||
<!-- Start KeyValue Element-types -->
|
||||
|
||||
<element name="DSAKeyValue" type="ds:DSAKeyValueType"/>
|
||||
<complexType name="DSAKeyValueType">
|
||||
<sequence>
|
||||
<sequence minOccurs="0">
|
||||
<element name="P" type="ds:CryptoBinary"/>
|
||||
<element name="Q" type="ds:CryptoBinary"/>
|
||||
</sequence>
|
||||
<element name="G" type="ds:CryptoBinary" minOccurs="0"/>
|
||||
<element name="Y" type="ds:CryptoBinary"/>
|
||||
<element name="J" type="ds:CryptoBinary" minOccurs="0"/>
|
||||
<sequence minOccurs="0">
|
||||
<element name="Seed" type="ds:CryptoBinary"/>
|
||||
<element name="PgenCounter" type="ds:CryptoBinary"/>
|
||||
</sequence>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<element name="RSAKeyValue" type="ds:RSAKeyValueType"/>
|
||||
<complexType name="RSAKeyValueType">
|
||||
<sequence>
|
||||
<element name="Modulus" type="ds:CryptoBinary"/>
|
||||
<element name="Exponent" type="ds:CryptoBinary"/>
|
||||
</sequence>
|
||||
</complexType>
|
||||
|
||||
<!-- End KeyValue Element-types -->
|
||||
|
||||
<!-- End Signature -->
|
||||
|
||||
</schema>
|
Loading…
Reference in New Issue