forked from Ruderverein-Donau-Linz/rowt
		
	Merge branch 'main' of gitlab.com:PhilippHofer/rot
This commit is contained in:
		@@ -21,6 +21,7 @@ CREATE TABLE IF NOT EXISTS "trip_details" (
 | 
			
		||||
	"planned_starting_time" text NOT NULL,
 | 
			
		||||
	"max_people" INTEGER NOT NULL,
 | 
			
		||||
	"day" TEXT NOT NULL,
 | 
			
		||||
	"allow_guests" boolean NOT NULL default false,
 | 
			
		||||
	"notes" TEXT,
 | 
			
		||||
	"trip_type_id" INTEGER,
 | 
			
		||||
	FOREIGN KEY(trip_type_id) REFERENCES trip_type(id)
 | 
			
		||||
@@ -30,7 +31,6 @@ CREATE TABLE IF NOT EXISTS "planned_event" (
 | 
			
		||||
	"id" integer NOT NULL PRIMARY KEY AUTOINCREMENT,
 | 
			
		||||
	"name" text NOT NULL,
 | 
			
		||||
	"planned_amount_cox" INTEGER unsigned NOT NULL,
 | 
			
		||||
	"allow_guests" boolean NOT NULL default false,
 | 
			
		||||
	"trip_details_id" INTEGER NOT NULL,
 | 
			
		||||
	"created_at" text NOT NULL DEFAULT CURRENT_TIMESTAMP,
 | 
			
		||||
	FOREIGN KEY(trip_details_id) REFERENCES trip_details(id) ON DELETE CASCADE
 | 
			
		||||
 
 | 
			
		||||
@@ -30,4 +30,21 @@ impl Day {
 | 
			
		||||
            trips: Trip::get_for_day(db, day).await,
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    pub async fn new_guest(db: &SqlitePool, day: NaiveDate) -> Self {
 | 
			
		||||
        let mut day = Self::new(db, day).await;
 | 
			
		||||
 | 
			
		||||
        day.planned_events = day
 | 
			
		||||
            .planned_events
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .filter(|e| e.planned_event.allow_guests)
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        day.trips = day
 | 
			
		||||
            .trips
 | 
			
		||||
            .into_iter()
 | 
			
		||||
            .filter(|t| t.trip.allow_guests)
 | 
			
		||||
            .collect();
 | 
			
		||||
 | 
			
		||||
        day
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -9,19 +9,19 @@ pub struct PlannedEvent {
 | 
			
		||||
    pub id: i64,
 | 
			
		||||
    name: String,
 | 
			
		||||
    planned_amount_cox: i64,
 | 
			
		||||
    allow_guests: bool,
 | 
			
		||||
    trip_details_id: i64,
 | 
			
		||||
    planned_starting_time: String,
 | 
			
		||||
    max_people: i64,
 | 
			
		||||
    day: String,
 | 
			
		||||
    notes: Option<String>,
 | 
			
		||||
    pub allow_guests: bool,
 | 
			
		||||
    trip_type_id: Option<i64>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize)]
 | 
			
		||||
pub struct PlannedEventWithUserAndTriptype {
 | 
			
		||||
    #[serde(flatten)]
 | 
			
		||||
    planned_event: PlannedEvent,
 | 
			
		||||
    pub planned_event: PlannedEvent,
 | 
			
		||||
    trip_type: Option<TripType>,
 | 
			
		||||
    cox_needed: bool,
 | 
			
		||||
    cox: Vec<Registration>,
 | 
			
		||||
@@ -42,7 +42,7 @@ impl PlannedEvent {
 | 
			
		||||
            Self,
 | 
			
		||||
            "
 | 
			
		||||
SELECT
 | 
			
		||||
    planned_event.id, planned_event.name, planned_amount_cox, allow_guests, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id
 | 
			
		||||
    planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id
 | 
			
		||||
FROM planned_event 
 | 
			
		||||
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id
 | 
			
		||||
WHERE planned_event.id like ?
 | 
			
		||||
@@ -61,7 +61,7 @@ WHERE planned_event.id like ?
 | 
			
		||||
        let day = format!("{day}");
 | 
			
		||||
        let events = sqlx::query_as!(
 | 
			
		||||
            PlannedEvent,
 | 
			
		||||
            "SELECT planned_event.id, planned_event.name, planned_amount_cox, allow_guests, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id
 | 
			
		||||
            "SELECT planned_event.id, planned_event.name, planned_amount_cox, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id
 | 
			
		||||
FROM planned_event
 | 
			
		||||
INNER JOIN trip_details ON planned_event.trip_details_id = trip_details.id
 | 
			
		||||
WHERE day=?",
 | 
			
		||||
@@ -127,12 +127,13 @@ FROM user_trip WHERE trip_details_id = (SELECT trip_details_id FROM planned_even
 | 
			
		||||
        db: &SqlitePool,
 | 
			
		||||
        name: String,
 | 
			
		||||
        planned_amount_cox: i32,
 | 
			
		||||
        allow_guests: bool,
 | 
			
		||||
        trip_details: TripDetails,
 | 
			
		||||
    ) {
 | 
			
		||||
        sqlx::query!(
 | 
			
		||||
            "INSERT INTO planned_event(name, planned_amount_cox, allow_guests, trip_details_id) VALUES(?, ?, ?, ?)",
 | 
			
		||||
            name, planned_amount_cox, allow_guests, trip_details.id
 | 
			
		||||
            "INSERT INTO planned_event(name, planned_amount_cox, trip_details_id) VALUES(?, ?, ?)",
 | 
			
		||||
            name,
 | 
			
		||||
            planned_amount_cox,
 | 
			
		||||
            trip_details.id
 | 
			
		||||
        )
 | 
			
		||||
        .execute(db)
 | 
			
		||||
        .await
 | 
			
		||||
@@ -170,7 +171,7 @@ mod test {
 | 
			
		||||
 | 
			
		||||
        let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
 | 
			
		||||
 | 
			
		||||
        PlannedEvent::create(&pool, "new-event".into(), 2, false, trip_details).await;
 | 
			
		||||
        PlannedEvent::create(&pool, "new-event".into(), 2, trip_details).await;
 | 
			
		||||
 | 
			
		||||
        let res =
 | 
			
		||||
            PlannedEvent::get_for_day(&pool, NaiveDate::from_ymd_opt(1970, 1, 1).unwrap()).await;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,13 +19,14 @@ pub struct Trip {
 | 
			
		||||
    max_people: i64,
 | 
			
		||||
    day: String,
 | 
			
		||||
    notes: Option<String>,
 | 
			
		||||
    pub allow_guests: bool,
 | 
			
		||||
    trip_type_id: Option<i64>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[derive(Serialize)]
 | 
			
		||||
pub struct TripWithUserAndType {
 | 
			
		||||
    #[serde(flatten)]
 | 
			
		||||
    trip: Trip,
 | 
			
		||||
    pub trip: Trip,
 | 
			
		||||
    rower: Vec<Registration>,
 | 
			
		||||
    trip_type: Option<TripType>,
 | 
			
		||||
}
 | 
			
		||||
@@ -47,7 +48,7 @@ impl Trip {
 | 
			
		||||
        sqlx::query_as!(
 | 
			
		||||
            Self,
 | 
			
		||||
            "
 | 
			
		||||
SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id
 | 
			
		||||
SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id
 | 
			
		||||
FROM trip 
 | 
			
		||||
INNER JOIN trip_details ON trip.trip_details_id = trip_details.id
 | 
			
		||||
INNER JOIN user ON trip.cox_id = user.id
 | 
			
		||||
@@ -100,7 +101,7 @@ WHERE trip.id=?
 | 
			
		||||
        let trips = sqlx::query_as!(
 | 
			
		||||
            Trip,
 | 
			
		||||
            "
 | 
			
		||||
SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, trip_type_id
 | 
			
		||||
SELECT trip.id, cox_id, user.name as cox_name, trip_details_id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id
 | 
			
		||||
FROM trip 
 | 
			
		||||
INNER JOIN trip_details ON trip.trip_details_id = trip_details.id
 | 
			
		||||
INNER JOIN user ON trip.cox_id = user.id
 | 
			
		||||
 
 | 
			
		||||
@@ -8,6 +8,7 @@ pub struct TripDetails {
 | 
			
		||||
    max_people: i64,
 | 
			
		||||
    day: String,
 | 
			
		||||
    notes: Option<String>,
 | 
			
		||||
    pub allow_guests: bool,
 | 
			
		||||
    trip_type_id: Option<i64>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -16,7 +17,7 @@ impl TripDetails {
 | 
			
		||||
        sqlx::query_as!(
 | 
			
		||||
            TripDetails,
 | 
			
		||||
            "
 | 
			
		||||
SELECT id, planned_starting_time, max_people, day, notes, trip_type_id
 | 
			
		||||
SELECT id, planned_starting_time, max_people, day, notes, allow_guests, trip_type_id
 | 
			
		||||
FROM trip_details 
 | 
			
		||||
WHERE id like ?
 | 
			
		||||
        ",
 | 
			
		||||
@@ -34,14 +35,16 @@ WHERE id like ?
 | 
			
		||||
        max_people: i32,
 | 
			
		||||
        day: String,
 | 
			
		||||
        notes: Option<String>,
 | 
			
		||||
        allow_guests: bool,
 | 
			
		||||
        trip_type_id: Option<i64>,
 | 
			
		||||
    ) -> i64 {
 | 
			
		||||
        let query = sqlx::query!(
 | 
			
		||||
            "INSERT INTO trip_details(planned_starting_time, max_people, day, notes, trip_type_id) VALUES(?, ?, ?, ?, ?)" ,
 | 
			
		||||
            "INSERT INTO trip_details(planned_starting_time, max_people, day, notes, allow_guests, trip_type_id) VALUES(?, ?, ?, ?, ?, ?)" ,
 | 
			
		||||
            planned_starting_time,
 | 
			
		||||
            max_people,
 | 
			
		||||
            day,
 | 
			
		||||
            notes,
 | 
			
		||||
            allow_guests,
 | 
			
		||||
            trip_type_id
 | 
			
		||||
        )
 | 
			
		||||
        .execute(db)
 | 
			
		||||
@@ -97,11 +100,29 @@ mod test {
 | 
			
		||||
        let pool = testdb!();
 | 
			
		||||
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TripDetails::create(&pool, "10:00".into(), 2, "1970-01-01".into(), None, None).await,
 | 
			
		||||
            TripDetails::create(
 | 
			
		||||
                &pool,
 | 
			
		||||
                "10:00".into(),
 | 
			
		||||
                2,
 | 
			
		||||
                "1970-01-01".into(),
 | 
			
		||||
                None,
 | 
			
		||||
                false,
 | 
			
		||||
                None
 | 
			
		||||
            )
 | 
			
		||||
            .await,
 | 
			
		||||
            3,
 | 
			
		||||
        );
 | 
			
		||||
        assert_eq!(
 | 
			
		||||
            TripDetails::create(&pool, "10:00".into(), 2, "1970-01-01".into(), None, None).await,
 | 
			
		||||
            TripDetails::create(
 | 
			
		||||
                &pool,
 | 
			
		||||
                "10:00".into(),
 | 
			
		||||
                2,
 | 
			
		||||
                "1970-01-01".into(),
 | 
			
		||||
                None,
 | 
			
		||||
                false,
 | 
			
		||||
                None
 | 
			
		||||
            )
 | 
			
		||||
            .await,
 | 
			
		||||
            4,
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ pub struct User {
 | 
			
		||||
    pw: Option<String>,
 | 
			
		||||
    pub is_cox: bool,
 | 
			
		||||
    pub is_admin: bool,
 | 
			
		||||
    is_guest: bool,
 | 
			
		||||
    pub is_guest: bool,
 | 
			
		||||
    #[serde(default = "bool::default")]
 | 
			
		||||
    deleted: bool,
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,10 @@ impl UserTrip {
 | 
			
		||||
            return Err(UserTripError::EventAlreadyFull);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if user.is_guest && !trip_details.allow_guests {
 | 
			
		||||
            return Err(UserTripError::GuestNotAllowedForThisEvent);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //check if cox if own event
 | 
			
		||||
        let is_cox = sqlx::query!(
 | 
			
		||||
            "SELECT count(*) as amount
 | 
			
		||||
@@ -80,6 +84,7 @@ pub enum UserTripError {
 | 
			
		||||
    AlreadyRegisteredAsCox,
 | 
			
		||||
    EventAlreadyFull,
 | 
			
		||||
    CantRegisterAtOwnEvent,
 | 
			
		||||
    GuestNotAllowedForThisEvent,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
@@ -180,4 +185,19 @@ mod test {
 | 
			
		||||
 | 
			
		||||
        assert_eq!(result, UserTripError::AlreadyRegisteredAsCox);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[sqlx::test]
 | 
			
		||||
    fn test_fail_create_guest() {
 | 
			
		||||
        let pool = testdb!();
 | 
			
		||||
 | 
			
		||||
        let user = User::find_by_name(&pool, "guest".into()).await.unwrap();
 | 
			
		||||
 | 
			
		||||
        let trip_details = TripDetails::find_by_id(&pool, 1).await.unwrap();
 | 
			
		||||
 | 
			
		||||
        let result = UserTrip::create(&pool, &user, &trip_details)
 | 
			
		||||
            .await
 | 
			
		||||
            .expect_err("Not allowed for guests");
 | 
			
		||||
 | 
			
		||||
        assert_eq!(result, UserTripError::GuestNotAllowedForThisEvent);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ async fn create(
 | 
			
		||||
        data.max_people,
 | 
			
		||||
        data.day.clone(),
 | 
			
		||||
        data.notes.clone(),
 | 
			
		||||
        data.allow_guests,
 | 
			
		||||
        data.trip_type,
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
@@ -43,14 +44,7 @@ async fn create(
 | 
			
		||||
                                                                                    //the object
 | 
			
		||||
 | 
			
		||||
    //TODO: fix clone()
 | 
			
		||||
    PlannedEvent::create(
 | 
			
		||||
        db,
 | 
			
		||||
        data.name.clone(),
 | 
			
		||||
        data.planned_amount_cox,
 | 
			
		||||
        data.allow_guests,
 | 
			
		||||
        trip_details,
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
    PlannedEvent::create(db, data.name.clone(), data.planned_amount_cox, trip_details).await;
 | 
			
		||||
 | 
			
		||||
    Flash::success(Redirect::to("/"), "Successfully planned the event")
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -22,6 +22,7 @@ struct AddTripForm {
 | 
			
		||||
    max_people: i32,
 | 
			
		||||
    notes: Option<String>,
 | 
			
		||||
    trip_type: Option<i64>,
 | 
			
		||||
    allow_guests: bool,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#[post("/trip", data = "<data>")]
 | 
			
		||||
@@ -33,6 +34,7 @@ async fn create(db: &State<SqlitePool>, data: Form<AddTripForm>, cox: CoxUser) -
 | 
			
		||||
        data.max_people,
 | 
			
		||||
        data.day.clone(),
 | 
			
		||||
        data.notes.clone(),
 | 
			
		||||
        data.allow_guests,
 | 
			
		||||
        data.trip_type,
 | 
			
		||||
    )
 | 
			
		||||
    .await;
 | 
			
		||||
 
 | 
			
		||||
@@ -37,6 +37,7 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_
 | 
			
		||||
            .num_days()
 | 
			
		||||
            + 1;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if user.is_cox || user.is_admin {
 | 
			
		||||
        let triptypes = TripType::all(db).await;
 | 
			
		||||
        context.insert("trip_types", &triptypes);
 | 
			
		||||
@@ -44,7 +45,12 @@ async fn index(db: &State<SqlitePool>, user: User, flash: Option<FlashMessage<'_
 | 
			
		||||
 | 
			
		||||
    for i in 0..show_next_n_days {
 | 
			
		||||
        let date = (Local::now() + Duration::days(i)).date_naive();
 | 
			
		||||
        days.push(Day::new(db, date).await);
 | 
			
		||||
 | 
			
		||||
        if user.is_guest {
 | 
			
		||||
            days.push(Day::new_guest(db, date).await);
 | 
			
		||||
        } else {
 | 
			
		||||
            days.push(Day::new(db, date).await);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if let Some(msg) = flash {
 | 
			
		||||
@@ -86,6 +92,10 @@ async fn join(db: &State<SqlitePool>, trip_details_id: i64, user: User) -> Flash
 | 
			
		||||
            Redirect::to("/"),
 | 
			
		||||
            "Du kannst bei einer selbst ausgeschriebenen Fahrt nicht mitrudern ;)",
 | 
			
		||||
        ),
 | 
			
		||||
        Err(UserTripError::GuestNotAllowedForThisEvent) => Flash::error(
 | 
			
		||||
            Redirect::to("/"),
 | 
			
		||||
            "Bei dieser Ausfahrt können leider keine Gäste mitfahren.",
 | 
			
		||||
        ),
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -7,8 +7,8 @@
 | 
			
		||||
    {{ macros::input(label='Startzeit', name='planned_starting_time', type='time', required=true) }}
 | 
			
		||||
    {{ macros::input(label='Anzahl Steuerleute', name='planned_amount_cox', type='number', required=true, min='0') }}
 | 
			
		||||
    {{ macros::input(label='Anzahl Ruderer (ohne Steuerperson)', name='max_people', type='number', required=true, min='0') }}
 | 
			
		||||
    {{ macros::checkbox(label='Gäste erlauben', name='max_allow_guestspeople') }}
 | 
			
		||||
    {{ macros::checkbox(label='Gäste erlauben', name='allow_guests') }}
 | 
			
		||||
    {{ macros::input(label='Anmerkungen', name='notes', type='input') }}
 | 
			
		||||
    <input value="Erstellen" class="w-full btn btn-primary" type="submit" />
 | 
			
		||||
  </form>
 | 
			
		||||
</div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,8 @@
 | 
			
		||||
        <input class="day-js" type="hidden" name="day" value="" />
 | 
			
		||||
        {{ macros::input(label='Startzeit (zB "10:00")', name='planned_starting_time', type='time', required=true) }}
 | 
			
		||||
        {{ macros::input(label='Anzahl Ruderer (ohne Steuerperson)', name='max_people', type='number', required=true, min='0') }}
 | 
			
		||||
    	{{ macros::checkbox(label='Gäste erlauben', name='allow_guests') }}
 | 
			
		||||
        {{ macros::input(label='Anmerkungen', name='notes', type='input') }}
 | 
			
		||||
        <input value="Erstellen" class="w-full btn btn-primary" type="submit" />
 | 
			
		||||
    </form>
 | 
			
		||||
</div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user