Added RubbbbiconMD SKU and updated SIGGNIGFY. Fixed some SKU mismatch bugs
This commit is contained in:
+3
-13
@@ -120,20 +120,10 @@ OAKSTREET_RETURN_CITY=Lewisville
|
|||||||
OAKSTREET_RETURN_STATE=TX
|
OAKSTREET_RETURN_STATE=TX
|
||||||
OAKSTREET_RETURN_ZIP=75067
|
OAKSTREET_RETURN_ZIP=75067
|
||||||
|
|
||||||
# RubiconMD - Oak Street subsidiary (RMD-prefixed SKUs). Still needs its
|
# RubiconMD - Oak Street subsidiary (RMD-prefixed SKUs). Uses Oak Street's
|
||||||
# real Carrier ID/Service Code (its own UPS account, not Oak Street's) -
|
# own shipping account/address in every respect - this is the one thing
|
||||||
# address defaults to the same shared warehouse, just under its own name,
|
# that's actually different, the name shown on the return label.
|
||||||
# since that's the only difference confirmed so far. Change the address if
|
|
||||||
# it actually ships from somewhere else.
|
|
||||||
RUBICONMD_RETURN_CARRIER_ID=
|
|
||||||
RUBICONMD_RETURN_SERVICE_CODE=
|
|
||||||
RUBICONMD_RETURN_NAME=Rubicon MD
|
RUBICONMD_RETURN_NAME=Rubicon MD
|
||||||
RUBICONMD_RETURN_PHONE=
|
|
||||||
RUBICONMD_RETURN_ADDRESS1=1000 Spinks Road Suite 100
|
|
||||||
RUBICONMD_RETURN_ADDRESS2=
|
|
||||||
RUBICONMD_RETURN_CITY=Lewisville
|
|
||||||
RUBICONMD_RETURN_STATE=TX
|
|
||||||
RUBICONMD_RETURN_ZIP=75067
|
|
||||||
|
|
||||||
# --- Packing ---
|
# --- Packing ---
|
||||||
# Serial-number fields to suggest per device keyword found in a ticket's line
|
# Serial-number fields to suggest per device keyword found in a ticket's line
|
||||||
|
|||||||
+4
-15
@@ -140,21 +140,10 @@ SETTINGS_SCHEMA: Dict[str, tuple[str, str, bool]] = {
|
|||||||
"OAKSTREET_RETURN_ZIP": ("Oak Street Return Address: Zip", "Return Labels", False),
|
"OAKSTREET_RETURN_ZIP": ("Oak Street Return Address: Zip", "Return Labels", False),
|
||||||
|
|
||||||
# RubiconMD - an Oak Street subsidiary (RMD-prefixed SKUs). Classified as
|
# RubiconMD - an Oak Street subsidiary (RMD-prefixed SKUs). Classified as
|
||||||
# Oak Street Health everywhere else, but return labels use its own UPS
|
# Oak Street Health everywhere else. It uses Oak Street's own shipping
|
||||||
# account and its own name on the return address.
|
# account and address in every respect - this is the one thing that's
|
||||||
"RUBICONMD_RETURN_CARRIER_ID": ("RubiconMD Return: ShipStation Carrier ID", "Return Labels", False),
|
# actually different, the name shown on the return label.
|
||||||
"RUBICONMD_RETURN_SERVICE_CODE": (
|
"RUBICONMD_RETURN_NAME": ("RubiconMD Return Address: Name (uses Oak Street's account/address otherwise)", "Return Labels", False),
|
||||||
"RubiconMD Return: Service code (e.g. ups_ground)",
|
|
||||||
"Return Labels",
|
|
||||||
False,
|
|
||||||
),
|
|
||||||
"RUBICONMD_RETURN_NAME": ("RubiconMD Return Address: Name", "Return Labels", False),
|
|
||||||
"RUBICONMD_RETURN_PHONE": ("RubiconMD Return Address: Phone", "Return Labels", False),
|
|
||||||
"RUBICONMD_RETURN_ADDRESS1": ("RubiconMD Return Address: Address 1", "Return Labels", False),
|
|
||||||
"RUBICONMD_RETURN_ADDRESS2": ("RubiconMD Return Address: Address 2", "Return Labels", False),
|
|
||||||
"RUBICONMD_RETURN_CITY": ("RubiconMD Return Address: City", "Return Labels", False),
|
|
||||||
"RUBICONMD_RETURN_STATE": ("RubiconMD Return Address: State", "Return Labels", False),
|
|
||||||
"RUBICONMD_RETURN_ZIP": ("RubiconMD Return Address: Zip", "Return Labels", False),
|
|
||||||
|
|
||||||
"ACTIVE_STATUSES": (
|
"ACTIVE_STATUSES": (
|
||||||
"Statuses that count as real active work (comma-separated) - "
|
"Statuses that count as real active work (comma-separated) - "
|
||||||
|
|||||||
@@ -273,27 +273,21 @@ def send_order_to_shipstation_api(order: Order) -> dict:
|
|||||||
VALID_CHARGE_EVENTS = {"on_creation", "on_carrier_acceptance", "carrier_default"}
|
VALID_CHARGE_EVENTS = {"on_creation", "on_carrier_acceptance", "carrier_default"}
|
||||||
|
|
||||||
|
|
||||||
def _return_config_prefix(order: Order) -> str:
|
def _is_rubiconmd_order(order: Order) -> bool:
|
||||||
"""
|
return any((sku or "").strip().upper().startswith("RMD") for sku in (order.skus or []))
|
||||||
Normally keyed off company, but RMD-prefixed SKUs (RubiconMD, an Oak
|
|
||||||
Street subsidiary) use their own UPS account and return address even
|
|
||||||
though the ticket is still classified as Oak Street Health for every
|
|
||||||
other purpose - so this checks the ticket's actual SKUs, not just
|
|
||||||
order.company. (The IE prefix seen in Signify's catalog is deprecated
|
|
||||||
and deliberately not handled here - not expected on current tickets.)
|
|
||||||
"""
|
|
||||||
if any((sku or "").strip().upper().startswith("RMD") for sku in (order.skus or [])):
|
|
||||||
return "RUBICONMD_RETURN_"
|
|
||||||
if order.company == "Signify Health":
|
|
||||||
return "SIGNIFY_RETURN_"
|
|
||||||
return "OAKSTREET_RETURN_"
|
|
||||||
|
|
||||||
|
|
||||||
def _return_address_for_order(order: Order) -> dict:
|
def _return_address_for_order(order: Order) -> dict:
|
||||||
|
"""RubiconMD (RMD-prefixed SKUs) uses Oak Street's own address in every
|
||||||
|
respect except the name on the label - not a separate warehouse, just
|
||||||
|
a different name for the same shipping account/address."""
|
||||||
settings = config.load_settings()
|
settings = config.load_settings()
|
||||||
prefix = _return_config_prefix(order)
|
prefix = "SIGNIFY_RETURN_" if order.company == "Signify Health" else "OAKSTREET_RETURN_"
|
||||||
|
name = settings.get(f"{prefix}NAME", "")
|
||||||
|
if _is_rubiconmd_order(order):
|
||||||
|
name = settings.get("RUBICONMD_RETURN_NAME", "") or name
|
||||||
return {
|
return {
|
||||||
"name": settings.get(f"{prefix}NAME", ""),
|
"name": name,
|
||||||
"phone": settings.get(f"{prefix}PHONE", ""),
|
"phone": settings.get(f"{prefix}PHONE", ""),
|
||||||
"address_line1": settings.get(f"{prefix}ADDRESS1", ""),
|
"address_line1": settings.get(f"{prefix}ADDRESS1", ""),
|
||||||
"address_line2": settings.get(f"{prefix}ADDRESS2", "") or None,
|
"address_line2": settings.get(f"{prefix}ADDRESS2", "") or None,
|
||||||
@@ -305,11 +299,13 @@ def _return_address_for_order(order: Order) -> dict:
|
|||||||
|
|
||||||
|
|
||||||
def _return_carrier_for_order(order: Order) -> tuple[str, str]:
|
def _return_carrier_for_order(order: Order) -> tuple[str, str]:
|
||||||
"""Each shipping account (Signify, Oak Street, and RubiconMD as its own
|
"""RubiconMD uses Oak Street's own UPS account - no separate carrier,
|
||||||
subsidiary account) has its own UPS carrier_id, even where the physical
|
just a different name on the return address (see
|
||||||
warehouse is shared."""
|
_return_address_for_order). Each of the two REAL shipping accounts
|
||||||
|
(Signify, Oak Street) has its own carrier_id even though they share a
|
||||||
|
physical warehouse."""
|
||||||
settings = config.load_settings()
|
settings = config.load_settings()
|
||||||
prefix = _return_config_prefix(order)
|
prefix = "SIGNIFY_RETURN_" if order.company == "Signify Health" else "OAKSTREET_RETURN_"
|
||||||
return settings.get(f"{prefix}CARRIER_ID", ""), settings.get(f"{prefix}SERVICE_CODE", "")
|
return settings.get(f"{prefix}CARRIER_ID", ""), settings.get(f"{prefix}SERVICE_CODE", "")
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -68,6 +68,16 @@ def check_company_mismatch(skus: List[str]) -> Optional[TicketIssue]:
|
|||||||
|
|
||||||
|
|
||||||
def check_return_device_mismatch(line_items: List[dict]) -> List[TicketIssue]:
|
def check_return_device_mismatch(line_items: List[dict]) -> List[TicketIssue]:
|
||||||
|
"""
|
||||||
|
A return SKU's implied device type needs to match SOMETHING else on the
|
||||||
|
ticket - either an actual device line item (break-fix: send the asset,
|
||||||
|
return the same type) OR another shipping item of the same type (asset
|
||||||
|
recovery: a box and a label for the same device, e.g. SH002 "Return Box
|
||||||
|
iPad" + SH011 "Return Label iPad" - both are "shipping" items by our
|
||||||
|
is-it-a-device check, and pairing them like this is correct, not a
|
||||||
|
mismatch - confirmed against real examples: SH002/SH011, OK001/OK006,
|
||||||
|
OK011/OK013).
|
||||||
|
"""
|
||||||
keyword_map = get_device_field_suggestions() # {keyword: [serial fields]} - keys only, here
|
keyword_map = get_device_field_suggestions() # {keyword: [serial fields]} - keys only, here
|
||||||
exempt_keywords = get_return_device_exempt_keywords()
|
exempt_keywords = get_return_device_exempt_keywords()
|
||||||
issues: List[TicketIssue] = []
|
issues: List[TicketIssue] = []
|
||||||
@@ -87,16 +97,22 @@ def check_return_device_mismatch(line_items: List[dict]) -> List[TicketIssue]:
|
|||||||
# nothing to check it against, so nothing to flag here either.
|
# nothing to check it against, so nothing to flag here either.
|
||||||
continue
|
continue
|
||||||
|
|
||||||
has_matching_device = any(
|
matches_a_device = any(
|
||||||
matched_keyword in item.get("item_name", "").lower() for item in device_items
|
matched_keyword in item.get("item_name", "").lower() for item in device_items
|
||||||
)
|
)
|
||||||
if not has_matching_device:
|
matches_another_shipping_item = any(
|
||||||
|
matched_keyword in other.get("item_name", "").lower()
|
||||||
|
for other in return_items
|
||||||
|
if other is not return_item
|
||||||
|
)
|
||||||
|
if not matches_a_device and not matches_another_shipping_item:
|
||||||
issues.append(
|
issues.append(
|
||||||
TicketIssue(
|
TicketIssue(
|
||||||
code="return_device_mismatch",
|
code="return_device_mismatch",
|
||||||
message=(
|
message=(
|
||||||
f"'{return_item.get('sku', '')}' ({return_item.get('item_name', '')}) "
|
f"'{return_item.get('sku', '')}' ({return_item.get('item_name', '')}) "
|
||||||
f"expects a matching '{matched_keyword}' device, but none is on this ticket"
|
f"expects a matching '{matched_keyword}' device or box/label pair, "
|
||||||
|
"but none is on this ticket"
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user