changing data model according to new data
This commit is contained in:
parent
464af45107
commit
9de3c4a482
4 changed files with 271 additions and 72 deletions
23
api/migrations/20250101002000_update_persons_schema.sql
Normal file
23
api/migrations/20250101002000_update_persons_schema.sql
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
BEGIN;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS persons;
|
||||||
|
|
||||||
|
CREATE TABLE persons (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
first_name TEXT NOT NULL,
|
||||||
|
last_name TEXT NOT NULL,
|
||||||
|
grade INTEGER NOT NULL,
|
||||||
|
parent_name TEXT NOT NULL,
|
||||||
|
parent_phone_number TEXT NOT NULL,
|
||||||
|
checked_in BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
inside BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
visitor BOOLEAN NOT NULL DEFAULT FALSE,
|
||||||
|
sleeping_spot BOOLEAN NOT NULL DEFAULT FALSE
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE INDEX idx_persons_first_name_trgm ON persons USING GIN (first_name gin_trgm_ops);
|
||||||
|
CREATE INDEX idx_persons_last_name_trgm ON persons USING GIN (last_name gin_trgm_ops);
|
||||||
|
CREATE INDEX idx_persons_parent_name_trgm ON persons USING GIN (parent_name gin_trgm_ops);
|
||||||
|
CREATE INDEX idx_persons_parent_phone_number ON persons (parent_phone_number);
|
||||||
|
|
||||||
|
COMMIT;
|
||||||
192
api/src/main.rs
192
api/src/main.rs
|
|
@ -187,13 +187,25 @@ async fn search_persons(
|
||||||
let persons = if let Some(id) = id_value {
|
let persons = if let Some(id) = id_value {
|
||||||
sqlx::query_as::<_, Person>(
|
sqlx::query_as::<_, Person>(
|
||||||
r#"
|
r#"
|
||||||
SELECT id, name, age, phone_number, checked_in, inside
|
SELECT
|
||||||
|
id,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
FROM persons
|
FROM persons
|
||||||
WHERE name ILIKE $1
|
WHERE first_name ILIKE $1
|
||||||
OR phone_number ILIKE $1
|
OR last_name ILIKE $1
|
||||||
|
OR parent_name ILIKE $1
|
||||||
|
OR parent_phone_number ILIKE $1
|
||||||
|
OR (first_name || ' ' || last_name) ILIKE $1
|
||||||
OR id = $2
|
OR id = $2
|
||||||
ORDER BY name
|
ORDER BY last_name, first_name
|
||||||
LIMIT 100
|
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(&like_pattern)
|
.bind(&like_pattern)
|
||||||
|
|
@ -203,12 +215,24 @@ async fn search_persons(
|
||||||
} else {
|
} else {
|
||||||
sqlx::query_as::<_, Person>(
|
sqlx::query_as::<_, Person>(
|
||||||
r#"
|
r#"
|
||||||
SELECT id, name, age, phone_number, checked_in, inside
|
SELECT
|
||||||
|
id,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
FROM persons
|
FROM persons
|
||||||
WHERE name ILIKE $1
|
WHERE first_name ILIKE $1
|
||||||
OR phone_number ILIKE $1
|
OR last_name ILIKE $1
|
||||||
ORDER BY name
|
OR parent_name ILIKE $1
|
||||||
LIMIT 100
|
OR parent_phone_number ILIKE $1
|
||||||
|
OR (first_name || ' ' || last_name) ILIKE $1
|
||||||
|
ORDER BY last_name, first_name
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(&like_pattern)
|
.bind(&like_pattern)
|
||||||
|
|
@ -252,7 +276,7 @@ async fn list_checked_in(
|
||||||
let id_value = search_term.as_ref().and_then(|s| s.parse::<i32>().ok());
|
let id_value = search_term.as_ref().and_then(|s| s.parse::<i32>().ok());
|
||||||
|
|
||||||
let mut qb = QueryBuilder::<sqlx::Postgres>::new(
|
let mut qb = QueryBuilder::<sqlx::Postgres>::new(
|
||||||
"SELECT id, name, age, phone_number, checked_in, inside FROM persons",
|
"SELECT id, first_name, last_name, grade, parent_name, parent_phone_number, checked_in, inside, visitor, sleeping_spot FROM persons",
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut first_condition = true;
|
let mut first_condition = true;
|
||||||
|
|
@ -278,8 +302,12 @@ async fn list_checked_in(
|
||||||
if let Some(like) = like_pattern.as_ref() {
|
if let Some(like) = like_pattern.as_ref() {
|
||||||
append_condition(&mut qb);
|
append_condition(&mut qb);
|
||||||
qb.push("(");
|
qb.push("(");
|
||||||
qb.push("name ILIKE ").push_bind(like);
|
qb.push("first_name ILIKE ").push_bind(like);
|
||||||
qb.push(" OR phone_number ILIKE ").push_bind(like);
|
qb.push(" OR last_name ILIKE ").push_bind(like);
|
||||||
|
qb.push(" OR parent_name ILIKE ").push_bind(like);
|
||||||
|
qb.push(" OR parent_phone_number ILIKE ").push_bind(like);
|
||||||
|
qb.push(" OR (first_name || ' ' || last_name) ILIKE ")
|
||||||
|
.push_bind(like);
|
||||||
if let Some(id) = id_value {
|
if let Some(id) = id_value {
|
||||||
qb.push(" OR id = ").push_bind(id);
|
qb.push(" OR id = ").push_bind(id);
|
||||||
}
|
}
|
||||||
|
|
@ -289,12 +317,9 @@ async fn list_checked_in(
|
||||||
if let Some(id) = id_value {
|
if let Some(id) = id_value {
|
||||||
qb.push(" ORDER BY CASE WHEN id = ")
|
qb.push(" ORDER BY CASE WHEN id = ")
|
||||||
.push_bind(id)
|
.push_bind(id)
|
||||||
.push(" THEN 0 ELSE 1 END, id, name");
|
.push(" THEN 0 ELSE 1 END, id, last_name, first_name");
|
||||||
} else {
|
} else {
|
||||||
qb.push(" ORDER BY id, name");
|
qb.push(" ORDER BY id, last_name, first_name");
|
||||||
}
|
|
||||||
if like_pattern.is_some() {
|
|
||||||
qb.push(" LIMIT 1000");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let persons = qb.build_query_as::<Person>().fetch_all(&state.db).await?;
|
let persons = qb.build_query_as::<Person>().fetch_all(&state.db).await?;
|
||||||
|
|
@ -345,53 +370,116 @@ async fn create_person(
|
||||||
state: &State<AppState>,
|
state: &State<AppState>,
|
||||||
payload: Json<NewPersonRequest>,
|
payload: Json<NewPersonRequest>,
|
||||||
) -> Result<Json<PersonActionResponse>, ApiError> {
|
) -> Result<Json<PersonActionResponse>, ApiError> {
|
||||||
let name = payload.name.trim();
|
let first_name = payload.first_name.trim();
|
||||||
if name.is_empty() {
|
if first_name.is_empty() {
|
||||||
return Err(ApiError::bad_request("Namn får inte vara tomt."));
|
return Err(ApiError::bad_request("Förnamn får inte vara tomt."));
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.age < 0 {
|
let last_name = payload.last_name.trim();
|
||||||
return Err(ApiError::bad_request("Ålder måste vara noll eller högre."));
|
if last_name.is_empty() {
|
||||||
|
return Err(ApiError::bad_request("Efternamn får inte vara tomt."));
|
||||||
}
|
}
|
||||||
|
|
||||||
let phone_number = payload.phone_number.trim();
|
if payload.grade < 0 {
|
||||||
if phone_number.is_empty() {
|
return Err(ApiError::bad_request("Klass måste vara noll eller högre."));
|
||||||
return Err(ApiError::bad_request("Telefonnummer krävs."));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let age = payload.age;
|
let parent_name = payload.parent_name.trim();
|
||||||
|
if parent_name.is_empty() {
|
||||||
|
return Err(ApiError::bad_request("Kontaktperson krävs."));
|
||||||
|
}
|
||||||
|
|
||||||
|
let parent_phone_number = payload.parent_phone_number.trim();
|
||||||
|
if parent_phone_number.is_empty() {
|
||||||
|
return Err(ApiError::bad_request(
|
||||||
|
"Kontaktpersonens telefonnummer krävs.",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
let grade = payload.grade;
|
||||||
let checked_in = payload.checked_in.unwrap_or(false);
|
let checked_in = payload.checked_in.unwrap_or(false);
|
||||||
let inside = payload.inside.unwrap_or(false);
|
let inside = payload.inside.unwrap_or(false);
|
||||||
|
let visitor = payload.visitor.unwrap_or(false);
|
||||||
|
let sleeping_spot = payload.sleeping_spot.unwrap_or(false);
|
||||||
|
|
||||||
let person = match payload.id {
|
let person = match payload.id {
|
||||||
Some(id) => sqlx::query_as::<_, Person>(
|
Some(id) => sqlx::query_as::<_, Person>(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO persons (id, name, age, phone_number, checked_in, inside)
|
INSERT INTO persons (
|
||||||
VALUES ($1, $2, $3, $4, $5, $6)
|
id,
|
||||||
RETURNING id, name, age, phone_number, checked_in, inside
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)
|
||||||
|
RETURNING
|
||||||
|
id,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
.bind(name)
|
.bind(first_name)
|
||||||
.bind(age)
|
.bind(last_name)
|
||||||
.bind(phone_number)
|
.bind(grade)
|
||||||
|
.bind(parent_name)
|
||||||
|
.bind(parent_phone_number)
|
||||||
.bind(checked_in)
|
.bind(checked_in)
|
||||||
.bind(inside)
|
.bind(inside)
|
||||||
|
.bind(visitor)
|
||||||
|
.bind(sleeping_spot)
|
||||||
.fetch_one(&state.db)
|
.fetch_one(&state.db)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| map_db_error(err, "Kunde inte skapa person"))?,
|
.map_err(|err| map_db_error(err, "Kunde inte skapa person"))?,
|
||||||
None => sqlx::query_as::<_, Person>(
|
None => sqlx::query_as::<_, Person>(
|
||||||
r#"
|
r#"
|
||||||
INSERT INTO persons (name, age, phone_number, checked_in, inside)
|
INSERT INTO persons (
|
||||||
VALUES ($1, $2, $3, $4, $5)
|
first_name,
|
||||||
RETURNING id, name, age, phone_number, checked_in, inside
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||||
|
RETURNING
|
||||||
|
id,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(name)
|
.bind(first_name)
|
||||||
.bind(age)
|
.bind(last_name)
|
||||||
.bind(phone_number)
|
.bind(grade)
|
||||||
|
.bind(parent_name)
|
||||||
|
.bind(parent_phone_number)
|
||||||
.bind(checked_in)
|
.bind(checked_in)
|
||||||
.bind(inside)
|
.bind(inside)
|
||||||
|
.bind(visitor)
|
||||||
|
.bind(sleeping_spot)
|
||||||
.fetch_one(&state.db)
|
.fetch_one(&state.db)
|
||||||
.await
|
.await
|
||||||
.map_err(|err| map_db_error(err, "Kunde inte skapa person"))?,
|
.map_err(|err| map_db_error(err, "Kunde inte skapa person"))?,
|
||||||
|
|
@ -415,7 +503,17 @@ async fn update_checked_in(
|
||||||
SET checked_in = $2,
|
SET checked_in = $2,
|
||||||
inside = $2
|
inside = $2
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
RETURNING id, name, age, phone_number, checked_in, inside
|
RETURNING
|
||||||
|
id,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
|
|
@ -446,7 +544,17 @@ async fn update_inside(
|
||||||
SET inside = $2
|
SET inside = $2
|
||||||
WHERE id = $1
|
WHERE id = $1
|
||||||
AND checked_in = TRUE
|
AND checked_in = TRUE
|
||||||
RETURNING id, name, age, phone_number, checked_in, inside
|
RETURNING
|
||||||
|
id,
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
"#,
|
"#,
|
||||||
)
|
)
|
||||||
.bind(id)
|
.bind(id)
|
||||||
|
|
@ -484,7 +592,7 @@ fn map_db_error(err: sqlx::Error, context: &str) -> ApiError {
|
||||||
if let Some(code) = db_err.code() {
|
if let Some(code) = db_err.code() {
|
||||||
if code == "23505" {
|
if code == "23505" {
|
||||||
return ApiError::bad_request(
|
return ApiError::bad_request(
|
||||||
"Krock i databasen – kontrollera id eller telefonnummer.",
|
"Krock i databasen – kontrollera id eller kontaktuppgifter.",
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -12,11 +12,15 @@ pub struct User {
|
||||||
#[derive(Debug, FromRow)]
|
#[derive(Debug, FromRow)]
|
||||||
pub struct Person {
|
pub struct Person {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub first_name: String,
|
||||||
pub age: i32,
|
pub last_name: String,
|
||||||
pub phone_number: String,
|
pub grade: i32,
|
||||||
|
pub parent_name: String,
|
||||||
|
pub parent_phone_number: String,
|
||||||
pub checked_in: bool,
|
pub checked_in: bool,
|
||||||
pub inside: bool,
|
pub inside: bool,
|
||||||
|
pub visitor: bool,
|
||||||
|
pub sleeping_spot: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
|
@ -36,25 +40,30 @@ pub struct LoginResponse {
|
||||||
#[serde(crate = "rocket::serde")]
|
#[serde(crate = "rocket::serde")]
|
||||||
pub struct PersonResponse {
|
pub struct PersonResponse {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub name: String,
|
pub first_name: String,
|
||||||
pub age: i32,
|
pub last_name: String,
|
||||||
pub phone_number: String,
|
pub grade: i32,
|
||||||
|
pub parent_name: String,
|
||||||
|
pub parent_phone_number: String,
|
||||||
pub checked_in: bool,
|
pub checked_in: bool,
|
||||||
pub inside: bool,
|
pub inside: bool,
|
||||||
pub under_ten: bool,
|
pub visitor: bool,
|
||||||
|
pub sleeping_spot: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Person> for PersonResponse {
|
impl From<Person> for PersonResponse {
|
||||||
fn from(person: Person) -> Self {
|
fn from(person: Person) -> Self {
|
||||||
let under_ten = person.age < 10;
|
|
||||||
PersonResponse {
|
PersonResponse {
|
||||||
id: person.id,
|
id: person.id,
|
||||||
name: person.name,
|
first_name: person.first_name,
|
||||||
age: person.age,
|
last_name: person.last_name,
|
||||||
phone_number: person.phone_number,
|
grade: person.grade,
|
||||||
|
parent_name: person.parent_name,
|
||||||
|
parent_phone_number: person.parent_phone_number,
|
||||||
checked_in: person.checked_in,
|
checked_in: person.checked_in,
|
||||||
inside: person.inside,
|
inside: person.inside,
|
||||||
under_ten,
|
visitor: person.visitor,
|
||||||
|
sleeping_spot: person.sleeping_spot,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -74,13 +83,19 @@ pub struct PersonActionResponse {
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
#[serde(crate = "rocket::serde")]
|
#[serde(crate = "rocket::serde")]
|
||||||
pub struct NewPersonRequest {
|
pub struct NewPersonRequest {
|
||||||
pub name: String,
|
pub first_name: String,
|
||||||
pub age: i32,
|
pub last_name: String,
|
||||||
pub phone_number: String,
|
pub grade: i32,
|
||||||
|
pub parent_name: String,
|
||||||
|
pub parent_phone_number: String,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub id: Option<i32>,
|
pub id: Option<i32>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub checked_in: Option<bool>,
|
pub checked_in: Option<bool>,
|
||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub inside: Option<bool>,
|
pub inside: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub visitor: Option<bool>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub sleeping_spot: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -45,13 +45,30 @@ async fn ensure_person_seed(pool: &PgPool) -> anyhow::Result<()> {
|
||||||
|
|
||||||
for person in persons {
|
for person in persons {
|
||||||
sqlx::query(
|
sqlx::query(
|
||||||
"INSERT INTO persons (name, age, phone_number, checked_in, inside) VALUES ($1, $2, $3, $4, $5)",
|
r#"
|
||||||
|
INSERT INTO persons (
|
||||||
|
first_name,
|
||||||
|
last_name,
|
||||||
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
|
checked_in,
|
||||||
|
inside,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot
|
||||||
|
)
|
||||||
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||||
|
"#,
|
||||||
)
|
)
|
||||||
.bind(&person.name)
|
.bind(&person.first_name)
|
||||||
.bind(person.age)
|
.bind(&person.last_name)
|
||||||
.bind(&person.phone_number)
|
.bind(person.grade)
|
||||||
|
.bind(&person.parent_name)
|
||||||
|
.bind(&person.parent_phone_number)
|
||||||
.bind(person.checked_in)
|
.bind(person.checked_in)
|
||||||
.bind(person.inside)
|
.bind(person.inside)
|
||||||
|
.bind(person.visitor)
|
||||||
|
.bind(person.sleeping_spot)
|
||||||
.execute(pool)
|
.execute(pool)
|
||||||
.await
|
.await
|
||||||
.context("Misslyckades att lägga till seed-person")?;
|
.context("Misslyckades att lägga till seed-person")?;
|
||||||
|
|
@ -61,20 +78,24 @@ async fn ensure_person_seed(pool: &PgPool) -> anyhow::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
struct PersonSeed {
|
struct PersonSeed {
|
||||||
name: String,
|
first_name: String,
|
||||||
age: i32,
|
last_name: String,
|
||||||
phone_number: String,
|
grade: i32,
|
||||||
|
parent_name: String,
|
||||||
|
parent_phone_number: String,
|
||||||
checked_in: bool,
|
checked_in: bool,
|
||||||
inside: bool,
|
inside: bool,
|
||||||
|
visitor: bool,
|
||||||
|
sleeping_spot: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_people() -> Vec<PersonSeed> {
|
fn generate_people() -> Vec<PersonSeed> {
|
||||||
let first_names = vec![
|
let first_names = [
|
||||||
"Alex", "Bianca", "Cecilia", "David", "Elias", "Fatima", "Gabriel", "Hanna", "Isak",
|
"Alex", "Bianca", "Cecilia", "David", "Elias", "Fatima", "Gabriel", "Hanna", "Isak",
|
||||||
"Johanna", "Karin", "Liam", "Maja", "Nils", "Olivia",
|
"Johanna", "Karin", "Liam", "Maja", "Nils", "Olivia",
|
||||||
];
|
];
|
||||||
|
|
||||||
let last_names = vec![
|
let last_names = [
|
||||||
"Andersson",
|
"Andersson",
|
||||||
"Berg",
|
"Berg",
|
||||||
"Carlsson",
|
"Carlsson",
|
||||||
|
|
@ -87,20 +108,52 @@ fn generate_people() -> Vec<PersonSeed> {
|
||||||
"Johansson",
|
"Johansson",
|
||||||
];
|
];
|
||||||
|
|
||||||
|
let guardian_first_names = [
|
||||||
|
"Anna",
|
||||||
|
"Bertil",
|
||||||
|
"Charlotte",
|
||||||
|
"Daniel",
|
||||||
|
"Emma",
|
||||||
|
"Fredrik",
|
||||||
|
"Greta",
|
||||||
|
"Henrik",
|
||||||
|
"Ingrid",
|
||||||
|
"Jakob",
|
||||||
|
"Klara",
|
||||||
|
"Lars",
|
||||||
|
"Maria",
|
||||||
|
"Niklas",
|
||||||
|
"Petra",
|
||||||
|
];
|
||||||
|
|
||||||
|
let guardian_last_names = [
|
||||||
|
"Lind", "Sandberg", "Forsberg", "Nyström", "Sjöberg", "Viklund", "Ågren", "Öberg",
|
||||||
|
"Boström", "Engman",
|
||||||
|
];
|
||||||
|
|
||||||
let mut people = Vec::with_capacity(first_names.len() * last_names.len());
|
let mut people = Vec::with_capacity(first_names.len() * last_names.len());
|
||||||
|
|
||||||
let mut idx: usize = 0;
|
let mut idx: usize = 0;
|
||||||
for first in &first_names {
|
for first in &first_names {
|
||||||
for last in &last_names {
|
for last in &last_names {
|
||||||
let name = format!("{} {}", first, last);
|
let grade = 1 + ((idx * 3) % 9) as i32; // Grades between 1 and 9
|
||||||
let age = 5 + ((idx * 11) % 60) as i32;
|
let parent_first = guardian_first_names[idx % guardian_first_names.len()];
|
||||||
let phone_number = format!("070{:03}{:04}", idx % 1_000, (idx * 37) % 10_000);
|
let parent_last = guardian_last_names[idx % guardian_last_names.len()];
|
||||||
|
let parent_name = format!("{} {}", parent_first, parent_last);
|
||||||
|
let parent_phone_number = format!("070{:03}{:04}", idx % 1_000, (idx * 37) % 10_000);
|
||||||
|
let visitor = idx % 7 == 0;
|
||||||
|
let sleeping_spot = !visitor && grade >= 3 && idx % 5 == 0;
|
||||||
|
|
||||||
people.push(PersonSeed {
|
people.push(PersonSeed {
|
||||||
name,
|
first_name: (*first).to_string(),
|
||||||
age,
|
last_name: (*last).to_string(),
|
||||||
phone_number,
|
grade,
|
||||||
|
parent_name,
|
||||||
|
parent_phone_number,
|
||||||
checked_in: false,
|
checked_in: false,
|
||||||
inside: false,
|
inside: false,
|
||||||
|
visitor,
|
||||||
|
sleeping_spot,
|
||||||
});
|
});
|
||||||
idx += 1;
|
idx += 1;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue