Commit d011eb7b by Mac Stephens

Connected to entcad database, uniqueries created with all fields, initial…

Connected to entcad database, uniqueries created with all fields, initial complaint list endpoint created, cleaned up more envoy calls issues
parent 6fa13c63
// Where the database is kept. Only used by Lookup.ServiceImpl to retrieve info
// from the data base and send it to the client.
// Author: ???
unit Api.Database;
interface
......@@ -15,7 +12,6 @@ type
ucEnvoy: TUniConnection;
PostgreSQLUniProvider1: TPostgreSQLUniProvider;
UniQuery1: TUniQuery;
ucBooking: TUniConnection;
OracleUniProvider1: TOracleUniProvider;
uqBooking: TUniQuery;
uqUnitsCurrent: TUniQuery;
......@@ -24,6 +20,104 @@ type
uqCFSMemos: TUniQuery;
uqComplaintList: TUniQuery;
uqComplaintDetails: TUniQuery;
ucENTCAD: TUniConnection;
uqComplaintListCOMPLAINTID: TFloatField;
uqComplaintListCFSID: TFloatField;
uqComplaintListCOMPLAINT: TStringField;
uqComplaintListAGENCY: TStringField;
uqComplaintListDISPATCH_CODE_DESC: TStringField;
uqComplaintListSOURCE: TStringField;
uqComplaintListSOURCE_DESC: TStringField;
uqComplaintListPRIORITY: TStringField;
uqComplaintListADDRESSID: TFloatField;
uqComplaintListADDRESS: TStringField;
uqComplaintListAPARTMENT: TStringField;
uqComplaintListCITY: TStringField;
uqComplaintListBUSINESS: TStringField;
uqComplaintListDISPATCHDISTRICT: TStringField;
uqComplaintListDISPATCHSECTOR: TStringField;
uqComplaintListADDRESSDISTRICT: TStringField;
uqComplaintListADDRESSSECTOR: TStringField;
uqComplaintListXCOORD: TFloatField;
uqComplaintListYCOORD: TFloatField;
uqComplaintListWARNINGS: TFloatField;
uqComplaintListCONTACTS: TFloatField;
uqComplaintListHISTORY: TFloatField;
uqComplaintListDATEREPORTED: TDateTimeField;
uqComplaintListDATERECEIVED: TDateTimeField;
uqComplaintListDATEDISPATCHED: TDateTimeField;
uqComplaintListDATERESPONDED: TDateTimeField;
uqComplaintListDATEARRIVED: TDateTimeField;
uqComplaintListDATECLEARED: TDateTimeField;
uqComplaintDetailsCOMPLAINTID: TFloatField;
uqComplaintDetailsCFSID: TFloatField;
uqComplaintDetailsCOMPLAINT: TStringField;
uqComplaintDetailsAGENCY: TStringField;
uqComplaintDetailsDISPATCHCODE: TStringField;
uqComplaintDetailsDISPATCH_CODE_DESC: TStringField;
uqComplaintDetailsSOURCE: TStringField;
uqComplaintDetailsSOURCE_DESC: TStringField;
uqComplaintDetailsPRIORITY: TStringField;
uqComplaintDetailsADDRESSID: TFloatField;
uqComplaintDetailsADDRESS: TStringField;
uqComplaintDetailsAPARTMENT: TStringField;
uqComplaintDetailsCITY: TStringField;
uqComplaintDetailsBUSINESS: TStringField;
uqComplaintDetailsDISPATCHDISTRICT: TStringField;
uqComplaintDetailsDISPATCHSECTOR: TStringField;
uqComplaintDetailsADDRESSDISTRICT: TStringField;
uqComplaintDetailsADDRESSSECTOR: TStringField;
uqComplaintDetailsXCOORD: TFloatField;
uqComplaintDetailsYCOORD: TFloatField;
uqComplaintDetailsWARNINGS: TFloatField;
uqComplaintDetailsCONTACTS: TFloatField;
uqComplaintDetailsHISTORY: TFloatField;
uqComplaintDetailsDATEREPORTED: TDateTimeField;
uqComplaintDetailsDATERECEIVED: TDateTimeField;
uqComplaintDetailsDATEDISPATCHED: TDateTimeField;
uqComplaintDetailsDATERESPONDED: TDateTimeField;
uqComplaintDetailsDATEARRIVED: TDateTimeField;
uqComplaintDetailsDATECLEARED: TDateTimeField;
uqCFSActiveCOMPLAINTID: TFloatField;
uqCFSActiveUNITID: TFloatField;
uqCFSActiveUNITNAME: TStringField;
uqCFSActiveDATEDISPATCHED: TDateTimeField;
uqCFSActiveDATERESPONDED: TDateTimeField;
uqCFSActiveDATEARRIVED: TDateTimeField;
uqCFSActiveDATECLEARED: TDateTimeField;
uqCFSActiveLOCATION: TStringField;
uqCFSMemosMEMO_ID: TFloatField;
uqCFSMemosCFSID: TFloatField;
uqCFSMemosMEMO_TYPE: TFloatField;
uqCFSMemosTIMESTAMP: TDateTimeField;
uqCFSMemosBADGE_NUMBER: TStringField;
uqCFSMemosREMARKS: TStringField;
uqUnitsCurrentENTRYID: TFloatField;
uqUnitsCurrentUNITID: TFloatField;
uqUnitsCurrentUNITNAME: TStringField;
uqUnitsCurrentUNIT_DISTRICT: TStringField;
uqUnitsCurrentGPS_LATITUDE: TFloatField;
uqUnitsCurrentGPS_LONGITUDE: TFloatField;
uqDISUnitsActiveUNITID: TFloatField;
uqDISUnitsActiveUNITNAME: TStringField;
uqDISUnitsActiveCARNUMBER_DESC: TStringField;
uqDISUnitsActiveDISTRICT_DESC: TStringField;
uqDISUnitsActiveSECTOR_DESC: TStringField;
uqDISUnitsActiveOFFICER1_EMPNUM: TStringField;
uqDISUnitsActiveOFFICER1_LAST_NAME: TStringField;
uqDISUnitsActiveOFFICER1_FIRST_NAME: TStringField;
uqDISUnitsActiveOFFICER1_MI: TStringField;
uqDISUnitsActiveOFFICER2_EMPNUM: TStringField;
uqDISUnitsActiveOFFICER2_LAST_NAME: TStringField;
uqDISUnitsActiveOFFICER2_FIRST_NAME: TStringField;
uqDISUnitsActiveOFFICER2_MI: TStringField;
uqDISUnitsActiveLOCATION: TStringField;
uqDISUnitsActiveCOMPLAINT: TStringField;
uqDISUnitsActiveUNITSTATUS: TFloatField;
uqDISUnitsActiveUNIT_STATUS_DESC: TStringField;
uqDISUnitsActiveENTRYID: TFloatField;
uqDISUnitsActiveGPS_LATITUDE: TFloatField;
uqDISUnitsActiveGPS_LONGITUDE: TFloatField;
procedure DataModuleCreate(Sender: TObject);
private
{ Private declarations }
......
unit Api.Service;
interface
uses
XData.Service.Common,
Aurelius.Mapping.Attributes,
System.JSON,
System.Generics.Collections,
System.Classes;
const
API_MODEL = 'Api';
type
[ServiceContract, Model(API_MODEL)]
IApiService = interface(IInvokable)
['{4FCB7FAF-44E5-49D6-9C0F-EE44BFB33313}']
[HttpGet] function GetComplaintList: TJSONObject;
end;
implementation
end.
unit Api.ServiceImpl;
interface
uses
XData.Server.Module, XData.Service.Common, Api.Database, Data.DB,
System.SysUtils, System.Generics.Collections, XData.Sys.Exceptions,
System.Hash, System.Classes, Common.Logging, System.JSON, Api.Service;
type
[ServiceImplementation]
TApiService = class(TInterfacedObject, IApiService)
strict private
ApiDB: TApiDatabaseModule;
private
procedure AfterConstruction; override;
procedure BeforeDestruction; override;
public
function GetComplaintList: TJSONObject;
end;
implementation
uses
uLibrary;
procedure TApiService.AfterConstruction;
begin
inherited;
ApiDB := TApiDatabaseModule.Create(nil);
Logger.Log(3, 'ApiDatabaseModule created');
end;
procedure TApiService.BeforeDestruction;
begin
ApiDB.Free;
inherited;
Logger.Log(3, 'ApiDatabaseModule destroyed');
end;
function TApiService.GetComplaintList: TJSONObject;
var
data: TJSONArray;
begin
Logger.Log(3, '---TApiService.GetComplaintList initiated');
Result := TJSONObject.Create;
TXDataOperationContext.Current.Handler.ManagedObjects.Add(Result);
data := TJSONArray.Create;
try
with ApiDB.uqComplaintList do
begin
Open;
First;
while not Eof do
begin
var status: string;
if not FieldByName('DATECLEARED').IsNull then
status := 'Cleared'
else if not FieldByName('DATEARRIVED').IsNull then
status := 'AtScene'
else if not FieldByName('DATEDISPATCHED').IsNull then
status := 'Dispatched'
else
status := 'Pending';
var item := TJSONObject.Create;
item.AddPair('ComplaintId', ApiDB.uqComplaintListCOMPLAINTID.AsString);
item.AddPair('Agency', ApiDB.uqComplaintListAGENCY.AsString);
item.AddPair('Priority', TJSONNumber.Create(ApiDB.uqComplaintListPRIORITY.AsString));
item.AddPair('DispatchCodeDesc', ApiDB.uqComplaintListDISPATCH_CODE_DESC.AsString);
item.AddPair('Address', ApiDB.uqComplaintListADDRESS.AsString);
item.AddPair('CFSId', ApiDB.uqComplaintListCFSID.AsString);
item.AddPair('Status', status);
item.AddPair('DispatchDistrict', ApiDB.uqComplaintListDISPATCHDISTRICT.AsString);
item.AddPair('DateReported', ApiDB.uqComplaintListDATEREPORTED.AsString);
data.AddElement(item);
Next;
end;
end;
Result.AddPair('count', TJSONNumber.Create(data.Count));
Result.AddPair('returned', TJSONNumber.Create(data.Count));
Result.AddPair('data', data);
except
data.Free;
Logger.Log(3, '---TApiService.GetComplaintList End (error)');
raise EXDataHttpException.Create(500, 'Failed to load complaints list');
end;
Logger.Log(3, '---TApiService.GetComplaintList End');
end;
initialization
RegisterServiceType(TApiService);
end.
// Lookup Service interface which retrieves information from the database
// which is then sent to the client.
// Authors:
// Cameron Hayes
// Mac ...
// Elias Sarraf
unit Lookup.Service;
interface
uses
XData.Service.Common,
Aurelius.Mapping.Attributes,
System.JSON,
System.Generics.Collections,
System.Classes;
const
API_MODEL = 'Api';
type
TCallItem = class
// Class of the info we want from the database from a specific call.
// callSid: SID of the call, 34 digit string.
// fromNumber: Who the phone call was from. (xxx) xxx-xxxx
// toNumber: Who the phone call was to. (xxx) xxx-xxxx
// dateCreated: Date the phone call was created. mm/dd/yyyy hh:nn:ss am/pm
// mediaURL: Link to the recording audio
// duration: Length of the entire call and recording.
// transcription: Transcription of the recording. Not always present due to
// the call being answerered or caller did not leave a message.
public
callSid: string;
fromNumber: string;
toNumber: string;
dateCreated: string;
mediaUrl: string;
duration: string;
transcription: string;
end;
// List of call items
// count: Total amount of records that fit the SQL query
// data: List of retrieved calls
TCallList = class
public
count: integer;
data: TList<TCallItem>;
end;
TUserItem = class
public
userID: string;
username: string;
full_name: string;
phone_number: string;
email_address: string;
admin: boolean;
active: boolean;
password: string;
end;
TUserList = class
public
count: integer;
data: TList<TUserItem>;
end;
type
[ServiceContract, Model(API_MODEL)]
ILookupService = interface(IInvokable)
['{F24E1468-5279-401F-A877-CD48B44F4416}']
[HttpGet] function GetCalls(searchOptions: string): TCallList;
[HttpGet] function Search(phoneNum: string): TCallList;
[HttpGet] function GetUsers(searchOptions: string): TUserList;
function AddUser(userInfo: string): string;
function DelUser(username: string): string;
function EditUser(const editOptions: string): string;
end;
implementation
initialization
RegisterServiceType(TypeInfo(ILookupService));
end.
......@@ -7,7 +7,7 @@ uses
System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs,
Vcl.StdCtrls, Vcl.ExtCtrls, System.Generics.Collections, System.IniFiles,
Auth.Service, Auth.Server.Module, Api.Server.Module, App.Server.Module,
ExeInfo, Lookup.Service;
ExeInfo, Api.Service;
type
TFMain = class(TForm)
......
......@@ -18,9 +18,9 @@ uses
Auth.Database in 'Source\Auth.Database.pas' {AuthDatabase: TDataModule},
uLibrary in 'Source\uLibrary.pas',
Auth.Service in 'Source\Auth.Service.pas',
Lookup.Service in 'Source\Lookup.Service.pas',
Api.Service in 'Source\Api.Service.pas',
Auth.ServiceImpl in 'Source\Auth.ServiceImpl.pas',
Lookup.ServiceImpl in 'Source\Lookup.ServiceImpl.pas',
Api.ServiceImpl in 'Source\Api.ServiceImpl.pas',
Twilio.Data.Module in 'Source\Twilio.Data.Module.pas' {TwilioDataModule: TDataModule},
App.Server.Module in 'Source\App.Server.Module.pas' {AppServerModule: TDataModule},
Common.Ini in 'Source\Common.Ini.pas';
......
......@@ -160,9 +160,9 @@
</DCCReference>
<DCCReference Include="Source\uLibrary.pas"/>
<DCCReference Include="Source\Auth.Service.pas"/>
<DCCReference Include="Source\Lookup.Service.pas"/>
<DCCReference Include="Source\Api.Service.pas"/>
<DCCReference Include="Source\Auth.ServiceImpl.pas"/>
<DCCReference Include="Source\Lookup.ServiceImpl.pas"/>
<DCCReference Include="Source\Api.ServiceImpl.pas"/>
<DCCReference Include="Source\Twilio.Data.Module.pas">
<Form>TwilioDataModule</Form>
<DesignClass>TDataModule</DesignClass>
......
[Settings]
LogFileNum=409
LogFileNum=414
webClientVersion=0.1.0
TwilioUpdateTime=1
......
object FViewComplaints: TFViewComplaints
Width = 676
Width = 359
Height = 480
CSSLibrary = cssBootstrap
ElementFont = efCSS
......@@ -11,157 +11,91 @@ object FViewComplaints: TFViewComplaints
ParentFont = False
Visible = True
OnCreate = WebFormCreate
object lblEntries: TWebLabel
Left = 0
Top = 336
Width = 77
Height = 13
Caption = 'Showing 0 of ...'
ElementID = 'lblentries'
object WebButton1: TWebButton
Left = 180
Top = 110
Width = 43
Height = 25
Caption = 'Group'
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'complaints_btngroup'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
end
object wcbPageSize: TWebComboBox
Left = 0
Top = 0
Width = 145
Height = 21
ElementClassName = 'custom-select'
ElementID = 'wcbpagesize'
object WebButton2: TWebButton
Left = 242
Top = 110
Width = 37
Height = 25
Caption = 'Filter'
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'complaints_btnfilter'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Text = '10'
Visible = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
'10'
'25'
'50')
end
object wcbLocation: TWebLookupComboBox
Left = 154
Top = 0
Width = 145
Height = 22
ElementClassName = 'custom-select'
ElementID = 'wcblocation'
ElementFont = efCSS
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
LookupValues = <
item
DisplayText = 'All'
end
item
Value = '(716) 681-8820'
DisplayText = 'Galleria'
end
item
Value = '(716) 297-4654'
DisplayText = 'NF Outlet'
end
item
Value = '(585) 445-8911'
DisplayText = 'Rochester'
end
item
Value = '(315) 565-4138'
DisplayText = 'Syracuse'
end>
end
object dtpStartDate: TWebEdit
Left = 342
Top = 0
Width = 121
Height = 22
ChildOrder = 10
ElementClassName = 'form-control'
ElementID = 'dtpstartdate'
object Complaints: TWebButton
Left = 114
Top = 110
Width = 53
Height = 25
Caption = 'Refresh'
ChildOrder = 1
ElementClassName = 'btn btn-light'
ElementID = 'complaints_btnrefresh'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
end
object dtpEndDate: TWebEdit
Left = 478
Top = 0
Width = 121
Height = 22
ChildOrder = 10
ElementClassName = 'form-control'
ElementID = 'dtpenddate'
ElementFont = efCSS
object dblComplaintsList: TWebDBListControl
Left = 36
Top = 148
Width = 263
Height = 237
ElementID = 'complaints_dbl_complaint_list'
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
end
object wcbSortBy: TWebComboBox
Left = 442
Top = 52
Width = 145
Height = 21
ElementClassName = 'custom-select'
ElementID = 'wcbsortby'
ChildOrder = 3
DefaultItemClassName = 'list-group-item'
DefaultItemLinkClassName = 'list-group-link'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Text = 'Date'
Visible = False
WidthPercent = 100.000000000000000000
ItemIndex = -1
Items.Strings = (
'Date'
'Phone Number')
ElementListClassName = 'list-group'
Items = <
item
ItemClassName = 'list-group-item'
Items = <>
LinkClassName = 'list-group-link'
Text = 'Item 0'
end
object btnApply: TWebButton
Left = 478
Top = 128
Width = 96
Height = 25
Caption = 'Apply'
ChildOrder = 7
ElementClassName = 'btn btn-light'
ElementID = 'btnapply'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
Visible = False
WidthPercent = 100.000000000000000000
item
ItemClassName = 'list-group-item'
Items = <>
LinkClassName = 'list-group-link'
Text = 'Item 1'
end
object edtSearch: TWebEdit
Left = 50
Top = 382
Width = 121
Height = 22
HelpType = htKeyword
ChildOrder = 8
ElementClassName = 'form-control'
ElementID = 'edtsearch'
ElementFont = efCSS
HeightStyle = ssAuto
HeightPercent = 100.000000000000000000
HideSelection = False
TextHint = 'Format: (XXX) XXX-XXXX'
Visible = False
WidthPercent = 100.000000000000000000
item
ItemClassName = 'list-group-item'
Items = <>
LinkClassName = 'list-group-link'
Text = 'Item 2'
end>
Style = lsListGroup
end
object XDataWebClient1: TXDataWebClient
object xdwcComplaints: TXDataWebClient
Connection = DMConnection.ApiConnection
Left = 426
Top = 240
Left = 92
Top = 416
end
object XDataWebDataSet1: TXDataWebDataSet
object xdwdsComplaints: TXDataWebDataSet
Connection = DMConnection.ApiConnection
Left = 440
Top = 300
Left = 214
Top = 414
end
end
......@@ -5,20 +5,20 @@
<div class="container-fluid">
<div class="row w-100 g-2 align-items-stretch">
<div class="col">
<span id="complaints.title" class="navbar-brand mb-0 h5 text-white">Complaints</span>
<span id="complaints_title" class="navbar-brand mb-0 h5 text-white">Complaints</span>
</div>
<div class="col">
<button id="complaints.btnrefresh" type="button" class="btn btn-primary w-100 h-100">
<button id="complaints_btnrefresh" type="button" class="btn btn-primary w-100 h-100">
<i class="fa fa-sync-alt me-1"></i><span class="d-none d-sm-inline">Refresh</span>
</button>
</div>
<div class="col">
<button id="complaints.btngroup" type="button" class="btn btn-primary w-100 h-100">
<button id="complaints_btngroup" type="button" class="btn btn-primary w-100 h-100">
<i class="fa fa-layer-group me-1"></i><span class="d-none d-sm-inline">Group</span>
</button>
</div>
<div class="col">
<button id="complaints.btnfilter" type="button" class="btn btn-primary w-100 h-100">
<button id="complaints_btnfilter" type="button" class="btn btn-primary w-100 h-100">
<i class="fa fa-sliders-h me-1"></i><span class="d-none d-sm-inline">Filter</span>
</button>
</div>
......@@ -31,38 +31,20 @@
<div class="container-fluid">
<div class="input-group">
<span class="input-group-text bg-white"><i class="fa fa-search"></i></span>
<input id="complaints.search" class="form-control" placeholder="Search...">
<input id="complaints_search" class="form-control" placeholder="Search...">
</div>
</div>
</div>
</div> <!-- /sticky-top wrapper -->
<!-- Existing content (unchanged) -->
<div class="row">
<div class="col-12">
<div class="container mt-4">
<!-- Complaints list container -->
<div class="container-fluid mt-2">
<div class="row justify-content-center">
<div class="col-12 col-md-10 col-lg-8">
<h1 class="page-header pt-3 pb-2 mb-3 border-bottom fs-4 fw-bold" id="view.calls.title">Complaints</h1>
<!-- Data Table -->
<div class="table-responsive mt-4">
<table class="table table-sm table-striped table-bordered align-middle" id="tblPhoneGrid">
<thead class="table-dark">
<tr>
<th scope="col">Phone Number</th>
<th scope="col">Caller</th>
<th scope="col">Time</th>
<th scope="col">Duration</th>
<th scope="col">Transcript</th>
<th scope="col">Listen</th>
</tr>
</thead>
<tbody>
<!-- Rows added dynamically in Delphi -->
</tbody>
</table>
<!-- This is where the DBListControl will inject cards -->
<div id="complaints_dbl_complaint_list" class="d-flex flex-column gap-2">
<!-- Cards will render here -->
</div>
<!-- Entry Count Label -->
......@@ -71,12 +53,11 @@
<!-- Pagination -->
<nav aria-label="Page navigation">
<ul class="pagination justify-content-center" id="pagination">
<!-- Pagination items added in Delphi -->
<!-- Pagination items rendered in Delphi -->
</ul>
</nav>
</div>
</div>
</div>
</div>
</div>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment