import json import logging import traceback import pydapper from ..schemas import model from .. import local_db from BreCal.database.update_database import evaluate_shipcall_state def GetShipcalls(options): """ No parameters, gets all entries """ # TODO: validate token try: pooledConnection = local_db.getPoolConnection() commands = pydapper.using(pooledConnection) query = ("SELECT s.id as id, ship_id, type, eta, voyage, etd, arrival_berth_id, departure_berth_id, tug_required, pilot_required, " + "flags, s.pier_side, bunkering, replenishing_terminal, replenishing_lock, draft, tidal_window_from, " + "tidal_window_to, rain_sensitive_cargo, recommended_tugs, anchored, moored_lock, canceled, evaluation, " + "evaluation_message, s.created as created, s.modified as modified " + "FROM shipcall s " + "LEFT JOIN times t ON t.shipcall_id = s.id AND t.participant_type = 8 " + "WHERE " + "(type = 1 AND " + "((t.id IS NOT NULL AND t.eta_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " + "(eta >= DATE(NOW() - INTERVAL %d DAY)))) OR " + "((type = 2 OR type = 3) AND " + "((t.id IS NOT NULL AND t.etd_berth >= DATE(NOW() - INTERVAL %d DAY)) OR " + "(etd >= DATE(NOW() - INTERVAL %d DAY)))) " + "ORDER BY eta") % (options["past_days"], options["past_days"], options["past_days"], options["past_days"]) data = commands.query(query, model=model.Shipcall) for shipcall in data: participant_query = "SELECT participant_id, type FROM shipcall_participant_map WHERE shipcall_id=?shipcall_id?"; for record in commands.query(participant_query, model=dict, param={"shipcall_id" : shipcall.id}, buffered=False): # model.Participant_Assignment = model.Participant_Assignment() pa = model.Participant_Assignment(record["participant_id"], record["type"]) shipcall.participants.append(pa) pooledConnection.close() except Exception as ex: logging.error(traceback.format_exc()) logging.error(ex) print(ex) result = {} result["message"] = "call failed" return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'} return json.dumps(data, default=model.obj_dict), 200, {'Content-Type': 'application/json; charset=utf-8'} def PostShipcalls(schemaModel): """ :param schemaModel: The deserialized dict of the request """ # TODO: Validate the upload data # This creates a *new* entry try: pooledConnection = local_db.getPoolConnection() commands = pydapper.using(pooledConnection) query = "INSERT INTO shipcall (" isNotFirst = False for key in schemaModel.keys(): if key == "id": continue if key == "participants": continue if key == "created": continue if key == "modified": continue if key == "evaluation": continue if key == "evaluation_message": continue if isNotFirst: query += "," isNotFirst = True query += key query += ") VALUES (" isNotFirst = False for key in schemaModel.keys(): if key == "id": continue if key == "participants": continue if key == "created": continue if key == "modified": continue if key == "evaluation": continue if key == "evaluation_message": continue if isNotFirst: query += "," isNotFirst = True query += "?" + key + "?" query += ")" commands.execute(query, schemaModel) new_id = commands.execute_scalar("select last_insert_id()") # add participant assignments pquery = "INSERT INTO shipcall_participant_map (shipcall_id, participant_id, type) VALUES (?shipcall_id?, ?participant_id?, ?type?)" for participant_assignment in schemaModel["participants"]: commands.execute(pquery, param={"shipcall_id" : new_id, "participant_id" : participant_assignment["participant_id"], "type" : participant_assignment["type"]}) # apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=new_id) # new_id (last insert id) refers to the shipcall id pooledConnection.close() return json.dumps({"id" : new_id}), 201, {'Content-Type': 'application/json; charset=utf-8'} except Exception as ex: logging.error(traceback.format_exc()) logging.error(ex) print(ex) result = {} result["message"] = "call failed" return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'} def PutShipcalls(schemaModel): """ :param schemaModel: The deserialized dict of the request """ # This updates an *existing* entry try: pooledConnection = local_db.getPoolConnection() commands = pydapper.using(pooledConnection) # test if object to update is found sentinel = object() theshipcall = commands.query_single_or_default("SELECT * FROM shipcall where id = ?id?", sentinel, param={"id" : schemaModel["id"]}) if theshipcall is sentinel: pooledConnection.close() return json.dumps("no such record"), 404, {'Content-Type': 'application/json; charset=utf-8'} query = "UPDATE shipcall SET " isNotFirst = False for key in schemaModel.keys(): if key == "id": continue if key == "participants": continue if key == "created": continue if key == "modified": continue if key == "evaluation": continue if key == "evaluation_message": continue if isNotFirst: query += ", " isNotFirst = True query += key + " = ?" + key + "? " query += "WHERE id = ?id?" affected_rows = commands.execute(query, param=schemaModel) pquery = "SELECT id, participant_id, type FROM shipcall_participant_map where shipcall_id = ?id?" pdata = commands.query(pquery,param={"id" : schemaModel["id"]}) # existing list of assignments # loop across passed participant ids, creating entries for those not present in pdata for participant_assignment in schemaModel["participants"]: found_participant = False for elem in pdata: if elem["participant_id"] == participant_assignment["participant_id"] and elem["type"] == participant_assignment["type"]: found_participant = True break if not found_participant: nquery = "INSERT INTO shipcall_participant_map (shipcall_id, participant_id, type) VALUES (?shipcall_id?, ?participant_id?, ?type?)" commands.execute(nquery, param={"shipcall_id" : schemaModel["id"], "participant_id" : participant_assignment["participant_id"], "type" : participant_assignment["type"]}) # loop across existing pdata entries, deleting those not present in participant list for elem in pdata: found_participant = False for participant_assignment in schemaModel["participants"]: if(participant_assignment["participant_id"] == elem["participant_id"] and participant_assignment["type"] == elem["type"]): found_participant = True break; if not found_participant: dquery = "DELETE FROM shipcall_participant_map WHERE id = ?existing_id?" commands.execute(dquery, param={"existing_id" : elem["id"]}) # apply 'Traffic Light' evaluation to obtain 'GREEN', 'YELLOW' or 'RED' evaluation state. The function internally updates the mysql database evaluate_shipcall_state(mysql_connector_instance=pooledConnection, shipcall_id=schemaModel["id"]) # schemaModel["id"] refers to the shipcall id pooledConnection.close() return json.dumps({"id" : schemaModel["id"]}), 200 except Exception as ex: logging.error(traceback.format_exc()) logging.error(ex) print(ex) result = {} result["message"] = "call failed" return json.dumps(result), 500, {'Content-Type': 'application/json; charset=utf-8'}