investment/import_wiz.py

212 lines
6.5 KiB
Python
Raw Normal View History

2022-12-19 20:13:32 +00:00
# -*- coding: utf-8 -*-
# This file is part of the investment-module from m-ds.de for Tryton.
2022-12-19 20:13:32 +00:00
# The COPYRIGHT file at the top level of this repository contains the
# full copyright notices and license terms.
from io import StringIO
2023-06-07 16:44:53 +00:00
from datetime import datetime, date
2022-12-19 20:13:32 +00:00
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'
2023-06-07 16:44:53 +00:00
asset = fields.Many2One(
string='Asset', readonly=True, model_name='investment.asset')
2022-12-19 20:13:32 +00:00
file_ = fields.Binary(string="CSV-File", required=True)
2023-06-07 16:44:53 +00:00
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)
2022-12-19 20:13:32 +00:00
# end ImportWizardStart
class ImportWizard(Wizard):
'Import CSV-File'
__name__ = 'investment.imp_wiz'
start_state = 'start'
2023-06-07 16:44:53 +00:00
start = StateView(
model_name='investment.imp_wiz.start',
view='investment.imp_wiz_start_form',
2022-12-19 20:13:32 +00:00
buttons=[
Button(string='Cancel', state='end', icon='tryton-cancel'),
2023-06-07 16:44:53 +00:00
Button(
string='Import File', state='importf',
icon='tryton-import', default=True),
2022-12-19 20:13:32 +00:00
])
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')
2024-01-21 18:37:48 +00:00
if self.start.file_:
2022-12-19 20:13:32 +00:00
(lines, max_date, min_date) = ImportWiz.read_csv_file(
2024-01-21 18:37:48 +00:00
self.start.file_.decode('utf8'),
dec_divider=self.start.dec_divider,
date_fmt=self.start.date_fmt,
delimiter=self.start.field_delimiter)
2022-12-19 20:13:32 +00:00
2024-01-21 18:37:48 +00:00
if lines:
2022-12-19 20:13:32 +00:00
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:
2023-06-07 16:44:53 +00:00
csv_lines = csv.DictReader(
fhdl,
fieldnames=['date', 'rate'],
dialect='excel',
delimiter=delimiter)
2022-12-19 20:13:32 +00:00
for line in csv_lines:
# skip first line
if line.get('date', '') == 'date':
continue
2023-06-07 16:44:53 +00:00
try:
date_val = datetime.strptime(
line.get('date', None).strip(), date_fmt).date()
except Exception:
2022-12-19 20:13:32 +00:00
raise UserError(gettext(
'investment.msg_import_err_date',
2023-06-07 16:44:53 +00:00
datefmt=date_fmt,
colnr='1',
2022-12-19 20:13:32 +00:00
))
2023-06-07 16:44:53 +00:00
try:
rate_val = line.get('rate', None).replace(
del_chars[0], '').strip()
2022-12-19 20:13:32 +00:00
rate_val = Decimal(rate_val.replace(dec_divider, '.'))
2023-06-07 16:44:53 +00:00
except Exception:
2022-12-19 20:13:32 +00:00
raise UserError(gettext(
'investment.msg_import_err_date',
2023-06-07 16:44:53 +00:00
datefmt='dd%sdd' % dec_divider,
colnr='2'))
2022-12-19 20:13:32 +00:00
2023-12-01 12:29:46 +00:00
if isinstance(date_val, date) and isinstance(
rate_val, Decimal):
2022-12-19 20:13:32 +00:00
result.append({'date': date_val, 'rate': rate_val})
# date range
if max_date is None:
max_date = date_val
2023-06-07 16:44:53 +00:00
else:
2022-12-19 20:13:32 +00:00
if max_date < date_val:
max_date = date_val
if min_date is None:
min_date = date_val
2023-06-07 16:44:53 +00:00
else:
2022-12-19 20:13:32 +00:00
if min_date > date_val:
min_date = date_val
# rate range
if max_rate is None:
max_rate = rate_val
2023-06-07 16:44:53 +00:00
else:
2022-12-19 20:13:32 +00:00
if max_rate < rate_val:
max_rate = rate_val
if min_rate is None:
min_rate = rate_val
2023-06-07 16:44:53 +00:00
else:
2022-12-19 20:13:32 +00:00
if min_rate > rate_val:
min_rate = rate_val
2023-06-07 16:44:53 +00:00
else:
2022-12-19 20:13:32 +00:00
raise UserError(gettext(
'investment.msg_err_unknown_content',
2023-06-07 16:44:53 +00:00
linetxt=line))
2022-12-19 20:13:32 +00:00
return (result, max_date, min_date)
# end ImportWizard