first commit
This commit is contained in:
2
modules/document_incoming_ocr_typless/__init__.py
Normal file
2
modules/document_incoming_ocr_typless/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
338
modules/document_incoming_ocr_typless/document.py
Normal file
338
modules/document_incoming_ocr_typless/document.py
Normal file
@@ -0,0 +1,338 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import base64
|
||||
from decimal import Decimal
|
||||
from functools import wraps
|
||||
|
||||
import requests
|
||||
|
||||
from trytond.i18n import gettext
|
||||
from trytond.model import fields
|
||||
from trytond.pool import Pool, PoolMeta
|
||||
from trytond.pyson import Eval
|
||||
|
||||
from .exceptions import TyplessCredentialWarning, TyplessError
|
||||
|
||||
MIME_TYPES = {
|
||||
'application/pdf',
|
||||
'image/jpeg',
|
||||
'image/png',
|
||||
'image/tiff',
|
||||
}
|
||||
EXTRACT_DATA = 'https://developers.typless.com/api/extract-data'
|
||||
ADD_DOCUMENT_FEEDBACK = (
|
||||
'https://developers.typless.com/api/add-document-feedback')
|
||||
|
||||
|
||||
def typless_api(func):
|
||||
@wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
try:
|
||||
return func(*args, **kwargs)
|
||||
except requests.HTTPError as e:
|
||||
error_message = e.args[0]
|
||||
raise TyplessError(
|
||||
gettext('document_incoming_ocr_typless'
|
||||
'.msg_typless_webserver_error',
|
||||
message=error_message))
|
||||
return wrapper
|
||||
|
||||
|
||||
def get_best_value(fields, name):
|
||||
for field in fields:
|
||||
if field.get('name') == name:
|
||||
break
|
||||
else:
|
||||
return
|
||||
values = field.get('values', [])
|
||||
values = sorted(
|
||||
values, key=lambda v: v.get('confidence_score'), reverse=True)
|
||||
if values:
|
||||
return values[0].get('value')
|
||||
|
||||
|
||||
class IncomingOCRService(metaclass=PoolMeta):
|
||||
__name__ = 'document.incoming.ocr.service'
|
||||
|
||||
_states = {
|
||||
'required': Eval('type') == 'typless',
|
||||
'invisible': Eval('type') != 'typless',
|
||||
}
|
||||
|
||||
typless_api_key = fields.Char(
|
||||
"API Key", states=_states,
|
||||
help="The standard token from Typless settings page.")
|
||||
typless_document_type = fields.Char(
|
||||
"Document Type", states=_states,
|
||||
help="The name of the document type on Typless.")
|
||||
|
||||
@classmethod
|
||||
def __setup__(cls):
|
||||
super().__setup__()
|
||||
cls.type.selection.append(('typless', "Typless"))
|
||||
|
||||
def match_mime_type(self, mime_type):
|
||||
match = super().match_mime_type(mime_type)
|
||||
if self.type == 'typless':
|
||||
match = mime_type in MIME_TYPES
|
||||
return match
|
||||
|
||||
@typless_api
|
||||
def _process_typless(self, document):
|
||||
payload = self._typless_extract_payload(document)
|
||||
headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': self.typless_api_key,
|
||||
}
|
||||
response = requests.post(EXTRACT_DATA, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
return response.json()
|
||||
|
||||
def _typless_extract_payload(self, document):
|
||||
return {
|
||||
'file': base64.b64encode(document.data).decode('utf-8'),
|
||||
'file_name': document.name,
|
||||
'document_type_name': self.typless_document_type,
|
||||
}
|
||||
|
||||
def _get_document_incoming_typless(self, document):
|
||||
document_data = {}
|
||||
if not document.parsed_data:
|
||||
return document_data
|
||||
fields = document.parsed_data.get('extracted_fields', [])
|
||||
document_type = get_best_value(fields, 'document_type')
|
||||
if document_type is not None:
|
||||
document_data['document_type'] = document_type
|
||||
return document_data
|
||||
|
||||
def _get_supplier_invoice_typless(self, document):
|
||||
invoice_data = {}
|
||||
if not document.parsed_data:
|
||||
return invoice_data
|
||||
fields = document.parsed_data.get('extracted_fields', [])
|
||||
for name in [
|
||||
'company_name', 'company_tax_identifier', 'supplier_name',
|
||||
'tax_identifier', 'currency', 'number', 'description',
|
||||
'invoice_date', 'payment_term_date', 'total_amount',
|
||||
'purchase_orders']:
|
||||
value = get_best_value(fields, name)
|
||||
if value is not None:
|
||||
if name == 'total_amount':
|
||||
value = Decimal(value)
|
||||
invoice_data[name] = value
|
||||
invoice_data['lines'] = lines = []
|
||||
for parsed_line in document.parsed_data.get('line_items', []):
|
||||
lines.append(self._get_supplier_invoice_typless_line(
|
||||
parsed_line, invoice_data))
|
||||
invoice_data['taxes'] = taxes = []
|
||||
for parsed_tax in document.parsed_data.get('vat_rates', []):
|
||||
taxes.append(self._get_supplier_invoice_typless_tax(
|
||||
parsed_tax, invoice_data))
|
||||
return invoice_data
|
||||
|
||||
def _get_supplier_invoice_typless_line(self, parsed_line, invoice_data):
|
||||
line = {}
|
||||
if 'purchase_orders' in invoice_data:
|
||||
line['purchase_orders'] = invoice_data['purchase_orders']
|
||||
for name in [
|
||||
'product_name', 'description', 'unit', 'quantity',
|
||||
'unit_price', 'amount', 'purchase_order']:
|
||||
value = get_best_value(parsed_line, name)
|
||||
if value is not None:
|
||||
if name in {'unit_price', 'amount'}:
|
||||
value = Decimal(value)
|
||||
elif name == 'quantity':
|
||||
value = float(value)
|
||||
line[name] = value
|
||||
return line
|
||||
|
||||
def _get_supplier_invoice_typless_tax(sef, parsed_tax, invoice_data):
|
||||
tax = {'type': 'percentage'}
|
||||
percentage = get_best_value(parsed_tax, 'vat_rate_percentage')
|
||||
if percentage is not None:
|
||||
tax['rate'] = Decimal(percentage) / 100
|
||||
net = get_best_value(parsed_tax, 'vat_rate_net')
|
||||
if net is not None:
|
||||
tax['base'] = Decimal(net)
|
||||
return tax
|
||||
|
||||
@typless_api
|
||||
def _send_feedback_typless(self, document):
|
||||
payload = self._typless_feedback_payload(document)
|
||||
headers = {
|
||||
'Accept': 'application/json',
|
||||
'Content-Type': 'application/json',
|
||||
'Authorization': self.typless_api_key,
|
||||
}
|
||||
response = requests.post(
|
||||
ADD_DOCUMENT_FEEDBACK, json=payload, headers=headers)
|
||||
response.raise_for_status()
|
||||
|
||||
def _typless_feedback_payload(self, document):
|
||||
source = document.result
|
||||
fields = document.parsed_data.get('extracted_fields', [])
|
||||
learning_fields = []
|
||||
getter = getattr(self, f'_typless_feedback_payload_{document.type}')
|
||||
for field in fields:
|
||||
name = field['name']
|
||||
value = getter(source, name)
|
||||
if value is None:
|
||||
value = get_best_value(fields, name)
|
||||
learning_fields.append({
|
||||
'name': name,
|
||||
'value': value,
|
||||
})
|
||||
payload = {
|
||||
'document_type_name': self.typless_document_type,
|
||||
'document_object_id': document.parsed_data['object_id'],
|
||||
'learning_fields': learning_fields,
|
||||
}
|
||||
line_items = document.parsed_data.get('line_items')
|
||||
if line_items is not None:
|
||||
lines = []
|
||||
getter = getattr(
|
||||
self, f'_typless_feedback_payload_line_items_{document.type}')
|
||||
for i, line_item in enumerate(line_items):
|
||||
line = []
|
||||
for field in line_item:
|
||||
name = field['name']
|
||||
value = getter(i, name, source)
|
||||
if value is None:
|
||||
value = get_best_value(line_item, name)
|
||||
line.append({
|
||||
'name': name,
|
||||
'value': value,
|
||||
})
|
||||
lines.append(line)
|
||||
payload['line_items'] = lines
|
||||
vat_rates = document.parsed_data.get('vat_rates')
|
||||
if vat_rates is not None:
|
||||
taxes = []
|
||||
getter = getattr(
|
||||
self, f'_typless_feedback_payload_vat_rates_{document.type}')
|
||||
for i, vat_rate in enumerate(vat_rates):
|
||||
percentage = getter(i, 'vat_rate_percentage', source)
|
||||
if percentage is None:
|
||||
percentage = get_best_value(
|
||||
vat_rate, 'vat_rate_percentage')
|
||||
net = getter(i, 'vat_rate_net', source)
|
||||
if net is None:
|
||||
net = get_best_value(vat_rate, 'vat_rate_net')
|
||||
taxes.append([{
|
||||
'name': 'vat_rate_percentage',
|
||||
'value': percentage,
|
||||
}, {
|
||||
'name': 'vat_rate_net',
|
||||
'value': net,
|
||||
}])
|
||||
payload['vat_rates'] = taxes
|
||||
return payload
|
||||
|
||||
def _typless_feedback_payload_document_incoming(self, document, name):
|
||||
if name == 'document_type':
|
||||
return document.type
|
||||
|
||||
def _typless_feedback_payload_line_items_document_incoming(
|
||||
self, index, name, document):
|
||||
pass
|
||||
|
||||
def _typless_feedback_payload_vat_rates_document_incoming(
|
||||
self, index, name, document):
|
||||
pass
|
||||
|
||||
def _typless_feedback_payload_supplier_invoice(self, invoice, name):
|
||||
if name == 'company_name':
|
||||
return invoice.company.party.name
|
||||
elif name == 'company_tax_identifier':
|
||||
if invoice.tax_identifier:
|
||||
return invoice.tax_identifier.code
|
||||
else:
|
||||
return ''
|
||||
elif name == 'supplier_name':
|
||||
return invoice.party.name
|
||||
elif name == 'tax_identifier':
|
||||
if invoice.party_tax_identifier:
|
||||
return invoice.party_tax_identifier.code
|
||||
else:
|
||||
return ''
|
||||
elif name == 'currency':
|
||||
return invoice.currency.code
|
||||
elif name == 'number':
|
||||
return invoice.reference
|
||||
elif name == 'description':
|
||||
return invoice.description
|
||||
elif name == 'invoice_date':
|
||||
return invoice.invoice_date.isoformat()
|
||||
elif name == 'payment_term_date':
|
||||
if invoice.payment_term_date:
|
||||
return invoice.payment_term_date.isoformat()
|
||||
else:
|
||||
return ''
|
||||
elif name == 'untaxed_amount':
|
||||
return str(invoice.untaxed_amount)
|
||||
elif name == 'tax_amount':
|
||||
return str(invoice.tax_amount)
|
||||
elif name == 'total_amount':
|
||||
return str(invoice.total_amount)
|
||||
elif name == 'purchase_orders':
|
||||
return invoice.origins
|
||||
|
||||
def _typless_feedback_payload_line_items_supplier_invoice(
|
||||
self, index, name, invoice):
|
||||
lines = [l for l in invoice.lines if l.type == 'line']
|
||||
try:
|
||||
line = lines[index]
|
||||
except IndexError:
|
||||
return ''
|
||||
if name == 'product_name':
|
||||
if line.product:
|
||||
return line.product.name
|
||||
else:
|
||||
return ''
|
||||
elif name == 'description':
|
||||
return line.description
|
||||
elif name == 'unit':
|
||||
if line.unit:
|
||||
return line.unit.name
|
||||
else:
|
||||
return ''
|
||||
elif name == 'quantity':
|
||||
return str(line.quantity)
|
||||
elif name == 'unit_price':
|
||||
return str(line.unit_price)
|
||||
elif name == 'amount':
|
||||
return str(line.amount)
|
||||
elif name == 'purchase_order':
|
||||
return line.origin_name
|
||||
|
||||
def _typless_feedback_payload_vat_rates_supplier_invoice(
|
||||
self, index, name, invoice):
|
||||
try:
|
||||
line = invoice.taxes[index]
|
||||
except IndexError:
|
||||
return ''
|
||||
if name == 'vat_rate_percentage':
|
||||
if line.tax and line.tax.type == 'percentage':
|
||||
return str(line.tax.rate * 100)
|
||||
else:
|
||||
return ''
|
||||
elif name == 'vat_rate_net':
|
||||
return str(line.base)
|
||||
|
||||
@classmethod
|
||||
def check_modification(cls, mode, services, values=None, external=False):
|
||||
pool = Pool()
|
||||
Warning = pool.get('res.user.warning')
|
||||
|
||||
super().check_modification(
|
||||
mode, services, values=values, external=external)
|
||||
|
||||
if mode == 'write' and external and 'typless_api_key' in values:
|
||||
warning_name = Warning.format('typless_credential', services)
|
||||
if Warning.check(warning_name):
|
||||
raise TyplessCredentialWarning(
|
||||
warning_name,
|
||||
gettext('document_incoming_ocr_typless'
|
||||
'.msg_typless_credential_modified'))
|
||||
12
modules/document_incoming_ocr_typless/document.xml
Normal file
12
modules/document_incoming_ocr_typless/document.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. 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="document_incoming_ocr_service_view_form">
|
||||
<field name="model">document.incoming.ocr.service</field>
|
||||
<field name="inherit" ref="document_incoming_ocr.document_incoming_ocr_service_view_form"/>
|
||||
<field name="name">document_incoming_ocr_service_form</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
12
modules/document_incoming_ocr_typless/exceptions.py
Normal file
12
modules/document_incoming_ocr_typless/exceptions.py
Normal file
@@ -0,0 +1,12 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.exceptions import UserError, UserWarning
|
||||
|
||||
|
||||
class TyplessError(UserError):
|
||||
pass
|
||||
|
||||
|
||||
class TyplessCredentialWarning(UserWarning):
|
||||
pass
|
||||
34
modules/document_incoming_ocr_typless/locale/bg.po
Normal file
34
modules/document_incoming_ocr_typless/locale/bg.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
36
modules/document_incoming_ocr_typless/locale/ca.po
Normal file
36
modules/document_incoming_ocr_typless/locale/ca.po
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "Clau API"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Tipus de document"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr "El token estàndard de la pàgina de configuració de Typless."
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr "El nom del tipus de document al Typless."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr "Estàs segur que vols modificar les credencials Typless?"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
"La crida al webservice Typless ha fallat amb el següent missatge: \n"
|
||||
"%(message)s"
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typless"
|
||||
34
modules/document_incoming_ocr_typless/locale/cs.po
Normal file
34
modules/document_incoming_ocr_typless/locale/cs.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
36
modules/document_incoming_ocr_typless/locale/de.po
Normal file
36
modules/document_incoming_ocr_typless/locale/de.po
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "API-Key"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Dokumententyp"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr "Das Standard-Token von der Typeless Einstellungsseite."
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr "Der Name des Dokumententyps bei Typless."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr "Wollen Sie wirklich die Typeless Anmeldedaten ändern?"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
"Der Aufruf des Typless Webservices ist mit folgender Meldung fehlgeschlagen:\n"
|
||||
"%(message)s"
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typless"
|
||||
36
modules/document_incoming_ocr_typless/locale/es.po
Normal file
36
modules/document_incoming_ocr_typless/locale/es.po
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "Clave API"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Tipo de documento"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr "El token estándar de la pagina de configuración de Typless."
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr "El nombre del tipo de documento en Typless."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr "¿Está seguro de que desea modificar las credenciales de Typless?"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
"La llamada al servicio web Typless ha fallado con el siguiente mensaje: \n"
|
||||
"%(message)s"
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typless"
|
||||
34
modules/document_incoming_ocr_typless/locale/es_419.po
Normal file
34
modules/document_incoming_ocr_typless/locale/es_419.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/et.po
Normal file
34
modules/document_incoming_ocr_typless/locale/et.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/fa.po
Normal file
34
modules/document_incoming_ocr_typless/locale/fa.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/fi.po
Normal file
34
modules/document_incoming_ocr_typless/locale/fi.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
38
modules/document_incoming_ocr_typless/locale/fr.po
Normal file
38
modules/document_incoming_ocr_typless/locale/fr.po
Normal file
@@ -0,0 +1,38 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "Clé API"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Type de document"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr "Le jeton standard de la page des paramètres Typless."
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr "Le nom du type de document sur Typless."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
"Êtes-vous sûr de vouloir modifier les informations d'identification de "
|
||||
"Typless ?"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
"L'appel au service Web Typless a échoué avec le message d'erreur suivant :\n"
|
||||
"%(message)s"
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typless"
|
||||
34
modules/document_incoming_ocr_typless/locale/hu.po
Normal file
34
modules/document_incoming_ocr_typless/locale/hu.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/id.po
Normal file
34
modules/document_incoming_ocr_typless/locale/id.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
37
modules/document_incoming_ocr_typless/locale/it.po
Normal file
37
modules/document_incoming_ocr_typless/locale/it.po
Normal file
@@ -0,0 +1,37 @@
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "Chiave API"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Tipo di documento"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr "Il nome del tipo di documento su Typeless."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
"La chiamata al servizio Web Typeless non è riuscita con il seguente messaggio di errore:\n"
|
||||
"%(message)s"
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typless"
|
||||
34
modules/document_incoming_ocr_typless/locale/lo.po
Normal file
34
modules/document_incoming_ocr_typless/locale/lo.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/lt.po
Normal file
34
modules/document_incoming_ocr_typless/locale/lt.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
36
modules/document_incoming_ocr_typless/locale/nl.po
Normal file
36
modules/document_incoming_ocr_typless/locale/nl.po
Normal file
@@ -0,0 +1,36 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "API sleutel"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Soort document"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr "De standaard token van de Typless configuratie pagina."
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr "De naam van het soort document op Typless."
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr "Weet u zeker dat u de inloggegevens van Typless wilt wijzigen?"
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
"Aanroepen van de Typless webservice is mislukt met de volgende foutmelding:\n"
|
||||
"%(message)s"
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typless"
|
||||
34
modules/document_incoming_ocr_typless/locale/pl.po
Normal file
34
modules/document_incoming_ocr_typless/locale/pl.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/pt.po
Normal file
34
modules/document_incoming_ocr_typless/locale/pt.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/ro.po
Normal file
34
modules/document_incoming_ocr_typless/locale/ro.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/ru.po
Normal file
34
modules/document_incoming_ocr_typless/locale/ru.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
35
modules/document_incoming_ocr_typless/locale/sl.po
Normal file
35
modules/document_incoming_ocr_typless/locale/sl.po
Normal file
@@ -0,0 +1,35 @@
|
||||
#
|
||||
#, fuzzy
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr "API ključ"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr "Vrsta dokumenta"
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr "Typeless"
|
||||
34
modules/document_incoming_ocr_typless/locale/tr.po
Normal file
34
modules/document_incoming_ocr_typless/locale/tr.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/uk.po
Normal file
34
modules/document_incoming_ocr_typless/locale/uk.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
34
modules/document_incoming_ocr_typless/locale/zh_CN.po
Normal file
34
modules/document_incoming_ocr_typless/locale/zh_CN.po
Normal file
@@ -0,0 +1,34 @@
|
||||
#
|
||||
msgid ""
|
||||
msgstr "Content-Type: text/plain; charset=utf-8\n"
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "API Key"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "field:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "Document Type"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_api_key:"
|
||||
msgid "The standard token from Typless settings page."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "help:document.incoming.ocr.service,typless_document_type:"
|
||||
msgid "The name of the document type on Typless."
|
||||
msgstr ""
|
||||
|
||||
msgctxt "model:ir.message,text:msg_typless_credential_modified"
|
||||
msgid "Are you sure you want to modify Typless credentials?"
|
||||
msgstr ""
|
||||
|
||||
#, python-format
|
||||
msgctxt "model:ir.message,text:msg_typless_webserver_error"
|
||||
msgid ""
|
||||
"Typless webservice call failed with the following error message:\n"
|
||||
"%(message)s"
|
||||
msgstr ""
|
||||
|
||||
msgctxt "selection:document.incoming.ocr.service,type:"
|
||||
msgid "Typless"
|
||||
msgstr ""
|
||||
14
modules/document_incoming_ocr_typless/message.xml
Normal file
14
modules/document_incoming_ocr_typless/message.xml
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<tryton>
|
||||
<data grouped="1">
|
||||
<record model="ir.message" id="msg_typless_credential_modified">
|
||||
<field name="text">Are you sure you want to modify Typless credentials?</field>
|
||||
</record>
|
||||
<record model="ir.message" id="msg_typless_webserver_error">
|
||||
<field name="text">Typless webservice call failed with the following error message:
|
||||
%(message)s</field>
|
||||
</record>
|
||||
</data>
|
||||
</tryton>
|
||||
2
modules/document_incoming_ocr_typless/tests/__init__.py
Normal file
2
modules/document_incoming_ocr_typless/tests/__init__.py
Normal file
@@ -0,0 +1,2 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,130 @@
|
||||
======================================
|
||||
Document Incoming OCR Typless Scenario
|
||||
======================================
|
||||
|
||||
Imports::
|
||||
|
||||
>>> import os
|
||||
>>> from decimal import Decimal
|
||||
|
||||
>>> from proteus import Model
|
||||
>>> from trytond.modules.account.tests.tools import (
|
||||
... create_chart, create_fiscalyear, create_tax, get_accounts)
|
||||
>>> from trytond.modules.account_invoice.tests.tools import (
|
||||
... set_fiscalyear_invoice_sequences)
|
||||
>>> from trytond.modules.company.tests.tools import create_company
|
||||
>>> from trytond.tests.tools import activate_modules, assertEqual
|
||||
>>> from trytond.tools import file_open
|
||||
|
||||
Activate modules::
|
||||
|
||||
>>> config = activate_modules([
|
||||
... 'document_incoming_ocr_typless',
|
||||
... 'document_incoming_invoice'],
|
||||
... create_company, create_chart)
|
||||
|
||||
>>> Document = Model.get('document.incoming')
|
||||
>>> OCRService = Model.get('document.incoming.ocr.service')
|
||||
>>> Party = Model.get('party.party')
|
||||
>>> ProductCategory = Model.get('product.category')
|
||||
>>> ProductTemplate = Model.get('product.template')
|
||||
>>> UoM = Model.get('product.uom')
|
||||
|
||||
Get accounts::
|
||||
|
||||
>>> accounts = get_accounts()
|
||||
|
||||
Create taxes::
|
||||
|
||||
>>> tax_10 = create_tax(Decimal('0.1'))
|
||||
>>> tax_10.save()
|
||||
>>> tax_20 = create_tax(Decimal('0.2'))
|
||||
>>> tax_20.save()
|
||||
|
||||
Create fiscal year::
|
||||
|
||||
>>> fiscalyear = set_fiscalyear_invoice_sequences(create_fiscalyear())
|
||||
>>> fiscalyear.click('create_period')
|
||||
|
||||
Set default supplier::
|
||||
|
||||
>>> suppplier = Party(name="Saber")
|
||||
>>> suppplier.save()
|
||||
|
||||
Create account category::
|
||||
|
||||
>>> account_category = ProductCategory(name="Accounting")
|
||||
>>> account_category.accounting = True
|
||||
>>> account_category.account_expense = accounts['expense']
|
||||
>>> account_category.save()
|
||||
|
||||
Create product::
|
||||
|
||||
>>> hour, = UoM.find([('name', '=', "Hour")])
|
||||
>>> template = ProductTemplate(name="Service")
|
||||
>>> template.default_uom = hour
|
||||
>>> template.type = 'service'
|
||||
>>> template.account_category = account_category
|
||||
>>> template.save()
|
||||
>>> service, = template.products
|
||||
|
||||
Setup Typless service::
|
||||
|
||||
>>> ocr_service = OCRService(type='typless')
|
||||
>>> ocr_service.typless_api_key = os.getenv('TYPLESS_API_KEY')
|
||||
>>> ocr_service.typless_document_type = os.getenv('TYPLESS_DOCUMENT_TYPE')
|
||||
>>> ocr_service.save()
|
||||
|
||||
Create incoming document::
|
||||
|
||||
>>> document = Document()
|
||||
>>> document.name = 'invoice.pdf'
|
||||
>>> with file_open(
|
||||
... 'document_incoming_ocr_typless/tests/'
|
||||
... 'supplier-invoice-sample.pdf',
|
||||
... mode='rb') as fp:
|
||||
... document.data = fp.read()
|
||||
>>> document.type = 'supplier_invoice'
|
||||
>>> document.save()
|
||||
|
||||
Process document::
|
||||
|
||||
>>> document.click('process')
|
||||
>>> invoice = document.result
|
||||
>>> assertEqual(invoice.party, suppplier)
|
||||
>>> invoice.reference
|
||||
'INV-0007'
|
||||
>>> invoice.invoice_date
|
||||
datetime.date(2023, 6, 28)
|
||||
>>> invoice.payment_term_date
|
||||
datetime.date(2023, 7, 28)
|
||||
>>> len(invoice.lines)
|
||||
2
|
||||
>>> line_service, = [l for l in invoice.lines if l.product]
|
||||
>>> assertEqual(line_service.product, service)
|
||||
>>> line_service.quantity
|
||||
23.0
|
||||
>>> line_service.unit_price
|
||||
Decimal('2.5000')
|
||||
>>> line_goods, = [l for l in invoice.lines if not l.product]
|
||||
>>> line_goods.quantity
|
||||
40.0
|
||||
>>> line_goods.unit_price
|
||||
Decimal('5.0000')
|
||||
>>> len(invoice.taxes)
|
||||
2
|
||||
>>> sorted([t.amount for t in invoice.taxes])
|
||||
[Decimal('5.75'), Decimal('40.00')]
|
||||
>>> sorted([t.base for t in invoice.taxes])
|
||||
[Decimal('57.50'), Decimal('200.00')]
|
||||
>>> assertEqual({t.tax for t in invoice.taxes}, {tax_10, tax_20})
|
||||
>>> invoice.untaxed_amount
|
||||
Decimal('257.50')
|
||||
>>> invoice.tax_amount
|
||||
Decimal('45.75')
|
||||
>>> invoice.total_amount
|
||||
Decimal('303.25')
|
||||
|
||||
Send feedback::
|
||||
|
||||
>>> document.click('ocr_send_feedback')
|
||||
Binary file not shown.
29
modules/document_incoming_ocr_typless/tests/test_module.py
Normal file
29
modules/document_incoming_ocr_typless/tests/test_module.py
Normal file
@@ -0,0 +1,29 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
from trytond.pool import Pool
|
||||
from trytond.tests.test_tryton import ModuleTestCase, with_transaction
|
||||
|
||||
|
||||
class DocumentIncomingOcrTyplessTestCase(ModuleTestCase):
|
||||
"Test Document Incoming Ocr Typless module"
|
||||
module = 'document_incoming_ocr_typless'
|
||||
|
||||
@with_transaction()
|
||||
def test_service_match(self):
|
||||
"Test Service match"
|
||||
pool = Pool()
|
||||
Service = pool.get('document.incoming.ocr.service')
|
||||
|
||||
for service, pattern, result in [
|
||||
(Service(type='typless', source=None), {}, False),
|
||||
(Service(type='typless', source=None),
|
||||
{'mime_type': 'application/pdf'}, True),
|
||||
(Service(type='typless', source=None),
|
||||
{'mime_type': 'application/octet-stream'}, False),
|
||||
]:
|
||||
with self.subTest(service=service, pattern=pattern):
|
||||
self.assertEqual(service.match(pattern), result)
|
||||
|
||||
|
||||
del ModuleTestCase
|
||||
15
modules/document_incoming_ocr_typless/tests/test_scenario.py
Normal file
15
modules/document_incoming_ocr_typless/tests/test_scenario.py
Normal file
@@ -0,0 +1,15 @@
|
||||
# This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
# this repository contains the full copyright notices and license terms.
|
||||
|
||||
import os
|
||||
|
||||
from trytond.tests.test_tryton import TEST_NETWORK, load_doc_tests
|
||||
|
||||
|
||||
def load_tests(*args, **kwargs):
|
||||
if (not TEST_NETWORK
|
||||
or not (os.getenv('TYPLESS_API_KEY')
|
||||
and os.getenv('TYPLESS_DOCUMENT_TYPE'))):
|
||||
kwargs.setdefault('skips', set()).add(
|
||||
'scenario_document_incoming_ocr_typless.rst')
|
||||
return load_doc_tests(__name__, __file__, *args, **kwargs)
|
||||
17
modules/document_incoming_ocr_typless/tryton.cfg
Normal file
17
modules/document_incoming_ocr_typless/tryton.cfg
Normal file
@@ -0,0 +1,17 @@
|
||||
[tryton]
|
||||
version=7.8.0
|
||||
depends:
|
||||
currency
|
||||
document_incoming
|
||||
document_incoming_ocr
|
||||
ir
|
||||
party
|
||||
extras_depend:
|
||||
document_incoming_invoice
|
||||
xml:
|
||||
document.xml
|
||||
message.xml
|
||||
|
||||
[register]
|
||||
model:
|
||||
document.IncomingOCRService
|
||||
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- This file is part of Tryton. The COPYRIGHT file at the top level of
|
||||
this repository contains the full copyright notices and license terms. -->
|
||||
<data>
|
||||
<xpath expr="//separator[@id='criteria']" position="before">
|
||||
<newline/>
|
||||
<label name="typless_api_key"/>
|
||||
<field name="typless_api_key" widget="password"/>
|
||||
<label name="typless_document_type"/>
|
||||
<field name="typless_document_type"/>
|
||||
<newline/>
|
||||
</xpath>
|
||||
</data>
|
||||
Reference in New Issue
Block a user