diff --git a/src/reports/index.ts b/src/reports/index.ts index 566ca2685..6d4efcb68 100644 --- a/src/reports/index.ts +++ b/src/reports/index.ts @@ -197,6 +197,63 @@ export class Reports extends CrowdinApi { return this.get(url, this.defaultConfig()); } + /** + * @param options optional parameters for the request + * @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/Reports/operation/api.reports.settings-templates.getMany + */ + listOrganizationReportSettingsTemplates( + options?: ReportsModel.ListOrganizationReportSettingsParams, + ): Promise<ResponseList<ReportsModel.OrganizationReportSettings>> { + let url = `${this.url}/reports/settings-templates`; + url = this.addQueryParam(url, 'projectId', options?.projectId); + url = this.addQueryParam(url, 'groupId', options?.groupId); + return this.getList(url, options?.limit, options?.offset); + } + + /** + * @param request request body + * @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/Reports/operation/api.reports.settings-templates.post + */ + addOrganizationReportSettingsTemplate( + request: ReportsModel.AddOrganizationReportSettingsRequest, + ): Promise<ResponseObject<ReportsModel.OrganizationReportSettings>> { + const url = `${this.url}/reports/settings-templates`; + return this.post(url, request, this.defaultConfig()); + } + + /** + * @param reportSettingsTemplateId report settings template identifier + * @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/Reports/operation/api.reports.settings-templates.get + */ + getOrganizationReportSettingsTemplate( + reportSettingsTemplateId: number, + ): Promise<ResponseObject<ReportsModel.OrganizationReportSettings>> { + const url = `${this.url}/reports/settings-templates/${reportSettingsTemplateId}`; + return this.get(url, this.defaultConfig()); + } + + /** + * @param reportSettingsTemplateId report settings template identifier + * @param request request body + * @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/Reports/operation/api.reports.settings-templates.patch + */ + editOrganizationReportSettingsTemplate( + reportSettingsTemplateId: number, + request: PatchRequest[], + ): Promise<ResponseObject<ReportsModel.OrganizationReportSettings>> { + const url = `${this.url}/reports/settings-templates/${reportSettingsTemplateId}`; + return this.patch(url, request, this.defaultConfig()); + } + + /** + * @param reportSettingsTemplateId report settings template identifier + * @see https://support.crowdin.com/developer/enterprise/api/v2/#tag/Reports/operation/api.reports.settings-templates.delete + */ + deleteOrganizationReportSettingsTemplate(reportSettingsTemplateId: number): Promise<void> { + const url = `${this.url}/reports/settings-templates/${reportSettingsTemplateId}`; + return this.delete(url, this.defaultConfig()); + } + /** * @param request request body * @see https://support.crowdin.com/enterprise/api/#operation/api.reports.post @@ -284,7 +341,7 @@ export class Reports extends CrowdinApi { */ addReportSettingsTemplate( projectId: number, - request: Omit<ReportsModel.ReportSettings, 'id' | 'createdAt' | 'updatedAt'>, + request: ReportsModel.AddReportSettingsRequest, ): Promise<ResponseObject<ReportsModel.ReportSettings>> { const url = `${this.url}/projects/${projectId}/reports/settings-templates`; return this.post(url, request, this.defaultConfig()); @@ -327,12 +384,76 @@ export class Reports extends CrowdinApi { const url = `${this.url}/projects/${projectId}/reports/settings-templates/${reportSettingsTemplateId}`; return this.delete(url, this.defaultConfig()); } + + /** + * @param userId user identifier + * @param options optional parameters for the request + * @see https://support.crowdin.com/developer/api/v2/#tag/Reports/operation/api.users.reports.settings-templates.getMany + */ + listUserReportSettingsTemplates( + userId: number, + options?: PaginationOptions, + ): Promise<ResponseList<ReportsModel.UserReportSettings>> { + const url = `${this.url}/users/${userId}/reports/settings-templates`; + return this.getList(url, options?.limit, options?.offset); + } + + /** + * @param userId user identifier + * @param request request body + * @see https://support.crowdin.com/developer/api/v2/#tag/Reports/operation/api.users.reports.settings-templates.post + */ + addUserReportSettingsTemplate( + userId: number, + request: ReportsModel.AddUserReportSettingsRequest, + ): Promise<ResponseObject<ReportsModel.UserReportSettings>> { + const url = `${this.url}/users/${userId}/reports/settings-templates`; + return this.post(url, request, this.defaultConfig()); + } + + /** + * @param userId user identifier + * @param reportSettingsTemplateId report settings template identifier + * @see https://support.crowdin.com/developer/api/v2/#tag/Reports/operation/api.users.reports.settings-templates.get + */ + getUserReportSettingsTemplate( + userId: number, + reportSettingsTemplateId: number, + ): Promise<ResponseObject<ReportsModel.UserReportSettings>> { + const url = `${this.url}/users/${userId}/reports/settings-templates/${reportSettingsTemplateId}`; + return this.get(url, this.defaultConfig()); + } + + /** + * @param userId user identifier + * @param reportSettingsTemplateId report settings template identifier + * @param request request body + * @see https://support.crowdin.com/developer/api/v2/#tag/Reports/operation/api.users.reports.settings-templates.patch + */ + editUserReportSettingsTemplate( + userId: number, + reportSettingsTemplateId: number, + request: PatchRequest[], + ): Promise<ResponseObject<ReportsModel.UserReportSettings>> { + const url = `${this.url}/users/${userId}/reports/settings-templates/${reportSettingsTemplateId}`; + return this.patch(url, request, this.defaultConfig()); + } + + /** + * @param userId user identifier + * @param reportSettingsTemplateId report settings template identifier + * @see https://support.crowdin.com/developer/api/v2/#tag/Reports/operation/api.users.reports.settings-templates.delete + */ + deleteUserReportSettingsTemplate(userId: number, reportSettingsTemplateId: number): Promise<void> { + const url = `${this.url}/users/${userId}/reports/settings-templates/${reportSettingsTemplateId}`; + return this.delete(url, this.defaultConfig()); + } } export namespace ReportsModel { export interface ReportArchive { id: number; - scopeType: number; + scopeType: string; scopeId: number; userId: number; name: string; @@ -375,6 +496,7 @@ export namespace ReportsModel { individualRates: IndividualRate[]; netRateSchemes: NetRateSchemas; excludeApprovalsForEditedTranslations?: boolean; + preTranslatedStringsCategorizationAdjustment?: boolean; groupBy?: GroupBy; dateFrom?: string; dateTo?: string; @@ -439,32 +561,78 @@ export namespace ReportsModel { dateTo?: string; } - export type ReportSchema = - | CostEstimationPostEndingSchema - | CostEstimationPostEndingSchemaByTask - | TranslationCostsPostEndingSchema - | TranslationCostsPostEndingSchemaByTask - | TopMembersSchema - | ContributionRawDataSchema - | PreTranslateEfficiencySchema; + export type GenerateReportRequest = + | PreTranslateAccuracy + | TranslateAccuracy + | CostEstimationPostEnding + | TranslationCostsPostEnding + | TopMembers + | ContributionRawData; + + export type ReportSchema = Pick<GenerateReportRequest, 'schema'>; + + export interface PreTranslateAccuracy { + name: 'pre-translate-efficiency' | 'pre-translate-accuracy'; + schema: PreTranslateAccuracySchema | PreTranslateAccuracySchemaByTask; + } + + export interface TranslateAccuracy { + name: 'translator-accuracy'; + schema: TranslateAccuracySchema; + } + + export interface CostEstimationPostEnding { + name: 'costs-estimation-pe'; + schema: CostEstimationPostEndingSchema | CostEstimationPostEndingSchemaByTask; + } + + export interface TranslationCostsPostEnding { + name: 'translation-costs-pe'; + schema: TranslationCostsPostEndingSchema | TranslationCostsPostEndingSchemaByTask; + } + + export interface TopMembers { + name: 'top-members'; + schema: TopMembersSchema; + } - export interface GenerateReportRequest { - name: - | 'top-members' - | 'contribution-raw-data' - | 'costs-estimation-pe' - | 'translation-costs-pe' - | 'pre-translate-efficiency'; - schema: ReportSchema; + export interface ContributionRawData { + name: 'contribution-raw-data'; + schema: ContributionRawDataSchema | ContributionRawDataSchemaByTask; } export interface ReportStatusAttributes<S> { format: Format; reportName: string; - projectIds?: number[]; schema: S; } + export interface PreTranslateAccuracySchema { + unit?: Unit; + format?: Format; + postEditingCategories?: string[]; + languageId?: string; + dateFrom?: string; + dateTo?: string; + } + + export interface PreTranslateAccuracySchemaByTask { + unit?: Unit; + format?: Format; + postEditingCategories?: string[]; + taskId?: number; + } + + export interface TranslateAccuracySchema { + unit?: Unit; + format?: Format; + postEditingCategories?: string[]; + languageId?: string; + userIds?: number[]; + dateFrom?: string; + dateTo?: string; + } + export interface CostEstimationPostEndingSchema { unit?: Unit; currency?: Currency; @@ -506,6 +674,7 @@ export namespace ReportsModel { netRateSchemes: NetRateSchemas; taskId?: number; excludeApprovalsForEditedTranslations?: boolean; + preTranslatedStringsCategorizationAdjustment?: boolean; } export interface TranslationCostsPostEndingSchema { @@ -575,6 +744,11 @@ export namespace ReportsModel { dateTo?: string; } + export interface ListOrganizationReportSettingsParams extends PaginationOptions { + projectId?: number; + groupId?: number; + } + export interface ReportSettings { id: number; name: string; @@ -582,10 +756,32 @@ export namespace ReportsModel { unit: Unit; config: ReportSettinsConfig; isPublic: boolean; + isGlobal: boolean; createdAt: string; updatedAt: string; } + export interface AddReportSettingsRequest { + name: string; + currency: Currency; + unit: Unit; + config: ReportSettinsConfig; + isPublic?: boolean; + isGlobal?: boolean; + } + + export type UserReportSettings = Omit<ReportSettings, 'isPublic' | 'isGlobal'>; + export type AddUserReportSettingsRequest = Omit<AddReportSettingsRequest, 'isPublic' | 'isGlobal'>; + + export type OrganizationReportSettings = Omit<ReportSettings, 'isGlobal'> & { + projectId: number; + groupId: number; + }; + export type AddOrganizationReportSettingsRequest = Omit<AddReportSettingsRequest, 'isGlobal'> & { + projectId?: number; + groupId?: number; + }; + export interface ReportSettinsConfig { baseRates: BaseRate; netRateSchemes: NetRateSchemas[]; @@ -637,11 +833,15 @@ export namespace ReportsModel { matchType: Mode; price: number; }[]; - mtMatch?: { + mtMatch: { + matchType: Mode; + price: number; + }[]; + suggestionMatch: { matchType: Mode; price: number; }[]; - suggestionMatch?: { + aiMatch?: { matchType: Mode; price: number; }[]; diff --git a/tests/reports/api.test.ts b/tests/reports/api.test.ts index 9901cb765..c6b993709 100644 --- a/tests/reports/api.test.ts +++ b/tests/reports/api.test.ts @@ -210,6 +210,79 @@ describe('Reports API', () => { url: downloadLink, }, }) + .get('/reports/settings-templates', undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: [ + { + data: { + id: reportSettingsTemplateId, + }, + }, + ], + pagination: { + offset: 0, + limit: 1, + }, + }) + .post( + '/reports/settings-templates', + { + name: reportName, + currency, + unit, + config, + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + id: reportSettingsTemplateId, + }, + }) + .get(`/reports/settings-templates/${reportSettingsTemplateId}`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: { + id: reportSettingsTemplateId, + }, + }) + .patch( + `/reports/settings-templates/${reportSettingsTemplateId}`, + [ + { + value: reportName, + op: 'replace', + path: '/name', + }, + ], + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + id: reportSettingsTemplateId, + }, + }) + .delete(`/reports/settings-templates/${reportSettingsTemplateId}`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200) .post( '/reports', { @@ -357,6 +430,79 @@ describe('Reports API', () => { Authorization: `Bearer ${api.token}`, }, }) + .reply(200) + .get(`/users/${userId}/reports/settings-templates`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: [ + { + data: { + id: reportSettingsTemplateId, + }, + }, + ], + pagination: { + offset: 0, + limit: 1, + }, + }) + .post( + `/users/${userId}/reports/settings-templates`, + { + name: reportName, + currency, + unit, + config, + }, + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + id: reportSettingsTemplateId, + }, + }) + .get(`/users/${userId}/reports/settings-templates/${reportSettingsTemplateId}`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) + .reply(200, { + data: { + id: reportSettingsTemplateId, + }, + }) + .patch( + `/users/${userId}/reports/settings-templates/${reportSettingsTemplateId}`, + [ + { + value: reportName, + op: 'replace', + path: '/name', + }, + ], + { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }, + ) + .reply(200, { + data: { + id: reportSettingsTemplateId, + }, + }) + .delete(`/users/${userId}/reports/settings-templates/${reportSettingsTemplateId}`, undefined, { + reqheaders: { + Authorization: `Bearer ${api.token}`, + }, + }) .reply(200); }); @@ -444,6 +590,43 @@ describe('Reports API', () => { expect(downloadUrl.data.url).toBe(downloadLink); }); + it('List Organization Report Settings Templates', async () => { + const templates = await api.listOrganizationReportSettingsTemplates(); + expect(templates.data.length).toBe(1); + expect(templates.data[0].data.id).toBe(reportSettingsTemplateId); + expect(templates.pagination.limit).toBe(1); + }); + + it('Add Organization Report Settings Template', async () => { + const template = await api.addOrganizationReportSettingsTemplate({ + config, + currency, + name: reportName, + unit, + }); + expect(template.data.id).toBe(reportSettingsTemplateId); + }); + + it('Get Organization Report Settings Template', async () => { + const template = await api.getOrganizationReportSettingsTemplate(reportSettingsTemplateId); + expect(template.data.id).toBe(reportSettingsTemplateId); + }); + + it('Edit Organization Report Settings Template', async () => { + const template = await api.editOrganizationReportSettingsTemplate(reportSettingsTemplateId, [ + { + op: 'replace', + path: '/name', + value: reportName, + }, + ]); + expect(template.data.id).toBe(reportSettingsTemplateId); + }); + + it('Delete Organization Report Settings Template', async () => { + await api.deleteOrganizationReportSettingsTemplate(reportSettingsTemplateId); + }); + it('Generate Organization Report', async () => { const report = await api.generateOrganizationReport({ name: reportName, @@ -517,4 +700,41 @@ describe('Reports API', () => { it('Delete Report Settings Template', async () => { await api.deleteReportSettingsTemplate(projectId, reportSettingsTemplateId); }); + + it('List User Report Settings Templates', async () => { + const templates = await api.listUserReportSettingsTemplates(userId); + expect(templates.data.length).toBe(1); + expect(templates.data[0].data.id).toBe(reportSettingsTemplateId); + expect(templates.pagination.limit).toBe(1); + }); + + it('Add User Report Settings Template', async () => { + const template = await api.addUserReportSettingsTemplate(userId, { + config, + currency, + name: reportName, + unit, + }); + expect(template.data.id).toBe(reportSettingsTemplateId); + }); + + it('Get User Report Settings Template', async () => { + const template = await api.getUserReportSettingsTemplate(userId, reportSettingsTemplateId); + expect(template.data.id).toBe(reportSettingsTemplateId); + }); + + it('Edit User Report Settings Template', async () => { + const template = await api.editUserReportSettingsTemplate(userId, reportSettingsTemplateId, [ + { + op: 'replace', + path: '/name', + value: reportName, + }, + ]); + expect(template.data.id).toBe(reportSettingsTemplateId); + }); + + it('Delete User Report Settings Template', async () => { + await api.deleteUserReportSettingsTemplate(userId, reportSettingsTemplateId); + }); });