This commit is contained in:
2026-09-01 12:00:46 +05:30
parent fe78c54eeb
commit a8e0dc069f
20 changed files with 1278 additions and 32 deletions

View File

@@ -43,6 +43,21 @@ export interface CreateBranchRequest {
deliveryradius?: number;
deliverymins?: number;
status?: string;
/**
* Who will run this outlet — an existing person, when one has been hired
* already.
*
* Omitted, the backend spawns a login named after the SHOP, on the shop's
* email address, one per outlet. That was the only option, and it is why two
* people at a counter shared a credential and nothing recorded which of them
* did anything.
*
* A branch must still arrive with SOMEBODY: name a person here, or give an
* `email` to spawn one from. The backend refuses a branch with neither,
* because an outlet nobody can sign in to is a dead end that shows up in
* every list and is noticed by whoever is standing in the shop.
*/
operatorid?: number;
}
export interface TenantListQuery {
@@ -110,7 +125,11 @@ export const tenantsApi = {
api.post<TenantInfo>(`${WEB}/tenants/createtenantuser`, toTenantBody(body)),
/**
* Commissions a branch and spawns its login (roleid 0, empty password).
* Commissions a branch, and gives it somebody to run it.
*
* Pass `operatorid` to place a person you have already hired. Without it the
* backend spawns a login named after the shop, as it always did — kept so
* nothing existing changes, but the named person is the better path.
*
* `createtenantlocation`, not `createlocation`: only this one returns the
* created row, and the new `locationid` is what a QR code and every
@@ -122,6 +141,48 @@ export const tenantsApi = {
updateBranch: (body: Partial<TenantLocation> & { locationid: number }) =>
api.put<TenantLocation>(`${WEB}/tenants/updatelocation`, body),
/**
* A merchant editing their own business record.
*
* The first write path `tenants` has ever had. Before it, everything about a
* shop — its name, its photograph, its licence, how to reach it — was set
* once at onboarding by a Nearle Admin and could never be changed by anyone.
*
* Only merchant-owned columns are written; the backend keeps the allowlist
* and ignores the rest, so `approved`, `status`, `partnerid` and the billing
* fields cannot be set from here even if a caller sends them. Anything
* omitted is left alone rather than blanked.
*/
updateProfile: (body: { tenantid: number } & Partial<TenantInfo>) =>
api.put<unknown>(`${WEB}/tenants/updatetenant`, body),
/**
* One business, by id — how a store login reads its own record.
*
* Not `listAll`. That is `getalltenants`, paginated over 262 merchants, so a
* shop on page two was simply absent and a profile screen built on it would
* show nothing for no visible reason.
*/
byId: (tenantid: number) => api.get<TenantInfo>(`${WEB}/tenants/gettenantinfo`, { tenantid }),
/**
* Somebody editing their own name, mobile or email.
*
* Not `users/update`. That one writes whatever struct it is handed and checks
* only the userid — no tenant, no guard on role or branch — so a self-service
* form built on it would let a branch user promote themselves or move shop.
* This is scoped to the caller's own account AND business, and writes
* identity fields only.
*/
updateOwnProfile: (body: {
userid: number;
tenantid: number;
firstname?: string;
lastname?: string;
contactno?: string;
email?: string;
}) => api.put<unknown>(`${WEB}/tenants/updateownprofile`, body),
};
/**