updates on the zone fix

This commit is contained in:
2026-10-06 19:33:02 +05:30
parent 7aca6a6a48
commit 21775fe6f9
3 changed files with 25 additions and 36 deletions

View File

@@ -23,15 +23,11 @@ export function ZoneProvider({ children }) {
const tenantId = user?.tenantid || localStorage.getItem('tenantid') || ''; const tenantId = user?.tenantid || localStorage.getItem('tenantid') || '';
const isTenantUser = Boolean(tenantId && tenantId !== '0'); const isTenantUser = Boolean(tenantId && tenantId !== '0');
// A client login's city (from the login response), used to offer them the // Staff see Doormile's hubs. A client sees ONLY its own locations (kitchens,
// Doormile hubs of their own city. Missing on a session signed in before the // depots). Doormile's hubs used to be appended for the client's city, and
// backend sent it, in which case every active hub is offered. // for every city whenever the session carried no city (any login made
const clientCityId = user?.applocationid != null && String(user.applocationid) !== '0' ? String(user.applocationid) : ''; // before the backend sent one), which is how a Coimbatore client ended up
// offered Hyderabad and Bangalore hubs.
// Staff see Doormile's hubs. A client sees their own locations (kitchens,
// depots) AND the Doormile hubs of their city: a newly onboarded client had
// no locations at all, so their zone list was just "All Zones" and the
// Coimbatore hub their orders run through never appeared.
const { data: rawHubs = [], isLoading: isHubsLoading, refetch: refetchHubs } = useHubs(); const { data: rawHubs = [], isLoading: isHubsLoading, refetch: refetchHubs } = useHubs();
const { data: tenantLocations = [], isLoading: isLocationsLoading, refetch: refetchLocations } = useTenantLocations( const { data: tenantLocations = [], isLoading: isLocationsLoading, refetch: refetchLocations } = useTenantLocations(
isTenantUser ? tenantId : null, isTenantUser ? tenantId : null,
@@ -72,14 +68,11 @@ export function ZoneProvider({ children }) {
isTenantLocation: true, isTenantLocation: true,
status: 'Active', status: 'Active',
})); }));
const cityHubs = clientCityId return own;
? doormileHubs.filter((hub) => String(hub.applocationid ?? '') === clientCityId)
: doormileHubs;
return [...own, ...cityHubs];
} }
return doormileHubs; return doormileHubs;
}, [isTenantUser, tenantLocations, rawHubs, clientCityId]); }, [isTenantUser, tenantLocations, rawHubs]);
const zones = useMemo(() => { const zones = useMemo(() => {
return [ALL_ZONE, ...activeHubs]; return [ALL_ZONE, ...activeHubs];

View File

@@ -79,34 +79,35 @@ describe('ZoneContext', () => {
longitude: 77.6408 longitude: 77.6408
}; };
// A client sees their own locations first, then the Doormile hubs. A newly // A client sees only its own locations, never Doormile's hubs.
// onboarded client used to have no locations and therefore no zones at all it('should offer the tenant only its own locations', () => {
// — not even the Coimbatore hub their orders run through.
it('should offer the tenant own locations and then the Doormile hubs', () => {
const { result } = setup({ user: { tenantid: '4' }, locations: [LOCATION] }); const { result } = setup({ user: { tenantid: '4' }, locations: [LOCATION] });
expect(result.current.isTenantUser).toBe(true); expect(result.current.isTenantUser).toBe(true);
expect(result.current.zones.map((z) => z.hubname)).toEqual(['All Zones', 'Indiranagar Kitchen', 'Koramangala Hub']); expect(result.current.zones.map((z) => z.hubname)).toEqual(['All Zones', 'Indiranagar Kitchen']);
expect(result.current.zones[1].hubtype).toBe('kitchen_hub'); expect(result.current.zones[1].hubtype).toBe('kitchen_hub');
expect(result.current.zones[1].isTenantLocation).toBe(true); expect(result.current.zones[1].isTenantLocation).toBe(true);
expect(result.current.zones[2].isTenantLocation).toBeFalsy();
}); });
it('should prefix a location zone id so it cannot collide with a hub id', () => { it('should prefix a location zone id so it cannot collide with a hub id', () => {
const { result } = setup({ user: { tenantid: '4' }, locations: [{ ...LOCATION, tenantlocationid: 2 }] }); const { result } = setup({ user: { tenantid: '4' }, locations: [{ ...LOCATION, tenantlocationid: 2 }] });
expect(result.current.zones.map((z) => z.hubid)).toEqual(['all', 'loc:2', '2']); expect(result.current.zones.map((z) => z.hubid)).toEqual(['all', 'loc:2']);
expect(result.current.zones[1].locationid).toBe('2'); expect(result.current.zones[1].locationid).toBe('2');
}); });
it('should offer only the hubs of the client own city when the login carries it', () => { // The Sai's Kitchen report: a Coimbatore client was offered Hyderabad and
// Bangalore hubs, because a session without a city fell back to every hub.
it('should never offer Doormile hubs to a client, with or without a city', () => {
const CBE = { ...KORAMANGALA, hubid: '7', hubname: 'Coimbatore Neptune Hub', applocationid: 1 }; const CBE = { ...KORAMANGALA, hubid: '7', hubname: 'Coimbatore Neptune Hub', applocationid: 1 };
const BLR = { ...KORAMANGALA, applocationid: 3 }; const HYD = { ...KORAMANGALA, hubid: '8', hubname: 'Hyderabad Mars Hub', applocationid: 2 };
const { result } = setup({ user: { tenantid: '4', applocationid: 1 }, hubs: [CBE, BLR] }); for (const user of [{ tenantid: '4', applocationid: 1 }, { tenantid: '4' }]) {
expect(result.current.zones.map((z) => z.hubname)).toEqual(['All Zones', 'Coimbatore Neptune Hub']); const { result } = setup({ user, hubs: [CBE, HYD, KORAMANGALA], locations: [LOCATION] });
expect(result.current.zones.map((z) => z.hubname)).toEqual(['All Zones', 'Indiranagar Kitchen']);
}
}); });
it('should still show the hubs to a client with no locations yet', () => { it('should show a client with no locations yet only All Zones', () => {
const { result } = setup({ user: { tenantid: '4' }, locations: [] }); const { result } = setup({ user: { tenantid: '4' }, locations: [] });
expect(result.current.zones.map((z) => z.hubname)).toEqual(['All Zones', 'Koramangala Hub']); expect(result.current.zones.map((z) => z.hubname)).toEqual(['All Zones']);
}); });
it('should scope the location query to the operator own tenant', () => { it('should scope the location query to the operator own tenant', () => {

View File

@@ -104,16 +104,11 @@ describe('a tenant session never matches on a hub id', () => {
})).toBe(true); })).toBe(true);
}); });
it('a client who picks a Doormile HUB is matched on hub ids, never on location ids', () => { it('a client cannot pick a Doormile hub: a stale hub id falls back to All Zones', () => {
const { result } = setup({ user: { tenantid: '13' }, locations: [KITCHEN] }); const { result } = setup({ user: { tenantid: '13' }, locations: [KITCHEN] });
expect(inZone(result, '5', { expect(result.current.zones.map((z) => z.hubid)).not.toContain('5');
bookingid: 5, bookingno: 'DM-H', tenantid: '13', pickuphubid: 5, act(() => result.current.setSelectedZoneId('5'));
pickupaddress: 'Gate 3', deliveryaddress: 'Block C' expect(result.current.isAllZones).toBe(true);
})).toBe(true);
expect(inZone(result, '5', {
bookingid: 6, bookingno: 'DM-L', tenantid: '13', tenantlocationid: 5,
pickupaddress: 'Gate 3', deliveryaddress: 'Block C'
})).toBe(false);
}); });
it("never shows a client another tenant's order, whatever zone is picked", () => { it("never shows a client another tenant's order, whatever zone is picked", () => {