feat: add optional inventory package association to service items and implement audit logging
- Added `inventory_package_uuid` and `inventory_package_title` fields to the `ServiceItem` interface. - Updated API documentation to reflect new fields in service item responses. - Implemented methods in `ClinicServiceController` to handle inventory package associations. - Created `ServiceItemAuditLog` entity and repository for tracking changes to service items. - Added functionality to log changes to service items, including inventory package associations. - Implemented tests for attaching/detaching inventory packages and auditing changes. - Created database migrations for new fields and audit log table.
This commit is contained in:
@@ -38,6 +38,10 @@ const mockApi = (item: unknown = ITEM, notFound = false) => {
|
||||
effective_plan: { name: 'professional', level: 2, max_secretaries: 10, features: { services: true } },
|
||||
} });
|
||||
if (url.includes('/payment/config')) return Promise.resolve({ success: true, data: { test_mode: true, gateways: [] } });
|
||||
if (url.includes('/audit-logs')) return Promise.resolve({ success: true, data: [
|
||||
{ uuid: 'l1', field: 'price_rials', operation: 'update', old_value: '7000000', new_value: '8500000', actor_name: 'دکتر تست', created_at: 1_800_000_000 },
|
||||
{ uuid: 'l2', field: 'name', operation: 'create', old_value: null, new_value: 'سرم ۵۰۰cc', actor_name: 'دکتر تست', created_at: 1_700_000_000 },
|
||||
] });
|
||||
if (url.includes('/service-item/')) {
|
||||
return notFound ? Promise.reject(new Error('یافت نشد')) : Promise.resolve({ success: true, data: item });
|
||||
}
|
||||
@@ -51,6 +55,12 @@ const mockApi = (item: unknown = ITEM, notFound = false) => {
|
||||
if (url.includes('/tenant-insurances')) return Promise.resolve({ data: { data: [
|
||||
{ uuid: 'ins1', insurance_name: 'بیمه ایران', insurance_kind: 'basic', coverage_percent: 70 },
|
||||
] } });
|
||||
if (url.includes('/inventory-packages')) return Promise.resolve({ success: true, data: [
|
||||
{
|
||||
uuid: 'pkg1', title: 'پکیج سرم', total: 1_200_000, available: true,
|
||||
items: [{ itemUuid: 'i1', name: 'سرم رینگر', unit: 'عدد', price: 600_000, amount: 2 }],
|
||||
},
|
||||
] });
|
||||
return Promise.resolve({ success: true, data: [] });
|
||||
});
|
||||
};
|
||||
@@ -125,6 +135,35 @@ describe('ServiceDetailPage (جزئیات سرویس)', () => {
|
||||
expect(screen.queryByText('این خدمت شامل بیمه میشود')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('تب کالاهای مرتبط، اقلام پکیج متصل را نشان میدهد', async () => {
|
||||
mockApi({ ...ITEM, inventory_package_uuid: 'pkg1', inventory_package_title: 'پکیج سرم' });
|
||||
render();
|
||||
fireEvent.click(await screen.findByText('کالاهای مرتبط'));
|
||||
|
||||
expect(await screen.findByText('پکیج سرم')).toBeInTheDocument();
|
||||
expect(screen.getByText('سرم رینگر')).toBeInTheDocument();
|
||||
expect(screen.getByText('۲ عدد')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('سرویس بدون پکیج، حالت خالی با لینک انبار میدهد', async () => {
|
||||
render();
|
||||
fireEvent.click(await screen.findByText('کالاهای مرتبط'));
|
||||
|
||||
expect(await screen.findByText('پکیج کالایی به این سرویس متصل نیست')).toBeInTheDocument();
|
||||
expect(screen.getByText('مدیریت انبار')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('تب لاگ تغییرات، مقدار قبل و بعد را خوانا نشان میدهد', async () => {
|
||||
render();
|
||||
fireEvent.click(await screen.findByText('لاگ تغییرات'));
|
||||
|
||||
expect(await screen.findByText('قیمت پایه')).toBeInTheDocument();
|
||||
expect(screen.getByText('۷۰۰٬۰۰۰ تومان')).toBeInTheDocument();
|
||||
expect(screen.getByText('۸۵۰٬۰۰۰ تومان')).toBeInTheDocument();
|
||||
expect(screen.getByText('ایجاد')).toBeInTheDocument();
|
||||
expect(screen.getAllByText(/توسط دکتر تست/).length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
it('سرویس غیرفعال نشان «غیرفعال» و دکمه فعالکردن دارد', async () => {
|
||||
mockApi({ ...ITEM, active: false });
|
||||
render();
|
||||
|
||||
Reference in New Issue
Block a user