@aglyn/plugins-commerce 1.0.0-beta.220 → 1.0.0-beta.221

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aglyn/plugins-commerce",
3
- "version": "1.0.0-beta.220",
3
+ "version": "1.0.0-beta.221",
4
4
  "license": "Apache-2.0",
5
5
  "homepage": "https://aglyn.com",
6
6
  "repository": {
@@ -25,18 +25,18 @@
25
25
  "./package.json": "./package.json"
26
26
  },
27
27
  "dependencies": {
28
- "@aglyn/aglyn": "1.0.0-beta.220",
29
- "@aglyn/shared-data-mdi": "1.0.0-beta.220",
30
- "@aglyn/shared-ui-jsx": "1.0.0-beta.220",
31
- "@aglyn/shared-ui-next": "1.0.0-beta.220",
32
- "@aglyn/shared-ui-snackstack": "1.0.0-beta.220",
33
- "@aglyn/shared-util-email": "1.0.0-beta.220",
34
- "@aglyn/shared-util-http": "1.0.0-beta.220",
35
- "@aglyn/shared-util-timestamp": "1.0.0-beta.220",
36
- "@aglyn/shared-util-tools": "1.0.0-beta.220",
37
- "@aglyn/tenant-data-admin": "1.0.0-beta.220",
38
- "@aglyn/tenant-feature-instance": "1.0.0-beta.220",
39
- "@aglyn/tenant-runtime": "1.0.0-beta.220",
28
+ "@aglyn/aglyn": "1.0.0-beta.221",
29
+ "@aglyn/shared-data-mdi": "1.0.0-beta.221",
30
+ "@aglyn/shared-ui-jsx": "1.0.0-beta.221",
31
+ "@aglyn/shared-ui-next": "1.0.0-beta.221",
32
+ "@aglyn/shared-ui-snackstack": "1.0.0-beta.221",
33
+ "@aglyn/shared-util-email": "1.0.0-beta.221",
34
+ "@aglyn/shared-util-http": "1.0.0-beta.221",
35
+ "@aglyn/shared-util-timestamp": "1.0.0-beta.221",
36
+ "@aglyn/shared-util-tools": "1.0.0-beta.221",
37
+ "@aglyn/tenant-data-admin": "1.0.0-beta.221",
38
+ "@aglyn/tenant-feature-instance": "1.0.0-beta.221",
39
+ "@aglyn/tenant-runtime": "1.0.0-beta.221",
40
40
  "@stripe/react-stripe-js": "^6.12.0",
41
41
  "@stripe/stripe-js": "^9.17.0",
42
42
  "@swc/helpers": "0.5.23",
@@ -17,7 +17,7 @@
17
17
  import * as Aglyn from "@aglyn/aglyn/server";
18
18
  import { findUserByUidAcrossPools, firebaseAdmin, getOrgForHost, meterHostEmail, notifyHostManagers, notifyRiskEvent, raiseOperatorAlert, renderHostEmailWithTokens, updateExisting, hostSendingIdentity } from "@aglyn/tenant-data-admin";
19
19
  import { paymentProvider } from "@aglyn/tenant-data-admin/server/payment-provider";
20
- import { captureHostContact } from "@aglyn/tenant-runtime";
20
+ import recordCapturedContact from "@aglyn/aglyn/plugin-manager/record-captured-contact";
21
21
  import { formatOperatorAlertAmount } from "@aglyn/aglyn/app-utils/operator-alerts";
22
22
  import { resolveSiteTimeZone } from "@aglyn/aglyn/app-utils/collection-entry-date";
23
23
  import { resolveHostToken } from "@aglyn/aglyn/app-utils/host-tokens";
@@ -1870,9 +1870,9 @@ async function findOrderForDispute(paymentIntentId) {
1870
1870
  const subscriptionRef = hostRef.collection('subscriptions').doc(String(object.subscription));
1871
1871
  // Redelivery guard (AGL-1732, the AGL-498 shape). Stripe delivers at
1872
1872
  // least once, and the effects below this write are NOT idempotent —
1873
- // `upsertHostContact`'s `purchaseCents` is a `FieldValue.increment`, so
1874
- // a replay would inflate the subscriber's lifetime value and their
1875
- // order count on every retry.
1873
+ // the capture's `purchaseCents` is added to the person's lifetime
1874
+ // value, so a replay would inflate the subscriber's lifetime value and
1875
+ // their order count on every retry.
1876
1876
  //
1877
1877
  // Keyed on `checkoutSessionId` rather than on the document existing:
1878
1878
  // `customer.subscription.created` writes the SAME doc path (status and
@@ -1955,24 +1955,35 @@ async function findOrderForDispute(paymentIntentId) {
1955
1955
  link: `/${hostId}/products`
1956
1956
  });
1957
1957
  // AWAITED SINCE AGL-2473, here and at the five sibling call sites in
1958
- // this file. `upsertHostContact` carries `purchaseCents`, so it is what
1959
- // feeds `ltvCents` and the RFM ranking — a `void`ed one is a paying
1960
- // customer quietly missing from the segment the merchant emails. It
1961
- // touches only our own Firestore, which is the whole line AGL-2473
1962
- // drew: Aglyn's own storage is awaited, a stranger's server is queued.
1963
- // `refund.ts` already awaited its sibling for exactly this reason.
1964
- await captureHostContact(_extends({
1958
+ // this file. The capture carries `purchaseCents`, which is what the
1959
+ // record system adds to a person's lifetime value and the RFM ranking
1960
+ // — a `void`ed one is a paying customer quietly missing from the
1961
+ // segment the merchant emails. It touches only our own Firestore,
1962
+ // which is the whole line AGL-2473 drew: Aglyn's own storage is
1963
+ // awaited, a stranger's server is queued. `refund.ts` already awaited
1964
+ // its sibling for exactly this reason.
1965
+ //
1966
+ // Through the contact-capture contract (AGL-3080), like every other
1967
+ // door commerce owns: the plugin that keeps people decides what a
1968
+ // purchase makes of them, and commerce imports none of it.
1969
+ await recordCapturedContact(_extends({
1970
+ orgId: '',
1965
1971
  hostId: String(hostId),
1966
- email: object == null ? void 0 : (_object_customer_details1 = object.customer_details) == null ? void 0 : _object_customer_details1.email,
1967
- name: (_ref10 = object == null ? void 0 : (_object_customer_details2 = object.customer_details) == null ? void 0 : _object_customer_details2.name) != null ? _ref10 : undefined,
1968
- source: 'order',
1972
+ identity: {
1973
+ email: object == null ? void 0 : (_object_customer_details1 = object.customer_details) == null ? void 0 : _object_customer_details1.email,
1974
+ name: (_ref10 = object == null ? void 0 : (_object_customer_details2 = object.customer_details) == null ? void 0 : _object_customer_details2.name) != null ? _ref10 : null
1975
+ },
1976
+ // A purchase makes the person a relationship (AGL-3232): a contact,
1977
+ // with an open lead for the address closed onto it.
1978
+ surface: 'relationship',
1969
1979
  // Every order door names `customer` (AGL-2612): a floor, so the
1970
1980
  // stage fills or advances and never moves anybody back.
1971
- initialLifecycleStage: 'customer'
1981
+ lifecycleFloor: 'customer'
1972
1982
  }, subscriptionCents > 0 ? {
1973
1983
  purchaseCents: subscriptionCents
1974
1984
  } : {}, {
1975
1985
  interaction: {
1986
+ source: 'order',
1976
1987
  refId: String(object.subscription),
1977
1988
  summary: `Started a subscription ($${(subscriptionCents / 100).toFixed(2)})`
1978
1989
  }
@@ -2513,20 +2524,23 @@ async function findOrderForDispute(paymentIntentId) {
2513
2524
  // counting only the first charge ranks them as a one-purchase
2514
2525
  // customer forever. Keyed to the invoice so the guard above is what
2515
2526
  // stops a redelivery inflating it.
2516
- await captureHostContact(_extends({
2527
+ await recordCapturedContact({
2528
+ orgId: '',
2517
2529
  hostId: invoiceHostId,
2518
- email: renewalEmail
2519
- }, soldSnapshot.get('customerName') ? {
2520
- name: String(soldSnapshot.get('customerName'))
2521
- } : {}, {
2522
- source: 'order',
2523
- initialLifecycleStage: 'customer',
2530
+ identity: _extends({
2531
+ email: renewalEmail
2532
+ }, soldSnapshot.get('customerName') ? {
2533
+ name: String(soldSnapshot.get('customerName'))
2534
+ } : {}),
2535
+ surface: 'relationship',
2536
+ lifecycleFloor: 'customer',
2524
2537
  purchaseCents: paidCents,
2525
2538
  interaction: {
2539
+ source: 'order',
2526
2540
  refId: invoiceId,
2527
2541
  summary: `Subscription renewed ($${(paidCents / 100).toFixed(2)})`
2528
2542
  }
2529
- }));
2543
+ });
2530
2544
  }
2531
2545
  }
2532
2546
  }
@@ -2704,18 +2718,22 @@ async function findOrderForDispute(paymentIntentId) {
2704
2718
  if (guestContactEmail) {
2705
2719
  var _ref37, _ref38;
2706
2720
  var _object_customer_details6;
2707
- await captureHostContact(_extends({
2721
+ await recordCapturedContact(_extends({
2722
+ orgId: '',
2708
2723
  hostId: String(hostId),
2709
- email: guestContactEmail,
2710
- name: (_ref37 = (_ref38 = object == null ? void 0 : (_object_customer_details6 = object.customer_details) == null ? void 0 : _object_customer_details6.name) != null ? _ref38 : reservation['guestName']) != null ? _ref37 : undefined,
2711
- source: 'booking',
2724
+ identity: {
2725
+ email: guestContactEmail,
2726
+ name: (_ref37 = (_ref38 = object == null ? void 0 : (_object_customer_details6 = object.customer_details) == null ? void 0 : _object_customer_details6.name) != null ? _ref38 : reservation['guestName']) != null ? _ref37 : null
2727
+ },
2728
+ surface: 'relationship',
2712
2729
  // A paid stay is a sale (AGL-2612), whatever the source says
2713
2730
  // about the kind of thing that was bought.
2714
- initialLifecycleStage: 'customer'
2731
+ lifecycleFloor: 'customer'
2715
2732
  }, paidCents > 0 ? {
2716
2733
  purchaseCents: paidCents
2717
2734
  } : {}, {
2718
2735
  interaction: {
2736
+ source: 'booking',
2719
2737
  refId: String(reservationId),
2720
2738
  summary: `Reserved a stay ($${(paidCents / 100).toFixed(2)})`
2721
2739
  }
@@ -3117,17 +3135,21 @@ async function findOrderForDispute(paymentIntentId) {
3117
3135
  body: `Order ${cartOrderLabel} came in on {site}: ${cartUnits} ` + `item${cartUnits === 1 ? '' : 's'}, ${cartOrderTotal}` + ((object == null ? void 0 : (_object_customer_details8 = object.customer_details) == null ? void 0 : _object_customer_details8.email) ? `, from ${object.customer_details.email}.` : '.'),
3118
3136
  link: `/${hostId}/products`
3119
3137
  });
3120
- await captureHostContact(_extends({
3138
+ await recordCapturedContact(_extends({
3139
+ orgId: '',
3121
3140
  hostId: String(hostId),
3122
- email: object == null ? void 0 : (_object_customer_details9 = object.customer_details) == null ? void 0 : _object_customer_details9.email,
3123
- name: (_ref43 = object == null ? void 0 : (_object_customer_details10 = object.customer_details) == null ? void 0 : _object_customer_details10.name) != null ? _ref43 : undefined,
3124
- source: 'order',
3125
- initialLifecycleStage: 'customer'
3141
+ identity: {
3142
+ email: object == null ? void 0 : (_object_customer_details9 = object.customer_details) == null ? void 0 : _object_customer_details9.email,
3143
+ name: (_ref43 = object == null ? void 0 : (_object_customer_details10 = object.customer_details) == null ? void 0 : _object_customer_details10.name) != null ? _ref43 : null
3144
+ },
3145
+ surface: 'relationship',
3146
+ lifecycleFloor: 'customer'
3126
3147
  }, marketingOptIn ? {
3127
3148
  marketingConsent: true
3128
3149
  } : {}, {
3129
3150
  purchaseCents: Number((_ref44 = object == null ? void 0 : object.amount_total) != null ? _ref44 : 0),
3130
3151
  interaction: {
3152
+ source: 'order',
3131
3153
  refId: String(object.id),
3132
3154
  summary: `Placed an order ($${(Number((_ref45 = object == null ? void 0 : object.amount_total) != null ? _ref45 : 0) / 100).toFixed(2)})`
3133
3155
  }
@@ -3559,16 +3581,20 @@ async function findOrderForDispute(paymentIntentId) {
3559
3581
  var _ref68, _ref69, _ref70;
3560
3582
  var _order_totals1, _object_customer_details17;
3561
3583
  const chargedCents = Number((_ref68 = object == null ? void 0 : object.amount_total) != null ? _ref68 : 0) || Number((_ref69 = (_order_totals1 = order.totals) == null ? void 0 : _order_totals1.totalCents) != null ? _ref69 : 0);
3562
- await captureHostContact(_extends({
3584
+ await recordCapturedContact(_extends({
3585
+ orgId: '',
3563
3586
  hostId: String(hostId),
3564
- email: draftEmail,
3565
- name: (_ref70 = object == null ? void 0 : (_object_customer_details17 = object.customer_details) == null ? void 0 : _object_customer_details17.name) != null ? _ref70 : undefined,
3566
- source: 'order',
3567
- initialLifecycleStage: 'customer'
3587
+ identity: {
3588
+ email: draftEmail,
3589
+ name: (_ref70 = object == null ? void 0 : (_object_customer_details17 = object.customer_details) == null ? void 0 : _object_customer_details17.name) != null ? _ref70 : null
3590
+ },
3591
+ surface: 'relationship',
3592
+ lifecycleFloor: 'customer'
3568
3593
  }, chargedCents > 0 ? {
3569
3594
  purchaseCents: chargedCents
3570
3595
  } : {}, {
3571
3596
  interaction: {
3597
+ source: 'order',
3572
3598
  refId: String(orderId),
3573
3599
  summary: `Paid ${CommerceModel.formatOrderNumber(order, String(orderId))} ($${(chargedCents / 100).toFixed(2)})`
3574
3600
  }
@@ -3943,14 +3969,18 @@ async function findOrderForDispute(paymentIntentId) {
3943
3969
  }
3944
3970
  })();
3945
3971
  // Contacts ingestion (AGL-197): buyers become contacts.
3946
- await captureHostContact({
3972
+ await recordCapturedContact({
3973
+ orgId: '',
3947
3974
  hostId: String(hostId),
3948
- email: object == null ? void 0 : (_object_customer_details19 = object.customer_details) == null ? void 0 : _object_customer_details19.email,
3949
- name: (_ref79 = object == null ? void 0 : (_object_customer_details20 = object.customer_details) == null ? void 0 : _object_customer_details20.name) != null ? _ref79 : undefined,
3950
- source: 'order',
3951
- initialLifecycleStage: 'customer',
3975
+ identity: {
3976
+ email: object == null ? void 0 : (_object_customer_details19 = object.customer_details) == null ? void 0 : _object_customer_details19.email,
3977
+ name: (_ref79 = object == null ? void 0 : (_object_customer_details20 = object.customer_details) == null ? void 0 : _object_customer_details20.name) != null ? _ref79 : null
3978
+ },
3979
+ surface: 'relationship',
3980
+ lifecycleFloor: 'customer',
3952
3981
  purchaseCents: Number((_ref80 = object == null ? void 0 : object.amount_total) != null ? _ref80 : 0),
3953
3982
  interaction: {
3983
+ source: 'order',
3954
3984
  refId: String(object.id),
3955
3985
  summary: `Placed an order ($${(Number((_ref81 = object == null ? void 0 : object.amount_total) != null ? _ref81 : 0) / 100).toFixed(2)})`
3956
3986
  }