• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

GEWIS / sudosos-backend / 25753937432

12 May 2026 09:17AM UTC coverage: 88.117% (-1.0%) from 89.089%
25753937432

push

github

web-flow
chore(deps): fix missing dependencies for running docs:dev (#911)

3925 of 4574 branches covered (85.81%)

Branch coverage included in aggregate %.

20093 of 22683 relevant lines covered (88.58%)

1125.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.23
/src/controller/voucher-group-controller.ts
1
/**
1✔
2
 *  SudoSOS back-end API service.
3
 *  Copyright (C) 2026 Study association GEWIS
4
 *
5
 *  This program is free software: you can redistribute it and/or modify
6
 *  it under the terms of the GNU Affero General Public License as published
7
 *  by the Free Software Foundation, either version 3 of the License, or
8
 *  (at your option) any later version.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU Affero General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU Affero General Public License
16
 *  along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
 *
18
 *  @license
19
 */
1✔
20

21
/**
1✔
22
 * This is the module page of the voucher-group-controller.
23
 *
24
 * @module vouchers
25
 */
1✔
26

27
import { Response } from 'express';
28
import log4js, { Logger } from 'log4js';
29
import BaseController, { BaseControllerOptions } from './base-controller';
30
import Policy from './policy';
31
import { VoucherGroupRequest } from './request/voucher-group-request';
32
import { RequestWithToken } from '../middleware/token-middleware';
33
import VoucherGroup from '../entity/user/voucher-group';
34
import VoucherGroupService from '../service/voucher-group-service';
35
import { parseRequestPagination, toResponse } from '../helpers/pagination';
36

37
export default class VoucherGroupController extends BaseController {
1✔
38
  private logger: Logger = log4js.getLogger('VoucherGroupController');
1✔
39

40
  public constructor(options: BaseControllerOptions) {
1✔
41
    super(options);
16✔
42
    this.configureLogger(this.logger);
16✔
43
  }
16✔
44

45
  /**
1✔
46
   * @inheritdoc
47
   */
1✔
48
  public getPolicy(): Policy {
1✔
49
    return {
16✔
50
      '/': {
16✔
51
        GET: {
16✔
52
          policy: async (req) => this.roleManager.can(req.token.roles, 'get', 'all', 'VoucherGroup', ['*']),
16✔
53
          handler: this.getAllVoucherGroups.bind(this),
16✔
54
        },
16✔
55
        POST: {
16✔
56
          body: { modelName: 'VoucherGroupRequest' },
16✔
57
          policy: async (req) => this.roleManager.can(req.token.roles, 'create', 'all', 'VoucherGroup', ['*']),
16✔
58
          handler: this.createVoucherGroup.bind(this),
16✔
59
        },
16✔
60
      },
16✔
61
      '/:id(\\d+)': {
16✔
62
        GET: {
16✔
63
          policy: async (req) => this.roleManager.can(req.token.roles, 'get', 'all', 'VoucherGroup', ['*']),
16✔
64
          handler: this.getVoucherGroupById.bind(this),
16✔
65
        },
16✔
66
        PATCH: {
16✔
67
          body: { modelName: 'VoucherGroupRequest' },
16✔
68
          policy: async (req) => this.roleManager.can(req.token.roles, 'update', 'all', 'VoucherGroup', ['*']),
16✔
69
          handler: this.updateVoucherGroup.bind(this),
16✔
70
        },
16✔
71
      },
16✔
72
    };
16✔
73
  }
16✔
74

75
  /**
1✔
76
   * GET /vouchergroups
77
   * @summary Returns all existing voucher groups
78
   * @operationId getAllVouchergroups
79
   * @tags vouchergroups - Operations of voucher group controller
80
   * @security JWT
81
   * @param {integer} take.query - How many voucher groups the endpoint should return
82
   * @param {integer} skip.query - How many voucher groups should be skipped (for pagination)
83
   * @return {PaginatedVoucherGroupResponse} 200 - All existingvoucher
84
   * groups without users
85
   * @return {string} 500 - Internal server error
86
   */
1✔
87
  public async getAllVoucherGroups(req: RequestWithToken, res: Response): Promise<void> {
1✔
88
    const { body } = req;
2✔
89
    this.logger.trace('Get all voucher groups', body, 'by user', req.token.user);
2✔
90

91
    let take;
2✔
92
    let skip;
2✔
93
    try {
2✔
94
      const pagination = parseRequestPagination(req);
2✔
95
      take = pagination.take;
2✔
96
      skip = pagination.skip;
2✔
97
    } catch (e) {
2!
98
      res.status(400).send(e.message);
×
99
      return;
×
100
    }
×
101

102
    // handle request
2✔
103
    try {
2✔
104
      const [bkgs, count] = await VoucherGroupService.getVoucherGroups({}, { take, skip });
2✔
105
      const records = bkgs.map((bkg) => VoucherGroupService.asVoucherGroupResponse(bkg, bkg.vouchers.map((v) => v.user)));
2✔
106
      res.json(toResponse(records, count, { take, skip }));
2✔
107
    } catch (error) {
2!
108
      this.logger.error('Could not return all voucher groups:', error);
×
109
      res.status(500).json('Internal server error.');
×
110
    }
×
111
  }
2✔
112

113
  /**
1✔
114
   * POST /vouchergroups
115
   * @summary Creates a new voucher group
116
   * @operationId createVouchergroup
117
   * @tags vouchergroups - Operations of voucher group controller
118
   * @param {VoucherGroupRequest} request.body.required -
119
   * The voucher group which should be created
120
   * @security JWT
121
   * @return {VoucherGroupResponse} 200 - The created voucher group entity
122
   * @return {string} 400 - Validation error
123
   * @return {string} 500 - Internal server error
124
   */
1✔
125
  public async createVoucherGroup(req: RequestWithToken, res: Response): Promise<void> {
1✔
126
    const body = req.body as VoucherGroupRequest;
3✔
127
    this.logger.trace('Create voucher group', body, 'by user', req.token.user);
3✔
128

129
    const voucherGroupParams = VoucherGroupService.asVoucherGroupParams(body);
3✔
130

131
    // handle request
3✔
132
    try {
3✔
133
      if (!VoucherGroupService.validateVoucherGroup(voucherGroupParams)) {
3✔
134
        res.status(400).json('Invalid voucher group.');
1✔
135
        return;
1✔
136
      }
1✔
137
      const { voucherGroup, users } = await VoucherGroupService.createVoucherGroup(voucherGroupParams);
2✔
138
      res.json(VoucherGroupService.asVoucherGroupResponse(voucherGroup, users));
2✔
139
    } catch (error) {
3!
140
      this.logger.error('Could not create voucher group:', error);
×
141
      res.status(500).json('Internal server error.');
×
142
    }
×
143
  }
3✔
144

145
  /**
1✔
146
   * GET /vouchergroups/{id}
147
   * @summary Returns the requested voucher group
148
   * @operationId getVouchergroupId
149
   * @tags vouchergroups - Operations of voucher group controller
150
   * @param {integer} id.path.required - The id of the voucher group which should be returned
151
   * @security JWT
152
   * @return {VoucherGroupResponse} 200 - The requested voucher group entity
153
   * @return {string} 404 - Not found error
154
   * @return {string} 500 - Internal server error
155
   */
1✔
156
  public async getVoucherGroupById(req: RequestWithToken, res: Response): Promise<void> {
1✔
157
    const { id } = req.params;
3✔
158
    const bkgId = Number.parseInt(id, 10);
3✔
159
    this.logger.trace('Get single voucher group', id, 'by user', req.token.user);
3✔
160

161
    // handle request
3✔
162
    try {
3✔
163
      const [bkgs] = await VoucherGroupService.getVoucherGroups({ bkgId });
3✔
164
      if (bkgs[0]) {
3✔
165
        const bkg = bkgs[0];
2✔
166
        res.json(VoucherGroupService.asVoucherGroupResponse(bkg, bkg.vouchers.map((v) => v.user)));
2✔
167
      } else {
3✔
168
        res.status(404).json('Voucher group not found.');
1✔
169
      }
1✔
170
    } catch (error) {
3!
171
      this.logger.error('Could not get voucher group:', error);
×
172
      res.status(500).json('Internal server error.');
×
173
    }
×
174
  }
3✔
175

176
  /**
1✔
177
   * PATCH /vouchergroups/{id}
178
   * @summary Updates the requested voucher group
179
   * @operationId updateVoucherGroup
180
   * @tags vouchergroups - Operations of voucher group controller
181
   * @param {integer} id.path.required - The id of the voucher group which should be updated
182
   * @param {VoucherGroupRequest} request.body.required -
183
   * The updated voucher group
184
   * @security JWT
185
   * @return {VoucherGroupResponse} 200 - The requested voucher group entity
186
   * @return {string} 400 - Validation error
187
   * @return {string} 404 - Not found error
188
   * @return {string} 500 - Internal server error
189
   */
1✔
190
  public async updateVoucherGroup(req: RequestWithToken, res: Response): Promise<void> {
1✔
191
    const body = req.body as VoucherGroupRequest;
3✔
192
    const { id } = req.params;
3✔
193
    const bkgId = Number.parseInt(id, 10);
3✔
194
    this.logger.trace('Update voucher group', id, 'with', body, 'by user', req.token.user);
3✔
195

196
    const voucherGroupParams = VoucherGroupService.asVoucherGroupParams(body);
3✔
197

198
    // handle request
3✔
199
    try {
3✔
200
      if (!VoucherGroupService.validateVoucherGroup(voucherGroupParams)) {
3✔
201
        res.status(400).json('Invalid voucher group.');
1✔
202
        return;
1✔
203
      }
1✔
204
      const bkg = await VoucherGroup.findOne({ where: { id: bkgId } });
2✔
205
      if (!bkg) {
3✔
206
        res.status(404).json('Voucher group not found.');
1✔
207
        return;
1✔
208
      }
1✔
209
      if (bkg.activeStartDate <= new Date()) {
3!
210
        res.status(403).json('Voucher StartDate has already passed.');
×
211
        return;
×
212
      }
✔
213
      if (voucherGroupParams.amount < bkg.amount) {
3!
214
        res.status(400).json('Cannot decrease number of VoucherGroupUsers');
×
215
        return;
×
216
      }
✔
217
      const result = await VoucherGroupService.updateVoucherGroup(bkgId, voucherGroupParams);
1✔
218
      res.status(200).json(
1✔
219
        VoucherGroupService.asVoucherGroupResponse(result.voucherGroup, result.users),
1✔
220
      );
221
    } catch (error) {
3!
222
      this.logger.error('Could not update voucher group:', error);
×
223
      res.status(500).json('Internal server error.');
×
224
    }
×
225
  }
3✔
226
}
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc