fix: дата подачи — день отправки, а не сохранения черновика
В подборе и реферале черновик хранил дату первого сохранения, и через несколько дней заявка уходила на согласование со старой датой подачи. Теперь при отправке дата подачи всегда сегодняшняя, а открытый черновик сразу показывает сегодня (как уже было в объяснительной по СКУД). В реферале дату больше нельзя поправить руками. Общая логика — shared/submitDate. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,6 +64,7 @@ import { VacancySection } from './sections/VacancySection';
|
||||
import { HealthTripsSection } from './sections/HealthTripsSection';
|
||||
import { ConditionsSection } from './sections/ConditionsSection';
|
||||
import { useStableCallback } from '../../shared/useStableCallback';
|
||||
import { submitDateOnOpen } from '../../shared/submitDate';
|
||||
|
||||
const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
|
||||
requestType,
|
||||
@@ -105,7 +106,7 @@ const RecruitingSelectionForm: React.FC<IRequestFormProps> = ({
|
||||
Promise.all([loadSelectionRequest(editId, editListId), getAttachments(editListId || dataListTitle(FORM_ID), editId)])
|
||||
.then(([loaded, atts]) => {
|
||||
if (alive) {
|
||||
setData(loaded.data);
|
||||
setData({ ...loaded.data, SubmitDate: submitDateOnOpen(loaded.status, loaded.data.SubmitDate) });
|
||||
setApproverChanges(loaded.approverChanges);
|
||||
setRequestStatus(loaded.status);
|
||||
setRequestCode(loaded.code || undefined);
|
||||
|
||||
@@ -3,6 +3,7 @@ import { ApprovalListService, IApproverToWrite, approvalServiceFor, writeRoute }
|
||||
import { ISaveItemResult, resolveDataList, saveRequestItem } from '../../shared/dataList';
|
||||
import { IFieldChange, serializeFieldChanges } from '../../shared/fieldChanges/fieldChanges';
|
||||
import { buildRequestTitle } from '../../shared/requestTitle';
|
||||
import { submitDateOnSave } from '../../shared/submitDate';
|
||||
import { FORM_ID, IFormData } from './model';
|
||||
import { APPROVER_CHANGES_FIELD } from './changeTracking';
|
||||
import { cleanVacancyReasons, legacyDetailsText } from './vacancyReasons';
|
||||
@@ -146,6 +147,7 @@ export async function saveSelectionRequest(
|
||||
): Promise<ISaveResult> {
|
||||
const item = buildScalarBody(data);
|
||||
item.RequestStatus = status;
|
||||
item.SubmitDate = submitDateOnSave(status, data.SubmitDate) || null;
|
||||
await applyPeople(item, data);
|
||||
|
||||
const result = await saveRequestItem(FORM_ID, existingId, listId, requestTypeId, item);
|
||||
|
||||
@@ -59,6 +59,7 @@ import { VacancySection } from './sections/VacancySection';
|
||||
import { CandidateInfoSection } from './sections/CandidateInfoSection';
|
||||
import { AssessmentSection } from './sections/AssessmentSection';
|
||||
import { useStableCallback } from '../../shared/useStableCallback';
|
||||
import { submitDateOnOpen } from '../../shared/submitDate';
|
||||
|
||||
const ReferralForm: React.FC<IRequestFormProps> = ({
|
||||
requestType,
|
||||
@@ -111,7 +112,7 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
|
||||
Promise.all([loadReferralRequest(editId, editListId), getAttachments(editListId || dataListTitle(FORM_ID), editId)])
|
||||
.then(([loaded, atts]) => {
|
||||
if (alive) {
|
||||
setData(loaded.data);
|
||||
setData({ ...loaded.data, SubmitDate: submitDateOnOpen(loaded.status, loaded.data.SubmitDate) });
|
||||
setRequestStatus(loaded.status);
|
||||
setRequestCode(loaded.code || undefined);
|
||||
if (loaded.code) notifyCode(loaded.code);
|
||||
@@ -141,7 +142,7 @@ const ReferralForm: React.FC<IRequestFormProps> = ({
|
||||
setData((prev) => ({
|
||||
...prev,
|
||||
Referrer: prev.Referrer || user.email,
|
||||
SubmitDate: prev.SubmitDate || todayIso()
|
||||
SubmitDate: todayIso()
|
||||
}));
|
||||
approval
|
||||
.getProfileFields(user.loginName)
|
||||
|
||||
@@ -5,8 +5,9 @@ import { ISectionProps, REFERRER_PLACEHOLDER } from '../model';
|
||||
/** Секция 1: кто рекомендует — дата подачи, сам рекомендатель и его контакты. */
|
||||
export const ReferrerSection: React.FC<ISectionProps> = ({ data, set, context, onReferrerChange, printOrgIndex }) => (
|
||||
<CollapseSection title="1. Рекомендатель" icon="people">
|
||||
{/* Дата подачи — всегда сегодняшняя (ставит форма, при отправке — заново), руками не меняется. */}
|
||||
<FormField label="1.1 Дата подачи" htmlFor="SubmitDate" required>
|
||||
<TextInput id="SubmitDate" type="date" value={data.SubmitDate} onChange={(v) => set('SubmitDate', v)} />
|
||||
<TextInput id="SubmitDate" type="date" value={data.SubmitDate} onChange={(v) => set('SubmitDate', v)} readOnly />
|
||||
</FormField>
|
||||
<FormField label="1.2 Ф.И.О. рекомендателя" htmlFor="Referrer" required full>
|
||||
<PeopleField
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ApprovalListService, IApproverToWrite, approvalServiceFor, writeRoute } from '../../shared/approval';
|
||||
import { ISaveItemResult, saveRequestItem } from '../../shared/dataList';
|
||||
import { ensureEmployee } from '../../shared/employee';
|
||||
import { submitDateOnSave } from '../../shared/submitDate';
|
||||
import { FORM_ID, IFormData, OTHER_VALUE } from './model';
|
||||
|
||||
/**
|
||||
@@ -28,7 +29,7 @@ function buildItem(data: IFormData, status: string, referrerId: number): Record<
|
||||
return {
|
||||
Title: buildTitle(data.CandidateName, data.VacancyTitle),
|
||||
RequestStatus: status,
|
||||
SubmitDate: data.SubmitDate || null,
|
||||
SubmitDate: submitDateOnSave(status, data.SubmitDate) || null,
|
||||
ReferrerId: referrerId,
|
||||
ReferrerPosition: data.ReferrerPosition || null,
|
||||
ReferrerDepartment: data.ReferrerDepartment || null,
|
||||
|
||||
@@ -35,6 +35,7 @@ import {
|
||||
dataListTitleForListId
|
||||
} from '../../shared/listTitles';
|
||||
import { useStableCallback } from '../../shared/useStableCallback';
|
||||
import { submitDateOnOpen } from '../../shared/submitDate';
|
||||
import { FORM_ID, FORM_TITLE, IFormData, EMPTY_DATA, SetField } from './model';
|
||||
import { validateSkudExplanation } from './validation';
|
||||
import { saveSkudExplanationRequest, skudExplanationApprovalService } from './submit';
|
||||
@@ -83,10 +84,7 @@ const SkudExplanationForm: React.FC<IRequestFormProps> = ({
|
||||
loadSkudExplanationRequest(editId, editListId)
|
||||
.then((loaded) => {
|
||||
if (!alive) return;
|
||||
// Черновик/доработку подают заново — дата подачи становится сегодняшней;
|
||||
// у отправленной заявки остаётся та, с которой её подали.
|
||||
const submitDate = isEditableStatus(loaded.status) ? todayDateKey() : loaded.data.SubmitDate;
|
||||
setData({ ...loaded.data, SubmitDate: submitDate });
|
||||
setData({ ...loaded.data, SubmitDate: submitDateOnOpen(loaded.status, loaded.data.SubmitDate) });
|
||||
setRequestStatus(loaded.status);
|
||||
setRequestCode(loaded.code || undefined);
|
||||
if (loaded.code) notifyCode(loaded.code);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { ApprovalListService, IApproverToWrite, approvalServiceFor, writeRoute } from '../../shared/approval';
|
||||
import { ISaveItemResult, saveRequestItem } from '../../shared/dataList';
|
||||
import { ensureEmployee } from '../../shared/employee';
|
||||
import { submitDateOnSave } from '../../shared/submitDate';
|
||||
import { FORM_ID, IFormData, OTHER_REASON } from './model';
|
||||
import { formatMissedDaysSummary, formatShortDate } from './noteText';
|
||||
import { todayDateKey } from './skud/skudDays';
|
||||
@@ -19,7 +20,7 @@ function buildItem(data: IFormData, status: string, employeeId: number, employee
|
||||
return {
|
||||
Title: buildTitle(employeeName),
|
||||
RequestStatus: status,
|
||||
SubmitDate: data.SubmitDate || null,
|
||||
SubmitDate: submitDateOnSave(status, data.SubmitDate) || null,
|
||||
EmployeeId: employeeId,
|
||||
SkudEmployeeFio: data.EmployeeFio || null,
|
||||
Position: data.Position || null,
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import { REQUEST_STATUS } from './approval/models/statuses';
|
||||
import { submitDateOnOpen, submitDateOnSave, todaySubmitDate } from './submitDate';
|
||||
|
||||
const OLD_DATE = '2026-09-01';
|
||||
|
||||
describe('submitDate', () => {
|
||||
it('отправка на согласование — сегодня, даже если черновик сохранён раньше', () => {
|
||||
expect(submitDateOnSave(REQUEST_STATUS.onApproval, OLD_DATE)).toBe(todaySubmitDate());
|
||||
expect(submitDateOnSave(REQUEST_STATUS.queued, OLD_DATE)).toBe(todaySubmitDate());
|
||||
});
|
||||
|
||||
it('черновик хранит дату с экрана', () => {
|
||||
expect(submitDateOnSave(REQUEST_STATUS.draft, OLD_DATE)).toBe(OLD_DATE);
|
||||
});
|
||||
|
||||
it('открыли черновик или доработку — сегодня, отправленную — как подали', () => {
|
||||
expect(submitDateOnOpen(REQUEST_STATUS.draft, OLD_DATE)).toBe(todaySubmitDate());
|
||||
expect(submitDateOnOpen(REQUEST_STATUS.returned, OLD_DATE)).toBe(todaySubmitDate());
|
||||
expect(submitDateOnOpen(REQUEST_STATUS.onApproval, OLD_DATE)).toBe(OLD_DATE);
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,30 @@
|
||||
import { REQUEST_STATUS, isEditableStatus } from './approval/models/statuses';
|
||||
|
||||
function pad2(n: number): string {
|
||||
return n < 10 ? `0${n}` : `${n}`;
|
||||
}
|
||||
|
||||
/** Сегодняшняя дата по местному времени, YYYY-MM-DD (формат input type=date). */
|
||||
export function todaySubmitDate(): string {
|
||||
const now = new Date();
|
||||
return `${now.getFullYear()}-${pad2(now.getMonth() + 1)}-${pad2(now.getDate())}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* «Дата подачи» для формы, открытой на редактирование. Черновик и доработку
|
||||
* подают заново — на экране сегодняшняя дата, а не дата первого сохранения;
|
||||
* у уже отправленной заявки остаётся та, с которой её подали.
|
||||
*/
|
||||
export function submitDateOnOpen(status: string, savedDate: string): string {
|
||||
return isEditableStatus(status) ? todaySubmitDate() : savedDate;
|
||||
}
|
||||
|
||||
/**
|
||||
* «Дата подачи» для записи в SharePoint из формы подачи. Любое сохранение кроме
|
||||
* черновика — это отправка («На согласовании» или «Ждёт очереди», см.
|
||||
* initialSubmitStatus): дата всегда сегодняшняя — форму могли открыть вчера, а
|
||||
* черновик сохранить неделю назад. Черновик хранит то, что на экране.
|
||||
*/
|
||||
export function submitDateOnSave(status: string, currentDate: string): string {
|
||||
return status === REQUEST_STATUS.draft ? currentDate : todaySubmitDate();
|
||||
}
|
||||
Reference in New Issue
Block a user