Skip to content

What the system does on its own

Some things happen without anyone clicking. Know what they are, so a document that changed overnight reads as normal rather than as someone else's mistake.

Everything below runs on the server's own schedule. Cron times are evaluated in the store's own time zone, so 23:00 means 11 PM in the shop, not in some other zone.

The schedule

When What runs
23:00 daily Automatic POS close
Daily FastBound push and delete retries, FastBound list refresh, stuck-record digest, GunBroker audit, item quantity self-heal, sale price refresh
Hourly Stale trade-in draft nudge, GunBroker listing sweep, stuck rule-run cleanup
Every 30 minutes Distributor order poll, drop-ship routing sweep
Every 15 minutes POS consolidation safety net, drop-ship listing sync, feed staleness watchdog, GunBroker order poll, GunBroker end-listing confirmation, auction bid watch
Every 10 minutes Consignment tracking poll, GunBroker tracking poll
Every 2 hours WooCommerce reconcile, order audit, serial reservation retry, shipped-undisposed check, web revenue backstop

The nightly POS close

At 23:00 the system closes every shift that is still open. It builds a POS Closing Entry for each one, sets the counted amount equal to the expected amount so the variance is zero, and submits it. That consolidates the day's POS Invoices into Sales Invoices, so the books are clean by morning.

A shift opened within the last hour is skipped, so a till opened shortly before 11 PM is not swept up by accident. A night the job misses is caught the next night.

This is a backstop, not the intended way to end a day. An automatic close trusts the till by definition, because nobody counted the drawer. Close the register properly at the end of your shift and the nightly job finds nothing to do. See Opening and closing the day.

The close is scoped to the shift's owner

A sale rung up by someone other than the person who opened the shift is not picked up by the nightly close. A separate sweep runs every fifteen minutes and retries any POS Invoice whose consolidation failed or was missed, so those leftovers get consolidated the next day. If one keeps failing, the sweep raises a task on it rather than retrying forever, because an unconsolidated sale leaves a sold gun looking like it is still in stock.

FastBound

Daily. Three jobs run. Two retry pushes and deletes that failed, so a transient network problem clears itself overnight. The third refreshes the cached acquisition and disposition type lists from FastBound.

Daily digest. A fourth job reads every acquisition and disposition carrying a sync error and emails one digest listing them. Entries that will not retry on their own are tagged [needs human]. A cancelled record that never reached FastBound is left out, because it has no bound book obligation. The subject line is <n> FastBound record(s) stuck unsynced, and at most one digest goes out per day. See A FastBound push failed.

The trade-in nudge

Hourly. Any draft trade-in acquisition whose possession date is before today raises an alert. It is hourly rather than daily on purpose: the bound book clock for a gun you have taken possession of runs to the close of the next business day, and it runs from physical possession, independent of whatever the buyer's side of the sale is doing. A delayed background check must not quietly carry an unbooked gun past that line.

The job fires stricter than the legal deadline, so staff still have the whole next business day to act. The email names each draft and its serial and says what to do: complete the checkout, submit the acquisition directly if the store is keeping the gun, or delete the draft if the customer took it back. The digest goes out at most twice a day. See Trade-ins.

GunBroker

Daily audit. One job reads everything a GunBroker order can be stuck halfway through and reports eight kinds of problem: a gun disposed with no invoice, an invoice with no payment recorded, an order paid but not disposed past the alert threshold, a status conflict where GunBroker shows cancelled or refunded while the invoice still stands, a fee accrual left on a cancelled invoice, a chargeback, an order whose sync has failed five times running, and an invoice more than a day old with no valid fee accrual. Every step of the order flow logs its failures rather than raising them, so the bound book exit is never rolled back, which is exactly why something has to read the wreckage once a day. Clear all eight before month end.

Hourly listing sweep. The only job that asks GunBroker what is actually true. Everything else reacts to a local event, and events go missing. It is a no-op when the integration is switched off.

Every fifteen minutes. Three jobs. The order poll pulls new orders down; fifteen minutes is the window in which a gun can sell on GunBroker and still be sitting on the shelf looking available, which is the window the counter's pre-sale check covers. The end-listing confirmation chases listings we asked GunBroker to end and could not verify at the time, and it runs on this timer rather than the hourly one because an unconfirmed end is the one state where a gun that has left the shelf can still be bought. The auction bid watch reads live auctions so the first bid locks the gun within fifteen minutes.

Every ten minutes. Tracking numbers are carried back from the shipping label the store bought. It only looks at orders with a step still outstanding, so a day with nothing shipping makes no calls at all.

Distributors and drop-ship

Every fifteen minutes. Drop-ship listings are synced. A listing whose price and published quantity have not changed is skipped rather than re-pushed.

Feed staleness watchdog, every fifteen minutes. Each drop-ship distributor's feed heartbeat is checked against a 90 minute threshold. Past it, the system emails once per distributor to say the published quantities are no longer trustworthy, and states whether the zero-stock interlock is on. Where a distributor has opted into that interlock, its listings are pushed to zero stock so an outage cannot oversell. A heartbeat that cannot be read at all is treated as stale, on the principle that not knowing is not the same as being fine.

Every thirty minutes. Live distributor orders are polled for status, backing off from every thirty minutes to every two hours as an order ages, and orders sitting untouched for fourteen days raise an alert. A second job routes any drop-ship order still waiting for a route.

Consignment

Every ten minutes. Consignment shipments still marked Pending that carry a ShipStation shipment id are asked whether a label has been bought yet. The first label with a tracking number writes that number, its carrier and its link back onto the record and flips it to Shipped. The job only runs while ShipStation is enabled and there are shipments within the 30 day window, so it costs nothing on a quiet day. See Shipping a consignment.

WooCommerce

Every two hours. Five jobs share one tick. Products are reconciled against the store, on the schedule set in WooCommerce Settings. The order audit checks once a day for store orders missing here. Stuck serial reservations are retried, bounded so a backlog cannot flood the store with calls. A check looks for orders marked shipped on the store but still pending here, which would mean a firearm out of the building with no bound book entry, and reports once a day. Last, a backstop re-runs revenue bookings and stock legs that never landed.

Where alerts land

Two places, and both matter.

Email goes to the addresses in Alert Recipients on FFL Settings. Leave that field empty and every System Manager receives them instead, so an alert is never silently dropped. Repeated failures are throttled per kind of problem, so something failing every fifteen minutes sends one message, not ninety-six.

An assigned task is raised on the document itself for a stranded record: a stock leg that could not be issued, a revenue booking that keeps failing, an invoice stuck in draft. It goes to the stock managers, the sales managers and the system managers, and it is raised exactly once and stays open until a person closes it. That is deliberate. A condition that persists gets one task, not one per run, and closing the task is how you say a human has dealt with it.

Check both as part of Daily checks.