diff --git a/brewman/brewman/main.py b/brewman/brewman/main.py index 3af29fa5..d3bea632 100644 --- a/brewman/brewman/main.py +++ b/brewman/brewman/main.py @@ -23,6 +23,7 @@ from .routers import ( employee_attendance, employee_benefit, fingerprint, + fingerprint_report, incentive, issue, issue_grid, @@ -78,6 +79,7 @@ app.include_router(attendance_types.router, prefix="/api/attendance-types", tags app.include_router(employee_attendance.router, prefix="/api/employee-attendance", tags=["attendance"]) app.include_router(employee_attendance.router, prefix="/api/employee-attendance", tags=["attendance"]) app.include_router(attendance_report.router, prefix="/attendance-report", tags=["attendance"]) +app.include_router(fingerprint_report.router, prefix="/fingerprint-report", tags=["attendance"]) app.include_router(rate_contract.router, prefix="/api/rate-contracts", tags=["products"]) app.include_router(cost_centre.router, prefix="/api/cost-centres", tags=["cost-centres"]) diff --git a/brewman/brewman/routers/fingerprint_report.py b/brewman/brewman/routers/fingerprint_report.py new file mode 100644 index 00000000..9c700626 --- /dev/null +++ b/brewman/brewman/routers/fingerprint_report.py @@ -0,0 +1,67 @@ +import csv +import io + +from datetime import date, datetime + +from fastapi import APIRouter +from fastapi.responses import StreamingResponse +from sqlalchemy import or_, select +from sqlalchemy.orm import Session + +from ..db.session import SessionFuture +from ..models.employee import Employee +from .attendance import date_range +from .fingerprint import get_prints + + +router = APIRouter() + + +@router.get("", response_class=StreamingResponse) +def get_report( + s: str, + f: str, + # user: UserToken = Security(get_user, scopes=["attendance"]) ## removed as jwt headers are a pain in the ass +) -> StreamingResponse: + try: + with SessionFuture() as db: + output = io.StringIO() + attendance_record( + datetime.strptime(s, "%d-%b-%Y"), + datetime.strptime(f, "%d-%b-%Y"), + output, + db, + ) + headers = {"Content-Disposition": "attachment; filename = fingerprint-record.csv"} + output.seek(0) + return StreamingResponse(output, media_type="text/csv", headers=headers) + finally: + pass + # output.close() + + +def attendance_record(start_date: date, finish_date: date, output: io.StringIO, db: Session) -> None: + header = ["Name", "Designation", "Department"] + for date_ in date_range(start_date, finish_date, inclusive=True): + header.append(date_.strftime("%d-%b")) + header.append("") + + employees = ( + db.execute( + select(Employee) + .where(Employee.joining_date <= finish_date, or_(Employee.is_active, Employee.leaving_date >= start_date)) + .order_by(Employee.cost_centre_id, Employee.designation, Employee.name) + ) + .scalars() + .all() + ) + + writer = csv.writer(output) + writer.writerow(header) + for employee in employees: + row_display = [employee.name, employee.designation, employee.cost_centre.name] + for date_ in date_range(start_date, finish_date, inclusive=True): + prints, hours, _ = get_prints(employee.id, date_, db) + row_display.append(prints) + row_display.append(hours) + writer.writerow(row_display) diff --git a/overlord/proxy.conf.json b/overlord/proxy.conf.json index acaeaeac..8bb17e5d 100644 --- a/overlord/proxy.conf.json +++ b/overlord/proxy.conf.json @@ -18,6 +18,11 @@ "target": "http://localhost:9998", "secure": false, "logLevel": "info" + }, + "/fingerprint-report": { + "target": "http://localhost:9998", + "secure": false, + "logLevel": "info" }, "/db-image": { "target": "http://localhost:9998", diff --git a/overlord/src/app/employee-functions/employee-functions.component.html b/overlord/src/app/employee-functions/employee-functions.component.html index 2acf7245..c58a9b30 100644 --- a/overlord/src/app/employee-functions/employee-functions.component.html +++ b/overlord/src/app/employee-functions/employee-functions.component.html @@ -47,7 +47,7 @@ fxLayoutGap="20px" fxLayoutGap.lt-md="0px" > - + - + - Download Attendance + Download Fingerprints diff --git a/overlord/src/app/employee-functions/employee-functions.component.ts b/overlord/src/app/employee-functions/employee-functions.component.ts index 26df5539..e6415524 100644 --- a/overlord/src/app/employee-functions/employee-functions.component.ts +++ b/overlord/src/app/employee-functions/employee-functions.component.ts @@ -92,6 +92,20 @@ export class EmployeeFunctionsComponent { return `/attendance-report?s=${startDate}&f=${finishDate}`; } + fingerPrintUrl() { + const startDate = moment( + (this.attendanceRecordForm.get('startDate') as FormControl).value, + ).format('DD-MMM-YYYY'); + const finishDate = moment( + (this.attendanceRecordForm.get('finishDate') as FormControl).value, + ).format('DD-MMM-YYYY'); + if (!startDate || !finishDate) { + // this.toaster.show('Danger', 'Please choose a start and finish date.'); + return ''; + } + return `/fingerprint-report?s=${startDate}&f=${finishDate}`; + } + detectFiles(event: Event) { // eslint-disable-next-line prefer-destructuring this.fingerprintFile = ((event.target as HTMLInputElement).files as FileList)[0];