diff --git a/src/reference/openapi.yml b/src/reference/openapi.yml index 568641bb7..0593f1d08 100644 --- a/src/reference/openapi.yml +++ b/src/reference/openapi.yml @@ -3988,11 +3988,6 @@ paths: name: campaign in: path required: true - - schema: - type: string - name: campaign - in: path - required: true post: summary: Your POST endpoint tags: [] @@ -13282,6 +13277,67 @@ paths: - jotformId - testerQuestionId description: '' + '/campaigns/{campaign}/finance/supplier': + get: + description: Get all finance suppliers + operationId: get-campaigns-campaign-finance-supplier + responses: + '200': + description: OK + content: + application/json: + schema: + type: object + required: + - items + properties: + items: + type: array + x-stoplight: + id: hhr19m5dfxjtt + items: + x-stoplight: + id: ihcfe7bywmrjs + type: object + required: + - name + properties: + name: + type: string + x-stoplight: + id: 08yzm5eu8tl1h + created_at: + type: string + x-stoplight: + id: w0fmflgc090ff + created_by: + type: integer + x-stoplight: + id: gcs2p8mvl32gc + examples: + Example 2: + value: + items: + - name: Respondent + created_at: '2026-01-01' + created_by: 10 + '400': + description: Bad Request + '403': + description: Forbidden + '500': + description: Internal Server Error + security: + - JWT: [] + summary: Get finance supplier + x-stoplight: + id: tlziygldrfder + parameters: + - schema: + type: string + name: campaign + in: path + required: true '/campaigns/{campaign}/finance/type': parameters: - schema: diff --git a/src/routes/campaigns/campaignId/finance/supplier/_get/index.spec.ts b/src/routes/campaigns/campaignId/finance/supplier/_get/index.spec.ts new file mode 100644 index 000000000..ee1bf1af0 --- /dev/null +++ b/src/routes/campaigns/campaignId/finance/supplier/_get/index.spec.ts @@ -0,0 +1,136 @@ +import request from "supertest"; +import app from "@src/app"; +import { tryber } from "@src/features/database"; + +describe("GET /campaigns/campaignId/finance/supplier", () => { + beforeAll(async () => { + await tryber.tables.WpAppqEvdProfile.do().insert([ + { + id: 1, + name: "John", + surname: "Doe", + wp_user_id: 1, + email: "", + employment_id: 1, + education_id: 1, + }, + { + id: 2, + name: "John", + surname: "Doe", + wp_user_id: 2, + email: "", + employment_id: 1, + education_id: 1, + }, + ]); + await tryber.tables.WpUsers.do().insert([{ ID: 1 }, { ID: 2 }]); + await tryber.tables.WpAppqEvdCampaign.do().insert({ + id: 1, + platform_id: 1, + start_date: "2020-01-01", + end_date: "2020-01-01", + title: "This is the title", + page_preview_id: 1, + page_manual_id: 1, + customer_id: 1, + pm_id: 1, + project_id: 1, + customer_title: "", + }); + await tryber.tables.WpAppqCampaignOtherCostsSupplier.do().insert([ + { + id: 1, + name: "Supplier 1", + created_by: 1, + created_on: "2024-01-01 10:00:00", + }, + { + id: 2, + name: "Supplier 2", + created_by: 2, + created_on: "2024-01-02 11:00:00", + }, + ]); + }); + + afterAll(async () => { + await tryber.tables.WpAppqCampaignOtherCostsSupplier.do().delete(); + await tryber.tables.WpAppqEvdCampaign.do().delete(); + await tryber.tables.WpUsers.do().delete(); + await tryber.tables.WpAppqEvdProfile.do().delete(); + }); + + it("Should return 403 if logged out", async () => { + const response = await request(app).get("/campaigns/1/finance/supplier"); + expect(response.status).toBe(403); + }); + + it("Should return 403 if logged in as not admin user", async () => { + const response = await request(app) + .get("/campaigns/1/finance/supplier") + .set("Authorization", "Bearer tester"); + expect(response.status).toBe(403); + }); + + it("Should return 403 if no access to the campaign", async () => { + const response = await request(app) + .get("/campaigns/1/finance/supplier") + .set("Authorization", 'Bearer tester"'); + expect(response.status).toBe(403); + }); + + it("Should return 200 if logged in as admin", async () => { + const response = await request(app) + .get("/campaigns/1/finance/supplier") + .set("Authorization", "Bearer admin"); + expect(response.status).toBe(200); + }); + + it("Should return finance suppliers - admin", async () => { + const response = await request(app) + .get("/campaigns/1/finance/supplier") + .set("Authorization", "Bearer admin"); + expect(response.body).toEqual( + expect.objectContaining({ + items: expect.arrayContaining([ + expect.objectContaining({ + name: "Supplier 1", + created_by: 1, + created_on: "2024-01-01 10:00:00", + }), + expect.objectContaining({ + name: "Supplier 2", + created_by: 2, + created_on: "2024-01-02 11:00:00", + }), + ]), + }) + ); + expect(response.body.items).toHaveLength(2); + }); + + it("Should return suppliers - olp permissions", async () => { + const response = await request(app) + .get("/campaigns/1/finance/supplier") + .set("Authorization", 'Bearer tester olp {"appq_campaign":[1]}'); + expect(response.status).toBe(200); + expect(response.body).toEqual( + expect.objectContaining({ + items: expect.arrayContaining([ + expect.objectContaining({ + name: "Supplier 1", + created_by: 1, + created_on: "2024-01-01 10:00:00", + }), + expect.objectContaining({ + name: "Supplier 2", + created_by: 2, + created_on: "2024-01-02 11:00:00", + }), + ]), + }) + ); + expect(response.body.items).toHaveLength(2); + }); +}); diff --git a/src/routes/campaigns/campaignId/finance/supplier/_get/index.ts b/src/routes/campaigns/campaignId/finance/supplier/_get/index.ts new file mode 100644 index 000000000..807584851 --- /dev/null +++ b/src/routes/campaigns/campaignId/finance/supplier/_get/index.ts @@ -0,0 +1,41 @@ +/** OPENAPI-CLASS: get-campaigns-campaign-finance-supplier */ + +import CampaignRoute from "@src/features/routes/CampaignRoute"; +import { tryber } from "@src/features/database"; +import OpenapiError from "@src/features/OpenapiError"; + +type Supplier = { + name: string; + created_on?: string; + created_by?: number; +}; + +export default class SupplierRoute extends CampaignRoute<{ + response: StoplightOperations["get-campaigns-campaign-finance-supplier"]["responses"]["200"]["content"]["application/json"]; + parameters: StoplightOperations["get-campaigns-campaign-finance-supplier"]["parameters"]["path"]; +}> { + protected async filter(): Promise { + if (!(await super.filter())) return false; + + if (!this.hasAccessToCampaign(this.cp_id)) { + this.setError(403, new OpenapiError("Access denied")); + + return false; + } + return true; + } + + protected async prepare(): Promise { + const suppliers = await this.getSuppliers(); + + return this.setSuccess(200, { items: suppliers }); + } + + private async getSuppliers(): Promise { + return await tryber.tables.WpAppqCampaignOtherCostsSupplier.do().select( + "name", + "created_on", + "created_by" + ); + } +} diff --git a/src/schema.ts b/src/schema.ts index e65ad0843..f7bd799a7 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -804,6 +804,15 @@ export interface paths { }; }; }; + "/campaigns/{campaign}/finance/supplier": { + /** Get all finance suppliers */ + get: operations["get-campaigns-campaign-finance-supplier"]; + parameters: { + path: { + campaign: string; + }; + }; + }; "/campaigns/{campaign}/finance/type": { get: operations["get-campaigns-campaign-finance-type"]; parameters: { @@ -5521,6 +5530,34 @@ export interface operations { }; }; }; + /** Get all finance suppliers */ + "get-campaigns-campaign-finance-supplier": { + parameters: { + path: { + campaign: string; + }; + }; + responses: { + /** OK */ + 200: { + content: { + "application/json": { + items: { + name: string; + created_at?: string; + created_by?: number; + }[]; + }; + }; + }; + /** Bad Request */ + 400: unknown; + /** Forbidden */ + 403: unknown; + /** Internal Server Error */ + 500: unknown; + }; + }; "get-campaigns-campaign-finance-type": { parameters: { path: {