More Shipstation integrations(warehouses)

This commit is contained in:
2026-08-31 15:00:37 -05:00
parent 4c172c1fd5
commit 9651b82415
12 changed files with 337 additions and 139 deletions
+56 -42
View File
@@ -41,43 +41,47 @@ There's no "source" filter because there's effectively one source.
Orders are cached locally in SQLite (`orders.db`). Re-importing updates
existing tickets rather than duplicating them.
## Status tracking, matched to your actual workflow
## Three tabs: Active, Cancelled, Done
- **Cancellation** (`CANCELLED_STATUSES`, default `Cancelled`): you
cancel a ticket yourself when the SKU is wrong or the address doesn't
validate. Any order in this status is **highlighted red** in the
table, and a **popup fires** right after an import if a ticket just
transitioned into it (not one that was already cancelled).
- **Fulfilled** (`FULFILLED_STATUS_WITH_RETURN` /
`FULFILLED_STATUS_WITHOUT_RETURN`, defaulting to `Waiting For Return`
/ `Device Return Not Needed`): these are **highlighted green**. The
"Pull Tracking Numbers" action figures out which one applies per
ticket automatically, from whether ShipStation's automation also
generated a return label (see below) - so you know which status to
set without checking each one by hand.
- **Carryover**: tickets you didn't close out same-day (rare, per what
you described) don't need anything special - they're just tickets
that haven't hit a terminal status yet (`JIRA_TERMINAL_STATUSES`,
default `Cancelled,Waiting For Return,Device Return Not Needed`).
Every JIRA import re-checks any such ticket regardless of when it was
created, so a carryover ticket stays "alive" and gets its status
change picked up whenever it happens, however many days later. The
Dashboard's Carryover count is just these tickets filtered to "created
before today."
The tab a ticket shows up on is decided by an **allowlist**, not a list
of every "finished" status:
## The Done pile
- **Active Orders**: status is in `ACTIVE_STATUSES` (default just
`Created`) - the only tickets that represent real work still to do.
- **Cancelled**: status is in `CANCELLED_STATUSES` (default `Cancelled`)
- its own tab so it doesn't clutter Active, but still reviewable
anytime. Any transition into this status also triggers a **popup**
right after the import that caused it (not one that was already
cancelled).
- **Done**: everything else, automatically. This is deliberate - rather
than maintaining a list of every status that means "finished"
(`Waiting For Return`, `Device Return Not Needed`, and whatever your
JIRA automation adds next, like `1st Contact Attempt`), only the
couple of statuses that mean "not done yet" are named. Anything that
isn't Created or Cancelled lands on Done with zero config changes
needed when your workflow adds another downstream status later.
Once a ticket reaches either fulfilled status, it moves off the
**Active Orders** tab and onto the **Done** tab automatically - the
active view stays focused on what's still being worked. This is a
filter, not a physical move: everything's still the same `orders`
table, split by current status each time the view refreshes, so if a
status ever changed back there'd be nothing to reconcile. Cancelled
tickets stay on Active Orders (still need eyes on them) - only the two
fulfilled statuses trigger the move. The Dashboard's "Active Orders"
count and company breakdown only reflect what's still active;
"Fulfilled Today" and "Arrived Past Cutoff Today" look at all of
today's activity regardless of which tab something ended up on.
This is a filter, not a physical move - it's the same `orders` table,
split by current status every time the view refreshes, so nothing to
reconcile if a status ever changes back.
Within Done, the two fulfilled statuses (`FULFILLED_STATUS_WITH_RETURN`
/ `FULFILLED_STATUS_WITHOUT_RETURN`, defaulting to `Waiting For Return`
/ `Device Return Not Needed`) still get **highlighted green** and drive
the "Fulfilled Today" dashboard count and `fulfilled_at` timestamp -
they're the two statuses this app actually knows the meaning of, versus
other done-statuses (like `1st Contact Attempt`) which land on Done but
aren't otherwise tracked, per "it is considered done...unnecessary to
be tracked for us."
**Carryover**: tickets that didn't get closed out same-day don't need
anything special - since `ACTIVE_STATUSES` defaults to just `Created`,
every JIRA import re-checks any ticket still in that status regardless
of when it was created, so it stays "alive" and its eventual status
change gets picked up whenever it happens. The Dashboard's Carryover
count is Active tickets created before today, plus today's tickets that
arrived past the cutoff (see below) - both cases are known not to get
done today, just at different points in the day.
## Intake cutoff tracking
@@ -153,14 +157,24 @@ account - check that ShipStation packed and priced an emergency-sent
order the way a normal one would before relying on this in an actual
emergency.
A couple of things worth confirming once you've seen real data:
- **Address 2**: two JIRA fields were both labeled "Address 1" when you
listed them (`customfield_10654` and `customfield_10655`) - this
assumes the second one is actually Address 2. Double-click a ticket
that has both filled in and check the Shipping Info section to confirm.
- **Quantity**: always sent as `1` per line item today, since JIRA
doesn't currently give a per-deliverable quantity. Say the word if
that's ever not right.
One thing worth knowing: **Quantity** is always sent as `1` per line
item today, since JIRA doesn't currently give a per-deliverable
quantity. Say the word if that's ever not right.
## Keeping .env in sync as new settings get added
`.env` is gitignored on purpose (it holds real credentials and field
IDs), which means pulling new code never updates it automatically -
new settings would otherwise sit silently blank until someone noticed
a feature wasn't working (this is what caused an early version of the
emergency-send feature to have no address data - the field IDs existed
in `.env.example` but never made it into the real `.env`). Every
startup now calls `config.sync_env_with_example()`, which adds any key
present in `.env.example` but missing from `.env`, using the example's
value as the default - without touching anything you've already set.
Existing tickets in the local database still need a fresh **Import
from JIRA** to pick up newly-added fields, though, since extraction
only runs when a ticket is actually re-fetched.
## How company/SKU extraction works