From c0c7b1a589b51b9fe27980ff7b5c80e56a77eb01 Mon Sep 17 00:00:00 2001 From: Daniel Friesel Date: Mon, 8 Apr 2019 21:20:04 +0200 Subject: Work-in-progress journey editor. Not ready for deployment. --- lib/Travelynx.pm | 130 ++++++++++++++++++++++++++++++++-- lib/Travelynx/Controller/Traveling.pm | 67 +++++++++++++++--- 2 files changed, 184 insertions(+), 13 deletions(-) (limited to 'lib') diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 7c1c1df..62d70c7 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -266,6 +266,37 @@ sub startup { ); } ); + $self->attr( + action_set_sched_time_query => sub { + my ($self) = @_; + + # TODO (re-)initialize all automatically added journeys with edited = 0 + # and use it as a bit field to precisely indicate which fields have + # been edited. -> ".. set edited = edited | 1", "... | 2" etc. + # The action_id check is redundant, but better safe than sorry + return $self->app->dbh->prepare( + qq{ + update user_actions + set sched_time = to_timestamp(?), edited = 1 + where id = ? and action_id = ? + } + ); + } + ); + $self->attr( + action_set_real_time_query => sub { + my ($self) = @_; + + # The action_id check is redundant, but better safe than sorry + return $self->app->dbh->prepare( + qq{ + update user_actions + set real_time = to_timestamp(?), edited = 1 + where id = ? and action_id = ? + } + ); + } + ); $self->attr( action_query => sub { my ($self) = @_; @@ -312,7 +343,7 @@ sub startup { stations.ds100, stations.name, train_type, train_line, train_no, train_id, extract(epoch from sched_time), extract(epoch from real_time), - route, messages + route, messages, edited from user_actions left outer join stations on station_id = stations.id where user_id = ? @@ -331,7 +362,7 @@ sub startup { stations.ds100, stations.name, train_type, train_line, train_no, train_id, extract(epoch from sched_time), extract(epoch from real_time), - route, messages + route, messages, edited from user_actions left outer join stations on station_id = stations.id where user_id = ? @@ -354,7 +385,7 @@ sub startup { stations.ds100, stations.name, train_type, train_line, train_no, train_id, extract(epoch from sched_time), extract(epoch from real_time), - route, messages + route, messages, edited from user_actions left outer join stations on station_id = stations.id where user_id = ? @@ -375,7 +406,7 @@ sub startup { stations.ds100, stations.name, train_type, train_line, train_no, train_id, extract(epoch from sched_time), extract(epoch from real_time), - route, messages + route, messages, edited from user_actions left outer join stations on station_id = stations.id where user_id = ? @@ -808,6 +839,77 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} } ); + $self->helper( + 'update_journey_part' => sub { + my ( $self, $checkin_id, $checkout_id, $key, $value ) = @_; + my ( $query, $id, $action_type ); + + if ( $key eq 'sched_departure' ) { + $query = $self->app->action_set_sched_time_query; + $id = $checkin_id; + $action_type = $self->app->action_type->{checkin}; + } + elsif ( $key eq 'rt_departure' ) { + $query = $self->app->action_set_real_time_query; + $id = $checkin_id; + $action_type = $self->app->action_type->{checkin}; + } + elsif ( $key eq 'sched_arrival' ) { + $query = $self->app->action_set_sched_time_query; + $id = $checkout_id; + $action_type = $self->app->action_type->{checkout}; + } + elsif ( $key eq 'rt_arrival' ) { + $query = $self->app->action_set_real_time_query; + $id = $checkout_id; + $action_type = $self->app->action_type->{checkout}; + } + else { + $self->app->log->error( + "update_journey_part(id = $id): Invalid key $key"); + return 'Internal Error'; + } + + my $success = $query->execute( $value, $id, $action_type ); + if ($success) { + if ( $query->rows == 1 ) { + return undef; + } + return 'UPDATE failed: did not match any journey part'; + } + my $err = $query->errstr; + $self->app->log->error( + "update_journey_part($id): UPDATE failed: $err"); + return 'UPDATE failed: ' . $err; + } + ); + + $self->helper( + 'journey_sanity_check' => sub { + my ( $self, $journey ) = @_; + + if ( $journey->{sched_duration} and $journey->{sched_duration} < 0 ) + { + return 'Die geplante Dauer dieser Zugfahrt ist negativ'; + } + if ( $journey->{rt_duration} and $journey->{rt_duration} < 0 ) { + return 'Die Dauer dieser Zugfahrt ist negativ'; + } + if ( $journey->{sched_duration} + and $journey->{sched_duration} > 60 * 60 * 24 ) + { + return 'Die Zugfahrt ist länger als 24 Stunden'; + } + if ( $journey->{rt_duration} + and $journey->{rt_duration} > 60 * 60 * 24 ) + { + return 'Die Zugfahrt ist länger als 24 Stunden'; + } + + return undef; + } + ); + $self->helper( 'get_station_id' => sub { my ( $self, %opt ) = @_; @@ -1161,7 +1263,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} $ds100, $name, $train_type, $train_line, $train_no, $train_id, $raw_sched_ts, $raw_real_ts, $raw_route, - $raw_messages + $raw_messages, $edited ) = @row; if ( $action == $match_actions[0] @@ -1185,6 +1287,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} ? [ split( qr{[|]}, $raw_route ) ] : undef, completed => 0, + edited => $edited // 0, } ); } @@ -1208,6 +1311,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} $ref->{no} //= $train_no; $ref->{messages} //= [ split( qr{[|]}, $raw_messages ) ]; $ref->{route} //= [ split( qr{[|]}, $raw_route ) ]; + $ref->{edited} += $edited; if ( $opt{verbose} ) { my @parsed_messages; @@ -1272,6 +1376,22 @@ qq{select * from pending_mails where email = ? and num_tries > 1;} } ); + $self->helper( + 'get_journey' => sub { + my ( $self, %opt ) = @_; + + my @journeys = $self->get_user_travels(%opt); + if ( @journeys == 0 + or not $journeys[0]{completed} + or $journeys[0]{ids}[1] != $opt{checkout_id} ) + { + return undef; + } + + return $journeys[0]; + } + ); + $self->helper( 'get_user_status' => sub { my ( $self, $uid ) = @_; diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm index 83036ba..ce7d1d4 100755 --- a/lib/Travelynx/Controller/Traveling.pm +++ b/lib/Travelynx/Controller/Traveling.pm @@ -2,6 +2,7 @@ package Travelynx::Controller::Traveling; use Mojo::Base 'Mojolicious::Controller'; use DateTime; +use DateTime::Format::Strptime; use Travel::Status::DE::IRIS::Stations; sub homepage { @@ -427,14 +428,12 @@ sub edit_journey { return; } - my @journeys = $self->get_user_travels( + my $journey = $self->get_journey( uid => $uid, - checkout_id => $checkout_id, + checkout_id => $checkout_id ); - if ( @journeys == 0 - or not $journeys[0]{completed} - or $journeys[0]{ids}[1] != $checkout_id ) - { + + if ( not $journey ) { $self->render( 'edit_journey', error => 'notfound', @@ -443,7 +442,59 @@ sub edit_journey { return; } - my $journey = $journeys[0]; + my $error = undef; + + if ( $self->param('action') and $self->param('action') eq 'cancel' ) { + $self->redirect_to("/journey/${uid}-${checkout_id}"); + return; + } + + if ( $self->param('action') and $self->param('action') eq 'save' ) { + my $parser = DateTime::Format::Strptime->new( + pattern => '%d.%m.%Y %H:%M', + locale => 'de_DE', + time_zone => 'Europe/Berlin' + ); + + $self->app->dbh->begin_work; + + for my $key (qw(sched_departure rt_departure sched_arrival rt_arrival)) + { + my $datetime = $parser->parse_datetime( $self->param($key) ); + if ( $datetime and $datetime->epoch ne $journey->{$key}->epoch ) { + $error = $self->update_journey_part( + $journey->{ids}[0], + $journey->{ids}[1], + $key, $datetime->epoch + ); + if ($error) { + last; + } + } + } + + if ($error) { + $self->app->dbh->rollback; + } + else { + $journey = $self->get_journey( + uid => $uid, + checkout_id => $checkout_id, + verbose => 1 + ); + $error = $self->journey_sanity_check($journey); + if ($error) { + $self->app->dbh->rollback; + } + else { + $self->invalidate_stats_cache( $journey->{checkout} ); + $self->app->dbh->commit; + $self->redirect_to("/journey/${uid}-${checkout_id}"); + return; + } + } + + } for my $key (qw(sched_departure rt_departure sched_arrival rt_arrival)) { if ( $journey->{$key} and $journey->{$key}->epoch ) { @@ -458,7 +509,7 @@ sub edit_journey { $self->render( 'edit_journey', - error => undef, + error => $error, journey => $journey ); } -- cgit v1.2.3