-
Notifications
You must be signed in to change notification settings - Fork 18
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: added schema and crl apis for organisation (#322)
- Loading branch information
Showing
15 changed files
with
326 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
mod handlers; | ||
pub mod types; | ||
pub use handlers::endpoints; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,146 @@ | ||
use actix_web::{ | ||
get, post, | ||
web::{self, Json, Query}, | ||
HttpResponse, Scope, | ||
}; | ||
use chrono::Utc; | ||
use diesel::prelude::*; | ||
use idgenerator::IdInstance; | ||
use service_utils::service::types::DbConnection; | ||
use superposition_types::database::{ | ||
models::organisation::{OrgStatus, Organisation}, | ||
schema::organisations::dsl::organisations, | ||
}; | ||
use superposition_types::{ | ||
custom_query::PaginationParams, result as superposition, PaginatedResponse, User, | ||
}; | ||
|
||
use super::types::{CreateOrganisationRequest, CreateOrganisationResponse}; | ||
|
||
pub fn endpoints() -> Scope { | ||
Scope::new("") | ||
.service(create_organisation) | ||
.service(list_organisations) | ||
.service(get_organisation) | ||
} | ||
|
||
#[post("")] | ||
pub async fn create_organisation( | ||
req: web::Json<CreateOrganisationRequest>, | ||
db_conn: DbConnection, | ||
user: User, | ||
) -> superposition::Result<HttpResponse> { | ||
let DbConnection(mut conn) = db_conn; | ||
|
||
// Generating a numeric ID from IdInstance and prefixing it with `orgid` | ||
let numeric_id = IdInstance::next_id(); | ||
let org_id = format!("orgid{}", numeric_id); | ||
let now = Utc::now().naive_utc(); | ||
|
||
let new_org = Organisation { | ||
id: org_id.clone(), | ||
name: req.name.clone(), | ||
country_code: req.country_code.clone(), | ||
contact_email: req.contact_email.clone(), | ||
contact_phone: req.contact_phone.clone(), | ||
created_by: user.get_username(), | ||
admin_email: req.admin_email.clone(), | ||
status: OrgStatus::PendingKyb, | ||
sector: req.sector.clone(), | ||
created_at: now, | ||
updated_at: now, | ||
updated_by: user.get_username(), | ||
}; | ||
|
||
diesel::insert_into(organisations) | ||
.values(&new_org) | ||
.execute(&mut conn) | ||
.map_err(|e| { | ||
log::error!("Failed to insert new organisation: {:?}", e); | ||
superposition::AppError::UnexpectedError(anyhow::anyhow!( | ||
"Failed to create organisation" | ||
)) | ||
})?; | ||
|
||
let mut http_resp = HttpResponse::Created(); | ||
Ok(http_resp.json(CreateOrganisationResponse { org_id })) | ||
} | ||
|
||
#[get("/{org_id}")] | ||
pub async fn get_organisation( | ||
org_id: web::Path<String>, | ||
db_conn: DbConnection, | ||
) -> superposition::Result<HttpResponse> { | ||
let DbConnection(mut conn) = db_conn; | ||
|
||
let org = organisations | ||
.find(org_id.as_str()) | ||
.first::<Organisation>(&mut conn) | ||
.map_err(|e| { | ||
log::error!("Failed to fetch organisation {}: {:?}", org_id, e); | ||
match e { | ||
diesel::result::Error::NotFound => superposition::AppError::NotFound( | ||
format!("Organisation {} not found", org_id), | ||
), | ||
_ => superposition::AppError::UnexpectedError(anyhow::anyhow!( | ||
"Failed to fetch organisation" | ||
)), | ||
} | ||
})?; | ||
|
||
Ok(HttpResponse::Ok().json(org)) | ||
} | ||
|
||
#[get("/list")] | ||
pub async fn list_organisations( | ||
db_conn: DbConnection, | ||
filters: Query<PaginationParams>, | ||
) -> superposition::Result<Json<PaginatedResponse<Organisation>>> { | ||
use superposition_types::database::schema::organisations::dsl::*; | ||
let DbConnection(mut conn) = db_conn; | ||
log::info!("list_organisations"); | ||
let result = | ||
conn.transaction::<_, superposition::AppError, _>(|transaction_conn| { | ||
// If all parameter is true, return all organisations | ||
if let Some(true) = filters.all { | ||
let result: Vec<Organisation> = organisations | ||
.order(created_at.desc()) | ||
.get_results(transaction_conn)?; | ||
log::info!("organisations: {organisations:?}"); | ||
return Ok(PaginatedResponse { | ||
total_pages: 1, | ||
total_items: result.len() as i64, | ||
data: result, | ||
}); | ||
} | ||
|
||
// Get total count of organisations | ||
let total_items: i64 = organisations.count().get_result(transaction_conn)?; | ||
|
||
// Set up pagination | ||
let limit = filters.count.unwrap_or(10); | ||
let mut builder = organisations | ||
.into_boxed() | ||
.order(created_at.desc()) | ||
.limit(limit); | ||
|
||
// Apply offset if page is specified | ||
if let Some(page) = filters.page { | ||
let offset = (page - 1) * limit; | ||
builder = builder.offset(offset); | ||
} | ||
|
||
// Get paginated results | ||
let data: Vec<Organisation> = builder.load(transaction_conn)?; | ||
|
||
let total_pages = (total_items as f64 / limit as f64).ceil() as i64; | ||
|
||
Ok(PaginatedResponse { | ||
total_pages, | ||
total_items, | ||
data: data, | ||
}) | ||
})?; | ||
|
||
Ok(Json(result)) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use serde::{Deserialize, Serialize}; | ||
|
||
// Request payload for creating an organisation | ||
#[derive(Deserialize)] | ||
pub struct CreateOrganisationRequest { | ||
pub country_code: Option<String>, | ||
pub contact_email: Option<String>, | ||
pub contact_phone: Option<String>, | ||
pub admin_email: String, | ||
pub name: String, | ||
pub sector: Option<String>, | ||
} | ||
|
||
// Response type to include `org_id` | ||
#[derive(Serialize)] | ||
pub struct CreateOrganisationResponse { | ||
pub org_id: String, | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
8 changes: 8 additions & 0 deletions
8
crates/superposition_types/migrations/2024-12-19-095525_create_organisation_table/down.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
-- down.sql | ||
DROP INDEX IF EXISTS superposition.idx_organisation_admin_email; | ||
DROP INDEX IF EXISTS superposition.idx_organisation_created_at; | ||
DROP INDEX IF EXISTS superposition.idx_organisation_status; | ||
DROP INDEX IF EXISTS superposition.idx_organisation_contact_email; | ||
DROP TABLE IF EXISTS superposition.organisation; | ||
DROP TYPE IF EXISTS superposition.org_status; | ||
DROP SCHEMA IF EXISTS superposition; |
26 changes: 26 additions & 0 deletions
26
crates/superposition_types/migrations/2024-12-19-095525_create_organisation_table/up.sql
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
-- up.sql | ||
CREATE SCHEMA IF NOT EXISTS superposition; | ||
|
||
CREATE TYPE superposition.org_status AS ENUM ('ACTIVE', 'INACTIVE', 'PENDING_KYB'); | ||
|
||
CREATE TABLE IF NOT EXISTS superposition.organisations ( | ||
id VARCHAR(30) PRIMARY KEY NOT NULL, | ||
name TEXT NOT NULL, | ||
country_code VARCHAR(10), | ||
contact_email VARCHAR(255), | ||
contact_phone VARCHAR(15), | ||
created_by VARCHAR(255) NOT NULL, | ||
admin_email VARCHAR(255) NOT NULL, | ||
status superposition.org_status NOT NULL DEFAULT 'ACTIVE', | ||
sector VARCHAR(100), | ||
created_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, | ||
updated_at TIMESTAMP WITHOUT TIME ZONE DEFAULT NOW() NOT NULL, | ||
updated_by VARCHAR(255) NOT NULL | ||
); | ||
|
||
-- Indexes for optimizing queries | ||
CREATE INDEX IF NOT EXISTS idx_organisation_contact_email ON superposition.organisations (contact_email); | ||
CREATE INDEX IF NOT EXISTS idx_organisation_status ON superposition.organisations (status); | ||
CREATE INDEX IF NOT EXISTS idx_organisation_created_at ON superposition.organisations (created_at); | ||
CREATE INDEX IF NOT EXISTS idx_organisation_admin_email ON superposition.organisations (admin_email); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,3 +1,4 @@ | ||
pub mod cac; | ||
#[cfg(feature = "experimentation")] | ||
pub mod experimentation; | ||
pub mod organisation; |
Oops, something went wrong.