Upgrade to 5.4
This commit is contained in:
parent
aa37f4fa6c
commit
a1f4e9f463
10
__init__.py
10
__init__.py
|
@ -2,13 +2,13 @@
|
||||||
# The COPYRIGHT file at the top level of this repository contains
|
# The COPYRIGHT file at the top level of this repository contains
|
||||||
# the full copyright notices and license terms.
|
# the full copyright notices and license terms.
|
||||||
from trytond.pool import Pool
|
from trytond.pool import Pool
|
||||||
from .csv_import import *
|
from . import csv_import
|
||||||
|
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
Pool.register(
|
Pool.register(
|
||||||
CSVProfile,
|
csv_import.CSVProfile,
|
||||||
CSVProfileBaseExternalMapping,
|
csv_import.CSVProfileBaseExternalMapping,
|
||||||
CSVArchive,
|
csv_import.CSVArchive,
|
||||||
BaseExternalMapping,
|
csv_import.BaseExternalMapping,
|
||||||
module='csv_import', type_='model')
|
module='csv_import', type_='model')
|
||||||
|
|
129
csv_import.py
129
csv_import.py
|
@ -1,39 +1,33 @@
|
||||||
# This file is part of csv_import module for Tryton.
|
# This file is part of csv_import module for Tryton.
|
||||||
# The COPYRIGHT file at the top level of this repository contains
|
# The COPYRIGHT file at the top level of this repository contains
|
||||||
# the full copyright notices and license terms.
|
# the full copyright notices and license terms.
|
||||||
try:
|
|
||||||
import cStringIO as StringIO
|
|
||||||
except ImportError:
|
|
||||||
from io import StringIO
|
|
||||||
from csv import reader
|
|
||||||
from datetime import datetime
|
|
||||||
from trytond.config import config
|
|
||||||
from trytond.model import ModelSQL, ModelView, fields, Workflow
|
|
||||||
from trytond.pool import Pool, PoolMeta
|
|
||||||
from trytond.pyson import Eval, If
|
|
||||||
from trytond.transaction import Transaction
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import unicodedata
|
import unicodedata
|
||||||
import string
|
import string
|
||||||
|
import csv
|
||||||
|
from io import StringIO
|
||||||
|
from datetime import datetime
|
||||||
|
from trytond.config import config
|
||||||
|
from trytond.model import ModelSQL, ModelView, fields, Workflow
|
||||||
|
from trytond.pool import Pool, PoolMeta
|
||||||
|
from trytond.pyson import Eval
|
||||||
|
from trytond.transaction import Transaction
|
||||||
|
from trytond.i18n import gettext
|
||||||
|
from trytond.exceptions import UserError
|
||||||
|
|
||||||
|
|
||||||
__all__ = ['BaseExternalMapping',
|
__all__ = ['BaseExternalMapping',
|
||||||
'CSVProfile', 'CSVProfileBaseExternalMapping', 'CSVArchive']
|
'CSVProfile', 'CSVProfileBaseExternalMapping', 'CSVArchive']
|
||||||
_slugify_strip_re = re.compile(r'[^\w\s-]')
|
|
||||||
_slugify_hyphenate_re = re.compile(r'[-\s]+')
|
|
||||||
|
|
||||||
|
|
||||||
def slugify(value):
|
def slugify(value):
|
||||||
if not isinstance(value, unicode):
|
|
||||||
value = unicode(value)
|
|
||||||
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
value = unicodedata.normalize('NFKD', value).encode('ascii', 'ignore')
|
||||||
value = unicode(_slugify_strip_re.sub('', value).strip().lower())
|
value = re.sub('[^\w\s-]', '', value.decode('utf-8')).strip().lower()
|
||||||
return _slugify_hyphenate_re.sub('-', value)
|
return re.sub('[-\s]+', '-', value)
|
||||||
|
|
||||||
|
|
||||||
class BaseExternalMapping:
|
class BaseExternalMapping(metaclass=PoolMeta):
|
||||||
__metaclass__ = PoolMeta
|
|
||||||
__name__ = 'base.external.mapping'
|
__name__ = 'base.external.mapping'
|
||||||
csv_mapping = fields.Many2One('base.external.mapping', 'CSV Mapping')
|
csv_mapping = fields.Many2One('base.external.mapping', 'CSV Mapping')
|
||||||
csv_rel_field = fields.Many2One('ir.model.field', 'CSV Field related')
|
csv_rel_field = fields.Many2One('ir.model.field', 'CSV Field related')
|
||||||
|
@ -137,8 +131,10 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
@classmethod
|
@classmethod
|
||||||
def __setup__(cls):
|
def __setup__(cls):
|
||||||
super(CSVArchive, cls).__setup__()
|
super(CSVArchive, cls).__setup__()
|
||||||
cls._order.insert(0, ('date_archive', 'DESC'))
|
cls._order = [
|
||||||
cls._order.insert(1, ('id', 'DESC'))
|
('date_archive', 'DESC'),
|
||||||
|
('id', 'DESC'),
|
||||||
|
]
|
||||||
cls._transitions |= set((
|
cls._transitions |= set((
|
||||||
('draft', 'done'),
|
('draft', 'done'),
|
||||||
('draft', 'canceled'),
|
('draft', 'canceled'),
|
||||||
|
@ -147,59 +143,43 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
cls._buttons.update({
|
cls._buttons.update({
|
||||||
'cancel': {
|
'cancel': {
|
||||||
'invisible': Eval('state') != 'draft',
|
'invisible': Eval('state') != 'draft',
|
||||||
|
'depends': ['state'],
|
||||||
},
|
},
|
||||||
'draft': {
|
'draft': {
|
||||||
'invisible': Eval('state') != 'canceled',
|
'invisible': Eval('state') != 'canceled',
|
||||||
'icon': If(Eval('state') == 'canceled', 'tryton-clear',
|
'depends': ['state'],
|
||||||
'tryton-go-previous'),
|
|
||||||
},
|
},
|
||||||
'import_csv': {
|
'import_csv': {
|
||||||
'invisible': Eval('state') != 'draft',
|
'invisible': Eval('state') != 'draft',
|
||||||
|
'depends': ['state'],
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
cls._error_messages.update({
|
|
||||||
'error': 'CSV Import Error!',
|
|
||||||
'reading_error': 'Error reading file %s.',
|
|
||||||
'read_error': 'Error reading file: %s.\nError %s.',
|
|
||||||
'success_simulation': 'Simulation successfully.',
|
|
||||||
'record_saved': 'Record ID %s saved successfully!',
|
|
||||||
'record_error': 'Error saving records.',
|
|
||||||
'not_create_update': 'Not create or update line %s',
|
|
||||||
})
|
|
||||||
|
|
||||||
def get_data(self, name):
|
def get_data(self, name):
|
||||||
cursor = Transaction().connection.cursor()
|
|
||||||
path = os.path.join(config.get('database', 'path'),
|
path = os.path.join(config.get('database', 'path'),
|
||||||
cursor.database_name, 'csv_import')
|
Transaction().database.name, 'csv_import')
|
||||||
archive = '%s/%s' % (path, self.archive_name.replace(' ', '_'))
|
archive = '%s/%s' % (path, self.archive_name.replace(' ', '_'))
|
||||||
try:
|
try:
|
||||||
with open(archive, 'r') as f:
|
with open(archive, 'rb') as f:
|
||||||
return fields.Binary.cast(f.read())
|
return fields.Binary.cast(f.read())
|
||||||
except IOError:
|
except IOError:
|
||||||
self.raise_user_error('error',
|
pass
|
||||||
error_description='reading_error',
|
|
||||||
error_description_args=(self.archive_name.replace(' ', '_'),),
|
|
||||||
raise_exception=True)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def set_data(cls, archives, name, value):
|
def set_data(cls, archives, name, value):
|
||||||
cursor = Transaction().connection.cursor()
|
|
||||||
path = os.path.join(config.get('database', 'path'),
|
path = os.path.join(config.get('database', 'path'),
|
||||||
cursor.database_name, 'csv_import')
|
Transaction().database.name, 'csv_import')
|
||||||
if not os.path.exists(path):
|
if not os.path.exists(path):
|
||||||
os.makedirs(path, mode=0777)
|
os.makedirs(path, mode=0o777)
|
||||||
for archive in archives:
|
for archive in archives:
|
||||||
archive = '%s/%s' % (path, archive.archive_name.replace(' ', '_'))
|
archive = '%s/%s' % (path, archive.archive_name.replace(' ', '_'))
|
||||||
try:
|
try:
|
||||||
with open(archive, 'w') as f:
|
with open(archive, 'wb') as f:
|
||||||
f.write(value)
|
f.write(value)
|
||||||
except IOError, e:
|
except IOError:
|
||||||
cls.raise_user_error('error',
|
raise UserError(gettext('csv_import.msg_error'))
|
||||||
error_description='save_error',
|
|
||||||
error_description_args=(e,),
|
|
||||||
raise_exception=True)
|
|
||||||
|
|
||||||
@fields.depends('profile')
|
@fields.depends('profile', '_parent_profile.rec_name')
|
||||||
def on_change_profile(self):
|
def on_change_profile(self):
|
||||||
if self.profile:
|
if self.profile:
|
||||||
today = Pool().get('ir.date').today()
|
today = Pool().get('ir.date').today()
|
||||||
|
@ -235,7 +215,7 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
if hasattr(cls, method_data):
|
if hasattr(cls, method_data):
|
||||||
import_data = getattr(cls, method_data)
|
import_data = getattr(cls, method_data)
|
||||||
record = import_data(record, values, parent_values)
|
record = import_data(record, values, parent_values)
|
||||||
for k, v in values.iteritems():
|
for k, v in values.items():
|
||||||
setattr(record, k, v)
|
setattr(record, k, v)
|
||||||
return record
|
return record
|
||||||
|
|
||||||
|
@ -260,24 +240,22 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
quote = profile.csv_quote
|
quote = profile.csv_quote
|
||||||
header = profile.csv_header
|
header = profile.csv_header
|
||||||
|
|
||||||
data = StringIO(archive.data)
|
data = StringIO(archive.data.decode('ascii', errors='replace'))
|
||||||
try:
|
try:
|
||||||
rows = reader(data, delimiter=str(separator),
|
reader = csv.reader(data, delimiter=str(separator),
|
||||||
quotechar=str(quote))
|
quotechar=str(quote))
|
||||||
except TypeError, e:
|
except TypeError:
|
||||||
cls.write([archive], {'logs': 'Error - %s' % (
|
cls.write([archive], {'logs': 'Error - %s' % (
|
||||||
cls.raise_user_error('error',
|
gettext('csv_import.msg_read_error',
|
||||||
error_description='read_error',
|
filename=archive.archive_name.replace(' ', '_'))
|
||||||
error_description_args=(archive.archive_name, e),
|
|
||||||
raise_exception=False),
|
|
||||||
)})
|
)})
|
||||||
return
|
return
|
||||||
|
|
||||||
if header: # TODO. Know why some header columns get ""
|
if header:
|
||||||
headers = [filter(lambda x: x in string.printable, x
|
# TODO. Know why some header columns get ""
|
||||||
).replace('"', '')
|
headers = ["".join(list(filter(lambda x: x in string.printable,
|
||||||
for x in next(rows)]
|
x.replace('"', '')))) for x in next(reader)]
|
||||||
return rows, headers
|
return reader, headers
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@ModelView.button
|
@ModelView.button
|
||||||
|
@ -298,7 +276,7 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
if not profile.create_record and not profile.update_record:
|
if not profile.create_record and not profile.update_record:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
data, headers = cls._read_csv_file(archive)
|
reader, headers = cls._read_csv_file(archive)
|
||||||
|
|
||||||
base_model = profile.model.model
|
base_model = profile.model.model
|
||||||
|
|
||||||
|
@ -308,10 +286,14 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
child_mappings.append(mapping)
|
child_mappings.append(mapping)
|
||||||
else:
|
else:
|
||||||
base_mapping = mapping
|
base_mapping = mapping
|
||||||
|
if not base_mapping:
|
||||||
|
logs.append(gettext('csv_import.msg_not_mapping',
|
||||||
|
profile=profile.rec_name))
|
||||||
|
continue
|
||||||
|
|
||||||
new_records = []
|
new_records = []
|
||||||
new_lines = []
|
new_lines = []
|
||||||
rows = list(data)
|
rows = list(reader)
|
||||||
Base = pool.get(base_model)
|
Base = pool.get(base_model)
|
||||||
for i in range(len(rows)):
|
for i in range(len(rows)):
|
||||||
row = rows[i]
|
row = rows[i]
|
||||||
|
@ -325,13 +307,17 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
if not new_lines:
|
if not new_lines:
|
||||||
base_values = ExternalMapping.map_external_to_tryton(
|
base_values = ExternalMapping.map_external_to_tryton(
|
||||||
base_mapping.name, vals)
|
base_mapping.name, vals)
|
||||||
if not base_values.values()[0] == '':
|
if not list(base_values.values())[0] == '':
|
||||||
new_lines = []
|
new_lines = []
|
||||||
|
|
||||||
#get values child models
|
#get values child models
|
||||||
child_values = None
|
child_values = None
|
||||||
child_rel_field = None
|
child_rel_field = None
|
||||||
for child in child_mappings:
|
for child in child_mappings:
|
||||||
|
if not child.csv_rel_field:
|
||||||
|
logs.append(gettext('csv_import.msg_missing_rel_field',
|
||||||
|
mapping=child.rec_name))
|
||||||
|
continue
|
||||||
child_rel_field = child.csv_rel_field.name
|
child_rel_field = child.csv_rel_field.name
|
||||||
child_values = ExternalMapping.map_external_to_tryton(
|
child_values = ExternalMapping.map_external_to_tryton(
|
||||||
child.name, vals)
|
child.name, vals)
|
||||||
|
@ -345,7 +331,7 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
if child_rel_field:
|
if child_rel_field:
|
||||||
base_values[child_rel_field] = new_lines
|
base_values[child_rel_field] = new_lines
|
||||||
|
|
||||||
#next row is empty first value, is a new line. Continue
|
# next row is empty first value, is a new line. Continue
|
||||||
if i < len(rows) - 1:
|
if i < len(rows) - 1:
|
||||||
if rows[i + 1]:
|
if rows[i + 1]:
|
||||||
if rows[i + 1][0] == '':
|
if rows[i + 1][0] == '':
|
||||||
|
@ -367,8 +353,8 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
record = Base()
|
record = Base()
|
||||||
|
|
||||||
if not record:
|
if not record:
|
||||||
logs.append(cls.raise_user_error('not_create_update',
|
logs.append(gettext('csv_import.msg_not_create_update',
|
||||||
error_args=(i + 1,), raise_exception=False))
|
line=i + 1))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
#get default values from base model
|
#get default values from base model
|
||||||
|
@ -377,13 +363,12 @@ class CSVArchive(Workflow, ModelSQL, ModelView):
|
||||||
#save - not testing
|
#save - not testing
|
||||||
if not profile.testing:
|
if not profile.testing:
|
||||||
record.save() # save or update
|
record.save() # save or update
|
||||||
logs.append(cls.raise_user_error('record_saved',
|
logs.append(gettext('csv_import.msg_record_saved',
|
||||||
error_args=(record.id,), raise_exception=False))
|
record=record.id))
|
||||||
new_records.append(record.id)
|
new_records.append(record.id)
|
||||||
|
|
||||||
if profile.testing:
|
if profile.testing:
|
||||||
logs.append(cls.raise_user_error('success_simulation',
|
logs.append(gettext('csv_import.msg_success_simulation'))
|
||||||
raise_exception=False))
|
|
||||||
|
|
||||||
cls.post_import(profile, new_records)
|
cls.post_import(profile, new_records)
|
||||||
cls.write([archive], {'logs': '\n'.join(logs)})
|
cls.write([archive], {'logs': '\n'.join(logs)})
|
||||||
|
|
|
@ -78,6 +78,22 @@ copyright notices and license terms. -->
|
||||||
<field name="group" ref="group_csv_import_admin"/>
|
<field name="group" ref="group_csv_import_admin"/>
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
<record model="ir.model.button" id="cancel_button">
|
||||||
|
<field name="name">cancel</field>
|
||||||
|
<field name="string">Cancel</field>
|
||||||
|
<field name="model" search="[('model', '=', 'csv.archive')]"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.button" id="draft_button">
|
||||||
|
<field name="name">draft</field>
|
||||||
|
<field name="string">Draft</field>
|
||||||
|
<field name="model" search="[('model', '=', 'csv.archive')]"/>
|
||||||
|
</record>
|
||||||
|
<record model="ir.model.button" id="import_csv_button">
|
||||||
|
<field name="name">import_csv</field>
|
||||||
|
<field name="string">Import CSV</field>
|
||||||
|
<field name="model" search="[('model', '=', 'csv.archive')]"/>
|
||||||
|
</record>
|
||||||
|
|
||||||
<!-- base.external.mapping -->
|
<!-- base.external.mapping -->
|
||||||
<record model="ir.ui.view" id="base_external_mapping_tree_view">
|
<record model="ir.ui.view" id="base_external_mapping_tree_view">
|
||||||
<field name="model">base.external.mapping</field>
|
<field name="model">base.external.mapping</field>
|
||||||
|
@ -138,4 +154,3 @@ copyright notices and license terms. -->
|
||||||
</record>
|
</record>
|
||||||
</data>
|
</data>
|
||||||
</tryton>
|
</tryton>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
<?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_error">
|
||||||
|
<field name="text">CSV Import Error!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_read_error">
|
||||||
|
<field name="text">Error reading file: %(filename)s.
|
||||||
|
%(error)s</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_success_simulation">
|
||||||
|
<field name="text">Simulation successfully</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_record_saved">
|
||||||
|
<field name="text">Record ID "%(record)s" saved successfully!</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_record_error">
|
||||||
|
<field name="text">Error saving records</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_not_create_update">
|
||||||
|
<field name="text">Not create or update line %(line)s</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_not_mapping">
|
||||||
|
<field name="text">Not found mapping at "%(profile)s"</field>
|
||||||
|
</record>
|
||||||
|
<record model="ir.message" id="msg_missing_rel_field">
|
||||||
|
<field name="text">Missing relation field at "%(mapping)s"</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</tryton>
|
|
@ -12,9 +12,11 @@ Imports::
|
||||||
>>> from dateutil.relativedelta import relativedelta
|
>>> from dateutil.relativedelta import relativedelta
|
||||||
>>> from decimal import Decimal
|
>>> from decimal import Decimal
|
||||||
>>> from operator import attrgetter
|
>>> from operator import attrgetter
|
||||||
>>> today = datetime.date.today()
|
>>> from proteus import config, Model, Wizard
|
||||||
|
>>> from trytond.tests.tools import activate_modules
|
||||||
>>> from trytond.config import config
|
>>> from trytond.config import config
|
||||||
>>> from trytond.tests.test_tryton import DB_NAME as db_name
|
>>> from trytond.tests.test_tryton import DB_NAME as db_name
|
||||||
|
>>> today = datetime.date.today()
|
||||||
|
|
||||||
>>> module_path = os.path.dirname(__file__) + '/'
|
>>> module_path = os.path.dirname(__file__) + '/'
|
||||||
|
|
||||||
|
@ -28,27 +30,14 @@ Imports::
|
||||||
>>> if not os.path.exists(data_path + db_name + module_name):
|
>>> if not os.path.exists(data_path + db_name + module_name):
|
||||||
... os.makedirs(data_path + db_name + module_name)
|
... os.makedirs(data_path + db_name + module_name)
|
||||||
|
|
||||||
>>> from proteus import config, Model, Wizard
|
Install csv_import::
|
||||||
|
|
||||||
Create database::
|
>>> config = activate_modules(['csv_import', 'party'])
|
||||||
|
|
||||||
>>> config = config.set_trytond()
|
|
||||||
>>> config.pool.test = True
|
|
||||||
|
|
||||||
Install modules::
|
|
||||||
|
|
||||||
>>> Module = Model.get('ir.module')
|
|
||||||
>>> modules = Module.find([
|
|
||||||
... ('name', 'in', ('party', 'csv_import')),
|
|
||||||
... ])
|
|
||||||
>>> Module.install([x.id for x in modules], config.context)
|
|
||||||
>>> Wizard('ir.module.install_upgrade').execute('upgrade')
|
|
||||||
|
|
||||||
Init models::
|
Init models::
|
||||||
|
|
||||||
>>> Model = Model.get('ir.model')
|
>>> Model = Model.get('ir.model')
|
||||||
>>> Field = Model.get('ir.model.field')
|
>>> Field = Model.get('ir.model.field')
|
||||||
>>> Group = Model.get('res.group')
|
|
||||||
>>> BaseExternalMapping = Model.get('base.external.mapping')
|
>>> BaseExternalMapping = Model.get('base.external.mapping')
|
||||||
>>> BaseExternalMappingLine = Model.get('base.external.mapping.line')
|
>>> BaseExternalMappingLine = Model.get('base.external.mapping.line')
|
||||||
>>> CSVProfile = Model.get('csv.profile')
|
>>> CSVProfile = Model.get('csv.profile')
|
||||||
|
@ -122,7 +111,6 @@ Create profile::
|
||||||
>>> profile = CSVProfile()
|
>>> profile = CSVProfile()
|
||||||
>>> profile.name = 'Parties'
|
>>> profile.name = 'Parties'
|
||||||
>>> profile.model = Model.find([('model', '=', 'party.party')])[0]
|
>>> profile.model = Model.find([('model', '=', 'party.party')])[0]
|
||||||
>>> profile.group = Group.find([('name', '=', 'Administration')])[0]
|
|
||||||
>>> profile.create_record = True
|
>>> profile.create_record = True
|
||||||
>>> profile.csv_header = True
|
>>> profile.csv_header = True
|
||||||
>>> profile.csv_archive_separator = ','
|
>>> profile.csv_archive_separator = ','
|
||||||
|
@ -136,7 +124,7 @@ Create CSV archive::
|
||||||
>>> srcfile = '%s/%s' % (module_path, 'import_party.csv')
|
>>> srcfile = '%s/%s' % (module_path, 'import_party.csv')
|
||||||
>>> dstfile = '%s/%s/%s/%s' % (data_path, db_name, module_name,
|
>>> dstfile = '%s/%s/%s/%s' % (data_path, db_name, module_name,
|
||||||
... 'import_party.csv')
|
... 'import_party.csv')
|
||||||
>>> shutil.copy(srcfile, dstfile)
|
>>> _ = shutil.copy(srcfile, dstfile)
|
||||||
>>> CSVArchive = Model.get('csv.archive')
|
>>> CSVArchive = Model.get('csv.archive')
|
||||||
>>> archive = CSVArchive()
|
>>> archive = CSVArchive()
|
||||||
>>> archive.profile = profile
|
>>> archive.profile = profile
|
||||||
|
@ -156,7 +144,7 @@ Create Parties and multi Addresses::
|
||||||
>>> srcfile = '%s/%s' % (module_path, 'import_party_multiaddress.csv')
|
>>> srcfile = '%s/%s' % (module_path, 'import_party_multiaddress.csv')
|
||||||
>>> dstfile = '%s/%s/%s/%s' % (data_path, db_name, module_name,
|
>>> dstfile = '%s/%s/%s/%s' % (data_path, db_name, module_name,
|
||||||
... 'import_party_multiaddress.csv')
|
... 'import_party_multiaddress.csv')
|
||||||
>>> shutil.copy(srcfile, dstfile)
|
>>> _ = shutil.copy(srcfile, dstfile)
|
||||||
>>> CSVArchive = Model.get('csv.archive')
|
>>> CSVArchive = Model.get('csv.archive')
|
||||||
>>> archive = CSVArchive()
|
>>> archive = CSVArchive()
|
||||||
>>> archive.profile = profile
|
>>> archive.profile = profile
|
||||||
|
@ -190,7 +178,7 @@ Create CSV Update archive::
|
||||||
>>> srcfile = '%s/%s' % (module_path, 'update_party.csv')
|
>>> srcfile = '%s/%s' % (module_path, 'update_party.csv')
|
||||||
>>> dstfile = '%s/%s/%s/%s' % (data_path, db_name, module_name,
|
>>> dstfile = '%s/%s/%s/%s' % (data_path, db_name, module_name,
|
||||||
... 'update_party.csv')
|
... 'update_party.csv')
|
||||||
>>> shutil.copy(srcfile, dstfile)
|
>>> _ = shutil.copy(srcfile, dstfile)
|
||||||
>>> CSVArchive = Model.get('csv.archive')
|
>>> CSVArchive = Model.get('csv.archive')
|
||||||
>>> archive = CSVArchive()
|
>>> archive = CSVArchive()
|
||||||
>>> archive.profile = CSVProfile.find([])[0]
|
>>> archive.profile = CSVProfile.find([])[0]
|
||||||
|
|
|
@ -10,7 +10,7 @@ from trytond.tests.test_tryton import doctest_checker
|
||||||
|
|
||||||
|
|
||||||
class CsvImportTestCase(ModuleTestCase):
|
class CsvImportTestCase(ModuleTestCase):
|
||||||
'Test Csv Import module'
|
'Test CSV Import module'
|
||||||
module = 'csv_import'
|
module = 'csv_import'
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
[tryton]
|
[tryton]
|
||||||
version=3.9.0
|
version=5.4.0
|
||||||
depends:
|
depends:
|
||||||
ir
|
ir
|
||||||
res
|
res
|
||||||
base_external_mapping
|
base_external_mapping
|
||||||
xml:
|
xml:
|
||||||
csv_import.xml
|
csv_import.xml
|
||||||
|
message.xml
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
The COPYRIGHT file at the top level of this repository contains the full
|
The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<data>
|
<data>
|
||||||
<xpath expr="/form/field[@name="mapping_lines"]"
|
<xpath expr="/form/field[@name='mapping_lines']" position="after">
|
||||||
position="after">
|
|
||||||
<group col="6" colspan="6" id="csv_import">
|
<group col="6" colspan="6" id="csv_import">
|
||||||
<separator id="csv_import" string="CSV Import" colspan="6"/>
|
<separator id="csv_import" string="CSV Import" colspan="6"/>
|
||||||
<label name="csv_mapping"/>
|
<label name="csv_mapping"/>
|
||||||
|
|
|
@ -3,8 +3,7 @@
|
||||||
The COPYRIGHT file at the top level of this repository contains the full
|
The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<data>
|
<data>
|
||||||
<xpath expr="/tree/field[@name="state"]"
|
<xpath expr="/tree/field[@name='state']" position="after">
|
||||||
position="after">
|
|
||||||
<field name="csv_mapping"/>
|
<field name="csv_mapping"/>
|
||||||
<field name="csv_rel_field"/>
|
<field name="csv_rel_field"/>
|
||||||
</xpath>
|
</xpath>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- This file is part of csv_import module for Tryton.
|
<!-- This file is part of csv_import module for Tryton.
|
||||||
The COPYRIGHT file at the top level of this repository contains the full
|
The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<form string="CSV Archive" col="4">
|
<form col="4">
|
||||||
<label name="profile"/>
|
<label name="profile"/>
|
||||||
<field name="profile"/>
|
<field name="profile"/>
|
||||||
<label name="date_archive"/>
|
<label name="date_archive"/>
|
||||||
|
@ -14,13 +14,9 @@ copyright notices and license terms. -->
|
||||||
<separator name="logs" colspan="4"/>
|
<separator name="logs" colspan="4"/>
|
||||||
<field name="logs" colspan="4"/>
|
<field name="logs" colspan="4"/>
|
||||||
<group col="4" colspan="4" id="csv_buttons">
|
<group col="4" colspan="4" id="csv_buttons">
|
||||||
<button name="cancel"
|
<button name="cancel" icon="tryton-cancel"/>
|
||||||
string="Cancel Import Data from CSV"
|
<button name="draft"/>
|
||||||
icon="tryton-cancel"/>
|
<button name="import_csv" icon="tryton-go-next"/>
|
||||||
<button name="draft" string="Draft"/>
|
|
||||||
<button name="import_csv"
|
|
||||||
string="Import Data from CSV"
|
|
||||||
icon="tryton-go-next"/>
|
|
||||||
</group>
|
</group>
|
||||||
<group col="4" colspan="4" id="states">
|
<group col="4" colspan="4" id="states">
|
||||||
<label name="state"/>
|
<label name="state"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- This file is part of csv_field module for Tryton.
|
<!-- This file is part of csv_field module for Tryton.
|
||||||
The COPYRIGHT file at the top level of this repository contains the full
|
The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<tree string="CSV Archive">
|
<tree>
|
||||||
<field name="profile"/>
|
<field name="profile"/>
|
||||||
<field name="date_archive" widget="date"/>
|
<field name="date_archive" widget="date"/>
|
||||||
<field name="date_archive" widget="time" string="Time"/>
|
<field name="date_archive" widget="time" string="Time"/>
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- This file is part of csv_import module for Tryton.
|
<!-- This file is part of csv_import module for Tryton.
|
||||||
The COPYRIGHT file at the top level of this repository contains the full
|
The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<form string="CSV Import">
|
<form>
|
||||||
<label name="name"/>
|
<label name="name"/>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<notebook colspan="4">
|
<notebook colspan="4">
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
<!-- This file is part of csv_import module for Tryton.
|
<!-- This file is part of csv_import module for Tryton.
|
||||||
The COPYRIGHT file at the top level of this repository contains the full
|
The COPYRIGHT file at the top level of this repository contains the full
|
||||||
copyright notices and license terms. -->
|
copyright notices and license terms. -->
|
||||||
<tree string="CSV Profiles">
|
<tree>
|
||||||
<field name="name"/>
|
<field name="name"/>
|
||||||
<field name="model"/>
|
<field name="model"/>
|
||||||
<field name="create_record"/>
|
<field name="create_record"/>
|
||||||
|
|
Loading…
Reference in New Issue