Files
tehran_taj/apps/api/src/modules/admin-users/admin-users.expert-sync.spec.ts
T

118 lines
5.2 KiB
TypeScript
Raw Normal View History

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),
// the cross-table check: does a customer (not the expert's own account) hold the number
findFirst: 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' } });
});
it('refuses a new mobile a customer already holds, and writes nothing', async () => {
const taken = build({ id: 'someone-else' });
await expect(taken.service.update('exp1', { mobile: '09120001111' })).rejects.toThrow(
'این شماره موبایل قبلاً برای یک مشتری ثبت شده است',
);
expect(taken.customerUpdate).not.toHaveBeenCalled();
});
it('does not ask about a mobile that is not changing, so an existing duplicate stays editable', async () => {
const { service, customerUpdate } = build({ id: 'someone-else' });
await expect(service.update('exp1', { mobile: '09902560722', fname: 'سعید1', lname: 'اسماعیلی1' })).resolves.toBeDefined();
expect(customerUpdate).toHaveBeenCalledWith({
where: { id: 'cust1' },
data: { firstName: 'سعید1', lastName: 'اسماعیلی1' },
});
});
it('refuses to create an expert on a number a customer holds', async () => {
const { service } = build({ id: 'someone-else' });
await expect(
service.create({ fname: 'علی', lname: 'رضایی', mobile: '09125550000', password: 'secret1', role: 'SALES_EXPERT' }),
).rejects.toThrow('این شماره موبایل قبلاً برای یک مشتری ثبت شده است');
});
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();
});
});