feat: implement license type management with creation and status toggling functionality

This commit is contained in:
estifanos
2026-09-02 11:10:27 +00:00
parent 3b5bdfb6d1
commit 5eeb9602b0
8 changed files with 767 additions and 17 deletions

View File

@@ -27,6 +27,8 @@ import type {
DocumentDecision,
DocumentReview,
ExportResult,
FamilyKind,
LicenseCategory,
LicenseTemplate,
Paginated,
PickupAppointment,
@@ -109,6 +111,28 @@ const TAGS = [
const listTag = (type: (typeof TAGS)[number]) => ({ type, id: 'LIST' }) as const;
const itemTag = (type: (typeof TAGS)[number], id: string) => ({ type, id }) as const;
/** What `POST /license-types` accepts. Mirrors the server's create DTO. */
export interface CreateLicenseTypeInput {
key: string;
name: { en: string; am: string };
description?: { en: string; am: string };
category?: LicenseCategory;
familyKind?: FamilyKind;
serviceKind?: ServiceKind;
workflowProfile?: WorkflowProfile;
certificatePrefix: string;
feeNewApplication?: number;
feeRenewal?: number;
feeCurrency?: string;
capitalThreshold?: number;
validityMonths?: number;
inspectionRequired?: boolean;
issuesCertificate?: boolean;
renewalEnabled?: boolean;
sortOrder?: number;
isActive?: boolean;
}
/**
* Typed licensing endpoints, shared by the portal and the backoffice.
*
@@ -222,6 +246,7 @@ export const licensingApi = baseApi
id: string;
workflowProfile?: WorkflowProfile;
serviceKind?: ServiceKind;
familyKind?: FamilyKind;
completionEffect?: CompletionEffect | null;
certificateCategory?: CertificateCategory | null;
requiresExamination?: boolean;
@@ -252,6 +277,36 @@ export const licensingApi = baseApi
error ? [] : [listTag('LicenseType'), itemTag('LicenseType', id)],
}),
/**
* Creates a licence type. The bare minimum a type needs to exist and
* be classified; its form, documents, fees and behaviour are configured
* afterwards on their own screens. The server upper-cases and trims the
* key, refuses a taken one with 409 `license_type_key_taken`, and lints
* a form schema if one is supplied.
*/
createLicenseType: builder.mutation<LicenseType, CreateLicenseTypeInput>({
query: (body) => ({ url: '/license-types', method: 'POST', body }),
invalidatesTags: (_r, error) => (error ? [] : [listTag('LicenseType')]),
}),
/**
* Opens or closes a type to new applications. Applications already in
* flight hold the type by id and keep running; only the portal
* catalogue changes.
*/
updateLicenseStatus: builder.mutation<
LicenseType,
{ id: string; isActive: boolean }
>({
query: ({ id, isActive }) => ({
url: `/license-types/${id}/status`,
method: 'PATCH',
body: { isActive },
}),
invalidatesTags: (_r, error, { id }) =>
error ? [] : [itemTag('LicenseType', id), listTag('LicenseType')],
}),
/** Validity is edited beside the certificate design, not with the fees. */
updateLicenseValidity: builder.mutation<
LicenseType,
@@ -1381,6 +1436,8 @@ export const {
useUpdateRankMutation,
useDeleteRankMutation,
useUpdateLicenseValidityMutation,
useCreateLicenseTypeMutation,
useUpdateLicenseStatusMutation,
useGetLicenseTypeRequirementsQuery,
useCreateApplicationMutation,
useGetExamStateForApplicationQuery,