fix: number a new report after the highest number in the project

Counting non-deleted reports reused numbers (and photo folders) after a
soft delete. Deleted reports are now included.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Тимур Городецкий
2026-10-19 16:17:57 +05:00
parent f6af34cb0a
commit f05ee3e854
2 changed files with 20 additions and 10 deletions
@@ -26,8 +26,8 @@ const bodyOf = (body: string | ArrayBuffer | undefined): unknown => JSON.parse(S
describe('адреса Dataverse (1:1 со stroy-bot-report)', () => { describe('адреса Dataverse (1:1 со stroy-bot-report)', () => {
it('отчёт, счётчик, строки, факт', () => { it('отчёт, счётчик, строки, факт', () => {
expect(DV_PATHS.report('r1')).toEqual('cree9_reports(r1)'); expect(DV_PATHS.report('r1')).toEqual('cree9_reports(r1)');
expect(DV_PATHS.reportCount(5)).toEqual( expect(DV_PATHS.lastReportNumber(5)).toEqual(
'cree9_reports?$filter=cree9_projectid eq 5 and cree9_deleted ne true&$count=true&$top=1&$select=cree9_number' 'cree9_reports?$filter=cree9_projectid eq 5&$orderby=cree9_number desc&$top=1&$select=cree9_number'
); );
expect(DV_PATHS.reportData('r1')).toEqual('cree9_report_datas?$filter=_cree9_column1_value eq r1'); expect(DV_PATHS.reportData('r1')).toEqual('cree9_report_datas?$filter=_cree9_column1_value eq r1');
expect(DV_PATHS.jobTotalFact('j1')).toEqual('cree9_report_datas?$filter=_cree9_jobid_value eq j1&$select=cree9_value'); expect(DV_PATHS.jobTotalFact('j1')).toEqual('cree9_report_datas?$filter=_cree9_jobid_value eq j1&$select=cree9_value');
@@ -165,11 +165,18 @@ describe('saveReportWithData', () => {
}); });
describe('прочие операции', () => { describe('прочие операции', () => {
it('номер нового отчёта = количество неудалённых + 1', async () => { it('номер нового отчёта = наибольший номер в проекте (включая удалённые) + 1', async () => {
const client = createFakeHttpClient([{ match: '$count=true', response: { body: { '@odata.count': 7, value: [] } } }]); const client = createFakeHttpClient([
{ match: 'cree9_number desc', response: { body: { value: [{ cree9_number: 7 }] } } }
]);
expect(await createDataverseReportRepository(client, DV).getNextReportNumber(5)).toEqual(8); expect(await createDataverseReportRepository(client, DV).getNextReportNumber(5)).toEqual(8);
}); });
it('первый отчёт проекта получает номер 1', async () => {
const client = createFakeHttpClient([{ match: 'cree9_number desc', response: { body: { value: [] } } }]);
expect(await createDataverseReportRepository(client, DV).getNextReportNumber(5)).toEqual(1);
});
it('утверждение — PATCH cree9_aprooved: true', async () => { it('утверждение — PATCH cree9_aprooved: true', async () => {
const client = createFakeHttpClient([{ match: 'cree9_reports(r1)', response: { status: 204 } }]); const client = createFakeHttpClient([{ match: 'cree9_reports(r1)', response: { status: 204 } }]);
await createDataverseReportRepository(client, DV).approveReport('r1'); await createDataverseReportRepository(client, DV).approveReport('r1');
@@ -50,9 +50,10 @@ export const DV_PATHS = {
`?$select=ReferencingAttribute,ReferencingEntityNavigationPropertyName` + `?$select=ReferencingAttribute,ReferencingEntityNavigationPropertyName` +
`&$filter=ReferencingAttribute eq 'cree9_parentid'`, `&$filter=ReferencingAttribute eq 'cree9_parentid'`,
report: (reportId: string): string => `${DV_TABLES.reports}(${reportId})`, report: (reportId: string): string => `${DV_TABLES.reports}(${reportId})`,
reportCount: (projectId: number): string => // Удалённые отчёты не исключаются: их номера (и папки фото {projectId}_{номер}) повторно не выдаются.
`${DV_TABLES.reports}?$filter=cree9_projectid eq ${projectId} and cree9_deleted ne true` + lastReportNumber: (projectId: number): string =>
`&$count=true&$top=1&$select=cree9_number`, `${DV_TABLES.reports}?$filter=cree9_projectid eq ${projectId}` +
`&$orderby=cree9_number desc&$top=1&$select=cree9_number`,
jobTotalFact: (jobId: string): string => jobTotalFact: (jobId: string): string =>
`${DV_TABLES.reportData}?$filter=_cree9_jobid_value eq ${jobId}&$select=cree9_value`, `${DV_TABLES.reportData}?$filter=_cree9_jobid_value eq ${jobId}&$select=cree9_value`,
reportData: (reportId: string): string => `${DV_TABLES.reportData}?$filter=_cree9_column1_value eq ${reportId}`, reportData: (reportId: string): string => `${DV_TABLES.reportData}?$filter=_cree9_column1_value eq ${reportId}`,
@@ -252,9 +253,11 @@ export function createDataverseReportRepository(client: IHttpClient, baseUrl: st
getReportById: (reportId) => get<IReportRow>(DV_PATHS.report(reportId)), getReportById: (reportId) => get<IReportRow>(DV_PATHS.report(reportId)),
getNextReportNumber: async (projectId) => { getNextReportNumber: async (projectId) => {
// 🐞 Номер = число неудалённых отчётов + 1: после мягкого удаления номер может повториться. // В старом коде номер = число неудалённых отчётов + 1, и после мягкого удаления номера повторялись —
const result = await get<{ '@odata.count'?: number }>(DV_PATHS.reportCount(projectId)); // исправлено при проверке T-REP-23: номер = наибольший номер в проекте + 1.
return (result['@odata.count'] || 0) + 1; const result = await get<{ value?: Array<{ cree9_number?: number }> }>(DV_PATHS.lastReportNumber(projectId));
const lastNumber = result.value?.[0]?.cree9_number || 0;
return lastNumber + 1;
}, },
approveReport: (reportId) => patch(DV_PATHS.report(reportId), { cree9_aprooved: true }), approveReport: (reportId) => patch(DV_PATHS.report(reportId), { cree9_aprooved: true }),