diff --git a/rattail/batches.py b/rattail/batches.py index fac796ed4733a87bbfb3f7aa5ec29fb93d1d5172..d19c3a6483a7d54ef775c8529decae3eb263c3b3 100644 --- a/rattail/batches.py +++ b/rattail/batches.py @@ -147,9 +147,14 @@ class RattailBatchTerminal(BatchTerminal): } target_columns = { + 'DEPT_DCT': [ + 'F03', + 'F238', + ], 'ITEM_DCT': [ 'F01', 'F02', + 'F155', ], } @@ -178,22 +183,53 @@ class RattailBatchTerminal(BatchTerminal): # return batch - def execute_batch(self, batch): - """ - Executes ``batch``, which should be a :class:`rattail.Batch` instance. - """ + def add_departments(self, session, batch): + for row in batch.provide_rows(): + dept = rattail.Department() + dept.number = row.F03 + dept.name = row.F238 + session.add(dept) + session.flush() - assert batch.action_type == rattail.BATCH_ADD - assert batch.dictionary.name == 'ITEM_DCT' + def add_products(self, session, batch): + q = session.query(rattail.Brand) + brands = {} + for brand in q: + brands[brand.name] = brand - session = object_session(batch) for row in batch.provide_rows(): + if row.F155 in brands: + brand = brands[row.F155] + else: + brand = rattail.Brand(name=row.F155) + session.add(brand) + session.flush() + brands[brand.name] = brand prod = rattail.Product() prod.upc = row.F01 prod.description = row.F02 + prod.brand = brand session.add(prod) session.flush() + def execute_batch(self, batch): + """ + Executes ``batch``, which should be a :class:`rattail.Batch` instance. + """ + + session = object_session(batch) + + if batch.action_type == rattail.BATCH_ADD: + + if batch.dictionary.name == 'DEPT_DCT': + self.add_departments(session, batch) + return + if batch.dictionary.name == 'ITEM_DCT': + self.add_products(session, batch) + return + + assert False, "FIXME" + # def make_batch(source, elements, session, batch_id=None, **kwargs): # """ diff --git a/rattail/db.py b/rattail/db.py index 53275c8153311eddb5d50cba95a3edbf389e91ac..1d100fe427bd335d79d70db397bcd95aed561da5 100644 --- a/rattail/db.py +++ b/rattail/db.py @@ -41,6 +41,9 @@ def init_database(session): columns = [ ('F01', 'UPC', 'GPC(14)'), ('F02', 'Description', 'CHAR(20)'), + ('F03', 'Department Number', 'NUMBER(4,0)'), + ('F155', 'Brand', 'CHAR(30)'), + ('F238', 'Department Name', 'CHAR(30)'), ] for name, disp, dtype in columns: @@ -49,16 +52,20 @@ def init_database(session): session.flush() dictionaries = [ - # ('CLASS_GROUP', 'Scale Class / Group', []), - # ('DEPT_DCT', 'Department', []), - # ('FCOST_DCT', 'Future Cost', []), - # ('FSPRICE_DCT', 'Future Sale Price', []), + ('DEPT_DCT', 'Department', [ + ('F03', True), + 'F238', + ]), ('ITEM_DCT', 'Product', [ ('F01', True), 'F02', + 'F155', ]), - # ('NUTRITION', 'Scale Nutrition', []), # ('PRICE_DCT', 'Price', []), + # ('FCOST_DCT', 'Future Cost', []), + # ('FSPRICE_DCT', 'Future Sale Price', []), + # ('CLASS_GROUP', 'Scale Class / Group', []), + # ('NUTRITION', 'Scale Nutrition', []), # ('SCALE_TEXT', 'Scale Text', []), # ('VENDOR_DCT', 'Vendor', []), ] @@ -73,6 +80,6 @@ def init_database(session): q = q.filter(rattail.SilColumn.sil_name == col) col = q.one() bd.columns.append( - rattail.BatchDictionaryColumn(column=col, key=key)) + rattail.BatchDictionaryColumn(sil_column=col, key=key)) session.add(bd) session.flush() diff --git a/rattail/model.py b/rattail/model.py index e31bec8f0f7ed2add982ff4e47b758da60a7cf45..552473b61c43d5ecfa74faa4e2f4afc040e377f8 100644 --- a/rattail/model.py +++ b/rattail/model.py @@ -29,7 +29,7 @@ import re from sqlalchemy import (Column, String, Integer, Date, DateTime, - Boolean, Text, ForeignKey, BigInteger) + Boolean, Text, ForeignKey, BigInteger, Numeric) from sqlalchemy.orm import relationship, object_session import edbob @@ -37,10 +37,10 @@ from edbob.db.model import Base, uuid_column __all__ = ['SilColumn', 'BatchDictionaryColumn', 'BatchDictionary', - 'BatchTerminalSourceColumn', 'BatchTerminalTargetColumn', - 'BatchTerminal', 'BatchColumn', 'Batch', 'Brand', 'Product'] + 'BatchTerminalColumn', 'BatchTerminal', 'BatchColumn', + 'Batch', 'Brand', 'Department', 'Product'] -sil_type_pattern = re.compile(r'^(CHAR)\((\d+)\)$') +sil_type_pattern = re.compile(r'^(CHAR|NUMBER)\((\d+(?:\,\d+)?)\)$') class SilColumn(Base): @@ -71,16 +71,16 @@ class BatchDictionaryColumn(Base): uuid = uuid_column() dictionary_uuid = Column(String(32), ForeignKey('batch_dictionaries.uuid')) - column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) + sil_column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) key = Column(Boolean) - column = relationship(SilColumn) + sil_column = relationship(SilColumn) def __repr__(self): - return "" % self.column + return "" % self.sil_column def __str__(self): - return str(self.column or '') + return str(self.sil_column or '') class BatchDictionary(Base): @@ -106,52 +106,30 @@ class BatchDictionary(Base): return str(self.description or '') -class BatchTerminalSourceColumn(Base): +class BatchTerminalColumn(Base): """ - Represents a "source column" supported by a :class:`BatchTerminal`. + Represents a column supported by a :class:`BatchTerminal`. """ - __tablename__ = 'batch_terminal_source_columns' + __tablename__ = 'batch_terminal_columns' uuid = uuid_column() terminal_uuid = Column(String(32), ForeignKey('batch_terminals.uuid')) dictionary_uuid = Column(String(32), ForeignKey('batch_dictionaries.uuid')) - column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) - ordinal = Column(Integer) - - dictionary = relationship(BatchDictionary) - column = relationship(SilColumn) - - def __repr__(self): - return "" % ( - self.terminal, self.dictionary, self.name) - - def __str__(self): - return str(self.name or '') - - -class BatchTerminalTargetColumn(Base): - """ - Represents a "target column" supported by a :class:`BatchTerminal`. - """ - - __tablename__ = 'batch_terminal_target_columns' - - uuid = uuid_column() - terminal_uuid = Column(String(32), ForeignKey('batch_terminals.uuid')) - dictionary_uuid = Column(String(32), ForeignKey('batch_dictionaries.uuid')) - column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) + sil_column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) ordinal = Column(Integer) + source = Column(Boolean) + target = Column(Boolean) dictionary = relationship(BatchDictionary) - column = relationship(SilColumn) + sil_column = relationship(SilColumn) def __repr__(self): - return "" % ( - self.terminal, self.dictionary, self.name) + return "" % ( + self.terminal, self.dictionary, self.sil_column) def __str__(self): - return str(self.name or '') + return str(self.sil_column or '') class BatchTerminal(Base): @@ -171,11 +149,8 @@ class BatchTerminal(Base): source_kwargs = Column(Text) target_kwargs = Column(Text) - source_columns = relationship( - BatchTerminalSourceColumn, - backref='terminal') - target_columns = relationship( - BatchTerminalTargetColumn, + columns = relationship( + BatchTerminalColumn, backref='terminal') _terminal = 'not_got_yet' @@ -186,6 +161,11 @@ class BatchTerminal(Base): def __str__(self): return str(self.description or '') + def source_columns(self, dictionary): + for col in self.columns: + if col.dictionary is dictionary: + yield col + def get_terminal(self): """ Returns the :class:`rattail.batches.BatchTerminal` instance which is @@ -211,11 +191,11 @@ class BatchColumn(Base): uuid = uuid_column() batch_uuid = Column(String(32), ForeignKey('batches.uuid')) ordinal = Column(Integer) - column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) + sil_column_uuid = Column(String(32), ForeignKey('sil_columns.uuid')) source_uuid = Column(String(32), ForeignKey('batch_terminals.uuid')) targeted = Column(Boolean) - column = relationship(SilColumn) + sil_column = relationship(SilColumn) source = relationship( BatchTerminal, @@ -224,7 +204,7 @@ class BatchColumn(Base): ) def __repr__(self): - return "" % (self.batch, self.column) + return "" % (self.batch, self.sil_column) # def get_sil_column(name): @@ -265,8 +245,18 @@ def get_sil_type(data_type): m = sil_type_pattern.match(data_type) if m: data_type, precision = m.groups() + if precision.isdigit(): + precision = int(precision) + scale = 0 + else: + precision, scale = precision.split(',') + precision = int(precision) + scale = int(scale) if data_type == 'CHAR': - return String(int(precision)) + assert not scale, "FIXME" + return String(precision) + if data_type == 'NUMBER': + return Numeric(precision, scale) assert False, "FIXME" @@ -418,7 +408,7 @@ class Batch(Base): 'uuid': uuid_column(), } for col in self.columns: - kwargs[col.column.sil_name] = Column(get_sil_type(col.column.data_type)) + kwargs[col.sil_column.sil_name] = Column(get_sil_type(col.sil_column.data_type)) self._row_classes[self.uuid] = type('BatchRow', (Base,), kwargs) return self._row_classes[self.uuid] @@ -512,6 +502,30 @@ class Brand(Base): uuid = uuid_column() name = Column(String(100)) + def __repr__(self): + return "" % self.name + + def __str__(self): + return str(self.name or '') + + +class Department(Base): + """ + Represents an organizational department. + """ + + __tablename__ = 'departments' + + uuid = uuid_column() + number = Column(Integer) + name = Column(String(30)) + + def __repr__(self): + return "" % self.name + + def __str__(self): + return str(self.name) + class Product(Base): """