Skip to content

Commit

Permalink
Add address and organization tables, and related services
Browse files Browse the repository at this point in the history
  • Loading branch information
rukmal committed Sep 26, 2022
1 parent e99b5aa commit 9ed14fc
Show file tree
Hide file tree
Showing 9 changed files with 241 additions and 4 deletions.
6 changes: 3 additions & 3 deletions api/Config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
USER="root"
PASSWORD="test"
DATABASE="avinya_db"
HOST="localhost"
PASSWORD="test"
PORT=3306
DATABASE="avinya_db"
USER="root"
43 changes: 43 additions & 0 deletions api/geo_data.bal
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ public distinct service class GeoData {
resource function get city(string name) returns CityData|error {
return new (name, ());
}

resource function get address(int id) returns AddressData|error {
return new (id);
}
}

public distinct service class ProvinceData {
Expand All @@ -28,6 +32,10 @@ public distinct service class ProvinceData {
self.province = province_raw;
}

resource function get id() returns int? {
return self.province.id;
}

resource function get name() returns LocalizedName {
return {
"name_en": self.province["name_en"],
Expand Down Expand Up @@ -84,6 +92,10 @@ public distinct service class DistrictData {
};
}

resource function get id() returns int? {
return self.district.id;
}

resource function get province() returns ProvinceData|error {
return new ((), self.district.province_id);
}
Expand Down Expand Up @@ -136,7 +148,38 @@ public distinct service class CityData {
};
}

resource function get id() returns int? {
return self.city.id;
}

resource function get district() returns DistrictData|error {
return new ((), self.city.district_id);
}
}


public distinct service class AddressData {
private Address address;

function init(int address_id) returns error? {
Address address_raw = check db_client -> queryRow(
`SELECT *
FROM avinya_db.address
WHERE id = ${address_id};`
);

self.address = address_raw.cloneReadOnly();
}

resource function get city() returns CityData|error {
return new ((), self.address.city_id);
}

resource function get street_address() returns string {
return self.address.street_address;
}

resource function get phone() returns int? {
return self.address.phone;
}
}
55 changes: 55 additions & 0 deletions api/main.bal
Original file line number Diff line number Diff line change
@@ -1,8 +1,63 @@
import ballerina/graphql;
import ballerina/sql;

service graphql:Service /graphql on new graphql:Listener(4000) {
resource function get geo() returns GeoData {
return new ();
}

resource function get organization(string? name, int? id) returns OrganizationData|error? {
return new (name, id);
}

remote function add_organization(Organization org) returns OrganizationData|error? {
sql:ExecutionResult res = check db_client->execute(
`INSERT INTO avinya_db.organization (
name_en,
name_si,
name_ta,
address_id,
phone
) VALUES (
${org.name_en},
${org.name_si},
${org.name_ta},
${org.address_id},
${org.phone},
);`
);

int|string? insert_id = res.lastInsertId;
if !(insert_id is int) {
return error("Unable to insert organization");
}

// Insert child and parent organization relationships
int[] child_org_ids = org.child_organizations ?: [];
int[] parent_org_ids = org.parent_organizations ?: [];

foreach int child_idx in child_org_ids {
_ = check db_client->execute(
`INSERT INTO avinya_db.parent_child_organization (
child_org_id,
parent_org_id
) VALUES (
${child_idx}, ${org.id}
);`
);
}

foreach int parent_idx in parent_org_ids {
_ = check db_client->execute(
`INSERT INTO avinya_db.parent_child_organization (
child_org_id,
parent_org_id
) VALUES (
${org.id}, ${parent_idx}
);`
);
}

return new ((), insert_id);
}
}
73 changes: 73 additions & 0 deletions api/organization_data.bal
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
public distinct service class OrganizationData {
private Organization organization;

function init(string? name, int? organization_id) returns error? {
Organization org_raw = check db_client -> queryRow(
`SELECT *
FROM avinya_db.organization
WHERE
id = ${organization_id}
OR name_en = ${name};`
);

self.organization = org_raw.cloneReadOnly();
}

resource function get address() returns AddressData|error? {
return new AddressData(self.organization.address_id);
}

resource function get phone() returns int {
return self.organization.phone;
}

resource function get name() returns LocalizedName {
return {
"name_en": self.organization["name_en"],
"name_si": <string>self.organization["name_si"],
"name_ta": <string>self.organization["name_ta"]
};
}

resource function get child_organizations() returns OrganizationData[]|error? {
// Get list of child organizations
stream<ParentChildOrganization, error?> child_org_ids = db_client->query(
`SELECT *
FROM avinya_db.parent_child_organization
WHERE parent_org_id = ${self.organization.id}`
);

OrganizationData[] child_orgs = [];

check from ParentChildOrganization pco in child_org_ids
do {
OrganizationData|error candidate_org = new OrganizationData((), pco.child_org_id);
if !(candidate_org is error) {
child_orgs.push(candidate_org);
}
};

return child_orgs;
}

resource function get parent_organizations() returns OrganizationData[]|error? {
// Get list of child organizations
stream<ParentChildOrganization, error?> parent_org_ids = db_client->query(
`SELECT *
FROM avinya_db.parent_child_organization
WHERE parent_org_id = ${self.organization.id}`
);

OrganizationData[] parent_orgs = [];

check from ParentChildOrganization pco in parent_org_ids
do {
OrganizationData|error candidate_org = new OrganizationData((), pco.parent_org_id);
if !(candidate_org is error) {
parent_orgs.push(candidate_org);
}
};

return parent_orgs;
}
}
2 changes: 1 addition & 1 deletion api/tests/Config.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
USER="root"
PASSWORD="test"
HOST="mysql"
PASSWORD="test"
PORT=3306
DATABASE="avinya_db"
26 changes: 26 additions & 0 deletions api/types.bal
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,29 @@ public type City record {|
string postcode;
*GeospatialInformation;
|};


public type Address record {
readonly string record_type = "address";
int id?;
*LocalizedName;
string street_address;
int? phone;
int city_id;
};


public type Organization record {|
readonly string record_type = "organization";
int id?;
*LocalizedName;
int[] child_organizations?;
int[] parent_organizations?;
int address_id;
int phone;
|};

type ParentChildOrganization record {|
int child_org_id;
int parent_org_id;
|};
7 changes: 7 additions & 0 deletions api/util.bal
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@ configurable string DATABASE = ?;
# MySQL database client
final mysql:Client db_client = check new (host = HOST, user = USER, password = PASSWORD, port = PORT, database = DATABASE);

// mysql:Client db_client = check new (host = HOST, port = PORT, user = USER, password = PASSWORD, database = DATABASE, options = {
// ssl: {
// mode: mysql:SSL_PREFERRED
// },
// serverTimezone: "Asia/Calcutta"
// });

# Function to build the `WHERE` clause for a SQL query, given a
# `LocalizedName` record. Iterates through the record and dynamically
# constructs the `WHERE` clause.
Expand Down
33 changes: 33 additions & 0 deletions db/schema/2-organization_and_address_tables.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
USE avinya_db;

-- Address
CREATE TABLE IF NOT EXISTS address (
id INT NOT NULL PRIMARY KEY,
name_en VARCHAR(255) NOT NULL,
name_ta VARCHAR(255),
name_si VARCHAR(255),
street_address VARCHAR(255) NOT NULL,
phone INT,
city_id INT NOT NULL,
FOREIGN KEY (city_id) REFERENCES city(id)
);

-- Organization
CREATE TABLE IF NOT EXISTS organization (
id INT NOT NULL PRIMARY KEY,
name_en VARCHAR(255) NOT NULL,
name_ta VARCHAR(255),
name_si VARCHAR(255),
phone int,
address_id INT NOT NULL,
FOREIGN KEY (address_id) REFERENCES address(id)
);

-- Parent/Child Organization relationship
CREATE TABLE IF NOT EXISTS parent_child_organization (
child_org_id INT NOT NULL,
parent_org_id INT NOT NULL,
FOREIGN KEY (child_org_id) REFERENCES organization(id),
FOREIGN KEY (parent_org_id) REFERENCES organization(id),
CONSTRAINT pk_parent_child_organization PRIMARY KEY (child_org_id, parent_org_id)
);
Empty file removed db/schema/2-person_tables.sql
Empty file.

0 comments on commit 9ed14fc

Please sign in to comment.