first push message
This commit is contained in:
@@ -0,0 +1 @@
|
||||
from . import ks_gantt_view_base_import
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,181 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
import tempfile
|
||||
import binascii
|
||||
import datetime
|
||||
import logging
|
||||
import json
|
||||
|
||||
import dateutil.parser
|
||||
import pandas as pd
|
||||
from odoo import models, fields, _
|
||||
from odoo.exceptions import ValidationError, UserError
|
||||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class KsGanttViewBaseImport(models.TransientModel):
|
||||
_name = 'ks.gantt.base.import.wizard'
|
||||
_description = 'Gantt View Import'
|
||||
|
||||
ks_file_type = fields.Selection(
|
||||
selection=[('xlsx', 'Excel'), ('json', 'JSON')],
|
||||
string='File Type',
|
||||
default='xlsx',
|
||||
required=True,
|
||||
)
|
||||
ks_file = fields.Binary(string='Upload File', required=True)
|
||||
|
||||
def ks_import_xlsx_file(self, ks_model):
|
||||
"""Parse an XLSX file and create records in ks_model."""
|
||||
fp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx")
|
||||
fp.write(binascii.a2b_base64(self.ks_file))
|
||||
fp.seek(0)
|
||||
try:
|
||||
df = pd.read_excel(fp.name, engine='openpyxl')
|
||||
except Exception:
|
||||
raise ValidationError(_("File can't be read — please upload a valid Excel file."))
|
||||
|
||||
ks_sheet_columns = df.columns.tolist()
|
||||
ks_model_obj = self.env[ks_model].sudo()
|
||||
|
||||
for row_no in range(df.shape[0]):
|
||||
row = list(df.iloc[row_no])
|
||||
ks_model_write_val = {}
|
||||
|
||||
for index, val in enumerate(ks_sheet_columns):
|
||||
if not ks_model_obj._fields.get(val):
|
||||
raise UserError(
|
||||
_('%s is not present in the %s model') % (val, ks_model)
|
||||
)
|
||||
field = ks_model_obj._fields[val]
|
||||
|
||||
if field.type in ['char', 'selection', 'float', 'integer']:
|
||||
if val == 'name' and field.type == 'char':
|
||||
ks_model_write_val[val] = str(row[index]) + '_copy'
|
||||
else:
|
||||
ks_model_write_val[val] = row[index]
|
||||
|
||||
elif field.type == 'many2one':
|
||||
ks_model_write_val[val] = self.ks_valid_many_to_one_data(
|
||||
field.comodel_name, row[index]
|
||||
)
|
||||
|
||||
elif field.type in ['datetime', 'date']:
|
||||
if row[index]:
|
||||
# Odoo 19: fields.Datetime.from_string removed → use
|
||||
# pd.to_datetime which returns a proper Python datetime.
|
||||
ks_model_write_val[val] = pd.to_datetime(row[index]).to_pydatetime()
|
||||
else:
|
||||
ks_model_write_val[val] = False
|
||||
|
||||
elif field.type == 'boolean':
|
||||
ks_model_write_val[val] = bool(row[index])
|
||||
|
||||
else:
|
||||
_logger.warning(
|
||||
"Field type '%s' is not supported for import.", field.type
|
||||
)
|
||||
|
||||
try:
|
||||
ks_model_obj.create(ks_model_write_val)
|
||||
except Exception as e:
|
||||
error_msg = (e.args[0] if e.args and e.args[0]
|
||||
else _('Some required fields are not available in the file.'))
|
||||
raise UserError(error_msg)
|
||||
|
||||
def ks_import_json_file(self, ks_model, ks_import_fields):
|
||||
"""Parse a JSON export file and create records in ks_model."""
|
||||
fp = tempfile.NamedTemporaryFile(delete=False, suffix=".json")
|
||||
fp.write(binascii.a2b_base64(self.ks_file))
|
||||
fp.seek(0)
|
||||
try:
|
||||
parsed_data = json.load(fp)
|
||||
except Exception:
|
||||
raise ValidationError(_("File can't be read — please upload a valid JSON file."))
|
||||
|
||||
config = parsed_data.get('config', {})
|
||||
task_data_block = (
|
||||
config.get('ks_gantt_task_data', {}).get('data')
|
||||
)
|
||||
if not task_data_block:
|
||||
raise UserError(
|
||||
_('Required data not found in the JSON file. Please upload a correct JSON file.')
|
||||
)
|
||||
|
||||
ks_model_obj = self.env[ks_model].sudo()
|
||||
|
||||
for model_data in task_data_block:
|
||||
if not model_data or 'ks_group_lvl' in model_data:
|
||||
continue
|
||||
|
||||
ks_model_write_val = {}
|
||||
for field_import in ks_import_fields:
|
||||
if not ks_model_obj._fields.get(field_import):
|
||||
raise UserError(
|
||||
_('%s is not present in the %s model') % (field_import, ks_model)
|
||||
)
|
||||
field = ks_model_obj._fields[field_import]
|
||||
|
||||
if field.type in ['char', 'selection', 'float', 'integer']:
|
||||
val = model_data.get(field_import)
|
||||
if field_import == 'name' and field.type == 'char':
|
||||
ks_model_write_val[field_import] = str(val) + '_copy'
|
||||
else:
|
||||
ks_model_write_val[field_import] = val
|
||||
|
||||
elif field.type == 'many2one':
|
||||
raw = model_data.get(field_import) or False
|
||||
ks_model_write_val[field_import] = self.ks_valid_many_to_one_data(
|
||||
field.comodel_name, raw
|
||||
)
|
||||
|
||||
elif field.type in ['datetime', 'date']:
|
||||
raw = model_data.get(field_import)
|
||||
if raw:
|
||||
# Odoo 19: avoid deprecated fields.Datetime.from_string.
|
||||
# Parse with dateutil and normalise to naive UTC datetime.
|
||||
parsed = dateutil.parser.parse(str(raw))
|
||||
naive = datetime.datetime.strftime(
|
||||
parsed.replace(tzinfo=None),
|
||||
'%Y-%m-%d %H:%M:%S',
|
||||
)
|
||||
ks_model_write_val[field_import] = datetime.datetime.strptime(
|
||||
naive, '%Y-%m-%d %H:%M:%S'
|
||||
)
|
||||
else:
|
||||
ks_model_write_val[field_import] = False
|
||||
|
||||
elif field.type == 'boolean':
|
||||
ks_model_write_val[field_import] = bool(model_data.get(field_import))
|
||||
|
||||
else:
|
||||
_logger.warning(
|
||||
"Field type '%s' is not supported for import.", field.type
|
||||
)
|
||||
|
||||
try:
|
||||
ks_model_obj.create(ks_model_write_val)
|
||||
except Exception as e:
|
||||
error_msg = (e.args[0] if e.args and e.args[0]
|
||||
else _('Some required fields are not available in the file.'))
|
||||
raise UserError(error_msg)
|
||||
|
||||
def ks_valid_many_to_one_data(self, comodel, value):
|
||||
"""
|
||||
Resolve a many2one value to a record id, or return False.
|
||||
Accepts an int id, a list [id, ...], or a string 'id,display_name'.
|
||||
"""
|
||||
if not value:
|
||||
return False
|
||||
|
||||
if isinstance(value, list):
|
||||
if not value:
|
||||
return False
|
||||
ks_id = int(value[0])
|
||||
elif isinstance(value, int):
|
||||
ks_id = value
|
||||
else:
|
||||
ks_id = int(str(value).split(',')[0])
|
||||
|
||||
record = self.env[comodel].sudo().search([('id', '=', ks_id)], limit=1)
|
||||
return record.id if record else False
|
||||
Reference in New Issue
Block a user