@fayz-ai/shop 0.7.0 → 0.8.2

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/dist/index.d.ts CHANGED
@@ -1,4 +1,5 @@
1
1
  export type { Product, ProductImage, Category, ProductEnquiry, ProductEnquiryStatus, Order, OrderItem, OrderStatus, FinancialStatus, FulfillmentStatus, ShopCustomer, Discount, DiscountType, DiscountMethod, DiscountStatus, ProductStatus, CreateProductInput, UpdateProductInput, ListProductsOptions, CreateProductEnquiryInput, ListProductEnquiriesOptions, CreateCategoryInput, UpdateCategoryInput, CreateOrderInput, UpdateOrderInput, ListOrdersOptions, CreateCustomerInput, UpdateCustomerInput, ListCustomersOptions, ResolveCustomerInput, CreateDiscountInput, UpdateDiscountInput, ListDiscountsOptions, PlaceOrderInput, PlaceOrderLine, DiscountValidation, InventoryLine, InventoryIssue, InventoryCheck, CartTotalLine, CartTotals, } from './types';
2
+ export type { ShippingZone, CreateShippingZoneInput, UpdateShippingZoneInput, ShippingQuoteOption, CustomerAddress, } from './types';
2
3
  export type { ShopProvider } from './provider';
3
4
  export { validateDiscount, applyDiscount, checkInventory, computeCartTotals, getCustomerOrders, } from './commerce';
4
5
  export { SupabaseShopProvider, createSupabaseShopProvider } from './supabase-provider';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EACrE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EACjE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EACpE,aAAa,EACb,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAC3D,yBAAyB,EAAE,2BAA2B,EACtD,mBAAmB,EAAE,mBAAmB,EACxC,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EACrD,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EACpF,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAC9D,eAAe,EAAE,cAAc,EAC/B,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,GAC7F,MAAM,SAAS,CAAA;AAEhB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EACL,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,GACtF,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AACtF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC1E,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG/E,OAAO,EACL,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,cAAc,EAAE,oBAAoB,EACrE,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EACjE,YAAY,EAAE,QAAQ,EAAE,YAAY,EAAE,cAAc,EAAE,cAAc,EACpE,aAAa,EACb,kBAAkB,EAAE,kBAAkB,EAAE,mBAAmB,EAC3D,yBAAyB,EAAE,2BAA2B,EACtD,mBAAmB,EAAE,mBAAmB,EACxC,gBAAgB,EAAE,gBAAgB,EAAE,iBAAiB,EACrD,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,oBAAoB,EACpF,mBAAmB,EAAE,mBAAmB,EAAE,oBAAoB,EAC9D,eAAe,EAAE,cAAc,EAC/B,kBAAkB,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,aAAa,EAAE,UAAU,GAC7F,MAAM,SAAS,CAAA;AAEhB,YAAY,EACV,YAAY,EAAE,uBAAuB,EAAE,uBAAuB,EAC9D,mBAAmB,EAAE,eAAe,GACrC,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,EACL,gBAAgB,EAAE,aAAa,EAAE,cAAc,EAAE,iBAAiB,EAAE,iBAAiB,GACtF,MAAM,YAAY,CAAA;AACnB,OAAO,EAAE,oBAAoB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AACtF,OAAO,EAAE,gBAAgB,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAA;AAC1E,YAAY,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAA;AACjE,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA;AAG/E,OAAO,EACL,aAAa,EACb,eAAe,EACf,cAAc,EACd,cAAc,EACd,gBAAgB,GACjB,MAAM,WAAW,CAAA;AAClB,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAA"}
package/dist/index.js CHANGED
@@ -388,6 +388,11 @@ var MockShopProvider = class {
388
388
  customerEmail: input.customerEmail ?? null,
389
389
  discountCode: input.discountCode ?? null,
390
390
  notes: input.notes ?? null,
391
+ shippingAddress: null,
392
+ // CreateOrderInput has no payment method — that is a PlaceOrderInput
393
+ // concern; the mock records none rather than inventing one.
394
+ paymentMethodKind: null,
395
+ paidAt: null,
391
396
  items: input.items.map((i) => ({ id: uid(), orderId, productId: i.productId ?? null, name: i.name, sku: i.sku ?? null, quantity: i.quantity, unitPrice: i.unitPrice, total: Math.round(i.quantity * i.unitPrice * 100) / 100, imageUrl: i.imageUrl ?? null })),
392
397
  createdAt: now(),
393
398
  updatedAt: now()
@@ -649,6 +654,21 @@ function getShopTenantId() {
649
654
  }
650
655
  }
651
656
 
657
+ // src/tables.ts
658
+ var T = {
659
+ products: "plg_shop_products",
660
+ productImages: "plg_shop_product_images",
661
+ categories: "plg_shop_categories",
662
+ orders: "plg_shop_orders",
663
+ orderItems: "plg_shop_order_items",
664
+ customers: "plg_shop_customers",
665
+ discounts: "plg_shop_discounts",
666
+ // Core, not plg_shop_*: a delivery zone is a fact about the business, and
667
+ // fulfilment and financial read it too. Same reasoning as addresses and
668
+ // orders — see migration 0021.
669
+ shippingZones: "shipping_zones"
670
+ };
671
+
652
672
  // src/supabase-provider.ts
653
673
  function getDb() {
654
674
  const supabase = getSupabaseClientOptional();
@@ -663,6 +683,40 @@ function asUuid(value) {
663
683
  if (!value) return null;
664
684
  return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value) ? value : null;
665
685
  }
686
+ function toPostalDigits(value) {
687
+ const digits = String(value ?? "").replace(/\D/g, "");
688
+ return digits ? digits.padStart(8, "0").slice(0, 8) : void 0;
689
+ }
690
+ function rowToShippingZone(row) {
691
+ return {
692
+ id: row.id,
693
+ tenantId: row.tenant_id,
694
+ name: row.name,
695
+ carrier: row.carrier ?? null,
696
+ postalFrom: String(row.postal_from ?? "").trim(),
697
+ postalTo: String(row.postal_to ?? "").trim(),
698
+ rate: Number(row.rate ?? 0),
699
+ freeAbove: row.free_above == null ? null : Number(row.free_above),
700
+ etaMinDays: row.eta_min_days ?? null,
701
+ etaMaxDays: row.eta_max_days ?? null,
702
+ active: row.active ?? true,
703
+ sortOrder: row.sort_order ?? 0
704
+ };
705
+ }
706
+ function shippingZonePayload(input) {
707
+ const payload = {};
708
+ if (input.name !== void 0) payload.name = input.name;
709
+ if (input.carrier !== void 0) payload.carrier = input.carrier || null;
710
+ if (input.postalFrom !== void 0) payload.postal_from = toPostalDigits(input.postalFrom);
711
+ if (input.postalTo !== void 0) payload.postal_to = toPostalDigits(input.postalTo);
712
+ if (input.rate !== void 0) payload.rate = input.rate;
713
+ if (input.freeAbove !== void 0) payload.free_above = input.freeAbove ?? null;
714
+ if (input.etaMinDays !== void 0) payload.eta_min_days = input.etaMinDays ?? null;
715
+ if (input.etaMaxDays !== void 0) payload.eta_max_days = input.etaMaxDays ?? null;
716
+ if (input.active !== void 0) payload.active = input.active;
717
+ if (input.sortOrder !== void 0) payload.sort_order = input.sortOrder;
718
+ return payload;
719
+ }
666
720
  function rowToProduct(row) {
667
721
  return {
668
722
  id: row.id,
@@ -711,6 +765,19 @@ function rowToCategory(row) {
711
765
  createdAt: row.created_at
712
766
  };
713
767
  }
768
+ function rowToOrderItem(row) {
769
+ return {
770
+ id: row.id,
771
+ orderId: row.order_id,
772
+ productId: row.product_id ?? null,
773
+ name: row.name,
774
+ sku: row.sku ?? null,
775
+ quantity: row.quantity ?? 0,
776
+ unitPrice: row.unit_price ?? 0,
777
+ total: row.total ?? 0,
778
+ imageUrl: row.image_url ?? null
779
+ };
780
+ }
714
781
  function rowToOrder(row) {
715
782
  return {
716
783
  id: row.id,
@@ -730,7 +797,10 @@ function rowToOrder(row) {
730
797
  customerEmail: row.customer_email,
731
798
  discountCode: row.discount_code,
732
799
  notes: row.notes,
733
- items: Array.isArray(row.items) ? row.items : [],
800
+ shippingAddress: row.shipping_address ?? null,
801
+ paymentMethodKind: row.payment_method_kind ?? null,
802
+ paidAt: row.paid_at ?? null,
803
+ items: Array.isArray(row.items) ? row.items.map(rowToOrderItem) : [],
734
804
  createdAt: row.created_at,
735
805
  updatedAt: row.updated_at
736
806
  };
@@ -776,7 +846,7 @@ var SupabaseShopProvider = class {
776
846
  async listProducts(options) {
777
847
  const db = getDb();
778
848
  const tenantId = getTenantId();
779
- let q = db.from("shop_products").select("*, images:shop_product_images(*)");
849
+ let q = db.from(T.products).select(`*, images:${T.productImages}(*)`);
780
850
  if (tenantId) q = q.eq("tenant_id", tenantId);
781
851
  if (options?.status) q = q.eq("status", options.status);
782
852
  if (options?.categoryId) q = q.eq("category_id", options.categoryId);
@@ -791,14 +861,14 @@ var SupabaseShopProvider = class {
791
861
  }
792
862
  async getProduct(id) {
793
863
  const db = getDb();
794
- const { data, error } = await db.from("shop_products").select("*, images:shop_product_images(*)").eq("id", id).maybeSingle();
864
+ const { data, error } = await db.from(T.products).select(`*, images:${T.productImages}(*)`).eq("id", id).maybeSingle();
795
865
  if (error) throw error;
796
866
  return data ? rowToProduct(data) : null;
797
867
  }
798
868
  async createProduct(input) {
799
869
  const db = getDb();
800
870
  const tenantId = getTenantId();
801
- const { data, error } = await db.from("shop_products").insert({
871
+ const { data, error } = await db.from(T.products).insert({
802
872
  tenant_id: tenantId,
803
873
  name: input.name,
804
874
  slug: input.slug ?? slugify(input.name),
@@ -815,7 +885,7 @@ var SupabaseShopProvider = class {
815
885
  is_physical: input.isPhysical ?? true,
816
886
  weight: input.weight ?? null,
817
887
  weight_unit: input.weightUnit ?? "kg"
818
- }).select("*, images:shop_product_images(*)").single();
888
+ }).select(`*, images:${T.productImages}(*)`).single();
819
889
  if (error) throw error;
820
890
  return rowToProduct(data);
821
891
  }
@@ -837,12 +907,12 @@ var SupabaseShopProvider = class {
837
907
  if (input.categoryId !== void 0) updates.category_id = input.categoryId;
838
908
  if (input.isPhysical !== void 0) updates.is_physical = input.isPhysical;
839
909
  if (input.weight !== void 0) updates.weight = input.weight;
840
- const { data, error } = await db.from("shop_products").update(updates).eq("id", id).select("*, images:shop_product_images(*)").single();
910
+ const { data, error } = await db.from(T.products).update(updates).eq("id", id).select(`*, images:${T.productImages}(*)`).single();
841
911
  if (error) throw error;
842
912
  return rowToProduct(data);
843
913
  }
844
914
  async deleteProduct(id) {
845
- const { error } = await getDb().from("shop_products").delete().eq("id", id);
915
+ const { error } = await getDb().from(T.products).delete().eq("id", id);
846
916
  if (error) throw error;
847
917
  }
848
918
  async uploadProductImage(productId, file) {
@@ -852,12 +922,37 @@ var SupabaseShopProvider = class {
852
922
  const { error: uploadErr } = await db.storage.from("shop-images").upload(path, file);
853
923
  if (uploadErr) throw uploadErr;
854
924
  const { data: { publicUrl } } = db.storage.from("shop-images").getPublicUrl(path);
855
- const { data, error } = await db.from("shop_product_images").insert({ product_id: productId, tenant_id: tenantId, url: publicUrl, sort_order: 0, is_primary: false }).select().single();
925
+ const { data: existing } = await db.from(T.productImages).select("id,sort_order").eq("product_id", productId).order("sort_order", { ascending: false }).limit(1);
926
+ const first = !existing || existing.length === 0;
927
+ const nextOrder = first ? 0 : (existing[0].sort_order ?? 0) + 1;
928
+ const { data, error } = await db.from(T.productImages).insert({
929
+ product_id: productId,
930
+ tenant_id: tenantId,
931
+ url: publicUrl,
932
+ sort_order: nextOrder,
933
+ is_primary: first
934
+ }).select().single();
935
+ if (error) throw error;
936
+ return rowToImage(data);
937
+ }
938
+ async updateProductImage(imageId, input) {
939
+ const db = getDb();
940
+ const updates = {};
941
+ if (input.sortOrder !== void 0) updates.sort_order = input.sortOrder;
942
+ if (input.altText !== void 0) updates.alt_text = input.altText;
943
+ if (input.isPrimary !== void 0) updates.is_primary = input.isPrimary;
944
+ if (input.isPrimary) {
945
+ const { data: target } = await db.from(T.productImages).select("product_id").eq("id", imageId).single();
946
+ if (target?.product_id) {
947
+ await db.from(T.productImages).update({ is_primary: false }).eq("product_id", target.product_id).neq("id", imageId);
948
+ }
949
+ }
950
+ const { data, error } = await db.from(T.productImages).update(updates).eq("id", imageId).select().single();
856
951
  if (error) throw error;
857
952
  return rowToImage(data);
858
953
  }
859
954
  async deleteProductImage(imageId) {
860
- const { error } = await getDb().from("shop_product_images").delete().eq("id", imageId);
955
+ const { error } = await getDb().from(T.productImages).delete().eq("id", imageId);
861
956
  if (error) throw error;
862
957
  }
863
958
  // ---------------------------------------------------------------------------
@@ -866,7 +961,7 @@ var SupabaseShopProvider = class {
866
961
  async listCategories() {
867
962
  const db = getDb();
868
963
  const tenantId = getTenantId();
869
- let q = db.from("shop_categories").select("*").order("sort_order", { ascending: true });
964
+ let q = db.from(T.categories).select("*").order("sort_order", { ascending: true });
870
965
  if (tenantId) q = q.eq("tenant_id", tenantId);
871
966
  const { data, error } = await q;
872
967
  if (error) throw error;
@@ -874,7 +969,7 @@ var SupabaseShopProvider = class {
874
969
  }
875
970
  async createCategory(input) {
876
971
  const db = getDb();
877
- const { data, error } = await db.from("shop_categories").insert({ tenant_id: getTenantId(), name: input.name, slug: input.slug ?? slugify(input.name), description: input.description ?? null, parent_id: input.parentId ?? null, sort_order: input.sortOrder ?? 0 }).select().single();
972
+ const { data, error } = await db.from(T.categories).insert({ tenant_id: getTenantId(), name: input.name, slug: input.slug ?? slugify(input.name), description: input.description ?? null, parent_id: input.parentId ?? null, sort_order: input.sortOrder ?? 0 }).select().single();
878
973
  if (error) throw error;
879
974
  return rowToCategory(data);
880
975
  }
@@ -886,12 +981,12 @@ var SupabaseShopProvider = class {
886
981
  if (input.description !== void 0) updates.description = input.description;
887
982
  if (input.parentId !== void 0) updates.parent_id = input.parentId;
888
983
  if (input.sortOrder !== void 0) updates.sort_order = input.sortOrder;
889
- const { data, error } = await db.from("shop_categories").update(updates).eq("id", id).select().single();
984
+ const { data, error } = await db.from(T.categories).update(updates).eq("id", id).select().single();
890
985
  if (error) throw error;
891
986
  return rowToCategory(data);
892
987
  }
893
988
  async deleteCategory(id) {
894
- const { error } = await getDb().from("shop_categories").delete().eq("id", id);
989
+ const { error } = await getDb().from(T.categories).delete().eq("id", id);
895
990
  if (error) throw error;
896
991
  }
897
992
  // ---------------------------------------------------------------------------
@@ -900,7 +995,7 @@ var SupabaseShopProvider = class {
900
995
  async listOrders(options) {
901
996
  const db = getDb();
902
997
  const tenantId = getTenantId();
903
- let q = db.from("shop_orders").select("*, items:shop_order_items(*)");
998
+ let q = db.from(T.orders).select(`*, items:${T.orderItems}(*)`);
904
999
  if (tenantId) q = q.eq("tenant_id", tenantId);
905
1000
  if (options?.status) q = q.eq("status", options.status);
906
1001
  if (options?.financialStatus) q = q.eq("financial_status", options.financialStatus);
@@ -915,7 +1010,7 @@ var SupabaseShopProvider = class {
915
1010
  return (data ?? []).map(rowToOrder);
916
1011
  }
917
1012
  async getOrder(id) {
918
- const { data, error } = await getDb().from("shop_orders").select("*, items:shop_order_items(*)").eq("id", id).maybeSingle();
1013
+ const { data, error } = await getDb().from(T.orders).select(`*, items:${T.orderItems}(*)`).eq("id", id).maybeSingle();
919
1014
  if (error) throw error;
920
1015
  return data ? rowToOrder(data) : null;
921
1016
  }
@@ -926,10 +1021,10 @@ var SupabaseShopProvider = class {
926
1021
  const discountTotal = input.discountTotal ?? 0;
927
1022
  const shippingTotal = input.shippingTotal ?? 0;
928
1023
  const total = Math.round((subtotal - discountTotal + shippingTotal) * 100) / 100;
929
- const { data: order, error: orderErr } = await db.from("shop_orders").insert({ tenant_id: tenantId, customer_id: input.customerId ?? null, customer_name: input.customerName ?? null, customer_email: input.customerEmail ?? null, currency: input.currency ?? "BRL", notes: input.notes ?? null, subtotal, discount_total: discountTotal, shipping_total: shippingTotal, discount_code: input.discountCode ?? null, total, status: "open", financial_status: "pending", fulfillment_status: "unfulfilled" }).select().single();
1024
+ const { data: order, error: orderErr } = await db.from(T.orders).insert({ tenant_id: tenantId, customer_id: input.customerId ?? null, customer_name: input.customerName ?? null, customer_email: input.customerEmail ?? null, currency: input.currency ?? "BRL", notes: input.notes ?? null, subtotal, discount_total: discountTotal, shipping_total: shippingTotal, discount_code: input.discountCode ?? null, total, status: "open", financial_status: "pending", fulfillment_status: "unfulfilled" }).select().single();
930
1025
  if (orderErr) throw orderErr;
931
1026
  const items = input.items.map((i) => ({ order_id: order.id, product_id: asUuid(i.productId), name: i.name, sku: i.sku ?? null, quantity: i.quantity, unit_price: i.unitPrice, total: i.quantity * i.unitPrice, image_url: i.imageUrl ?? null }));
932
- await db.from("shop_order_items").insert(items);
1027
+ await db.from(T.orderItems).insert(items);
933
1028
  return this.getOrder(order.id);
934
1029
  }
935
1030
  async updateOrder(id, input) {
@@ -938,7 +1033,53 @@ var SupabaseShopProvider = class {
938
1033
  if (input.financialStatus !== void 0) updates.financial_status = input.financialStatus;
939
1034
  if (input.fulfillmentStatus !== void 0) updates.fulfillment_status = input.fulfillmentStatus;
940
1035
  if (input.notes !== void 0) updates.notes = input.notes;
941
- const { error } = await getDb().from("shop_orders").update(updates).eq("id", id);
1036
+ const { error } = await getDb().from(T.orders).update(updates).eq("id", id);
1037
+ if (error) throw error;
1038
+ return this.getOrder(id);
1039
+ }
1040
+ // -------------------------------------------------------------------------
1041
+ // Delivery zones
1042
+ //
1043
+ // Postal codes are stored as 8 bare digits so the range test in
1044
+ // shop_quote_shipping is a plain BETWEEN. Accepting '22.041-001' from the
1045
+ // form and normalising here means the merchant never has to think about it.
1046
+ // -------------------------------------------------------------------------
1047
+ async listShippingZones() {
1048
+ const tenantId = getTenantId();
1049
+ const { data, error } = await getDb().from(T.shippingZones).select("*").eq("tenant_id", tenantId).order("sort_order", { ascending: true }).order("postal_from", { ascending: true });
1050
+ if (error) throw error;
1051
+ return (data ?? []).map(rowToShippingZone);
1052
+ }
1053
+ async createShippingZone(input) {
1054
+ const tenantId = getTenantId();
1055
+ if (!tenantId) throw new Error("@fayz-ai/shop: createShippingZone requires a tenant id.");
1056
+ const { data, error } = await getDb().from(T.shippingZones).insert({ tenant_id: tenantId, ...shippingZonePayload(input) }).select().single();
1057
+ if (error) throw error;
1058
+ return rowToShippingZone(data);
1059
+ }
1060
+ async updateShippingZone(id, input) {
1061
+ const { data, error } = await getDb().from(T.shippingZones).update(shippingZonePayload(input)).eq("id", id).select().single();
1062
+ if (error) throw error;
1063
+ return rowToShippingZone(data);
1064
+ }
1065
+ async deleteShippingZone(id) {
1066
+ const { error } = await getDb().from(T.shippingZones).delete().eq("id", id);
1067
+ if (error) throw error;
1068
+ }
1069
+ /**
1070
+ * Settle a pending order: the merchant confirming that the money arrived.
1071
+ *
1072
+ * Goes through the RPC rather than an UPDATE so the payment ledger row in
1073
+ * public.transactions closes in the same transaction as the order — set
1074
+ * financial_status by hand and the order says paid while the ledger still
1075
+ * says pending. Since 0019 the RPC also enforces who may call it: a member of
1076
+ * the owning tenant, or a PSP webhook with the service role.
1077
+ */
1078
+ async confirmPayment(id, reference) {
1079
+ const { error } = await getDb().rpc("shop_confirm_payment", {
1080
+ p_order_id: id,
1081
+ p_reference: reference ?? null
1082
+ });
942
1083
  if (error) throw error;
943
1084
  return this.getOrder(id);
944
1085
  }
@@ -957,6 +1098,22 @@ var SupabaseShopProvider = class {
957
1098
  p_currency: input.currency ?? "BRL",
958
1099
  p_discount_code: input.discountCode ?? null,
959
1100
  p_shipping_total: input.shippingTotal ?? 0,
1101
+ // snake_case keys on purpose: the RPC freezes this jsonb onto the
1102
+ // order and public.addresses uses these exact column names.
1103
+ p_shipping_address: input.shippingAddress ? {
1104
+ postal_code: input.shippingAddress.postalCode,
1105
+ street: input.shippingAddress.street,
1106
+ number: input.shippingAddress.number ?? null,
1107
+ complement: input.shippingAddress.complement ?? null,
1108
+ district: input.shippingAddress.district ?? null,
1109
+ city: input.shippingAddress.city,
1110
+ state: input.shippingAddress.state,
1111
+ country: input.shippingAddress.country ?? "BR",
1112
+ recipient: input.shippingAddress.recipient ?? null,
1113
+ phone: input.shippingAddress.phone ?? null,
1114
+ label: input.shippingAddress.label ?? null
1115
+ } : null,
1116
+ p_payment_method: input.paymentMethod ?? null,
960
1117
  p_notes: input.notes ?? null
961
1118
  });
962
1119
  if (error) throw error;
@@ -971,7 +1128,7 @@ var SupabaseShopProvider = class {
971
1128
  async listCustomers(options) {
972
1129
  const db = getDb();
973
1130
  const tenantId = getTenantId();
974
- let q = db.from("shop_customers").select("*").order("first_name", { ascending: true });
1131
+ let q = db.from(T.customers).select("*").order("first_name", { ascending: true });
975
1132
  if (tenantId) q = q.eq("tenant_id", tenantId);
976
1133
  if (options?.search) q = q.or(`first_name.ilike.%${options.search}%,last_name.ilike.%${options.search}%,email.ilike.%${options.search}%`);
977
1134
  if (options?.limit) q = q.limit(options.limit);
@@ -980,12 +1137,12 @@ var SupabaseShopProvider = class {
980
1137
  return (data ?? []).map(rowToCustomer);
981
1138
  }
982
1139
  async getCustomer(id) {
983
- const { data, error } = await getDb().from("shop_customers").select("*").eq("id", id).maybeSingle();
1140
+ const { data, error } = await getDb().from(T.customers).select("*").eq("id", id).maybeSingle();
984
1141
  if (error) throw error;
985
1142
  return data ? rowToCustomer(data) : null;
986
1143
  }
987
1144
  async createCustomer(input) {
988
- const { data, error } = await getDb().from("shop_customers").insert({ tenant_id: getTenantId(), first_name: input.firstName, last_name: input.lastName ?? "", email: input.email ?? null, phone: input.phone ?? null, notes: input.notes ?? null }).select().single();
1145
+ const { data, error } = await getDb().from(T.customers).insert({ tenant_id: getTenantId(), first_name: input.firstName, last_name: input.lastName ?? "", email: input.email ?? null, phone: input.phone ?? null, notes: input.notes ?? null }).select().single();
989
1146
  if (error) throw error;
990
1147
  return rowToCustomer(data);
991
1148
  }
@@ -996,12 +1153,12 @@ var SupabaseShopProvider = class {
996
1153
  if (input.email !== void 0) updates.email = input.email;
997
1154
  if (input.phone !== void 0) updates.phone = input.phone;
998
1155
  if (input.notes !== void 0) updates.notes = input.notes;
999
- const { data, error } = await getDb().from("shop_customers").update(updates).eq("id", id).select().single();
1156
+ const { data, error } = await getDb().from(T.customers).update(updates).eq("id", id).select().single();
1000
1157
  if (error) throw error;
1001
1158
  return rowToCustomer(data);
1002
1159
  }
1003
1160
  async deleteCustomer(id) {
1004
- const { error } = await getDb().from("shop_customers").delete().eq("id", id);
1161
+ const { error } = await getDb().from(T.customers).delete().eq("id", id);
1005
1162
  if (error) throw error;
1006
1163
  }
1007
1164
  // Find-or-create + link to auth.uid server-side (SECURITY DEFINER RPC), so the
@@ -1026,7 +1183,7 @@ var SupabaseShopProvider = class {
1026
1183
  async listDiscounts(options) {
1027
1184
  const db = getDb();
1028
1185
  const tenantId = getTenantId();
1029
- let q = db.from("shop_discounts").select("*").order("created_at", { ascending: false });
1186
+ let q = db.from(T.discounts).select("*").order("created_at", { ascending: false });
1030
1187
  if (tenantId) q = q.eq("tenant_id", tenantId);
1031
1188
  if (options?.status) q = q.eq("status", options.status);
1032
1189
  if (options?.type) q = q.eq("type", options.type);
@@ -1037,12 +1194,12 @@ var SupabaseShopProvider = class {
1037
1194
  return (data ?? []).map(rowToDiscount);
1038
1195
  }
1039
1196
  async getDiscount(id) {
1040
- const { data, error } = await getDb().from("shop_discounts").select("*").eq("id", id).maybeSingle();
1197
+ const { data, error } = await getDb().from(T.discounts).select("*").eq("id", id).maybeSingle();
1041
1198
  if (error) throw error;
1042
1199
  return data ? rowToDiscount(data) : null;
1043
1200
  }
1044
1201
  async createDiscount(input) {
1045
- const { data, error } = await getDb().from("shop_discounts").insert({ tenant_id: getTenantId(), title: input.title, code: input.code ?? null, type: input.type, method: input.method ?? "code", value: input.value, usage_limit: input.usageLimit ?? null, once_per_customer: input.oncePerCustomer ?? false, starts_at: input.startsAt ?? (/* @__PURE__ */ new Date()).toISOString(), ends_at: input.endsAt ?? null, status: input.status ?? "active", times_used: 0 }).select().single();
1202
+ const { data, error } = await getDb().from(T.discounts).insert({ tenant_id: getTenantId(), title: input.title, code: input.code ?? null, type: input.type, method: input.method ?? "code", value: input.value, usage_limit: input.usageLimit ?? null, once_per_customer: input.oncePerCustomer ?? false, starts_at: input.startsAt ?? (/* @__PURE__ */ new Date()).toISOString(), ends_at: input.endsAt ?? null, status: input.status ?? "active", times_used: 0 }).select().single();
1046
1203
  if (error) throw error;
1047
1204
  return rowToDiscount(data);
1048
1205
  }
@@ -1055,12 +1212,12 @@ var SupabaseShopProvider = class {
1055
1212
  if (input.usageLimit !== void 0) updates.usage_limit = input.usageLimit;
1056
1213
  if (input.status !== void 0) updates.status = input.status;
1057
1214
  if (input.endsAt !== void 0) updates.ends_at = input.endsAt;
1058
- const { data, error } = await getDb().from("shop_discounts").update(updates).eq("id", id).select().single();
1215
+ const { data, error } = await getDb().from(T.discounts).update(updates).eq("id", id).select().single();
1059
1216
  if (error) throw error;
1060
1217
  return rowToDiscount(data);
1061
1218
  }
1062
1219
  async deleteDiscount(id) {
1063
- const { error } = await getDb().from("shop_discounts").delete().eq("id", id);
1220
+ const { error } = await getDb().from(T.discounts).delete().eq("id", id);
1064
1221
  if (error) throw error;
1065
1222
  }
1066
1223
  };