feat: CSV utilities for order entity serialization

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
2026-04-21 15:50:23 +08:00
parent 3239fd1032
commit dd5edfe03c
2 changed files with 202 additions and 0 deletions

View File

@@ -0,0 +1,70 @@
import csv
from datetime import datetime
from pathlib import Path
from typing import Any
CSV_COLUMNS = [
"PartitionKey",
"RowKey",
"OrderTime",
"ReceiveTime",
"revenue",
"platformOrder",
"prodCount",
"pfId",
"prodId",
"prodPrice",
"state",
"ver",
"customData",
]
def _format_value(val: Any) -> str:
if val is None:
return ""
if isinstance(val, datetime):
return val.isoformat()
return str(val)
def entity_to_row(entity: dict[str, Any]) -> dict[str, str]:
return {col: _format_value(entity.get(col)) for col in CSV_COLUMNS}
def _parse_row(raw: dict[str, str]) -> dict[str, Any]:
result: dict[str, Any] = {}
for col in CSV_COLUMNS:
val = raw.get(col, "")
if val == "":
result[col] = None
continue
if col in ("OrderTime", "ReceiveTime"):
result[col] = datetime.fromisoformat(val)
elif col in ("revenue", "prodPrice"):
result[col] = float(val)
elif col in ("prodCount", "state", "ver"):
result[col] = int(val)
else:
result[col] = val
return result
def row_to_entity(raw: dict[str, str]) -> dict[str, Any]:
return _parse_row(raw)
def write_csv(path: Path, entities: list[dict[str, Any]]) -> None:
path.parent.mkdir(parents=True, exist_ok=True)
with open(path, "w", newline="") as f:
writer = csv.DictWriter(f, fieldnames=CSV_COLUMNS)
writer.writeheader()
for entity in entities:
writer.writerow(entity_to_row(entity))
def read_csv(path: Path):
with open(path, newline="") as f:
reader = csv.DictReader(f)
for row in reader:
yield _parse_row(row)

132
tests/test_csv_utils.py Normal file
View File

@@ -0,0 +1,132 @@
import csv
from datetime import datetime, timezone
from pathlib import Path
from order_bak.csv_utils import (
CSV_COLUMNS,
entity_to_row,
row_to_entity,
write_csv,
read_csv,
)
def test_csv_columns_defined():
assert "PartitionKey" in CSV_COLUMNS
assert "RowKey" in CSV_COLUMNS
assert "OrderTime" in CSV_COLUMNS
assert "state" in CSV_COLUMNS
assert len(CSV_COLUMNS) == 13
def test_entity_to_row_converts_datetime():
entity = {
"PartitionKey": "user1",
"RowKey": "order1",
"OrderTime": datetime(2025, 6, 15, 10, 30, 0, tzinfo=timezone.utc),
"ReceiveTime": datetime(2025, 6, 15, 11, 0, 0, tzinfo=timezone.utc),
"revenue": 99.5,
"platformOrder": "plat123",
"prodCount": 2,
"pfId": "user1",
"prodId": "prod1",
"prodPrice": 49.75,
"state": 1,
"ver": 3,
"customData": '{"key":"val"}',
}
row = entity_to_row(entity)
assert row["OrderTime"] == "2025-06-15T10:30:00+00:00"
assert row["ReceiveTime"] == "2025-06-15T11:00:00+00:00"
assert row["revenue"] == "99.5"
assert row["state"] == "1"
def test_entity_to_row_handles_none():
entity = {
"PartitionKey": "user1",
"RowKey": "order1",
"OrderTime": datetime(2025, 1, 1, tzinfo=timezone.utc),
"ReceiveTime": None,
"revenue": None,
"platformOrder": None,
"prodCount": None,
"pfId": None,
"prodId": None,
"prodPrice": None,
"state": 0,
"ver": None,
"customData": None,
}
row = entity_to_row(entity)
assert row["ReceiveTime"] == ""
assert row["revenue"] == ""
def test_row_to_entity_roundtrip(tmp_path):
original = {
"PartitionKey": "user1",
"RowKey": "order1",
"OrderTime": "2025-06-15T10:30:00+00:00",
"ReceiveTime": "",
"revenue": "99.5",
"platformOrder": "plat123",
"prodCount": "2",
"pfId": "user1",
"prodId": "prod1",
"prodPrice": "49.75",
"state": "1",
"ver": "3",
"customData": '{"key":"val"}',
}
entity = row_to_entity(original)
assert entity["PartitionKey"] == "user1"
assert entity["state"] == 1
assert entity["revenue"] == 99.5
assert entity["prodCount"] == 2
assert entity["ReceiveTime"] is None
def test_write_and_read_csv(tmp_path):
entities = [
{
"PartitionKey": "user1",
"RowKey": "order1",
"OrderTime": datetime(2025, 6, 15, 10, 30, tzinfo=timezone.utc),
"ReceiveTime": None,
"revenue": 99.5,
"platformOrder": "p1",
"prodCount": 2,
"pfId": "user1",
"prodId": "prod1",
"prodPrice": 49.75,
"state": 1,
"ver": 3,
"customData": None,
},
{
"PartitionKey": "user2",
"RowKey": "order2",
"OrderTime": datetime(2025, 6, 16, 12, 0, tzinfo=timezone.utc),
"ReceiveTime": datetime(2025, 6, 16, 13, 0, tzinfo=timezone.utc),
"revenue": 10.0,
"platformOrder": "p2",
"prodCount": 1,
"pfId": "user2",
"prodId": "prod2",
"prodPrice": 10.0,
"state": 1,
"ver": 3,
"customData": '{"note":"test"}',
},
]
csv_path = tmp_path / "test.csv"
write_csv(csv_path, entities)
result = list(read_csv(csv_path))
assert len(result) == 2
assert result[0]["PartitionKey"] == "user1"
assert result[1]["PartitionKey"] == "user2"
assert result[1]["revenue"] == 10.0
assert result[0]["ReceiveTime"] is None
assert result[1]["ReceiveTime"] is not None