220 lines
6.4 KiB
Python
220 lines
6.4 KiB
Python
"""选品读写:表 1 领取、表 2 落结果。
|
||
|
||
claim 时 deal_flag 0 → 3;save 时写成 1 或 2。
|
||
中途崩溃会停在 3,需人工改回 0 再跑。
|
||
"""
|
||
from __future__ import annotations
|
||
|
||
from collections.abc import Callable
|
||
from dataclasses import dataclass
|
||
from typing import Any
|
||
|
||
from db import DEAL_USER_NAME, RepoUnavailable, connect_from_env, oracle_dsn
|
||
|
||
_SELECT_PENDING = """
|
||
SELECT fid, oms_id, bar_code, sale_price, plan_purchase_qty,
|
||
NVL(approval_no, '') AS approval_no,
|
||
NVL(goods_name, '') AS goods_name,
|
||
NVL(goods_spec, '') AS goods_spec,
|
||
NVL(manufacturer, '') AS manufacturer,
|
||
NVL(org_code, '') AS org_code,
|
||
deal_flag
|
||
FROM rpa_sales_goods_mapping_data
|
||
WHERE deal_flag = 0
|
||
ORDER BY fid
|
||
"""
|
||
|
||
_SELECT_PENDING_LIMIT = f"""
|
||
SELECT * FROM (
|
||
{_SELECT_PENDING}
|
||
) WHERE ROWNUM <= :limit
|
||
"""
|
||
|
||
_CLAIM_SQL = """
|
||
UPDATE rpa_sales_goods_mapping_data
|
||
SET deal_flag = 3,
|
||
deal_time = SYSDATE,
|
||
update_time = SYSDATE,
|
||
deal_user_name = :deal_user_name
|
||
WHERE fid = :fid AND deal_flag = 0
|
||
"""
|
||
|
||
_INSERT_CART_SQL = """
|
||
INSERT INTO rpa_cart_settlement_goods_data (
|
||
operate_type, oms_id, platform_type, supplier_name, bar_code,
|
||
purchase_price, purchase_qty, purchase_total, status, fail_reason,
|
||
push_status, create_time, org_code, multi_platform_flag, create_user_name
|
||
) VALUES (
|
||
:operate_type, :oms_id, :platform_type, :supplier_name, :bar_code,
|
||
:purchase_price, :purchase_qty, :purchase_total, :status, :fail_reason,
|
||
:push_status, SYSDATE, :org_code, :multi_platform_flag, :create_user_name
|
||
)
|
||
"""
|
||
|
||
_COMPLETE_SQL = """
|
||
UPDATE rpa_sales_goods_mapping_data
|
||
SET deal_flag = :deal_flag,
|
||
deal_result = :deal_result,
|
||
deal_time = SYSDATE,
|
||
update_time = SYSDATE,
|
||
deal_user_name = :deal_user_name
|
||
WHERE oms_id = :oms_id
|
||
"""
|
||
|
||
_CART_BIND_KEYS = (
|
||
"operate_type",
|
||
"oms_id",
|
||
"platform_type",
|
||
"supplier_name",
|
||
"bar_code",
|
||
"purchase_price",
|
||
"purchase_qty",
|
||
"purchase_total",
|
||
"status",
|
||
"fail_reason",
|
||
"push_status",
|
||
"org_code",
|
||
"multi_platform_flag",
|
||
)
|
||
|
||
|
||
@dataclass
|
||
class MappingRow:
|
||
fid: int
|
||
oms_id: int
|
||
bar_code: str
|
||
sale_price: float | None
|
||
plan_purchase_qty: float | None
|
||
approval_no: str
|
||
goods_name: str
|
||
goods_spec: str
|
||
manufacturer: str
|
||
org_code: str
|
||
deal_flag: int
|
||
deal_result: str = ""
|
||
|
||
|
||
class MemorySelectRepo:
|
||
def __init__(self, rows: list[MappingRow]):
|
||
self.mapping: dict[int, MappingRow] = {row.oms_id: row for row in rows}
|
||
self.cart: list[dict[str, Any]] = []
|
||
|
||
def claim_pending(self, limit: int | None = None) -> list[MappingRow]:
|
||
pending = sorted(
|
||
(row for row in self.mapping.values() if row.deal_flag == 0),
|
||
key=lambda row: row.fid,
|
||
)
|
||
if limit is not None:
|
||
pending = pending[:limit]
|
||
for row in pending:
|
||
row.deal_flag = 3
|
||
return pending
|
||
|
||
def save_result(
|
||
self,
|
||
oms_id: int,
|
||
deal_flag: int,
|
||
deal_result: str,
|
||
cart_rows: list[dict[str, Any]],
|
||
) -> None:
|
||
row = self.mapping[oms_id]
|
||
row.deal_flag = deal_flag
|
||
row.deal_result = deal_result
|
||
self.cart.extend(dict(item) for item in cart_rows)
|
||
|
||
|
||
class OracleSelectRepo:
|
||
def __init__(self, connect: Callable):
|
||
self._connect = connect
|
||
|
||
@classmethod
|
||
def from_env(cls) -> "OracleSelectRepo":
|
||
oracle_dsn()
|
||
return cls(connect=connect_from_env)
|
||
|
||
def claim_pending(self, limit: int | None = None) -> list[MappingRow]:
|
||
conn = self._connect()
|
||
try:
|
||
with conn.cursor() as cur:
|
||
if limit is None:
|
||
cur.execute(_SELECT_PENDING)
|
||
else:
|
||
cur.execute(_SELECT_PENDING_LIMIT, {"limit": int(limit)})
|
||
fetched = [_mapping_from_cursor(cur, rec) for rec in cur.fetchall()]
|
||
claimed: list[MappingRow] = []
|
||
for row in fetched:
|
||
cur.execute(
|
||
_CLAIM_SQL,
|
||
{"fid": row.fid, "deal_user_name": DEAL_USER_NAME},
|
||
)
|
||
if cur.rowcount == 1:
|
||
row.deal_flag = 3
|
||
claimed.append(row)
|
||
conn.commit()
|
||
return claimed
|
||
except Exception as exc:
|
||
try:
|
||
conn.rollback()
|
||
except Exception:
|
||
pass
|
||
raise RepoUnavailable(str(exc)) from exc
|
||
finally:
|
||
conn.close()
|
||
|
||
def save_result(
|
||
self,
|
||
oms_id: int,
|
||
deal_flag: int,
|
||
deal_result: str,
|
||
cart_rows: list[dict[str, Any]],
|
||
) -> None:
|
||
conn = self._connect()
|
||
try:
|
||
with conn.cursor() as cur:
|
||
for row in cart_rows:
|
||
payload = {key: row.get(key) for key in _CART_BIND_KEYS}
|
||
payload["create_user_name"] = DEAL_USER_NAME
|
||
cur.execute(_INSERT_CART_SQL, payload)
|
||
cur.execute(
|
||
_COMPLETE_SQL,
|
||
{
|
||
"deal_flag": deal_flag,
|
||
"deal_result": deal_result,
|
||
"deal_user_name": DEAL_USER_NAME,
|
||
"oms_id": oms_id,
|
||
},
|
||
)
|
||
conn.commit()
|
||
except Exception as exc:
|
||
try:
|
||
conn.rollback()
|
||
except Exception:
|
||
pass
|
||
raise RepoUnavailable(str(exc)) from exc
|
||
finally:
|
||
conn.close()
|
||
|
||
|
||
def _mapping_from_cursor(cur, rec) -> MappingRow:
|
||
cols = [item[0].lower() for item in cur.description]
|
||
data = dict(zip(cols, rec))
|
||
return MappingRow(
|
||
fid=int(data["fid"]),
|
||
oms_id=int(data["oms_id"]),
|
||
bar_code=str(data.get("bar_code") or ""),
|
||
sale_price=_float_or_none(data.get("sale_price")),
|
||
plan_purchase_qty=_float_or_none(data.get("plan_purchase_qty")),
|
||
approval_no=str(data.get("approval_no") or ""),
|
||
goods_name=str(data.get("goods_name") or ""),
|
||
goods_spec=str(data.get("goods_spec") or ""),
|
||
manufacturer=str(data.get("manufacturer") or ""),
|
||
org_code=str(data.get("org_code") or ""),
|
||
deal_flag=int(data.get("deal_flag") or 0),
|
||
)
|
||
|
||
|
||
def _float_or_none(value: object) -> float | None:
|
||
if value is None or value == "":
|
||
return None
|
||
return float(value)
|