EinsatzOnline/src/database/controller/events.rs

628 lines
23 KiB
Rust

use chrono::NaiveDateTime;
use diesel::{BoolExpressionMethods, ExpressionMethods, PgTextExpressionMethods, RunQueryDsl, sql_query};
use diesel::dsl::any;
use diesel::pg::types::sql_types::Uuid;
use rocket::State;
use crate::database::controller::connector::establish_connection;
use crate::database::controller::events::instances::instance_positions::RawPositionInstance;
use crate::database::controller::events::instances::instances::RawEventUnitInstance;
use crate::database::controller::events::templates::vehicle_positions::get_eu_vehicle_positions_for_template;
use crate::database::model::events::{Event, EventType, EventUnitInstancePosition, EventUnitInstanceVehiclePosition, EventUnitPosition, EventUnitTemplate, EventUnitVehiclePosition};
use crate::diesel::QueryDsl;
use crate::helper::settings::Settings;
use crate::schema::eu_position_instances::dsl::eu_position_instances;
use crate::schema::eu_positions_templates;
pub mod templates;
pub mod instances;
//TODO: migrate to multiple files to improve readability
//TODO: document this whole file...
pub fn add_event(settings: &State<Settings>, data: Event) -> Result<Event, diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(events).values(data).get_result(&connection) {
Ok(org) => Ok(org),
Err(e) => {
error!("Couldn't create event: {}", e);
Err(e)
}
}
}
/// Sets state for event from 0 or 2 to 4 and therefore locks the event.
/// Used in API endpoint for billing module
/// Returns an empty Ok result or an [diesel::result::Error].
pub fn close_event(settings: &State<Settings>, event_id: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::update(events.filter(entity_id.eq(event_id)).filter(state.eq(any(vec!(0, 2))))).set(state.eq(4)).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't close event: {}", e);
Err(e)
}
}
}
/// Sets state for event from 4 to 6
/// Used in API endpoint for billing module
/// Returns an empty Ok result or an [diesel::result::Error].
pub fn approve_event_times(settings: &State<Settings>, event_id: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::update(events.filter(entity_id.eq(event_id)).filter(state.eq(4))).set(state.eq(6)).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't approve event times: {}", e);
Err(e)
}
}
}
/// Sets state for event from 6 to 7
/// Used in API endpoint for billing module
/// Returns an empty Ok result or an [diesel::result::Error].
pub fn finish_personnel_billing(settings: &State<Settings>, event_id: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::update(events.filter(entity_id.eq(event_id)).filter(state.eq(6))).set(state.eq(7)).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't finish personnel billing: {}", e);
Err(e)
}
}
}
pub fn approve_stage(settings: &State<Settings>, event_id2: uuid::Uuid, stage: uuid::Uuid, caller: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::eu_instances::dsl::*;
let connection = establish_connection(settings);
match diesel::update(eu_instances).filter(event_id.eq(event_id2)).set((billing_state_id.eq(stage), billing_state_author.eq(caller))).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't approve stage: {}", e);
Err(e)
}
}
}
/// Sets state for event from 7 to 8
/// Used in API endpoint for billing module
/// Returns an empty Ok result or an [diesel::result::Error].
pub fn finish_billing(settings: &State<Settings>, event_id: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::update(events.filter(entity_id.eq(event_id)).filter(state.eq(7))).set(state.eq(8)).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't finish billing: {}", e);
Err(e)
}
}
}
pub fn change_event(settings: &State<Settings>, data: Event) -> Result<Event, diesel::result::Error> {
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match diesel::update(events.filter(entity_id.eq(data.entity_id))).set(data).get_result(&connection) {
Ok(org) => Ok(org),
Err(e) => {
error!("Couldn't update event: {}", e);
Err(e)
}
}
}
pub fn get_events(settings: &State<Settings>, startdate: NaiveDateTime, enddate: NaiveDateTime, limit: i64, offset: i64, groups: Option<Vec<uuid::Uuid>>, states: Option<Vec<i16>>) -> Result<Vec<Event>, diesel::result::Error>{
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
let mut query = events.order(start.asc()).filter(start.ge(startdate)).filter(end.le(enddate)).limit(limit).offset(offset).into_boxed();
if let Some(groups) = groups {
query = query.filter(related_group.eq(any(groups)));
};
if let Some(states) = states{
query = query.filter(state.eq(any(states)));
};
match query.get_results(&connection){
Ok(eventlist) => Ok(eventlist),
Err(e) => {
error!("Couldn't get events: {}", e);
Err(e)
}
}
}
pub fn get_event(settings: &State<Settings>, event_id: uuid::Uuid) -> Result<Event, diesel::result::Error>{
use crate::schema::events::dsl::*;
let connection = establish_connection(settings);
match events.filter(entity_id.eq(event_id)).get_result(&connection){
Ok(event) => Ok(event),
Err(e) => {
error!("Couldn't get event: {}", e);
Err(e)
}
}
}
pub fn get_event_count(settings: &State<Settings>, startdate: NaiveDateTime, enddate: NaiveDateTime, groups: Option<Vec<uuid::Uuid>>, states: Option<Vec<i16>>) -> Result<i64, diesel::result::Error>{
use crate::schema::events::dsl::*;
use diesel::dsl::count;
let connection = establish_connection(settings);
let mut query = events.select(count(entity_id)).filter(start.ge(startdate)).filter(end.le(enddate)).into_boxed();
if let Some(groups) = groups {
query = query.filter(related_group.eq(any(groups)));
};
if let Some(states) = states{
query = query.filter(state.eq(any(states)));
};
match query.get_result(&connection){
Ok(eventcount) => Ok(eventcount),
Err(e) => {
error!("Couldn't get event count: {}", e);
Err(e)
}
}
}
pub fn get_event_types(settings: &State<Settings>) -> Result<Vec<EventType>, diesel::result::Error>{
use crate::schema::event_types::dsl::*;
let connection = establish_connection(settings);
match event_types.load(&connection){
Ok(types) => Ok(types),
Err(e) => {
error!("Couldn't get event types: {}", e);
Err(e)
}
}
}
pub fn get_event_type(settings: &State<Settings>, type_id : uuid::Uuid) -> Result<EventType, diesel::result::Error>{
use crate::schema::event_types::dsl::event_types;
let connection = establish_connection(settings);
match event_types.filter(crate::schema::event_types::dsl::type_id.eq(type_id)).get_result(&connection){
Ok(etype) => Ok(etype),
Err(e) => {
error!("Couldn't get event type: {}", e);
Err(e)
}
}
}
pub fn add_event_unit_position(settings: &State<Settings>, eup: EventUnitPosition) -> Result<EventUnitPosition, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(eu_positions).values(eup).get_result(&connection){
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't create event unit position: {}", e);
Err(e)
}
}
}
pub fn set_event_unit_position(settings: &State<Settings>, eup: EventUnitPosition) -> Result<EventUnitPosition, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
match diesel::update(eu_positions.filter(entity_id.eq(eup.entity_id))).set(eup).get_result(&connection){
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't update event unit position: {}", e);
Err(e)
}
}
}
pub fn get_event_unit_positions(settings: &State<Settings>, limit: i64, offset: i64, q: Option<String>) -> Result<Vec<EventUnitPosition>, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
let mut query = eu_positions.order(name.asc()).limit(limit).offset(offset).into_boxed();
match q{
Some(q) => {
query = query.filter(name.ilike(format!("%{}%", q)).or(description.ilike(format!("%{}%", q))));
},
None => {}
}
match query.load(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit positions: {}", e);
Err(e)
}
}
}
pub fn get_event_unit_positions_count(settings: &State<Settings>,) -> Result<i64, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
use diesel::dsl::count;
let connection = establish_connection(settings);
match eu_positions.select(count(entity_id)).get_result(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit position count: {}", e);
Err(e)
}
}
}
pub fn add_event_unit_template(settings: &State<Settings>, eut: EventUnitTemplate) -> Result<EventUnitTemplate, diesel::result::Error>{
use crate::schema::eu_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(eu_templates).values(eut).get_result(&connection){
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't create event unit template: {}", e);
Err(e)
}
}
}
pub fn add_position_to_template(settings: &State<Settings>, data: RawEventUnitTemplatePosition) -> Result<(), diesel::result::Error> {
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(eu_positions_templates).values(data).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't add position to template: {}", e);
Err(e)
}
}
}
pub fn get_event_unit_templates(settings: &State<Settings>, limit: i64, offset: i64, q: Option<String>) -> Result<Vec<EventUnitTemplate>, diesel::result::Error>{
use crate::schema::eu_templates::dsl::*;
let connection = establish_connection(settings);
let mut query = eu_templates.order(name.asc()).limit(limit).offset(offset).into_boxed();
match q{
Some(q) => {
query = query.filter(name.ilike(format!("%{}%", q)));
},
None => {}
}
match query.load(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit templates: {}", e);
Err(e)
}
}
}
pub fn get_event_unit_templates_count(settings: &State<Settings>,) -> Result<i64, diesel::result::Error>{
use crate::schema::eu_templates::dsl::*;
use diesel::dsl::count;
let connection = establish_connection(settings);
match eu_templates.select(count(entity_id)).get_result(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit template count: {}", e);
Err(e)
}
}
}
#[derive(Queryable, Clone, Deserialize, Serialize, AsChangeset, Insertable, Identifiable)]
#[table_name = "eu_positions_templates"]
#[changeset_options(treat_none_as_null = "true")]
#[primary_key(position_template_id)]
pub struct RawEventUnitTemplatePosition{
pub(crate) position_entity_id: uuid::Uuid,
pub(crate) template_id: uuid::Uuid,
pub(crate) position_template_id: uuid::Uuid, //primary key
pub(crate) num: i32,
pub(crate) tag: Option<String>,
}
#[derive(Queryable, Clone, Deserialize, Serialize)]
pub struct EventUnitTemplatePosition{
pub(crate) position_template_id: uuid::Uuid,
pub(crate) tag: Option<String>,
pub(crate) num: i32,
pub(crate) template_id: uuid::Uuid,
pub(crate) position: EventUnitPosition,
}
pub fn get_event_unit_positions_for_template(settings: &State<Settings>, template: uuid::Uuid) -> Result<Vec<EventUnitTemplatePosition>, diesel::result::Error>{
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
let mut res: Vec<EventUnitTemplatePosition> = vec![];
let positions : Vec<RawEventUnitTemplatePosition> = match eu_positions_templates.filter(template_id.eq(template)).get_results(&connection){
Ok(pos) => pos,
Err(e) => {
error!("Couldn't get unit positions for template: {}", e);
return Err(e)
}
};
for position in positions{
res.push(EventUnitTemplatePosition{
position_template_id: position.position_template_id,
tag: position.tag,
num: position.num,
template_id: position.template_id,
position: get_event_unit_position(settings, position.position_entity_id)?
})
}
Ok(res)
}
fn get_event_unit_position(settings: &State<Settings>, position_id: uuid::Uuid) -> Result<EventUnitPosition, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
match eu_positions.filter(entity_id.eq(position_id)).get_result(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get unit position: {}", e);
Err(e)
}
}
}
pub fn remove_position_from_template(settings: &State<Settings>, template: uuid::Uuid, position: uuid::Uuid, position_template_id2: uuid::Uuid) -> Result<(), diesel::result::Error> {
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::delete(eu_positions_templates.filter(template_id.eq(template)).filter(position_entity_id.eq(position)).filter(position_template_id.eq(position_template_id2))).execute(&connection) {
Ok(_) => Ok(()),
Err(e) => {
error!("Couldn't delete position from template: {}", e);
Err(e)
}
}
}
pub fn update_positions_templates(settings: &State<Settings>, data: RawEventUnitTemplatePosition) -> Result<EventUnitTemplatePosition, diesel::result::Error> {
use crate::schema::eu_positions_templates::dsl::*;
let connection = establish_connection(settings);
let res: RawEventUnitTemplatePosition = match diesel::update(eu_positions_templates).filter(position_template_id.eq(data.position_template_id)).set(data).get_result(&connection) {
Ok(res) => res,
Err(e) => {
error!("Couldn't update position for template: {}", e);
return Err(e)
}
};
Ok(EventUnitTemplatePosition {
position_template_id: res.position_template_id,
tag: res.tag,
num: res.num,
template_id: res.template_id,
position: get_event_unit_position(settings, res.position_entity_id)?,
})
}
pub fn update_eu_template(settings: &State<Settings>, template: EventUnitTemplate) -> Result<EventUnitTemplate, diesel::result::Error> {
use crate::schema::eu_templates::dsl::*;
let connection = establish_connection(settings);
match diesel::update(eu_templates.filter(entity_id.eq(template.entity_id))).set(template).get_result(&connection) {
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't update event unit template: {}", e);
Err(e)
}
}
}
pub fn add_instance(settings: &State<Settings>, instance: RawEventUnitInstance) -> Result<RawEventUnitInstance, diesel::result::Error> {
use crate::schema::eu_instances::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(eu_instances).values(instance).get_result(&connection) {
Ok(res) => Ok(res),
Err(e) => {
error!("Couldn't create event unit instance: {}", e);
Err(e)
}
}
}
pub fn add_position_instances_for_instance(settings: &State<Settings>, instance_id2: uuid::Uuid, template_id2: uuid::Uuid) -> Result<(), diesel::result::Error>{
use crate::schema::eu_position_instances::dsl::*;
let positions = match get_event_unit_positions_for_template(settings, template_id2){
Ok(pos) => pos,
Err(e) => return Err(e)
};
let vehicle_positions = match get_eu_vehicle_positions_for_template(settings, template_id2) {
Ok(pos) => pos,
Err(e) => return Err(e)
};
let connection = establish_connection(settings);
for position in positions{
for _i in 1..position.num+1{
match diesel::insert_into(eu_position_instances).values((instance_id.eq(instance_id2), position_id.eq(position.position.entity_id))).execute(&connection){
Ok(_) => {debug!("Inserted new eu_position_instance with position_id {} and instance_id {}.", position.position.entity_id, instance_id2)},
Err(e) => return Err(e)
}
}
}
for position in vehicle_positions{
match diesel::insert_into(eu_position_instances).values((instance_id.eq(instance_id2), position_id.eq(position.entity_id))).execute(&connection){
Ok(_) => {},
Err(e) => return Err(e)
}
}
Ok(())
}
#[deprecated]
pub fn get_instance_positions_name_description(settings: &State<Settings>, instance_id2: uuid::Uuid) -> Result<Vec<EventUnitInstancePosition>, diesel::result::Error> {
let connection = establish_connection(settings);
let position_instances: Result<Vec<EventUnitInstancePosition>, diesel::result::Error> = sql_query(
"SELECT position_instance_id, instance_id, position_id, taken_by, name, description, requirements FROM eu_position_instances INNER JOIN eu_positions ON position_id = entity_id WHERE instance_id = $1;",
)
.bind::<Uuid, _>(instance_id2)
.get_results(&connection);
match position_instances {
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get instance positions: {}", e);
Err(e)
}
}
}
pub fn get_position_instances(settings: &State<Settings>, instance_id: uuid::Uuid) -> Result<Vec<RawPositionInstance>, diesel::result::Error> {
let connection = establish_connection(settings);
match eu_position_instances.filter(crate::schema::eu_position_instances::dsl::instance_id.eq(instance_id)).get_results(&connection) {
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get instance positions: {}", e);
Err(e)
}
}
}
pub fn get_position_instance(settings: &State<Settings>, position_instance_id: uuid::Uuid) -> Result<RawPositionInstance, diesel::result::Error> {
let connection = establish_connection(settings);
match eu_position_instances.filter(crate::schema::eu_position_instances::dsl::position_instance_id.eq(position_instance_id)).get_result(&connection) {
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get position instance: {}", e);
Err(e)
}
}
}
pub fn get_instance_vehicle_positions(settings: &State<Settings>, instance_id2: uuid::Uuid) -> Result<Vec<EventUnitInstanceVehiclePosition>, diesel::result::Error> {
let connection = establish_connection(settings);
let position_instances: Result<Vec<EventUnitInstanceVehiclePosition>, diesel::result::Error> = sql_query(
"SELECT position_instance_id, instance_id, position_id, taken_by, name, description, required_vehicle_category FROM eu_position_instances INNER JOIN eu_vehicle_positions ON position_id = entity_id WHERE instance_id = $1;",
)
.bind::<Uuid, _>(instance_id2)
.get_results(&connection);
match position_instances {
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get instance vehicle positions: {}", e);
Err(e)
}
}
}
pub fn add_vehicle_position(settings: &State<Settings>, position: EventUnitVehiclePosition) -> Result<EventUnitVehiclePosition, diesel::result::Error>{
use crate::schema::eu_vehicle_positions::dsl::*;
let connection = establish_connection(settings);
match diesel::insert_into(eu_vehicle_positions).values(&position).get_result(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't create vehicle position: {}", e);
Err(e)
}
}
}
pub fn change_position_instances(settings: &State<Settings>, position_instance_id2: uuid::Uuid, taken_by2: Option<uuid::Uuid>) -> Result<usize, diesel::result::Error>{
use crate::schema::eu_position_instances::dsl::*;
let connection = establish_connection(settings);
match diesel::update(eu_position_instances).filter(position_instance_id.eq(position_instance_id2)).set(taken_by.eq(taken_by2)).execute(&connection){
Ok(count) => Ok(count),
Err(e) => {
error!("Couldn't update position instances: {}", e);
Err(e)
}
}
}
pub fn get_eu_position(settings: &State<Settings>, position_id: uuid::Uuid) -> Result<EventUnitPosition, diesel::result::Error>{
use crate::schema::eu_positions::dsl::*;
let connection = establish_connection(settings);
match eu_positions.filter(entity_id.eq(position_id)).get_result(&connection){
Ok(pos) => Ok(pos),
Err(e) => {
error!("Couldn't get eu_position {}: {}", position_id, e);
Err(e)
}
}
}
pub fn get_events_for_member_in_future(settings: &State<Settings>, member_id: uuid::Uuid) -> Result<Vec<Event>, diesel::result::Error>{
let connection = establish_connection(settings);
let event_list: Result<Vec<Event>, diesel::result::Error> = sql_query(
"SELECT * FROM events WHERE entity_id IN (SELECT event_id FROM eu_instances WHERE instance_id IN (SELECT instance_id FROM eu_position_instances WHERE taken_by = $1)) AND start > now() ORDER BY start ASC;",
)
.bind::<Uuid, _>(member_id)
.get_results(&connection);
match event_list{
Ok(eventlist) => Ok(eventlist),
Err(e) => {
error!("Couldn't get events for member in future: {}", e);
Err(e)
}
}
}