@rovela-ai/sdk 0.1.17 → 0.1.19
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/admin/api/auth.js +5 -11
- package/dist/admin/api/auth.js.map +1 -1
- package/dist/admin/api/categories.js +43 -50
- package/dist/admin/api/categories.js.map +1 -1
- package/dist/admin/api/check.js +6 -9
- package/dist/admin/api/check.js.map +1 -1
- package/dist/admin/api/customers.js +17 -21
- package/dist/admin/api/customers.js.map +1 -1
- package/dist/admin/api/index.js +10 -38
- package/dist/admin/api/index.js.map +1 -1
- package/dist/admin/api/orders.js +30 -35
- package/dist/admin/api/orders.js.map +1 -1
- package/dist/admin/api/products.js +56 -66
- package/dist/admin/api/products.js.map +1 -1
- package/dist/admin/api/refund.js +26 -29
- package/dist/admin/api/refund.js.map +1 -1
- package/dist/admin/api/settings.js +17 -21
- package/dist/admin/api/settings.js.map +1 -1
- package/dist/admin/api/setup.js +17 -20
- package/dist/admin/api/setup.js.map +1 -1
- package/dist/admin/api/stats.js +14 -17
- package/dist/admin/api/stats.js.map +1 -1
- package/dist/admin/components/AdminGuard.js +13 -17
- package/dist/admin/components/AdminGuard.js.map +1 -1
- package/dist/admin/components/AdminHeader.js +8 -11
- package/dist/admin/components/AdminHeader.js.map +1 -1
- package/dist/admin/components/AdminLayout.js +5 -8
- package/dist/admin/components/AdminLayout.js.map +1 -1
- package/dist/admin/components/AdminLoginForm.js +11 -14
- package/dist/admin/components/AdminLoginForm.js.map +1 -1
- package/dist/admin/components/AdminNav.js +11 -14
- package/dist/admin/components/AdminNav.js.map +1 -1
- package/dist/admin/components/AdminSetupForm.js +11 -14
- package/dist/admin/components/AdminSetupForm.js.map +1 -1
- package/dist/admin/components/InventoryEditor.js +16 -19
- package/dist/admin/components/InventoryEditor.js.map +1 -1
- package/dist/admin/components/LowStockAlert.js +6 -9
- package/dist/admin/components/LowStockAlert.js.map +1 -1
- package/dist/admin/components/OrderDetails.js +15 -18
- package/dist/admin/components/OrderDetails.js.map +1 -1
- package/dist/admin/components/OrderTable.js +13 -16
- package/dist/admin/components/OrderTable.js.map +1 -1
- package/dist/admin/components/ProductForm.js +17 -20
- package/dist/admin/components/ProductForm.js.map +1 -1
- package/dist/admin/components/ProductTable.js +15 -18
- package/dist/admin/components/ProductTable.js.map +1 -1
- package/dist/admin/components/RecentOrders.js +6 -9
- package/dist/admin/components/RecentOrders.js.map +1 -1
- package/dist/admin/components/RefundDialog.js +12 -15
- package/dist/admin/components/RefundDialog.js.map +1 -1
- package/dist/admin/components/StatsCards.js +7 -10
- package/dist/admin/components/StatsCards.js.map +1 -1
- package/dist/admin/components/StoreSettings.js +10 -13
- package/dist/admin/components/StoreSettings.js.map +1 -1
- package/dist/admin/components/index.js +16 -35
- package/dist/admin/components/index.js.map +1 -1
- package/dist/admin/config.js +12 -54
- package/dist/admin/config.js.map +1 -1
- package/dist/admin/hooks/index.js +4 -11
- package/dist/admin/hooks/index.js.map +1 -1
- package/dist/admin/hooks/useAdminAuth.js +9 -12
- package/dist/admin/hooks/useAdminAuth.js.map +1 -1
- package/dist/admin/hooks/useAdminOrders.js +11 -14
- package/dist/admin/hooks/useAdminOrders.js.map +1 -1
- package/dist/admin/hooks/useAdminProducts.js +13 -16
- package/dist/admin/hooks/useAdminProducts.js.map +1 -1
- package/dist/admin/hooks/useAdminStats.js +11 -14
- package/dist/admin/hooks/useAdminStats.js.map +1 -1
- package/dist/admin/index.js +13 -66
- package/dist/admin/index.js.map +1 -1
- package/dist/admin/server/admin-service.js +39 -83
- package/dist/admin/server/admin-service.js.map +1 -1
- package/dist/admin/server/index.js +3 -13
- package/dist/admin/server/index.js.map +1 -1
- package/dist/admin/types.js +1 -2
- package/dist/admin/types.js.map +1 -1
- package/dist/auth/api/auth.js +6 -14
- package/dist/auth/api/auth.js.map +1 -1
- package/dist/auth/api/forgot-password.js +8 -11
- package/dist/auth/api/forgot-password.js.map +1 -1
- package/dist/auth/api/index.js +6 -18
- package/dist/auth/api/index.js.map +1 -1
- package/dist/auth/api/register.js +17 -20
- package/dist/auth/api/register.js.map +1 -1
- package/dist/auth/api/resend-verification.js +9 -12
- package/dist/auth/api/resend-verification.js.map +1 -1
- package/dist/auth/api/reset-password.js +18 -22
- package/dist/auth/api/reset-password.js.map +1 -1
- package/dist/auth/api/verify-email.js +14 -18
- package/dist/auth/api/verify-email.js.map +1 -1
- package/dist/auth/components/AuthGuard.js +13 -17
- package/dist/auth/components/AuthGuard.js.map +1 -1
- package/dist/auth/components/ForgotPasswordForm.js +11 -14
- package/dist/auth/components/ForgotPasswordForm.js.map +1 -1
- package/dist/auth/components/ResetPasswordForm.js +18 -21
- package/dist/auth/components/ResetPasswordForm.js.map +1 -1
- package/dist/auth/components/SignInForm.js +13 -16
- package/dist/auth/components/SignInForm.js.map +1 -1
- package/dist/auth/components/SignUpForm.js +15 -18
- package/dist/auth/components/SignUpForm.js.map +1 -1
- package/dist/auth/components/UserMenu.js +13 -16
- package/dist/auth/components/UserMenu.js.map +1 -1
- package/dist/auth/components/VerifyEmailNotice.js +10 -13
- package/dist/auth/components/VerifyEmailNotice.js.map +1 -1
- package/dist/auth/components/index.js +7 -18
- package/dist/auth/components/index.js.map +1 -1
- package/dist/auth/config.js +9 -49
- package/dist/auth/config.js.map +1 -1
- package/dist/auth/hooks/index.js +1 -5
- package/dist/auth/hooks/index.js.map +1 -1
- package/dist/auth/hooks/useAuth.js +14 -17
- package/dist/auth/hooks/useAuth.js.map +1 -1
- package/dist/auth/index.js +15 -37
- package/dist/auth/index.js.map +1 -1
- package/dist/auth/server/customer-service.js +39 -83
- package/dist/auth/server/customer-service.js.map +1 -1
- package/dist/auth/server/email-sender.js +11 -17
- package/dist/auth/server/email-sender.js.map +1 -1
- package/dist/auth/server/index.js +5 -36
- package/dist/auth/server/index.js.map +1 -1
- package/dist/auth/server/password-reset-service.js +30 -70
- package/dist/auth/server/password-reset-service.js.map +1 -1
- package/dist/auth/server/password.js +9 -18
- package/dist/auth/server/password.js.map +1 -1
- package/dist/auth/server/verification-service.js +35 -76
- package/dist/auth/server/verification-service.js.map +1 -1
- package/dist/auth/types.js +1 -2
- package/dist/auth/types.js.map +1 -1
- package/dist/cart/CartProvider.js +13 -17
- package/dist/cart/CartProvider.js.map +1 -1
- package/dist/cart/components/AddToCartButton.js +16 -19
- package/dist/cart/components/AddToCartButton.js.map +1 -1
- package/dist/cart/components/CartDrawer.js +17 -23
- package/dist/cart/components/CartDrawer.js.map +1 -1
- package/dist/cart/components/CartIcon.js +9 -12
- package/dist/cart/components/CartIcon.js.map +1 -1
- package/dist/cart/components/CartItem.js +7 -13
- package/dist/cart/components/CartItem.js.map +1 -1
- package/dist/cart/components/CartSummary.js +12 -15
- package/dist/cart/components/CartSummary.js.map +1 -1
- package/dist/cart/components/QuantitySelector.js +9 -12
- package/dist/cart/components/QuantitySelector.js.map +1 -1
- package/dist/cart/components/index.js +6 -15
- package/dist/cart/components/index.js.map +1 -1
- package/dist/cart/index.js +3 -17
- package/dist/cart/index.js.map +1 -1
- package/dist/cart/store.js +8 -13
- package/dist/cart/store.js.map +1 -1
- package/dist/checkout/api/checkout.js +12 -15
- package/dist/checkout/api/checkout.js.map +1 -1
- package/dist/checkout/api/index.js +2 -7
- package/dist/checkout/api/index.js.map +1 -1
- package/dist/checkout/api/webhook.js +8 -11
- package/dist/checkout/api/webhook.js.map +1 -1
- package/dist/checkout/components/CheckoutButton.js +8 -11
- package/dist/checkout/components/CheckoutButton.js.map +1 -1
- package/dist/checkout/components/CheckoutSuccess.js +11 -14
- package/dist/checkout/components/CheckoutSuccess.js.map +1 -1
- package/dist/checkout/components/OrderSummary.js +8 -11
- package/dist/checkout/components/OrderSummary.js.map +1 -1
- package/dist/checkout/components/ShippingForm.js +14 -17
- package/dist/checkout/components/ShippingForm.js.map +1 -1
- package/dist/checkout/components/index.js +4 -11
- package/dist/checkout/components/index.js.map +1 -1
- package/dist/checkout/hooks/index.js +1 -6
- package/dist/checkout/hooks/index.js.map +1 -1
- package/dist/checkout/hooks/useCheckout.js +10 -19
- package/dist/checkout/hooks/useCheckout.js.map +1 -1
- package/dist/checkout/index.js +7 -28
- package/dist/checkout/index.js.map +1 -1
- package/dist/checkout/server/create-checkout-session.js +11 -16
- package/dist/checkout/server/create-checkout-session.js.map +1 -1
- package/dist/checkout/server/handle-webhook.js +21 -24
- package/dist/checkout/server/handle-webhook.js.map +1 -1
- package/dist/checkout/server/index.js +3 -13
- package/dist/checkout/server/index.js.map +1 -1
- package/dist/checkout/server/order-service.js +11 -16
- package/dist/checkout/server/order-service.js.map +1 -1
- package/dist/checkout/stripe/client.js +13 -29
- package/dist/checkout/stripe/client.js.map +1 -1
- package/dist/checkout/stripe/index.js +1 -15
- package/dist/checkout/stripe/index.js.map +1 -1
- package/dist/checkout/types.js +1 -2
- package/dist/checkout/types.js.map +1 -1
- package/dist/core/config.js +12 -57
- package/dist/core/config.js.map +1 -1
- package/dist/core/db/client.js +16 -62
- package/dist/core/db/client.js.map +1 -1
- package/dist/core/db/index.js +14 -93
- package/dist/core/db/index.js.map +1 -1
- package/dist/core/db/queries.js +207 -284
- package/dist/core/db/queries.js.map +1 -1
- package/dist/core/db/schema.js +179 -182
- package/dist/core/db/schema.js.map +1 -1
- package/dist/core/index.js +12 -42
- package/dist/core/index.js.map +1 -1
- package/dist/core/server/index.js +16 -68
- package/dist/core/server/index.js.map +1 -1
- package/dist/core/types.js +1 -2
- package/dist/core/types.js.map +1 -1
- package/dist/core/utils.js +26 -51
- package/dist/core/utils.js.map +1 -1
- package/dist/emails/config.js +13 -21
- package/dist/emails/config.js.map +1 -1
- package/dist/emails/index.js +10 -72
- package/dist/emails/index.js.map +1 -1
- package/dist/emails/send/auth.js +26 -34
- package/dist/emails/send/auth.js.map +1 -1
- package/dist/emails/send/index.js +2 -21
- package/dist/emails/send/index.js.map +1 -1
- package/dist/emails/send/orders.js +38 -50
- package/dist/emails/send/orders.js.map +1 -1
- package/dist/emails/sender.js +7 -12
- package/dist/emails/sender.js.map +1 -1
- package/dist/emails/templates/base.js +37 -53
- package/dist/emails/templates/base.js.map +1 -1
- package/dist/emails/templates/email-verification.js +12 -16
- package/dist/emails/templates/email-verification.js.map +1 -1
- package/dist/emails/templates/index.js +9 -43
- package/dist/emails/templates/index.js.map +1 -1
- package/dist/emails/templates/order-cancelled.js +18 -22
- package/dist/emails/templates/order-cancelled.js.map +1 -1
- package/dist/emails/templates/order-confirmation.js +30 -34
- package/dist/emails/templates/order-confirmation.js.map +1 -1
- package/dist/emails/templates/order-delivered.js +20 -24
- package/dist/emails/templates/order-delivered.js.map +1 -1
- package/dist/emails/templates/order-shipped.js +19 -23
- package/dist/emails/templates/order-shipped.js.map +1 -1
- package/dist/emails/templates/password-reset.js +12 -16
- package/dist/emails/templates/password-reset.js.map +1 -1
- package/dist/emails/templates/refund-processed.js +17 -21
- package/dist/emails/templates/refund-processed.js.map +1 -1
- package/dist/emails/templates/welcome.js +11 -15
- package/dist/emails/templates/welcome.js.map +1 -1
- package/dist/emails/types.js +1 -2
- package/dist/emails/types.js.map +1 -1
- package/dist/emails/utils.js +9 -20
- package/dist/emails/utils.js.map +1 -1
- package/dist/index.js +24 -176
- package/dist/index.js.map +1 -1
- package/dist/products/api/categories.js +7 -10
- package/dist/products/api/categories.js.map +1 -1
- package/dist/products/api/index.js +3 -9
- package/dist/products/api/index.js.map +1 -1
- package/dist/products/api/product.js +10 -13
- package/dist/products/api/product.js.map +1 -1
- package/dist/products/api/products.js +8 -11
- package/dist/products/api/products.js.map +1 -1
- package/dist/products/components/CategoryNav.js +20 -26
- package/dist/products/components/CategoryNav.js.map +1 -1
- package/dist/products/components/ProductBreadcrumb.js +7 -13
- package/dist/products/components/ProductBreadcrumb.js.map +1 -1
- package/dist/products/components/ProductCard.js +6 -12
- package/dist/products/components/ProductCard.js.map +1 -1
- package/dist/products/components/ProductDetails.js +14 -17
- package/dist/products/components/ProductDetails.js.map +1 -1
- package/dist/products/components/ProductFilters.js +15 -18
- package/dist/products/components/ProductFilters.js.map +1 -1
- package/dist/products/components/ProductGallery.js +17 -23
- package/dist/products/components/ProductGallery.js.map +1 -1
- package/dist/products/components/ProductGrid.js +10 -13
- package/dist/products/components/ProductGrid.js.map +1 -1
- package/dist/products/components/ProductSearch.js +14 -17
- package/dist/products/components/ProductSearch.js.map +1 -1
- package/dist/products/components/ProductSort.js +8 -11
- package/dist/products/components/ProductSort.js.map +1 -1
- package/dist/products/components/VariantSelector.js +16 -19
- package/dist/products/components/VariantSelector.js.map +1 -1
- package/dist/products/components/index.js +10 -23
- package/dist/products/components/index.js.map +1 -1
- package/dist/products/hooks/index.js +4 -11
- package/dist/products/hooks/index.js.map +1 -1
- package/dist/products/hooks/useCategories.js +12 -15
- package/dist/products/hooks/useCategories.js.map +1 -1
- package/dist/products/hooks/useProduct.js +9 -12
- package/dist/products/hooks/useProduct.js.map +1 -1
- package/dist/products/hooks/useProductAttributes.js +10 -13
- package/dist/products/hooks/useProductAttributes.js.map +1 -1
- package/dist/products/hooks/useProducts.js +15 -18
- package/dist/products/hooks/useProducts.js.map +1 -1
- package/dist/products/index.js +6 -23
- package/dist/products/index.js.map +1 -1
- package/dist/theme/ThemeProvider.js +12 -14
- package/dist/theme/ThemeProvider.js.map +1 -1
- package/dist/theme/colors.js +3 -8
- package/dist/theme/colors.js.map +1 -1
- package/dist/theme/defaults.js +27 -30
- package/dist/theme/defaults.js.map +1 -1
- package/dist/theme/fonts.js +12 -18
- package/dist/theme/fonts.js.map +1 -1
- package/dist/theme/generator.js +63 -69
- package/dist/theme/generator.js.map +1 -1
- package/dist/theme/hooks.js +11 -16
- package/dist/theme/hooks.js.map +1 -1
- package/dist/theme/index.js +6 -42
- package/dist/theme/index.js.map +1 -1
- package/package.json +35 -34
package/dist/core/db/queries.js
CHANGED
|
@@ -1,126 +1,49 @@
|
|
|
1
|
-
"use strict";
|
|
2
1
|
/**
|
|
3
2
|
* @rovela/sdk/core/db/queries
|
|
4
3
|
*
|
|
5
4
|
* Type-safe query helpers with automatic tenant isolation
|
|
6
5
|
* All queries are scoped to the current tenant
|
|
7
6
|
*/
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
12
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
13
|
-
}
|
|
14
|
-
Object.defineProperty(o, k2, desc);
|
|
15
|
-
}) : (function(o, m, k, k2) {
|
|
16
|
-
if (k2 === undefined) k2 = k;
|
|
17
|
-
o[k2] = m[k];
|
|
18
|
-
}));
|
|
19
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
20
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
21
|
-
}) : function(o, v) {
|
|
22
|
-
o["default"] = v;
|
|
23
|
-
});
|
|
24
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
25
|
-
var ownKeys = function(o) {
|
|
26
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
27
|
-
var ar = [];
|
|
28
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
29
|
-
return ar;
|
|
30
|
-
};
|
|
31
|
-
return ownKeys(o);
|
|
32
|
-
};
|
|
33
|
-
return function (mod) {
|
|
34
|
-
if (mod && mod.__esModule) return mod;
|
|
35
|
-
var result = {};
|
|
36
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
37
|
-
__setModuleDefault(result, mod);
|
|
38
|
-
return result;
|
|
39
|
-
};
|
|
40
|
-
})();
|
|
41
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
42
|
-
exports.findProducts = findProducts;
|
|
43
|
-
exports.findProductBySlug = findProductBySlug;
|
|
44
|
-
exports.findProductById = findProductById;
|
|
45
|
-
exports.findProductVariants = findProductVariants;
|
|
46
|
-
exports.countProducts = countProducts;
|
|
47
|
-
exports.findCategories = findCategories;
|
|
48
|
-
exports.findCategoryBySlug = findCategoryBySlug;
|
|
49
|
-
exports.findOrders = findOrders;
|
|
50
|
-
exports.findOrderById = findOrderById;
|
|
51
|
-
exports.findOrderItems = findOrderItems;
|
|
52
|
-
exports.findCustomerByEmail = findCustomerByEmail;
|
|
53
|
-
exports.findCustomerById = findCustomerById;
|
|
54
|
-
exports.findCustomers = findCustomers;
|
|
55
|
-
exports.findAdminByEmail = findAdminByEmail;
|
|
56
|
-
exports.getStoreStats = getStoreStats;
|
|
57
|
-
exports.getLowStockProducts = getLowStockProducts;
|
|
58
|
-
exports.getRecentOrders = getRecentOrders;
|
|
59
|
-
exports.createOrder = createOrder;
|
|
60
|
-
exports.createOrderItems = createOrderItems;
|
|
61
|
-
exports.updateOrderStatus = updateOrderStatus;
|
|
62
|
-
exports.findOrderByPaymentIntent = findOrderByPaymentIntent;
|
|
63
|
-
exports.createProduct = createProduct;
|
|
64
|
-
exports.updateProduct = updateProduct;
|
|
65
|
-
exports.deleteProduct = deleteProduct;
|
|
66
|
-
exports.hardDeleteProduct = hardDeleteProduct;
|
|
67
|
-
exports.createProductVariant = createProductVariant;
|
|
68
|
-
exports.updateProductVariant = updateProductVariant;
|
|
69
|
-
exports.deleteProductVariant = deleteProductVariant;
|
|
70
|
-
exports.updateVariantInventory = updateVariantInventory;
|
|
71
|
-
exports.findVariantById = findVariantById;
|
|
72
|
-
exports.findCategoryById = findCategoryById;
|
|
73
|
-
exports.createCategory = createCategory;
|
|
74
|
-
exports.updateCategory = updateCategory;
|
|
75
|
-
exports.deleteCategory = deleteCategory;
|
|
76
|
-
exports.countCategories = countCategories;
|
|
77
|
-
exports.countCustomers = countCustomers;
|
|
78
|
-
exports.findCustomerOrders = findCustomerOrders;
|
|
79
|
-
exports.countOrders = countOrders;
|
|
80
|
-
exports.getRevenueByPeriod = getRevenueByPeriod;
|
|
81
|
-
exports.getOrdersByStatus = getOrdersByStatus;
|
|
82
|
-
exports.findSettings = findSettings;
|
|
83
|
-
exports.upsertSettings = upsertSettings;
|
|
84
|
-
const drizzle_orm_1 = require("drizzle-orm");
|
|
85
|
-
const client_1 = require("./client");
|
|
86
|
-
const schema = __importStar(require("./schema"));
|
|
7
|
+
import { eq, and, desc, asc, like, sql, inArray } from 'drizzle-orm';
|
|
8
|
+
import { getDb, getTenantId } from './client';
|
|
9
|
+
import * as schema from './schema';
|
|
87
10
|
/**
|
|
88
11
|
* Find products with filtering, sorting, and pagination
|
|
89
12
|
* Automatically scoped to current tenant
|
|
90
13
|
*/
|
|
91
|
-
async function findProducts(options = {}) {
|
|
92
|
-
const db =
|
|
93
|
-
const tenantId =
|
|
94
|
-
const conditions = [
|
|
14
|
+
export async function findProducts(options = {}) {
|
|
15
|
+
const db = getDb();
|
|
16
|
+
const tenantId = getTenantId();
|
|
17
|
+
const conditions = [eq(schema.products.tenantId, tenantId)];
|
|
95
18
|
if (options.categoryId) {
|
|
96
|
-
conditions.push(
|
|
19
|
+
conditions.push(eq(schema.products.categoryId, options.categoryId));
|
|
97
20
|
}
|
|
98
21
|
if (options.status) {
|
|
99
|
-
conditions.push(
|
|
22
|
+
conditions.push(eq(schema.products.status, options.status));
|
|
100
23
|
}
|
|
101
24
|
if (options.search) {
|
|
102
|
-
conditions.push(
|
|
25
|
+
conditions.push(like(schema.products.name, `%${options.search}%`));
|
|
103
26
|
}
|
|
104
27
|
// Determine sort order
|
|
105
28
|
let orderBy;
|
|
106
29
|
switch (options.sort) {
|
|
107
30
|
case 'price-asc':
|
|
108
|
-
orderBy =
|
|
31
|
+
orderBy = asc(schema.products.price);
|
|
109
32
|
break;
|
|
110
33
|
case 'price-desc':
|
|
111
|
-
orderBy =
|
|
34
|
+
orderBy = desc(schema.products.price);
|
|
112
35
|
break;
|
|
113
36
|
case 'name':
|
|
114
|
-
orderBy =
|
|
37
|
+
orderBy = asc(schema.products.name);
|
|
115
38
|
break;
|
|
116
39
|
case 'newest':
|
|
117
40
|
default:
|
|
118
|
-
orderBy =
|
|
41
|
+
orderBy = desc(schema.products.createdAt);
|
|
119
42
|
}
|
|
120
43
|
const query = db
|
|
121
44
|
.select()
|
|
122
45
|
.from(schema.products)
|
|
123
|
-
.where(
|
|
46
|
+
.where(and(...conditions))
|
|
124
47
|
.orderBy(orderBy);
|
|
125
48
|
if (options.limit) {
|
|
126
49
|
query.limit(options.limit);
|
|
@@ -133,59 +56,59 @@ async function findProducts(options = {}) {
|
|
|
133
56
|
/**
|
|
134
57
|
* Find a single product by slug
|
|
135
58
|
*/
|
|
136
|
-
async function findProductBySlug(slug) {
|
|
137
|
-
const db =
|
|
138
|
-
const tenantId =
|
|
59
|
+
export async function findProductBySlug(slug) {
|
|
60
|
+
const db = getDb();
|
|
61
|
+
const tenantId = getTenantId();
|
|
139
62
|
const result = await db
|
|
140
63
|
.select()
|
|
141
64
|
.from(schema.products)
|
|
142
|
-
.where(
|
|
65
|
+
.where(and(eq(schema.products.tenantId, tenantId), eq(schema.products.slug, slug)))
|
|
143
66
|
.limit(1);
|
|
144
67
|
return result[0] || null;
|
|
145
68
|
}
|
|
146
69
|
/**
|
|
147
70
|
* Find a single product by ID
|
|
148
71
|
*/
|
|
149
|
-
async function findProductById(id) {
|
|
150
|
-
const db =
|
|
151
|
-
const tenantId =
|
|
72
|
+
export async function findProductById(id) {
|
|
73
|
+
const db = getDb();
|
|
74
|
+
const tenantId = getTenantId();
|
|
152
75
|
const result = await db
|
|
153
76
|
.select()
|
|
154
77
|
.from(schema.products)
|
|
155
|
-
.where(
|
|
78
|
+
.where(and(eq(schema.products.tenantId, tenantId), eq(schema.products.id, id)))
|
|
156
79
|
.limit(1);
|
|
157
80
|
return result[0] || null;
|
|
158
81
|
}
|
|
159
82
|
/**
|
|
160
83
|
* Get product variants for a product
|
|
161
84
|
*/
|
|
162
|
-
async function findProductVariants(productId) {
|
|
163
|
-
const db =
|
|
85
|
+
export async function findProductVariants(productId) {
|
|
86
|
+
const db = getDb();
|
|
164
87
|
return db
|
|
165
88
|
.select()
|
|
166
89
|
.from(schema.productVariants)
|
|
167
|
-
.where(
|
|
90
|
+
.where(eq(schema.productVariants.productId, productId));
|
|
168
91
|
}
|
|
169
92
|
/**
|
|
170
93
|
* Count total products matching filters
|
|
171
94
|
*/
|
|
172
|
-
async function countProducts(options = {}) {
|
|
173
|
-
const db =
|
|
174
|
-
const tenantId =
|
|
175
|
-
const conditions = [
|
|
95
|
+
export async function countProducts(options = {}) {
|
|
96
|
+
const db = getDb();
|
|
97
|
+
const tenantId = getTenantId();
|
|
98
|
+
const conditions = [eq(schema.products.tenantId, tenantId)];
|
|
176
99
|
if (options.categoryId) {
|
|
177
|
-
conditions.push(
|
|
100
|
+
conditions.push(eq(schema.products.categoryId, options.categoryId));
|
|
178
101
|
}
|
|
179
102
|
if (options.status) {
|
|
180
|
-
conditions.push(
|
|
103
|
+
conditions.push(eq(schema.products.status, options.status));
|
|
181
104
|
}
|
|
182
105
|
if (options.search) {
|
|
183
|
-
conditions.push(
|
|
106
|
+
conditions.push(like(schema.products.name, `%${options.search}%`));
|
|
184
107
|
}
|
|
185
108
|
const result = await db
|
|
186
|
-
.select({ count:
|
|
109
|
+
.select({ count: sql `count(*)` })
|
|
187
110
|
.from(schema.products)
|
|
188
|
-
.where(
|
|
111
|
+
.where(and(...conditions));
|
|
189
112
|
return Number(result[0]?.count || 0);
|
|
190
113
|
}
|
|
191
114
|
// =============================================================================
|
|
@@ -194,46 +117,46 @@ async function countProducts(options = {}) {
|
|
|
194
117
|
/**
|
|
195
118
|
* Find all categories for the current tenant
|
|
196
119
|
*/
|
|
197
|
-
async function findCategories() {
|
|
198
|
-
const db =
|
|
199
|
-
const tenantId =
|
|
120
|
+
export async function findCategories() {
|
|
121
|
+
const db = getDb();
|
|
122
|
+
const tenantId = getTenantId();
|
|
200
123
|
return db
|
|
201
124
|
.select()
|
|
202
125
|
.from(schema.categories)
|
|
203
|
-
.where(
|
|
204
|
-
.orderBy(
|
|
126
|
+
.where(eq(schema.categories.tenantId, tenantId))
|
|
127
|
+
.orderBy(asc(schema.categories.order), asc(schema.categories.name));
|
|
205
128
|
}
|
|
206
129
|
/**
|
|
207
130
|
* Find a category by slug
|
|
208
131
|
*/
|
|
209
|
-
async function findCategoryBySlug(slug) {
|
|
210
|
-
const db =
|
|
211
|
-
const tenantId =
|
|
132
|
+
export async function findCategoryBySlug(slug) {
|
|
133
|
+
const db = getDb();
|
|
134
|
+
const tenantId = getTenantId();
|
|
212
135
|
const result = await db
|
|
213
136
|
.select()
|
|
214
137
|
.from(schema.categories)
|
|
215
|
-
.where(
|
|
138
|
+
.where(and(eq(schema.categories.tenantId, tenantId), eq(schema.categories.slug, slug)))
|
|
216
139
|
.limit(1);
|
|
217
140
|
return result[0] || null;
|
|
218
141
|
}
|
|
219
142
|
/**
|
|
220
143
|
* Find orders with filtering and pagination
|
|
221
144
|
*/
|
|
222
|
-
async function findOrders(options = {}) {
|
|
223
|
-
const db =
|
|
224
|
-
const tenantId =
|
|
225
|
-
const conditions = [
|
|
145
|
+
export async function findOrders(options = {}) {
|
|
146
|
+
const db = getDb();
|
|
147
|
+
const tenantId = getTenantId();
|
|
148
|
+
const conditions = [eq(schema.orders.tenantId, tenantId)];
|
|
226
149
|
if (options.status) {
|
|
227
|
-
conditions.push(
|
|
150
|
+
conditions.push(eq(schema.orders.status, options.status));
|
|
228
151
|
}
|
|
229
152
|
if (options.customerId) {
|
|
230
|
-
conditions.push(
|
|
153
|
+
conditions.push(eq(schema.orders.customerId, options.customerId));
|
|
231
154
|
}
|
|
232
155
|
const query = db
|
|
233
156
|
.select()
|
|
234
157
|
.from(schema.orders)
|
|
235
|
-
.where(
|
|
236
|
-
.orderBy(
|
|
158
|
+
.where(and(...conditions))
|
|
159
|
+
.orderBy(desc(schema.orders.createdAt));
|
|
237
160
|
if (options.limit) {
|
|
238
161
|
query.limit(options.limit);
|
|
239
162
|
}
|
|
@@ -245,20 +168,20 @@ async function findOrders(options = {}) {
|
|
|
245
168
|
/**
|
|
246
169
|
* Find order by ID with items
|
|
247
170
|
*/
|
|
248
|
-
async function findOrderById(id) {
|
|
249
|
-
const db =
|
|
250
|
-
const tenantId =
|
|
171
|
+
export async function findOrderById(id) {
|
|
172
|
+
const db = getDb();
|
|
173
|
+
const tenantId = getTenantId();
|
|
251
174
|
const order = await db
|
|
252
175
|
.select()
|
|
253
176
|
.from(schema.orders)
|
|
254
|
-
.where(
|
|
177
|
+
.where(and(eq(schema.orders.tenantId, tenantId), eq(schema.orders.id, id)))
|
|
255
178
|
.limit(1);
|
|
256
179
|
if (!order[0])
|
|
257
180
|
return null;
|
|
258
181
|
const items = await db
|
|
259
182
|
.select()
|
|
260
183
|
.from(schema.orderItems)
|
|
261
|
-
.where(
|
|
184
|
+
.where(eq(schema.orderItems.orderId, id));
|
|
262
185
|
return {
|
|
263
186
|
...order[0],
|
|
264
187
|
items,
|
|
@@ -267,12 +190,12 @@ async function findOrderById(id) {
|
|
|
267
190
|
/**
|
|
268
191
|
* Get order items for an order
|
|
269
192
|
*/
|
|
270
|
-
async function findOrderItems(orderId) {
|
|
271
|
-
const db =
|
|
193
|
+
export async function findOrderItems(orderId) {
|
|
194
|
+
const db = getDb();
|
|
272
195
|
return db
|
|
273
196
|
.select()
|
|
274
197
|
.from(schema.orderItems)
|
|
275
|
-
.where(
|
|
198
|
+
.where(eq(schema.orderItems.orderId, orderId));
|
|
276
199
|
}
|
|
277
200
|
// =============================================================================
|
|
278
201
|
// Customers
|
|
@@ -280,44 +203,44 @@ async function findOrderItems(orderId) {
|
|
|
280
203
|
/**
|
|
281
204
|
* Find customer by email
|
|
282
205
|
*/
|
|
283
|
-
async function findCustomerByEmail(email) {
|
|
284
|
-
const db =
|
|
285
|
-
const tenantId =
|
|
206
|
+
export async function findCustomerByEmail(email) {
|
|
207
|
+
const db = getDb();
|
|
208
|
+
const tenantId = getTenantId();
|
|
286
209
|
const result = await db
|
|
287
210
|
.select()
|
|
288
211
|
.from(schema.customers)
|
|
289
|
-
.where(
|
|
212
|
+
.where(and(eq(schema.customers.tenantId, tenantId), eq(schema.customers.email, email.toLowerCase())))
|
|
290
213
|
.limit(1);
|
|
291
214
|
return result[0] || null;
|
|
292
215
|
}
|
|
293
216
|
/**
|
|
294
217
|
* Find customer by ID
|
|
295
218
|
*/
|
|
296
|
-
async function findCustomerById(id) {
|
|
297
|
-
const db =
|
|
298
|
-
const tenantId =
|
|
219
|
+
export async function findCustomerById(id) {
|
|
220
|
+
const db = getDb();
|
|
221
|
+
const tenantId = getTenantId();
|
|
299
222
|
const result = await db
|
|
300
223
|
.select()
|
|
301
224
|
.from(schema.customers)
|
|
302
|
-
.where(
|
|
225
|
+
.where(and(eq(schema.customers.tenantId, tenantId), eq(schema.customers.id, id)))
|
|
303
226
|
.limit(1);
|
|
304
227
|
return result[0] || null;
|
|
305
228
|
}
|
|
306
229
|
/**
|
|
307
230
|
* Find all customers with pagination
|
|
308
231
|
*/
|
|
309
|
-
async function findCustomers(options = {}) {
|
|
310
|
-
const db =
|
|
311
|
-
const tenantId =
|
|
312
|
-
const conditions = [
|
|
232
|
+
export async function findCustomers(options = {}) {
|
|
233
|
+
const db = getDb();
|
|
234
|
+
const tenantId = getTenantId();
|
|
235
|
+
const conditions = [eq(schema.customers.tenantId, tenantId)];
|
|
313
236
|
if (options.search) {
|
|
314
|
-
conditions.push(
|
|
237
|
+
conditions.push(like(schema.customers.email, `%${options.search}%`));
|
|
315
238
|
}
|
|
316
239
|
const query = db
|
|
317
240
|
.select()
|
|
318
241
|
.from(schema.customers)
|
|
319
|
-
.where(
|
|
320
|
-
.orderBy(
|
|
242
|
+
.where(and(...conditions))
|
|
243
|
+
.orderBy(desc(schema.customers.createdAt));
|
|
321
244
|
if (options.limit) {
|
|
322
245
|
query.limit(options.limit);
|
|
323
246
|
}
|
|
@@ -332,13 +255,13 @@ async function findCustomers(options = {}) {
|
|
|
332
255
|
/**
|
|
333
256
|
* Find admin by email
|
|
334
257
|
*/
|
|
335
|
-
async function findAdminByEmail(email) {
|
|
336
|
-
const db =
|
|
337
|
-
const tenantId =
|
|
258
|
+
export async function findAdminByEmail(email) {
|
|
259
|
+
const db = getDb();
|
|
260
|
+
const tenantId = getTenantId();
|
|
338
261
|
const result = await db
|
|
339
262
|
.select()
|
|
340
263
|
.from(schema.storeAdmins)
|
|
341
|
-
.where(
|
|
264
|
+
.where(and(eq(schema.storeAdmins.tenantId, tenantId), eq(schema.storeAdmins.email, email.toLowerCase())))
|
|
342
265
|
.limit(1);
|
|
343
266
|
return result[0] || null;
|
|
344
267
|
}
|
|
@@ -348,30 +271,30 @@ async function findAdminByEmail(email) {
|
|
|
348
271
|
/**
|
|
349
272
|
* Get store statistics for admin dashboard
|
|
350
273
|
*/
|
|
351
|
-
async function getStoreStats() {
|
|
352
|
-
const db =
|
|
353
|
-
const tenantId =
|
|
274
|
+
export async function getStoreStats() {
|
|
275
|
+
const db = getDb();
|
|
276
|
+
const tenantId = getTenantId();
|
|
354
277
|
const [productCount, orderCount, customerCount, revenue] = await Promise.all([
|
|
355
278
|
// Total products
|
|
356
279
|
db
|
|
357
|
-
.select({ count:
|
|
280
|
+
.select({ count: sql `count(*)` })
|
|
358
281
|
.from(schema.products)
|
|
359
|
-
.where(
|
|
282
|
+
.where(and(eq(schema.products.tenantId, tenantId), eq(schema.products.status, 'active'))),
|
|
360
283
|
// Total orders
|
|
361
284
|
db
|
|
362
|
-
.select({ count:
|
|
285
|
+
.select({ count: sql `count(*)` })
|
|
363
286
|
.from(schema.orders)
|
|
364
|
-
.where(
|
|
287
|
+
.where(eq(schema.orders.tenantId, tenantId)),
|
|
365
288
|
// Total customers
|
|
366
289
|
db
|
|
367
|
-
.select({ count:
|
|
290
|
+
.select({ count: sql `count(*)` })
|
|
368
291
|
.from(schema.customers)
|
|
369
|
-
.where(
|
|
292
|
+
.where(eq(schema.customers.tenantId, tenantId)),
|
|
370
293
|
// Total revenue (paid orders only)
|
|
371
294
|
db
|
|
372
|
-
.select({ total:
|
|
295
|
+
.select({ total: sql `COALESCE(SUM(total), 0)` })
|
|
373
296
|
.from(schema.orders)
|
|
374
|
-
.where(
|
|
297
|
+
.where(and(eq(schema.orders.tenantId, tenantId), inArray(schema.orders.status, ['paid', 'shipped', 'delivered']))),
|
|
375
298
|
]);
|
|
376
299
|
return {
|
|
377
300
|
products: Number(productCount[0]?.count || 0),
|
|
@@ -383,9 +306,9 @@ async function getStoreStats() {
|
|
|
383
306
|
/**
|
|
384
307
|
* Get low stock products (inventory < threshold)
|
|
385
308
|
*/
|
|
386
|
-
async function getLowStockProducts(threshold = 10) {
|
|
387
|
-
const db =
|
|
388
|
-
const tenantId =
|
|
309
|
+
export async function getLowStockProducts(threshold = 10) {
|
|
310
|
+
const db = getDb();
|
|
311
|
+
const tenantId = getTenantId();
|
|
389
312
|
// Get products with variants that have low stock
|
|
390
313
|
const lowStockVariants = await db
|
|
391
314
|
.select({
|
|
@@ -393,22 +316,22 @@ async function getLowStockProducts(threshold = 10) {
|
|
|
393
316
|
variant: schema.productVariants,
|
|
394
317
|
})
|
|
395
318
|
.from(schema.productVariants)
|
|
396
|
-
.innerJoin(schema.products,
|
|
397
|
-
.where(
|
|
398
|
-
.orderBy(
|
|
319
|
+
.innerJoin(schema.products, eq(schema.productVariants.productId, schema.products.id))
|
|
320
|
+
.where(and(eq(schema.products.tenantId, tenantId), eq(schema.products.status, 'active'), sql `${schema.productVariants.inventory} < ${threshold}`))
|
|
321
|
+
.orderBy(asc(schema.productVariants.inventory));
|
|
399
322
|
return lowStockVariants;
|
|
400
323
|
}
|
|
401
324
|
/**
|
|
402
325
|
* Get recent orders
|
|
403
326
|
*/
|
|
404
|
-
async function getRecentOrders(limit = 5) {
|
|
405
|
-
const db =
|
|
406
|
-
const tenantId =
|
|
327
|
+
export async function getRecentOrders(limit = 5) {
|
|
328
|
+
const db = getDb();
|
|
329
|
+
const tenantId = getTenantId();
|
|
407
330
|
return db
|
|
408
331
|
.select()
|
|
409
332
|
.from(schema.orders)
|
|
410
|
-
.where(
|
|
411
|
-
.orderBy(
|
|
333
|
+
.where(eq(schema.orders.tenantId, tenantId))
|
|
334
|
+
.orderBy(desc(schema.orders.createdAt))
|
|
412
335
|
.limit(limit);
|
|
413
336
|
}
|
|
414
337
|
// =============================================================================
|
|
@@ -417,9 +340,9 @@ async function getRecentOrders(limit = 5) {
|
|
|
417
340
|
/**
|
|
418
341
|
* Create a new order
|
|
419
342
|
*/
|
|
420
|
-
async function createOrder(data) {
|
|
421
|
-
const db =
|
|
422
|
-
const tenantId =
|
|
343
|
+
export async function createOrder(data) {
|
|
344
|
+
const db = getDb();
|
|
345
|
+
const tenantId = getTenantId();
|
|
423
346
|
const [order] = await db
|
|
424
347
|
.insert(schema.orders)
|
|
425
348
|
.values({ ...data, tenantId })
|
|
@@ -429,8 +352,8 @@ async function createOrder(data) {
|
|
|
429
352
|
/**
|
|
430
353
|
* Create order items for an order
|
|
431
354
|
*/
|
|
432
|
-
async function createOrderItems(items) {
|
|
433
|
-
const db =
|
|
355
|
+
export async function createOrderItems(items) {
|
|
356
|
+
const db = getDb();
|
|
434
357
|
if (items.length === 0) {
|
|
435
358
|
return [];
|
|
436
359
|
}
|
|
@@ -439,13 +362,13 @@ async function createOrderItems(items) {
|
|
|
439
362
|
/**
|
|
440
363
|
* Update order status
|
|
441
364
|
*/
|
|
442
|
-
async function updateOrderStatus(orderId, status) {
|
|
443
|
-
const db =
|
|
444
|
-
const tenantId =
|
|
365
|
+
export async function updateOrderStatus(orderId, status) {
|
|
366
|
+
const db = getDb();
|
|
367
|
+
const tenantId = getTenantId();
|
|
445
368
|
const [order] = await db
|
|
446
369
|
.update(schema.orders)
|
|
447
370
|
.set({ status, updatedAt: new Date() })
|
|
448
|
-
.where(
|
|
371
|
+
.where(and(eq(schema.orders.tenantId, tenantId), eq(schema.orders.id, orderId)))
|
|
449
372
|
.returning();
|
|
450
373
|
return order || null;
|
|
451
374
|
}
|
|
@@ -453,13 +376,13 @@ async function updateOrderStatus(orderId, status) {
|
|
|
453
376
|
* Find order by Stripe Payment Intent ID
|
|
454
377
|
* Used for idempotency in webhook handling
|
|
455
378
|
*/
|
|
456
|
-
async function findOrderByPaymentIntent(paymentIntentId) {
|
|
457
|
-
const db =
|
|
458
|
-
const tenantId =
|
|
379
|
+
export async function findOrderByPaymentIntent(paymentIntentId) {
|
|
380
|
+
const db = getDb();
|
|
381
|
+
const tenantId = getTenantId();
|
|
459
382
|
const [order] = await db
|
|
460
383
|
.select()
|
|
461
384
|
.from(schema.orders)
|
|
462
|
-
.where(
|
|
385
|
+
.where(and(eq(schema.orders.tenantId, tenantId), eq(schema.orders.stripePaymentIntentId, paymentIntentId)))
|
|
463
386
|
.limit(1);
|
|
464
387
|
return order || null;
|
|
465
388
|
}
|
|
@@ -469,9 +392,9 @@ async function findOrderByPaymentIntent(paymentIntentId) {
|
|
|
469
392
|
/**
|
|
470
393
|
* Create a new product
|
|
471
394
|
*/
|
|
472
|
-
async function createProduct(data) {
|
|
473
|
-
const db =
|
|
474
|
-
const tenantId =
|
|
395
|
+
export async function createProduct(data) {
|
|
396
|
+
const db = getDb();
|
|
397
|
+
const tenantId = getTenantId();
|
|
475
398
|
const [product] = await db
|
|
476
399
|
.insert(schema.products)
|
|
477
400
|
.values({ ...data, tenantId })
|
|
@@ -481,13 +404,13 @@ async function createProduct(data) {
|
|
|
481
404
|
/**
|
|
482
405
|
* Update a product by ID
|
|
483
406
|
*/
|
|
484
|
-
async function updateProduct(id, data) {
|
|
485
|
-
const db =
|
|
486
|
-
const tenantId =
|
|
407
|
+
export async function updateProduct(id, data) {
|
|
408
|
+
const db = getDb();
|
|
409
|
+
const tenantId = getTenantId();
|
|
487
410
|
const [product] = await db
|
|
488
411
|
.update(schema.products)
|
|
489
412
|
.set({ ...data, updatedAt: new Date() })
|
|
490
|
-
.where(
|
|
413
|
+
.where(and(eq(schema.products.tenantId, tenantId), eq(schema.products.id, id)))
|
|
491
414
|
.returning();
|
|
492
415
|
return product || null;
|
|
493
416
|
}
|
|
@@ -496,7 +419,7 @@ async function updateProduct(id, data) {
|
|
|
496
419
|
* Sets status to 'archived' instead of deleting to preserve order history.
|
|
497
420
|
* Use hardDeleteProduct() for permanent deletion if needed.
|
|
498
421
|
*/
|
|
499
|
-
async function deleteProduct(id) {
|
|
422
|
+
export async function deleteProduct(id) {
|
|
500
423
|
const result = await updateProduct(id, { status: 'archived' });
|
|
501
424
|
return result !== null;
|
|
502
425
|
}
|
|
@@ -505,12 +428,12 @@ async function deleteProduct(id) {
|
|
|
505
428
|
* WARNING: This will fail if there are order_items referencing this product.
|
|
506
429
|
* Use deleteProduct() (soft delete) for most cases.
|
|
507
430
|
*/
|
|
508
|
-
async function hardDeleteProduct(id) {
|
|
509
|
-
const db =
|
|
510
|
-
const tenantId =
|
|
431
|
+
export async function hardDeleteProduct(id) {
|
|
432
|
+
const db = getDb();
|
|
433
|
+
const tenantId = getTenantId();
|
|
511
434
|
const result = await db
|
|
512
435
|
.delete(schema.products)
|
|
513
|
-
.where(
|
|
436
|
+
.where(and(eq(schema.products.tenantId, tenantId), eq(schema.products.id, id)))
|
|
514
437
|
.returning({ id: schema.products.id });
|
|
515
438
|
return result.length > 0;
|
|
516
439
|
}
|
|
@@ -520,8 +443,8 @@ async function hardDeleteProduct(id) {
|
|
|
520
443
|
/**
|
|
521
444
|
* Create a new product variant
|
|
522
445
|
*/
|
|
523
|
-
async function createProductVariant(data) {
|
|
524
|
-
const db =
|
|
446
|
+
export async function createProductVariant(data) {
|
|
447
|
+
const db = getDb();
|
|
525
448
|
const [variant] = await db
|
|
526
449
|
.insert(schema.productVariants)
|
|
527
450
|
.values(data)
|
|
@@ -531,45 +454,45 @@ async function createProductVariant(data) {
|
|
|
531
454
|
/**
|
|
532
455
|
* Update a product variant by ID
|
|
533
456
|
*/
|
|
534
|
-
async function updateProductVariant(id, data) {
|
|
535
|
-
const db =
|
|
457
|
+
export async function updateProductVariant(id, data) {
|
|
458
|
+
const db = getDb();
|
|
536
459
|
const [variant] = await db
|
|
537
460
|
.update(schema.productVariants)
|
|
538
461
|
.set(data)
|
|
539
|
-
.where(
|
|
462
|
+
.where(eq(schema.productVariants.id, id))
|
|
540
463
|
.returning();
|
|
541
464
|
return variant || null;
|
|
542
465
|
}
|
|
543
466
|
/**
|
|
544
467
|
* Delete a product variant by ID
|
|
545
468
|
*/
|
|
546
|
-
async function deleteProductVariant(id) {
|
|
547
|
-
const db =
|
|
469
|
+
export async function deleteProductVariant(id) {
|
|
470
|
+
const db = getDb();
|
|
548
471
|
const result = await db
|
|
549
472
|
.delete(schema.productVariants)
|
|
550
|
-
.where(
|
|
473
|
+
.where(eq(schema.productVariants.id, id))
|
|
551
474
|
.returning({ id: schema.productVariants.id });
|
|
552
475
|
return result.length > 0;
|
|
553
476
|
}
|
|
554
477
|
/**
|
|
555
478
|
* Update variant inventory
|
|
556
479
|
*/
|
|
557
|
-
async function updateVariantInventory(id, inventory) {
|
|
558
|
-
const db =
|
|
480
|
+
export async function updateVariantInventory(id, inventory) {
|
|
481
|
+
const db = getDb();
|
|
559
482
|
await db
|
|
560
483
|
.update(schema.productVariants)
|
|
561
484
|
.set({ inventory })
|
|
562
|
-
.where(
|
|
485
|
+
.where(eq(schema.productVariants.id, id));
|
|
563
486
|
}
|
|
564
487
|
/**
|
|
565
488
|
* Find a variant by ID
|
|
566
489
|
*/
|
|
567
|
-
async function findVariantById(id) {
|
|
568
|
-
const db =
|
|
490
|
+
export async function findVariantById(id) {
|
|
491
|
+
const db = getDb();
|
|
569
492
|
const [variant] = await db
|
|
570
493
|
.select()
|
|
571
494
|
.from(schema.productVariants)
|
|
572
|
-
.where(
|
|
495
|
+
.where(eq(schema.productVariants.id, id))
|
|
573
496
|
.limit(1);
|
|
574
497
|
return variant || null;
|
|
575
498
|
}
|
|
@@ -579,22 +502,22 @@ async function findVariantById(id) {
|
|
|
579
502
|
/**
|
|
580
503
|
* Find a category by ID
|
|
581
504
|
*/
|
|
582
|
-
async function findCategoryById(id) {
|
|
583
|
-
const db =
|
|
584
|
-
const tenantId =
|
|
505
|
+
export async function findCategoryById(id) {
|
|
506
|
+
const db = getDb();
|
|
507
|
+
const tenantId = getTenantId();
|
|
585
508
|
const [category] = await db
|
|
586
509
|
.select()
|
|
587
510
|
.from(schema.categories)
|
|
588
|
-
.where(
|
|
511
|
+
.where(and(eq(schema.categories.tenantId, tenantId), eq(schema.categories.id, id)))
|
|
589
512
|
.limit(1);
|
|
590
513
|
return category || null;
|
|
591
514
|
}
|
|
592
515
|
/**
|
|
593
516
|
* Create a new category
|
|
594
517
|
*/
|
|
595
|
-
async function createCategory(data) {
|
|
596
|
-
const db =
|
|
597
|
-
const tenantId =
|
|
518
|
+
export async function createCategory(data) {
|
|
519
|
+
const db = getDb();
|
|
520
|
+
const tenantId = getTenantId();
|
|
598
521
|
const [category] = await db
|
|
599
522
|
.insert(schema.categories)
|
|
600
523
|
.values({ ...data, tenantId })
|
|
@@ -604,38 +527,38 @@ async function createCategory(data) {
|
|
|
604
527
|
/**
|
|
605
528
|
* Update a category by ID
|
|
606
529
|
*/
|
|
607
|
-
async function updateCategory(id, data) {
|
|
608
|
-
const db =
|
|
609
|
-
const tenantId =
|
|
530
|
+
export async function updateCategory(id, data) {
|
|
531
|
+
const db = getDb();
|
|
532
|
+
const tenantId = getTenantId();
|
|
610
533
|
const [category] = await db
|
|
611
534
|
.update(schema.categories)
|
|
612
535
|
.set(data)
|
|
613
|
-
.where(
|
|
536
|
+
.where(and(eq(schema.categories.tenantId, tenantId), eq(schema.categories.id, id)))
|
|
614
537
|
.returning();
|
|
615
538
|
return category || null;
|
|
616
539
|
}
|
|
617
540
|
/**
|
|
618
541
|
* Delete a category by ID
|
|
619
542
|
*/
|
|
620
|
-
async function deleteCategory(id) {
|
|
621
|
-
const db =
|
|
622
|
-
const tenantId =
|
|
543
|
+
export async function deleteCategory(id) {
|
|
544
|
+
const db = getDb();
|
|
545
|
+
const tenantId = getTenantId();
|
|
623
546
|
const result = await db
|
|
624
547
|
.delete(schema.categories)
|
|
625
|
-
.where(
|
|
548
|
+
.where(and(eq(schema.categories.tenantId, tenantId), eq(schema.categories.id, id)))
|
|
626
549
|
.returning({ id: schema.categories.id });
|
|
627
550
|
return result.length > 0;
|
|
628
551
|
}
|
|
629
552
|
/**
|
|
630
553
|
* Count categories for the current tenant
|
|
631
554
|
*/
|
|
632
|
-
async function countCategories() {
|
|
633
|
-
const db =
|
|
634
|
-
const tenantId =
|
|
555
|
+
export async function countCategories() {
|
|
556
|
+
const db = getDb();
|
|
557
|
+
const tenantId = getTenantId();
|
|
635
558
|
const result = await db
|
|
636
|
-
.select({ count:
|
|
559
|
+
.select({ count: sql `count(*)` })
|
|
637
560
|
.from(schema.categories)
|
|
638
|
-
.where(
|
|
561
|
+
.where(eq(schema.categories.tenantId, tenantId));
|
|
639
562
|
return Number(result[0]?.count || 0);
|
|
640
563
|
}
|
|
641
564
|
// =============================================================================
|
|
@@ -644,30 +567,30 @@ async function countCategories() {
|
|
|
644
567
|
/**
|
|
645
568
|
* Count customers for the current tenant with optional search
|
|
646
569
|
*/
|
|
647
|
-
async function countCustomers(options = {}) {
|
|
648
|
-
const db =
|
|
649
|
-
const tenantId =
|
|
650
|
-
const conditions = [
|
|
570
|
+
export async function countCustomers(options = {}) {
|
|
571
|
+
const db = getDb();
|
|
572
|
+
const tenantId = getTenantId();
|
|
573
|
+
const conditions = [eq(schema.customers.tenantId, tenantId)];
|
|
651
574
|
if (options.search) {
|
|
652
|
-
conditions.push(
|
|
575
|
+
conditions.push(like(schema.customers.email, `%${options.search}%`));
|
|
653
576
|
}
|
|
654
577
|
const result = await db
|
|
655
|
-
.select({ count:
|
|
578
|
+
.select({ count: sql `count(*)` })
|
|
656
579
|
.from(schema.customers)
|
|
657
|
-
.where(
|
|
580
|
+
.where(and(...conditions));
|
|
658
581
|
return Number(result[0]?.count || 0);
|
|
659
582
|
}
|
|
660
583
|
/**
|
|
661
584
|
* Find orders for a specific customer
|
|
662
585
|
*/
|
|
663
|
-
async function findCustomerOrders(customerId) {
|
|
664
|
-
const db =
|
|
665
|
-
const tenantId =
|
|
586
|
+
export async function findCustomerOrders(customerId) {
|
|
587
|
+
const db = getDb();
|
|
588
|
+
const tenantId = getTenantId();
|
|
666
589
|
return db
|
|
667
590
|
.select()
|
|
668
591
|
.from(schema.orders)
|
|
669
|
-
.where(
|
|
670
|
-
.orderBy(
|
|
592
|
+
.where(and(eq(schema.orders.tenantId, tenantId), eq(schema.orders.customerId, customerId)))
|
|
593
|
+
.orderBy(desc(schema.orders.createdAt));
|
|
671
594
|
}
|
|
672
595
|
// =============================================================================
|
|
673
596
|
// Order Queries (for admin module)
|
|
@@ -675,36 +598,36 @@ async function findCustomerOrders(customerId) {
|
|
|
675
598
|
/**
|
|
676
599
|
* Count orders with optional status filter
|
|
677
600
|
*/
|
|
678
|
-
async function countOrders(options = {}) {
|
|
679
|
-
const db =
|
|
680
|
-
const tenantId =
|
|
681
|
-
const conditions = [
|
|
601
|
+
export async function countOrders(options = {}) {
|
|
602
|
+
const db = getDb();
|
|
603
|
+
const tenantId = getTenantId();
|
|
604
|
+
const conditions = [eq(schema.orders.tenantId, tenantId)];
|
|
682
605
|
if (options.status) {
|
|
683
|
-
conditions.push(
|
|
606
|
+
conditions.push(eq(schema.orders.status, options.status));
|
|
684
607
|
}
|
|
685
608
|
const result = await db
|
|
686
|
-
.select({ count:
|
|
609
|
+
.select({ count: sql `count(*)` })
|
|
687
610
|
.from(schema.orders)
|
|
688
|
-
.where(
|
|
611
|
+
.where(and(...conditions));
|
|
689
612
|
return Number(result[0]?.count || 0);
|
|
690
613
|
}
|
|
691
614
|
/**
|
|
692
615
|
* Get revenue by period (for analytics)
|
|
693
616
|
*/
|
|
694
|
-
async function getRevenueByPeriod(days) {
|
|
695
|
-
const db =
|
|
696
|
-
const tenantId =
|
|
617
|
+
export async function getRevenueByPeriod(days) {
|
|
618
|
+
const db = getDb();
|
|
619
|
+
const tenantId = getTenantId();
|
|
697
620
|
const startDate = new Date();
|
|
698
621
|
startDate.setDate(startDate.getDate() - days);
|
|
699
622
|
const result = await db
|
|
700
623
|
.select({
|
|
701
|
-
date:
|
|
702
|
-
revenue:
|
|
624
|
+
date: sql `DATE(${schema.orders.createdAt})`,
|
|
625
|
+
revenue: sql `COALESCE(SUM(${schema.orders.total}), 0)`,
|
|
703
626
|
})
|
|
704
627
|
.from(schema.orders)
|
|
705
|
-
.where(
|
|
706
|
-
.groupBy(
|
|
707
|
-
.orderBy(
|
|
628
|
+
.where(and(eq(schema.orders.tenantId, tenantId), inArray(schema.orders.status, ['paid', 'shipped', 'delivered']), sql `${schema.orders.createdAt} >= ${startDate.toISOString()}`))
|
|
629
|
+
.groupBy(sql `DATE(${schema.orders.createdAt})`)
|
|
630
|
+
.orderBy(sql `DATE(${schema.orders.createdAt})`);
|
|
708
631
|
return result.map((r) => ({
|
|
709
632
|
date: String(r.date),
|
|
710
633
|
revenue: Number(r.revenue),
|
|
@@ -713,16 +636,16 @@ async function getRevenueByPeriod(days) {
|
|
|
713
636
|
/**
|
|
714
637
|
* Get orders by status count (for analytics)
|
|
715
638
|
*/
|
|
716
|
-
async function getOrdersByStatus() {
|
|
717
|
-
const db =
|
|
718
|
-
const tenantId =
|
|
639
|
+
export async function getOrdersByStatus() {
|
|
640
|
+
const db = getDb();
|
|
641
|
+
const tenantId = getTenantId();
|
|
719
642
|
const result = await db
|
|
720
643
|
.select({
|
|
721
644
|
status: schema.orders.status,
|
|
722
|
-
count:
|
|
645
|
+
count: sql `count(*)`,
|
|
723
646
|
})
|
|
724
647
|
.from(schema.orders)
|
|
725
|
-
.where(
|
|
648
|
+
.where(eq(schema.orders.tenantId, tenantId))
|
|
726
649
|
.groupBy(schema.orders.status);
|
|
727
650
|
return result.map((r) => ({
|
|
728
651
|
status: r.status,
|
|
@@ -733,13 +656,13 @@ async function getOrdersByStatus() {
|
|
|
733
656
|
* Find store settings for the current tenant.
|
|
734
657
|
* Returns null if no settings exist (first time access).
|
|
735
658
|
*/
|
|
736
|
-
async function findSettings() {
|
|
737
|
-
const db =
|
|
738
|
-
const tenantId =
|
|
659
|
+
export async function findSettings() {
|
|
660
|
+
const db = getDb();
|
|
661
|
+
const tenantId = getTenantId();
|
|
739
662
|
const [settings] = await db
|
|
740
663
|
.select()
|
|
741
664
|
.from(schema.storeSettings)
|
|
742
|
-
.where(
|
|
665
|
+
.where(eq(schema.storeSettings.tenantId, tenantId))
|
|
743
666
|
.limit(1);
|
|
744
667
|
if (!settings)
|
|
745
668
|
return null;
|
|
@@ -760,9 +683,9 @@ async function findSettings() {
|
|
|
760
683
|
* Upsert (create or update) store settings for the current tenant.
|
|
761
684
|
* Uses ON CONFLICT to update if row already exists.
|
|
762
685
|
*/
|
|
763
|
-
async function upsertSettings(data) {
|
|
764
|
-
const db =
|
|
765
|
-
const tenantId =
|
|
686
|
+
export async function upsertSettings(data) {
|
|
687
|
+
const db = getDb();
|
|
688
|
+
const tenantId = getTenantId();
|
|
766
689
|
// Build the values object
|
|
767
690
|
const values = {
|
|
768
691
|
tenantId,
|
|
@@ -787,14 +710,14 @@ async function upsertSettings(data) {
|
|
|
787
710
|
.onConflictDoUpdate({
|
|
788
711
|
target: schema.storeSettings.tenantId,
|
|
789
712
|
set: {
|
|
790
|
-
storeName:
|
|
791
|
-
storeEmail:
|
|
792
|
-
storeCurrency:
|
|
793
|
-
storeTimezone:
|
|
794
|
-
taxEnabled:
|
|
795
|
-
taxRate:
|
|
796
|
-
shippingEnabled:
|
|
797
|
-
freeShippingThreshold:
|
|
713
|
+
storeName: sql `COALESCE(EXCLUDED.store_name, ${schema.storeSettings.storeName})`,
|
|
714
|
+
storeEmail: sql `COALESCE(EXCLUDED.store_email, ${schema.storeSettings.storeEmail})`,
|
|
715
|
+
storeCurrency: sql `COALESCE(EXCLUDED.store_currency, ${schema.storeSettings.storeCurrency})`,
|
|
716
|
+
storeTimezone: sql `COALESCE(EXCLUDED.store_timezone, ${schema.storeSettings.storeTimezone})`,
|
|
717
|
+
taxEnabled: sql `COALESCE(EXCLUDED.tax_enabled, ${schema.storeSettings.taxEnabled})`,
|
|
718
|
+
taxRate: sql `COALESCE(EXCLUDED.tax_rate, ${schema.storeSettings.taxRate})`,
|
|
719
|
+
shippingEnabled: sql `COALESCE(EXCLUDED.shipping_enabled, ${schema.storeSettings.shippingEnabled})`,
|
|
720
|
+
freeShippingThreshold: sql `COALESCE(EXCLUDED.free_shipping_threshold, ${schema.storeSettings.freeShippingThreshold})`,
|
|
798
721
|
updatedAt: new Date(),
|
|
799
722
|
},
|
|
800
723
|
})
|