backend.components.workers.workerController

  1from flask import Blueprint, request, send_file
  2from datetime import datetime
  3import io
  4
  5from backend.database.schema.schemas import WorkerSchema
  6from backend.components.utils.imageUtils import parse_image
  7from backend.components.workers.workerService import (
  8    create_worker, extend_worker_expiration, update_worker_name, update_worker_face_image, get_all_workers, get_worker_by_id, generate_worker_entry_pass
  9)
 10
 11bp = Blueprint('bp_workers', __name__)
 12
 13@bp.route('/api/workers', defaults={'worker_id': None}, methods=['GET'])
 14@bp.route('/api/workers/<worker_id>', methods=['GET'])
 15def get_workers(worker_id):
 16    """
 17    Retrieves workers from the database.
 18
 19    **Parameters**:
 20    - `worker_id` (int|None): The ID of the worker to retrieve. If `None`, retrieves all workers.
 21
 22    **Returns**:
 23    - `tuple`: A tuple containing the serialized worker(s) and the HTTP status code.
 24      - If `worker_id` is provided and the worker exists, returns the serialized worker and status code 200.
 25      - If `worker_id` is not provided, returns all workers and status code 200.
 26      - If the worker is not found, returns a 404 status code.
 27
 28    ---
 29    tags:
 30      - Workers
 31    parameters:
 32      - name: worker_id
 33        in: path
 34        type: integer
 35        required: false
 36        description: ID of the worker. If omitted, returns all workers.
 37    responses:
 38      200:
 39        description: Worker(s) retrieved successfully.
 40        schema:
 41          type: object
 42          description: Returns a single Worker object OR a list of Worker objects depending on the route used.
 43      404:
 44        description: Worker not found (only applicable when worker_id is provided).
 45    """
 46    if worker_id:
 47        worker = get_worker_by_id(worker_id)
 48        if not worker:
 49            return 'Worker not found', 404
 50        serialized = WorkerSchema(many=False).dump(worker)
 51    else:
 52        worker = get_all_workers()
 53        serialized = WorkerSchema(many=True).dump(worker)
 54
 55    return serialized, 200
 56
 57
 58@bp.route('/api/workers', methods=['POST'])
 59def create_worker_endpoint():
 60    """
 61    Creates a new worker in the database.
 62
 63    **Form Body**:
 64    - `name` (str): The name of the worker.
 65    - `expiration_date` (str): The expiration date for the worker's access in ISO format.
 66    - `file` (FileStorage): The image file of the worker's face.
 67
 68    **Returns**:
 69    - `tuple`: A tuple containing the serialized worker and the HTTP status code 200.
 70
 71    ---
 72    tags:
 73      - Workers
 74    consumes:
 75      - multipart/form-data
 76    parameters:
 77      - name: name
 78        in: formData
 79        type: string
 80        required: true
 81        description: The name of the worker.
 82      - name: expiration_date
 83        in: formData
 84        type: string
 85        format: date-time
 86        required: true
 87        description: Expiration date in ISO format (YYYY-MM-DDTHH:MM:SS).
 88      - name: file
 89        in: formData
 90        type: file
 91        required: true
 92        description: The image file of the worker's face.
 93    responses:
 94      200:
 95        description: Worker successfully created.
 96        schema:
 97          type: object
 98          properties:
 99            id:
100              type: integer
101            name:
102              type: string
103            expiration_date:
104              type: string
105              format: date-time
106      400:
107        description: Missing worker data.
108    """
109    name = request.form.get('name')
110    expiration_date = request.form.get('expiration_date')
111    image_file = request.files['file']
112    if not name or not expiration_date or not image_file:
113        return 'Missing worker data', 400
114
115    expiration_date = datetime.fromisoformat(expiration_date)
116    face_image = parse_image(image_file.read())
117    worker = create_worker(name, face_image, expiration_date)
118
119    # TODO: the endpoint should return **THE QR CODE**
120
121    return WorkerSchema(many=False).dump(worker), 200
122
123
124@bp.route('/api/workers/<worker_id>', methods=['PUT'])
125def update_worker(worker_id):
126    """
127    Updates an existing worker in the database.
128
129    **Parameters**:
130    - `worker_id` (int): The ID of the worker to update.
131
132    **Request Body** (multipart/form-data):
133    - `name` (str|optional): The new name for the worker.
134    - `expiration_date` (str|optional): The new expiration date in ISO format.
135    - `file` (FileStorage|optional): The new image file of the worker's face.
136
137    **Returns**:
138    - `tuple`: A tuple containing the serialized updated worker and the HTTP status code 200.
139      - If the worker is not found, returns a 404 status code.
140
141    ---
142    tags:
143      - Workers
144    consumes:
145      - multipart/form-data
146    parameters:
147      - name: worker_id
148        in: path
149        type: integer
150        required: true
151        description: The ID of the worker to update.
152      - name: name
153        in: formData
154        type: string
155        required: false
156        description: New name for the worker.
157      - name: expiration_date
158        in: formData
159        type: string
160        format: date-time
161        required: false
162        description: New expiration date (ISO format).
163      - name: file
164        in: formData
165        type: file
166        required: false
167        description: New face image file.
168    responses:
169      200:
170        description: Worker updated successfully.
171      404:
172        description: Worker not found.
173    """
174    worker = get_worker_by_id(worker_id)
175    if not worker:
176        return 'Worker not found', 404
177
178    name = request.form.get('name')
179    if name:
180        update_worker_name(worker, name)
181
182    expiration_date = request.form.get('expiration_date')
183    if expiration_date:
184        expiration_date = datetime.fromisoformat(expiration_date)
185        extend_worker_expiration(worker, expiration_date)
186
187    image_file = request.files.get('file')
188    if image_file:
189        face_image = parse_image(image_file.read())
190        update_worker_face_image(worker, face_image)
191
192    return WorkerSchema(many=False).dump(worker), 200
193
194
195@bp.route('/api/workers/invalidate/<worker_id>', methods=['PUT'])
196def invalidate_worker(worker_id):
197    """
198    Invalidate an existing worker entry permit in the database.
199
200    Sets the worker's expiration date to the current time, effectively blocking entry.
201
202    **Parameters**:
203    - `worker_id` (int): The ID of the worker to update.
204
205    **Returns**:
206    - `tuple`: A tuple containing the serialized updated worker and the HTTP status code 200.
207    - If the worker is not found, returns a 404 status code.
208
209    ---
210    tags:
211      - Workers
212    parameters:
213      - name: worker_id
214        in: path
215        type: integer
216        required: true
217        description: The ID of the worker to invalidate.
218    responses:
219      200:
220        description: Worker permit invalidated successfully.
221      404:
222        description: Worker not found.
223    """
224    worker = get_worker_by_id(worker_id)
225    if not worker:
226        return 'Worker not found', 404
227
228    expiration_date = datetime.now()
229    extend_worker_expiration(worker, expiration_date)
230
231    return WorkerSchema(many=False).dump(worker), 200
232
233
234@bp.route('/api/workers/entrypass/<worker_id>', methods=['GET'])
235def get_worker_entry_pass(worker_id):
236    """
237    Return the worker entry pass for printing.
238
239    Generates a PNG image containing the worker's details and QR code.
240
241    **Parameters**:
242    - `worker_id` (int): The ID of the worker's pass.
243
244    **Returns**:
245    - `bytes`: Entry pass image encoded as png.
246    - If the worker is not found, returns a 404 status code.
247
248    ---
249    tags:
250      - Workers
251    produces:
252      - image/png
253    parameters:
254      - name: worker_id
255        in: path
256        type: integer
257        required: true
258        description: The ID of the worker.
259    responses:
260      200:
261        description: Entry pass image generated.
262        schema:
263          type: file
264      404:
265        description: Worker not found.
266    """
267    worker = get_worker_by_id(worker_id)
268    if not worker:
269        return 'Worker not found', 404
270
271    image = generate_worker_entry_pass(worker)
272
273    return send_file(io.BytesIO(image), mimetype="image/png", as_attachment=False), 200
bp = <Blueprint 'bp_workers'>
@bp.route('/api/workers', defaults={'worker_id': None}, methods=['GET'])
@bp.route('/api/workers/<worker_id>', methods=['GET'])
def get_workers(worker_id):
14@bp.route('/api/workers', defaults={'worker_id': None}, methods=['GET'])
15@bp.route('/api/workers/<worker_id>', methods=['GET'])
16def get_workers(worker_id):
17    """
18    Retrieves workers from the database.
19
20    **Parameters**:
21    - `worker_id` (int|None): The ID of the worker to retrieve. If `None`, retrieves all workers.
22
23    **Returns**:
24    - `tuple`: A tuple containing the serialized worker(s) and the HTTP status code.
25      - If `worker_id` is provided and the worker exists, returns the serialized worker and status code 200.
26      - If `worker_id` is not provided, returns all workers and status code 200.
27      - If the worker is not found, returns a 404 status code.
28
29    ---
30    tags:
31      - Workers
32    parameters:
33      - name: worker_id
34        in: path
35        type: integer
36        required: false
37        description: ID of the worker. If omitted, returns all workers.
38    responses:
39      200:
40        description: Worker(s) retrieved successfully.
41        schema:
42          type: object
43          description: Returns a single Worker object OR a list of Worker objects depending on the route used.
44      404:
45        description: Worker not found (only applicable when worker_id is provided).
46    """
47    if worker_id:
48        worker = get_worker_by_id(worker_id)
49        if not worker:
50            return 'Worker not found', 404
51        serialized = WorkerSchema(many=False).dump(worker)
52    else:
53        worker = get_all_workers()
54        serialized = WorkerSchema(many=True).dump(worker)
55
56    return serialized, 200

Retrieves workers from the database.

Parameters:

  • worker_id (int|None): The ID of the worker to retrieve. If None, retrieves all workers.

Returns:

  • tuple: A tuple containing the serialized worker(s) and the HTTP status code.
    • If worker_id is provided and the worker exists, returns the serialized worker and status code 200.
    • If worker_id is not provided, returns all workers and status code 200.
    • If the worker is not found, returns a 404 status code.

tags:

  • Workers parameters:
  • name: worker_id in: path type: integer required: false description: ID of the worker. If omitted, returns all workers. responses: 200: description: Worker(s) retrieved successfully. schema: type: object description: Returns a single Worker object OR a list of Worker objects depending on the route used. 404: description: Worker not found (only applicable when worker_id is provided).
@bp.route('/api/workers', methods=['POST'])
def create_worker_endpoint():
 59@bp.route('/api/workers', methods=['POST'])
 60def create_worker_endpoint():
 61    """
 62    Creates a new worker in the database.
 63
 64    **Form Body**:
 65    - `name` (str): The name of the worker.
 66    - `expiration_date` (str): The expiration date for the worker's access in ISO format.
 67    - `file` (FileStorage): The image file of the worker's face.
 68
 69    **Returns**:
 70    - `tuple`: A tuple containing the serialized worker and the HTTP status code 200.
 71
 72    ---
 73    tags:
 74      - Workers
 75    consumes:
 76      - multipart/form-data
 77    parameters:
 78      - name: name
 79        in: formData
 80        type: string
 81        required: true
 82        description: The name of the worker.
 83      - name: expiration_date
 84        in: formData
 85        type: string
 86        format: date-time
 87        required: true
 88        description: Expiration date in ISO format (YYYY-MM-DDTHH:MM:SS).
 89      - name: file
 90        in: formData
 91        type: file
 92        required: true
 93        description: The image file of the worker's face.
 94    responses:
 95      200:
 96        description: Worker successfully created.
 97        schema:
 98          type: object
 99          properties:
100            id:
101              type: integer
102            name:
103              type: string
104            expiration_date:
105              type: string
106              format: date-time
107      400:
108        description: Missing worker data.
109    """
110    name = request.form.get('name')
111    expiration_date = request.form.get('expiration_date')
112    image_file = request.files['file']
113    if not name or not expiration_date or not image_file:
114        return 'Missing worker data', 400
115
116    expiration_date = datetime.fromisoformat(expiration_date)
117    face_image = parse_image(image_file.read())
118    worker = create_worker(name, face_image, expiration_date)
119
120    # TODO: the endpoint should return **THE QR CODE**
121
122    return WorkerSchema(many=False).dump(worker), 200

Creates a new worker in the database.

Form Body:

  • name (str): The name of the worker.
  • expiration_date (str): The expiration date for the worker's access in ISO format.
  • file (FileStorage): The image file of the worker's face.

Returns:

  • tuple: A tuple containing the serialized worker and the HTTP status code 200.

tags:

  • Workers consumes:
  • multipart/form-data parameters:
  • name: name in: formData type: string required: true description: The name of the worker.
  • name: expiration_date in: formData type: string format: date-time required: true description: Expiration date in ISO format (YYYY-MM-DDTHH:MM:SS).
  • name: file in: formData type: file required: true description: The image file of the worker's face. responses: 200: description: Worker successfully created. schema: type: object properties: id: type: integer name: type: string expiration_date: type: string format: date-time 400: description: Missing worker data.
@bp.route('/api/workers/<worker_id>', methods=['PUT'])
def update_worker(worker_id):
125@bp.route('/api/workers/<worker_id>', methods=['PUT'])
126def update_worker(worker_id):
127    """
128    Updates an existing worker in the database.
129
130    **Parameters**:
131    - `worker_id` (int): The ID of the worker to update.
132
133    **Request Body** (multipart/form-data):
134    - `name` (str|optional): The new name for the worker.
135    - `expiration_date` (str|optional): The new expiration date in ISO format.
136    - `file` (FileStorage|optional): The new image file of the worker's face.
137
138    **Returns**:
139    - `tuple`: A tuple containing the serialized updated worker and the HTTP status code 200.
140      - If the worker is not found, returns a 404 status code.
141
142    ---
143    tags:
144      - Workers
145    consumes:
146      - multipart/form-data
147    parameters:
148      - name: worker_id
149        in: path
150        type: integer
151        required: true
152        description: The ID of the worker to update.
153      - name: name
154        in: formData
155        type: string
156        required: false
157        description: New name for the worker.
158      - name: expiration_date
159        in: formData
160        type: string
161        format: date-time
162        required: false
163        description: New expiration date (ISO format).
164      - name: file
165        in: formData
166        type: file
167        required: false
168        description: New face image file.
169    responses:
170      200:
171        description: Worker updated successfully.
172      404:
173        description: Worker not found.
174    """
175    worker = get_worker_by_id(worker_id)
176    if not worker:
177        return 'Worker not found', 404
178
179    name = request.form.get('name')
180    if name:
181        update_worker_name(worker, name)
182
183    expiration_date = request.form.get('expiration_date')
184    if expiration_date:
185        expiration_date = datetime.fromisoformat(expiration_date)
186        extend_worker_expiration(worker, expiration_date)
187
188    image_file = request.files.get('file')
189    if image_file:
190        face_image = parse_image(image_file.read())
191        update_worker_face_image(worker, face_image)
192
193    return WorkerSchema(many=False).dump(worker), 200

Updates an existing worker in the database.

Parameters:

  • worker_id (int): The ID of the worker to update.

Request Body (multipart/form-data):

  • name (str|optional): The new name for the worker.
  • expiration_date (str|optional): The new expiration date in ISO format.
  • file (FileStorage|optional): The new image file of the worker's face.

Returns:

  • tuple: A tuple containing the serialized updated worker and the HTTP status code 200.
    • If the worker is not found, returns a 404 status code.

tags:

  • Workers consumes:
  • multipart/form-data parameters:
  • name: worker_id in: path type: integer required: true description: The ID of the worker to update.
  • name: name in: formData type: string required: false description: New name for the worker.
  • name: expiration_date in: formData type: string format: date-time required: false description: New expiration date (ISO format).
  • name: file in: formData type: file required: false description: New face image file. responses: 200: description: Worker updated successfully. 404: description: Worker not found.
@bp.route('/api/workers/invalidate/<worker_id>', methods=['PUT'])
def invalidate_worker(worker_id):
196@bp.route('/api/workers/invalidate/<worker_id>', methods=['PUT'])
197def invalidate_worker(worker_id):
198    """
199    Invalidate an existing worker entry permit in the database.
200
201    Sets the worker's expiration date to the current time, effectively blocking entry.
202
203    **Parameters**:
204    - `worker_id` (int): The ID of the worker to update.
205
206    **Returns**:
207    - `tuple`: A tuple containing the serialized updated worker and the HTTP status code 200.
208    - If the worker is not found, returns a 404 status code.
209
210    ---
211    tags:
212      - Workers
213    parameters:
214      - name: worker_id
215        in: path
216        type: integer
217        required: true
218        description: The ID of the worker to invalidate.
219    responses:
220      200:
221        description: Worker permit invalidated successfully.
222      404:
223        description: Worker not found.
224    """
225    worker = get_worker_by_id(worker_id)
226    if not worker:
227        return 'Worker not found', 404
228
229    expiration_date = datetime.now()
230    extend_worker_expiration(worker, expiration_date)
231
232    return WorkerSchema(many=False).dump(worker), 200

Invalidate an existing worker entry permit in the database.

Sets the worker's expiration date to the current time, effectively blocking entry.

Parameters:

  • worker_id (int): The ID of the worker to update.

Returns:

  • tuple: A tuple containing the serialized updated worker and the HTTP status code 200.
  • If the worker is not found, returns a 404 status code.

tags:

  • Workers parameters:
  • name: worker_id in: path type: integer required: true description: The ID of the worker to invalidate. responses: 200: description: Worker permit invalidated successfully. 404: description: Worker not found.
@bp.route('/api/workers/entrypass/<worker_id>', methods=['GET'])
def get_worker_entry_pass(worker_id):
235@bp.route('/api/workers/entrypass/<worker_id>', methods=['GET'])
236def get_worker_entry_pass(worker_id):
237    """
238    Return the worker entry pass for printing.
239
240    Generates a PNG image containing the worker's details and QR code.
241
242    **Parameters**:
243    - `worker_id` (int): The ID of the worker's pass.
244
245    **Returns**:
246    - `bytes`: Entry pass image encoded as png.
247    - If the worker is not found, returns a 404 status code.
248
249    ---
250    tags:
251      - Workers
252    produces:
253      - image/png
254    parameters:
255      - name: worker_id
256        in: path
257        type: integer
258        required: true
259        description: The ID of the worker.
260    responses:
261      200:
262        description: Entry pass image generated.
263        schema:
264          type: file
265      404:
266        description: Worker not found.
267    """
268    worker = get_worker_by_id(worker_id)
269    if not worker:
270        return 'Worker not found', 404
271
272    image = generate_worker_entry_pass(worker)
273
274    return send_file(io.BytesIO(image), mimetype="image/png", as_attachment=False), 200

Return the worker entry pass for printing.

Generates a PNG image containing the worker's details and QR code.

Parameters:

  • worker_id (int): The ID of the worker's pass.

Returns:

  • bytes: Entry pass image encoded as png.
  • If the worker is not found, returns a 404 status code.

tags:

  • Workers produces:
  • image/png parameters:
  • name: worker_id in: path type: integer required: true description: The ID of the worker. responses: 200: description: Entry pass image generated. schema: type: file 404: description: Worker not found.