backend requirements onthe xustomer app
This commit is contained in:
170
seed_customer_app.sql
Normal file
170
seed_customer_app.sql
Normal file
@@ -0,0 +1,170 @@
|
||||
-- ============================================================
|
||||
-- Doormile — customer app (doormile_cx) seed data
|
||||
-- Idempotent: safe to re-run (ON CONFLICT DO UPDATE throughout)
|
||||
--
|
||||
-- Seeded to mirror the client's in-app mock exactly, because those cases back
|
||||
-- the app's 18 widget tests and its design QA:
|
||||
-- * Tamil Nadu / Kerala / Karnataka open
|
||||
-- * Puducherry serviceable with NO open district (the "opening soon" state)
|
||||
-- * Madurai / Kozhikode / Mangaluru unavailable, each with a reason
|
||||
-- * At least one fully-booked pickup slot (t5, capacity 0)
|
||||
-- Change any of those and a green test suite stops meaning anything.
|
||||
--
|
||||
-- Run AFTER the Go service has started once, so AutoMigrate has created the
|
||||
-- tables this file fills.
|
||||
-- ============================================================
|
||||
|
||||
-- ── Serviceable states ───────────────────────────────────────────────────────
|
||||
-- districtCount is computed at read time from the districts below, so a state
|
||||
-- listed here with nothing open still returns and carries its transit tag. The
|
||||
-- app hides a state showing 0 rather than the server omitting it.
|
||||
|
||||
INSERT INTO serviceablestates (statecode, statename, transittag, displayorder, status, createdat, updatedat)
|
||||
VALUES
|
||||
('TN', 'Tamil Nadu', 'Ultra-fast transit', 1, 'Active', NOW(), NOW()),
|
||||
('KL', 'Kerala', 'Next-day transit', 2, 'Active', NOW(), NOW()),
|
||||
('KA', 'Karnataka', 'Next-day transit', 3, 'Active', NOW(), NOW()),
|
||||
('TG', 'Telangana', 'Next-day transit', 4, 'Active', NOW(), NOW()),
|
||||
('PY', 'Puducherry', 'Opening soon', 5, 'Active', NOW(), NOW())
|
||||
ON CONFLICT (statecode) DO UPDATE
|
||||
SET statename = EXCLUDED.statename,
|
||||
transittag = EXCLUDED.transittag,
|
||||
displayorder = EXCLUDED.displayorder,
|
||||
status = EXCLUDED.status,
|
||||
updatedat = NOW();
|
||||
|
||||
-- ── Serviceable districts ────────────────────────────────────────────────────
|
||||
-- Unavailable districts are seeded too, and returned by the API. The picker
|
||||
-- filters them out but the app shows their names in a quiet "coming soon" line,
|
||||
-- so deleting them would remove real copy from the screen. `note` is why —
|
||||
-- never left blank on an unavailable row, or the app has to invent a reason.
|
||||
--
|
||||
-- centrelatitude/longitude matter more than they look: only state and district
|
||||
-- are required at booking time, so for most destinations these coordinates are
|
||||
-- the ONLY geography the parcel has until the miler corrects it at the door.
|
||||
-- They price the estimate and they keep the stop out of the 0,0 bucket that
|
||||
-- route sequencing skips.
|
||||
|
||||
INSERT INTO serviceabledistricts
|
||||
(districtcode, statecode, districtname, available, note, promise,
|
||||
centrelatitude, centrelongitude, pincodeprefix, displayorder, createdat, updatedat)
|
||||
VALUES
|
||||
-- Tamil Nadu
|
||||
('TN-CBE', 'TN', 'Coimbatore', TRUE, '', 'Next-day delivery', 11.016845, 76.955832, '641', 1, NOW(), NOW()),
|
||||
('TN-MAA', 'TN', 'Chennai', TRUE, '', 'Next-day delivery', 13.082680, 80.270718, '600', 2, NOW(), NOW()),
|
||||
('TN-SLM', 'TN', 'Salem', TRUE, '', '2-day delivery', 11.664325, 78.146011, '636', 3, NOW(), NOW()),
|
||||
('TN-TRY', 'TN', 'Tiruchirappalli', TRUE, '', '2-day delivery', 10.790483, 78.704674, '620', 4, NOW(), NOW()),
|
||||
('TN-ERD', 'TN', 'Erode', TRUE, '', '2-day delivery', 11.341000, 77.717300, '638', 5, NOW(), NOW()),
|
||||
('TN-KNK', 'TN', 'Kanyakumari', TRUE, '', '2-day delivery', 8.178200, 77.435400, '629', 6, NOW(), NOW()),
|
||||
('TN-MDU', 'TN', 'Madurai', FALSE, 'Opening soon', '', 9.925201, 78.119775, '625', 7, NOW(), NOW()),
|
||||
|
||||
-- Kerala
|
||||
('KL-EKM', 'KL', 'Ernakulam', TRUE, '', 'Next-day delivery', 9.981636, 76.299881, '682', 1, NOW(), NOW()),
|
||||
('KL-TVM', 'KL', 'Thiruvananthapuram', TRUE, '', '2-day delivery', 8.524139, 76.936638, '695', 2, NOW(), NOW()),
|
||||
('KL-TSR', 'KL', 'Thrissur', TRUE, '', '2-day delivery', 10.527640, 76.214402, '680', 3, NOW(), NOW()),
|
||||
('KL-KKD', 'KL', 'Kozhikode', FALSE, 'Opening soon', '', 11.258753, 75.780411, '673', 4, NOW(), NOW()),
|
||||
|
||||
-- Karnataka
|
||||
('KA-BLR', 'KA', 'Bengaluru Urban', TRUE, '', 'Next-day delivery', 12.971599, 77.594566, '560', 1, NOW(), NOW()),
|
||||
('KA-MYS', 'KA', 'Mysuru', TRUE, '', '2-day delivery', 12.295810, 76.639381, '570', 2, NOW(), NOW()),
|
||||
('KA-MNG', 'KA', 'Dakshina Kannada', FALSE, 'Paused this week', '', 12.914142, 74.856000, '575', 3, NOW(), NOW()),
|
||||
|
||||
-- Telangana
|
||||
('TG-HYD', 'TG', 'Hyderabad', TRUE, '', 'Next-day delivery', 17.385044, 78.486671, '500', 1, NOW(), NOW()),
|
||||
|
||||
-- Puducherry: serviceable state, no open district. This is the "Opening
|
||||
-- soon" state the app has a designed screen for, and the only place that
|
||||
-- screen can be exercised.
|
||||
('PY-PDY', 'PY', 'Puducherry', FALSE, 'Opening soon', '', 11.913860, 79.812600, '605', 1, NOW(), NOW())
|
||||
ON CONFLICT (districtcode) DO UPDATE
|
||||
SET statecode = EXCLUDED.statecode,
|
||||
districtname = EXCLUDED.districtname,
|
||||
available = EXCLUDED.available,
|
||||
note = EXCLUDED.note,
|
||||
promise = EXCLUDED.promise,
|
||||
centrelatitude = EXCLUDED.centrelatitude,
|
||||
centrelongitude = EXCLUDED.centrelongitude,
|
||||
pincodeprefix = EXCLUDED.pincodeprefix,
|
||||
displayorder = EXCLUDED.displayorder,
|
||||
updatedat = NOW();
|
||||
|
||||
-- Attach each district to the nearest active hub, so the destination card can
|
||||
-- name a serving base. Done by proximity rather than hard-coded ids because hub
|
||||
-- ids differ between environments and a wrong id is worse than a missing name.
|
||||
UPDATE serviceabledistricts d
|
||||
SET hubid = nearest.hubid
|
||||
FROM LATERAL (
|
||||
SELECT h.hubid
|
||||
FROM hubs h
|
||||
WHERE h.status = 'Active'
|
||||
AND h.deletedat IS NULL
|
||||
AND h.latitude <> 0
|
||||
ORDER BY (h.latitude - d.centrelatitude) ^ 2
|
||||
+ (h.longitude - d.centrelongitude) ^ 2
|
||||
LIMIT 1
|
||||
) AS nearest
|
||||
WHERE d.hubid IS NULL;
|
||||
|
||||
-- ── Pickup slot templates ────────────────────────────────────────────────────
|
||||
-- Roughly six windows a day, which is what the design lays out. The customer
|
||||
-- never sees these rows: the API expands them onto today and tomorrow and mints
|
||||
-- a dated slot id, so a slot the customer picks always resolves back to a real
|
||||
-- preferredpickupfrom/to that the assignment engine can staff.
|
||||
--
|
||||
-- t5 is seeded at capacity 0 on purpose — it is the ONLY way to reach the
|
||||
-- "Fully booked" state in design QA without actually filling a window.
|
||||
|
||||
INSERT INTO pickupslottemplates
|
||||
(code, starthour, startminute, endhour, endminute, capacity, applocationid,
|
||||
tag, caption, displayorder, status, createdat, updatedat)
|
||||
VALUES
|
||||
('t1', 8, 0, 10, 0, 25, NULL, 'Fastest pickup', 'Arriving in approx. 45 mins', 1, 'Active', NOW(), NOW()),
|
||||
('t2', 10, 0, 12, 0, 25, NULL, '', '', 2, 'Active', NOW(), NOW()),
|
||||
('t3', 12, 0, 14, 0, 25, NULL, '', '', 3, 'Active', NOW(), NOW()),
|
||||
('t4', 14, 0, 16, 0, 25, NULL, '', '', 4, 'Active', NOW(), NOW()),
|
||||
('t5', 16, 0, 18, 0, 0, NULL, '', '', 5, 'Active', NOW(), NOW()),
|
||||
('t6', 18, 0, 20, 0, 20, NULL, '', '', 6, 'Active', NOW(), NOW())
|
||||
ON CONFLICT DO NOTHING;
|
||||
|
||||
-- ── Booking limits ───────────────────────────────────────────────────────────
|
||||
-- The global default row. Ops varies these per city by inserting a row with an
|
||||
-- applocationid; the client keeps 20/5 if the call fails, and the server never
|
||||
-- answers 0 for either — a zero cap would reject every booking on the platform.
|
||||
|
||||
-- maxdestinations is seeded at 1 ON PURPOSE, not at the 5 the design allows.
|
||||
--
|
||||
-- The fan-out works server-side, but the deployed rider app keys its stop list
|
||||
-- on `orderid`, which is booking-level — so all three stops of a
|
||||
-- three-destination pickup collapse into one in its local store, and two
|
||||
-- parcels would be left with no stop and no way to close them. Accepting such a
|
||||
-- booking would create work nobody can complete.
|
||||
--
|
||||
-- Because the client reads this value from GET /customer/config/booking-limits
|
||||
-- and adapts, capping it here keeps every pickup single-destination with no
|
||||
-- feature flag and no app release. Raise it to 5 with a single UPDATE once a
|
||||
-- rider build that keys on `consignmentid` is live:
|
||||
--
|
||||
-- UPDATE customerbookinglimits SET maxdestinations = 5 WHERE applocationid IS NULL;
|
||||
--
|
||||
-- Same discipline as MILER_HUB_HANDOVER_ENABLED: never turn on a server
|
||||
-- behaviour the deployed rider app cannot finish.
|
||||
INSERT INTO customerbookinglimits (applocationid, maxpackages, maxdestinations, createdat, updatedat)
|
||||
SELECT NULL, 20, 1, NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM customerbookinglimits WHERE applocationid IS NULL);
|
||||
|
||||
-- ── Test account ─────────────────────────────────────────────────────────────
|
||||
-- Automated tests and design QA cannot receive a real text, and the previous
|
||||
-- end-to-end attempt on this platform stalled for exactly that reason: customer
|
||||
-- login needed an OTP on a real handset and could not be scripted.
|
||||
--
|
||||
-- Pair this row with CX_STAGING_OTP=1234 in the staging environment. That env
|
||||
-- var is refused outright when ENV=production (internal/sms), because a fixed
|
||||
-- code is a skeleton key for every account on the platform.
|
||||
|
||||
INSERT INTO appcustomers (firstname, lastname, phone, email, status, configid, createdat, updatedat)
|
||||
SELECT 'Doormile', 'QA', '+919999900001', 'qa@doormile.com', 'Active', 1001, NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM appcustomers WHERE phone = '+919999900001');
|
||||
|
||||
INSERT INTO appcustomers (firstname, lastname, phone, email, status, configid, createdat, updatedat)
|
||||
SELECT 'Design', 'QA', '+919999900002', 'design.qa@doormile.com', 'Active', 1001, NOW(), NOW()
|
||||
WHERE NOT EXISTS (SELECT 1 FROM appcustomers WHERE phone = '+919999900002');
|
||||
Reference in New Issue
Block a user