vonpay-medusa 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -626,6 +626,84 @@ const UpdateBanner = () => {
626
626
  ] }) });
627
627
  };
628
628
  adminSdk.defineWidgetConfig({ zone: "order.list.before" });
629
+ const EVENT_LABEL = {
630
+ "subscription.created": "Signed up",
631
+ "subscription.renewed": "Renewal paid",
632
+ "subscription.payment_failed": "Renewal declined",
633
+ "subscription.cancelled": "Cancelled",
634
+ "subscription.updated": "Changed"
635
+ };
636
+ const eventLabel = (type) => EVENT_LABEL[type] ?? "Other";
637
+ const amountLabel = (major, currency) => major && currency ? `${major} ${currency}` : "—";
638
+ const NOT_ENABLED_NOTE = `Vonpay is not running this store's subscriptions. To let it, set the payment provider's subscriptions option to "vonpay", register the plugin's subscriptions module in medusa-config, run npx medusa db:migrate and restart — the setup check confirms each step.`;
639
+ const ORDERS_NOT_YET_NOTE = "Renewal orders are not created from these notifications yet: this list shows what Vonpay reported, so nothing here changes an order.";
640
+ const SUBSCRIPTION_PAGE_SIZE = 20;
641
+ function useSubscriptionEvents(page) {
642
+ return reactQuery.useQuery({
643
+ queryKey: ["vonpay-subscription-events", page.limit, page.offset],
644
+ queryFn: () => sdk.client.fetch("/admin/vonpay/subscriptions", { query: { limit: page.limit, offset: page.offset } }),
645
+ placeholderData: reactQuery.keepPreviousData
646
+ });
647
+ }
648
+ const pageCountFor = (count) => {
649
+ const remainder = count % SUBSCRIPTION_PAGE_SIZE;
650
+ return Math.max(1, (count - remainder) / SUBSCRIPTION_PAGE_SIZE + (remainder > 0 ? 1 : 0));
651
+ };
652
+ const when = (iso) => iso ? new Date(iso).toLocaleString() : "—";
653
+ const VonpaySubscriptionsPage = () => {
654
+ const [pageIndex, setPageIndex] = react.useState(0);
655
+ const { data, isLoading, isError } = useSubscriptionEvents({ limit: SUBSCRIPTION_PAGE_SIZE, offset: pageIndex * SUBSCRIPTION_PAGE_SIZE });
656
+ return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
657
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
658
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Vonpay subscriptions" }),
659
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Notifications from Vonpay's subscription billing, newest first." })
660
+ ] }),
661
+ isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-full" }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "error", children: "The list could not be loaded. Reload the page to try again." }) }) : !data?.enabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "info", children: NOT_ENABLED_NOTE }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
662
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: ORDERS_NOT_YET_NOTE }) }),
663
+ data.events.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "No subscription notifications yet." }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
664
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
665
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
666
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "What happened" }),
667
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Subscription" }),
668
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Period" }),
669
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Amount" }),
670
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Next bill" }),
671
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Received" })
672
+ ] }) }),
673
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: data.events.map((e) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
674
+ /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
675
+ eventLabel(e.type),
676
+ e.mode === "test" ? " (test)" : ""
677
+ ] }),
678
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "font-mono text-xs", children: e.subscription_id }),
679
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: e.billing_cycle ?? "—" }),
680
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: amountLabel(e.amount_major, e.currency) }),
681
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.next_bill_at) }),
682
+ /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.received_at) })
683
+ ] }, e.id)) })
684
+ ] }) }),
685
+ /* @__PURE__ */ jsxRuntime.jsx(
686
+ ui.Table.Pagination,
687
+ {
688
+ count: data.count,
689
+ pageSize: SUBSCRIPTION_PAGE_SIZE,
690
+ pageIndex,
691
+ pageCount: pageCountFor(data.count),
692
+ canPreviousPage: pageIndex > 0,
693
+ canNextPage: (pageIndex + 1) * SUBSCRIPTION_PAGE_SIZE < data.count,
694
+ previousPage: () => setPageIndex((p) => Math.max(0, p - 1)),
695
+ nextPage: () => setPageIndex((p) => p + 1)
696
+ }
697
+ )
698
+ ] })
699
+ ] })
700
+ ] });
701
+ };
702
+ const config$2 = adminSdk.defineRouteConfig({
703
+ label: "Vonpay subscriptions",
704
+ icon: icons.ArrowPath,
705
+ nested: "/orders"
706
+ });
629
707
  function useSetupCheck() {
630
708
  return reactQuery.useMutation({
631
709
  mutationFn: () => sdk.client.fetch("/admin/vonpay/setup-check", { method: "POST", body: {} }),
@@ -1050,7 +1128,7 @@ const HeldPaymentsPage = () => {
1050
1128
  /* @__PURE__ */ jsxRuntime.jsx(SetupCheckPanel, {})
1051
1129
  ] });
1052
1130
  };
1053
- const config$2 = adminSdk.defineRouteConfig({
1131
+ const config$1 = adminSdk.defineRouteConfig({
1054
1132
  label: "Held payments",
1055
1133
  icon: icons.ExclamationCircle,
1056
1134
  nested: "/orders"
@@ -1514,89 +1592,11 @@ const VonpayOffersPage = () => {
1514
1592
  ] })
1515
1593
  ] });
1516
1594
  };
1517
- const config$1 = adminSdk.defineRouteConfig({
1595
+ const config = adminSdk.defineRouteConfig({
1518
1596
  label: "One-click offers",
1519
1597
  icon: icons.Sparkles,
1520
1598
  nested: "/orders"
1521
1599
  });
1522
- const EVENT_LABEL = {
1523
- "subscription.created": "Signed up",
1524
- "subscription.renewed": "Renewal paid",
1525
- "subscription.payment_failed": "Renewal declined",
1526
- "subscription.cancelled": "Cancelled",
1527
- "subscription.updated": "Changed"
1528
- };
1529
- const eventLabel = (type) => EVENT_LABEL[type] ?? "Other";
1530
- const amountLabel = (major, currency) => major && currency ? `${major} ${currency}` : "—";
1531
- const NOT_ENABLED_NOTE = `Vonpay is not running this store's subscriptions. To let it, set the payment provider's subscriptions option to "vonpay", register the plugin's subscriptions module in medusa-config, run npx medusa db:migrate and restart — the setup check confirms each step.`;
1532
- const ORDERS_NOT_YET_NOTE = "Renewal orders are not created from these notifications yet: this list shows what Vonpay reported, so nothing here changes an order.";
1533
- const SUBSCRIPTION_PAGE_SIZE = 20;
1534
- function useSubscriptionEvents(page) {
1535
- return reactQuery.useQuery({
1536
- queryKey: ["vonpay-subscription-events", page.limit, page.offset],
1537
- queryFn: () => sdk.client.fetch("/admin/vonpay/subscriptions", { query: { limit: page.limit, offset: page.offset } }),
1538
- placeholderData: reactQuery.keepPreviousData
1539
- });
1540
- }
1541
- const pageCountFor = (count) => {
1542
- const remainder = count % SUBSCRIPTION_PAGE_SIZE;
1543
- return Math.max(1, (count - remainder) / SUBSCRIPTION_PAGE_SIZE + (remainder > 0 ? 1 : 0));
1544
- };
1545
- const when = (iso) => iso ? new Date(iso).toLocaleString() : "—";
1546
- const VonpaySubscriptionsPage = () => {
1547
- const [pageIndex, setPageIndex] = react.useState(0);
1548
- const { data, isLoading, isError } = useSubscriptionEvents({ limit: SUBSCRIPTION_PAGE_SIZE, offset: pageIndex * SUBSCRIPTION_PAGE_SIZE });
1549
- return /* @__PURE__ */ jsxRuntime.jsxs(ui.Container, { className: "divide-y p-0", children: [
1550
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-6 py-4", children: [
1551
- /* @__PURE__ */ jsxRuntime.jsx(ui.Heading, { level: "h1", children: "Vonpay subscriptions" }),
1552
- /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: "Notifications from Vonpay's subscription billing, newest first." })
1553
- ] }),
1554
- isLoading ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Skeleton, { className: "h-8 w-full" }) }) : isError ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "error", children: "The list could not be loaded. Reload the page to try again." }) }) : !data?.enabled ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Alert, { variant: "info", children: NOT_ENABLED_NOTE }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1555
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { size: "small", className: "text-ui-fg-subtle", children: ORDERS_NOT_YET_NOTE }) }),
1556
- data.events.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsxRuntime.jsx(ui.Text, { children: "No subscription notifications yet." }) }) : /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
1557
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table, { children: [
1558
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Header, { children: /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1559
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "What happened" }),
1560
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Subscription" }),
1561
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Period" }),
1562
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Amount" }),
1563
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Next bill" }),
1564
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.HeaderCell, { children: "Received" })
1565
- ] }) }),
1566
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Body, { children: data.events.map((e) => /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Row, { children: [
1567
- /* @__PURE__ */ jsxRuntime.jsxs(ui.Table.Cell, { children: [
1568
- eventLabel(e.type),
1569
- e.mode === "test" ? " (test)" : ""
1570
- ] }),
1571
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { className: "font-mono text-xs", children: e.subscription_id }),
1572
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: e.billing_cycle ?? "—" }),
1573
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: amountLabel(e.amount_major, e.currency) }),
1574
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.next_bill_at) }),
1575
- /* @__PURE__ */ jsxRuntime.jsx(ui.Table.Cell, { children: when(e.received_at) })
1576
- ] }, e.id)) })
1577
- ] }) }),
1578
- /* @__PURE__ */ jsxRuntime.jsx(
1579
- ui.Table.Pagination,
1580
- {
1581
- count: data.count,
1582
- pageSize: SUBSCRIPTION_PAGE_SIZE,
1583
- pageIndex,
1584
- pageCount: pageCountFor(data.count),
1585
- canPreviousPage: pageIndex > 0,
1586
- canNextPage: (pageIndex + 1) * SUBSCRIPTION_PAGE_SIZE < data.count,
1587
- previousPage: () => setPageIndex((p) => Math.max(0, p - 1)),
1588
- nextPage: () => setPageIndex((p) => p + 1)
1589
- }
1590
- )
1591
- ] })
1592
- ] })
1593
- ] });
1594
- };
1595
- const config = adminSdk.defineRouteConfig({
1596
- label: "Vonpay subscriptions",
1597
- icon: icons.ArrowPath,
1598
- nested: "/orders"
1599
- });
1600
1600
  const i18nTranslations0 = {};
1601
1601
  const widgetModule = { widgets: [
1602
1602
  {
@@ -1618,18 +1618,18 @@ const widgetModule = { widgets: [
1618
1618
  const routeModule = {
1619
1619
  routes: [
1620
1620
  {
1621
- Component: HeldPaymentsPage,
1622
- path: "/vonpay-holds",
1621
+ Component: VonpaySubscriptionsPage,
1622
+ path: "/vonpay-subscriptions",
1623
1623
  handle: { label: config$2.label, translationNs: config$2.translationNs }
1624
1624
  },
1625
1625
  {
1626
- Component: VonpayOffersPage,
1627
- path: "/vonpay-offers",
1626
+ Component: HeldPaymentsPage,
1627
+ path: "/vonpay-holds",
1628
1628
  handle: { label: config$1.label, translationNs: config$1.translationNs }
1629
1629
  },
1630
1630
  {
1631
- Component: VonpaySubscriptionsPage,
1632
- path: "/vonpay-subscriptions",
1631
+ Component: VonpayOffersPage,
1632
+ path: "/vonpay-offers",
1633
1633
  handle: { label: config.label, translationNs: config.translationNs }
1634
1634
  }
1635
1635
  ]
@@ -1637,24 +1637,24 @@ const routeModule = {
1637
1637
  const menuItemModule = {
1638
1638
  menuItems: [
1639
1639
  {
1640
- label: config$2.label,
1641
- icon: config$2.icon,
1640
+ label: config$1.label,
1641
+ icon: config$1.icon,
1642
1642
  path: "/vonpay-holds",
1643
1643
  nested: "/orders",
1644
1644
  rank: void 0,
1645
1645
  translationNs: void 0
1646
1646
  },
1647
1647
  {
1648
- label: config$1.label,
1649
- icon: config$1.icon,
1648
+ label: config.label,
1649
+ icon: config.icon,
1650
1650
  path: "/vonpay-offers",
1651
1651
  nested: "/orders",
1652
1652
  rank: void 0,
1653
1653
  translationNs: void 0
1654
1654
  },
1655
1655
  {
1656
- label: config.label,
1657
- icon: config.icon,
1656
+ label: config$2.label,
1657
+ icon: config$2.icon,
1658
1658
  path: "/vonpay-subscriptions",
1659
1659
  nested: "/orders",
1660
1660
  rank: void 0,
@@ -1,10 +1,10 @@
1
1
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
2
2
  import { defineWidgetConfig, defineRouteConfig } from "@medusajs/admin-sdk";
3
- import { Alert, Text, Button, Container, Heading, StatusBadge, Select, Skeleton, Table, Tooltip, Copy, Drawer, CodeBlock, Prompt, Label, Input, Textarea, usePrompt, Switch, IconButton } from "@medusajs/ui";
3
+ import { Alert, Text, Button, Container, Heading, Skeleton, Table, StatusBadge, Select, Tooltip, Copy, Drawer, CodeBlock, Prompt, Label, Input, Textarea, usePrompt, Switch, IconButton } from "@medusajs/ui";
4
4
  import { Link } from "react-router-dom";
5
5
  import { useQuery, keepPreviousData, useQueryClient, useMutation } from "@tanstack/react-query";
6
6
  import Medusa from "@medusajs/js-sdk";
7
- import { ExclamationCircle, XMarkMini, Sparkles, ArrowUpMini, ArrowDownMini, Trash, ArrowPath } from "@medusajs/icons";
7
+ import { ArrowPath, ExclamationCircle, XMarkMini, Sparkles, ArrowUpMini, ArrowDownMini, Trash } from "@medusajs/icons";
8
8
  import { useState } from "react";
9
9
  const REASON_COPY = {
10
10
  deleted_while_charged: {
@@ -623,6 +623,84 @@ const UpdateBanner = () => {
623
623
  ] }) });
624
624
  };
625
625
  defineWidgetConfig({ zone: "order.list.before" });
626
+ const EVENT_LABEL = {
627
+ "subscription.created": "Signed up",
628
+ "subscription.renewed": "Renewal paid",
629
+ "subscription.payment_failed": "Renewal declined",
630
+ "subscription.cancelled": "Cancelled",
631
+ "subscription.updated": "Changed"
632
+ };
633
+ const eventLabel = (type) => EVENT_LABEL[type] ?? "Other";
634
+ const amountLabel = (major, currency) => major && currency ? `${major} ${currency}` : "—";
635
+ const NOT_ENABLED_NOTE = `Vonpay is not running this store's subscriptions. To let it, set the payment provider's subscriptions option to "vonpay", register the plugin's subscriptions module in medusa-config, run npx medusa db:migrate and restart — the setup check confirms each step.`;
636
+ const ORDERS_NOT_YET_NOTE = "Renewal orders are not created from these notifications yet: this list shows what Vonpay reported, so nothing here changes an order.";
637
+ const SUBSCRIPTION_PAGE_SIZE = 20;
638
+ function useSubscriptionEvents(page) {
639
+ return useQuery({
640
+ queryKey: ["vonpay-subscription-events", page.limit, page.offset],
641
+ queryFn: () => sdk.client.fetch("/admin/vonpay/subscriptions", { query: { limit: page.limit, offset: page.offset } }),
642
+ placeholderData: keepPreviousData
643
+ });
644
+ }
645
+ const pageCountFor = (count) => {
646
+ const remainder = count % SUBSCRIPTION_PAGE_SIZE;
647
+ return Math.max(1, (count - remainder) / SUBSCRIPTION_PAGE_SIZE + (remainder > 0 ? 1 : 0));
648
+ };
649
+ const when = (iso) => iso ? new Date(iso).toLocaleString() : "—";
650
+ const VonpaySubscriptionsPage = () => {
651
+ const [pageIndex, setPageIndex] = useState(0);
652
+ const { data, isLoading, isError } = useSubscriptionEvents({ limit: SUBSCRIPTION_PAGE_SIZE, offset: pageIndex * SUBSCRIPTION_PAGE_SIZE });
653
+ return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
654
+ /* @__PURE__ */ jsxs("div", { className: "px-6 py-4", children: [
655
+ /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Vonpay subscriptions" }),
656
+ /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Notifications from Vonpay's subscription billing, newest first." })
657
+ ] }),
658
+ isLoading ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }) }) : isError ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Alert, { variant: "error", children: "The list could not be loaded. Reload the page to try again." }) }) : !data?.enabled ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Alert, { variant: "info", children: NOT_ENABLED_NOTE }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
659
+ /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: ORDERS_NOT_YET_NOTE }) }),
660
+ data.events.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { children: "No subscription notifications yet." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
661
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs(Table, { children: [
662
+ /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
663
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "What happened" }),
664
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Subscription" }),
665
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Period" }),
666
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Amount" }),
667
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Next bill" }),
668
+ /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Received" })
669
+ ] }) }),
670
+ /* @__PURE__ */ jsx(Table.Body, { children: data.events.map((e) => /* @__PURE__ */ jsxs(Table.Row, { children: [
671
+ /* @__PURE__ */ jsxs(Table.Cell, { children: [
672
+ eventLabel(e.type),
673
+ e.mode === "test" ? " (test)" : ""
674
+ ] }),
675
+ /* @__PURE__ */ jsx(Table.Cell, { className: "font-mono text-xs", children: e.subscription_id }),
676
+ /* @__PURE__ */ jsx(Table.Cell, { children: e.billing_cycle ?? "—" }),
677
+ /* @__PURE__ */ jsx(Table.Cell, { children: amountLabel(e.amount_major, e.currency) }),
678
+ /* @__PURE__ */ jsx(Table.Cell, { children: when(e.next_bill_at) }),
679
+ /* @__PURE__ */ jsx(Table.Cell, { children: when(e.received_at) })
680
+ ] }, e.id)) })
681
+ ] }) }),
682
+ /* @__PURE__ */ jsx(
683
+ Table.Pagination,
684
+ {
685
+ count: data.count,
686
+ pageSize: SUBSCRIPTION_PAGE_SIZE,
687
+ pageIndex,
688
+ pageCount: pageCountFor(data.count),
689
+ canPreviousPage: pageIndex > 0,
690
+ canNextPage: (pageIndex + 1) * SUBSCRIPTION_PAGE_SIZE < data.count,
691
+ previousPage: () => setPageIndex((p) => Math.max(0, p - 1)),
692
+ nextPage: () => setPageIndex((p) => p + 1)
693
+ }
694
+ )
695
+ ] })
696
+ ] })
697
+ ] });
698
+ };
699
+ const config$2 = defineRouteConfig({
700
+ label: "Vonpay subscriptions",
701
+ icon: ArrowPath,
702
+ nested: "/orders"
703
+ });
626
704
  function useSetupCheck() {
627
705
  return useMutation({
628
706
  mutationFn: () => sdk.client.fetch("/admin/vonpay/setup-check", { method: "POST", body: {} }),
@@ -1047,7 +1125,7 @@ const HeldPaymentsPage = () => {
1047
1125
  /* @__PURE__ */ jsx(SetupCheckPanel, {})
1048
1126
  ] });
1049
1127
  };
1050
- const config$2 = defineRouteConfig({
1128
+ const config$1 = defineRouteConfig({
1051
1129
  label: "Held payments",
1052
1130
  icon: ExclamationCircle,
1053
1131
  nested: "/orders"
@@ -1511,89 +1589,11 @@ const VonpayOffersPage = () => {
1511
1589
  ] })
1512
1590
  ] });
1513
1591
  };
1514
- const config$1 = defineRouteConfig({
1592
+ const config = defineRouteConfig({
1515
1593
  label: "One-click offers",
1516
1594
  icon: Sparkles,
1517
1595
  nested: "/orders"
1518
1596
  });
1519
- const EVENT_LABEL = {
1520
- "subscription.created": "Signed up",
1521
- "subscription.renewed": "Renewal paid",
1522
- "subscription.payment_failed": "Renewal declined",
1523
- "subscription.cancelled": "Cancelled",
1524
- "subscription.updated": "Changed"
1525
- };
1526
- const eventLabel = (type) => EVENT_LABEL[type] ?? "Other";
1527
- const amountLabel = (major, currency) => major && currency ? `${major} ${currency}` : "—";
1528
- const NOT_ENABLED_NOTE = `Vonpay is not running this store's subscriptions. To let it, set the payment provider's subscriptions option to "vonpay", register the plugin's subscriptions module in medusa-config, run npx medusa db:migrate and restart — the setup check confirms each step.`;
1529
- const ORDERS_NOT_YET_NOTE = "Renewal orders are not created from these notifications yet: this list shows what Vonpay reported, so nothing here changes an order.";
1530
- const SUBSCRIPTION_PAGE_SIZE = 20;
1531
- function useSubscriptionEvents(page) {
1532
- return useQuery({
1533
- queryKey: ["vonpay-subscription-events", page.limit, page.offset],
1534
- queryFn: () => sdk.client.fetch("/admin/vonpay/subscriptions", { query: { limit: page.limit, offset: page.offset } }),
1535
- placeholderData: keepPreviousData
1536
- });
1537
- }
1538
- const pageCountFor = (count) => {
1539
- const remainder = count % SUBSCRIPTION_PAGE_SIZE;
1540
- return Math.max(1, (count - remainder) / SUBSCRIPTION_PAGE_SIZE + (remainder > 0 ? 1 : 0));
1541
- };
1542
- const when = (iso) => iso ? new Date(iso).toLocaleString() : "—";
1543
- const VonpaySubscriptionsPage = () => {
1544
- const [pageIndex, setPageIndex] = useState(0);
1545
- const { data, isLoading, isError } = useSubscriptionEvents({ limit: SUBSCRIPTION_PAGE_SIZE, offset: pageIndex * SUBSCRIPTION_PAGE_SIZE });
1546
- return /* @__PURE__ */ jsxs(Container, { className: "divide-y p-0", children: [
1547
- /* @__PURE__ */ jsxs("div", { className: "px-6 py-4", children: [
1548
- /* @__PURE__ */ jsx(Heading, { level: "h1", children: "Vonpay subscriptions" }),
1549
- /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: "Notifications from Vonpay's subscription billing, newest first." })
1550
- ] }),
1551
- isLoading ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-full" }) }) : isError ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Alert, { variant: "error", children: "The list could not be loaded. Reload the page to try again." }) }) : !data?.enabled ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Alert, { variant: "info", children: NOT_ENABLED_NOTE }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1552
- /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { size: "small", className: "text-ui-fg-subtle", children: ORDERS_NOT_YET_NOTE }) }),
1553
- data.events.length === 0 ? /* @__PURE__ */ jsx("div", { className: "px-6 py-4", children: /* @__PURE__ */ jsx(Text, { children: "No subscription notifications yet." }) }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1554
- /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs(Table, { children: [
1555
- /* @__PURE__ */ jsx(Table.Header, { children: /* @__PURE__ */ jsxs(Table.Row, { children: [
1556
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "What happened" }),
1557
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Subscription" }),
1558
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Period" }),
1559
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Amount" }),
1560
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Next bill" }),
1561
- /* @__PURE__ */ jsx(Table.HeaderCell, { children: "Received" })
1562
- ] }) }),
1563
- /* @__PURE__ */ jsx(Table.Body, { children: data.events.map((e) => /* @__PURE__ */ jsxs(Table.Row, { children: [
1564
- /* @__PURE__ */ jsxs(Table.Cell, { children: [
1565
- eventLabel(e.type),
1566
- e.mode === "test" ? " (test)" : ""
1567
- ] }),
1568
- /* @__PURE__ */ jsx(Table.Cell, { className: "font-mono text-xs", children: e.subscription_id }),
1569
- /* @__PURE__ */ jsx(Table.Cell, { children: e.billing_cycle ?? "—" }),
1570
- /* @__PURE__ */ jsx(Table.Cell, { children: amountLabel(e.amount_major, e.currency) }),
1571
- /* @__PURE__ */ jsx(Table.Cell, { children: when(e.next_bill_at) }),
1572
- /* @__PURE__ */ jsx(Table.Cell, { children: when(e.received_at) })
1573
- ] }, e.id)) })
1574
- ] }) }),
1575
- /* @__PURE__ */ jsx(
1576
- Table.Pagination,
1577
- {
1578
- count: data.count,
1579
- pageSize: SUBSCRIPTION_PAGE_SIZE,
1580
- pageIndex,
1581
- pageCount: pageCountFor(data.count),
1582
- canPreviousPage: pageIndex > 0,
1583
- canNextPage: (pageIndex + 1) * SUBSCRIPTION_PAGE_SIZE < data.count,
1584
- previousPage: () => setPageIndex((p) => Math.max(0, p - 1)),
1585
- nextPage: () => setPageIndex((p) => p + 1)
1586
- }
1587
- )
1588
- ] })
1589
- ] })
1590
- ] });
1591
- };
1592
- const config = defineRouteConfig({
1593
- label: "Vonpay subscriptions",
1594
- icon: ArrowPath,
1595
- nested: "/orders"
1596
- });
1597
1597
  const i18nTranslations0 = {};
1598
1598
  const widgetModule = { widgets: [
1599
1599
  {
@@ -1615,18 +1615,18 @@ const widgetModule = { widgets: [
1615
1615
  const routeModule = {
1616
1616
  routes: [
1617
1617
  {
1618
- Component: HeldPaymentsPage,
1619
- path: "/vonpay-holds",
1618
+ Component: VonpaySubscriptionsPage,
1619
+ path: "/vonpay-subscriptions",
1620
1620
  handle: { label: config$2.label, translationNs: config$2.translationNs }
1621
1621
  },
1622
1622
  {
1623
- Component: VonpayOffersPage,
1624
- path: "/vonpay-offers",
1623
+ Component: HeldPaymentsPage,
1624
+ path: "/vonpay-holds",
1625
1625
  handle: { label: config$1.label, translationNs: config$1.translationNs }
1626
1626
  },
1627
1627
  {
1628
- Component: VonpaySubscriptionsPage,
1629
- path: "/vonpay-subscriptions",
1628
+ Component: VonpayOffersPage,
1629
+ path: "/vonpay-offers",
1630
1630
  handle: { label: config.label, translationNs: config.translationNs }
1631
1631
  }
1632
1632
  ]
@@ -1634,24 +1634,24 @@ const routeModule = {
1634
1634
  const menuItemModule = {
1635
1635
  menuItems: [
1636
1636
  {
1637
- label: config$2.label,
1638
- icon: config$2.icon,
1637
+ label: config$1.label,
1638
+ icon: config$1.icon,
1639
1639
  path: "/vonpay-holds",
1640
1640
  nested: "/orders",
1641
1641
  rank: void 0,
1642
1642
  translationNs: void 0
1643
1643
  },
1644
1644
  {
1645
- label: config$1.label,
1646
- icon: config$1.icon,
1645
+ label: config.label,
1646
+ icon: config.icon,
1647
1647
  path: "/vonpay-offers",
1648
1648
  nested: "/orders",
1649
1649
  rank: void 0,
1650
1650
  translationNs: void 0
1651
1651
  },
1652
1652
  {
1653
- label: config.label,
1654
- icon: config.icon,
1653
+ label: config$2.label,
1654
+ icon: config$2.icon,
1655
1655
  path: "/vonpay-subscriptions",
1656
1656
  nested: "/orders",
1657
1657
  rank: void 0,
@@ -1,5 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.currencyDigits = currencyDigits;
3
4
  exports.toMinorUnits = toMinorUnits;
4
5
  exports.exactMinorUnits = exactMinorUnits;
5
6
  exports.minorTotal = minorTotal;
@@ -27,6 +28,9 @@ function toDecimal(amount) {
27
28
  throw (0, errors_1.vonpayError)("amount_not_a_number");
28
29
  return parsed;
29
30
  }
31
+ function currencyDigits(currency) {
32
+ return (0, checkout_node_1.minorUnitDigits)(currency) ?? null;
33
+ }
30
34
  function toMinorUnits(amount, currency) {
31
35
  const digits = digitsFor(currency);
32
36
  const major = toDecimal(amount);
@@ -13,6 +13,7 @@ exports.readOrderFacts = readOrderFacts;
13
13
  exports.collectionHasLiveOrder = collectionHasLiveOrder;
14
14
  exports.requireResolveConfirmation = requireResolveConfirmation;
15
15
  exports.within = within;
16
+ exports.readCartTotal = readCartTotal;
16
17
  exports.isSubscriptionLine = isSubscriptionLine;
17
18
  exports.checkoutEmailOf = checkoutEmailOf;
18
19
  exports.readCheckoutCart = readCheckoutCart;
@@ -248,6 +249,18 @@ async function cartIdsFor(query, collectionId, ms) {
248
249
  const ids = data.map((r) => r?.cart_id).filter((x) => typeof x === "string" && session_data_1.MEDUSA_ID.test(x));
249
250
  return [...new Set(ids)].sort();
250
251
  }
252
+ async function readCartTotal(query, collectionId, ms) {
253
+ const ids = await cartIdsFor(query, collectionId, ms);
254
+ if (ids.length === 0)
255
+ return "none";
256
+ if (ids.length > 1)
257
+ throw new Error("several_carts");
258
+ const { data } = await within(ms, () => query.graph({ entity: "cart", fields: ["id", "total", "raw_total", "currency_code"], filters: { id: ids } }));
259
+ const c = data[0];
260
+ if (!c || c.id !== ids[0])
261
+ throw new Error("cart_unreadable");
262
+ return { total: c.raw_total ?? c.total, currency: c.currency_code };
263
+ }
251
264
  function isSubscriptionLine(metadata) {
252
265
  if (!metadata || typeof metadata !== "object")
253
266
  return false;