feat: implement per-doctor insurance settings in multi-doctor clinics

- Updated InsuranceModal to include doctorUuid in the payload for insurance contracts.
- Enhanced TenantInsuranceContracts to allow selection of doctors and pass doctorUuid in API requests.
- Modified InsuranceController to handle doctorUuid for tenant insurance endpoints, ensuring contracts are stored per doctor.
- Updated API documentation to reflect the new optional doctor_uuid parameter for tenant insurance endpoints.
- Added tests to verify the functionality of per-doctor insurance contracts and ensure isolation of contracts between doctors.
This commit is contained in:
hamed
2026-07-21 19:21:55 +03:30
parent 7e847b62c4
commit 5507b42fd8
6 changed files with 478 additions and 25 deletions
+11 -4
View File
@@ -59,8 +59,12 @@ export function contractToForm(c: Contract): InsuranceFormValues {
};
}
/** Build the API payload from form values (toman → rials, Y-m-d → unix). */
export function buildInsurancePayload(v: InsuranceFormValues) {
/**
* Build the API payload from form values (toman → rials, Y-m-d → unix).
* When `doctorUuid` is set, the contract is targeted at that doctor (multi-doctor
* clinic); otherwise it falls back to the caller's own tenant on the backend.
*/
export function buildInsurancePayload(v: InsuranceFormValues, doctorUuid?: string | null) {
return {
insurance_id: Number(v.insuranceId),
kind: v.kind || null,
@@ -69,6 +73,7 @@ export function buildInsurancePayload(v: InsuranceFormValues) {
annual_ceiling_rials: v.ceiling === '' ? null : tomanToRial(Number(v.ceiling)),
effective_from: isoToUnix(v.effectiveFrom),
effective_to: isoToUnix(v.effectiveTo),
...(doctorUuid ? { doctor_uuid: doctorUuid } : {}),
};
}
@@ -79,6 +84,8 @@ interface Props {
options: InsuranceOption[];
/** Insurance kind of the active tab ('basic'|'supplementary'); assigned to new contracts, not user-editable. */
kind: string;
/** Target doctor in a multi-doctor clinic; threaded into the payload as `doctor_uuid`. */
doctorUuid?: string | null;
onClose: () => void;
onSubmit: (payload: ReturnType<typeof buildInsurancePayload>) => void;
isPending?: boolean;
@@ -89,7 +96,7 @@ interface Props {
* state, emits the built payload via onSubmit. Fields mirror the Figma "افزودن بیمه"
* modal plus the injected coverage/franchise/ceiling controls.
*/
export default function InsuranceModal({ open, editContract, options, kind, onClose, onSubmit, isPending }: Props) {
export default function InsuranceModal({ open, editContract, options, kind, doctorUuid, onClose, onSubmit, isPending }: Props) {
const [form, setForm] = useState<InsuranceFormValues>(EMPTY_FORM);
useEffect(() => {
@@ -102,7 +109,7 @@ export default function InsuranceModal({ open, editContract, options, kind, onCl
const submit = () => {
if (!form.insuranceId) return;
onSubmit(buildInsurancePayload(form));
onSubmit(buildInsurancePayload(form, doctorUuid));
};
const field = { display: 'flex', flexDirection: 'column' as const, gap: 6 };