square_sandbox_simulator 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE.txt +21 -0
- data/README.md +176 -0
- data/bin/simulate +388 -0
- data/lib/square_sandbox_simulator/configuration.rb +193 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/categories.json +54 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/combos.json +33 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/coupon_codes.json +133 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/discounts.json +113 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/items.json +55 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/modifiers.json +73 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/tax_rates.json +26 -0
- data/lib/square_sandbox_simulator/data/cafe_bakery/tenders.json +41 -0
- data/lib/square_sandbox_simulator/data/restaurant/categories.json +54 -0
- data/lib/square_sandbox_simulator/data/restaurant/combos.json +265 -0
- data/lib/square_sandbox_simulator/data/restaurant/coupon_codes.json +266 -0
- data/lib/square_sandbox_simulator/data/restaurant/discounts.json +198 -0
- data/lib/square_sandbox_simulator/data/restaurant/gift_cards.json +82 -0
- data/lib/square_sandbox_simulator/data/restaurant/items.json +388 -0
- data/lib/square_sandbox_simulator/data/restaurant/modifiers.json +62 -0
- data/lib/square_sandbox_simulator/data/restaurant/tax_rates.json +38 -0
- data/lib/square_sandbox_simulator/data/restaurant/tenders.json +41 -0
- data/lib/square_sandbox_simulator/data/salon_spa/categories.json +24 -0
- data/lib/square_sandbox_simulator/data/salon_spa/combos.json +88 -0
- data/lib/square_sandbox_simulator/data/salon_spa/coupon_codes.json +96 -0
- data/lib/square_sandbox_simulator/data/salon_spa/discounts.json +93 -0
- data/lib/square_sandbox_simulator/data/salon_spa/gift_cards.json +47 -0
- data/lib/square_sandbox_simulator/data/salon_spa/items.json +100 -0
- data/lib/square_sandbox_simulator/data/salon_spa/modifiers.json +49 -0
- data/lib/square_sandbox_simulator/data/salon_spa/tax_rates.json +17 -0
- data/lib/square_sandbox_simulator/data/salon_spa/tenders.json +41 -0
- data/lib/square_sandbox_simulator/database.rb +224 -0
- data/lib/square_sandbox_simulator/db/factories/api_requests.rb +95 -0
- data/lib/square_sandbox_simulator/db/factories/business_types.rb +178 -0
- data/lib/square_sandbox_simulator/db/factories/categories.rb +379 -0
- data/lib/square_sandbox_simulator/db/factories/daily_summaries.rb +56 -0
- data/lib/square_sandbox_simulator/db/factories/items.rb +1526 -0
- data/lib/square_sandbox_simulator/db/factories/simulated_orders.rb +112 -0
- data/lib/square_sandbox_simulator/db/factories/simulated_payments.rb +61 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000000_enable_pgcrypto.rb +7 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000001_create_business_types.rb +18 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000002_create_categories.rb +18 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000003_create_items.rb +23 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000004_create_simulated_orders.rb +36 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000005_create_simulated_payments.rb +26 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000006_create_api_requests.rb +27 -0
- data/lib/square_sandbox_simulator/db/migrate/20260312000007_create_daily_summaries.rb +24 -0
- data/lib/square_sandbox_simulator/generators/data_loader.rb +202 -0
- data/lib/square_sandbox_simulator/generators/entity_generator.rb +248 -0
- data/lib/square_sandbox_simulator/generators/order_generator.rb +632 -0
- data/lib/square_sandbox_simulator/models/api_request.rb +43 -0
- data/lib/square_sandbox_simulator/models/business_type.rb +25 -0
- data/lib/square_sandbox_simulator/models/category.rb +18 -0
- data/lib/square_sandbox_simulator/models/daily_summary.rb +68 -0
- data/lib/square_sandbox_simulator/models/item.rb +33 -0
- data/lib/square_sandbox_simulator/models/record.rb +16 -0
- data/lib/square_sandbox_simulator/models/simulated_order.rb +42 -0
- data/lib/square_sandbox_simulator/models/simulated_payment.rb +28 -0
- data/lib/square_sandbox_simulator/seeder.rb +242 -0
- data/lib/square_sandbox_simulator/services/base_service.rb +253 -0
- data/lib/square_sandbox_simulator/services/square/catalog_service.rb +203 -0
- data/lib/square_sandbox_simulator/services/square/customer_service.rb +130 -0
- data/lib/square_sandbox_simulator/services/square/order_service.rb +121 -0
- data/lib/square_sandbox_simulator/services/square/payment_service.rb +136 -0
- data/lib/square_sandbox_simulator/services/square/services_manager.rb +68 -0
- data/lib/square_sandbox_simulator/services/square/team_service.rb +108 -0
- data/lib/square_sandbox_simulator/version.rb +5 -0
- data/lib/square_sandbox_simulator.rb +47 -0
- metadata +348 -0
|
@@ -0,0 +1,1526 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# ~168 item traits across 9 business types and 38 categories.
|
|
4
|
+
# Each trait sets name, price (cents), sku, and associates with the correct
|
|
5
|
+
# category (which in turn associates with the correct business type).
|
|
6
|
+
#
|
|
7
|
+
# Usage:
|
|
8
|
+
# build(:item, :buffalo_wings) # auto-creates category + business_type
|
|
9
|
+
# create(:item, :buffalo_wings, category: my_cat) # override category
|
|
10
|
+
|
|
11
|
+
FactoryBot.define do
|
|
12
|
+
factory :item, class: "SquareSandboxSimulator::Models::Item" do
|
|
13
|
+
association :category
|
|
14
|
+
sequence(:name) { |n| "Item #{n}" }
|
|
15
|
+
price { 999 } # cents
|
|
16
|
+
active { true }
|
|
17
|
+
variants { [] }
|
|
18
|
+
metadata { {} }
|
|
19
|
+
|
|
20
|
+
# ═══════════════════════════════════════════════════════════
|
|
21
|
+
# RESTAURANT (5 categories, 25 items)
|
|
22
|
+
# ═══════════════════════════════════════════════════════════
|
|
23
|
+
|
|
24
|
+
# ── Appetizers ─────────────────────────────────────────────
|
|
25
|
+
|
|
26
|
+
trait :buffalo_wings do
|
|
27
|
+
name { "Buffalo Wings" }
|
|
28
|
+
price { 1299 }
|
|
29
|
+
sku { "REST-APP-001" }
|
|
30
|
+
association :category, factory: %i[category appetizers]
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
trait :mozzarella_sticks do
|
|
34
|
+
name { "Mozzarella Sticks" }
|
|
35
|
+
price { 999 }
|
|
36
|
+
sku { "REST-APP-002" }
|
|
37
|
+
association :category, factory: %i[category appetizers]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
trait :loaded_nachos do
|
|
41
|
+
name { "Loaded Nachos" }
|
|
42
|
+
price { 1199 }
|
|
43
|
+
sku { "REST-APP-003" }
|
|
44
|
+
association :category, factory: %i[category appetizers]
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
trait :spinach_artichoke_dip do
|
|
48
|
+
name { "Spinach Artichoke Dip" }
|
|
49
|
+
price { 1099 }
|
|
50
|
+
sku { "REST-APP-004" }
|
|
51
|
+
association :category, factory: %i[category appetizers]
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
trait :calamari do
|
|
55
|
+
name { "Calamari" }
|
|
56
|
+
price { 1399 }
|
|
57
|
+
sku { "REST-APP-005" }
|
|
58
|
+
association :category, factory: %i[category appetizers]
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# ── Entrees ────────────────────────────────────────────────
|
|
62
|
+
|
|
63
|
+
trait :grilled_salmon do
|
|
64
|
+
name { "Grilled Salmon" }
|
|
65
|
+
price { 2299 }
|
|
66
|
+
sku { "REST-ENT-001" }
|
|
67
|
+
association :category, factory: %i[category entrees]
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
trait :ny_strip_steak do
|
|
71
|
+
name { "NY Strip Steak" }
|
|
72
|
+
price { 2899 }
|
|
73
|
+
sku { "REST-ENT-002" }
|
|
74
|
+
association :category, factory: %i[category entrees]
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
trait :chicken_parmesan do
|
|
78
|
+
name { "Chicken Parmesan" }
|
|
79
|
+
price { 1899 }
|
|
80
|
+
sku { "REST-ENT-003" }
|
|
81
|
+
association :category, factory: %i[category entrees]
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
trait :pasta_primavera do
|
|
85
|
+
name { "Pasta Primavera" }
|
|
86
|
+
price { 1599 }
|
|
87
|
+
sku { "REST-ENT-004" }
|
|
88
|
+
association :category, factory: %i[category entrees]
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
trait :herb_roasted_chicken do
|
|
92
|
+
name { "Herb Roasted Chicken" }
|
|
93
|
+
price { 1999 }
|
|
94
|
+
sku { "REST-ENT-005" }
|
|
95
|
+
association :category, factory: %i[category entrees]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# ── Sides ──────────────────────────────────────────────────
|
|
99
|
+
|
|
100
|
+
trait :french_fries do
|
|
101
|
+
name { "French Fries" }
|
|
102
|
+
price { 599 }
|
|
103
|
+
sku { "REST-SID-001" }
|
|
104
|
+
association :category, factory: %i[category sides]
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
trait :coleslaw do
|
|
108
|
+
name { "Coleslaw" }
|
|
109
|
+
price { 499 }
|
|
110
|
+
sku { "REST-SID-002" }
|
|
111
|
+
association :category, factory: %i[category sides]
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
trait :mashed_potatoes do
|
|
115
|
+
name { "Mashed Potatoes" }
|
|
116
|
+
price { 699 }
|
|
117
|
+
sku { "REST-SID-003" }
|
|
118
|
+
association :category, factory: %i[category sides]
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
trait :side_salad do
|
|
122
|
+
name { "Side Salad" }
|
|
123
|
+
price { 549 }
|
|
124
|
+
sku { "REST-SID-004" }
|
|
125
|
+
association :category, factory: %i[category sides]
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
trait :onion_rings do
|
|
129
|
+
name { "Onion Rings" }
|
|
130
|
+
price { 699 }
|
|
131
|
+
sku { "REST-SID-005" }
|
|
132
|
+
association :category, factory: %i[category sides]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
# ── Desserts ───────────────────────────────────────────────
|
|
136
|
+
|
|
137
|
+
trait :chocolate_lava_cake do
|
|
138
|
+
name { "Chocolate Lava Cake" }
|
|
139
|
+
price { 999 }
|
|
140
|
+
sku { "REST-DES-001" }
|
|
141
|
+
association :category, factory: %i[category desserts]
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
trait :ny_cheesecake do
|
|
145
|
+
name { "New York Cheesecake" }
|
|
146
|
+
price { 899 }
|
|
147
|
+
sku { "REST-DES-002" }
|
|
148
|
+
association :category, factory: %i[category desserts]
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
trait :restaurant_tiramisu do
|
|
152
|
+
name { "Tiramisu" }
|
|
153
|
+
price { 1099 }
|
|
154
|
+
sku { "REST-DES-003" }
|
|
155
|
+
association :category, factory: %i[category desserts]
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
trait :apple_pie do
|
|
159
|
+
name { "Apple Pie a la Mode" }
|
|
160
|
+
price { 799 }
|
|
161
|
+
sku { "REST-DES-004" }
|
|
162
|
+
association :category, factory: %i[category desserts]
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
trait :ice_cream_sundae do
|
|
166
|
+
name { "Ice Cream Sundae" }
|
|
167
|
+
price { 699 }
|
|
168
|
+
sku { "REST-DES-005" }
|
|
169
|
+
association :category, factory: %i[category desserts]
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# ── Beverages ──────────────────────────────────────────────
|
|
173
|
+
|
|
174
|
+
trait :soft_drink do
|
|
175
|
+
name { "Soft Drink" }
|
|
176
|
+
price { 299 }
|
|
177
|
+
sku { "REST-BEV-001" }
|
|
178
|
+
association :category, factory: %i[category beverages]
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
trait :iced_tea do
|
|
182
|
+
name { "Iced Tea" }
|
|
183
|
+
price { 299 }
|
|
184
|
+
sku { "REST-BEV-002" }
|
|
185
|
+
association :category, factory: %i[category beverages]
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
trait :lemonade do
|
|
189
|
+
name { "Lemonade" }
|
|
190
|
+
price { 349 }
|
|
191
|
+
sku { "REST-BEV-003" }
|
|
192
|
+
association :category, factory: %i[category beverages]
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
trait :sparkling_water do
|
|
196
|
+
name { "Sparkling Water" }
|
|
197
|
+
price { 399 }
|
|
198
|
+
sku { "REST-BEV-004" }
|
|
199
|
+
association :category, factory: %i[category beverages]
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
trait :restaurant_coffee do
|
|
203
|
+
name { "Coffee" }
|
|
204
|
+
price { 249 }
|
|
205
|
+
sku { "REST-BEV-005" }
|
|
206
|
+
association :category, factory: %i[category beverages]
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
# ═══════════════════════════════════════════════════════════
|
|
210
|
+
# CAFE & BAKERY (5 categories, 21 items)
|
|
211
|
+
# ═══════════════════════════════════════════════════════════
|
|
212
|
+
|
|
213
|
+
# ── Coffee & Espresso ──────────────────────────────────────
|
|
214
|
+
|
|
215
|
+
trait :house_drip_coffee do
|
|
216
|
+
name { "House Drip Coffee" }
|
|
217
|
+
price { 299 }
|
|
218
|
+
sku { "CAFE-COF-001" }
|
|
219
|
+
association :category, factory: %i[category coffee_espresso]
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
trait :espresso do
|
|
223
|
+
name { "Espresso" }
|
|
224
|
+
price { 349 }
|
|
225
|
+
sku { "CAFE-COF-002" }
|
|
226
|
+
association :category, factory: %i[category coffee_espresso]
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
trait :cappuccino do
|
|
230
|
+
name { "Cappuccino" }
|
|
231
|
+
price { 499 }
|
|
232
|
+
sku { "CAFE-COF-003" }
|
|
233
|
+
association :category, factory: %i[category coffee_espresso]
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
trait :latte do
|
|
237
|
+
name { "Latte" }
|
|
238
|
+
price { 549 }
|
|
239
|
+
sku { "CAFE-COF-004" }
|
|
240
|
+
association :category, factory: %i[category coffee_espresso]
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
trait :cold_brew do
|
|
244
|
+
name { "Cold Brew" }
|
|
245
|
+
price { 499 }
|
|
246
|
+
sku { "CAFE-COF-005" }
|
|
247
|
+
association :category, factory: %i[category coffee_espresso]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
# ── Pastries ───────────────────────────────────────────────
|
|
251
|
+
|
|
252
|
+
trait :croissant do
|
|
253
|
+
name { "Butter Croissant" }
|
|
254
|
+
price { 399 }
|
|
255
|
+
sku { "CAFE-PAS-001" }
|
|
256
|
+
association :category, factory: %i[category pastries]
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
trait :blueberry_muffin do
|
|
260
|
+
name { "Blueberry Muffin" }
|
|
261
|
+
price { 349 }
|
|
262
|
+
sku { "CAFE-PAS-002" }
|
|
263
|
+
association :category, factory: %i[category pastries]
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
trait :cinnamon_roll do
|
|
267
|
+
name { "Cinnamon Roll" }
|
|
268
|
+
price { 449 }
|
|
269
|
+
sku { "CAFE-PAS-003" }
|
|
270
|
+
association :category, factory: %i[category pastries]
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
trait :chocolate_chip_cookie do
|
|
274
|
+
name { "Chocolate Chip Cookie" }
|
|
275
|
+
price { 299 }
|
|
276
|
+
sku { "CAFE-PAS-004" }
|
|
277
|
+
association :category, factory: %i[category pastries]
|
|
278
|
+
end
|
|
279
|
+
|
|
280
|
+
# ── Breakfast ──────────────────────────────────────────────
|
|
281
|
+
|
|
282
|
+
trait :avocado_toast do
|
|
283
|
+
name { "Avocado Toast" }
|
|
284
|
+
price { 999 }
|
|
285
|
+
sku { "CAFE-BRK-001" }
|
|
286
|
+
association :category, factory: %i[category breakfast]
|
|
287
|
+
end
|
|
288
|
+
|
|
289
|
+
trait :breakfast_burrito do
|
|
290
|
+
name { "Breakfast Burrito" }
|
|
291
|
+
price { 899 }
|
|
292
|
+
sku { "CAFE-BRK-002" }
|
|
293
|
+
association :category, factory: %i[category breakfast]
|
|
294
|
+
end
|
|
295
|
+
|
|
296
|
+
trait :acai_bowl do
|
|
297
|
+
name { "Acai Bowl" }
|
|
298
|
+
price { 1199 }
|
|
299
|
+
sku { "CAFE-BRK-003" }
|
|
300
|
+
association :category, factory: %i[category breakfast]
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
trait :yogurt_parfait do
|
|
304
|
+
name { "Yogurt Parfait" }
|
|
305
|
+
price { 699 }
|
|
306
|
+
sku { "CAFE-BRK-004" }
|
|
307
|
+
association :category, factory: %i[category breakfast]
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
# ── Sandwiches ─────────────────────────────────────────────
|
|
311
|
+
|
|
312
|
+
trait :turkey_club do
|
|
313
|
+
name { "Turkey Club" }
|
|
314
|
+
price { 1099 }
|
|
315
|
+
sku { "CAFE-SAN-001" }
|
|
316
|
+
association :category, factory: %i[category sandwiches]
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
trait :caprese_panini do
|
|
320
|
+
name { "Caprese Panini" }
|
|
321
|
+
price { 999 }
|
|
322
|
+
sku { "CAFE-SAN-002" }
|
|
323
|
+
association :category, factory: %i[category sandwiches]
|
|
324
|
+
end
|
|
325
|
+
|
|
326
|
+
trait :chicken_caesar_wrap do
|
|
327
|
+
name { "Chicken Caesar Wrap" }
|
|
328
|
+
price { 1049 }
|
|
329
|
+
sku { "CAFE-SAN-003" }
|
|
330
|
+
association :category, factory: %i[category sandwiches]
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
trait :blt do
|
|
334
|
+
name { "BLT" }
|
|
335
|
+
price { 899 }
|
|
336
|
+
sku { "CAFE-SAN-004" }
|
|
337
|
+
association :category, factory: %i[category sandwiches]
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
# ── Smoothies & Juices ─────────────────────────────────────
|
|
341
|
+
|
|
342
|
+
trait :berry_blast_smoothie do
|
|
343
|
+
name { "Berry Blast Smoothie" }
|
|
344
|
+
price { 699 }
|
|
345
|
+
sku { "CAFE-SMO-001" }
|
|
346
|
+
association :category, factory: %i[category smoothies]
|
|
347
|
+
end
|
|
348
|
+
|
|
349
|
+
trait :green_detox_juice do
|
|
350
|
+
name { "Green Detox Juice" }
|
|
351
|
+
price { 749 }
|
|
352
|
+
sku { "CAFE-SMO-002" }
|
|
353
|
+
association :category, factory: %i[category smoothies]
|
|
354
|
+
end
|
|
355
|
+
|
|
356
|
+
trait :mango_tango_smoothie do
|
|
357
|
+
name { "Mango Tango Smoothie" }
|
|
358
|
+
price { 699 }
|
|
359
|
+
sku { "CAFE-SMO-003" }
|
|
360
|
+
association :category, factory: %i[category smoothies]
|
|
361
|
+
end
|
|
362
|
+
|
|
363
|
+
trait :fresh_oj do
|
|
364
|
+
name { "Fresh-Squeezed OJ" }
|
|
365
|
+
price { 499 }
|
|
366
|
+
sku { "CAFE-SMO-004" }
|
|
367
|
+
association :category, factory: %i[category smoothies]
|
|
368
|
+
end
|
|
369
|
+
|
|
370
|
+
# ═══════════════════════════════════════════════════════════
|
|
371
|
+
# CAFE & BAKERY — DUPLICATES (mirrors real Square messiness)
|
|
372
|
+
# Same item names appearing in multiple categories, same names
|
|
373
|
+
# with different prices, items cross-listed in overlapping categories.
|
|
374
|
+
# ═══════════════════════════════════════════════════════════
|
|
375
|
+
|
|
376
|
+
# ── Duplicate Coffee & Espresso (2nd category, same item names, different prices) ──
|
|
377
|
+
|
|
378
|
+
trait :house_drip_coffee_dup do
|
|
379
|
+
name { "House Drip Coffee" } # Same name as original!
|
|
380
|
+
price { 350 } # Different price ($3.50 vs $2.99)
|
|
381
|
+
sku { "CAFE-COF2-001" }
|
|
382
|
+
association :category, factory: %i[category coffee_espresso_dup]
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
trait :latte_dup do
|
|
386
|
+
name { "Latte" } # Same name as original!
|
|
387
|
+
price { 599 } # Different price ($5.99 vs $5.49)
|
|
388
|
+
sku { "CAFE-COF2-002" }
|
|
389
|
+
association :category, factory: %i[category coffee_espresso_dup]
|
|
390
|
+
end
|
|
391
|
+
|
|
392
|
+
trait :iced_latte do
|
|
393
|
+
name { "Iced Latte" } # New item only in duplicate category
|
|
394
|
+
price { 599 }
|
|
395
|
+
sku { "CAFE-COF2-003" }
|
|
396
|
+
association :category, factory: %i[category coffee_espresso_dup]
|
|
397
|
+
end
|
|
398
|
+
|
|
399
|
+
trait :matcha_latte do
|
|
400
|
+
name { "Matcha Latte" }
|
|
401
|
+
price { 649 }
|
|
402
|
+
sku { "CAFE-COF2-004" }
|
|
403
|
+
association :category, factory: %i[category coffee_espresso_dup]
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
# ── Duplicate Pastries (2nd category, some same item names) ──
|
|
407
|
+
|
|
408
|
+
trait :croissant_dup do
|
|
409
|
+
name { "Butter Croissant" } # Same name as original!
|
|
410
|
+
price { 450 } # Higher price ($4.50 vs $3.99)
|
|
411
|
+
sku { "CAFE-PAS2-001" }
|
|
412
|
+
association :category, factory: %i[category pastries_dup]
|
|
413
|
+
end
|
|
414
|
+
|
|
415
|
+
trait :blueberry_muffin_dup do
|
|
416
|
+
name { "Blueberry Muffin" } # Same name as original!
|
|
417
|
+
price { 349 } # Same price
|
|
418
|
+
sku { "CAFE-PAS2-002" }
|
|
419
|
+
association :category, factory: %i[category pastries_dup]
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
trait :almond_croissant do
|
|
423
|
+
name { "Almond Croissant" } # New item
|
|
424
|
+
price { 499 }
|
|
425
|
+
sku { "CAFE-PAS2-003" }
|
|
426
|
+
association :category, factory: %i[category pastries_dup]
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
trait :banana_bread do
|
|
430
|
+
name { "Banana Bread" }
|
|
431
|
+
price { 399 }
|
|
432
|
+
sku { "CAFE-PAS2-004" }
|
|
433
|
+
association :category, factory: %i[category pastries_dup]
|
|
434
|
+
end
|
|
435
|
+
|
|
436
|
+
# ── Duplicate Breakfast (2nd category, same + different items) ──
|
|
437
|
+
|
|
438
|
+
trait :avocado_toast_dup do
|
|
439
|
+
name { "Avocado Toast" } # Same name as original!
|
|
440
|
+
price { 1099 } # Higher price ($10.99 vs $9.99)
|
|
441
|
+
sku { "CAFE-BRK2-001" }
|
|
442
|
+
association :category, factory: %i[category breakfast_dup]
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
trait :eggs_benedict do
|
|
446
|
+
name { "Eggs Benedict" }
|
|
447
|
+
price { 1399 }
|
|
448
|
+
sku { "CAFE-BRK2-002" }
|
|
449
|
+
association :category, factory: %i[category breakfast_dup]
|
|
450
|
+
end
|
|
451
|
+
|
|
452
|
+
trait :french_toast do
|
|
453
|
+
name { "French Toast" }
|
|
454
|
+
price { 1199 }
|
|
455
|
+
sku { "CAFE-BRK2-003" }
|
|
456
|
+
association :category, factory: %i[category breakfast_dup]
|
|
457
|
+
end
|
|
458
|
+
|
|
459
|
+
# ── Drinks (catch-all that overlaps Coffee & Smoothies) ──
|
|
460
|
+
|
|
461
|
+
trait :cafe_drip_coffee do
|
|
462
|
+
name { "House Drip Coffee" } # Same name AGAIN (3rd occurrence!)
|
|
463
|
+
price { 275 } # Yet another price ($2.75)
|
|
464
|
+
sku { "CAFE-DRK-001" }
|
|
465
|
+
association :category, factory: %i[category cafe_drinks]
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
trait :cafe_iced_tea do
|
|
469
|
+
name { "Iced Tea" }
|
|
470
|
+
price { 349 }
|
|
471
|
+
sku { "CAFE-DRK-002" }
|
|
472
|
+
association :category, factory: %i[category cafe_drinks]
|
|
473
|
+
end
|
|
474
|
+
|
|
475
|
+
trait :cafe_lemonade do
|
|
476
|
+
name { "Lemonade" }
|
|
477
|
+
price { 399 }
|
|
478
|
+
sku { "CAFE-DRK-003" }
|
|
479
|
+
association :category, factory: %i[category cafe_drinks]
|
|
480
|
+
end
|
|
481
|
+
|
|
482
|
+
trait :cafe_hot_chocolate do
|
|
483
|
+
name { "Hot Chocolate" }
|
|
484
|
+
price { 449 }
|
|
485
|
+
sku { "CAFE-DRK-004" }
|
|
486
|
+
association :category, factory: %i[category cafe_drinks]
|
|
487
|
+
end
|
|
488
|
+
|
|
489
|
+
trait :berry_blast_smoothie_dup do
|
|
490
|
+
name { "Berry Blast Smoothie" } # Same name as in Smoothies!
|
|
491
|
+
price { 749 } # Different price ($7.49 vs $6.99)
|
|
492
|
+
sku { "CAFE-DRK-005" }
|
|
493
|
+
association :category, factory: %i[category cafe_drinks]
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
# ── Grab & Go (cross-listed items from other categories) ──
|
|
497
|
+
|
|
498
|
+
trait :gg_croissant do
|
|
499
|
+
name { "Butter Croissant" } # 3rd occurrence of this item name!
|
|
500
|
+
price { 399 }
|
|
501
|
+
sku { "CAFE-GNG-001" }
|
|
502
|
+
association :category, factory: %i[category cafe_grab_and_go]
|
|
503
|
+
end
|
|
504
|
+
|
|
505
|
+
trait :gg_muffin do
|
|
506
|
+
name { "Blueberry Muffin" } # 3rd occurrence
|
|
507
|
+
price { 399 }
|
|
508
|
+
sku { "CAFE-GNG-002" }
|
|
509
|
+
association :category, factory: %i[category cafe_grab_and_go]
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
trait :gg_blt do
|
|
513
|
+
name { "BLT" } # Same as in Sandwiches
|
|
514
|
+
price { 899 }
|
|
515
|
+
sku { "CAFE-GNG-003" }
|
|
516
|
+
association :category, factory: %i[category cafe_grab_and_go]
|
|
517
|
+
end
|
|
518
|
+
|
|
519
|
+
trait :gg_yogurt_parfait do
|
|
520
|
+
name { "Yogurt Parfait" } # Same as in Breakfast
|
|
521
|
+
price { 599 } # Lower price ($5.99 vs $6.99)
|
|
522
|
+
sku { "CAFE-GNG-004" }
|
|
523
|
+
association :category, factory: %i[category cafe_grab_and_go]
|
|
524
|
+
end
|
|
525
|
+
|
|
526
|
+
trait :gg_cold_brew do
|
|
527
|
+
name { "Cold Brew" } # Same as in Coffee & Espresso
|
|
528
|
+
price { 499 }
|
|
529
|
+
sku { "CAFE-GNG-005" }
|
|
530
|
+
association :category, factory: %i[category cafe_grab_and_go]
|
|
531
|
+
end
|
|
532
|
+
|
|
533
|
+
# ═══════════════════════════════════════════════════════════
|
|
534
|
+
# BAR & NIGHTCLUB (5 categories, 20 items)
|
|
535
|
+
# ═══════════════════════════════════════════════════════════
|
|
536
|
+
|
|
537
|
+
# ── Draft Beer ─────────────────────────────────────────────
|
|
538
|
+
|
|
539
|
+
trait :house_lager do
|
|
540
|
+
name { "House Lager" }
|
|
541
|
+
price { 600 }
|
|
542
|
+
sku { "BAR-DRF-001" }
|
|
543
|
+
association :category, factory: %i[category draft_beer]
|
|
544
|
+
end
|
|
545
|
+
|
|
546
|
+
trait :ipa do
|
|
547
|
+
name { "IPA" }
|
|
548
|
+
price { 700 }
|
|
549
|
+
sku { "BAR-DRF-002" }
|
|
550
|
+
association :category, factory: %i[category draft_beer]
|
|
551
|
+
end
|
|
552
|
+
|
|
553
|
+
trait :stout do
|
|
554
|
+
name { "Stout" }
|
|
555
|
+
price { 750 }
|
|
556
|
+
sku { "BAR-DRF-003" }
|
|
557
|
+
association :category, factory: %i[category draft_beer]
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
trait :wheat_beer do
|
|
561
|
+
name { "Wheat Beer" }
|
|
562
|
+
price { 650 }
|
|
563
|
+
sku { "BAR-DRF-004" }
|
|
564
|
+
association :category, factory: %i[category draft_beer]
|
|
565
|
+
end
|
|
566
|
+
|
|
567
|
+
# ── Cocktails ──────────────────────────────────────────────
|
|
568
|
+
|
|
569
|
+
trait :margarita do
|
|
570
|
+
name { "Margarita" }
|
|
571
|
+
price { 1200 }
|
|
572
|
+
sku { "BAR-CTL-001" }
|
|
573
|
+
association :category, factory: %i[category cocktails]
|
|
574
|
+
end
|
|
575
|
+
|
|
576
|
+
trait :old_fashioned do
|
|
577
|
+
name { "Old Fashioned" }
|
|
578
|
+
price { 1400 }
|
|
579
|
+
sku { "BAR-CTL-002" }
|
|
580
|
+
association :category, factory: %i[category cocktails]
|
|
581
|
+
end
|
|
582
|
+
|
|
583
|
+
trait :mojito do
|
|
584
|
+
name { "Mojito" }
|
|
585
|
+
price { 1300 }
|
|
586
|
+
sku { "BAR-CTL-003" }
|
|
587
|
+
association :category, factory: %i[category cocktails]
|
|
588
|
+
end
|
|
589
|
+
|
|
590
|
+
trait :espresso_martini do
|
|
591
|
+
name { "Espresso Martini" }
|
|
592
|
+
price { 1500 }
|
|
593
|
+
sku { "BAR-CTL-004" }
|
|
594
|
+
association :category, factory: %i[category cocktails]
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
# ── Spirits ────────────────────────────────────────────────
|
|
598
|
+
|
|
599
|
+
trait :whiskey_neat do
|
|
600
|
+
name { "Whiskey Neat" }
|
|
601
|
+
price { 800 }
|
|
602
|
+
sku { "BAR-SPR-001" }
|
|
603
|
+
association :category, factory: %i[category spirits]
|
|
604
|
+
end
|
|
605
|
+
|
|
606
|
+
trait :vodka_soda do
|
|
607
|
+
name { "Vodka Soda" }
|
|
608
|
+
price { 700 }
|
|
609
|
+
sku { "BAR-SPR-002" }
|
|
610
|
+
association :category, factory: %i[category spirits]
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
trait :tequila_shot do
|
|
614
|
+
name { "Tequila Shot" }
|
|
615
|
+
price { 900 }
|
|
616
|
+
sku { "BAR-SPR-003" }
|
|
617
|
+
association :category, factory: %i[category spirits]
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
trait :rum_and_coke do
|
|
621
|
+
name { "Rum & Coke" }
|
|
622
|
+
price { 800 }
|
|
623
|
+
sku { "BAR-SPR-004" }
|
|
624
|
+
association :category, factory: %i[category spirits]
|
|
625
|
+
end
|
|
626
|
+
|
|
627
|
+
# ── Wine ───────────────────────────────────────────────────
|
|
628
|
+
|
|
629
|
+
trait :house_red do
|
|
630
|
+
name { "House Red (Glass)" }
|
|
631
|
+
price { 1000 }
|
|
632
|
+
sku { "BAR-WIN-001" }
|
|
633
|
+
association :category, factory: %i[category wine]
|
|
634
|
+
end
|
|
635
|
+
|
|
636
|
+
trait :house_white do
|
|
637
|
+
name { "House White (Glass)" }
|
|
638
|
+
price { 1000 }
|
|
639
|
+
sku { "BAR-WIN-002" }
|
|
640
|
+
association :category, factory: %i[category wine]
|
|
641
|
+
end
|
|
642
|
+
|
|
643
|
+
trait :prosecco do
|
|
644
|
+
name { "Prosecco (Glass)" }
|
|
645
|
+
price { 1200 }
|
|
646
|
+
sku { "BAR-WIN-003" }
|
|
647
|
+
association :category, factory: %i[category wine]
|
|
648
|
+
end
|
|
649
|
+
|
|
650
|
+
trait :rose do
|
|
651
|
+
name { "Rose (Glass)" }
|
|
652
|
+
price { 1100 }
|
|
653
|
+
sku { "BAR-WIN-004" }
|
|
654
|
+
association :category, factory: %i[category wine]
|
|
655
|
+
end
|
|
656
|
+
|
|
657
|
+
# ── Bar Snacks ─────────────────────────────────────────────
|
|
658
|
+
|
|
659
|
+
trait :bar_loaded_fries do
|
|
660
|
+
name { "Loaded Fries" }
|
|
661
|
+
price { 999 }
|
|
662
|
+
sku { "BAR-SNK-001" }
|
|
663
|
+
association :category, factory: %i[category bar_snacks]
|
|
664
|
+
end
|
|
665
|
+
|
|
666
|
+
trait :sliders do
|
|
667
|
+
name { "Sliders (3pc)" }
|
|
668
|
+
price { 1299 }
|
|
669
|
+
sku { "BAR-SNK-002" }
|
|
670
|
+
association :category, factory: %i[category bar_snacks]
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
trait :bar_wings do
|
|
674
|
+
name { "Chicken Wings" }
|
|
675
|
+
price { 1199 }
|
|
676
|
+
sku { "BAR-SNK-003" }
|
|
677
|
+
association :category, factory: %i[category bar_snacks]
|
|
678
|
+
end
|
|
679
|
+
|
|
680
|
+
trait :pretzel_bites do
|
|
681
|
+
name { "Pretzel Bites" }
|
|
682
|
+
price { 899 }
|
|
683
|
+
sku { "BAR-SNK-004" }
|
|
684
|
+
association :category, factory: %i[category bar_snacks]
|
|
685
|
+
end
|
|
686
|
+
|
|
687
|
+
# ═══════════════════════════════════════════════════════════
|
|
688
|
+
# FOOD TRUCK (3 categories, 14 items)
|
|
689
|
+
# ═══════════════════════════════════════════════════════════
|
|
690
|
+
|
|
691
|
+
# ── Tacos ──────────────────────────────────────────────────
|
|
692
|
+
|
|
693
|
+
trait :carne_asada_taco do
|
|
694
|
+
name { "Carne Asada Taco" }
|
|
695
|
+
price { 499 }
|
|
696
|
+
sku { "FT-TAC-001" }
|
|
697
|
+
association :category, factory: %i[category tacos]
|
|
698
|
+
end
|
|
699
|
+
|
|
700
|
+
trait :al_pastor_taco do
|
|
701
|
+
name { "Al Pastor Taco" }
|
|
702
|
+
price { 449 }
|
|
703
|
+
sku { "FT-TAC-002" }
|
|
704
|
+
association :category, factory: %i[category tacos]
|
|
705
|
+
end
|
|
706
|
+
|
|
707
|
+
trait :fish_taco do
|
|
708
|
+
name { "Fish Taco" }
|
|
709
|
+
price { 549 }
|
|
710
|
+
sku { "FT-TAC-003" }
|
|
711
|
+
association :category, factory: %i[category tacos]
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
trait :veggie_taco do
|
|
715
|
+
name { "Veggie Taco" }
|
|
716
|
+
price { 399 }
|
|
717
|
+
sku { "FT-TAC-004" }
|
|
718
|
+
association :category, factory: %i[category tacos]
|
|
719
|
+
end
|
|
720
|
+
|
|
721
|
+
trait :birria_taco do
|
|
722
|
+
name { "Birria Taco" }
|
|
723
|
+
price { 599 }
|
|
724
|
+
sku { "FT-TAC-005" }
|
|
725
|
+
association :category, factory: %i[category tacos]
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
# ── Burritos & Bowls ───────────────────────────────────────
|
|
729
|
+
|
|
730
|
+
trait :classic_burrito do
|
|
731
|
+
name { "Classic Burrito" }
|
|
732
|
+
price { 1099 }
|
|
733
|
+
sku { "FT-BUR-001" }
|
|
734
|
+
association :category, factory: %i[category burritos_bowls]
|
|
735
|
+
end
|
|
736
|
+
|
|
737
|
+
trait :burrito_bowl do
|
|
738
|
+
name { "Burrito Bowl" }
|
|
739
|
+
price { 1149 }
|
|
740
|
+
sku { "FT-BUR-002" }
|
|
741
|
+
association :category, factory: %i[category burritos_bowls]
|
|
742
|
+
end
|
|
743
|
+
|
|
744
|
+
trait :quesadilla do
|
|
745
|
+
name { "Quesadilla" }
|
|
746
|
+
price { 899 }
|
|
747
|
+
sku { "FT-BUR-003" }
|
|
748
|
+
association :category, factory: %i[category burritos_bowls]
|
|
749
|
+
end
|
|
750
|
+
|
|
751
|
+
trait :truck_nachos do
|
|
752
|
+
name { "Loaded Nachos" }
|
|
753
|
+
price { 999 }
|
|
754
|
+
sku { "FT-BUR-004" }
|
|
755
|
+
association :category, factory: %i[category burritos_bowls]
|
|
756
|
+
end
|
|
757
|
+
|
|
758
|
+
# ── Sides & Drinks ─────────────────────────────────────────
|
|
759
|
+
|
|
760
|
+
trait :chips_and_guac do
|
|
761
|
+
name { "Chips & Guacamole" }
|
|
762
|
+
price { 499 }
|
|
763
|
+
sku { "FT-SDE-001" }
|
|
764
|
+
association :category, factory: %i[category truck_sides_drinks]
|
|
765
|
+
end
|
|
766
|
+
|
|
767
|
+
trait :elote do
|
|
768
|
+
name { "Elote (Street Corn)" }
|
|
769
|
+
price { 399 }
|
|
770
|
+
sku { "FT-SDE-002" }
|
|
771
|
+
association :category, factory: %i[category truck_sides_drinks]
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
trait :rice_and_beans do
|
|
775
|
+
name { "Rice & Beans" }
|
|
776
|
+
price { 349 }
|
|
777
|
+
sku { "FT-SDE-003" }
|
|
778
|
+
association :category, factory: %i[category truck_sides_drinks]
|
|
779
|
+
end
|
|
780
|
+
|
|
781
|
+
trait :horchata do
|
|
782
|
+
name { "Horchata" }
|
|
783
|
+
price { 399 }
|
|
784
|
+
sku { "FT-SDE-004" }
|
|
785
|
+
association :category, factory: %i[category truck_sides_drinks]
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
trait :jarritos do
|
|
789
|
+
name { "Jarritos" }
|
|
790
|
+
price { 299 }
|
|
791
|
+
sku { "FT-SDE-005" }
|
|
792
|
+
association :category, factory: %i[category truck_sides_drinks]
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
# ═══════════════════════════════════════════════════════════
|
|
796
|
+
# FINE DINING (3 categories, 15 items)
|
|
797
|
+
# ═══════════════════════════════════════════════════════════
|
|
798
|
+
|
|
799
|
+
# ── First Course ───────────────────────────────────────────
|
|
800
|
+
|
|
801
|
+
trait :seared_foie_gras do
|
|
802
|
+
name { "Seared Foie Gras" }
|
|
803
|
+
price { 2400 }
|
|
804
|
+
sku { "FD-FST-001" }
|
|
805
|
+
association :category, factory: %i[category first_course]
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
trait :lobster_bisque do
|
|
809
|
+
name { "Lobster Bisque" }
|
|
810
|
+
price { 1800 }
|
|
811
|
+
sku { "FD-FST-002" }
|
|
812
|
+
association :category, factory: %i[category first_course]
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
trait :tuna_tartare do
|
|
816
|
+
name { "Tuna Tartare" }
|
|
817
|
+
price { 2200 }
|
|
818
|
+
sku { "FD-FST-003" }
|
|
819
|
+
association :category, factory: %i[category first_course]
|
|
820
|
+
end
|
|
821
|
+
|
|
822
|
+
trait :burrata_salad do
|
|
823
|
+
name { "Burrata Salad" }
|
|
824
|
+
price { 1900 }
|
|
825
|
+
sku { "FD-FST-004" }
|
|
826
|
+
association :category, factory: %i[category first_course]
|
|
827
|
+
end
|
|
828
|
+
|
|
829
|
+
trait :oysters_half_dozen do
|
|
830
|
+
name { "Oysters (Half Dozen)" }
|
|
831
|
+
price { 2800 }
|
|
832
|
+
sku { "FD-FST-005" }
|
|
833
|
+
association :category, factory: %i[category first_course]
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
# ── Main Course ────────────────────────────────────────────
|
|
837
|
+
|
|
838
|
+
trait :wagyu_ribeye do
|
|
839
|
+
name { "Wagyu Ribeye" }
|
|
840
|
+
price { 6500 }
|
|
841
|
+
sku { "FD-MAN-001" }
|
|
842
|
+
association :category, factory: %i[category main_course]
|
|
843
|
+
end
|
|
844
|
+
|
|
845
|
+
trait :chilean_sea_bass do
|
|
846
|
+
name { "Pan-Seared Chilean Sea Bass" }
|
|
847
|
+
price { 4800 }
|
|
848
|
+
sku { "FD-MAN-002" }
|
|
849
|
+
association :category, factory: %i[category main_course]
|
|
850
|
+
end
|
|
851
|
+
|
|
852
|
+
trait :rack_of_lamb do
|
|
853
|
+
name { "Rack of Lamb" }
|
|
854
|
+
price { 5200 }
|
|
855
|
+
sku { "FD-MAN-003" }
|
|
856
|
+
association :category, factory: %i[category main_course]
|
|
857
|
+
end
|
|
858
|
+
|
|
859
|
+
trait :duck_breast do
|
|
860
|
+
name { "Duck Breast" }
|
|
861
|
+
price { 4200 }
|
|
862
|
+
sku { "FD-MAN-004" }
|
|
863
|
+
association :category, factory: %i[category main_course]
|
|
864
|
+
end
|
|
865
|
+
|
|
866
|
+
trait :truffle_risotto do
|
|
867
|
+
name { "Truffle Risotto" }
|
|
868
|
+
price { 3800 }
|
|
869
|
+
sku { "FD-MAN-005" }
|
|
870
|
+
association :category, factory: %i[category main_course]
|
|
871
|
+
end
|
|
872
|
+
|
|
873
|
+
# ── Desserts & Petit Fours ─────────────────────────────────
|
|
874
|
+
|
|
875
|
+
trait :creme_brulee do
|
|
876
|
+
name { "Creme Brulee" }
|
|
877
|
+
price { 1600 }
|
|
878
|
+
sku { "FD-DES-001" }
|
|
879
|
+
association :category, factory: %i[category fine_desserts]
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
trait :chocolate_souffle do
|
|
883
|
+
name { "Chocolate Souffle" }
|
|
884
|
+
price { 1800 }
|
|
885
|
+
sku { "FD-DES-002" }
|
|
886
|
+
association :category, factory: %i[category fine_desserts]
|
|
887
|
+
end
|
|
888
|
+
|
|
889
|
+
trait :tasting_plate do
|
|
890
|
+
name { "Tasting Plate" }
|
|
891
|
+
price { 2200 }
|
|
892
|
+
sku { "FD-DES-003" }
|
|
893
|
+
association :category, factory: %i[category fine_desserts]
|
|
894
|
+
end
|
|
895
|
+
|
|
896
|
+
trait :cheese_board do
|
|
897
|
+
name { "Cheese Board" }
|
|
898
|
+
price { 2400 }
|
|
899
|
+
sku { "FD-DES-004" }
|
|
900
|
+
association :category, factory: %i[category fine_desserts]
|
|
901
|
+
end
|
|
902
|
+
|
|
903
|
+
trait :fine_tiramisu do
|
|
904
|
+
name { "Tiramisu" }
|
|
905
|
+
price { 1600 }
|
|
906
|
+
sku { "FD-DES-005" }
|
|
907
|
+
association :category, factory: %i[category fine_desserts]
|
|
908
|
+
end
|
|
909
|
+
|
|
910
|
+
# ═══════════════════════════════════════════════════════════
|
|
911
|
+
# PIZZERIA (3 categories, 16 items)
|
|
912
|
+
# ═══════════════════════════════════════════════════════════
|
|
913
|
+
|
|
914
|
+
# ── Pizzas ─────────────────────────────────────────────────
|
|
915
|
+
|
|
916
|
+
trait :margherita do
|
|
917
|
+
name { "Margherita" }
|
|
918
|
+
price { 1499 }
|
|
919
|
+
sku { "PIZ-PIZ-001" }
|
|
920
|
+
association :category, factory: %i[category pizzas]
|
|
921
|
+
end
|
|
922
|
+
|
|
923
|
+
trait :pepperoni do
|
|
924
|
+
name { "Pepperoni" }
|
|
925
|
+
price { 1599 }
|
|
926
|
+
sku { "PIZ-PIZ-002" }
|
|
927
|
+
association :category, factory: %i[category pizzas]
|
|
928
|
+
end
|
|
929
|
+
|
|
930
|
+
trait :supreme do
|
|
931
|
+
name { "Supreme" }
|
|
932
|
+
price { 1899 }
|
|
933
|
+
sku { "PIZ-PIZ-003" }
|
|
934
|
+
association :category, factory: %i[category pizzas]
|
|
935
|
+
end
|
|
936
|
+
|
|
937
|
+
trait :hawaiian do
|
|
938
|
+
name { "Hawaiian" }
|
|
939
|
+
price { 1699 }
|
|
940
|
+
sku { "PIZ-PIZ-004" }
|
|
941
|
+
association :category, factory: %i[category pizzas]
|
|
942
|
+
end
|
|
943
|
+
|
|
944
|
+
trait :bbq_chicken_pizza do
|
|
945
|
+
name { "BBQ Chicken Pizza" }
|
|
946
|
+
price { 1999 }
|
|
947
|
+
sku { "PIZ-PIZ-005" }
|
|
948
|
+
association :category, factory: %i[category pizzas]
|
|
949
|
+
end
|
|
950
|
+
|
|
951
|
+
trait :meat_lovers do
|
|
952
|
+
name { "Meat Lovers" }
|
|
953
|
+
price { 2099 }
|
|
954
|
+
sku { "PIZ-PIZ-006" }
|
|
955
|
+
association :category, factory: %i[category pizzas]
|
|
956
|
+
end
|
|
957
|
+
|
|
958
|
+
# ── Calzones & Stromboli ───────────────────────────────────
|
|
959
|
+
|
|
960
|
+
trait :classic_calzone do
|
|
961
|
+
name { "Classic Calzone" }
|
|
962
|
+
price { 1399 }
|
|
963
|
+
sku { "PIZ-CAL-001" }
|
|
964
|
+
association :category, factory: %i[category calzones]
|
|
965
|
+
end
|
|
966
|
+
|
|
967
|
+
trait :meat_calzone do
|
|
968
|
+
name { "Meat Calzone" }
|
|
969
|
+
price { 1599 }
|
|
970
|
+
sku { "PIZ-CAL-002" }
|
|
971
|
+
association :category, factory: %i[category calzones]
|
|
972
|
+
end
|
|
973
|
+
|
|
974
|
+
trait :stromboli do
|
|
975
|
+
name { "Stromboli" }
|
|
976
|
+
price { 1499 }
|
|
977
|
+
sku { "PIZ-CAL-003" }
|
|
978
|
+
association :category, factory: %i[category calzones]
|
|
979
|
+
end
|
|
980
|
+
|
|
981
|
+
trait :spinach_calzone do
|
|
982
|
+
name { "Spinach & Ricotta Calzone" }
|
|
983
|
+
price { 1399 }
|
|
984
|
+
sku { "PIZ-CAL-004" }
|
|
985
|
+
association :category, factory: %i[category calzones]
|
|
986
|
+
end
|
|
987
|
+
|
|
988
|
+
# ── Sides & Drinks ─────────────────────────────────────────
|
|
989
|
+
|
|
990
|
+
trait :garlic_bread do
|
|
991
|
+
name { "Garlic Bread" }
|
|
992
|
+
price { 599 }
|
|
993
|
+
sku { "PIZ-SDE-001" }
|
|
994
|
+
association :category, factory: %i[category pizza_sides_drinks]
|
|
995
|
+
end
|
|
996
|
+
|
|
997
|
+
trait :garden_salad do
|
|
998
|
+
name { "Garden Salad" }
|
|
999
|
+
price { 799 }
|
|
1000
|
+
sku { "PIZ-SDE-002" }
|
|
1001
|
+
association :category, factory: %i[category pizza_sides_drinks]
|
|
1002
|
+
end
|
|
1003
|
+
|
|
1004
|
+
trait :caesar_salad do
|
|
1005
|
+
name { "Caesar Salad" }
|
|
1006
|
+
price { 899 }
|
|
1007
|
+
sku { "PIZ-SDE-003" }
|
|
1008
|
+
association :category, factory: %i[category pizza_sides_drinks]
|
|
1009
|
+
end
|
|
1010
|
+
|
|
1011
|
+
trait :garlic_knots do
|
|
1012
|
+
name { "Garlic Knots (6pc)" }
|
|
1013
|
+
price { 699 }
|
|
1014
|
+
sku { "PIZ-SDE-004" }
|
|
1015
|
+
association :category, factory: %i[category pizza_sides_drinks]
|
|
1016
|
+
end
|
|
1017
|
+
|
|
1018
|
+
trait :fountain_drink do
|
|
1019
|
+
name { "Fountain Drink" }
|
|
1020
|
+
price { 249 }
|
|
1021
|
+
sku { "PIZ-SDE-005" }
|
|
1022
|
+
association :category, factory: %i[category pizza_sides_drinks]
|
|
1023
|
+
end
|
|
1024
|
+
|
|
1025
|
+
trait :cannoli do
|
|
1026
|
+
name { "Cannoli" }
|
|
1027
|
+
price { 599 }
|
|
1028
|
+
sku { "PIZ-SDE-006" }
|
|
1029
|
+
association :category, factory: %i[category pizza_sides_drinks]
|
|
1030
|
+
end
|
|
1031
|
+
|
|
1032
|
+
# ═══════════════════════════════════════════════════════════
|
|
1033
|
+
# RETAIL CLOTHING (5 categories, 21 items)
|
|
1034
|
+
# — items include `variants` jsonb with sizes/colors
|
|
1035
|
+
# ═══════════════════════════════════════════════════════════
|
|
1036
|
+
|
|
1037
|
+
# ── Tops ───────────────────────────────────────────────────
|
|
1038
|
+
|
|
1039
|
+
trait :classic_tshirt do
|
|
1040
|
+
name { "Classic T-Shirt" }
|
|
1041
|
+
price { 2499 }
|
|
1042
|
+
sku { "RCL-TOP-001" }
|
|
1043
|
+
association :category, factory: %i[category tops]
|
|
1044
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Black White Navy] }] }
|
|
1045
|
+
end
|
|
1046
|
+
|
|
1047
|
+
trait :button_down_shirt do
|
|
1048
|
+
name { "Button-Down Shirt" }
|
|
1049
|
+
price { 4999 }
|
|
1050
|
+
sku { "RCL-TOP-002" }
|
|
1051
|
+
association :category, factory: %i[category tops]
|
|
1052
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[White Blue Striped] }] }
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
trait :polo_shirt do
|
|
1056
|
+
name { "Polo Shirt" }
|
|
1057
|
+
price { 3999 }
|
|
1058
|
+
sku { "RCL-TOP-003" }
|
|
1059
|
+
association :category, factory: %i[category tops]
|
|
1060
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Black White Red] }] }
|
|
1061
|
+
end
|
|
1062
|
+
|
|
1063
|
+
trait :hoodie do
|
|
1064
|
+
name { "Hoodie" }
|
|
1065
|
+
price { 5499 }
|
|
1066
|
+
sku { "RCL-TOP-004" }
|
|
1067
|
+
association :category, factory: %i[category tops]
|
|
1068
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Black Gray Navy] }] }
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1071
|
+
trait :tank_top do
|
|
1072
|
+
name { "Tank Top" }
|
|
1073
|
+
price { 1999 }
|
|
1074
|
+
sku { "RCL-TOP-005" }
|
|
1075
|
+
association :category, factory: %i[category tops]
|
|
1076
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[White Black] }] }
|
|
1077
|
+
end
|
|
1078
|
+
|
|
1079
|
+
# ── Bottoms ────────────────────────────────────────────────
|
|
1080
|
+
|
|
1081
|
+
trait :slim_fit_jeans do
|
|
1082
|
+
name { "Slim Fit Jeans" }
|
|
1083
|
+
price { 5999 }
|
|
1084
|
+
sku { "RCL-BTM-001" }
|
|
1085
|
+
association :category, factory: %i[category bottoms]
|
|
1086
|
+
variants { [{ sizes: %w[28 30 32 34 36], colors: %w[Indigo Black Light] }] }
|
|
1087
|
+
end
|
|
1088
|
+
|
|
1089
|
+
trait :chino_pants do
|
|
1090
|
+
name { "Chino Pants" }
|
|
1091
|
+
price { 4499 }
|
|
1092
|
+
sku { "RCL-BTM-002" }
|
|
1093
|
+
association :category, factory: %i[category bottoms]
|
|
1094
|
+
variants { [{ sizes: %w[28 30 32 34 36], colors: %w[Khaki Navy Olive] }] }
|
|
1095
|
+
end
|
|
1096
|
+
|
|
1097
|
+
trait :joggers do
|
|
1098
|
+
name { "Joggers" }
|
|
1099
|
+
price { 3999 }
|
|
1100
|
+
sku { "RCL-BTM-003" }
|
|
1101
|
+
association :category, factory: %i[category bottoms]
|
|
1102
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Black Gray] }] }
|
|
1103
|
+
end
|
|
1104
|
+
|
|
1105
|
+
trait :shorts do
|
|
1106
|
+
name { "Shorts" }
|
|
1107
|
+
price { 3499 }
|
|
1108
|
+
sku { "RCL-BTM-004" }
|
|
1109
|
+
association :category, factory: %i[category bottoms]
|
|
1110
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Navy Khaki Black] }] }
|
|
1111
|
+
end
|
|
1112
|
+
|
|
1113
|
+
# ── Outerwear ──────────────────────────────────────────────
|
|
1114
|
+
|
|
1115
|
+
trait :denim_jacket do
|
|
1116
|
+
name { "Denim Jacket" }
|
|
1117
|
+
price { 7999 }
|
|
1118
|
+
sku { "RCL-OUT-001" }
|
|
1119
|
+
association :category, factory: %i[category outerwear]
|
|
1120
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Indigo Light] }] }
|
|
1121
|
+
end
|
|
1122
|
+
|
|
1123
|
+
trait :bomber_jacket do
|
|
1124
|
+
name { "Bomber Jacket" }
|
|
1125
|
+
price { 8999 }
|
|
1126
|
+
sku { "RCL-OUT-002" }
|
|
1127
|
+
association :category, factory: %i[category outerwear]
|
|
1128
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Black Olive] }] }
|
|
1129
|
+
end
|
|
1130
|
+
|
|
1131
|
+
trait :puffer_vest do
|
|
1132
|
+
name { "Puffer Vest" }
|
|
1133
|
+
price { 6999 }
|
|
1134
|
+
sku { "RCL-OUT-003" }
|
|
1135
|
+
association :category, factory: %i[category outerwear]
|
|
1136
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Black Navy Red] }] }
|
|
1137
|
+
end
|
|
1138
|
+
|
|
1139
|
+
trait :rain_jacket do
|
|
1140
|
+
name { "Rain Jacket" }
|
|
1141
|
+
price { 6499 }
|
|
1142
|
+
sku { "RCL-OUT-004" }
|
|
1143
|
+
association :category, factory: %i[category outerwear]
|
|
1144
|
+
variants { [{ sizes: %w[S M L XL], colors: %w[Yellow Navy Black] }] }
|
|
1145
|
+
end
|
|
1146
|
+
|
|
1147
|
+
# ── Accessories ────────────────────────────────────────────
|
|
1148
|
+
|
|
1149
|
+
trait :baseball_cap do
|
|
1150
|
+
name { "Baseball Cap" }
|
|
1151
|
+
price { 2499 }
|
|
1152
|
+
sku { "RCL-ACC-001" }
|
|
1153
|
+
association :category, factory: %i[category accessories]
|
|
1154
|
+
variants { [{ colors: %w[Black White Navy Red] }] }
|
|
1155
|
+
end
|
|
1156
|
+
|
|
1157
|
+
trait :beanie do
|
|
1158
|
+
name { "Beanie" }
|
|
1159
|
+
price { 1999 }
|
|
1160
|
+
sku { "RCL-ACC-002" }
|
|
1161
|
+
association :category, factory: %i[category accessories]
|
|
1162
|
+
variants { [{ colors: %w[Black Gray Burgundy] }] }
|
|
1163
|
+
end
|
|
1164
|
+
|
|
1165
|
+
trait :canvas_belt do
|
|
1166
|
+
name { "Canvas Belt" }
|
|
1167
|
+
price { 2999 }
|
|
1168
|
+
sku { "RCL-ACC-003" }
|
|
1169
|
+
association :category, factory: %i[category accessories]
|
|
1170
|
+
variants { [{ sizes: %w[S M L], colors: %w[Black Brown Tan] }] }
|
|
1171
|
+
end
|
|
1172
|
+
|
|
1173
|
+
trait :scarf do
|
|
1174
|
+
name { "Scarf" }
|
|
1175
|
+
price { 3499 }
|
|
1176
|
+
sku { "RCL-ACC-004" }
|
|
1177
|
+
association :category, factory: %i[category accessories]
|
|
1178
|
+
variants { [{ colors: ["Plaid", "Solid Gray", "Solid Black"] }] }
|
|
1179
|
+
end
|
|
1180
|
+
|
|
1181
|
+
# ── Footwear ───────────────────────────────────────────────
|
|
1182
|
+
|
|
1183
|
+
trait :canvas_sneakers do
|
|
1184
|
+
name { "Canvas Sneakers" }
|
|
1185
|
+
price { 4999 }
|
|
1186
|
+
sku { "RCL-FTW-001" }
|
|
1187
|
+
association :category, factory: %i[category footwear]
|
|
1188
|
+
variants { [{ sizes: %w[7 8 9 10 11 12], colors: %w[White Black Navy] }] }
|
|
1189
|
+
end
|
|
1190
|
+
|
|
1191
|
+
trait :leather_boots do
|
|
1192
|
+
name { "Leather Boots" }
|
|
1193
|
+
price { 12_999 }
|
|
1194
|
+
sku { "RCL-FTW-002" }
|
|
1195
|
+
association :category, factory: %i[category footwear]
|
|
1196
|
+
variants { [{ sizes: %w[7 8 9 10 11 12], colors: %w[Brown Black] }] }
|
|
1197
|
+
end
|
|
1198
|
+
|
|
1199
|
+
trait :sandals do
|
|
1200
|
+
name { "Sandals" }
|
|
1201
|
+
price { 3499 }
|
|
1202
|
+
sku { "RCL-FTW-003" }
|
|
1203
|
+
association :category, factory: %i[category footwear]
|
|
1204
|
+
variants { [{ sizes: %w[7 8 9 10 11 12], colors: %w[Tan Black] }] }
|
|
1205
|
+
end
|
|
1206
|
+
|
|
1207
|
+
trait :running_shoes do
|
|
1208
|
+
name { "Running Shoes" }
|
|
1209
|
+
price { 8999 }
|
|
1210
|
+
sku { "RCL-FTW-004" }
|
|
1211
|
+
association :category, factory: %i[category footwear]
|
|
1212
|
+
variants { [{ sizes: %w[7 8 9 10 11 12], colors: %w[Black White Red] }] }
|
|
1213
|
+
end
|
|
1214
|
+
|
|
1215
|
+
# ═══════════════════════════════════════════════════════════
|
|
1216
|
+
# RETAIL GENERAL (5 categories, 20 items)
|
|
1217
|
+
# ═══════════════════════════════════════════════════════════
|
|
1218
|
+
|
|
1219
|
+
# ── Electronics ────────────────────────────────────────────
|
|
1220
|
+
|
|
1221
|
+
trait :wireless_earbuds do
|
|
1222
|
+
name { "Wireless Earbuds" }
|
|
1223
|
+
price { 7999 }
|
|
1224
|
+
sku { "RGN-ELC-001" }
|
|
1225
|
+
association :category, factory: %i[category electronics]
|
|
1226
|
+
end
|
|
1227
|
+
|
|
1228
|
+
trait :phone_charger do
|
|
1229
|
+
name { "Phone Charger" }
|
|
1230
|
+
price { 1999 }
|
|
1231
|
+
sku { "RGN-ELC-002" }
|
|
1232
|
+
association :category, factory: %i[category electronics]
|
|
1233
|
+
end
|
|
1234
|
+
|
|
1235
|
+
trait :bluetooth_speaker do
|
|
1236
|
+
name { "Bluetooth Speaker" }
|
|
1237
|
+
price { 4999 }
|
|
1238
|
+
sku { "RGN-ELC-003" }
|
|
1239
|
+
association :category, factory: %i[category electronics]
|
|
1240
|
+
end
|
|
1241
|
+
|
|
1242
|
+
trait :power_bank do
|
|
1243
|
+
name { "Power Bank" }
|
|
1244
|
+
price { 3499 }
|
|
1245
|
+
sku { "RGN-ELC-004" }
|
|
1246
|
+
association :category, factory: %i[category electronics]
|
|
1247
|
+
end
|
|
1248
|
+
|
|
1249
|
+
# ── Home & Kitchen ─────────────────────────────────────────
|
|
1250
|
+
|
|
1251
|
+
trait :scented_candle do
|
|
1252
|
+
name { "Scented Candle" }
|
|
1253
|
+
price { 2499 }
|
|
1254
|
+
sku { "RGN-HMK-001" }
|
|
1255
|
+
association :category, factory: %i[category home_kitchen]
|
|
1256
|
+
end
|
|
1257
|
+
|
|
1258
|
+
trait :throw_pillow do
|
|
1259
|
+
name { "Throw Pillow" }
|
|
1260
|
+
price { 2999 }
|
|
1261
|
+
sku { "RGN-HMK-002" }
|
|
1262
|
+
association :category, factory: %i[category home_kitchen]
|
|
1263
|
+
end
|
|
1264
|
+
|
|
1265
|
+
trait :kitchen_towel_set do
|
|
1266
|
+
name { "Kitchen Towel Set" }
|
|
1267
|
+
price { 1499 }
|
|
1268
|
+
sku { "RGN-HMK-003" }
|
|
1269
|
+
association :category, factory: %i[category home_kitchen]
|
|
1270
|
+
end
|
|
1271
|
+
|
|
1272
|
+
trait :ceramic_mug do
|
|
1273
|
+
name { "Ceramic Mug" }
|
|
1274
|
+
price { 1299 }
|
|
1275
|
+
sku { "RGN-HMK-004" }
|
|
1276
|
+
association :category, factory: %i[category home_kitchen]
|
|
1277
|
+
end
|
|
1278
|
+
|
|
1279
|
+
# ── Personal Care ──────────────────────────────────────────
|
|
1280
|
+
|
|
1281
|
+
trait :hand_soap do
|
|
1282
|
+
name { "Hand Soap" }
|
|
1283
|
+
price { 699 }
|
|
1284
|
+
sku { "RGN-PRC-001" }
|
|
1285
|
+
association :category, factory: %i[category personal_care]
|
|
1286
|
+
end
|
|
1287
|
+
|
|
1288
|
+
trait :body_lotion do
|
|
1289
|
+
name { "Body Lotion" }
|
|
1290
|
+
price { 1499 }
|
|
1291
|
+
sku { "RGN-PRC-002" }
|
|
1292
|
+
association :category, factory: %i[category personal_care]
|
|
1293
|
+
end
|
|
1294
|
+
|
|
1295
|
+
trait :lip_balm do
|
|
1296
|
+
name { "Lip Balm" }
|
|
1297
|
+
price { 499 }
|
|
1298
|
+
sku { "RGN-PRC-003" }
|
|
1299
|
+
association :category, factory: %i[category personal_care]
|
|
1300
|
+
end
|
|
1301
|
+
|
|
1302
|
+
trait :sunscreen do
|
|
1303
|
+
name { "Sunscreen SPF 50" }
|
|
1304
|
+
price { 1299 }
|
|
1305
|
+
sku { "RGN-PRC-004" }
|
|
1306
|
+
association :category, factory: %i[category personal_care]
|
|
1307
|
+
end
|
|
1308
|
+
|
|
1309
|
+
# ── Office Supplies ────────────────────────────────────────
|
|
1310
|
+
|
|
1311
|
+
trait :notebook do
|
|
1312
|
+
name { "Notebook" }
|
|
1313
|
+
price { 999 }
|
|
1314
|
+
sku { "RGN-OFC-001" }
|
|
1315
|
+
association :category, factory: %i[category office_supplies]
|
|
1316
|
+
end
|
|
1317
|
+
|
|
1318
|
+
trait :pen_set do
|
|
1319
|
+
name { "Ballpoint Pen Set" }
|
|
1320
|
+
price { 799 }
|
|
1321
|
+
sku { "RGN-OFC-002" }
|
|
1322
|
+
association :category, factory: %i[category office_supplies]
|
|
1323
|
+
end
|
|
1324
|
+
|
|
1325
|
+
trait :desk_organizer do
|
|
1326
|
+
name { "Desk Organizer" }
|
|
1327
|
+
price { 1999 }
|
|
1328
|
+
sku { "RGN-OFC-003" }
|
|
1329
|
+
association :category, factory: %i[category office_supplies]
|
|
1330
|
+
end
|
|
1331
|
+
|
|
1332
|
+
trait :sticky_notes do
|
|
1333
|
+
name { "Sticky Notes" }
|
|
1334
|
+
price { 499 }
|
|
1335
|
+
sku { "RGN-OFC-004" }
|
|
1336
|
+
association :category, factory: %i[category office_supplies]
|
|
1337
|
+
end
|
|
1338
|
+
|
|
1339
|
+
# ── Snacks & Beverages ─────────────────────────────────────
|
|
1340
|
+
|
|
1341
|
+
trait :granola_bar_3pack do
|
|
1342
|
+
name { "Granola Bar (3-Pack)" }
|
|
1343
|
+
price { 599 }
|
|
1344
|
+
sku { "RGN-SNK-001" }
|
|
1345
|
+
association :category, factory: %i[category snacks_beverages]
|
|
1346
|
+
end
|
|
1347
|
+
|
|
1348
|
+
trait :retail_sparkling_water do
|
|
1349
|
+
name { "Sparkling Water" }
|
|
1350
|
+
price { 249 }
|
|
1351
|
+
sku { "RGN-SNK-002" }
|
|
1352
|
+
association :category, factory: %i[category snacks_beverages]
|
|
1353
|
+
end
|
|
1354
|
+
|
|
1355
|
+
trait :trail_mix do
|
|
1356
|
+
name { "Trail Mix" }
|
|
1357
|
+
price { 699 }
|
|
1358
|
+
sku { "RGN-SNK-003" }
|
|
1359
|
+
association :category, factory: %i[category snacks_beverages]
|
|
1360
|
+
end
|
|
1361
|
+
|
|
1362
|
+
trait :dark_chocolate_bar do
|
|
1363
|
+
name { "Dark Chocolate Bar" }
|
|
1364
|
+
price { 499 }
|
|
1365
|
+
sku { "RGN-SNK-004" }
|
|
1366
|
+
association :category, factory: %i[category snacks_beverages]
|
|
1367
|
+
end
|
|
1368
|
+
|
|
1369
|
+
# ═══════════════════════════════════════════════════════════
|
|
1370
|
+
# SALON & SPA (4 categories, 16 items)
|
|
1371
|
+
# — services use unit: "session", metadata with duration
|
|
1372
|
+
# ═══════════════════════════════════════════════════════════
|
|
1373
|
+
|
|
1374
|
+
# ── Haircuts ───────────────────────────────────────────────
|
|
1375
|
+
|
|
1376
|
+
trait :womens_haircut do
|
|
1377
|
+
name { "Women's Haircut" }
|
|
1378
|
+
price { 5500 }
|
|
1379
|
+
sku { "SPA-HAR-001" }
|
|
1380
|
+
unit { "session" }
|
|
1381
|
+
metadata { { "duration_minutes" => 45 } }
|
|
1382
|
+
association :category, factory: %i[category haircuts]
|
|
1383
|
+
end
|
|
1384
|
+
|
|
1385
|
+
trait :mens_haircut do
|
|
1386
|
+
name { "Men's Haircut" }
|
|
1387
|
+
price { 3000 }
|
|
1388
|
+
sku { "SPA-HAR-002" }
|
|
1389
|
+
unit { "session" }
|
|
1390
|
+
metadata { { "duration_minutes" => 30 } }
|
|
1391
|
+
association :category, factory: %i[category haircuts]
|
|
1392
|
+
end
|
|
1393
|
+
|
|
1394
|
+
trait :childrens_haircut do
|
|
1395
|
+
name { "Children's Haircut" }
|
|
1396
|
+
price { 2000 }
|
|
1397
|
+
sku { "SPA-HAR-003" }
|
|
1398
|
+
unit { "session" }
|
|
1399
|
+
metadata { { "duration_minutes" => 20 } }
|
|
1400
|
+
association :category, factory: %i[category haircuts]
|
|
1401
|
+
end
|
|
1402
|
+
|
|
1403
|
+
trait :bang_trim do
|
|
1404
|
+
name { "Bang Trim" }
|
|
1405
|
+
price { 1500 }
|
|
1406
|
+
sku { "SPA-HAR-004" }
|
|
1407
|
+
unit { "session" }
|
|
1408
|
+
metadata { { "duration_minutes" => 15 } }
|
|
1409
|
+
association :category, factory: %i[category haircuts]
|
|
1410
|
+
end
|
|
1411
|
+
|
|
1412
|
+
# ── Color Services ─────────────────────────────────────────
|
|
1413
|
+
|
|
1414
|
+
trait :full_color do
|
|
1415
|
+
name { "Full Color" }
|
|
1416
|
+
price { 12_000 }
|
|
1417
|
+
sku { "SPA-CLR-001" }
|
|
1418
|
+
unit { "session" }
|
|
1419
|
+
metadata { { "duration_minutes" => 120 } }
|
|
1420
|
+
association :category, factory: %i[category color_services]
|
|
1421
|
+
end
|
|
1422
|
+
|
|
1423
|
+
trait :partial_highlights do
|
|
1424
|
+
name { "Highlights (Partial)" }
|
|
1425
|
+
price { 9000 }
|
|
1426
|
+
sku { "SPA-CLR-002" }
|
|
1427
|
+
unit { "session" }
|
|
1428
|
+
metadata { { "duration_minutes" => 90 } }
|
|
1429
|
+
association :category, factory: %i[category color_services]
|
|
1430
|
+
end
|
|
1431
|
+
|
|
1432
|
+
trait :full_highlights do
|
|
1433
|
+
name { "Highlights (Full)" }
|
|
1434
|
+
price { 15_000 }
|
|
1435
|
+
sku { "SPA-CLR-003" }
|
|
1436
|
+
unit { "session" }
|
|
1437
|
+
metadata { { "duration_minutes" => 120 } }
|
|
1438
|
+
association :category, factory: %i[category color_services]
|
|
1439
|
+
end
|
|
1440
|
+
|
|
1441
|
+
trait :balayage do
|
|
1442
|
+
name { "Balayage" }
|
|
1443
|
+
price { 18_000 }
|
|
1444
|
+
sku { "SPA-CLR-004" }
|
|
1445
|
+
unit { "session" }
|
|
1446
|
+
metadata { { "duration_minutes" => 150 } }
|
|
1447
|
+
association :category, factory: %i[category color_services]
|
|
1448
|
+
end
|
|
1449
|
+
|
|
1450
|
+
# ── Spa Treatments ─────────────────────────────────────────
|
|
1451
|
+
|
|
1452
|
+
trait :swedish_massage do
|
|
1453
|
+
name { "Swedish Massage (60min)" }
|
|
1454
|
+
price { 9500 }
|
|
1455
|
+
sku { "SPA-SPA-001" }
|
|
1456
|
+
unit { "hour" }
|
|
1457
|
+
metadata { { "duration_minutes" => 60 } }
|
|
1458
|
+
association :category, factory: %i[category spa_treatments]
|
|
1459
|
+
end
|
|
1460
|
+
|
|
1461
|
+
trait :deep_tissue_massage do
|
|
1462
|
+
name { "Deep Tissue Massage (60min)" }
|
|
1463
|
+
price { 11_000 }
|
|
1464
|
+
sku { "SPA-SPA-002" }
|
|
1465
|
+
unit { "hour" }
|
|
1466
|
+
metadata { { "duration_minutes" => 60 } }
|
|
1467
|
+
association :category, factory: %i[category spa_treatments]
|
|
1468
|
+
end
|
|
1469
|
+
|
|
1470
|
+
trait :hot_stone_massage do
|
|
1471
|
+
name { "Hot Stone Massage (60min)" }
|
|
1472
|
+
price { 12_000 }
|
|
1473
|
+
sku { "SPA-SPA-003" }
|
|
1474
|
+
unit { "hour" }
|
|
1475
|
+
metadata { { "duration_minutes" => 60 } }
|
|
1476
|
+
association :category, factory: %i[category spa_treatments]
|
|
1477
|
+
end
|
|
1478
|
+
|
|
1479
|
+
trait :facial do
|
|
1480
|
+
name { "Facial (60min)" }
|
|
1481
|
+
price { 8500 }
|
|
1482
|
+
sku { "SPA-SPA-004" }
|
|
1483
|
+
unit { "hour" }
|
|
1484
|
+
metadata { { "duration_minutes" => 60 } }
|
|
1485
|
+
association :category, factory: %i[category spa_treatments]
|
|
1486
|
+
end
|
|
1487
|
+
|
|
1488
|
+
# ── Nail Services ──────────────────────────────────────────
|
|
1489
|
+
|
|
1490
|
+
trait :manicure do
|
|
1491
|
+
name { "Manicure" }
|
|
1492
|
+
price { 2500 }
|
|
1493
|
+
sku { "SPA-NAL-001" }
|
|
1494
|
+
unit { "session" }
|
|
1495
|
+
metadata { { "duration_minutes" => 30 } }
|
|
1496
|
+
association :category, factory: %i[category nail_services]
|
|
1497
|
+
end
|
|
1498
|
+
|
|
1499
|
+
trait :pedicure do
|
|
1500
|
+
name { "Pedicure" }
|
|
1501
|
+
price { 3500 }
|
|
1502
|
+
sku { "SPA-NAL-002" }
|
|
1503
|
+
unit { "session" }
|
|
1504
|
+
metadata { { "duration_minutes" => 45 } }
|
|
1505
|
+
association :category, factory: %i[category nail_services]
|
|
1506
|
+
end
|
|
1507
|
+
|
|
1508
|
+
trait :gel_manicure do
|
|
1509
|
+
name { "Gel Manicure" }
|
|
1510
|
+
price { 4000 }
|
|
1511
|
+
sku { "SPA-NAL-003" }
|
|
1512
|
+
unit { "session" }
|
|
1513
|
+
metadata { { "duration_minutes" => 45 } }
|
|
1514
|
+
association :category, factory: %i[category nail_services]
|
|
1515
|
+
end
|
|
1516
|
+
|
|
1517
|
+
trait :acrylic_full_set do
|
|
1518
|
+
name { "Acrylic Full Set" }
|
|
1519
|
+
price { 5500 }
|
|
1520
|
+
sku { "SPA-NAL-004" }
|
|
1521
|
+
unit { "session" }
|
|
1522
|
+
metadata { { "duration_minutes" => 60 } }
|
|
1523
|
+
association :category, factory: %i[category nail_services]
|
|
1524
|
+
end
|
|
1525
|
+
end
|
|
1526
|
+
end
|