mirror of
https://git.meshkee.com/Meshkee/backend.git
synced 2026-08-11 22:30:59 +04:30
Initial commit: Meshkee CMS API
NestJS backend with Prisma, Docker Compose for Postgres/Redis, and deploy docs for the production VM.
This commit is contained in:
@@ -0,0 +1,183 @@
|
||||
-- Sample seed data for local development / DataGrip testing
|
||||
-- Password for all users: password
|
||||
--
|
||||
-- User types:
|
||||
-- 1 Ali — super_admin
|
||||
-- 2 Reza — business_owner (Meshkee Demo Shop)
|
||||
-- 3 Sara — business_owner (Creative Studio)
|
||||
-- 4 Mina — customer on shop-a.local
|
||||
-- 5 Amir — customer on studio-b.local
|
||||
|
||||
INSERT INTO users (id, cell_number, password_hash, email, first_name, last_name, cell_verified_at) VALUES
|
||||
(1, '+989121111111', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'ali@meshkee.demo', 'Ali', 'Hassani', NOW()),
|
||||
(2, '+989122222222', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'reza@shop.demo', 'Reza', 'Ahmadi', NOW()),
|
||||
(3, '+989123333333', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'sara@studio.demo', 'Sara', 'Karimi', NOW()),
|
||||
(4, '+989124444444', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'mina@customer.demo', 'Mina', 'Salehi', NOW()),
|
||||
(5, '+989125555555', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'amir@customer.demo', 'Amir', 'Jafari', NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO businesses (id, name, name_fa, about, slug, description) VALUES
|
||||
(1, 'Meshkee Demo Shop', 'فروشگاه دمو مشکی', 'فروشگاه آنلاین نمونه برای تست سیستم', 'meshkee-demo-shop', 'Sample e-commerce business'),
|
||||
(2, 'Creative Studio', 'استودیو خلاق', 'آژانس طراحی و برندینگ', 'creative-studio', 'Design and branding agency')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- System business categories are seeded in 005_business_categories.sql
|
||||
|
||||
INSERT INTO domains (id, business_id, host, is_primary, is_verified, verified_at, ssl_enabled) VALUES
|
||||
(1, 1, 'shop-a.local', TRUE, TRUE, NOW(), FALSE),
|
||||
(2, 1, 'www.shop-a.local', FALSE, TRUE, NOW(), FALSE),
|
||||
(3, 2, 'studio-b.local', TRUE, TRUE, NOW(), FALSE)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- Roles
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT 1, r.id FROM roles r WHERE r.slug = 'super_admin'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT 2, r.id FROM roles r WHERE r.slug = 'business_owner'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT 3, r.id FROM roles r WHERE r.slug = 'business_owner'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT 4, r.id FROM roles r WHERE r.slug = 'customer'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT 5, r.id FROM roles r WHERE r.slug = 'customer'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
-- Business owners (assigned by super admin)
|
||||
INSERT INTO business_users (id, business_id, user_id, is_owner) VALUES
|
||||
(1, 1, 2, TRUE),
|
||||
(2, 2, 3, TRUE)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
-- Team staff: editor on business 1 (invited by business owner)
|
||||
INSERT INTO users (id, cell_number, password_hash, email, first_name, last_name, cell_verified_at) VALUES
|
||||
(6, '+989126666667', '$2b$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', 'editor@shop.demo', 'Nima', 'Editori', NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO business_users (id, business_id, user_id, is_owner, role_id, invited_by)
|
||||
SELECT 3, 1, 6, FALSE, r.id, 2
|
||||
FROM roles r WHERE r.slug = 'editor'
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT 6, r.id FROM roles r WHERE r.slug = 'business_staff'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
|
||||
-- Website customers
|
||||
INSERT INTO business_customers (id, business_id, user_id) VALUES
|
||||
(1, 1, 4),
|
||||
(2, 2, 5)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO media (
|
||||
id, business_id, uploaded_by, media_type, storage_disk, storage_path, public_url,
|
||||
file_name, original_file_name, mime_type, file_size_bytes, width, height, duration_seconds, alt_text
|
||||
) VALUES
|
||||
(1, 1, 2, 'image', 'local', '/uploads/shop/hero-phone.jpg', 'https://cdn.meshkee.demo/shop/hero-phone.jpg', 'hero-phone.jpg', 'hero-phone.jpg', 'image/jpeg', 245000, 1200, 800, NULL, 'Smartphone hero'),
|
||||
(2, 1, 2, 'image', 'local', '/uploads/shop/laptop.jpg', 'https://cdn.meshkee.demo/shop/laptop.jpg', 'laptop.jpg', 'laptop.jpg', 'image/jpeg', 198000, 1200, 800, NULL, 'Laptop product shot'),
|
||||
(3, 1, 2, 'video', 'local', '/uploads/shop/unboxing.mp4', 'https://cdn.meshkee.demo/shop/unboxing.mp4', 'unboxing.mp4', 'unboxing.mp4', 'video/mp4', 5200000, NULL, NULL, 42.50, 'Product unboxing'),
|
||||
(4, 2, 3, 'image', 'local', '/uploads/studio/brand-cover.jpg', 'https://cdn.meshkee.demo/studio/brand-cover.jpg', 'brand-cover.jpg', 'brand-cover.jpg', 'image/jpeg', 310000, 1600, 900, NULL, 'Branding project cover'),
|
||||
(5, 2, 3, 'image', 'local', '/uploads/studio/web-ui.jpg', 'https://cdn.meshkee.demo/studio/web-ui.jpg', 'web-ui.jpg', 'web-ui.jpg', 'image/jpeg', 275000, 1440, 900, NULL, 'Web design mockup')
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO categories (id, business_id, entity_type, parent_id, name, slug, description, sort_order) VALUES
|
||||
(1, 1, 'product', NULL, 'Electronics', 'electronics', 'Electronic devices', 1),
|
||||
(2, 1, 'product', 1, 'Phones', 'phones', 'Mobile phones', 1),
|
||||
(3, 1, 'product', 1, 'Laptops', 'laptops', 'Laptops and notebooks', 2),
|
||||
(4, 1, 'product', NULL, 'Accessories', 'accessories', 'Phone and laptop accessories', 2),
|
||||
(5, 1, 'blog', NULL, 'Tutorials', 'tutorials', 'How-to guides', 1),
|
||||
(6, 1, 'blog', NULL, 'News', 'news', 'Store news and updates', 2),
|
||||
(7, 1, 'portfolio', NULL, 'Product Photography', 'product-photography', 'Commercial product shoots', 1),
|
||||
(8, 2, 'product', NULL, 'Design Packages', 'design-packages', 'Service packages', 1),
|
||||
(9, 2, 'blog', NULL, 'Case Studies', 'case-studies', 'Client success stories', 1),
|
||||
(10, 2, 'blog', NULL, 'Design Tips', 'design-tips', 'Tips for better design', 2),
|
||||
(11, 2, 'portfolio', NULL, 'Branding', 'branding', 'Logo and identity work', 1),
|
||||
(12, 2, 'portfolio', NULL, 'Web Design', 'web-design', 'Websites and web apps', 2)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO products (
|
||||
id, business_id, title, slug, description, content, price, compare_at_price, sku,
|
||||
stock_quantity, status, featured_media_id, sort_order, published_at
|
||||
) VALUES
|
||||
(1, 1, 'Meshkee X Phone', 'meshkee-x-phone', 'Flagship smartphone with OLED display.',
|
||||
'{"blocks":[{"type":"paragraph","text":"6.5 inch OLED, 256GB storage."}]}',
|
||||
12990000, 14990000, 'MXP-001', 25, 'published', 1, 1, NOW()),
|
||||
(2, 1, 'Meshkee Book Pro', 'meshkee-book-pro', 'Lightweight laptop for creators.',
|
||||
'{"blocks":[{"type":"paragraph","text":"14 inch, 16GB RAM, 512GB SSD."}]}',
|
||||
28990000, NULL, 'MBP-001', 10, 'published', 2, 2, NOW()),
|
||||
(3, 2, 'Brand Identity Package', 'brand-identity-package', 'Logo, color palette, and brand guidelines.',
|
||||
'{"blocks":[{"type":"paragraph","text":"Includes 3 logo concepts."}]}',
|
||||
15000000, NULL, 'PKG-BRAND-01', NULL, 'published', 4, 1, NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO blogs (
|
||||
id, business_id, author_id, title, slug, excerpt, content, status, featured_media_id, published_at
|
||||
) VALUES
|
||||
(1, 1, 2, 'How to Choose the Right Phone', 'how-to-choose-phone',
|
||||
'A quick guide to picking your next smartphone.',
|
||||
'{"blocks":[{"type":"heading","text":"Battery life"},{"type":"paragraph","text":"Look for 4000mAh or more."}]}',
|
||||
'published', 1, NOW()),
|
||||
(2, 1, 2, 'Summer Sale Starts Next Week', 'summer-sale-next-week',
|
||||
'Up to 30% off on selected electronics.',
|
||||
'{"blocks":[{"type":"paragraph","text":"Sale runs Monday through Sunday."}]}',
|
||||
'draft', NULL, NULL),
|
||||
(3, 2, 3, 'Rebranding a Local Café', 'rebranding-local-cafe',
|
||||
'How we refreshed a neighborhood café brand.',
|
||||
'{"blocks":[{"type":"paragraph","text":"We started with customer interviews."}]}',
|
||||
'published', 4, NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO portfolios (
|
||||
id, business_id, title, slug, description, content, client_name, project_url,
|
||||
status, featured_media_id, sort_order, published_at
|
||||
) VALUES
|
||||
(1, 1, 'Phone Launch Campaign', 'phone-launch-campaign',
|
||||
'Product photos and video for Meshkee X Phone launch.',
|
||||
'{"blocks":[{"type":"paragraph","text":"Shot in studio with 3 lighting setups."}]}',
|
||||
'Meshkee', 'https://shop-a.local/products/meshkee-x-phone', 'published', 1, 1, NOW()),
|
||||
(2, 2, 'Nova Café Rebrand', 'nova-cafe-rebrand',
|
||||
'Full brand identity for Nova Café.',
|
||||
'{"blocks":[{"type":"paragraph","text":"Logo, menu design, and signage."}]}',
|
||||
'Nova Café', 'https://novacafe.example.com', 'published', 4, 1, NOW()),
|
||||
(3, 2, 'FinTech Dashboard UI', 'fintech-dashboard-ui',
|
||||
'Dashboard design for a financial startup.',
|
||||
'{"blocks":[{"type":"paragraph","text":"Dark mode first design system."}]}',
|
||||
'PayFlow', 'https://payflow.example.com', 'published', 5, 2, NOW())
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO category_assignments (id, business_id, category_id, entity_type, entity_id) VALUES
|
||||
(1, 1, 2, 'product', 1),
|
||||
(2, 1, 3, 'product', 2),
|
||||
(3, 2, 8, 'product', 3),
|
||||
(4, 1, 5, 'blog', 1),
|
||||
(5, 1, 6, 'blog', 2),
|
||||
(6, 2, 9, 'blog', 3),
|
||||
(7, 1, 7, 'portfolio', 1),
|
||||
(8, 2, 11, 'portfolio', 2),
|
||||
(9, 2, 12, 'portfolio', 3)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
INSERT INTO media_attachments (id, business_id, media_id, entity_type, entity_id, sort_order, is_featured) VALUES
|
||||
(1, 1, 3, 'product', 1, 1, FALSE),
|
||||
(2, 2, 5, 'portfolio', 3, 1, FALSE)
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
SELECT setval(pg_get_serial_sequence('users', 'id'), COALESCE((SELECT MAX(id) FROM users), 1));
|
||||
SELECT setval(pg_get_serial_sequence('businesses', 'id'), COALESCE((SELECT MAX(id) FROM businesses), 1));
|
||||
SELECT setval(pg_get_serial_sequence('domains', 'id'), COALESCE((SELECT MAX(id) FROM domains), 1));
|
||||
SELECT setval(pg_get_serial_sequence('business_users', 'id'), COALESCE((SELECT MAX(id) FROM business_users), 1));
|
||||
SELECT setval(pg_get_serial_sequence('business_customers', 'id'), COALESCE((SELECT MAX(id) FROM business_customers), 1));
|
||||
SELECT setval(pg_get_serial_sequence('media', 'id'), COALESCE((SELECT MAX(id) FROM media), 1));
|
||||
SELECT setval(pg_get_serial_sequence('categories', 'id'), COALESCE((SELECT MAX(id) FROM categories), 1));
|
||||
SELECT setval(pg_get_serial_sequence('products', 'id'), COALESCE((SELECT MAX(id) FROM products), 1));
|
||||
SELECT setval(pg_get_serial_sequence('blogs', 'id'), COALESCE((SELECT MAX(id) FROM blogs), 1));
|
||||
SELECT setval(pg_get_serial_sequence('portfolios', 'id'), COALESCE((SELECT MAX(id) FROM portfolios), 1));
|
||||
SELECT setval(pg_get_serial_sequence('category_assignments', 'id'), COALESCE((SELECT MAX(id) FROM category_assignments), 1));
|
||||
SELECT setval(pg_get_serial_sequence('media_attachments', 'id'), COALESCE((SELECT MAX(id) FROM media_attachments), 1));
|
||||
@@ -0,0 +1,35 @@
|
||||
-- Super admin account for production / staging
|
||||
-- Cell: +989127004945 (09127004945)
|
||||
-- Password: Ali2reza
|
||||
|
||||
INSERT INTO users (cell_number, password_hash, email, first_name, last_name, cell_verified_at, is_active)
|
||||
VALUES (
|
||||
'+989127004945',
|
||||
'$2b$10$avrNkn5W5gWkZNrupUAXwePyj4FiwQM4H5hvHp.btPA1L0I0NqgAi',
|
||||
'ali@meshkee.app',
|
||||
'Ali',
|
||||
'Reza',
|
||||
NOW(),
|
||||
TRUE
|
||||
)
|
||||
ON CONFLICT (cell_number) DO UPDATE SET
|
||||
password_hash = EXCLUDED.password_hash,
|
||||
first_name = EXCLUDED.first_name,
|
||||
last_name = EXCLUDED.last_name,
|
||||
is_active = TRUE,
|
||||
cell_verified_at = COALESCE(users.cell_verified_at, NOW());
|
||||
|
||||
-- Ensure only super_admin as global role (removes business_owner/customer if present)
|
||||
DELETE FROM user_roles ur
|
||||
USING users u, roles r
|
||||
WHERE ur.user_id = u.id
|
||||
AND ur.role_id = r.id
|
||||
AND u.cell_number = '+989127004945'
|
||||
AND r.slug IN ('super_admin', 'business_owner', 'business_staff', 'customer');
|
||||
|
||||
INSERT INTO user_roles (user_id, role_id)
|
||||
SELECT u.id, r.id
|
||||
FROM users u
|
||||
JOIN roles r ON r.slug = 'super_admin'
|
||||
WHERE u.cell_number = '+989127004945'
|
||||
ON CONFLICT (user_id, role_id) DO NOTHING;
|
||||
@@ -0,0 +1,181 @@
|
||||
-- Sample comments and expert reviews for product 4
|
||||
-- Resolves business_id and approver from the product / business owner automatically.
|
||||
-- Requires migrations 012_comments.sql and 013_expert_reviews.sql
|
||||
|
||||
WITH product_ctx AS (
|
||||
SELECT
|
||||
p.id AS product_id,
|
||||
p.business_id,
|
||||
owner.user_id AS owner_user_id
|
||||
FROM products p
|
||||
JOIN business_users owner
|
||||
ON owner.business_id = p.business_id
|
||||
AND owner.is_owner = TRUE
|
||||
WHERE p.id = 4
|
||||
),
|
||||
comment_rows AS (
|
||||
SELECT *
|
||||
FROM (VALUES
|
||||
(
|
||||
1::bigint,
|
||||
'Mina Salehi'::varchar,
|
||||
'mina@customer.demo'::varchar,
|
||||
'Camera quality is outstanding, especially in low light. Very happy with the upgrade.'::text,
|
||||
TRUE,
|
||||
NOW() - INTERVAL '2 days',
|
||||
NOW() - INTERVAL '3 days'
|
||||
),
|
||||
(
|
||||
2,
|
||||
'Arash Mohammadi',
|
||||
'arash@example.com',
|
||||
'Smooth performance and the display looks fantastic. Battery could last a bit longer though.',
|
||||
TRUE,
|
||||
NOW() - INTERVAL '1 day',
|
||||
NOW() - INTERVAL '2 days'
|
||||
),
|
||||
(
|
||||
3,
|
||||
'Leila Karimi',
|
||||
'leila@example.com',
|
||||
'Premium build and fast delivery from Sanihome. Setup was seamless.',
|
||||
TRUE,
|
||||
NOW() - INTERVAL '5 hours',
|
||||
NOW() - INTERVAL '1 day'
|
||||
),
|
||||
(
|
||||
4,
|
||||
'Hossein Rahimi',
|
||||
'hossein@example.com',
|
||||
'Just placed my order — excited to try the new Pro model.',
|
||||
FALSE,
|
||||
NULL::timestamptz,
|
||||
NOW() - INTERVAL '3 hours'
|
||||
),
|
||||
(
|
||||
5,
|
||||
'Nazanin Azizi',
|
||||
NULL,
|
||||
'Does this model support dual SIM for Iran?',
|
||||
FALSE,
|
||||
NULL::timestamptz,
|
||||
NOW() - INTERVAL '1 hour'
|
||||
)
|
||||
) AS rows(
|
||||
id,
|
||||
author_name,
|
||||
author_email,
|
||||
text,
|
||||
is_approved,
|
||||
approved_at,
|
||||
created_at
|
||||
)
|
||||
)
|
||||
INSERT INTO comments (
|
||||
id, business_id, entity_type, entity_id, author_name, author_email, text,
|
||||
is_approved, approved_at, approved_by, created_at
|
||||
)
|
||||
SELECT
|
||||
r.id,
|
||||
ctx.business_id,
|
||||
'product'::media_entity_type,
|
||||
ctx.product_id,
|
||||
r.author_name,
|
||||
r.author_email,
|
||||
r.text,
|
||||
r.is_approved,
|
||||
CASE WHEN r.is_approved THEN r.approved_at ELSE NULL END,
|
||||
CASE WHEN r.is_approved THEN ctx.owner_user_id ELSE NULL END,
|
||||
r.created_at
|
||||
FROM comment_rows r
|
||||
CROSS JOIN product_ctx ctx
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
WITH product_ctx AS (
|
||||
SELECT
|
||||
p.id AS product_id,
|
||||
p.business_id,
|
||||
owner.user_id AS owner_user_id
|
||||
FROM products p
|
||||
JOIN business_users owner
|
||||
ON owner.business_id = p.business_id
|
||||
AND owner.is_owner = TRUE
|
||||
WHERE p.id = 4
|
||||
),
|
||||
review_rows AS (
|
||||
SELECT *
|
||||
FROM (VALUES
|
||||
(
|
||||
1::bigint,
|
||||
'MobileTech Review'::varchar,
|
||||
'reviews@mobiletech.demo'::varchar,
|
||||
9::smallint,
|
||||
ARRAY['Excellent camera system', 'Top-tier performance', 'Premium display', 'Strong build quality']::text[],
|
||||
ARRAY['High price point', 'No charger in box']::text[],
|
||||
'The iPhone 17 Pro remains a benchmark flagship. Photo and video capabilities are class-leading, and day-to-day performance is flawless for power users.'::text,
|
||||
TRUE,
|
||||
NOW() - INTERVAL '4 days',
|
||||
NOW() - INTERVAL '5 days'
|
||||
),
|
||||
(
|
||||
2,
|
||||
'Gadget Iran',
|
||||
'editor@gadgetiran.demo',
|
||||
8,
|
||||
ARRAY['Bright ProMotion display', 'Reliable iOS updates', 'Great video stabilization'],
|
||||
ARRAY['Heavy for one-handed use', 'Storage upgrades are expensive'],
|
||||
'A compelling Pro model for creators and professionals. The camera and display are the main reasons to choose it over the standard line.',
|
||||
TRUE,
|
||||
NOW() - INTERVAL '2 days',
|
||||
NOW() - INTERVAL '3 days'
|
||||
),
|
||||
(
|
||||
3,
|
||||
'PhoneLab',
|
||||
'lab@phonelab.demo',
|
||||
7,
|
||||
ARRAY['Fast A-series chip', 'Solid battery for its class', 'Excellent ecosystem integration'],
|
||||
ARRAY['Incremental design changes', 'Pro price without major leaps for casual users'],
|
||||
'A polished flagship that makes sense for Apple loyalists and mobile photographers, though casual upgraders may find better value elsewhere.',
|
||||
FALSE,
|
||||
NULL::timestamptz,
|
||||
NOW() - INTERVAL '6 hours'
|
||||
)
|
||||
) AS rows(
|
||||
id,
|
||||
author_name,
|
||||
author_email,
|
||||
rate,
|
||||
positive_points,
|
||||
negative_points,
|
||||
text,
|
||||
is_approved,
|
||||
approved_at,
|
||||
created_at
|
||||
)
|
||||
)
|
||||
INSERT INTO expert_reviews (
|
||||
id, business_id, product_id, author_name, author_email, rate,
|
||||
positive_points, negative_points, text,
|
||||
is_approved, approved_at, approved_by, created_at
|
||||
)
|
||||
SELECT
|
||||
r.id,
|
||||
ctx.business_id,
|
||||
ctx.product_id,
|
||||
r.author_name,
|
||||
r.author_email,
|
||||
r.rate,
|
||||
r.positive_points,
|
||||
r.negative_points,
|
||||
r.text,
|
||||
r.is_approved,
|
||||
CASE WHEN r.is_approved THEN r.approved_at ELSE NULL END,
|
||||
CASE WHEN r.is_approved THEN ctx.owner_user_id ELSE NULL END,
|
||||
r.created_at
|
||||
FROM review_rows r
|
||||
CROSS JOIN product_ctx ctx
|
||||
ON CONFLICT (id) DO NOTHING;
|
||||
|
||||
SELECT setval(pg_get_serial_sequence('comments', 'id'), COALESCE((SELECT MAX(id) FROM comments), 1));
|
||||
SELECT setval(pg_get_serial_sequence('expert_reviews', 'id'), COALESCE((SELECT MAX(id) FROM expert_reviews), 1));
|
||||
@@ -0,0 +1,113 @@
|
||||
-- Iran location reference data (country → provinces → provincial capitals)
|
||||
-- Requires migration 015_cities.sql
|
||||
|
||||
INSERT INTO cities (parent_id, level, name_fa, name_en, landline_code, slug, sort_order) VALUES
|
||||
(NULL, 'country', 'ایران', 'Iran', '98', 'iran', 1);
|
||||
|
||||
INSERT INTO cities (parent_id, level, name_fa, name_en, landline_code, slug, sort_order)
|
||||
SELECT c.id, 'province', v.name_fa, v.name_en, v.landline_code, v.slug, v.sort_order
|
||||
FROM cities c
|
||||
CROSS JOIN (
|
||||
VALUES
|
||||
('آذربایجان شرقی', 'East Azerbaijan', '041', 'east-azerbaijan', 1),
|
||||
('آذربایجان غربی', 'West Azerbaijan', '044', 'west-azerbaijan', 2),
|
||||
('اردبیل', 'Ardabil', '045', 'ardabil', 3),
|
||||
('اصفهان', 'Isfahan', '031', 'isfahan', 4),
|
||||
('البرز', 'Alborz', '026', 'alborz', 5),
|
||||
('ایلام', 'Ilam', '084', 'ilam', 6),
|
||||
('بوشهر', 'Bushehr', '077', 'bushehr', 7),
|
||||
('تهران', 'Tehran', '021', 'tehran-province', 8),
|
||||
('چهارمحال و بختیاری', 'Chaharmahal and Bakhtiari', '038', 'chaharmahal-bakhtiari', 9),
|
||||
('خراسان جنوبی', 'South Khorasan', '056', 'south-khorasan', 10),
|
||||
('خراسان رضوی', 'Razavi Khorasan', '051', 'razavi-khorasan', 11),
|
||||
('خراسان شمالی', 'North Khorasan', '058', 'north-khorasan', 12),
|
||||
('خوزستان', 'Khuzestan', '061', 'khuzestan', 13),
|
||||
('زنجان', 'Zanjan', '024', 'zanjan', 14),
|
||||
('سمنان', 'Semnan', '023', 'semnan', 15),
|
||||
('سیستان و بلوچستان', 'Sistan and Baluchestan', '054', 'sistan-baluchestan', 16),
|
||||
('فارس', 'Fars', '071', 'fars', 17),
|
||||
('قزوین', 'Qazvin', '028', 'qazvin', 18),
|
||||
('قم', 'Qom', '025', 'qom', 19),
|
||||
('کردستان', 'Kurdistan', '087', 'kurdistan', 20),
|
||||
('کرمان', 'Kerman', '034', 'kerman', 21),
|
||||
('کرمانشاه', 'Kermanshah', '083', 'kermanshah', 22),
|
||||
('کهگیلویه و بویراحمد', 'Kohgiluyeh and Boyer-Ahmad', '074', 'kohgiluyeh-boyer-ahmad', 23),
|
||||
('گلستان', 'Golestan', '017', 'golestan', 24),
|
||||
('گیلان', 'Gilan', '013', 'gilan', 25),
|
||||
('لرستان', 'Lorestan', '066', 'lorestan', 26),
|
||||
('مازندران', 'Mazandaran', '011', 'mazandaran', 27),
|
||||
('مرکزی', 'Markazi', '086', 'markazi', 28),
|
||||
('هرمزگان', 'Hormozgan', '076', 'hormozgan', 29),
|
||||
('همدان', 'Hamadan', '081', 'hamadan', 30),
|
||||
('یزد', 'Yazd', '035', 'yazd', 31)
|
||||
) AS v(name_fa, name_en, landline_code, slug, sort_order)
|
||||
WHERE c.slug = 'iran';
|
||||
|
||||
INSERT INTO cities (parent_id, level, name_fa, name_en, landline_code, slug, sort_order)
|
||||
SELECT p.id, 'city', v.name_fa, v.name_en, v.landline_code, v.slug, v.sort_order
|
||||
FROM cities p
|
||||
JOIN (
|
||||
VALUES
|
||||
('east-azerbaijan', 'تبریز', 'Tabriz', '041', 'tabriz', 1),
|
||||
('west-azerbaijan', 'ارومیه', 'Urmia', '044', 'urmia', 1),
|
||||
('ardabil', 'اردبیل', 'Ardabil', '045', 'ardabil-city', 1),
|
||||
('isfahan', 'اصفهان', 'Isfahan', '031', 'isfahan-city', 1),
|
||||
('alborz', 'کرج', 'Karaj', '026', 'karaj', 1),
|
||||
('ilam', 'ایلام', 'Ilam', '084', 'ilam-city', 1),
|
||||
('bushehr', 'بوشهر', 'Bushehr', '077', 'bushehr-city', 1),
|
||||
('tehran-province', 'تهران', 'Tehran', '021', 'tehran', 1),
|
||||
('chaharmahal-bakhtiari', 'شهرکرد', 'Shahrekord', '038', 'shahrekord', 1),
|
||||
('south-khorasan', 'بیرجند', 'Birjand', '056', 'birjand', 1),
|
||||
('razavi-khorasan', 'مشهد', 'Mashhad', '051', 'mashhad', 1),
|
||||
('north-khorasan', 'بجنورد', 'Bojnord', '058', 'bojnord', 1),
|
||||
('khuzestan', 'اهواز', 'Ahvaz', '061', 'ahvaz', 1),
|
||||
('zanjan', 'زنجان', 'Zanjan', '024', 'zanjan-city', 1),
|
||||
('semnan', 'سمنان', 'Semnan', '023', 'semnan-city', 1),
|
||||
('sistan-baluchestan', 'زاهدان', 'Zahedan', '054', 'zahedan', 1),
|
||||
('fars', 'شیراز', 'Shiraz', '071', 'shiraz', 1),
|
||||
('qazvin', 'قزوین', 'Qazvin', '028', 'qazvin-city', 1),
|
||||
('qom', 'قم', 'Qom', '025', 'qom-city', 1),
|
||||
('kurdistan', 'سنندج', 'Sanandaj', '087', 'sanandaj', 1),
|
||||
('kerman', 'کرمان', 'Kerman', '034', 'kerman-city', 1),
|
||||
('kermanshah', 'کرمانشاه', 'Kermanshah', '083', 'kermanshah-city', 1),
|
||||
('kohgiluyeh-boyer-ahmad', 'یاسوج', 'Yasuj', '074', 'yasuj', 1),
|
||||
('golestan', 'گرگان', 'Gorgan', '017', 'gorgan', 1),
|
||||
('gilan', 'رشت', 'Rasht', '013', 'rasht', 1),
|
||||
('lorestan', 'خرمآباد', 'Khorramabad', '066', 'khorramabad', 1),
|
||||
('mazandaran', 'ساری', 'Sari', '011', 'sari', 1),
|
||||
('markazi', 'اراک', 'Arak', '086', 'arak', 1),
|
||||
('hormozgan', 'بندرعباس', 'Bandar Abbas', '076', 'bandar-abbas', 1),
|
||||
('hamadan', 'همدان', 'Hamadan', '081', 'hamadan-city', 1),
|
||||
('yazd', 'یزد', 'Yazd', '035', 'yazd-city', 1)
|
||||
) AS v(province_slug, name_fa, name_en, landline_code, slug, sort_order)
|
||||
ON p.slug = v.province_slug
|
||||
WHERE p.level = 'province';
|
||||
|
||||
-- Additional major cities
|
||||
INSERT INTO cities (parent_id, level, name_fa, name_en, landline_code, slug, sort_order)
|
||||
SELECT p.id, 'city', v.name_fa, v.name_en, v.landline_code, v.slug, v.sort_order
|
||||
FROM cities p
|
||||
JOIN (
|
||||
VALUES
|
||||
('tehran-province', 'ری', 'Rey', '021', 'rey', 2),
|
||||
('tehran-province', 'شهریار', 'Shahriar', '021', 'shahriar', 3),
|
||||
('tehran-province', 'ورامین', 'Varamin', '021', 'varamin', 4),
|
||||
('isfahan', 'کاشان', 'Kashan', '031', 'kashan', 2),
|
||||
('isfahan', 'نجفآباد', 'Najafabad', '031', 'najafabad', 3),
|
||||
('fars', 'مرودشت', 'Marvdasht', '071', 'marvdasht', 2),
|
||||
('fars', 'جهرم', 'Jahrom', '071', 'jahrom', 3),
|
||||
('khuzestan', 'آبادان', 'Abadan', '061', 'abadan', 2),
|
||||
('khuzestan', 'دزفول', 'Dezful', '061', 'dezful', 3),
|
||||
('razavi-khorasan', 'نیشابور', 'Neyshabur', '051', 'neyshabur', 2),
|
||||
('razavi-khorasan', 'سبزوار', 'Sabzevar', '051', 'sabzevar', 3),
|
||||
('mazandaran', 'آمل', 'Amol', '011', 'amol', 2),
|
||||
('mazandaran', 'بابل', 'Babol', '011', 'babol', 3),
|
||||
('gilan', 'انزلی', 'Bandar Anzali', '013', 'bandar-anzali', 2),
|
||||
('east-azerbaijan', 'مراغه', 'Maragheh', '041', 'maragheh', 2),
|
||||
('kerman', 'رفسنجان', 'Rafsanjan', '034', 'rafsanjan', 2),
|
||||
('alborz', 'فردیس', 'Fardis', '026', 'fardis', 2)
|
||||
) AS v(province_slug, name_fa, name_en, landline_code, slug, sort_order)
|
||||
ON p.slug = v.province_slug
|
||||
WHERE p.level = 'province';
|
||||
|
||||
SELECT setval(pg_get_serial_sequence('cities', 'id'), COALESCE((SELECT MAX(id) FROM cities), 1));
|
||||
@@ -0,0 +1,178 @@
|
||||
-- System business categories: retail, industry, and services (up to 3 levels)
|
||||
-- Run after 001_sample_data.sql (replaces the minimal categories seeded there)
|
||||
|
||||
DELETE FROM business_category_assignments;
|
||||
DELETE FROM business_categories;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Level 1 — top-level industries
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO business_categories (parent_id, name, slug, description, sort_order) VALUES
|
||||
(NULL, 'Retail & Shopping', 'retail-shopping', 'Physical and online retail businesses', 1),
|
||||
(NULL, 'Manufacturing & Industry', 'manufacturing-industry', 'Production, factories, and industrial businesses', 2),
|
||||
(NULL, 'Food & Beverage', 'food-beverage', 'Restaurants, food production, and beverage brands', 3),
|
||||
(NULL, 'Professional Services', 'professional-services', 'Consulting, creative, and business services', 4),
|
||||
(NULL, 'Technology & Digital', 'technology-digital', 'Software, IT, and digital businesses', 5),
|
||||
(NULL, 'Health & Wellness', 'health-wellness', 'Healthcare, beauty, and fitness businesses', 6),
|
||||
(NULL, 'Home & Living', 'home-living', 'Furniture, décor, and home improvement', 7),
|
||||
(NULL, 'Automotive', 'automotive', 'Vehicle sales, parts, and services', 8);
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Level 2 — sectors
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO business_categories (parent_id, name, slug, description, sort_order)
|
||||
SELECT p.id, v.name, v.slug, v.description, v.sort_order
|
||||
FROM business_categories p
|
||||
JOIN (
|
||||
VALUES
|
||||
-- Retail & Shopping
|
||||
('retail-shopping', 'Fashion & Apparel', 'fashion-apparel', 'Clothing, footwear, and fashion accessories', 1),
|
||||
('retail-shopping', 'Electronics & Tech Retail', 'electronics-retail', 'Consumer electronics and technology retail', 2),
|
||||
('retail-shopping', 'Grocery & Supermarket', 'grocery-supermarket', 'Supermarkets, grocery, and convenience stores', 3),
|
||||
('retail-shopping', 'Home & Furniture Retail', 'home-furniture-retail', 'Furniture, décor, and home goods stores', 4),
|
||||
('retail-shopping', 'Sports & Outdoors', 'sports-outdoors-retail', 'Sporting goods and outdoor equipment', 5),
|
||||
('retail-shopping', 'Jewelry & Accessories', 'jewelry-accessories', 'Jewelry, watches, and fashion accessories', 6),
|
||||
('retail-shopping', 'Books & Stationery', 'books-stationery', 'Bookstores, stationery, and office supplies', 7),
|
||||
('retail-shopping', 'E-commerce & Online', 'e-commerce-online', 'Online-only and omnichannel retail', 8),
|
||||
|
||||
-- Manufacturing & Industry
|
||||
('manufacturing-industry', 'Textile & Apparel', 'textile-apparel-mfg', 'Garment, fabric, and textile production', 1),
|
||||
('manufacturing-industry', 'Food Processing', 'food-processing-mfg', 'Packaged food and beverage manufacturing', 2),
|
||||
('manufacturing-industry', 'Metal & Machinery', 'metal-machinery-mfg', 'Metalwork, machinery, and industrial equipment', 3),
|
||||
('manufacturing-industry', 'Chemicals & Materials', 'chemicals-materials', 'Chemicals, plastics, and raw materials', 4),
|
||||
('manufacturing-industry', 'Electronics Manufacturing', 'electronics-manufacturing', 'Electronic components and device manufacturing', 5),
|
||||
('manufacturing-industry', 'Packaging & Printing', 'packaging-printing', 'Packaging, labels, and commercial printing', 6),
|
||||
|
||||
-- Food & Beverage
|
||||
('food-beverage', 'Restaurants & Cafés', 'restaurants-cafes', 'Dining, cafés, and hospitality', 1),
|
||||
('food-beverage', 'Bakery & Confectionery', 'bakery-confectionery', 'Bakeries, pastries, and sweets', 2),
|
||||
('food-beverage', 'Beverage Production', 'beverage-production', 'Juice, soft drinks, tea, and coffee production', 3),
|
||||
('food-beverage', 'Food Wholesale & Distribution', 'food-wholesale', 'Food distribution and wholesale supply', 4),
|
||||
|
||||
-- Professional Services
|
||||
('professional-services', 'Design & Creative', 'design-creative', 'Design, branding, and creative agencies', 1),
|
||||
('professional-services', 'Consulting & Advisory', 'consulting-advisory', 'Business, legal, and management consulting', 2),
|
||||
('professional-services', 'Education & Training', 'education-training', 'Schools, courses, and training providers', 3),
|
||||
('professional-services', 'Marketing & Advertising', 'marketing-advertising', 'Marketing agencies and advertising services', 4),
|
||||
|
||||
-- Technology & Digital
|
||||
('technology-digital', 'Software & IT Services', 'software-it-services', 'Software development and IT consulting', 1),
|
||||
('technology-digital', 'Digital Media & Content', 'digital-media', 'Media, content, and publishing platforms', 2),
|
||||
('technology-digital', 'Hardware & Devices', 'hardware-devices', 'Hardware products and device companies', 3),
|
||||
|
||||
-- Health & Wellness
|
||||
('health-wellness', 'Beauty & Personal Care', 'beauty-personal-care', 'Salons, cosmetics, and personal care retail', 1),
|
||||
('health-wellness', 'Pharmacy & Medical Supply', 'pharmacy-medical-supply', 'Pharmacies and medical supply stores', 2),
|
||||
('health-wellness', 'Fitness & Sports Clubs', 'fitness-sports-clubs', 'Gyms, fitness studios, and sports clubs', 3),
|
||||
|
||||
-- Home & Living
|
||||
('home-living', 'Furniture & Décor', 'furniture-decor', 'Furniture stores and interior décor', 1),
|
||||
('home-living', 'Building Materials', 'building-materials', 'Construction and building supply', 2),
|
||||
('home-living', 'Garden & Outdoor Living', 'garden-outdoor-living', 'Garden centers and outdoor living products', 3),
|
||||
|
||||
-- Automotive
|
||||
('automotive', 'Vehicle Dealers', 'auto-dealers', 'Car, motorcycle, and vehicle dealerships', 1),
|
||||
('automotive', 'Parts & Service', 'auto-parts-service', 'Auto parts, repair, and maintenance services', 2)
|
||||
) AS v(parent_slug, name, slug, description, sort_order)
|
||||
ON p.slug = v.parent_slug
|
||||
WHERE p.parent_id IS NULL;
|
||||
|
||||
-- ---------------------------------------------------------------------------
|
||||
-- Level 3 — specific business / store types
|
||||
-- ---------------------------------------------------------------------------
|
||||
INSERT INTO business_categories (parent_id, name, slug, description, sort_order)
|
||||
SELECT p.id, v.name, v.slug, v.description, v.sort_order
|
||||
FROM business_categories p
|
||||
JOIN (
|
||||
VALUES
|
||||
-- Fashion & Apparel
|
||||
('fashion-apparel', 'Women''s Clothing Store', 'womens-clothing-store', 'Retail stores focused on women''s apparel', 1),
|
||||
('fashion-apparel', 'Men''s Clothing Store', 'mens-clothing-store', 'Retail stores focused on men''s apparel', 2),
|
||||
('fashion-apparel', 'Children''s Clothing Store', 'children-clothing-store', 'Apparel for infants, kids, and teens', 3),
|
||||
('fashion-apparel', 'Footwear Store', 'footwear-store', 'Shoes, boots, and footwear retail', 4),
|
||||
('fashion-apparel', 'Luxury Fashion Boutique', 'luxury-fashion-boutique', 'High-end and designer fashion retail', 5),
|
||||
|
||||
-- Electronics & Tech Retail
|
||||
('electronics-retail', 'Mobile & Accessories Store', 'mobile-accessories-store', 'Phones, tablets, and mobile accessories', 1),
|
||||
('electronics-retail', 'Computer & Laptop Store', 'computer-laptop-store', 'Computers, laptops, and peripherals', 2),
|
||||
('electronics-retail', 'Home Appliances Store', 'home-appliances-store', 'Large and small home appliances', 3),
|
||||
('electronics-retail', 'Consumer Electronics Store', 'consumer-electronics-store', 'General electronics and gadgets retail', 4),
|
||||
|
||||
-- Grocery & Supermarket
|
||||
('grocery-supermarket', 'Supermarket & Hypermarket', 'supermarket-hypermarket', 'Large-format grocery and hypermarket chains', 1),
|
||||
('grocery-supermarket', 'Convenience Store', 'convenience-store', 'Neighborhood and convenience grocery', 2),
|
||||
('grocery-supermarket', 'Organic & Health Food Store', 'organic-health-food-store', 'Organic, natural, and health food retail', 3),
|
||||
|
||||
-- E-commerce & Online
|
||||
('e-commerce-online', 'General E-commerce Store', 'general-e-commerce-store', 'Multi-category online retail stores', 1),
|
||||
('e-commerce-online', 'Online Fashion Store', 'online-fashion-store', 'Fashion-focused online retailers', 2),
|
||||
('e-commerce-online', 'Online Electronics Store', 'online-electronics-store', 'Electronics-focused online retailers', 3),
|
||||
('e-commerce-online', 'Marketplace Seller', 'marketplace-seller', 'Businesses selling primarily on marketplaces', 4),
|
||||
|
||||
-- Textile & Apparel Manufacturing
|
||||
('textile-apparel-mfg', 'Garment Factory', 'garment-factory', 'Clothing and garment mass production', 1),
|
||||
('textile-apparel-mfg', 'Fabric & Textile Mill', 'fabric-textile-mill', 'Fabric weaving, knitting, and textile mills', 2),
|
||||
('textile-apparel-mfg', 'Leather Goods Manufacturing', 'leather-goods-manufacturing', 'Bags, belts, and leather products', 3),
|
||||
|
||||
-- Food Processing
|
||||
('food-processing-mfg', 'Dairy Processing', 'dairy-processing', 'Milk, cheese, and dairy product manufacturing', 1),
|
||||
('food-processing-mfg', 'Meat Processing', 'meat-processing', 'Meat packing and processed meat products', 2),
|
||||
('food-processing-mfg', 'Snack Foods Manufacturing', 'snack-foods-manufacturing', 'Chips, nuts, and packaged snack production', 3),
|
||||
|
||||
-- Metal & Machinery
|
||||
('metal-machinery-mfg', 'Industrial Machinery', 'industrial-machinery', 'Heavy machinery and industrial equipment', 1),
|
||||
('metal-machinery-mfg', 'Metal Fabrication', 'metal-fabrication', 'Sheet metal, welding, and metal parts', 2),
|
||||
('metal-machinery-mfg', 'Tools & Hardware Manufacturing', 'tools-hardware-manufacturing', 'Hand tools and hardware production', 3),
|
||||
|
||||
-- Restaurants & Cafés
|
||||
('restaurants-cafes', 'Fast Food', 'fast-food', 'Quick-service and fast food restaurants', 1),
|
||||
('restaurants-cafes', 'Café & Coffee Shop', 'cafe-coffee-shop', 'Cafés, coffee shops, and tea houses', 2),
|
||||
('restaurants-cafes', 'Fine Dining Restaurant', 'fine-dining-restaurant', 'Full-service and upscale dining', 3),
|
||||
('restaurants-cafes', 'Bakery & Pastry Shop', 'bakery-pastry-shop', 'Retail bakeries and pastry shops', 4),
|
||||
|
||||
-- Design & Creative
|
||||
('design-creative', 'Graphic Design Studio', 'graphic-design-studio', 'Visual design and print-focused studios', 1),
|
||||
('design-creative', 'Branding Agency', 'branding-agency', 'Brand strategy, identity, and positioning', 2),
|
||||
('design-creative', 'Web Design Agency', 'web-design-agency', 'Website and digital experience design', 3),
|
||||
('design-creative', 'Photography Studio', 'photography-studio', 'Commercial and studio photography', 4),
|
||||
|
||||
-- Software & IT Services
|
||||
('software-it-services', 'Software Development', 'software-development', 'Custom software and application development', 1),
|
||||
('software-it-services', 'SaaS Company', 'saas-company', 'Software-as-a-service product companies', 2),
|
||||
('software-it-services', 'IT Consulting', 'it-consulting', 'IT strategy, integration, and support services', 3),
|
||||
|
||||
-- Beauty & Personal Care
|
||||
('beauty-personal-care', 'Cosmetics Store', 'cosmetics-store', 'Makeup and skincare retail', 1),
|
||||
('beauty-personal-care', 'Hair & Beauty Salon', 'hair-beauty-salon', 'Salons and beauty service providers', 2),
|
||||
('beauty-personal-care', 'Perfume & Fragrance Store', 'perfume-fragrance-store', 'Perfume and fragrance specialty retail', 3),
|
||||
|
||||
-- Furniture & Décor
|
||||
('furniture-decor', 'Furniture Store', 'furniture-store', 'Home and office furniture retail', 1),
|
||||
('furniture-decor', 'Home Décor Store', 'home-decor-store', 'Decorative items and home accessories', 2),
|
||||
('furniture-decor', 'Lighting Store', 'lighting-store', 'Lamps, fixtures, and lighting retail', 3),
|
||||
|
||||
-- Automotive
|
||||
('auto-dealers', 'Car Dealership', 'car-dealership', 'New and used passenger car dealers', 1),
|
||||
('auto-dealers', 'Motorcycle Dealer', 'motorcycle-dealer', 'Motorcycle and scooter dealerships', 2),
|
||||
('auto-parts-service', 'Auto Parts Store', 'auto-parts-store', 'Spare parts and accessories retail', 1),
|
||||
('auto-parts-service', 'Auto Repair & Service', 'auto-repair-service', 'Vehicle maintenance and repair workshops', 2)
|
||||
) AS v(parent_slug, name, slug, description, sort_order)
|
||||
ON p.slug = v.parent_slug;
|
||||
|
||||
-- Demo business category assignments (by slug)
|
||||
INSERT INTO business_category_assignments (business_id, category_id)
|
||||
SELECT 1, c.id
|
||||
FROM business_categories c
|
||||
WHERE c.slug IN ('general-e-commerce-store', 'electronics-retail', 'retail-shopping')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
INSERT INTO business_category_assignments (business_id, category_id)
|
||||
SELECT 2, c.id
|
||||
FROM business_categories c
|
||||
WHERE c.slug IN ('branding-agency', 'graphic-design-studio', 'design-creative')
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
SELECT setval(
|
||||
pg_get_serial_sequence('business_categories', 'id'),
|
||||
COALESCE((SELECT MAX(id) FROM business_categories), 1)
|
||||
);
|
||||
Reference in New Issue
Block a user