mirror of
https://github.com/Tria-plc/edr-platform.git
synced 2026-08-30 05:18:11 +00:00
contrat nad booking modification
This commit is contained in:
@@ -87,40 +87,6 @@ export function useBookingMutations(bookingId: string) {
|
||||
},
|
||||
});
|
||||
|
||||
const approveStep = useMutation({
|
||||
mutationFn: ({
|
||||
stepId,
|
||||
requiredRole,
|
||||
}: {
|
||||
stepId: string;
|
||||
requiredRole: string;
|
||||
}) =>
|
||||
api.bookings.approveStep.call({
|
||||
id: bookingId,
|
||||
stepId,
|
||||
requiredRole,
|
||||
}),
|
||||
onSuccess: (data) => onSuccess(data, "Approval step completed"),
|
||||
onError: (error) => toast.error(parseApiError(error, "Failed to approve step")),
|
||||
});
|
||||
|
||||
const rejectStep = useMutation({
|
||||
mutationFn: ({
|
||||
stepId,
|
||||
reason,
|
||||
}: {
|
||||
stepId: string;
|
||||
reason: string;
|
||||
}) =>
|
||||
api.bookings.rejectStep.call({
|
||||
id: bookingId,
|
||||
stepId,
|
||||
reason,
|
||||
}),
|
||||
onSuccess: (data) => onSuccess(data, "Booking rejected at approval step"),
|
||||
onError: (error) => toast.error(parseApiError(error, "Failed to reject step")),
|
||||
});
|
||||
|
||||
const generateContract = useMutation({
|
||||
mutationFn: () => api.bookings.generateContract.call({ id: bookingId }),
|
||||
onSuccess: (data) => onSuccess(data, "Contract generated"),
|
||||
@@ -167,8 +133,6 @@ export function useBookingMutations(bookingId: string) {
|
||||
staffAccept.isPending ||
|
||||
requestChanges.isPending ||
|
||||
staffReject.isPending ||
|
||||
approveStep.isPending ||
|
||||
rejectStep.isPending ||
|
||||
generateContract.isPending ||
|
||||
signContract.isPending ||
|
||||
payBooking.isPending ||
|
||||
@@ -182,8 +146,6 @@ export function useBookingMutations(bookingId: string) {
|
||||
requestChanges,
|
||||
staffReject,
|
||||
reviewOperation,
|
||||
approveStep,
|
||||
rejectStep,
|
||||
generateContract,
|
||||
signContract,
|
||||
payBooking,
|
||||
|
||||
@@ -122,6 +122,15 @@ export function useContractMutations(contractId: string) {
|
||||
const onSuccess = (data: { id: string }, message: string) => {
|
||||
toast.success(message);
|
||||
void invalidateContractDetail(qc, data.id);
|
||||
// Approving or editing can change who holds document-editing rights (it
|
||||
// passes to the next approver), and edits add revisions — so both the draft
|
||||
// and the history are refreshed on every contract mutation.
|
||||
void qc.invalidateQueries({
|
||||
queryKey: ["contracts", data.id, "document-draft"],
|
||||
});
|
||||
void qc.invalidateQueries({
|
||||
queryKey: ["contracts", data.id, "document-revisions"],
|
||||
});
|
||||
};
|
||||
|
||||
const staffAccept = useMutation({
|
||||
@@ -160,21 +169,16 @@ export function useContractMutations(contractId: string) {
|
||||
});
|
||||
|
||||
const approveStep = useMutation({
|
||||
mutationFn: ({
|
||||
stepId,
|
||||
requiredRole,
|
||||
}: {
|
||||
stepId: string;
|
||||
requiredRole: string;
|
||||
}) =>
|
||||
contractsService.approveStep({ id: contractId, stepId, requiredRole }),
|
||||
// The server derives the required role from the step itself, so the client
|
||||
// does not send one.
|
||||
mutationFn: ({ stepId }: { stepId: string }) =>
|
||||
contractsService.approveStep({ id: contractId, stepId }),
|
||||
onSuccess: (data) => {
|
||||
// The document is generated at the accept stage and reviewed during
|
||||
// approval, so the final approval moves the contract straight to
|
||||
// CONTRACT_READY on the server — no client-side generate call here.
|
||||
// The final approval is what generates the PDF and moves the contract to
|
||||
// CONTRACT_READY — before that approvers review a live preview.
|
||||
const message =
|
||||
data.status === "CONTRACT_READY"
|
||||
? "Final approval complete — contract ready to sign"
|
||||
? "Final approval complete — contract generated and ready to sign"
|
||||
: "Approval step completed";
|
||||
onSuccess(data, message);
|
||||
},
|
||||
|
||||
@@ -9,7 +9,10 @@ import {
|
||||
type SubmitPriorityRuleChangePayload,
|
||||
type SubmitRateChangePayload,
|
||||
} from "@/services/ruleEngine/ruleEngine.service";
|
||||
import { RULE_ENGINE_SELECT_NONE } from "@/pages/ruleEngine/config/resources";
|
||||
import {
|
||||
LEGACY_APPROVAL_ROLES,
|
||||
RULE_ENGINE_SELECT_NONE,
|
||||
} from "@/pages/ruleEngine/config/resources";
|
||||
import type {
|
||||
RuleEngineRecord,
|
||||
RuleEngineResourceSlug,
|
||||
@@ -155,6 +158,33 @@ export const useContainerTypeOptions = (
|
||||
select: (rows) => buildContainerTypeSelectOptions(rows, includeNone),
|
||||
});
|
||||
|
||||
/**
|
||||
* Approval-step role options, sourced from the live IAM position types. The
|
||||
* three pre-IAM role strings are appended (marked "(legacy)") so an approval
|
||||
* rule still stored against one of them renders its label instead of an empty
|
||||
* select; a position type that reuses one of those values wins the dedupe.
|
||||
*/
|
||||
export const useApprovalRoleOptions = (enabled = true) =>
|
||||
useQuery({
|
||||
queryKey: QUERY_KEYS.RULE_ENGINE.selectOptions("approval-rules", {
|
||||
positionTypes: true,
|
||||
}),
|
||||
queryFn: () => ruleEngineService.getApprovalPositionTypes(),
|
||||
enabled,
|
||||
select: (rows): { label: string; value: string }[] => {
|
||||
const byValue = new Map<string, { label: string; value: string }>();
|
||||
for (const row of rows) {
|
||||
const value = String(row?.value ?? "").trim();
|
||||
if (!value) continue;
|
||||
byValue.set(value, { label: String(row.label ?? "").trim() || value, value });
|
||||
}
|
||||
for (const legacy of LEGACY_APPROVAL_ROLES) {
|
||||
if (!byValue.has(legacy.value)) byValue.set(legacy.value, legacy);
|
||||
}
|
||||
return [...byValue.values()];
|
||||
},
|
||||
});
|
||||
|
||||
/** A yard option that remembers its country, so callers can filter by leg. */
|
||||
export interface YardOption {
|
||||
label: string;
|
||||
|
||||
Reference in New Issue
Block a user