210 lines
6.5 KiB
Python
210 lines
6.5 KiB
Python
# -*- coding: utf-8 -*-
|
|
# This file is part of the investment-module from m-ds.de for Tryton.
|
|
# The COPYRIGHT file at the top level of this repository contains the
|
|
# full copyright notices and license terms.
|
|
|
|
from io import StringIO
|
|
from datetime import datetime, date
|
|
from decimal import Decimal
|
|
import csv
|
|
from trytond.pool import Pool
|
|
from trytond.model import ModelView, fields
|
|
from trytond.wizard import Wizard, StateTransition, StateView, Button
|
|
from trytond.transaction import Transaction
|
|
from trytond.exceptions import UserError
|
|
from trytond.i18n import gettext
|
|
|
|
|
|
sel_dec_divider = [
|
|
(',', ','),
|
|
('.', '.'),
|
|
]
|
|
|
|
sel_date_fmt = [
|
|
('%d.%m.%Y', 'dd.mm.yyyy'),
|
|
('%Y-%m-%d', 'yyyy-mm-dd'),
|
|
('%m/%d/%Y', 'mm/dd/yyyy'),
|
|
]
|
|
|
|
sel_field_delimiter = [
|
|
(';', ';'),
|
|
(',', ','),
|
|
]
|
|
|
|
|
|
class ImportWizardStart(ModelView):
|
|
'Import CSV-File'
|
|
__name__ = 'investment.imp_wiz.start'
|
|
|
|
asset = fields.Many2One(
|
|
string='Asset', readonly=True, model_name='investment.asset')
|
|
file_ = fields.Binary(string="CSV-File", required=True)
|
|
dec_divider = fields.Selection(
|
|
string='Decimal divider', required=True, selection=sel_dec_divider)
|
|
date_fmt = fields.Selection(
|
|
string='Date format', required=True, selection=sel_date_fmt)
|
|
field_delimiter = fields.Selection(
|
|
string='Field delimiter', required=True, selection=sel_field_delimiter)
|
|
|
|
# end ImportWizardStart
|
|
|
|
|
|
class ImportWizard(Wizard):
|
|
'Import CSV-File'
|
|
__name__ = 'investment.imp_wiz'
|
|
|
|
start_state = 'start'
|
|
start = StateView(
|
|
model_name='investment.imp_wiz.start',
|
|
view='investment.imp_wiz_start_form',
|
|
buttons=[
|
|
Button(string='Cancel', state='end', icon='tryton-cancel'),
|
|
Button(
|
|
string='Import File', state='importf',
|
|
icon='tryton-import', default=True),
|
|
])
|
|
importf = StateTransition()
|
|
|
|
def default_start(self, fields):
|
|
""" show asset
|
|
"""
|
|
context = Transaction().context
|
|
|
|
values = {
|
|
'dec_divider': ',',
|
|
'date_fmt': '%d.%m.%Y',
|
|
'field_delimiter': ';',
|
|
}
|
|
values['asset'] = context.get('active_id', None)
|
|
return values
|
|
|
|
def transition_importf(self):
|
|
""" read file, import
|
|
"""
|
|
pool = Pool()
|
|
ImportWiz = pool.get('investment.imp_wiz', type='wizard')
|
|
|
|
if self.start.file_ is not None:
|
|
(lines, max_date, min_date) = ImportWiz.read_csv_file(
|
|
self.start.file_.decode('utf8'),
|
|
dec_divider=self.start.dec_divider,
|
|
date_fmt=self.start.date_fmt,
|
|
delimiter=self.start.field_delimiter)
|
|
|
|
if len(lines) > 0:
|
|
ImportWiz.upload_rates(
|
|
self.start.asset,
|
|
lines, min_date, max_date)
|
|
return 'end'
|
|
|
|
@classmethod
|
|
def upload_rates(cls, asset, rates_list, min_date, max_date):
|
|
""" upload new rates to asset
|
|
"""
|
|
Rate = Pool().get('investment.rate')
|
|
|
|
# get rate in date-range
|
|
rates = Rate.search([
|
|
('asset.id', '=', asset.id),
|
|
('date', '>=', min_date),
|
|
('date', '<=', max_date),
|
|
])
|
|
existing_dates = [x.date for x in rates]
|
|
done_dates = []
|
|
|
|
to_create = []
|
|
for rate in rates_list:
|
|
if rate['date'] in existing_dates:
|
|
continue
|
|
if rate['date'] in done_dates:
|
|
continue
|
|
|
|
to_create.append({
|
|
'asset': asset.id,
|
|
'date': rate['date'],
|
|
'rate': rate['rate'],
|
|
})
|
|
done_dates.append(rate['date'])
|
|
|
|
if len(to_create) > 0:
|
|
Rate.create(to_create)
|
|
|
|
@classmethod
|
|
def read_csv_file(cls, file_content, dec_divider, date_fmt, delimiter):
|
|
""" read file-content from csv
|
|
"""
|
|
result = []
|
|
|
|
del_chars = ['.', ',']
|
|
del_chars.remove(dec_divider)
|
|
min_date = None
|
|
max_date = None
|
|
min_rate = None
|
|
max_rate = None
|
|
|
|
with StringIO(file_content) as fhdl:
|
|
csv_lines = csv.DictReader(
|
|
fhdl,
|
|
fieldnames=['date', 'rate'],
|
|
dialect='excel',
|
|
delimiter=delimiter)
|
|
|
|
for line in csv_lines:
|
|
# skip first line
|
|
if line.get('date', '') == 'date':
|
|
continue
|
|
|
|
try:
|
|
date_val = datetime.strptime(
|
|
line.get('date', None).strip(), date_fmt).date()
|
|
except Exception:
|
|
raise UserError(gettext(
|
|
'investment.msg_import_err_date',
|
|
datefmt=date_fmt,
|
|
colnr='1',
|
|
))
|
|
try:
|
|
rate_val = line.get('rate', None).replace(
|
|
del_chars[0], '').strip()
|
|
rate_val = Decimal(rate_val.replace(dec_divider, '.'))
|
|
except Exception:
|
|
raise UserError(gettext(
|
|
'investment.msg_import_err_date',
|
|
datefmt='dd%sdd' % dec_divider,
|
|
colnr='2'))
|
|
|
|
if isinstance(date_val, date) and isinstance(rate_val, Decimal):
|
|
result.append({'date': date_val, 'rate': rate_val})
|
|
|
|
# date range
|
|
if max_date is None:
|
|
max_date = date_val
|
|
else:
|
|
if max_date < date_val:
|
|
max_date = date_val
|
|
|
|
if min_date is None:
|
|
min_date = date_val
|
|
else:
|
|
if min_date > date_val:
|
|
min_date = date_val
|
|
|
|
# rate range
|
|
if max_rate is None:
|
|
max_rate = rate_val
|
|
else:
|
|
if max_rate < rate_val:
|
|
max_rate = rate_val
|
|
|
|
if min_rate is None:
|
|
min_rate = rate_val
|
|
else:
|
|
if min_rate > rate_val:
|
|
min_rate = rate_val
|
|
else:
|
|
raise UserError(gettext(
|
|
'investment.msg_err_unknown_content',
|
|
linetxt=line))
|
|
return (result, max_date, min_date)
|
|
|
|
# end ImportWizard
|