Add basic support for importing from CSV to office_arch.bigArchive

still requires CSV file header column names to match the SA model,
and *not* the underlying mysql names
This commit is contained in:
Lance Edgar 2024-05-08 14:54:16 -05:00
parent db8f872eef
commit 8eb097867e
3 changed files with 48 additions and 44 deletions

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar # Copyright © 2010-2024 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -33,7 +33,6 @@ from requests.auth import HTTPDigestAuth
from rattail import commands from rattail import commands
from rattail_corepos import __version__ from rattail_corepos import __version__
from rattail.util import load_object
from rattail_corepos.corepos.office.util import get_fannie_config_value, get_blueline_template, make_blueline from rattail_corepos.corepos.office.util import get_fannie_config_value, get_blueline_template, make_blueline
from rattail_corepos.corepos.util import get_core_members from rattail_corepos.corepos.util import get_core_members
from rattail_corepos.config import core_office_url from rattail_corepos.config import core_office_url
@ -223,7 +222,7 @@ class CoreDBImportSubcommand(commands.ImportSubcommand):
super().add_parser_args(parser) super().add_parser_args(parser)
parser.add_argument('--corepos-dbtype', metavar='TYPE', default='office_op', parser.add_argument('--corepos-dbtype', metavar='TYPE', default='office_op',
choices=['office_op', 'office_trans'], choices=['office_op', 'office_trans', 'office_arch'],
help="Config *type* for CORE-POS database engine to which data " help="Config *type* for CORE-POS database engine to which data "
"should be written. Default type is 'office_op' - this determines " "should be written. Default type is 'office_op' - this determines "
"which config section is used with regard to the --corepos-dbkey arg.") "which config section is used with regard to the --corepos-dbkey arg.")
@ -234,6 +233,7 @@ class CoreDBImportSubcommand(commands.ImportSubcommand):
"determiend by the --corpos-dbtype arg.") "determiend by the --corpos-dbtype arg.")
def get_handler_kwargs(self, **kwargs): def get_handler_kwargs(self, **kwargs):
kwargs = super().get_handler_kwargs(**kwargs)
if 'args' in kwargs: if 'args' in kwargs:
kwargs['corepos_dbtype'] = kwargs['args'].corepos_dbtype kwargs['corepos_dbtype'] = kwargs['args'].corepos_dbtype
kwargs['corepos_dbkey'] = kwargs['args'].corepos_dbkey kwargs['corepos_dbkey'] = kwargs['args'].corepos_dbkey
@ -250,7 +250,7 @@ class ExportLaneOp(commands.ImportSubcommand):
default_dbkey = 'default' default_dbkey = 'default'
def add_parser_args(self, parser): def add_parser_args(self, parser):
super(ExportLaneOp, self).add_parser_args(parser) super().add_parser_args(parser)
parser.add_argument('--dbkey', metavar='KEY', default=self.default_dbkey, parser.add_argument('--dbkey', metavar='KEY', default=self.default_dbkey,
help="Config key for database engine to be used as the " help="Config key for database engine to be used as the "
"\"target\" CORE Lane DB, i.e. where data will be " "\"target\" CORE Lane DB, i.e. where data will be "
@ -290,31 +290,14 @@ class ExportCSV(commands.ExportFileSubcommand):
handler_key = 'to_csv.from_corepos_db_office_op.export' handler_key = 'to_csv.from_corepos_db_office_op.export'
class ImportCSV(commands.ImportFileSubcommand): class ImportCSV(commands.ImportFileSubcommand, CoreDBImportSubcommand):
""" """
Import data from CSV to CORE Office "op" DB Import data from CSV to a CORE Office DB
""" """
name = 'import-csv' name = 'import-csv'
description = __doc__.strip() description = __doc__.strip()
handler_key = 'to_corepos_db_office_op.from_csv.import' handler_key = 'to_corepos_db_office_op.from_csv.import'
def add_parser_args(self, parser):
super().add_parser_args(parser)
parser.add_argument('--dbkey', metavar='KEY', default='default',
help="Config key for database engine to be used as the \"target\" "
"CORE DB, i.e. where data will be imported *to*. This key must be "
"defined in the [corepos.db.office_op] section of your config file.")
def get_handler_kwargs(self, **kwargs):
kwargs = super().get_handler_kwargs(**kwargs)
if 'args' in kwargs:
args = kwargs['args']
kwargs['dbkey'] = args.dbkey
return kwargs
class ImportSelf(commands.ImportSubcommand): class ImportSelf(commands.ImportSubcommand):
""" """

View file

@ -2,7 +2,7 @@
################################################################################ ################################################################################
# #
# Rattail -- Retail Software Framework # Rattail -- Retail Software Framework
# Copyright © 2010-2023 Lance Edgar # Copyright © 2010-2024 Lance Edgar
# #
# This file is part of Rattail. # This file is part of Rattail.
# #
@ -24,8 +24,6 @@
CSV -> CORE data import CSV -> CORE data import
""" """
from corepos.db.office_op import model as corepos, Session as CoreSession
from rattail.importing.handlers import FromFileHandler from rattail.importing.handlers import FromFileHandler
from rattail.importing.csv import FromCSVToSQLAlchemyMixin from rattail.importing.csv import FromCSVToSQLAlchemyMixin
from rattail_corepos.corepos.office.importing.db.model import ToCoreHandler, ToCore from rattail_corepos.corepos.office.importing.db.model import ToCoreHandler, ToCore
@ -39,10 +37,20 @@ class FromCSVToCore(FromCSVToSQLAlchemyMixin, FromFileHandler, ToCoreHandler):
ToParent = ToCore ToParent = ToCore
def get_model(self): def get_model(self):
return corepos
def make_session(self): if self.corepos_dbtype == 'office_op':
return CoreSession(bind=self.config.corepos_engines[self.dbkey]) from corepos.db.office_op import model
return model
if self.corepos_dbtype == 'office_trans':
from corepos.db.office_trans import model
return model
if self.corepos_dbtype == 'office_arch':
from corepos.db.office_arch import model
return model
raise ValueError(f"unknown corepos_dbtype: {self.corepos_dbtype}")
def get_default_keys(self): def get_default_keys(self):
keys = super().get_default_keys() keys = super().get_default_keys()

View file

@ -33,8 +33,8 @@ CORE-POS model importers (direct DB)
import logging import logging
from corepos.db.office_op import model as corepos, Session as CoreSession from corepos.db.office_op import model as corepos
from corepos.db.office_trans import model as coretrans, Session as CoreTransSession from corepos.db.office_trans import model as coretrans
from rattail import importing from rattail import importing
from rattail.importing.handlers import ToSQLAlchemyHandler from rattail.importing.handlers import ToSQLAlchemyHandler
@ -55,19 +55,32 @@ class ToCoreHandler(ToSQLAlchemyHandler):
@property @property
def local_title(self): def local_title(self):
dbtype = 'op' dbtype = '??'
if self.corepos_dbtype == 'office_trans':
if self.corepos_dbtype == 'office_op':
dbtype = 'op'
elif self.corepos_dbtype == 'office_trans':
dbtype = 'trans' dbtype = 'trans'
elif self.corepos_dbtype == 'office_arch':
dbtype = 'arch'
return f"CORE Office (DB '{dbtype}')" return f"CORE Office (DB '{dbtype}')"
def make_session(self): def make_session(self):
# session type depends on the --corepos-dbtype arg if self.corepos_dbtype == 'office_op':
if self.corepos_dbtype == 'office_trans': from corepos.db.office_op import Session
return CoreTransSession(bind=self.config.coretrans_engines[self.corepos_dbkey]) return Session(bind=self.config.core_office_op_engines[self.corepos_dbkey])
# assume office_op by default if self.corepos_dbtype == 'office_trans':
return CoreSession(bind=self.config.corepos_engines[self.corepos_dbkey]) from corepos.db.office_trans import Session
return Session(bind=self.config.core_office_trans_engines[self.corepos_dbkey])
if self.corepos_dbtype == 'office_arch':
from corepos.db.office_arch import Session
return Session(bind=self.config.core_office_arch_engines[self.corepos_dbkey])
raise ValueError(f"unknown corepos_dbtype: {self.corepos_dbtype}")
class ToCore(importing.ToSQLAlchemy): class ToCore(importing.ToSQLAlchemy):
@ -84,7 +97,7 @@ class ToCore(importing.ToSQLAlchemy):
if self.dry_run: if self.dry_run:
return host_data return host_data
return super(ToCore, self).create_object(key, host_data) return super().create_object(key, host_data)
def update_object(self, obj, host_data, **kwargs): def update_object(self, obj, host_data, **kwargs):
@ -95,7 +108,7 @@ class ToCore(importing.ToSQLAlchemy):
if self.dry_run: if self.dry_run:
return obj return obj
return super(ToCore, self).update_object(obj, host_data, **kwargs) return super().update_object(obj, host_data, **kwargs)
def delete_object(self, obj): def delete_object(self, obj):
@ -106,7 +119,7 @@ class ToCore(importing.ToSQLAlchemy):
if self.dry_run: if self.dry_run:
return True return True
return super(ToCore, self).delete_object(obj) return super().delete_object(obj)
class ToCoreTrans(importing.ToSQLAlchemy): class ToCoreTrans(importing.ToSQLAlchemy):
@ -223,14 +236,14 @@ class MemberInfoImporter(ToCore):
@property @property
def supported_fields(self): def supported_fields(self):
fields = list(super(MemberInfoImporter, self).supported_fields) fields = list(super().supported_fields)
fields.append('member_type_id') fields.append('member_type_id')
return fields return fields
def normalize_local_object(self, member): def normalize_local_object(self, member):
data = super(MemberInfoImporter, self).normalize_local_object(member) data = super().normalize_local_object(member)
if self.prefer_local_names_from_custdata and member.customers: if self.prefer_local_names_from_custdata and member.customers:
customer = member.customers[0] customer = member.customers[0]
@ -257,7 +270,7 @@ class MemberInfoImporter(ToCore):
return data return data
def update_object(self, member, host_data, local_data=None, **kwargs): def update_object(self, member, host_data, local_data=None, **kwargs):
member = super(MemberInfoImporter, self).update_object( member = super().update_object(
member, host_data, local_data=local_data, **kwargs) member, host_data, local_data=local_data, **kwargs)
if 'first_name' in self.fields: if 'first_name' in self.fields: