Remove user-app v1 and ship pending order, auth, and app fixes.
Drop the duplicate customer app from the monorepo and keep user-app-v2 as the only app; include order pricing, admin cart, OTP/SMS, and dashboard cache updates. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -109,7 +109,7 @@ describe('OrdersService.createOrder — order ban', () => {
|
||||
|
||||
/** MON-08 (owner ruling 2026-10-08): an app order is priced by the server, never by the app. */
|
||||
describe('OrdersService.createOrder — server-side making charge', () => {
|
||||
function build() {
|
||||
function build(rialWage?: number | string | null) {
|
||||
const created: Record<string, any>[] = [];
|
||||
const tx = {
|
||||
order: {
|
||||
@@ -124,7 +124,13 @@ describe('OrdersService.createOrder — server-side making charge', () => {
|
||||
customer: { findUnique: jest.fn(async () => ({ id: 'c1', canPlaceOrders: true, referredByAgentId: null, goldDebtGrams: new Prisma.Decimal(0), goldCreditLimitGrams: new Prisma.Decimal(1000) })) },
|
||||
$transaction: jest.fn(async (fn: (t: typeof tx) => unknown) => fn(tx)),
|
||||
};
|
||||
const catalog = { getVariantOrThrow: jest.fn(async () => ({ id: 'v1', rashWeightGrams: '10' })) };
|
||||
const catalog = {
|
||||
getVariantOrThrow: jest.fn(async () => ({
|
||||
id: 'v1',
|
||||
rashWeightGrams: '10',
|
||||
...(rialWage !== undefined ? { rialWage } : {}),
|
||||
})),
|
||||
};
|
||||
const service = new OrdersService(prisma as never, catalog as never, {} as never, { orderStatusReached: jest.fn() } as never, wageStub as never, smsStub as never);
|
||||
return { service, created };
|
||||
}
|
||||
@@ -145,6 +151,35 @@ describe('OrdersService.createOrder — server-side making charge', () => {
|
||||
expect(created[0].flatRialCharge.toString()).toBe('999');
|
||||
});
|
||||
|
||||
it('charges the variant rial wage on an app order and ignores a tampered body', async () => {
|
||||
const warn = jest.spyOn(Logger.prototype, 'warn').mockImplementation(() => undefined);
|
||||
try {
|
||||
const { service, created } = build(500000);
|
||||
await service.createOrder(tampered, 'c1', { placedBy: 'customer' });
|
||||
expect(created[0].items.create[0].flatRialCharge.toString()).toBe('500000');
|
||||
expect(created[0].flatRialCharge.toString()).toBe('500000');
|
||||
const lines = warn.mock.calls.map((c) => String(c[0])).join('\n');
|
||||
expect(lines).toContain('flatRialCharge sent=999 used=500000');
|
||||
} finally {
|
||||
warn.mockRestore();
|
||||
}
|
||||
});
|
||||
|
||||
it('keeps an operator rial figure when the variant has its own wage', async () => {
|
||||
const { service, created } = build(500000);
|
||||
await service.createOrder(tampered, 'c1', { placedBy: 'operator' });
|
||||
expect(created[0].items.create[0].flatRialCharge.toString()).toBe('999');
|
||||
expect(created[0].flatRialCharge.toString()).toBe('999');
|
||||
});
|
||||
|
||||
it('copies the variant rial wage when an operator omits the field', async () => {
|
||||
const omitted = { items: [{ productVariantId: 'v1', quantity: 2, wagePercent: 10 }] } as never;
|
||||
const { service, created } = build(500000);
|
||||
await service.createOrder(omitted, 'c1', { placedBy: 'operator' });
|
||||
expect(created[0].items.create[0].flatRialCharge.toString()).toBe('500000');
|
||||
expect(created[0].flatRialCharge.toString()).toBe('1000000');
|
||||
});
|
||||
|
||||
/**
|
||||
* MON-08 step 3 (owner ruling): «تست مقایسهای که نشان دهد نتیجه برای کاربر
|
||||
* عادی یکسان است». An unmodified app sends what the server derives
|
||||
|
||||
Reference in New Issue
Block a user