feat: integer cents money handling, order page fixes, and vendor filter persistence
Money Handling Architecture: - Store all monetary values as integer cents (€105.91 = 10591) - Add app/utils/money.py with Money class and conversion helpers - Add static/shared/js/money.js for frontend formatting - Update all database models to use _cents columns (Product, Order, etc.) - Update CSV processor to convert prices to cents on import - Add Alembic migration for Float to Integer conversion - Create .architecture-rules/money.yaml with 7 validation rules - Add docs/architecture/money-handling.md documentation Order Details Page Fixes: - Fix customer name showing 'undefined undefined' - use flat field names - Fix vendor info empty - add vendor_name/vendor_code to OrderDetailResponse - Fix shipping address using wrong nested object structure - Enrich order detail API response with vendor info Vendor Filter Persistence Fixes: - Fix orders.js: restoreSavedVendor now sets selectedVendor and filters - Fix orders.js: init() only loads orders if no saved vendor to restore - Fix marketplace-letzshop.js: restoreSavedVendor calls selectVendor() - Fix marketplace-letzshop.js: clearVendorSelection clears TomSelect dropdown - Align vendor selector placeholder text between pages 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
178
tests/integration/api/v1/vendor/test_letzshop.py
vendored
178
tests/integration/api/v1/vendor/test_letzshop.py
vendored
@@ -238,50 +238,105 @@ class TestVendorLetzshopOrdersAPI:
|
||||
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
|
||||
):
|
||||
"""Test listing orders with status filter."""
|
||||
from models.database.letzshop import LetzshopOrder
|
||||
from models.database.order import Order
|
||||
|
||||
# Create test orders
|
||||
order1 = LetzshopOrder(
|
||||
# Create test orders using unified Order model with all required fields
|
||||
order1 = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
letzshop_order_id="order_1",
|
||||
letzshop_state="unconfirmed",
|
||||
sync_status="pending",
|
||||
customer_id=1,
|
||||
order_number=f"LS-{test_vendor_with_vendor_user.id}-order_1",
|
||||
channel="letzshop",
|
||||
external_order_id="order_1",
|
||||
status="pending",
|
||||
customer_first_name="Test",
|
||||
customer_last_name="User",
|
||||
customer_email="test1@example.com",
|
||||
ship_first_name="Test",
|
||||
ship_last_name="User",
|
||||
ship_address_line_1="123 Test Street",
|
||||
ship_city="Luxembourg",
|
||||
ship_postal_code="1234",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="User",
|
||||
bill_address_line_1="123 Test Street",
|
||||
bill_city="Luxembourg",
|
||||
bill_postal_code="1234",
|
||||
bill_country_iso="LU",
|
||||
total_amount_cents=10000,
|
||||
currency="EUR",
|
||||
)
|
||||
order2 = LetzshopOrder(
|
||||
order2 = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
letzshop_order_id="order_2",
|
||||
letzshop_state="confirmed",
|
||||
sync_status="confirmed",
|
||||
customer_id=1,
|
||||
order_number=f"LS-{test_vendor_with_vendor_user.id}-order_2",
|
||||
channel="letzshop",
|
||||
external_order_id="order_2",
|
||||
status="processing",
|
||||
customer_first_name="Test",
|
||||
customer_last_name="User",
|
||||
customer_email="test2@example.com",
|
||||
ship_first_name="Test",
|
||||
ship_last_name="User",
|
||||
ship_address_line_1="456 Test Avenue",
|
||||
ship_city="Luxembourg",
|
||||
ship_postal_code="5678",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="User",
|
||||
bill_address_line_1="456 Test Avenue",
|
||||
bill_city="Luxembourg",
|
||||
bill_postal_code="5678",
|
||||
bill_country_iso="LU",
|
||||
total_amount_cents=20000,
|
||||
currency="EUR",
|
||||
)
|
||||
db.add_all([order1, order2])
|
||||
db.commit()
|
||||
|
||||
# List pending only
|
||||
response = client.get(
|
||||
"/api/v1/vendor/letzshop/orders?sync_status=pending",
|
||||
"/api/v1/vendor/letzshop/orders?status=pending",
|
||||
headers=vendor_user_headers,
|
||||
)
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["total"] == 1
|
||||
assert data["orders"][0]["sync_status"] == "pending"
|
||||
assert data["orders"][0]["status"] == "pending"
|
||||
|
||||
def test_get_order_detail(
|
||||
self, client, db, vendor_user_headers, test_vendor_with_vendor_user
|
||||
):
|
||||
"""Test getting order detail."""
|
||||
from models.database.letzshop import LetzshopOrder
|
||||
from models.database.order import Order
|
||||
|
||||
order = LetzshopOrder(
|
||||
order = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
letzshop_order_id="order_detail_test",
|
||||
letzshop_shipment_id="shipment_1",
|
||||
letzshop_state="unconfirmed",
|
||||
customer_id=1,
|
||||
order_number=f"LS-{test_vendor_with_vendor_user.id}-order_detail_test",
|
||||
channel="letzshop",
|
||||
external_order_id="order_detail_test",
|
||||
external_shipment_id="shipment_1",
|
||||
status="pending",
|
||||
customer_first_name="Test",
|
||||
customer_last_name="User",
|
||||
customer_email="test@example.com",
|
||||
total_amount="99.99",
|
||||
sync_status="pending",
|
||||
raw_order_data={"test": "data"},
|
||||
ship_first_name="Test",
|
||||
ship_last_name="User",
|
||||
ship_address_line_1="123 Test Street",
|
||||
ship_city="Luxembourg",
|
||||
ship_postal_code="1234",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="User",
|
||||
bill_address_line_1="123 Test Street",
|
||||
bill_city="Luxembourg",
|
||||
bill_postal_code="1234",
|
||||
bill_country_iso="LU",
|
||||
total_amount_cents=9999, # €99.99
|
||||
currency="EUR",
|
||||
external_data={"test": "data"},
|
||||
)
|
||||
db.add(order)
|
||||
db.commit()
|
||||
@@ -293,9 +348,9 @@ class TestVendorLetzshopOrdersAPI:
|
||||
|
||||
assert response.status_code == 200
|
||||
data = response.json()
|
||||
assert data["letzshop_order_id"] == "order_detail_test"
|
||||
assert data["external_order_id"] == "order_detail_test"
|
||||
assert data["customer_email"] == "test@example.com"
|
||||
assert data["raw_order_data"] == {"test": "data"}
|
||||
assert data["external_data"] == {"test": "data"}
|
||||
|
||||
def test_get_order_not_found(
|
||||
self, client, vendor_user_headers, test_vendor_with_vendor_user
|
||||
@@ -393,18 +448,50 @@ class TestVendorLetzshopFulfillmentAPI:
|
||||
test_vendor_with_vendor_user,
|
||||
):
|
||||
"""Test confirming an order."""
|
||||
from models.database.letzshop import LetzshopOrder
|
||||
from models.database.order import Order, OrderItem
|
||||
|
||||
# Create test order
|
||||
order = LetzshopOrder(
|
||||
# Create test order using unified Order model with all required fields
|
||||
order = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
letzshop_order_id="order_confirm",
|
||||
letzshop_shipment_id="shipment_1",
|
||||
letzshop_state="unconfirmed",
|
||||
sync_status="pending",
|
||||
inventory_units=[{"id": "unit_1", "state": "unconfirmed"}],
|
||||
customer_id=1,
|
||||
order_number=f"LS-{test_vendor_with_vendor_user.id}-order_confirm",
|
||||
channel="letzshop",
|
||||
external_order_id="order_confirm",
|
||||
external_shipment_id="shipment_1",
|
||||
status="pending",
|
||||
customer_first_name="Test",
|
||||
customer_last_name="User",
|
||||
customer_email="test@example.com",
|
||||
ship_first_name="Test",
|
||||
ship_last_name="User",
|
||||
ship_address_line_1="123 Test Street",
|
||||
ship_city="Luxembourg",
|
||||
ship_postal_code="1234",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="User",
|
||||
bill_address_line_1="123 Test Street",
|
||||
bill_city="Luxembourg",
|
||||
bill_postal_code="1234",
|
||||
bill_country_iso="LU",
|
||||
total_amount_cents=10000,
|
||||
currency="EUR",
|
||||
)
|
||||
db.add(order)
|
||||
db.flush()
|
||||
|
||||
# Add order item
|
||||
item = OrderItem(
|
||||
order_id=order.id,
|
||||
product_id=1,
|
||||
product_name="Test Product",
|
||||
quantity=1,
|
||||
unit_price_cents=10000,
|
||||
total_price_cents=10000,
|
||||
external_item_id="unit_1",
|
||||
item_state="unconfirmed",
|
||||
)
|
||||
db.add(item)
|
||||
db.commit()
|
||||
|
||||
# Save credentials
|
||||
@@ -447,14 +534,33 @@ class TestVendorLetzshopFulfillmentAPI:
|
||||
test_vendor_with_vendor_user,
|
||||
):
|
||||
"""Test setting tracking information."""
|
||||
from models.database.letzshop import LetzshopOrder
|
||||
from models.database.order import Order
|
||||
|
||||
order = LetzshopOrder(
|
||||
order = Order(
|
||||
vendor_id=test_vendor_with_vendor_user.id,
|
||||
letzshop_order_id="order_tracking",
|
||||
letzshop_shipment_id="shipment_track",
|
||||
letzshop_state="confirmed",
|
||||
sync_status="confirmed",
|
||||
customer_id=1,
|
||||
order_number=f"LS-{test_vendor_with_vendor_user.id}-order_tracking",
|
||||
channel="letzshop",
|
||||
external_order_id="order_tracking",
|
||||
external_shipment_id="shipment_track",
|
||||
status="processing", # confirmed state
|
||||
customer_first_name="Test",
|
||||
customer_last_name="User",
|
||||
customer_email="test@example.com",
|
||||
ship_first_name="Test",
|
||||
ship_last_name="User",
|
||||
ship_address_line_1="123 Test Street",
|
||||
ship_city="Luxembourg",
|
||||
ship_postal_code="1234",
|
||||
ship_country_iso="LU",
|
||||
bill_first_name="Test",
|
||||
bill_last_name="User",
|
||||
bill_address_line_1="123 Test Street",
|
||||
bill_city="Luxembourg",
|
||||
bill_postal_code="1234",
|
||||
bill_country_iso="LU",
|
||||
total_amount_cents=10000,
|
||||
currency="EUR",
|
||||
)
|
||||
db.add(order)
|
||||
db.commit()
|
||||
|
||||
Reference in New Issue
Block a user