2 RattailCore
Lance Edgar edited this page 2025-10-06 16:58:37 -05:00

Rattail Core

This document attempts to describe Rattail conceptually. The developer documentation is available at PyPI.

What Rattail Is Not

Rattail proper is not an application in the usual sense of the word. It technically does provide a console application which can install and upgrade Rattail databases, etc., but Rattail itself is really only useful to developers. (Currently the only application built with Rattail is BONE.)

What Rattail Is

Rattail (often referred to as "core") is a Python package which provides (among other things) a common data layer for retail-oriented database applications. Some of the problems it aims to address include:

  • Environment Neutrality - Console, graphical, and web applications should all be possible.
  • Database Abstraction - Multiple database back-ends should be supported by the same code.
  • Schema Extensibility - Everyone has unique needs; the schema should grow to meet them.
  • Data Auditing - Changes to primary data (e.g. products) should be logged and auditable.
  • Data Syncing - Some data must be synchronized between databases, e.g. server and POS.
  • Code Simplicity - Interaction with the Rattail API should be intuitive (Pythonic).

Environment Neutrality

Rattail is environment-neutral by virtue of providing only what it does, i.e. interaction with configuration files, databases, etc. None of these things require or even imply a specific environment; that choice is left to the developer.

As mentioned above, Rattail includes a console application which can make certain tasks convenient for the developer. This utility may also be extended by other applications, so it might be said that Rattail does have a console bias ... but regardless the console environment is only "required" if it's intentionally used.

Database Abstraction

Rattail uses SQLAlchemy for its database interaction. This allows code to be written without any SQL at all, which in turn allows a great many database back-ends to be used without any changes to the code. Some common ones which are known to work include:

  • MySQL
  • PostgreSQL
  • Microsoft SQL Server
  • Oracle
  • SQLite

See SQLAlchemy's full list of supported databases.

Schema Extensibility

Every organization is unique and most will need more out of their database than what Rattail offers out-of-the-box. Rattail tries to accommodate this fact by providing a ''core'' schema and then allowing ''extensions'' to add layers of data "on top of" the core. The core schema includes things which are "commonly" useful, e.g. Customer, Product, Store, Employee. Extensions then may add domain-specific data, e.g. Member, Vendor, !SomeUniqueThing.

Extensions may also be constructed so as to fit on top of each other in a hierarchy. In this way an industry-specific extension can be created, e.g. one concerned with tracking membership within a co-op (and in fact one has been started), and then if a particular co-op had a really unique need with regard to their membership data, they could create an extension which only provided what they needed ''in addition to'' the core and more general membership extension.

Here is a list of extensions which have technically been started; some are more developed than others:

  • ar - Accounts receivable (invoices, etc.)
  • food - Food-based product attributes, e.g. "organic"
  • members - Membership info (as in above example)
  • orders - Customer order tracking
  • purchasing - Product "sources" and purchase orders
  • orders_purchasing - Relates customer orders to purchase orders
  • pos - Point of sale (transactions, etc.)
  • timeclock - Employee time logging and scheduling

There is some info on developing extensions.

Data Auditing

A relatively new addition to the Rattail framework is data "auditing" (or "version tracking"). It is not fully functional and some design specifics have not quite been settled upon, but the idea is to record changes to "important" data for auditing purposes, etc. This would include things like Customer, Product, Employee, etc. Each time a change is made to such an object, a revision (basically, a copy) of the object's data is created with a timestamp and a reference to the user who made the change.

More information on this idea should be available as it is further developed...

Data Syncing

Also a new addition to the framework, data "synchronization" is intended to allow data to be independently created and edited at a particular database and then propagated to other databases. It is hoped that this will provide the mechanism necessary for two specific use cases:

  1. Sales are rung at one or more POS machines, each of which writes only to a local database, and then the server pulls transaction data from each POS database. Vice versa, the POS machines will each pull customer and product data from the server.
  2. More than one physical location exists for the organization and each has its own server; changes are allowed at each but must propagate to all the other locations.

Synchronization is (hoped to be) achieved by configuring databases to "subscribe" to one another for certain types of data. Within a particular database, as new revisions are created as part of the auditing framework, stub records are created for each database that is subscribed to this particular type of data on this particular database. Then software responsible for the subscribing database must poll the first database for its changes.

For example, if server A is subscribed to Product data on server B, then when a new product is created on server B a stub will also be created which indicates that there is a new product. This stub is ''only'' relevant to server A though, so if server C was also interested then two stubs would need to be created. At some point then, a daemon application running on server A (and/or server C) would query the database on server B and find the stub which server B had created. Upon finding the stub, the server A daemon will copy the new product data to its own database, and in turn create stubs for any ''other'' databases which are subscribed to server A's product data. Etc.

Code Simplicity

Rattail is really all about abstraction. It tries to expose functionality as simply as is practical. Much of its code simplicity is sort of "inherited" from SQLAlchemy (and of course Python itself), but Rattail also makes an effort to continue in that vein.

It might be noted that some of Rattail's class mappings, and therefore schema extension development in general, are not necessarily intuitive if one is not yet accustomed to defining things with SQLAlchemy. This is perhaps unfortunate, but it doesn't detract from the ''exposed'' API, which is what an application would be calling. Once an extension has been created, other applications can be built to use it without concern for the "hairiness" underneath the extension.

At any rate here is a very simple "application":

>>> import rattail
>>> rattail.init()
>>> session = rattail.Session(user='admin')
>>> product = rattail.Product(description='Test Product', price=4.20)
>>> session.add(product)
>>> session.commit()
>>> session.query(rattail.Product).one()
<Product: Test Product>