Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9d0109c
Modified src/reference/openapi.yml
Jan 23, 2026
777fcce
Modified src/reference/openapi.yml
Jan 27, 2026
11e9c13
feat: add POST /campaigns/{campaign}/finance/attachments route and up…
iDome89 Jan 27, 2026
39443da
Modified src/reference/openapi.yml
Jan 28, 2026
c2577d2
Modified src/reference/openapi.yml
Jan 28, 2026
c075223
Modified src/reference/openapi.yml
Jan 28, 2026
ee47019
feat: add endpoint to create a new campaign supplier
Kariamos Jan 28, 2026
09288fd
feat: implement POST route for campaign finance supplier with validation
Kariamos Jan 28, 2026
7e105f7
fix: update @appquality/tryber-database version to 0.46.17 in package…
Kariamos Jan 29, 2026
e3163d5
Modified src/reference/openapi.yml
Jan 29, 2026
d08d123
fix: update @appquality/tryber-database dependency to version 0.46.17
Kariamos Jan 29, 2026
f841044
feat: add finance type endpoint for campaigns
Kariamos Jan 29, 2026
3b762a7
feat: implement finance type retrieval for campaigns
Kariamos Jan 29, 2026
8f955c7
Merge pull request #513 from AppQuality/UN-2283-get-finance-type
iDome89 Jan 29, 2026
1cedfdc
Merge pull request #510 from AppQuality/UN-2278-post-attachment
iDome89 Jan 29, 2026
40752e0
Modified src/reference/openapi.yml
Jan 28, 2026
67ef756
Modified src/reference/openapi.yml
Jan 28, 2026
adbc425
Modified src/reference/openapi.yml
Jan 28, 2026
933e544
feat: add finance suppliers endpoints for campaigns
Kariamos Jan 28, 2026
2e12057
Modified src/reference/openapi.yml
Jan 28, 2026
d1f9a38
refactor: update finance suppliers endpoint and remove duplicated ope…
Kariamos Jan 28, 2026
c9de030
feat: implement finance suppliers endpoint for campaigns
Kariamos Jan 28, 2026
9dc4013
refactor: enhance tests for finance suppliers endpoint and improve cl…
Kariamos Jan 29, 2026
fab376b
Modified src/reference/openapi.yml
Jan 29, 2026
d5d4c81
refactor: remove redundant 'id' field from operations interface
Kariamos Jan 29, 2026
8780256
refactor: remove 'id' field from Supplier type and related queries
Kariamos Jan 29, 2026
963432e
refactor: remove duplicated finance suppliers endpoint from campaigns…
Kariamos Jan 29, 2026
23cf049
refactor: update finance supplier endpoint and adjust related operations
Kariamos Jan 29, 2026
476fc0d
Merge pull request #511 from AppQuality/UN-2281-get-finance-suppliers
Kariamos Jan 29, 2026
e644d3c
Merge branch 'UN-2274-other-costs' into UN-2278-post-campaign-supplier
Kariamos Jan 29, 2026
1d1bb3f
refactor: update campaign finance supplier endpoint to remove unneces…
Kariamos Jan 29, 2026
422ea7d
refactor: enhance post campaign finance supplier endpoint with detail…
Kariamos Jan 29, 2026
67ec301
Modified src/reference/openapi.yml
Jan 29, 2026
a08afd8
refactor: simplify response schema for post campaign operation
Kariamos Jan 29, 2026
cbf0f1e
fix: correct error handling message for supplier creation
Kariamos Jan 29, 2026
8336be7
Merge pull request #512 from AppQuality/UN-2278-post-campaign-supplier
Kariamos Jan 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 51 additions & 23 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
"author": "",
"license": "ISC",
"dependencies": {
"@appquality/tryber-database": "^0.46.11",
"@appquality/tryber-database": "^0.46.17",
"@appquality/wp-auth": "^1.0.7",
"@aws-crypto/sha256-js": "^5.2.0",
"@aws-sdk/hash-node": "^3.374.0",
Expand Down
220 changes: 220 additions & 0 deletions src/reference/openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3981,6 +3981,82 @@ paths:
required: true
schema:
type: string
'/campaigns/{campaign}/finance/attachments':
parameters:
- schema:
type: string
name: campaign
in: path
required: true
post:
summary: Your POST endpoint
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
properties:
attachments:
type: array
items:
type: object
required:
- url
- name
- mime_type
properties:
url:
type: string
name:
type: string
mime_type:
type: string
failed:
type: array
items:
type: object
required:
- name
- path
properties:
name:
type: string
path:
type: string
'403':
$ref: '#/components/responses/NotAuthorized'
'500':
description: Internal Server Error
operationId: post-campaigns-campaign-finance-attachments
x-stoplight:
id: 0ucra88nj3skb
security:
- JWT: []
requestBody:
content:
multipart/form-data:
schema:
type: object
properties:
attachment:
x-stoplight:
id: loo9qp15yg7er
oneOf:
- type: string
x-stoplight:
id: 1y0da4vjut50n
format: binary
- type: array
x-stoplight:
id: 567eldf6sv5mh
items:
x-stoplight:
id: ykrxebcilk657
type: string
format: binary
'/campaigns/{campaign}/forms':
get:
description: ''
Expand Down Expand Up @@ -13199,6 +13275,150 @@ 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
post:
summary: POST a new supplier
operationId: post-campaigns-campaign-finance-supplier
tags:
- Campaign
responses:
'201':
description: Created
content: {}
'400':
description: Bad Request
'403':
description: Forbidden
'500':
description: Internal Server Error
security:
- JWT: []
requestBody:
content:
application/json:
schema:
type: object
required:
- name
properties:
name:
type: string
examples:
Example 1:
value:
name: Respondent
x-stoplight:
id: j17dlfvjwluu7
'/campaigns/{campaign}/finance/type':
parameters:
- schema:
type: string
name: campaign
in: path
required: true
get:
summary: GET types
tags: []
responses:
'200':
description: OK
content:
application/json:
schema:
type: object
required:
- items
properties:
items:
type: array
x-stoplight:
id: d7f0e5l5qrx6o
items:
x-stoplight:
id: r1p9rcymebjpu
type: object
properties:
name:
type: string
x-stoplight:
id: y0keeoutvijjh
examples:
Example 1:
value:
items:
- name: Recruiting
- name: Survey
'403':
$ref: '#/components/responses/NotAuthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
description: Internal Server Error
operationId: get-campaigns-campaign-finance-type
x-stoplight:
id: 02e8ns5xdhecm
security:
- JWT: []
servers:
- url: 'https://api.app-quality.com'
tags:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import app from "@src/app";
import { tryber } from "@src/features/database";
import upload from "@src/features/upload";
import request from "supertest";

jest.mock("@src/features/upload");

const profile = {
id: 1,
wp_user_id: 1,
email: "tester@example.com",
employment_id: 1,
education_id: 1,
};
const wpUser = {
ID: 1,
user_login: "tester",
user_email: "tester@example.com",
user_pass: "pass",
};
const campaign = {
id: 1,
title: "Test Campaign",
customer_title: "Test Campaign",
start_date: "2020-01-01",
end_date: "2020-01-01",
pm_id: 1,
page_manual_id: 0,
page_preview_id: 0,
platform_id: 1,
customer_id: 1,
project_id: 1,
};

const campaign2 = {
...campaign,
id: 2,
};

describe("Route POST /campaigns/{campaignId}/finance/attachments", () => {
beforeAll(async () => {
(upload as jest.Mock).mockImplementation(
({ key, bucket }: { bucket: string; key: string }) => {
return `https://s3.amazonaws.com/${bucket}/${key}`;
}
);
await tryber.tables.WpUsers.do().insert(wpUser);
await tryber.tables.WpAppqEvdProfile.do().insert(profile);
await tryber.tables.WpAppqEvdCampaign.do().insert([campaign, campaign2]);
});

afterAll(async () => {
await tryber.tables.WpUsers.do().delete();
await tryber.tables.WpAppqEvdProfile.do().delete();
await tryber.tables.WpAppqEvdCampaign.do().delete();
});

it("Should answer 403 if not logged in", async () => {
const response = await request(app).post(
"/campaigns/1/finance/attachments"
);
expect(response.status).toBe(403);
});

it("Should answer 200 and mark as failed if try to send file as .bat, .sh and .exe", async () => {
const mockFileBuffer = Buffer.from("some data");

const response = await request(app)
.post("/campaigns/1/finance/attachments")
.attach("media", mockFileBuffer, "void.bat")
.attach("media", mockFileBuffer, "image.png")
.attach("media", mockFileBuffer, "void.sh")
.attach("media", mockFileBuffer, "void.exe")
.set("authorization", 'Bearer tester olp {"appq_campaign":[1]}');

expect(response.status).toBe(200);
expect(response.body).toHaveProperty("failed", [
{ path: "INVALID_FILE_EXTENSION", name: "void.bat" },
{ path: "INVALID_FILE_EXTENSION", name: "void.sh" },
{ path: "INVALID_FILE_EXTENSION", name: "void.exe" },
]);
});

it("Should answer 200 and mark as failed if try to send an oversized file", async () => {
process.env.MAX_FILE_SIZE = "100";
const mockFileBuffer = Buffer.alloc(101);

const response = await request(app)
.post("/campaigns/1/finance/attachments")
.attach("media", mockFileBuffer, "oversized.png")
.set("authorization", 'Bearer tester olp {"appq_campaign":[1]}');

expect(response.status).toBe(200);
expect(response.body).toHaveProperty("failed", [
{ path: "FILE_TOO_BIG", name: "oversized.png" },
]);
});
});
Loading
Loading