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
This commit is contained in:
parent
76b8856854
commit
827d8cf924
|
@ -31,6 +31,7 @@ import logging
|
||||||
from rattail.db import Session, model
|
from rattail.db import Session, model
|
||||||
from rattail.config import parse_bool
|
from rattail.config import parse_bool
|
||||||
from rattail.filemon import Action
|
from rattail.filemon import Action
|
||||||
|
from rattail.time import make_utc
|
||||||
from rattail.util import load_object
|
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.
|
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.
|
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
|
: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
|
auto-deleted in the event that it has no data rows, after being
|
||||||
initially populated from the given data file.
|
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:
|
if not handler:
|
||||||
assert batch_type
|
assert batch_type
|
||||||
handler = self.config.require('rattail.batch', '{}.handler'.format(batch_type))
|
handler = self.config.require('rattail.batch', '{}.handler'.format(batch_type))
|
||||||
handler = load_object(handler)(self.config)
|
handler = load_object(handler)(self.config)
|
||||||
session = Session()
|
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)
|
batch = handler.make_batch(session, **kwargs)
|
||||||
handler.set_input_file(batch, path)
|
handler.set_input_file(batch, path)
|
||||||
handler.populate(batch)
|
handler.populate(batch)
|
||||||
|
@ -79,6 +89,12 @@ class MakeBatch(Action):
|
||||||
log.debug("auto-deleting empty '{}' batch: {}".format(handler.batch_key, batch))
|
log.debug("auto-deleting empty '{}' batch: {}".format(handler.batch_key, batch))
|
||||||
batch.delete_data(self.config)
|
batch.delete_data(self.config)
|
||||||
session.delete(batch)
|
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.commit()
|
||||||
session.close()
|
session.close()
|
||||||
|
|
|
@ -308,6 +308,13 @@ class BatchHandler(object):
|
||||||
return True
|
return True
|
||||||
return not bool(batch.executed)
|
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):
|
def execute(self, batch, progress=None, **kwargs):
|
||||||
"""
|
"""
|
||||||
Execute the given batch, with given progress and kwargs. That is an
|
Execute the given batch, with given progress and kwargs. That is an
|
||||||
|
|
|
@ -37,6 +37,7 @@ from rattail import enum
|
||||||
from rattail.db import model, api
|
from rattail.db import model, api
|
||||||
from rattail.gpc import GPC
|
from rattail.gpc import GPC
|
||||||
from rattail.batch import BatchHandler
|
from rattail.batch import BatchHandler
|
||||||
|
from rattail.csvutil import UnicodeDictReader
|
||||||
from rattail.util import progress_loop
|
from rattail.util import progress_loop
|
||||||
from rattail.time import make_utc
|
from rattail.time import make_utc
|
||||||
from rattail.config import parse_bool
|
from rattail.config import parse_bool
|
||||||
|
@ -67,6 +68,15 @@ class LabelBatchHandler(BatchHandler):
|
||||||
self.calc_check_digit = parse_bool(self.calc_check_digit)
|
self.calc_check_digit = parse_bool(self.calc_check_digit)
|
||||||
return super(LabelBatchHandler, self).make_batch(session, progress, **kwargs)
|
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):
|
def populate(self, batch, progress=None):
|
||||||
"""
|
"""
|
||||||
Pre-fill batch with row data from handheld batch, etc.
|
Pre-fill batch with row data from handheld batch, etc.
|
||||||
|
@ -118,13 +128,16 @@ class LabelBatchHandler(BatchHandler):
|
||||||
if self.skip_first_line:
|
if self.skip_first_line:
|
||||||
f.readline()
|
f.readline()
|
||||||
reader = csv.reader(f)
|
reader = csv.reader(f)
|
||||||
|
data = [{'upc': row[0]} for row in reader]
|
||||||
|
else:
|
||||||
|
reader = UnicodeDictReader(f)
|
||||||
data = list(reader)
|
data = list(reader)
|
||||||
|
|
||||||
products = []
|
products = []
|
||||||
session = orm.object_session(batch)
|
session = orm.object_session(batch)
|
||||||
|
|
||||||
def append(entry, i):
|
def append(entry, i):
|
||||||
upc = entry[0].strip()
|
upc = entry['upc'].strip()
|
||||||
if upc:
|
if upc:
|
||||||
upc = GPC(upc, calc_check_digit=self.calc_check_digit)
|
upc = GPC(upc, calc_check_digit=self.calc_check_digit)
|
||||||
product = api.get_product_by_upc(session, upc)
|
product = api.get_product_by_upc(session, upc)
|
||||||
|
@ -133,8 +146,8 @@ class LabelBatchHandler(BatchHandler):
|
||||||
else:
|
else:
|
||||||
log.warning("product not found: {}".format(upc))
|
log.warning("product not found: {}".format(upc))
|
||||||
|
|
||||||
if self.progress_loop(append, data, progress,
|
self.progress_loop(append, data, progress,
|
||||||
message="Reading data from CSV file"):
|
message="Reading data from CSV file")
|
||||||
return products
|
return products
|
||||||
|
|
||||||
def get_label_profile(self, session):
|
def get_label_profile(self, session):
|
||||||
|
|
Loading…
Reference in a new issue