ShipStation tracking pull, status tracking, dashboard rework
This commit is contained in:
@@ -17,7 +17,9 @@ import requests
|
||||
|
||||
from app import config
|
||||
from app.companies import parse_mapping, resolve_company_for_skus
|
||||
from app.queries import get_open_ticket_numbers
|
||||
from app.services.base import OrderService, NormalizedOrder
|
||||
from app.status_rules import parse_status_list
|
||||
|
||||
SEARCH_PAGE_SIZE = 50
|
||||
REQUEST_TIMEOUT_SECONDS = 30
|
||||
@@ -58,6 +60,12 @@ class JiraService(OrderService):
|
||||
settings["COMPANY_SKU_MAP"] or config.DEFAULT_COMPANY_SKU_MAP
|
||||
)
|
||||
|
||||
# Statuses at which we stop re-checking a ticket for changes -
|
||||
# see fetch_orders() for why we re-check at all.
|
||||
self.terminal_statuses = parse_status_list(
|
||||
settings["JIRA_TERMINAL_STATUSES"] or config.DEFAULT_TERMINAL_STATUSES
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _split_field_ids(raw: str) -> List[str]:
|
||||
return [f.strip() for f in (raw or "").split(",") if f.strip()]
|
||||
@@ -72,12 +80,51 @@ class JiraService(OrderService):
|
||||
"JIRA Site URL, Email, API Token, and JQL."
|
||||
)
|
||||
|
||||
issues = self._search_all_issues()
|
||||
# Your JQL (e.g. "created >= startOfDay()") only catches NEW
|
||||
# tickets. On its own, that would miss a ticket that gets
|
||||
# cancelled a day or two after it was created, since it no
|
||||
# longer matches "created today". So on top of your JQL, we
|
||||
# also re-check every previously-imported JIRA ticket that
|
||||
# hasn't reached a terminal status yet (JIRA_TERMINAL_STATUSES,
|
||||
# default just "Cancelled") - that's how a later cancellation
|
||||
# gets picked up.
|
||||
recheck_keys = get_open_ticket_numbers("jira", self.terminal_statuses)
|
||||
effective_jql = self._build_effective_jql(self.jql, recheck_keys)
|
||||
|
||||
issues = self._search_all_issues(effective_jql)
|
||||
return [self._to_normalized_order(issue) for issue in issues]
|
||||
|
||||
# -- internals -----------------------------------------------------
|
||||
|
||||
def _search_all_issues(self) -> List[dict]:
|
||||
@staticmethod
|
||||
def _build_effective_jql(base_jql: str, recheck_keys: List[str]) -> str:
|
||||
"""
|
||||
Combine the configured JQL with "OR key in (...)" for tickets we
|
||||
want to re-check, being careful to keep any ORDER BY clause at
|
||||
the very end (JQL requires it there).
|
||||
|
||||
Note: as the number of still-open tracked tickets grows, this
|
||||
"key in (...)" list grows too. If that ever gets unwieldy, add
|
||||
more statuses to JIRA_TERMINAL_STATUSES (e.g. "Done", once you
|
||||
know your workflow's real terminal status names) so fulfilled
|
||||
tickets stop being re-checked and drop out of this list.
|
||||
"""
|
||||
if not recheck_keys:
|
||||
return base_jql
|
||||
|
||||
order_by_match = re.search(r"\bORDER BY\b.*$", base_jql, re.IGNORECASE)
|
||||
if order_by_match:
|
||||
where_part = base_jql[: order_by_match.start()].strip()
|
||||
order_by_clause = " " + order_by_match.group(0)
|
||||
else:
|
||||
where_part = base_jql.strip()
|
||||
order_by_clause = ""
|
||||
|
||||
keys_clause = "key in (" + ", ".join(recheck_keys) + ")"
|
||||
combined_where = f"({where_part}) OR {keys_clause}" if where_part else keys_clause
|
||||
return combined_where + order_by_clause
|
||||
|
||||
def _search_all_issues(self, jql: str) -> List[dict]:
|
||||
url = f"{self.base_url}/rest/api/3/search"
|
||||
auth = (self.email, self.api_token)
|
||||
headers = {"Accept": "application/json"}
|
||||
@@ -92,7 +139,7 @@ class JiraService(OrderService):
|
||||
|
||||
while True:
|
||||
params = {
|
||||
"jql": self.jql,
|
||||
"jql": jql,
|
||||
"startAt": start_at,
|
||||
"maxResults": SEARCH_PAGE_SIZE,
|
||||
"fields": fields,
|
||||
@@ -221,6 +268,7 @@ class JiraService(OrderService):
|
||||
ticket_number=ticket_number,
|
||||
company=company,
|
||||
skus=skus,
|
||||
tracking_numbers=[],
|
||||
summary=summary,
|
||||
status=(fields.get("status") or {}).get("name", ""),
|
||||
source_created_at=created_at,
|
||||
|
||||
Reference in New Issue
Block a user