67 lines
2.4 KiB
TypeScript
67 lines
2.4 KiB
TypeScript
import { Body, Controller, Get, HttpCode, Post, Query } from '@nestjs/common';
|
|||
|
|
import { SalesExpertAppService } from './sales-expert-app.service';
|
||
|
|
import { CurrentCustomer, CustomerAuth } from '../customer-auth/customer.guards';
|
||
|
|
import type { AuthenticatedCustomer } from '../customer-auth/app-principal';
|
||
|
|
|
||
|
|
/**
|
||
|
|
* The sales expert's own screens in the customer apps.
|
||
|
|
*
|
||
|
|
* POST expert/child-orders -> legacy POST /order/child (ApiMobileController:759)
|
||
|
|
* POST expert/my-customers -> legacy POST /my-child (ApiMobileController:184)
|
||
|
|
* GET expert/me -> the expert's profile strip
|
||
|
|
*
|
||
|
|
* Every route sits behind the app token and takes its scope from
|
||
|
|
* `me.adminUserId`, which only a sales-expert token carries. An ordinary
|
||
|
|
* customer's token has it undefined, so the service refuses with 403 — the
|
||
|
|
* apps also hide the menu entries, but the server does not rely on that.
|
||
|
|
*
|
||
|
|
* No route accepts a customer id or an agent id from the client.
|
||
|
|
*/
|
||
|
|
@Controller('expert')
|
||
|
|
export class SalesExpertAppController {
|
||
|
|
constructor(private readonly expert: SalesExpertAppService) {}
|
||
|
|
|
||
|
|
/** Legacy POST /order/child — POST because the reference posted its paging. */
|
||
|
|
@CustomerAuth()
|
||
|
|
@Post('child-orders')
|
||
|
|
@HttpCode(200)
|
||
|
|
childOrders(
|
||
|
|
@Body() body: { page?: number; limit?: number; search?: string | null },
|
||
|
|
@CurrentCustomer() me: AuthenticatedCustomer,
|
||
|
|
) {
|
||
|
|
return this.expert.childOrders(me.adminUserId, body ?? {});
|
||
|
|
}
|
||
|
|
|
||
|
|
/** Legacy POST /my-child. */
|
||
|
|
@CustomerAuth()
|
||
|
|
@Post('my-customers')
|
||
|
|
@HttpCode(200)
|
||
|
|
myCustomers(
|
||
|
|
@Body() body: { search?: string | null; text_search?: string | null },
|
||
|
|
@CurrentCustomer() me: AuthenticatedCustomer,
|
||
|
|
) {
|
||
|
|
// The reference read `text_search` (ApiMobileController.php:186); the
|
||
|
|
// ported screens send `search`. Both accepted.
|
||
|
|
return this.expert.myCustomers(me.adminUserId, {
|
||
|
|
search: body?.search ?? body?.text_search ?? null,
|
||
|
|
});
|
||
|
|
}
|
||
|
|
|
||
|
|
@CustomerAuth()
|
||
|
|
@Get('me')
|
||
|
|
me(@CurrentCustomer() me: AuthenticatedCustomer) {
|
||
|
|
return this.expert.me(me.adminUserId);
|
||
|
|
}
|
||
|
|
|
||
|
|
/**
|
||
|
|
* Whether the signed-in principal is a sales expert. The apps call this once
|
||
|
|
* after login to decide whether to show the two expert entries; the answer
|
||
|
|
* comes from the token, so a customer cannot make it say yes.
|
||
|
|
*/
|
||
|
|
@CustomerAuth()
|
||
|
|
@Get('whoami')
|
||
|
|
whoami(@CurrentCustomer() me: AuthenticatedCustomer) {
|
||
|
|
return { isSalesExpert: Boolean(me.adminUserId), type: me.type };
|
||
|
|
}
|
||
|
|
}
|