This commit is contained in:
@@ -55,6 +55,7 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
||||
// после первого сохранения.
|
||||
const [requestId, setRequestId] = useState<number | undefined>(editId);
|
||||
const [requestStatus, setRequestStatus] = useState<string | undefined>(undefined);
|
||||
const [requestCode, setRequestCode] = useState<string | undefined>(undefined);
|
||||
const submit = useRequestSubmit();
|
||||
|
||||
const readOnly = !isEditableStatus(requestStatus);
|
||||
@@ -73,6 +74,7 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
||||
if (alive) {
|
||||
setData(loaded.data);
|
||||
setRequestStatus(loaded.status);
|
||||
setRequestCode(loaded.code || undefined);
|
||||
setExistingAttachments(atts);
|
||||
}
|
||||
})
|
||||
@@ -152,7 +154,7 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
||||
};
|
||||
|
||||
const save = (status: string): (() => Promise<void>) => async (): Promise<void> => {
|
||||
const id = await saveHireRequest(
|
||||
const { id, code } = await saveHireRequest(
|
||||
requestId,
|
||||
data,
|
||||
toApprovers(matrix.rows),
|
||||
@@ -161,6 +163,9 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
||||
);
|
||||
setRequestId(id);
|
||||
setRequestStatus(status);
|
||||
if (code) {
|
||||
setRequestCode(code);
|
||||
}
|
||||
if (files.length > 0) {
|
||||
await uploadAttachments(DATA_LIST_TITLE, id, files); // файлы — после создания элемента
|
||||
setFiles([]); // выгруженные файлы убираем, чтобы пересохранение не дублировало
|
||||
@@ -218,7 +223,7 @@ const RecruitingHireForm: React.FC<IRequestFormProps> = ({ requestType, context,
|
||||
requestId || requestStatus ? (
|
||||
<>
|
||||
{requestStatus && <StatusBadge status={requestStatus} />}
|
||||
{requestId && <RequestNumber id={requestId} />}
|
||||
{requestCode && <RequestNumber code={requestCode} />}
|
||||
</>
|
||||
) : undefined
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ const NOOP_SET: SetField = () => undefined;
|
||||
const RecruitingHireView: React.FC<IRecruitingHireViewProps> = ({ context, itemId }) => {
|
||||
const [data, setData] = useState<IFormData>(EMPTY_DATA);
|
||||
const [status, setStatus] = useState<string>('');
|
||||
const [code, setCode] = useState<string>('');
|
||||
const [attachments, setAttachments] = useState<IAttachmentInfo[]>([]);
|
||||
const [loading, setLoading] = useState<boolean>(true);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
@@ -89,6 +90,7 @@ const RecruitingHireView: React.FC<IRecruitingHireViewProps> = ({ context, itemI
|
||||
if (alive) {
|
||||
setData(loaded.data);
|
||||
setStatus(loaded.status);
|
||||
setCode(loaded.code);
|
||||
setAttachments(files);
|
||||
setError(null);
|
||||
setLoading(false);
|
||||
@@ -140,7 +142,7 @@ const RecruitingHireView: React.FC<IRecruitingHireViewProps> = ({ context, itemI
|
||||
<div className="rp-print-root">
|
||||
<FormCard
|
||||
title="Заявка на прием"
|
||||
subtitle={`№${itemId}`}
|
||||
subtitle={`№${code || itemId}`}
|
||||
headerRight={status ? <StatusBadge status={status} /> : undefined}
|
||||
>
|
||||
<FormModeProvider readOnly>
|
||||
|
||||
@@ -13,6 +13,8 @@ const SCALAR_FIELDS: (keyof IFormData)[] = [
|
||||
export interface ILoadedRequest {
|
||||
data: IFormData;
|
||||
status: string;
|
||||
/** Уникальный код заявки; '' — если запись создана до появления поля. */
|
||||
code: string;
|
||||
}
|
||||
|
||||
/** Прочитать заявку «на прием» по id: модель формы + статус (для режима чтения). */
|
||||
@@ -21,7 +23,7 @@ export async function loadHireRequest(itemId: number): Promise<ILoadedRequest> {
|
||||
const item = (await sp.web.lists
|
||||
.getByTitle(LIST_TITLE)
|
||||
.items.getById(itemId)
|
||||
.select(...SCALAR_FIELDS, 'Status')()) as Record<string, unknown>;
|
||||
.select(...SCALAR_FIELDS, 'Status', 'RequestUniqueCode')()) as Record<string, unknown>;
|
||||
|
||||
const data: IFormData = { ...EMPTY_DATA };
|
||||
const writable = data as unknown as Record<string, string>;
|
||||
@@ -37,5 +39,5 @@ export async function loadHireRequest(itemId: number): Promise<ILoadedRequest> {
|
||||
}
|
||||
});
|
||||
|
||||
return { data, status: (item.Status as string) || '' };
|
||||
return { data, status: (item.Status as string) || '', code: (item.RequestUniqueCode as string) || '' };
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { getSP } from '../../shared/pnp/pnpjs';
|
||||
import { ApprovalListService, IApproverToWrite, writeRoute } from '../../shared/approval';
|
||||
import { buildRequestUniqueCode } from '../../shared/requestCode';
|
||||
import { IFormData } from './model';
|
||||
|
||||
export const DATA_LIST_TITLE = 'Прием на работу — данные';
|
||||
@@ -37,12 +38,18 @@ function buildItem(data: IFormData, status: string): Record<string, unknown> {
|
||||
return item;
|
||||
}
|
||||
|
||||
export interface ISaveResult {
|
||||
id: number;
|
||||
/** Задан только при создании новой заявки (существующий код не меняется). */
|
||||
code?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Сохранить заявку «на прием»: контент + маршрут (согласующие + исполнители) со статусом.
|
||||
* existingId задан → обновляем ту же запись (черновик/доработка), иначе создаём новую.
|
||||
* status = «Черновик» (сохранение) или «На согласовании» (отправка).
|
||||
* executors может быть пустым — тогда после согласования заявка станет «Согласовано».
|
||||
* Возвращает Id заявки.
|
||||
* Возвращает Id заявки (+ код при создании).
|
||||
*/
|
||||
export async function saveHireRequest(
|
||||
existingId: number | undefined,
|
||||
@@ -50,21 +57,23 @@ export async function saveHireRequest(
|
||||
approvers: IApproverToWrite[],
|
||||
executors: IApproverToWrite[],
|
||||
status: string
|
||||
): Promise<number> {
|
||||
): Promise<ISaveResult> {
|
||||
const list = getSP().web.lists.getByTitle(DATA_LIST_TITLE);
|
||||
const item = buildItem(data, status);
|
||||
|
||||
let id: number;
|
||||
let code: string | undefined;
|
||||
if (existingId) {
|
||||
await list.items.getById(existingId).update(item);
|
||||
id = existingId;
|
||||
} else {
|
||||
const added = await list.items.add(item);
|
||||
id = (added as { Id: number }).Id;
|
||||
// Уникальный код заявки: пока = id (id известен только после создания).
|
||||
await list.items.getById(id).update({ RequestUniqueCode: String(id) });
|
||||
// Код известен только после создания элемента (нужен его Id).
|
||||
code = buildRequestUniqueCode(HIRE_REQUEST_TYPE_ID, id, new Date());
|
||||
await list.items.getById(id).update({ RequestUniqueCode: code });
|
||||
}
|
||||
|
||||
await writeRoute(hireApprovalService(), id, approvers, executors, status);
|
||||
return id;
|
||||
return { id, code };
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user