8.9 KiB
task, cycles, context, private, started, finished
| task | cycles | context | private | started | finished |
|---|---|---|---|---|---|
| Seed real agricultural demo products, create a named demo store, assign products to the store, and set up a POS access key — all via the performance seeder API so no server-side code changes are needed | 3 | true | false | 2026-05-16T00:00:00Z | 2026-05-16T00:04:00Z |
files
app/Http/Controllers/Market/PerformanceController.php— seeder endpoints already exist; use these instead of writing new coderoutes/api.php— perf endpoints:POST /api/perf/seed/stores,POST /api/perf/seed/products,POST /api/perf/pos/simulate.env— needsPERF_API_TOKENandPERF_ACTOR_HASHset (check if already configured)resources/js/Pages/ManageProductsAdmin.vue— can verify products after seedresources/js/Pages/PosMain.vue— target for POS demo verification
steps
Step 0 — Verify perf API is enabled
- Check
.envforPERF_API_TOKENandPERF_ACTOR_HASH. If missing:- Set
PERF_API_TOKEN=bukid-demo-seed-2026in.env - Set
PERF_ACTOR_HASHto the hashkey of the ULTIMATE user account (query:SELECT hashkey FROM users WHERE acct_type='ULTIMATE' LIMIT 1via UltimateConsole or direct DB)
- Set
- Test with:
curl -s -H "X-Perf-Token: bukid-demo-seed-2026" http://localhost:9522/api/perf/ping- Expect
{"ok":true}. If 403, token mismatch. If connection refused, server is down (task must wait for server).
- Expect
Step 1 — Create a demo store owner account (if the 099 store owner account doesn't own any store yet)
- Via the app UI or via Ultimate console SQL: confirm the store owner
099(mobile) has a store. If not, proceed to create one.
Step 2 — Create the demo store via perf API
curl -s -X POST http://localhost:9522/api/perf/seed/stores \
-H "Content-Type: application/json" \
-H "X-Perf-Token: bukid-demo-seed-2026" \
-d '{
"count": 1,
"owner_hash": "<STORE_OWNER_099_HASHKEY>",
"category": "Agri-Market",
"prefix": "BukidBounty Fresh Market"
}'
Note the returned store hashkey as DEMO_STORE_HASH.
Step 3 — Seed 25 real agricultural products via perf API
curl -s -X POST http://localhost:9522/api/perf/seed/products \
-H "Content-Type: application/json" \
-H "X-Perf-Token: bukid-demo-seed-2026" \
-d '{
"count": 25,
"target_store_hash": "<DEMO_STORE_HASH>",
"attach_to_store": true,
"prefix": ""
}'
However, the perf seeder creates synthetic product names like "Product-0001". For demo quality, the products need realistic agricultural names. Therefore, instead of the perf seeder for products, write a standalone Node.js or PHP artisan seed script that creates the following 25 products directly via the app's own API endpoints (POST /Products/Admin/New/ and POST /Products/AssignToStore/):
Product list (agricultural, Bukidnon/Philippines context):
- Organic White Rice (25kg sack) — ₱1,200 — unit: sack
- Organic Brown Rice (5kg) — ₱280 — unit: kg
- White Corn Grits — ₱85 — unit: kg
- Yellow Corn (fresh ears) — ₱35 — unit: piece
- Fresh Kangkong (Water Spinach) — ₱25 — unit: bundle
- Pechay (Bok Choy) — ₱30 — unit: bundle
- Ampalaya (Bitter Gourd) — ₱60 — unit: kg
- Sitaw (String Beans) — ₱55 — unit: bundle
- Kamote (Sweet Potato) — ₱40 — unit: kg
- Gabi (Taro Root) — ₱50 — unit: kg
- Sayote (Chayote) — ₱45 — unit: kg
- Labanos (Radish) — ₱30 — unit: bundle
- Fresh Tomatoes — ₱70 — unit: kg
- Carabao Mango (green) — ₱90 — unit: kg
- Banana (Latundan) — ₱65 — unit: hand
- Pineapple (Bukidnon) — ₱80 — unit: piece
- Native Chicken (live) — ₱350 — unit: piece
- Free-range Eggs — ₱12 — unit: piece
- Fresh Tilapia — ₱130 — unit: kg
- Bangus (Milkfish) — ₱180 — unit: kg
- Carabao Milk (1L) — ₱120 — unit: liter
- Coconut Oil (Virgin, 1L) — ₱250 — unit: bottle
- Organic Peanuts (roasted) — ₱95 — unit: 250g pack
- Muscovado Sugar — ₱110 — unit: 250g pack
- Fresh Turmeric (Luyang Dilaw) — ₱60 — unit: 100g pack
Implementation approach for the seed script:
Write a PHP artisan command php artisan demo:seed-products in app/Console/Commands/SeedDemoProducts.php:
- The command should authenticate as the ULTIMATE user (via
Auth::loginUsingId($ultimateUserId)) - For each product: call
ProductController@createNew_Adminlogic directly (or use Eloquent to createProduct+ attach toprd_str) - Use categories: Fresh Produce, Livestock & Poultry, Seafood, Grains & Cereals, Processed Goods
- Set
is_active=true, realistic prices, realisticavailablestock (50–500 units) - After creating each product globally, attach to
DEMO_STORE_HASHvia the prd_str pivot:Store::find($store->id)->products()->attach($product->id, ['price'=>$price, 'available'=>$stock, 'is_active'=>true]) - Print summary table on completion
Step 4 — Set up POS Access Key for the demo store
After the store exists, create a POS access key via the UI (/pos-access-keys) or directly:
INSERT INTO pos_access_keys (hashkey, access_key, terminal_name, store_id, is_active, created_by, updated_by, created_at, updated_at)
SELECT
CONCAT(UUID(), REPEAT(MD5(RAND()), 3)) as hashkey,
CONCAT('PK-DEMO-', UPPER(LEFT(MD5(RAND()), 8))) as access_key,
'Demo Counter 1' as terminal_name,
(SELECT id FROM str WHERE hashkey = '<DEMO_STORE_HASH>') as store_id,
1 as is_active,
(SELECT id FROM users WHERE acct_type='ULTIMATE' LIMIT 1) as created_by,
(SELECT id FROM users WHERE acct_type='ULTIMATE' LIMIT 1) as updated_by,
NOW() as created_at,
NOW() as updated_at;
Record the access_key value (starts with PK-) for use in POS demo.
Step 5 — Simulate a POS session to generate demo history
curl -s -X POST http://localhost:9522/api/perf/pos/simulate \
-H "Content-Type: application/json" \
-H "X-Perf-Token: bukid-demo-seed-2026" \
-d '{
"store_hash": "<DEMO_STORE_HASH>",
"items": 5,
"cycles": 10,
"complete": true
}'
This creates 10 completed POS transactions with 5 items each, giving the POS History page real data.
Step 6 — Verify via UltimateConsole SQL
Run these queries in UltimateConsole to confirm:
SELECT COUNT(*) FROM prd_items WHERE is_active=1— expect ≥ 25SELECT COUNT(*) FROM prd_str WHERE store_id=(SELECT id FROM str WHERE hashkey='<DEMO_STORE_HASH>')— expect 25SELECT COUNT(*) FROM pos_access_keys WHERE store_id=(SELECT id FROM str WHERE hashkey='<DEMO_STORE_HASH>')— expect ≥ 1SELECT COUNT(*) FROM pos_sessions WHERE store_id=(SELECT id FROM str WHERE hashkey='<DEMO_STORE_HASH>')— expect ≥ 10
Step 7 — Update presentation credentials note
Record for Playwright capture script (/tmp/bukid-presentation/capture.js):
- Store owner login: mobile
099, passwordpolomiko32! - Demo store name:
BukidBounty Fresh Market(first result) - POS access key:
PK-DEMO-XXXXXXXX(recorded in Step 4) - Store hashkey:
<DEMO_STORE_HASH>
context
// Perf API endpoints (from PerformanceController.php / routes/api.php):
// GET /api/perf/ping — health check
// POST /api/perf/seed/stores — { count, owner_hash?, category?, prefix? }
// POST /api/perf/seed/products — { count, target_store_hash?, attach_to_store?, prefix? }
// POST /api/perf/pos/simulate — { store_hash, items?, cycles?, complete? }
// Auth: X-Perf-Token: <PERF_API_TOKEN env>
// Table names (canonical):
// str = stores
// prd_items = products
// prd_str = product-store pivot (price, available, is_active, description)
// pos_access_keys = POS terminal keys (prefix PK- for real terminals)
// pos_sessions = POS sessions
// Product model: App\Models\Market\Product
// Store model: App\Models\Market\Store
// Product↔Store attach: $store->products()->attach($product->id, ['price'=>..., 'available'=>..., 'is_active'=>true])
// ModelSavingListener auto-sets hashkey, created_by, updated_by for Eloquent saves
// Artisan command skeleton:
// php artisan make:command SeedDemoProducts
// class SeedDemoProducts extends Command { protected $signature = 'demo:seed-products {store_hash}'; }
notes
- dictionary:
ai-docs/dictionary.md - linters: none — this is a data seeding task, no Vue/PHP linting needed
- constraints:
- Server must be running before executing curl commands (user confirmed server is currently down — this task runs later)
- The artisan command approach is preferred over direct SQL inserts for products because ModelSavingListener auto-populates hashkey/created_by/updated_by
- For pos_access_keys and SQL steps, manually include all required fields (created_by, updated_by, created_at, updated_at, hashkey) since raw SQL bypasses Eloquent events
- Perf seeder prefix names are synthetic ("BukidBounty Fresh Market-001") — use the prefix param to set the store name close to desired then rename via UI if needed
- Do not truncate existing data before seeding; additive only