Add initial/basic docs for batches
that still needs a lot yet i'm sure, but is a start
This commit is contained in:
parent
da9823324d
commit
e5e642ad8b
|
@ -4,4 +4,5 @@ App Handlers
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
||||||
* Report Handler
|
* :doc:`/data/reports/handler`
|
||||||
|
* :doc:`/data/batch/handlers`
|
||||||
|
|
|
@ -3,4 +3,73 @@
|
||||||
Adding a Custom Batch
|
Adding a Custom Batch
|
||||||
=====================
|
=====================
|
||||||
|
|
||||||
TODO
|
If none of the native batch types fit your needs, you can always add a new one.
|
||||||
|
See :doc:`native` for the list of what's available.
|
||||||
|
|
||||||
|
Adding a new batch type involves 3 steps:
|
||||||
|
|
||||||
|
* add the batch table schema
|
||||||
|
* add the batch handler
|
||||||
|
* add web views for user interaction
|
||||||
|
|
||||||
|
For sake of example here, we'll define a "Please Come Back" batch. The purpose
|
||||||
|
of this batch is to identify members who've not shopped in the store within the
|
||||||
|
last 6 months, and generate custom coupons for each, to encourage them to come
|
||||||
|
back.
|
||||||
|
|
||||||
|
Adding the batch table schema is not much different than adding any other table
|
||||||
|
to the DB; see also :doc:`/data/db/extend`. Note that you should always prefix
|
||||||
|
table names with something unique to your app, and generally speaking the word
|
||||||
|
"batch" should go in there somewhere too. For instance we might call them:
|
||||||
|
|
||||||
|
* ``poser_batch_plzcomeback``
|
||||||
|
* ``poser_batch_plzcomeback_row``
|
||||||
|
|
||||||
|
To add the batch tables, create a new Python module. This would go in
|
||||||
|
``~/src/poser/poser/db/model/batch/plzcomeback.py`` for instance. Within that
|
||||||
|
module you then define the batch table classes. Be sure to also define the
|
||||||
|
``batch_key`` for the main table, which should also get the app-specific
|
||||||
|
prefix, e.g.::
|
||||||
|
|
||||||
|
from rattail.db.model import Base, BatchMixin, BatchRowMixin
|
||||||
|
|
||||||
|
class PleaseComeBack(BatchMixin, Base):
|
||||||
|
__tablename__ = 'poser_batch_plzcomeback'
|
||||||
|
__batchrow_class__ = 'PleaseComeBackRow'
|
||||||
|
batch_key = 'poser_plzcomeback'
|
||||||
|
model_title = "Please Come Back Batch"
|
||||||
|
model_title_plural = "Please Come Back Batches"
|
||||||
|
|
||||||
|
class PleaseComeBackRow(BatchRowMixin, Base):
|
||||||
|
__tablename__ = 'poser_batch_plzcomeback_row'
|
||||||
|
__batch_class__ = PleaseComeBack
|
||||||
|
model_title = "Please Come Back Batch Row"
|
||||||
|
|
||||||
|
To add the batch handler, create a new Python module. This would go in
|
||||||
|
``~/src/poser/poser/batch/plzcomeback.py`` for instance. Within that module
|
||||||
|
you then define the batch handler class. Be sure to tie this back to the main
|
||||||
|
batch table, e.g.::
|
||||||
|
|
||||||
|
from rattail.batch import BatchHandler
|
||||||
|
from poser.db import model
|
||||||
|
|
||||||
|
class PleaseComeBackHandler(BatchHandler):
|
||||||
|
batch_model_class = model.PleaseComeBack
|
||||||
|
|
||||||
|
To add the web views, also create a new Python module. This one would go in
|
||||||
|
``~/src/poser/poser/web/views/batch/plzcomeback.py`` for instance. Within that
|
||||||
|
module you then define the batch master view class. Be sure to tie this back
|
||||||
|
to both the batch and row tables, as well as the handler, e.g.::
|
||||||
|
|
||||||
|
from tailbone.views.batch import BatchMasterView
|
||||||
|
from poser.db import model
|
||||||
|
|
||||||
|
class PleaseComeBackView(BatchMasterView):
|
||||||
|
model_class = model.PleaseComeBack
|
||||||
|
model_row_class = model.PleaseComeBackRow
|
||||||
|
default_handler_spec = 'poser.batch.plzcomeback:PleaseComeBackHandler'
|
||||||
|
route_prefix = 'batch.poser_plzcomeback'
|
||||||
|
url_prefix = '/batches/please-come-back'
|
||||||
|
|
||||||
|
def includeme(config):
|
||||||
|
PleaseComeBackView.defaults(config)
|
||||||
|
|
|
@ -3,4 +3,17 @@
|
||||||
Batch Handlers
|
Batch Handlers
|
||||||
==============
|
==============
|
||||||
|
|
||||||
TODO
|
A "batch handler" contains logic to handle the entire life cycle of a batch.
|
||||||
|
Meaning, the batch handler is what will actually create the batch, and update
|
||||||
|
it per user edits, refresh it etc. and ultimately execute it.
|
||||||
|
|
||||||
|
The UI exposes tools for interacting with the batch but ultimately the handler
|
||||||
|
is what "acts on" the batch based on user input.
|
||||||
|
|
||||||
|
See also :doc:`/base/handlers` for general info on handlers.
|
||||||
|
|
||||||
|
Each type of batch will have precisely one "handler" associated with it. For
|
||||||
|
instance, there is a handler for inventory batches, and another for label
|
||||||
|
batches, etc. The app can override the handler for each batch type, should
|
||||||
|
they need to customize behavior. And of course if the app adds a new batch
|
||||||
|
type then it must also provide a handler for it.
|
||||||
|
|
|
@ -3,4 +3,17 @@
|
||||||
Native Batch Types
|
Native Batch Types
|
||||||
==================
|
==================
|
||||||
|
|
||||||
TODO
|
The following batch types are provided by Rattail itself. Listed below for
|
||||||
|
each is the "batch type key" followed by the descriptive name.
|
||||||
|
|
||||||
|
* ``custorder`` - Customer Order Batch
|
||||||
|
* ``handheld`` - Handheld Batch
|
||||||
|
* ``importer`` - Importer Batch
|
||||||
|
* ``inventory`` - Inventory Batch
|
||||||
|
* ``labels`` - Label Batch
|
||||||
|
* ``newproduct`` - New Product Batch
|
||||||
|
* ``pricing`` - Pricing Batch
|
||||||
|
* ``product`` - Product Batch
|
||||||
|
* ``purchase`` - Purchasing Batch
|
||||||
|
* ``vendor_catalog`` - Vendor Catalog
|
||||||
|
* ``vendor_invoice`` - Vendor Invoice
|
||||||
|
|
|
@ -3,4 +3,140 @@
|
||||||
Overview
|
Overview
|
||||||
==========
|
==========
|
||||||
|
|
||||||
TODO
|
What is a "batch" anyway? That seems to be one of those terms which means
|
||||||
|
something specific in various contexts, but the meanings don't always line up.
|
||||||
|
So let's define it within the Rattail context:
|
||||||
|
|
||||||
|
A "batch" is essentially any set of "pending" data, which must be "reviewed" by
|
||||||
|
an authorized user, and ultimately then "executed" - which causes the data set
|
||||||
|
to go into production by way of updating the various systems involved.
|
||||||
|
|
||||||
|
This means that if you do not specifically need a review/execute workflow, then
|
||||||
|
you probably do not need a batch. It also means that if you *do* need a batch,
|
||||||
|
then you will probably also need a web app, to give the user an actual way to
|
||||||
|
review/execute. (See also :doc:`/web/index`.) Most of the interesting parts
|
||||||
|
of a batch however do belong to the Data Layer, so are described here.
|
||||||
|
|
||||||
|
Beyond that vague conceptual definition, a "batch" in Rattail also implies the
|
||||||
|
use of its "batch framework" - meaning there is a "batch handler" involved etc.
|
||||||
|
|
||||||
|
|
||||||
|
Batch Workflow
|
||||||
|
--------------
|
||||||
|
|
||||||
|
All batches have the following basic workflow in common:
|
||||||
|
|
||||||
|
* batch is created
|
||||||
|
* if applicable, batch is initially populated from some data set
|
||||||
|
* batch is reviewed and if applicable, further modified
|
||||||
|
* batch is executed
|
||||||
|
|
||||||
|
In nearly all cases, the execution requires user intervention, meaning a batch
|
||||||
|
is rarely "created and executed" automatically.
|
||||||
|
|
||||||
|
|
||||||
|
Batch vs. Importer
|
||||||
|
------------------
|
||||||
|
|
||||||
|
Let's say you have a CSV of product data and you wish to import that to the
|
||||||
|
``product`` table of your Rattail DB. Most likely you will use an "importer"
|
||||||
|
only, in which case the data goes straight in.
|
||||||
|
|
||||||
|
But let's say you would prefer to bring the CSV data into a "batch" within the
|
||||||
|
DB instead, and then a user must review and execute that batch in order for the
|
||||||
|
data to truly update your ``product`` table.
|
||||||
|
|
||||||
|
That is the essential difference between an importer and a batch - a batch will
|
||||||
|
always require user intervention (review/execute) whereas a plain importer
|
||||||
|
never does.
|
||||||
|
|
||||||
|
Now, that said, what if you have a working importer but you would rather
|
||||||
|
"interrupt" its process and introduce a user review/execute step before the
|
||||||
|
data was truly imported to the target system? Well that is also possible, and
|
||||||
|
we refer to that as an "importer batch" (creative, I know).
|
||||||
|
|
||||||
|
|
||||||
|
..
|
||||||
|
Batch Archetypes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Here are what you might call "archetypes" for all possible batches.
|
||||||
|
|
||||||
|
|
||||||
|
Batch from Importer
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
aka. "importer batch"
|
||||||
|
|
||||||
|
This is relatively less common in practice, but it serves as a good starting
|
||||||
|
point since we already mentioned it.
|
||||||
|
|
||||||
|
With an "importer batch" the data in question always comes from whatever the
|
||||||
|
"source" (host) is for the importer. The schema for the batch data table is
|
||||||
|
kept dynamic so that "any" importer can produce a batch, theoretically. Each
|
||||||
|
importer run will produce a new table in the DB, columns for which will depend
|
||||||
|
on what was provided by the importer run. Such dynamic batch data tables are
|
||||||
|
kept in a separate (``batch``) schema within the DB, to avoid cluttering the
|
||||||
|
``default`` schema. (Note that the ``batch`` schema must be explicitly created
|
||||||
|
if you need to support importer batches.)
|
||||||
|
|
||||||
|
The execution step for this type of batch is also relatively well-defined.
|
||||||
|
Since the batch itself is merely "pausing" the processing which the importer
|
||||||
|
normally would do, when the batch is executed it merely "unpauses" and the
|
||||||
|
remainder of the importer logic continues. The only other difference being,
|
||||||
|
the importer will not read data from its normal "source" but instead will
|
||||||
|
simply read data from the batch - but from there it will continue as normal to
|
||||||
|
write data to the target/local system.
|
||||||
|
|
||||||
|
|
||||||
|
Batch from User-Provided File
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
More typically a batch will be "created" when a user uploads a data file. With
|
||||||
|
this type of batch, the data obviously comes from the uploaded file, but it may
|
||||||
|
be supplemented via SQL lookups etc. The goal being, take what the user gave
|
||||||
|
us but then load the "full picture" into the batch data tables.
|
||||||
|
|
||||||
|
User then will review/execute as normal. What such a batch actually does when
|
||||||
|
executed, can vary quite a bit.
|
||||||
|
|
||||||
|
Note that in some cases, a user-provided file can be better handled via
|
||||||
|
importer only, with no batch at all unless you need the review/execute
|
||||||
|
workflow.
|
||||||
|
|
||||||
|
|
||||||
|
Batch from User-Provided Query
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
In this pattern the user starts by filtering e.g. the Products table grid
|
||||||
|
according to their needs. When they're happy with results, they create a new
|
||||||
|
batch using that same query. So this defines the data set for the batch - it
|
||||||
|
is simply all products matching the query.
|
||||||
|
|
||||||
|
Note that Products is the only table/query supported for this method thus far.
|
||||||
|
It is possible to create multiple batch types with this method.
|
||||||
|
|
||||||
|
User then will review/execute as normal. What such a batch actually does when
|
||||||
|
executed, can vary quite a bit. A common example might be to create a Labels
|
||||||
|
batch from product query, execution of which will print labels for all products
|
||||||
|
in the batch.
|
||||||
|
|
||||||
|
|
||||||
|
Batch from Custom Data Set
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
In this pattern the logic used to obtain the data is likely hard-coded within
|
||||||
|
the batch handler.
|
||||||
|
|
||||||
|
For instance let's say you need a batch which allowed the user to generate
|
||||||
|
"Please Come Back!" coupons for all active members who have not shopped in the
|
||||||
|
store in the past 6 months.
|
||||||
|
|
||||||
|
You should not require the user to provide a data file etc. because the whole
|
||||||
|
point of this batch is to identify relevant members and issue coupons. If the
|
||||||
|
batch itself can identify the members then no need for the user to do that.
|
||||||
|
|
||||||
|
So here the batch handler logic would a) create a new empty batch, then b)
|
||||||
|
identify members not seen in 6 months, adding each as a row to the batch,
|
||||||
|
then c) user reviews and executes per usual, at which point d) coupons are
|
||||||
|
issued.
|
||||||
|
|
|
@ -3,4 +3,26 @@
|
||||||
Batch Table Schema
|
Batch Table Schema
|
||||||
==================
|
==================
|
||||||
|
|
||||||
TODO
|
From a schema standpoint there are 2 types of batches generally speaking:
|
||||||
|
static and dynamic.
|
||||||
|
|
||||||
|
Static batch types have 2 "dedicated" tables within the ``default`` schema of
|
||||||
|
the DB: one table for the batch "headers" and another for its "data". For
|
||||||
|
instance the basic inventory batch uses these tables:
|
||||||
|
|
||||||
|
* ``batch_inventory``
|
||||||
|
* ``batch_inventory_row``
|
||||||
|
|
||||||
|
When a new inventory batch is created, 1 new ``batch_inventory`` record is
|
||||||
|
created but multiple new ``batch_inventory_row`` records may be created. The
|
||||||
|
latter table contains all rows for all inventory batches.
|
||||||
|
|
||||||
|
Dynamic batch types however are just that, and do not have a dedicated "data"
|
||||||
|
table, although they still do have a dedicated "header" table. For instance
|
||||||
|
this approach is used for "importer batches" - when running an importer creates
|
||||||
|
a batch, it will create 1 new ``batch_importer`` record but then will create a
|
||||||
|
brand new table with custom schema based on the importer, to hold the data.
|
||||||
|
|
||||||
|
To avoid cluttering the ``default`` schema within the DB, dynamic batch data
|
||||||
|
tables are not stored there. Instead they are kept within the ``batch``
|
||||||
|
schema, which must be manually created if you need it.
|
||||||
|
|
Loading…
Reference in a new issue