Database schema
1. Users collection
{
_id:
mobileNo:
name:
lastLogin:
rank:
created at:
office: id precinct
precinctsIncharge: [ids precincts]
verification:{
otp:
updatedAt:
}(Required for OTP verification)
complaints:[array of complaint id]
}
2. Ranks collection (post of police officers)
{
_id:
hierarchicalVal:
title:
}
3. Complaints collection (list of complaints)
{
_id:
name: CHATRAM/25.04.2020/3 string
place:
description:
assigned: [array of officers assigned]
dateOfOccurrence:
createdAt:
updatedAt:
precinct:
documents: [array of hashed file names]
status: closed/open boolean
complaintType: id of complaint type
}
4 Precinct collection (List of precinct)
{
_id:
type: office/precinct boolean
dayComplaintCount: number
title:
}
5 ComplaintsType
{
_id:
title:
}
Instructions:
complaint status:
pending: no one is assigned and complaint open
active: assigned and complaint open
closed: complaint closed
Office: any office, precinct or commissioner assistant commissioner office
Precinct: only precinct
Type: true ->precinct false->office
Any number of officers may be assigned to a complaint
Working:
User sends otp call first
Otp response exist redirects to register or login route (exist: true for login, false for register
route)
Register or login is called, jwt is responded
List of ranks can be got in get request
List of precincts can be got using get request
New complaint created by any officer
Complaints assigned for a officer can be got (active)
New officer can be added and deleted from a complaint for assigned complaints
DB sample data:
PRECINCTS:
db.createCollection("precincts")
db.precincts.insert({ title: "CANTONMENT" , type:1, dayComplaintCount: 0})
db.precincts.insert({ title: "WORAIYUR" , type:1, dayComplaintCount: 0})
db.precincts.insert({ title: "SRIRANGAM," , type:1, dayComplaintCount: 0})
db.precincts.insert({ title: "ASSISTANT-COMMISSIONER-OFFICE" , type:0,
dayComplaintCount: 0})
db.precincts.insert({ title: "COMMISSIONER-OFFICE" , type:0, dayComplaintCount: 0})
RANKS:
db.createCollection("ranks")
db.ranks.insert({ title: "COMMISSIONER" ,hierarchicalVal:1})
db.ranks.insert({ title: "ASSISTANT-COMMISSIONER" ,hierarchicalVal:2})
db.ranks.insert({ title: "INSPECTOR" ,hierarchicalVal:3})
db.ranks.insert({ title: "SUB-INSPECTOR" ,hierarchicalVal:4})
db.ranks.insert({ title: "CONSTABLES" ,hierarchicalVal:5})
ComplaintTypes:
db.createCollection("complainttypes")
db.complainttypes.insert([
{ title: "Abuse" },
{ title: "Assault" },
{ title: "Cell phone missing" },
{ title: "Civil dispute" },
{ title: "Communal class quarrel" },
{ title: "Disorderly contact" },
{ title: "Document missing" },
{ title: "Dowry related" },
{ title: "Eve teasing" },
{ title: "Family quarrel" },
{ title: "Fishing rights" },
{ title: "House owner / tenant" },
{ title: "Irrigation rights" },
{ title: "Land dispute" },
{ title: "Land owner / tenant" },
{ title: "Love affair" },
{ title: "Marital problem" },
{ title: "Miscellaneous" },
{ title: "Money quarrel" },
{ title: "Neighbor quarrel" },
{ title: "Property dispute" },
{ title: "Ragging" },
{ title: "Street tap quarrel" },
{ title: "Threats" },
{ title: "Worldly quarrel" }
])
Base url: https://spider.nitt.edu/police_cms
Auth Routes
1.OTP INIT :
ROUTE : /auth/login/otpinit
Request :
{
"mobileNo"
:
7299338845
}
RESPONSE
:
200 : {
"message"
:
"OTP sent"
,
“exist”: true || false // false - new user, use register route
}
208 : { “message” : “ wait for 59 seconds to resend OTP” }
// If otp is initiated before
expiration
500 : { “message” : “Server error. Try again later” }
2. Register
Route : /auth/register
POST REQUEST :
{
"name": "flipkart",
"mobileNo": 3215678931,
"rank": "5f7f5828557edcf587ee743d",
"office": "5f7f5862557edcf587ee743f",
"precinctsIncharge":
["5f7f5862557edcf587ee743f","5f7f5858557edcf587ee743e"],
"otp": 678931
}
RESPONSE:
200 : {
"message": "Success",
"name": "flipkart",
"id": "5f96ef2081b2c7a77c8955b5",
"mobileNo": 3215678931,
"office": {
"_id": "5f7f5862557edcf587ee743f",
"dayComplaintCount": 0
,
"title": "CENTRAL"
},
"rank": {
"_id": "5f7f5828557edcf587ee743d",
"title": "COMMISSIONER"
},
"precinctsIncharge": {
"data": [
{
"_id": "5f7f5862557edcf587ee743f",
"dayComplaintCount": 0,
"title": "
CENTRAL"
},
{
"_id": "5f7f5858557edcf587ee743e",
"dayComplaintCount": 0,
"title": "
SATRAM"
}
],
"length": 2
},
"token":
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZmxvcGthcnQiLCJpZCI
6IjVmOTZlZjIwODFiMmM3YTc3Yzg5NTViNSIsIm1vYmlsZU5vIjozMjE1Njc4OTMxLCJp
YXQiOjE2MDM3ODU0NzMsImV4cCI6MTYwNjM3NzQ3M30.HXbKjYO7MFzIJt8ZrZtV4PrhK
yM4PEFO88KKWb82Qfc"
}
400 : { “message” : “ Fill all Fields” } // if
any field missed
409 : { “message” : “ User already exist” }
404 : { “message” : “ User not found “ } //if otp
is not initialised
404 : { “message” : “ Enter valid rank “ } //given
rank not found in db
404 : { “message” : “ Enter valid precinct“ }
//given precinct not found in db
400 : { “message” : “ Invalid OTP “ }
//provided otp is wrong
403 : { “message” : “ OTP expired. “ } //provided
otp is expired
500 : { “message” : “Server error. Try again later” }
3.LOGIN
ROUTE : /auth/login
Request :
{
"mobileNo": 3215678931,
"otp": 678931
}
Response :
200 : {
"message": "Success",
"name": "flipkart",
"id": "5f96ef2081b2c7a77c8955b5",
"mobileNo": 3215678931,
"office": {
"_id": "5f7f5862557edcf587ee743f",
"dayComplaintCount": 0
,
"title": "CENTRAL"
},
"rank": {
"_id": "5f7f5828557edcf587ee743d",
"title": "COMMISSIONER"
},
"precinctsIncharge": {
"data": [
{
"_id": "5f7f5862557edcf587ee743f",
"dayComplaintCount": 0,
"title": "
CENTRAL"
},
{
"_id": "5f7f5858557edcf587ee743e",
"dayComplaintCount": 0,
"title": "
SATRAM"
}
],
"length": 2
},
"token":
"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiZmxvcGthcnQiLCJpZCI6IjVmOT
ZlZjIwODFiMmM3YTc3Yzg5NTViNSIsIm1vYmlsZU5vIjozMjE1Njc4OTMxLCJpYXQiOjE2MDM3OD
U0NzMsImV4cCI6MTYwNjM3NzQ3M30.HXbKjYO7MFzIJt8ZrZtV4PrhKyM4PEFO88KKWb82Qfc"
}
400 : { “message” : “Fill all fields” }
404 : { “message” : “User not found” }
403 : { “message” : “Not registered” }
400 : { “message” : “Invalid OTP“ } //provided otp is wrong
403 : { “message” : “ OTP expired.“ }
500 : { “message” : “Server error. Try again later” }
Api routes
Public routes, no jwt required
1. Get the all present ranks
/api/list/ranks
GET ROUTE:
Fetch the all Ranks present in the database.Does not require auth token
Response :
{
“data”:[ {
_id: 12345,
title: “INSPECTOR”,
hierarchicalval : 3
},
{
_id: 1234556768,
title: “COMMISSIONER”,
hierarchicalval : 1
}],
“length” : 2
}
Return 200 success message with all Ranks present in the database (if zero rank present then
return empty array )
Else return 500 error with error message.
2. Get the all present precinct
/api/list/precincts
GET ROUTE:
Fetch the all Precinct present in the database.Does not require auth token
Response :
{
“data”:[ {
_id: 12345,
title: “Central”
Type : , true/false true->precinct, false->office
dayComplaintCount:
},
“ {
_id: 1234556768,
title: “Chatram”,
Type : ,
dayComplaintCount:
}],
“length” : 2
}
Return 200 success message with all Ranks present in the database (if zero rank present then
return empty array )
Else return 500 error with error message.
Private routes: jwt required
JWT check
Jwt should be a header for all api routes(not auth routes)
JWT MIDDLEWARE :
Request :
Auth-Token : JWT
Response :
200 : Jwt_payload :{
"name": "Raina",
"id": "5f8f2e0306099b76d065fcd8",
"mobileNo": 1299338845,
"iat": 1603218961,
"exp": 1605810961
}
(this is not a response, the requested route will be executed)
401 : { “message” : “No token” }
403 : { “Message” : “Token expired or invalid” }
500 : { “message” : “Server error. Try again later” }
1.Officers of a rank
api/police/ranks_and_officers?rankid={rankid}
GET Request:
{
rankid: 5f7ddc5aa59e8bb3cc4cbb95
}
Response:
{
“data”: [{
"_id": "5f97d11d8fcfa551482134b3",
"name": "ram",
"rank": {
"_id": "5f97d11d8fcfa551482134b0",
"title": "Inspector",
"hierarchicalVal": 3,
"__v": 0
},
"office": {
"_id": "5f97d11c8fcfa551482134ac",
"title": "Central",
"__v": 0,
"dayComplaintCount": 0
}
}],
length: 1
}
Status code:
200: Success
406: No officers found in that rank
500: server issue
2.Officers of a Precinct
/api/police/precinct_officers?precinctid=5f8151e8d7a8e42d7cd2a168
Response:
{
"data": [{
"_id": "5f97d11d8fcfa551482134b3",
"name": "ram",
"rank": {
"_id": "5f97d11d8fcfa551482134b0",
"title": "Inspector",
"hierarchicalVal": 3,
"__v": 0
},
"office": {
"_id": "5f97d11c8fcfa551482134ac",
"title": "Central",
"__v": 0
}
}],
“length” : 1
}
{
"message": "Invalid Precinct"
}
3.list of complaint types
/api/police/list_complaint_types
Response:
{
"data": [{
"_id": "5f96b54310427d4810c1e324",
"title": "Abuse"
},
{
"_id": "5f96b54310427d4810c1e32e",
"title": "Fishing rights"
},
{
"_id": "5f96b54310427d4810c1e32f",
"title": "House owner / tenant"
},
{
"_id": "5f96b54310427d4810c1e330",
"title": "Irrigation rights"
}],
"length": 4
}
4.NEW COMPLAINT:
ROUTE: /api/police/new_complaint
POST Request:
{
“place”:”india”,
“description”:”murder”, //optional
“assigned”: [ “5f91b22fc42e1b20dc5e9bd2” , ”5f91b22fc42e1b20dc5e9bt8” ],//optional
“files”: single file or an array of files, //optional
“dateOfOccurrence”: 2 020-10-06T17:09:46.644+00:00,
“
complaintType“ : “
5f94404b3e377fe8dd10b23c”,
“precinct” : “5f7f5862557edcf587ee743f”
}
Response:
201 : {
"message": "New complaint created",
"complaint": {
"assigned": [ “ 5f91b22fc42e1b20dc5e9bd2” , ”5f91b22fc42e1b20dc5e9bt8”],
"_id": "5f96af903e9b8055a82557ef",
"documents": [
{
"_id": "5f96af903e9b8055a82557f0",
"originalname": "106119141-DSD-lab.pdf",
"mimetype": "application/pdf",
"file_stored_name":
"7f27b735-f8e9-46a5-96c9-c7fa261b1253.pdf"
}
],
"place": "india",
"description": "Murder", //optional
"dateOfOccurrence": "2020-10-15T00:00:00.000Z",
"createdAt": "2020-10-26T11:14:24.034Z",
"updatedAt": "2020-10-26T11:14:24.034Z",
"status": true,
"precinct": "5f7f5862557edcf587ee743f",
"complaintType": "
5f94404b3e377fe8dd10b23c",
"name": "SATRAM/26-10-2020/1",
"__v": 0
}
}
400 : {
{ Error : err } // file upload error
{message:"Fill all required fields"}
{message:"Error while searching assignee"}
}
404 :{
{message:"precinct not found"}
{message:"complaint type not found"}
{message:`Assignee ${assign ID} is not found`}
}
500 : {
{message:"Error updating user's complaint"}
{message: 'Complaint cannot be created'}
}
5. Getting complaints route
api/police/active_complaints_user
GET ROUTE:
Get a complaints list for the logged-in user.if no complaints are assigned to user then it will
return the empty array
REQUEST:
Id of current user will be taken by jwt payload so need for any req.
RESPONSE:
If complaints are found, the response will be an array of complaints.
Status: 200
{
"complaints": [
{
"assigned": [],
"documents": [{}],
"_id": "5f816dcb9aa1243820c33a24",
"place": "some desx",
"description": "some description",
"__v": 0
}
],
"complaints_length": 1
}
If complaints_length == 0 then no complaints are assigned to particular user
{
"complaints": [],
"complaints_length": 0
}
//Error conditions
It will return error message
Status:404
{ message: "No such user found " }
}
Status: 500
{ "message": "Server error : Try again later" }
When the user of particular id is not found
6. Get all active complaints of precinct incharge by the police
api/police/active_complaints_incharge
REQUEST
Header: JWT Token
RESPONSE
If assigned active complaints exist
Status: 200
{
activeComplaint:[{
precinctComplaints:[{
“place”: ”someplace”,
“description”:”description”,
“assigned”:[“id1”,”id2”..],
“Precinct”:”precinct_id”,
“dateOfOccurence”:date,
“createdAt”:date,
“updatedAt”:date,
“status”:true,
“Documents”:[“doc1”,”doc2”....],
},
{...}]
totalComplaints:2
},
{.....}]
totalPrecincts:2
}
Status: 500:Message :”Server error : try again later”
Status: 500:Message : “Database error : try again later”
Occurs if there is any mistake in the records
Status: 400:Message:”Type Mismatch: Object Id”
Object id is invalid
7. Get all pending complaints of the precincts for which the officer is incharge.
GET: /api/police/pending_complaints_precinct
● REQUEST: Header JWT-Token
● RESPONSE:
Status: 200
If Pending Complaints is Not Empty:
{
"data": [
{
"assigned": [],
"_id": "5f96cd17c137219e7f2ad50c",
"place": "place1",
"description": "some description1",
"dateOfOccurrence": "2020-10-01T00:00:00.000Z",
"precinct": "5f96cd16c137219e7f2ad506",
"createdAt": "2020-10-26T13:20:23.532Z",
"updatedAt": null,
"status": true,
"documents": []
}
],
"length": 1
}
If Pending Complaints is Empty:
{
"data": [],
"length": 0
}
Status: 500
{
"message": "Server error : Try again later"
}
8. Get all pending complaints of precinct incharge by the police
GET: /api/police/pending_complaints_office
● REQUEST: Header JWT-Token
● RESPONSE:
Status: 200
If Pending Complaints is Not Empty:
{
"data": [
{
"assigned": [],
"_id": "5f96cd17c137219e7f2ad50c",
"place": "place1",
"description": "some description1",
"dateOfOccurrence": "2020-10-01T00:00:00.000Z",
"precinct": "5f96cd16c137219e7f2ad506",
"createdAt": "2020-10-26T13:20:23.532Z",
"updatedAt": null,
"status": true,
"documents": []
}
],
"length": 1
}
If Pending Complaints is Empty:
{
"data": [],
"length": 0
}
Status: 500
{
"message": "Server error : Try again later"
}
9. Complaint details
Provides the single complaint for search using id or name
Route: GET /api/police/complaint_search
Request :
{
"complaintID": "5f96836d97410a0decee9c27",
Or
"name": "CENTRAL/25-05-2020/5",
}
Response:
Status 200
{
"assigned": [
{
"precinctsIncharge": [
{
"_id": "5f7f62725015067d0af6d198",
"title": "CENTRAL"
}
],
"complaints": [
"5f7f471e04d7330ffdc14e3d"
],
"_id": "5f7e2ade763d58358a3b9cc2",
"mobileNo": 7092622767,
"__v": 0,
"name": "test 1",
"office": {
"_id": "5f7f62725015067d0af6d198",
"title": "CENTRAL"
},
"rank": {
"_id": "5f7ddc78a59e8bb3cc4cbb97",
"title": "INSPECTOR",
"__v": 0
}
}
],
"_id": "5f7f471e04d7330ffdc14e3d",
"Documents": [
"1602176798491download.jpeg"
],
"place": "india",
"description": "hello world",
"dateOfOccurrence": "2020-10-06T17:09:46.644Z",
"createdAt": "2020-10-08T17:06:38.499Z",
"updatedAt": "2020-10-13T05:35:22.547Z",
"FIRNo": 22,
"name": "anish",
"__v": 0,
"precinct": {
"_id": "5f7f62725015067d0af6d198",
"title": "CENTRAL",
"dayComplaintCount": 0
},
"documents": []
}
Status 401
{
"message": "No request body"
}
Status 405
{
"message": "Something went wrong while populating user"
Status 400
{
"message": "Unauthorized access" // The user is not assigned
}
Status 500
{
"message": "complaint not found"
}
10.Update Complaint:
Updates the fields of the complaint. Only open complaints can be updated and
only a person assigned to it can update it. id is a necessary field others are optional
.Its not necessary to send in all the fields and only the fields that are being sent will be
updated.
Route: /api/police/update_complaint
Request:
{
"id": "5f96836d97410a0decee9c27",
"place": "new place 3",
"description": "some description 2",
"dateOfOccurrence": "2020-01-01"
}
Response:
200:
{
"updatedComplaint": {
"assigned": [
"5f9681762e47d82894f19a44"
],
"_id": "5f96836d97410a0decee9c27",
"place": "new place 3",
"description": "some description 2",
"dateOfOccurrence": "2020-01-01T00:00:00.000Z",
"precinct": "5f966eef0ccdaa2920d70c23",
"createdAt": "2020-10-26T08:06:05.906Z",
"updatedAt": "2020-10-27T04:14:32.733Z",
"status": true,
"documents": [],
"__v": 0
}
}
400:
{
"message": "Invalid values of request items",
"errors": [
{
"msg": "Invalid value",
"param": "id",
"location": "body"
}
]
}
400:
{
"message": "Invalid Complaint id"
}
403:
{
"message": "You don't have permission to modify the complaint "
}
403:
{
"message": "The complaint is closed"
}
404:
{
"message": "Complaint not found for the given id"
}
500:
{
"message": "Complaint not updated"
}
500:
{
"message": "Server Error : Complaint cannot be updated"
}
11. Adding Police of higher rank
/api/police/add_assignee
POST ROUTE:
REQUEST:
Header : JWT Token
policeId
complaintId
RESPONSE
200: Message:”Success”
202: Message:”Record already updated”
Record is already updated
401: Message:”Record cannot be accessed”
When complaint does not exist or police does not belong to precinct of complaint
400: Message:”Invalid object id”
The given id is not proper object id
400: Message:”Request not received”
Empty policeId or complaintId
404:Message:”Record cannot be found”
Record does not exist
500: Message: “Server error : Try again later”
12. Deleting Police of higher rank
/api/police/del_assignee
POST ROUTE:
REQUEST:
Header : JWT Token
policeId
complaintId
RESPONSE
200: Message:”Success”
401: Message:”Record cannot be accessed”
When complaint does not exist or police does not belong to precinct of complaint
400: Message:”Invalid object id”
The given id is not proper object id
400: Message:”Request not received”
Empty policeId or complaintId
404:Message:”Record cannot be found”
Record does not exist i.e.,police is not found in complaint and vice versa
500: Message: “Server error : Try again later”
13. ADD FILES :
POST ROUTE : /api/police/add_file/{ complaintID }
REQUEST : {
files : add single or multiple files array
}
RESPONSE :
200 : {
{message:"file added successfully"}
}
400 : {
{Error:err}
{message: "complaintID required" }
{message: "Complaint closed" }
}
403 : {
{ message: "Only assignees can modify" }
}
404 : {
{message: "Complaint not found for the given id" }
{message:"file not found"}
}
500 : {
{message:"server error"}
}
14. DELETE FILE :
POST ROUTE : /api/police/delete_file/{complaintID}?fileName={filename stored}
RESPONSE :
200 : {
{message:"file deleted successfully"}
}
400 : {
{Error:err}
{message: "complaintID required" }
{message: "Complaint closed" }
}
403 : {
{ message: "Only assignees can modify" }
}
404 : {
{message: "complaintID & filename required"}
{message: "Complaint not found for the given id" }
{message:"file not found"}
}
500 : {
{message:"server error"}
}
15. DOWNLOAD FILE : (single)
POST ROUTE :
/api/police/downloads/complaint_id?filename={stored_file_name}
RESPONSE :
200 : {
File will download directly
}
400 : {
{message:"no such file exist in directory"}
{message:"No documents found for given complaint id"}
{message:”filename required”}
}
404 : {
message:"No document found for given params id"
}
500 : {
{message:"server error"}
}
16. Open OR Close petition:
POST: /api/police/openclose_petition
REQUEST:
user_id from header jwt-token
{
"complaintId":"5f96cd17c137219e7f2ad50d",
"operate":"open"
}
● Note:
To open petition -> "
operate":"open"
To close petition -> "operate":"close"
RESPONSE:
Status: 200
● If petition got open successfully:
( Note: If the officer is within the precinct of petition and is assigned / not assigned
he/she can open the petition. )
{
"message": "Petition Opened"
}
● If petition got open successfully:
( Note: If the officer is within the precinct of petition and is NOT assigned to the petition
he/she cannot close the petition. )
{
"message": "Petition Closed"
}
Status: 406
● If petition is not assigned to officer and (officer) is within the precinct/office and
if he/she attempt to close the petition:
{
"message": "Not Assigned To Petition"
}
● If petition is not within the precinct range of officer and he/she attempts to
close/open the petition:
{
"message": "Petition Precinct Not In Range"
}
Status: 500
{
"message": "Server error : Try again later"
}
SAMPLE DATA:
use police_cms
switched to db police_cms
> db.users.insert({Name:"name", phone:"9999999999", complaints:["<the complaint id>"]})
WriteResult({ "nInserted" : 1 })
> db.ranks.insert({title:"Officer"})
WriteResult({ "nInserted" : 1 })
> db.complaints.insert({assigned:["<the user id>"], updatedAt:1243})
WriteResult({ "nInserted" : 1 })
use police_cms
switched to db police_cms
> db.users.insert({Name:"name2", phone:"9999999998", complaints:["<the complaint id>"]})
WriteResult({ "nInserted" : 1 })
> db.ranks.insert({title:"Officer"})
WriteResult({ "nInserted" : 1 })
> db.complaints.insert({assigned:["<the user id>"], updatedAt:1243})
WriteResult({ "nInserted" : 1 })
use police_cms
switched to db police_cms
> db.users.insert({Name:"name3", phone:"9999999997", complaints:["<the complaint id>"]})
WriteResult({ "nInserted" : 1 })
> db.ranks.insert({title:"Captain"})
WriteResult({ "nInserted" : 1 })
> db.complaints.insert({assigned:["<the user id>"], updatedAt:1243})
WriteResult({ "nInserted" : 1 })