From 2d32439da5f8f28c22a17f70651beca8405407aa 2012-04-16 00:47:26 From: Lance Edgar Date: 2012-04-16 00:47:26 Subject: [PATCH] more batch changes (save point) --- diff --git a/rattail/batches.py b/rattail/batches.py index d19c3a6483a7d54ef775c8529decae3eb263c3b3..6dc0a92d02d72f1956f77491013da5f221870608 100644 --- a/rattail/batches.py +++ b/rattail/batches.py @@ -94,6 +94,15 @@ class BatchTerminal(edbob.Object): def fieldmap_user(self): pass + @requires_impl() + def provide_rows(self, session, rowclass, dictionary, query=None, **kwargs): + """ + Generator which yields (new) batch row instances. This is used to + populate batches. + """ + + raise NotImplementedError + # def get_elements(self, elements, fieldmap, *required): # """ # Returns the proper element list according to current context. @@ -124,21 +133,6 @@ class RattailBatchTerminal(BatchTerminal): name = 'rattail' description = "Rattail (local)" - # source = True - # target = True - - # fieldmap_internal = { - # 'F01' : 'upc', - # 'F02' : 'description', - # 'F4001' : 'description2', - # } - - # fieldmap_user = { - # 'F01' : "UPC", - # 'F02' : "Description", - # 'F4001' : "Description 2", - # } - source_columns = { 'ITEM_DCT': [ 'F01', @@ -154,10 +148,37 @@ class RattailBatchTerminal(BatchTerminal): 'ITEM_DCT': [ 'F01', 'F02', + 'F03', + 'F22', 'F155', ], } + def provide_rows(self, session, rowclass, dictionary, query=None, **kwargs): + + if dictionary.name == 'DEPT_DCT': + if not query: + query = session.query(rattail.Department) + for dept in query: + yield rowclass( + F03=dept.number, + F238=dept.name, + ) + return + + elif dictionary.name == 'ITEM_DCT': + if not query: + query = session.query(rattail.Product) + for product in query: + yield rowclass( + F01=int(product.upc), + F02=product.description[:20], + F155=product.brand.name if product.brand else None, + ) + return + + assert False, "FIXME" + # def import_main_item(self, session, elements=None, progress_factory=None): # """ # Create a main item (ITEM_DCT) batch from current Rattail data. @@ -191,27 +212,141 @@ class RattailBatchTerminal(BatchTerminal): session.add(dept) session.flush() + def add_replace_departments(self, session, batch): + for row in batch.provide_rows(): + q = session.query(rattail.Department) + q = q.filter_by(number=row.F03) + if q.count(): + prods = session.query(rattail.Product) + prods = prods.filter_by(department_uuid=q.first().uuid) + if prods.count(): + prods.update(dict(department_uuid=None), synchronize_session='fetch') + q.delete(synchronize_session=False) + + dept = rattail.Department() + dept.number = row.F03 + dept.name = row.F238 + session.add(dept) + session.flush() + def add_products(self, session, batch): + q = session.query(rattail.Department) + depts = {} + for dept in q: + depts[dept.number] = dept + q = session.query(rattail.Brand) brands = {} for brand in q: brands[brand.name] = brand 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 + dept = None + if row.F03: + if row.F03 in depts: + dept = depts[row.F03] + else: + dept = rattail.Department(number=row.F03) + session.add(dept) + session.flush() + depts[dept.number] = dept + + brand = None + if row.F155: + 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.size = row.F22 + prod.department = dept prod.brand = brand session.add(prod) session.flush() + def add_replace_products(self, session, batch): + q = session.query(rattail.Department) + depts = {} + for dept in q: + depts[dept.number] = dept + + q = session.query(rattail.Brand) + brands = {} + for brand in q: + brands[brand.name] = brand + + products = session.query(rattail.Product) + for row in batch.provide_rows(): + dept = None + if row.F03: + if row.F03 in depts: + dept = depts[row.F03] + else: + dept = rattail.Department(number=row.F03) + session.add(dept) + session.flush() + depts[dept.number] = dept + + brand = None + if row.F155: + 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 + + q = products.filter_by(upc=row.F01) + if q.count(): + q.delete(synchronize_session=False) + + prod = rattail.Product() + prod.upc = row.F01 + prod.description = row.F02 + prod.size = row.F22 + prod.department = dept + prod.brand = brand + session.add(prod) + session.flush() + + def change_departments(self, session, batch): + depts = session.query(rattail.Department) + for row in batch.provide_rows(): + dept = depts.filter_by(number=row.F03).first() + if dept: + dept.name = row.F238 + session.flush() + + def change_products(self, session, batch): + q = session.query(rattail.Department) + depts = {} + for dept in q: + depts[dept.number] = dept + + products = session.query(rattail.Product) + for row in batch.provide_rows(): + prod = products.filter_by(upc=row.F01).first() + if prod: + dept = None + if row.F03: + if row.F03 in depts: + dept = depts[row.F03] + else: + dept = rattail.Department(number=row.F03) + session.add(dept) + session.flush() + depts[dept.number] = dept + prod.dept = dept + prod.size = row.F22 + session.flush() + def execute_batch(self, batch): """ Executes ``batch``, which should be a :class:`rattail.Batch` instance. @@ -228,8 +363,49 @@ class RattailBatchTerminal(BatchTerminal): self.add_products(session, batch) return + if batch.action_type == rattail.BATCH_ADD_REPLACE: + if batch.dictionary.name == 'DEPT_DCT': + return self.add_replace_departments(session, batch) + if batch.dictionary.name == 'ITEM_DCT': + return self.add_replace_products(session, batch) + + if batch.action_type == rattail.BATCH_CHANGE: + + if batch.dictionary.name == 'DEPT_DCT': + self.change_departments(session, batch) + return + + if batch.dictionary.name == 'ITEM_DCT': + return self.change_products(session, batch) + + if batch.action_type == rattail.BATCH_REMOVE: + if batch.dictionary.name == 'DEPT_DCT': + return self.remove_departments(session, batch) + if batch.dictionary.name == 'ITEM_DCT': + return self.remove_products(session, batch) + assert False, "FIXME" + def remove_departments(self, session, batch): + depts = session.query(rattail.Department) + products = session.query(rattail.Product) + for row in batch.provide_rows(): + dept = depts.filter_by(number=row.F03).first() + if dept: + q = products.filter_by(department_uuid=dept.uuid) + if q.count(): + q.update({'department_uuid': None}, synchronize_session=False) + session.delete(dept) + session.flush() + + def remove_products(self, session, batch): + products = session.query(rattail.Product) + for row in batch.provide_rows(): + prod = products.filter_by(upc=row.F01).first() + if prod: + session.delete(prod) + session.flush() + # def make_batch(source, elements, session, batch_id=None, **kwargs): # """ diff --git a/rattail/db.py b/rattail/db.py index 1d100fe427bd335d79d70db397bcd95aed561da5..49eb0d5bb39a9642484b2b1f9d2fff106f4124ef 100644 --- a/rattail/db.py +++ b/rattail/db.py @@ -42,6 +42,7 @@ def init_database(session): ('F01', 'UPC', 'GPC(14)'), ('F02', 'Description', 'CHAR(20)'), ('F03', 'Department Number', 'NUMBER(4,0)'), + ('F22', 'Size', 'CHAR(30)'), ('F155', 'Brand', 'CHAR(30)'), ('F238', 'Department Name', 'CHAR(30)'), ] @@ -59,6 +60,8 @@ def init_database(session): ('ITEM_DCT', 'Product', [ ('F01', True), 'F02', + 'F03', + 'F22', 'F155', ]), # ('PRICE_DCT', 'Price', []), diff --git a/rattail/model.py b/rattail/model.py index 552473b61c43d5ecfa74faa4e2f4afc040e377f8..912f94b0718ec87c0620705db2b86f2fe06189aa 100644 --- a/rattail/model.py +++ b/rattail/model.py @@ -524,7 +524,7 @@ class Department(Base): return "" % self.name def __str__(self): - return str(self.name) + return str(self.name or '') class Product(Base): @@ -536,11 +536,13 @@ class Product(Base): uuid = uuid_column() upc = Column(BigInteger) + department_uuid = Column(String(32), ForeignKey('departments.uuid')) brand_uuid = Column(String(32), ForeignKey('brands.uuid')) description = Column(String(60)) description2 = Column(String(60)) size = Column(String(30)) + department = relationship(Department) brand = relationship(Brand) def __repr__(self):