fix(auth): align demo staff phone identity and clock-in payload
This commit is contained in:
@@ -630,8 +630,14 @@ export async function listTodayShifts(actorUid) {
|
||||
SELECT
|
||||
a.id AS "assignmentId",
|
||||
s.id AS "shiftId",
|
||||
COALESCE(s.title, sr.role_name || ' shift') AS title,
|
||||
b.business_name AS "clientName",
|
||||
ROUND(COALESCE(sr.pay_rate_cents, 0)::numeric / 100, 2) AS "hourlyRate",
|
||||
sr.role_name AS "roleName",
|
||||
COALESCE(cp.label, s.location_name) AS location,
|
||||
COALESCE(s.location_address, cp.address) AS "locationAddress",
|
||||
COALESCE(s.latitude, cp.latitude) AS latitude,
|
||||
COALESCE(s.longitude, cp.longitude) AS longitude,
|
||||
s.starts_at AS "startTime",
|
||||
s.ends_at AS "endTime",
|
||||
COALESCE(s.clock_in_mode, cp.default_clock_in_mode, 'EITHER') AS "clockInMode",
|
||||
@@ -643,6 +649,7 @@ export async function listTodayShifts(actorUid) {
|
||||
FROM assignments a
|
||||
JOIN shifts s ON s.id = a.shift_id
|
||||
JOIN shift_roles sr ON sr.id = a.shift_role_id
|
||||
JOIN businesses b ON b.id = s.business_id
|
||||
LEFT JOIN clock_points cp ON cp.id = s.clock_point_id
|
||||
LEFT JOIN attendance_sessions ON attendance_sessions.assignment_id = a.id
|
||||
WHERE a.tenant_id = $1
|
||||
|
||||
@@ -1,10 +1,24 @@
|
||||
import { signInWithPassword, signUpWithPassword } from '../src/services/identity-toolkit.js';
|
||||
import { applicationDefault, getApps, initializeApp } from 'firebase-admin/app';
|
||||
import { getAuth } from 'firebase-admin/auth';
|
||||
|
||||
const ownerEmail = process.env.V2_DEMO_OWNER_EMAIL || 'legendary.owner+v2@krowd.com';
|
||||
const staffEmail = process.env.V2_DEMO_STAFF_EMAIL || 'ana.barista+v2@krowd.com';
|
||||
const staffPhone = process.env.V2_DEMO_STAFF_PHONE || '+15557654321';
|
||||
const ownerPassword = process.env.V2_DEMO_OWNER_PASSWORD || 'Demo2026!';
|
||||
const staffPassword = process.env.V2_DEMO_STAFF_PASSWORD || 'Demo2026!';
|
||||
|
||||
function ensureAdminApp() {
|
||||
if (getApps().length === 0) {
|
||||
initializeApp({ credential: applicationDefault() });
|
||||
}
|
||||
}
|
||||
|
||||
function getAdminAuth() {
|
||||
ensureAdminApp();
|
||||
return getAuth();
|
||||
}
|
||||
|
||||
async function ensureUser({ email, password, displayName }) {
|
||||
try {
|
||||
const signedIn = await signInWithPassword({ email, password });
|
||||
@@ -40,6 +54,44 @@ async function ensureUser({ email, password, displayName }) {
|
||||
}
|
||||
}
|
||||
|
||||
async function getUserByPhoneNumber(phoneNumber) {
|
||||
try {
|
||||
return await getAdminAuth().getUserByPhoneNumber(phoneNumber);
|
||||
} catch (error) {
|
||||
if (error?.code === 'auth/user-not-found') return null;
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
async function reconcileStaffPhoneIdentity({ uid, email, displayName, phoneNumber }) {
|
||||
const auth = getAdminAuth();
|
||||
const current = await auth.getUser(uid);
|
||||
const existingPhoneUser = await getUserByPhoneNumber(phoneNumber);
|
||||
let deletedConflictingUid = null;
|
||||
|
||||
if (existingPhoneUser && existingPhoneUser.uid !== uid) {
|
||||
deletedConflictingUid = existingPhoneUser.uid;
|
||||
await auth.deleteUser(existingPhoneUser.uid);
|
||||
}
|
||||
|
||||
const updatePayload = {};
|
||||
if (current.displayName !== displayName) updatePayload.displayName = displayName;
|
||||
if (current.email !== email) updatePayload.email = email;
|
||||
if (current.phoneNumber !== phoneNumber) updatePayload.phoneNumber = phoneNumber;
|
||||
|
||||
if (Object.keys(updatePayload).length > 0) {
|
||||
await auth.updateUser(uid, updatePayload);
|
||||
}
|
||||
|
||||
const reconciled = await auth.getUser(uid);
|
||||
return {
|
||||
uid: reconciled.uid,
|
||||
email: reconciled.email,
|
||||
phoneNumber: reconciled.phoneNumber,
|
||||
deletedConflictingUid,
|
||||
};
|
||||
}
|
||||
|
||||
async function main() {
|
||||
const owner = await ensureUser({
|
||||
email: ownerEmail,
|
||||
@@ -53,8 +105,15 @@ async function main() {
|
||||
displayName: 'Ana Barista V2',
|
||||
});
|
||||
|
||||
const reconciledStaff = await reconcileStaffPhoneIdentity({
|
||||
uid: staff.uid,
|
||||
email: staff.email,
|
||||
displayName: staff.displayName,
|
||||
phoneNumber: staffPhone,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(JSON.stringify({ owner, staff }, null, 2));
|
||||
console.log(JSON.stringify({ owner, staff: { ...staff, ...reconciledStaff } }, null, 2));
|
||||
}
|
||||
|
||||
main().catch((error) => {
|
||||
|
||||
@@ -631,6 +631,10 @@ async function main() {
|
||||
assert.ok(Array.isArray(todaysShifts.items));
|
||||
const assignedTodayShift = todaysShifts.items.find((shift) => shift.shiftId === fixture.shifts.assigned.id);
|
||||
assert.ok(assignedTodayShift);
|
||||
assert.equal(assignedTodayShift.clientName, fixture.business.name);
|
||||
assert.equal(typeof assignedTodayShift.hourlyRate, 'number');
|
||||
assert.equal(typeof assignedTodayShift.latitude, 'number');
|
||||
assert.equal(typeof assignedTodayShift.longitude, 'number');
|
||||
assert.equal(assignedTodayShift.clockInMode, fixture.shifts.assigned.clockInMode);
|
||||
assert.equal(assignedTodayShift.allowClockInOverride, fixture.shifts.assigned.allowClockInOverride);
|
||||
logStep('staff.clock-in.shifts-today.ok', { count: todaysShifts.items.length });
|
||||
|
||||
Reference in New Issue
Block a user