From 827d8cf9243d9e7de456082432236c0b3da92d16 2017-11-29 18:22:50 From: Lance Edgar Date: 2017-11-29 18:22:50 Subject: [PATCH] Add basic "auto-execute" logic for new batches created via filemon this is for the sake of label batches in particular, when deploying several copies from host to all store nodes --- diff --git a/rattail/batch/filemon.py b/rattail/batch/filemon.py index ed146b712f703ee7fed65acde91b0b712b1079c1..72d802e422be08ef4819ed4f6c2a5e1d39d66324 100644 --- a/rattail/batch/filemon.py +++ b/rattail/batch/filemon.py @@ -31,6 +31,7 @@ import logging from rattail.db import Session, model from rattail.config import parse_bool from rattail.filemon import Action +from rattail.time import make_utc from rattail.util import load_object @@ -43,7 +44,9 @@ class MakeBatch(Action): handles the simple case of creating a batch with a single input data file. """ - def __call__(self, path, batch_type='', handler='', user='', delete_if_empty='false', **kwargs): + def __call__(self, path, batch_type='', handler='', user='', + delete_if_empty='false', auto_execute_allowed='true', + **kwargs): """ Make a batch from the given file path. @@ -61,13 +64,20 @@ class MakeBatch(Action): :param delete_if_empty: Set this to 'true' if you wish the batch to be auto-deleted in the event that it has no data rows, after being initially populated from the given data file. + + :param auto_execute_allowed: Set this to 'false' if you wish to disable + auto-execution of new batches. Default behavior is for the handler + to decide whether each batch is eligible for auto-execution. Note + that it is not possible to "force" auto-execution of a batch; you + may only "allow" or "prevent" it. """ if not handler: assert batch_type handler = self.config.require('rattail.batch', '{}.handler'.format(batch_type)) handler = load_object(handler)(self.config) session = Session() - kwargs['created_by'] = session.query(model.User).filter_by(username=user).one() + user = session.query(model.User).filter_by(username=user).one() + kwargs['created_by'] = user batch = handler.make_batch(session, **kwargs) handler.set_input_file(batch, path) handler.populate(batch) @@ -79,6 +89,12 @@ class MakeBatch(Action): log.debug("auto-deleting empty '{}' batch: {}".format(handler.batch_key, batch)) batch.delete_data(self.config) session.delete(batch) + batch = None + + if batch and parse_bool(auto_execute_allowed) and handler.auto_executable(batch): + handler.execute(batch, user=user) + batch.executed = make_utc() + batch.executed_by = user session.commit() session.close() diff --git a/rattail/batch/handlers.py b/rattail/batch/handlers.py index eeb07b632c67a45cdb88f16f0333b207800702af..227c96ee951d57370e100b8a3d8db23047c4eca5 100644 --- a/rattail/batch/handlers.py +++ b/rattail/batch/handlers.py @@ -308,6 +308,13 @@ class BatchHandler(object): return True return not bool(batch.executed) + def auto_executable(self, batch): + """ + Must return a boolean indicating whether the given bath is eligible for + "automatic" execution, i.e. immediately after batch is created. + """ + return False + def execute(self, batch, progress=None, **kwargs): """ Execute the given batch, with given progress and kwargs. That is an diff --git a/rattail/batch/labels.py b/rattail/batch/labels.py index e38dd7185eeac46c7a0aea727fbfd64b4af5f4b0..a14157010ef66ff270c746fd602a734a5ef8a409 100644 --- a/rattail/batch/labels.py +++ b/rattail/batch/labels.py @@ -37,6 +37,7 @@ from rattail import enum from rattail.db import model, api from rattail.gpc import GPC from rattail.batch import BatchHandler +from rattail.csvutil import UnicodeDictReader from rattail.util import progress_loop from rattail.time import make_utc from rattail.config import parse_bool @@ -67,6 +68,15 @@ class LabelBatchHandler(BatchHandler): self.calc_check_digit = parse_bool(self.calc_check_digit) return super(LabelBatchHandler, self).make_batch(session, progress, **kwargs) + def auto_executable(self, batch): + """ + Must return a boolean indicating whether the given bath is eligible for + "automatic" execution, i.e. immediately after batch is created. + """ + if batch.filename and '.autoexecute.' in batch.filename: + return True + return False + def populate(self, batch, progress=None): """ Pre-fill batch with row data from handheld batch, etc. @@ -117,14 +127,17 @@ class LabelBatchHandler(BatchHandler): with open(path, 'rb') as f: if self.skip_first_line: f.readline() - reader = csv.reader(f) - data = list(reader) + reader = csv.reader(f) + data = [{'upc': row[0]} for row in reader] + else: + reader = UnicodeDictReader(f) + data = list(reader) products = [] session = orm.object_session(batch) def append(entry, i): - upc = entry[0].strip() + upc = entry['upc'].strip() if upc: upc = GPC(upc, calc_check_digit=self.calc_check_digit) product = api.get_product_by_upc(session, upc) @@ -133,9 +146,9 @@ class LabelBatchHandler(BatchHandler): else: log.warning("product not found: {}".format(upc)) - if self.progress_loop(append, data, progress, - message="Reading data from CSV file"): - return products + self.progress_loop(append, data, progress, + message="Reading data from CSV file") + return products def get_label_profile(self, session): code = self.config.get('rattail.batch', 'labels.default_code')