feat: add Printify order submission and fulfilment tracking
Submit paid orders to Printify via provider API with idempotent guards, Stripe address mapping, and error handling. Track fulfilment status through submitted → processing → shipped → delivered via webhook-driven updates (primary) and Oban Cron polling fallback. - 9 fulfilment fields on orders (status, provider IDs, tracking, timestamps) - OrderSubmissionWorker with retry logic, auto-enqueued after Stripe payment - FulfilmentStatusWorker polls every 30 mins for missed webhook events - Printify order webhook handlers (sent-to-production, shipment, delivered) - Admin UI: fulfilment column in table, fulfilment card with tracking info, submit/retry and refresh buttons on order detail - Mox provider mocking for test isolation (Provider.for_type configurable) - 33 new tests (555 total), verified against real Printify API Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -115,5 +115,76 @@ defmodule SimpleshopThemeWeb.AdminLive.OrdersTest do
|
||||
{:error, {:live_redirect, %{to: "/admin/orders"}}} =
|
||||
live(conn, ~p"/admin/orders/#{fake_id}")
|
||||
end
|
||||
|
||||
test "shows fulfilment card", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Fulfilment"
|
||||
assert html =~ "unfulfilled"
|
||||
end
|
||||
|
||||
test "shows submit button for paid unfulfilled orders", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Submit to provider"
|
||||
end
|
||||
|
||||
test "shows retry button for failed fulfilment", %{conn: conn} do
|
||||
order = order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, order} =
|
||||
SimpleshopTheme.Orders.update_fulfilment(order, %{fulfilment_status: "failed"})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Retry submission"
|
||||
end
|
||||
|
||||
test "shows refresh button for submitted orders", %{conn: conn} do
|
||||
{order, _v, _p, _c} =
|
||||
SimpleshopTheme.OrdersFixtures.submitted_order_fixture()
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "Refresh status"
|
||||
end
|
||||
|
||||
test "shows tracking info when available", %{conn: conn} do
|
||||
{order, _v, _p, _c} =
|
||||
SimpleshopTheme.OrdersFixtures.submitted_order_fixture()
|
||||
|
||||
{:ok, order} =
|
||||
SimpleshopTheme.Orders.update_fulfilment(order, %{
|
||||
fulfilment_status: "shipped",
|
||||
tracking_number: "TRACK123",
|
||||
tracking_url: "https://track.example.com/TRACK123",
|
||||
shipped_at: DateTime.utc_now() |> DateTime.truncate(:second)
|
||||
})
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders/#{order}")
|
||||
|
||||
assert html =~ "TRACK123"
|
||||
assert html =~ "https://track.example.com/TRACK123"
|
||||
end
|
||||
end
|
||||
|
||||
describe "order list fulfilment column" do
|
||||
setup %{conn: conn, user: user} do
|
||||
conn = log_in_user(conn, user)
|
||||
%{conn: conn}
|
||||
end
|
||||
|
||||
test "shows fulfilment badge in table", %{conn: conn} do
|
||||
order_fixture(payment_status: "paid")
|
||||
|
||||
{:ok, _view, html} = live(conn, ~p"/admin/orders")
|
||||
|
||||
assert html =~ "Fulfilment"
|
||||
assert html =~ "unfulfilled"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user