|
@@ -10,7 +10,7 @@ from sqlalchemy import and_, or_, not_, func
|
|
|
import json, requests, re, os
|
|
|
from .forms import RecordForm, QualificationTypeForm, QualificationForm, QualificationTypeRemovalForm, QualificationRemovalForm, RecordQualificationForm, RecordQualificationRemovalForm
|
|
|
from .forms import RoleDepartmentForm, RoleForm, RoleDepartmentRemovalForm, RoleRemovalForm, \
|
|
|
- UploadForm, UploadRemovalForm, FilterForm
|
|
|
+ UploadForm, UploadRemovalForm, FilterForm, TenderForm, TenderRemovalForm, TenderAllocationForm, TenderCVRemovalForm
|
|
|
from .forms import UserForm, UserRemovalForm
|
|
|
import re
|
|
|
import datetime as datetime_class
|
|
@@ -145,6 +145,7 @@ def index():
|
|
|
# end of surrounding try-except
|
|
|
# end of index view function for route /
|
|
|
|
|
|
+
|
|
|
@bp.route("/icons", methods=["GET"])
|
|
|
def icons():
|
|
|
"""icons preview - purely testing"""
|
|
@@ -177,6 +178,8 @@ def capture_record(i_record:int = 0):
|
|
|
qualification_form.sel_qualification.choices = l_choices
|
|
|
# end of checking if qualifications were retrieved
|
|
|
# end of checking if there are qualification types
|
|
|
+ tender_form = TenderAllocationForm()
|
|
|
+ tender_removal_form = TenderCVRemovalForm()
|
|
|
if form.validate_on_submit() and request.form.get("btn_save", "")=="Save":
|
|
|
s_action = "updated"
|
|
|
o_record = None
|
|
@@ -258,9 +261,36 @@ def capture_record(i_record:int = 0):
|
|
|
db.session.commit()
|
|
|
flash("Qualification removed")
|
|
|
# end of making sure retrieved record
|
|
|
- # end of checking for form submission
|
|
|
+ elif tender_removal_form.validate_on_submit() and request.form.get("hid_tender_cv_id", None) is not None:
|
|
|
+ i_tender_cv_id = int(tender_removal_form.hid_tender_cv_id.data)
|
|
|
+ db.session.execute(delete(tbl_tender_cvs).where(tbl_tender_cvs.id==i_tender_cv_id))
|
|
|
+ db.session.commit()
|
|
|
+ flash("Tender allocation removed", "success")
|
|
|
+ # end of checking for form submission initially
|
|
|
+ # populate possible tender allocation choices
|
|
|
+ sq_tenders = select(tbl_tender_cvs.i_tender_id.distinct()).filter(tbl_tender_cvs.i_record_id==i_record)
|
|
|
+ l_other_tenders = list(map(dict_row, db.session.query(tbl_tenders.id, tbl_tenders.v_reference_number, tbl_tenders.v_description).filter(tbl_tenders.id.not_in(sq_tenders)).all()))
|
|
|
+ if len(l_other_tenders)>0:
|
|
|
+ l_tender_choices = []
|
|
|
+ for ix, d_tender in enumerate(l_other_tenders):
|
|
|
+ l_tender_choices.append((d_tender["id"], " - ".join((d_tender["v_reference_number"], str(d_tender["v_description"])[:20]))))
|
|
|
+ # end of looping through other tenders
|
|
|
+ tender_form.sel_tender.choices = tender_form.sel_tender.choices + l_tender_choices
|
|
|
+ # end of checking if need to populate tender choices for possible allocation
|
|
|
+ # second form submission check after cv allocation might have been updated - because am populating tender choices here b4 validation
|
|
|
+ if tender_form.validate_on_submit() and request.form.get("btn_allocate", "")=="Allocate":
|
|
|
+ i_tender_id = int(tender_form.sel_tender.data)
|
|
|
+ if i_tender_id>0:
|
|
|
+ db.session.add(tbl_tender_cvs(i_tender_id=i_tender_id, i_record_id=i_record))
|
|
|
+ db.session.commit()
|
|
|
+ flash("Tender allocated", "success")
|
|
|
+ # update tender allocation choices
|
|
|
+ tender_form.sel_tender.choices = list(filter((lambda x : x[0]!=i_tender_id), tender_form.sel_tender.choices))
|
|
|
+ # end of making sure actual tender record was selected
|
|
|
+ # end of second form submission check
|
|
|
form.hid_record_id.data = i_record
|
|
|
remove_qualification_form.hid_remove_qualification_id.data = 0
|
|
|
+ tender_form.sel_tender.data = 0
|
|
|
# populate record info if existing record
|
|
|
if i_record>0:
|
|
|
o_record = db.session.get(tbl_records, i_record)
|
|
@@ -288,9 +318,13 @@ def capture_record(i_record:int = 0):
|
|
|
l_languages = db.session.query(tbl_languages.v_language_abbreviation, tbl_languages.v_language_name, tbl_languages.si_level).filter(tbl_languages.i_record_id==i_record).order_by(tbl_languages.si_ranking).all()
|
|
|
l_languages = list(map(dict_row, l_languages))
|
|
|
l_record_qualifications = list(map(dict_row, db.session.query(tbl_record_qualifications.id, tbl_qualification_types.v_qualification_type, tbl_qualifications.v_qualification_name, tbl_record_qualifications.d_acquired).join(tbl_qualifications, tbl_record_qualifications.i_qualification_id==tbl_qualifications.id, isouter=False).join(tbl_qualification_types, tbl_qualifications.i_qualification_type==tbl_qualification_types.id, isouter=False).filter(tbl_record_qualifications.i_record_id==i_record).order_by(tbl_record_qualifications.d_acquired, tbl_qualifications.v_qualification_name).all()))
|
|
|
+ l_prior_tenders = list(map(dict_row, db.session.query(tbl_tender_cvs.id, tbl_tenders.v_reference_number, tbl_tenders.v_description, tbl_tender_cvs.dt_when).join(tbl_tenders, tbl_tenders.id==tbl_tender_cvs.i_tender_id, isouter=False).filter(tbl_tender_cvs.i_record_id==i_record).order_by(tbl_tender_cvs.dt_when.desc()).limit(3)))
|
|
|
+ for ix, t in enumerate(l_prior_tenders):
|
|
|
+ l_prior_tenders[ix]["dt_when"] = l_prior_tenders[ix]["dt_when"].strftime("%Y-%m-%d %H:%M")
|
|
|
+ # end of updating values in prior tenders
|
|
|
s_base = "base_bs.html" if Config.BOOTSTRAP else "base.html"
|
|
|
s_url = url_for("main.capture_record")#, _external=True)
|
|
|
- return render_template("capture_record.html", js=True, base=s_base, url=s_url, form=form, record_id=i_record, languages=l_languages, all_languages=l_all_languages, qualification_types=l_qualification_types, qualification_form=qualification_form, record_qualifications=l_record_qualifications, departments=l_departments, roles=l_roles, department_id=i_department_id, role_id=i_role_id, remove_qualification_form=remove_qualification_form)
|
|
|
+ return render_template("capture_record.html", js=True, base=s_base, url=s_url, form=form, record_id=i_record, languages=l_languages, all_languages=l_all_languages, qualification_types=l_qualification_types, qualification_form=qualification_form, record_qualifications=l_record_qualifications, departments=l_departments, roles=l_roles, department_id=i_department_id, role_id=i_role_id, remove_qualification_form=remove_qualification_form, prior_tenders=l_prior_tenders, tender_form=tender_form, remove_tender_form=tender_removal_form)
|
|
|
except Exception as exc:
|
|
|
return render_template_string(end_user_debugging("capture_record"))
|
|
|
# end of surrounding try-except
|
|
@@ -560,7 +594,7 @@ def roles():
|
|
|
except Exception as exc:
|
|
|
return render_template_string(end_user_debugging("roles"))
|
|
|
# end of surrounding try-except
|
|
|
-# end of roles view function for route /positions
|
|
|
+# end of roles view function for route /roles
|
|
|
|
|
|
|
|
|
@bp.route("/roles_list/<int:i_department_id>/", methods=["GET"])
|
|
@@ -686,6 +720,7 @@ def record_details(i_record_id):
|
|
|
# end of looping through qualifications
|
|
|
d_out["uploads"] = list(map(dict_row, db.session.query(tbl_uploads.id, tbl_uploads.si_upload_type, tbl_uploads.v_filename, tbl_uploads.v_description, tbl_qualifications.v_qualification_name).join(tbl_qualifications, tbl_qualifications.id==tbl_uploads.i_matching_id, isouter=True).filter(tbl_uploads.i_record_id==i_record_id).all()))
|
|
|
for ix, d in enumerate(d_out["uploads"]): d["si_upload_type"] = {0: "Original CV", 1: "Alteram CV", 2: "Certificate/Diploma/Degree", 3: "I.D. Document or Passport"}[d["si_upload_type"]]
|
|
|
+ d_out["tenders"] = list(map(dict_row, db.session.query(tbl_tender_cvs.id, tbl_tenders.v_reference_number).join(tbl_tenders, tbl_tenders.id==tbl_tender_cvs.i_tender_id, isouter=False).filter(tbl_tender_cvs.i_record_id==i_record_id).order_by(tbl_tender_cvs.dt_when).limit(3)))
|
|
|
# end of initial query length check
|
|
|
return make_response(jsonify(d_out), 200)
|
|
|
except Exception as exc:
|
|
@@ -789,6 +824,100 @@ def css_sample():
|
|
|
# end of css_sample view function for route /css_sample
|
|
|
|
|
|
|
|
|
-s_todo = """
|
|
|
- double-check both try-except across the board, along with then logging exceptions
|
|
|
-"""
|
|
|
+@bp.route("/tenders/", methods=["GET", "POST"])
|
|
|
+@login_required
|
|
|
+@check_admin
|
|
|
+def tenders():
|
|
|
+ """manage tenders available for assignment to records"""
|
|
|
+ try:
|
|
|
+ tender_form = TenderForm()
|
|
|
+ remove_tender_form = TenderRemovalForm()
|
|
|
+ if tender_form.validate_on_submit() and request.form.get("btn_save_tender", "")=="Save":
|
|
|
+ i_tender_id, s_reference_number, s_description = (int(tender_form.hid_tender_id.data), str(tender_form.txt_reference_number.data), str(tender_form.txt_description.data))
|
|
|
+ if i_tender_id > 0:
|
|
|
+ o_tender = db.session.get(tbl_tenders, i_tender_id)
|
|
|
+ if o_tender is not None:
|
|
|
+ if db.session.query(tbl_tenders).filter(tbl_tenders.id!=i_tender_id, tbl_tenders.v_reference_number==s_reference_number).count()>0:
|
|
|
+ flash("There is already another tender with the same reference number on record", "error")
|
|
|
+ else:
|
|
|
+ o_tender.v_reference_number = s_reference_number
|
|
|
+ o_tender.v_description = s_description
|
|
|
+ db.session.add(o_tender)
|
|
|
+ db.session.commit()
|
|
|
+ flash("Tender updated", "success")
|
|
|
+ # end of making sure no other duplicates with same reference number
|
|
|
+ else:
|
|
|
+ flash("No tender record could be retrieved", "error")
|
|
|
+ # end of checking if record existed
|
|
|
+ else:
|
|
|
+ if db.session.query(tbl_tenders.id).filter(tbl_tenders.v_reference_number==s_reference_number).count()<1:
|
|
|
+ db.session.add(tbl_tenders(v_reference_number=s_reference_number, v_description=s_description))
|
|
|
+ db.session.commit()
|
|
|
+ flash("Tender inserted", "success")
|
|
|
+ else:
|
|
|
+ flash("Atender with the same reference number has already been recorded", "error")
|
|
|
+ # end of making sure new tender is not a duplicate
|
|
|
+ # end of checking if new or existing tender record
|
|
|
+ elif remove_tender_form.validate_on_submit():
|
|
|
+ i_tender_id = int(remove_tender_form.hid_remove_tender_id.data)
|
|
|
+ o_tender = db.session.get(tbl_tenders, i_tender_id)
|
|
|
+ if o_tender is not None:
|
|
|
+ db.session.delete(o_tender)
|
|
|
+ db.session.commit()
|
|
|
+ db.session.execute(delete(tbl_tender_cvs).where(tbl_tender_cvs.i_tender_id==i_tender_id))
|
|
|
+ db.session.commit()
|
|
|
+ flash("Tender removed", "success")
|
|
|
+ # end of checking if record existed
|
|
|
+ # end of checking for form submission
|
|
|
+ tender_form.hid_tender_id.data, tender_form.txt_reference_number.data, tender_form.txt_description.data = (0, "", "")
|
|
|
+ remove_tender_form.hid_remove_tender_id.data = "0"
|
|
|
+ i_page = request.form.get("hid_page", 1, type=int)
|
|
|
+ q_tenders = db.session.query(tbl_tenders.id, tbl_tenders.v_reference_number, tbl_tenders.v_description).order_by(tbl_tenders.v_reference_number)
|
|
|
+ pagination = q_tenders.paginate(page=i_page, per_page=20)
|
|
|
+ l_tenders = list(map(dict_row, pagination.items))
|
|
|
+ s_base = "base_bs.html" if Config.BOOTSTRAP else "base.html"
|
|
|
+ s_url = url_for("main.tenders")#, _external=True)
|
|
|
+ return render_template("tenders.html", js=True, base=s_base, url=s_url, tenders=l_tenders, form=tender_form, remove_form=remove_tender_form, paging=pagination)
|
|
|
+ except Exception as exc:
|
|
|
+ return render_template_string(end_user_debugging("tenders"))
|
|
|
+ # end of surrounding try-except
|
|
|
+# end of tenders view function for route /tenders
|
|
|
+
|
|
|
+
|
|
|
+@bp.route("/tenders_list/", methods=["GET"])
|
|
|
+@login_required
|
|
|
+def tenders_list():
|
|
|
+ """return list of tender entries"""
|
|
|
+ try:
|
|
|
+ l_out = []
|
|
|
+ try:
|
|
|
+ q_tenders = db.session.query(tbl_tenders.id, tbl_tenders.v_reference_number, tbl_tenders.v_description)
|
|
|
+ if q_tenders.count()>0:
|
|
|
+ q_tenders = q_tenders.order_by(tbl_tenders.v_reference_number)
|
|
|
+ l_out = list(map(dict_row, q_tenders.all()))
|
|
|
+ # end of checking result count of query
|
|
|
+ except Exception as exc:
|
|
|
+ print(extract_exc("list roles?"))
|
|
|
+ # end of try-except
|
|
|
+ return make_response(jsonify(l_out), 200)
|
|
|
+ except Exception as exc:
|
|
|
+ return render_template_string(end_user_debugging("tenders_list"))
|
|
|
+ # end of surrounding try-except
|
|
|
+# end of tenders_list view function for route /tenders_list/
|
|
|
+
|
|
|
+
|
|
|
+@bp.route("/tender_details/<int:i_tender_id>/", methods=["GET"])
|
|
|
+@login_required
|
|
|
+def tender_details(i_tender_id):
|
|
|
+ """retrieve tender details"""
|
|
|
+ try:
|
|
|
+ d_out = {}
|
|
|
+ o_tender = db.session.get(tbl_tenders, i_tender_id)
|
|
|
+ if o_tender is not None:
|
|
|
+ d_out = dict_instance(o_tender)
|
|
|
+ # end of checking if record retrieved
|
|
|
+ return make_response(jsonify(d_out), 200)
|
|
|
+ except Exception as exc:
|
|
|
+ return render_template_string(end_user_debugging("tender_details"))
|
|
|
+ # end of surrounding try-except
|
|
|
+# end of tender_details view function for route /tender_details/<int:i_tender_id>/
|