Compare commits
5 Commits
4f9778eccf
...
80ac131fb2
Author | SHA1 | Date | |
---|---|---|---|
80ac131fb2 | |||
8e65a6540d | |||
d7e5731753 | |||
1a4d5ac569 | |||
668fc5e295 |
@ -213,3 +213,9 @@ CREATE TABLE IF NOT EXISTS "trailer_reservation" (
|
|||||||
"created_at" datetime not null default CURRENT_TIMESTAMP
|
"created_at" datetime not null default CURRENT_TIMESTAMP
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE IF NOT EXISTS "distance" (
|
||||||
|
"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||||
|
"destination" text NOT NULL,
|
||||||
|
"distance_in_km" integer NOT NULL
|
||||||
|
);
|
||||||
|
|
||||||
|
@ -67,3 +67,5 @@ INSERT INTO "boat_damage" (boat_id, desc, user_id_created, created_at, lock_boat
|
|||||||
INSERT INTO "notification" (user_id, message, category) VALUES (1, 'This is a test notification', 'test-cat');
|
INSERT INTO "notification" (user_id, message, category) VALUES (1, 'This is a test notification', 'test-cat');
|
||||||
INSERT INTO "trailer" (name) VALUES('Großer Hänger');
|
INSERT INTO "trailer" (name) VALUES('Großer Hänger');
|
||||||
INSERT INTO "trailer" (name) VALUES('Kleiner Hänger');
|
INSERT INTO "trailer" (name) VALUES('Kleiner Hänger');
|
||||||
|
insert into distance(destination, distance_in_km) values('Ottensheim', 25);
|
||||||
|
|
||||||
|
33
src/model/distance.rs
Normal file
33
src/model/distance.rs
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
use serde::Serialize;
|
||||||
|
use sqlx::{FromRow, SqlitePool};
|
||||||
|
|
||||||
|
#[derive(FromRow, Serialize, Clone, Debug)]
|
||||||
|
pub struct Distance {
|
||||||
|
pub id: i64,
|
||||||
|
pub destination: String,
|
||||||
|
pub distance_in_km: i64,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Distance {
|
||||||
|
/// Return all default `distance`s, ordered by usage in logbook entries
|
||||||
|
pub async fn all(db: &SqlitePool) -> Vec<Self> {
|
||||||
|
sqlx::query_as!(
|
||||||
|
Self,
|
||||||
|
"SELECT
|
||||||
|
d.id,
|
||||||
|
d.destination,
|
||||||
|
d.distance_in_km
|
||||||
|
FROM
|
||||||
|
distance d
|
||||||
|
LEFT JOIN
|
||||||
|
logbook l ON d.destination = l.destination AND d.distance_in_km = l.distance_in_km
|
||||||
|
GROUP BY
|
||||||
|
d.id, d.destination, d.distance_in_km
|
||||||
|
ORDER BY
|
||||||
|
COUNT(l.id) DESC, d.destination ASC;"
|
||||||
|
)
|
||||||
|
.fetch_all(db)
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
}
|
@ -496,25 +496,6 @@ ORDER BY departure DESC
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn distances(db: &SqlitePool) -> Vec<(String, i64)> {
|
|
||||||
let result = sqlx::query!("SELECT destination, distance_in_km FROM logbook WHERE id IN (SELECT MIN(id) FROM logbook GROUP BY destination) AND destination IS NOT NULL AND distance_in_km IS NOT NULL;")
|
|
||||||
.fetch_all(db)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
result
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(|r| {
|
|
||||||
if let (Some(destination), Some(distance_in_km)) = (r.destination, r.distance_in_km)
|
|
||||||
{
|
|
||||||
Some((destination, distance_in_km))
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn remove_rowers(&self, db: &mut Transaction<'_, Sqlite>) {
|
async fn remove_rowers(&self, db: &mut Transaction<'_, Sqlite>) {
|
||||||
sqlx::query!("DELETE FROM rower WHERE logbook_id=?", self.id)
|
sqlx::query!("DELETE FROM rower WHERE logbook_id=?", self.id)
|
||||||
.execute(db.deref_mut())
|
.execute(db.deref_mut())
|
||||||
@ -1071,21 +1052,6 @@ mod test {
|
|||||||
assert_eq!(res, Err(LogbookCreateError::TooManyRowers(1, 2)));
|
assert_eq!(res, Err(LogbookCreateError::TooManyRowers(1, 2)));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[sqlx::test]
|
|
||||||
fn test_distances() {
|
|
||||||
let pool = testdb!();
|
|
||||||
|
|
||||||
let res = Logbook::distances(&pool).await;
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
res,
|
|
||||||
vec![
|
|
||||||
("Ottensheim".into(), 25 as i64),
|
|
||||||
("Ottensheim + Regattastrecke".into(), 29 as i64),
|
|
||||||
]
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[sqlx::test]
|
#[sqlx::test]
|
||||||
fn test_succ_home() {
|
fn test_succ_home() {
|
||||||
let pool = testdb!();
|
let pool = testdb!();
|
||||||
|
@ -14,6 +14,7 @@ pub mod boat;
|
|||||||
pub mod boatdamage;
|
pub mod boatdamage;
|
||||||
pub mod boathouse;
|
pub mod boathouse;
|
||||||
pub mod boatreservation;
|
pub mod boatreservation;
|
||||||
|
pub mod distance;
|
||||||
pub mod event;
|
pub mod event;
|
||||||
pub mod family;
|
pub mod family;
|
||||||
pub mod location;
|
pub mod location;
|
||||||
|
@ -18,6 +18,7 @@ use tera::Context;
|
|||||||
use crate::model::{
|
use crate::model::{
|
||||||
boat::Boat,
|
boat::Boat,
|
||||||
boatreservation::BoatReservation,
|
boatreservation::BoatReservation,
|
||||||
|
distance::Distance,
|
||||||
log::Log,
|
log::Log,
|
||||||
logbook::{
|
logbook::{
|
||||||
LogToAdd, LogToFinalize, LogToUpdate, Logbook, LogbookAdminUpdateError, LogbookCreateError,
|
LogToAdd, LogToFinalize, LogToUpdate, Logbook, LogbookAdminUpdateError, LogbookCreateError,
|
||||||
@ -75,7 +76,7 @@ async fn index(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let logtypes = LogType::all(db).await;
|
let logtypes = LogType::all(db).await;
|
||||||
let distances = Logbook::distances(db).await;
|
let distances = Distance::all(db).await;
|
||||||
|
|
||||||
let on_water = Logbook::on_water(db).await;
|
let on_water = Logbook::on_water(db).await;
|
||||||
|
|
||||||
@ -180,7 +181,7 @@ async fn kiosk(
|
|||||||
});
|
});
|
||||||
|
|
||||||
let logtypes = LogType::all(db).await;
|
let logtypes = LogType::all(db).await;
|
||||||
let distances = Logbook::distances(db).await;
|
let distances = Distance::all(db).await;
|
||||||
|
|
||||||
let on_water = Logbook::on_water(db).await;
|
let on_water = Logbook::on_water(db).await;
|
||||||
|
|
||||||
|
@ -53,9 +53,10 @@
|
|||||||
id="destination"
|
id="destination"
|
||||||
name="destination"
|
name="destination"
|
||||||
value=""
|
value=""
|
||||||
data-relation="distance_in_km" />
|
data-relation="distance_in_km"
|
||||||
|
autocomplete="off" />
|
||||||
<datalist id="destinations">
|
<datalist id="destinations">
|
||||||
{% for distance in distances %}<option value="{{ distance.0 }}" distance="{{ distance.1 }}" />{% endfor %}
|
{% for distance in distances %}<option value="{{ distance.destination }}" distance="{{ distance.distance_in_km}}" />{% endfor %}
|
||||||
</datalist>
|
</datalist>
|
||||||
</div>
|
</div>
|
||||||
<div class="relative col-span-2">
|
<div class="relative col-span-2">
|
||||||
|
Loading…
Reference in New Issue
Block a user