fix(experts): an expert edited in the panel now shows up in the app
The app shows a sales expert their own account through the linked trading Customer row (/customer/me). That row was seeded from the expert once, at first sign-in, and never updated again, so a name, mobile, credit-limit or wage-percent change made in the panel never reached the app. In the reference the agent and that account were one row, so an edit changed both. Editing an expert now mirrors exactly the changed fields onto the trading row in the same transaction: name parts, credit limit (gram_level), wage percent, and the mobile when no other customer holds it. Existing drift heals on the next save. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
600ce06d15
commit
ee43d664d5
@@ -0,0 +1,91 @@
|
||||
import { Prisma } from '@prisma/client';
|
||||
import { AdminUsersService } from './admin-users.service';
|
||||
|
||||
/**
|
||||
* Editing a sales expert in the panel must reach the app: the app shows the
|
||||
* expert their own account through the linked trading Customer row, which is
|
||||
* only seeded once at first sign-in.
|
||||
*/
|
||||
describe('AdminUsersService — expert edit reaches the trading account', () => {
|
||||
const expertRow = {
|
||||
id: 'exp1',
|
||||
role: 'SALES_EXPERT',
|
||||
fullName: 'سعید اسماعیلی',
|
||||
firstName: 'سعید',
|
||||
lastName: 'اسماعیلی',
|
||||
mobile: '09902560722',
|
||||
wagePercent: new Prisma.Decimal(12),
|
||||
isActive: true,
|
||||
salesExpertProfile: { tradingCustomerId: 'cust1', gramLevel: new Prisma.Decimal(0) },
|
||||
};
|
||||
|
||||
function build(customerHolder: { id: string } | null = null) {
|
||||
const customerUpdate = jest.fn(async () => ({}));
|
||||
const tx = {
|
||||
adminUser: {
|
||||
update: jest.fn(async ({ data }: { data: Record<string, unknown> }) => ({
|
||||
...expertRow,
|
||||
...(data.firstName !== undefined ? { firstName: data.firstName, fullName: `${data.firstName} ${data.lastName}` } : {}),
|
||||
...(data.lastName !== undefined ? { lastName: data.lastName } : {}),
|
||||
...(data.mobile !== undefined ? { mobile: data.mobile } : {}),
|
||||
...(data.wagePercent !== undefined ? { wagePercent: data.wagePercent } : {}),
|
||||
salesExpertProfile: {
|
||||
...expertRow.salesExpertProfile,
|
||||
...((data.salesExpertProfile as { upsert?: { update?: { gramLevel?: Prisma.Decimal } } } | undefined)
|
||||
?.upsert?.update?.gramLevel !== undefined
|
||||
? { gramLevel: (data.salesExpertProfile as { upsert: { update: { gramLevel: Prisma.Decimal } } }).upsert.update.gramLevel }
|
||||
: {}),
|
||||
},
|
||||
})),
|
||||
},
|
||||
customer: { update: customerUpdate, findUnique: jest.fn(async () => customerHolder) },
|
||||
};
|
||||
const prisma = {
|
||||
...tx,
|
||||
admin: { findUnique: jest.fn(async () => null) },
|
||||
adminUser: {
|
||||
...tx.adminUser,
|
||||
findFirst: jest.fn(async () => expertRow),
|
||||
// the expert-table mobile clash check: no other expert holds the number
|
||||
findUnique: jest.fn(async () => null),
|
||||
},
|
||||
$transaction: jest.fn(async (fn: (t: typeof tx) => unknown) => fn(tx)),
|
||||
};
|
||||
const service = new AdminUsersService(prisma as never, {} as never, {} as never);
|
||||
return { service, customerUpdate };
|
||||
}
|
||||
|
||||
it('copies a name change to the trading account', async () => {
|
||||
const { service, customerUpdate } = build();
|
||||
await service.update('exp1', { fname: 'سعید1', lname: 'اسماعیلی1' });
|
||||
expect(customerUpdate).toHaveBeenCalledWith({
|
||||
where: { id: 'cust1' },
|
||||
data: { firstName: 'سعید1', lastName: 'اسماعیلی1' },
|
||||
});
|
||||
});
|
||||
|
||||
it('copies the credit limit and wage percent the operator changed', async () => {
|
||||
const { service, customerUpdate } = build();
|
||||
await service.update('exp1', { gram_level: '50', percent: '3' });
|
||||
const data = (customerUpdate.mock.calls[0] as unknown as [{ data: Record<string, Prisma.Decimal> }])[0].data;
|
||||
expect(data.goldCreditLimitGrams.toString()).toBe('50');
|
||||
expect(data.makingChargeOffsetPercent.toString()).toBe('3');
|
||||
expect(data).not.toHaveProperty('firstName');
|
||||
});
|
||||
|
||||
it('copies a new mobile only when no other customer holds it', async () => {
|
||||
const free = build(null);
|
||||
await free.service.update('exp1', { mobile: '09120001111' });
|
||||
expect(free.customerUpdate).toHaveBeenCalledWith({ where: { id: 'cust1' }, data: { mobile: '09120001111' } });
|
||||
|
||||
const taken = build({ id: 'someone-else' });
|
||||
await taken.service.update('exp1', { mobile: '09120001111' });
|
||||
expect(taken.customerUpdate).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('writes nothing to the trading account when nothing it mirrors changed', async () => {
|
||||
const { service, customerUpdate } = build();
|
||||
await service.update('exp1', { address: 'تهران' });
|
||||
expect(customerUpdate).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user