The POS vocabulary

What a till prints differs between POS products and versions by words, not by structure: SoftRestaurant 8 writes FOLIO NO. 7 where 9 writes FOLIO:17, and CUENTAS CANCELADOS where 9 writes CUENTAS CANCELADAS. So the words live in the database, one set per POS in the catalogue, and the engine in pkg/extract applies them. Supporting a new version, or correcting one, is a matter of rows, not code.

The table

CREATE TABLE pos_patterns (
    id            BIGSERIAL PRIMARY KEY,
    pos_system_id INTEGER NOT NULL REFERENCES pos_systems(id) ON DELETE CASCADE,
    field         TEXT    NOT NULL,   -- what this feeds
    kind          TEXT    NOT NULL,   -- how the engine applies it
    pattern       TEXT    NOT NULL,   -- RE2
    note          TEXT    NOT NULL DEFAULT '',
    UNIQUE (pos_system_id, field)
);

kind is the closed set the engine knows how to apply:

kind what it does needs a capture group
match presence test no
label_int label → integer on the same line no, the engine appends the tail
label_money label → amount on the same line no
capture its own expression with groups yes

For label_int and label_money the row holds only the label (CUENTAS NORMALES); the engine appends the number that follows it. An operator writes a word, not a regular expression.

The fields

field names what the pattern feeds: the family and version marks (vendor_mark, version), the sales bill (bill.folio, bill.date, …), the day close (close.heading, close.accounts_normal, close.tips, …) and the till’s reports (report.ventas, ventas.period, …). The complete list is the Field... constants in pkg/extract/patterns.go; a row naming anything else is refused. What a line of payments looks like - a name, two spaces, an amount - is grammar rather than a word, and stays in the code.

Editing

The catalogue screen and PUT /api/pos/:posId/patterns (owner only) write these rows. A pattern is refused unless its field is one the engine reads, its kind is one of the four above, and it compiles - including, for capture, a group to capture. Go’s regular expressions are RE2, so a pattern cannot backtrack exponentially; it can still match the wrong thing, so check a change against a till’s real paper before relying on it.