72 lines
2.5 KiB
Python
72 lines
2.5 KiB
Python
"""
|
|
Database models.
|
|
|
|
Order is intentionally source-agnostic: JIRA tickets, ShipStation
|
|
orders, and Odoo sale orders all get normalized into this shape on the
|
|
way in (see app/services/*). The `source` + `external_id` pair tells
|
|
you where a row came from, and `raw_data` keeps the original payload
|
|
in case a later feature needs a field we didn't think to pull out yet.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import datetime as dt
|
|
|
|
from sqlalchemy import (
|
|
Column,
|
|
Integer,
|
|
String,
|
|
DateTime,
|
|
Boolean,
|
|
JSON,
|
|
UniqueConstraint,
|
|
)
|
|
from sqlalchemy.orm import declarative_base
|
|
|
|
Base = declarative_base()
|
|
|
|
|
|
class Order(Base):
|
|
__tablename__ = "orders"
|
|
__table_args__ = (
|
|
UniqueConstraint("source", "external_id", name="uq_source_external_id"),
|
|
)
|
|
|
|
id = Column(Integer, primary_key=True)
|
|
|
|
# Where this order came from and its ID in that system.
|
|
# e.g. source="jira", external_id="AR-1234"; source="shipstation", external_id="se-9988"
|
|
source = Column(String(32), nullable=False, index=True)
|
|
external_id = Column(String(128), nullable=False, index=True)
|
|
|
|
# The AR-###### style ticket number. Present on both JIRA and
|
|
# ShipStation orders once the ticket number carries through - this is
|
|
# the field that lets the dashboard correlate the same real-world
|
|
# order across both sources.
|
|
ticket_number = Column(String(64), nullable=True, index=True)
|
|
|
|
# Signify Health / Oak Street Health / Unknown - derived from SKU
|
|
# prefix (JIRA) or store ID (ShipStation). See app/companies.py.
|
|
company = Column(String(100), nullable=False, default="Unknown", index=True)
|
|
|
|
# SKUs found on this order/ticket. A ticket can have several, but
|
|
# per business rule they never mix companies on one ticket.
|
|
skus = Column(JSON, nullable=True)
|
|
|
|
summary = Column(String(500), nullable=False, default="")
|
|
status = Column(String(100), nullable=False, default="")
|
|
|
|
# When the order/ticket was created in the source system
|
|
source_created_at = Column(DateTime, nullable=True)
|
|
# When we pulled it into this app
|
|
imported_at = Column(DateTime, nullable=False, default=dt.datetime.utcnow)
|
|
|
|
# Downstream pipeline flags - useful once ShipStation/Odoo steps exist
|
|
fulfilled = Column(Boolean, nullable=False, default=False)
|
|
|
|
# Full original payload from the source system, for anything not
|
|
# modeled explicitly above.
|
|
raw_data = Column(JSON, nullable=True)
|
|
|
|
def __repr__(self) -> str: # pragma: no cover - debugging aid
|
|
return f"<Order {self.source}:{self.external_id} '{self.summary[:30]}'>"
|