summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Friesel <derf@finalrewind.org>2019-04-13 10:43:05 +0200
committerDaniel Friesel <derf@finalrewind.org>2019-04-13 10:43:05 +0200
commit1ee185d26bbfb9c7ef37aa6405645c8049d56f53 (patch)
tree7eeb83f545f7452cdbfea2654f35ce2c872d5958
parent863a33b111506e66850ccf1dcfde9e42584f52ab (diff)
work-in-progress manual journey entry. incomplete and not enabled yet.
-rwxr-xr-xlib/Travelynx.pm88
-rwxr-xr-xlib/Travelynx/Controller/Traveling.pm74
-rw-r--r--templates/add_journey.html.ep8
-rw-r--r--templates/layouts/default.html.ep4
4 files changed, 168 insertions, 6 deletions
diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm
index 5812c54..1965da4 100755
--- a/lib/Travelynx.pm
+++ b/lib/Travelynx.pm
@@ -625,6 +625,91 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
}
);
+ # Returns (checkin id, checkout id, error)
+ # Must be called during a transaction.
+ # Must perform a rollback on error.
+ $self->helper(
+ 'add_journey' => sub {
+ my ( $self, %opt ) = @_;
+
+ my $user_status = $self->get_user_status;
+ if ( $user_status->{checked_in} or $user_status->{cancelled} ) {
+
+ # TODO: change database schema to one row per journey instead of two
+ return ( undef, undef,
+'Während einer Zugfahrt können momentan keine manuellen Einträge vorgenommen werden. Klingt komisch, ist aber so.'
+ );
+ }
+
+ my $uid = $self->current_user->{id};
+ my $dep_station = get_station( $opt{dep_station} );
+ my $arr_station = get_station( $opt{arr_station} );
+
+ if ( not $dep_station ) {
+ return ( undef, undef, 'Unbekannter Startbahnhof' );
+ }
+ if ( not $arr_station ) {
+ return ( undef, undef, 'Unbekannter Zielbahnhof' );
+ }
+
+ say $dep_station->[0];
+ say $dep_station->[1];
+ say $arr_station->[0];
+ say $arr_station->[1];
+
+ my $success = $self->app->action_query->execute(
+ $uid,
+ $self->app->action_type->{checkin},
+ $self->get_station_id(
+ ds100 => $dep_station->[0],
+ name => $dep_station->[1],
+ ),
+ DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
+ 0x0f,
+ $opt{train_type},
+ $opt{train_line},
+ $opt{train_no},
+ undef,
+ $opt{sched_departure}->epoch,
+ $opt{rt_departure} ? $opt{rt_departure}->epoch : undef,
+ undef, undef
+ );
+ if ( not $success ) {
+ my $err = $self->app->action_query->errstr;
+ $self->app->log->error(
+ "add_journey($uid, checkin): INSERT failed: $err");
+ return ( undef, undef, 'INSERT failed: ' . $err );
+ }
+ my $checkin_id = $self->app->action_query->last_insert_id;
+
+ $success = $self->app->action_query->execute(
+ $uid,
+ $self->app->action_type->{checkout},
+ $self->get_station_id(
+ ds100 => $arr_station->[0],
+ name => $arr_station->[1],
+ ),
+ DateTime->now( time_zone => 'Europe/Berlin' )->epoch,
+ 0x0f,
+ $opt{train_type},
+ $opt{train_line},
+ $opt{train_no},
+ undef,
+ $opt{sched_arrival}->epoch,
+ $opt{rt_arrival} ? $opt{rt_arrival}->epoch : undef,
+ undef, undef
+ );
+ if ( not $success ) {
+ my $err = $self->app->action_query->errstr;
+ $self->app->log->error(
+ "add_journey($uid, checkout): INSERT failed: $err");
+ return ( undef, undef, 'INSERT failed: ' . $err );
+ }
+ my $checkout_id = $self->app->action_query->last_insert_id;
+ return ( $checkin_id, $checkout_id, undef );
+ }
+ );
+
$self->helper(
'checkin' => sub {
my ( $self, $station, $train_id, $action_id ) = @_;
@@ -1218,7 +1303,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
}
elsif ( $opt{after} and $opt{before} ) {
- # Each journey consists of at least two database entries: one for
+ # Each journey consists of exactly two database entries: one for
# checkin, one for checkout. A simple query using e.g.
# after = YYYY-01-01T00:00:00 and before YYYY-02-01T00:00:00
# will miss journeys where checkin and checkout take place in
@@ -1602,6 +1687,7 @@ qq{select * from pending_mails where email = ? and num_tries > 1;}
$authed_r->get('/journey/add')->to('traveling#add_journey_form');
$authed_r->get('/journey/:id')->to('traveling#journey_details');
$authed_r->get('/s/*station')->to('traveling#station');
+ $authed_r->post('/journey/add')->to('traveling#add_journey_form');
$authed_r->post('/journey/edit')->to('traveling#edit_journey');
$authed_r->post('/change_password')->to('account#change_password');
$authed_r->post('/delete')->to('account#delete');
diff --git a/lib/Travelynx/Controller/Traveling.pm b/lib/Travelynx/Controller/Traveling.pm
index ce7d1d4..0ace304 100755
--- a/lib/Travelynx/Controller/Traveling.pm
+++ b/lib/Travelynx/Controller/Traveling.pm
@@ -8,7 +8,11 @@ use Travel::Status::DE::IRIS::Stations;
sub homepage {
my ($self) = @_;
if ( $self->is_user_authenticated ) {
- $self->render( 'landingpage', with_geolocation => 1 );
+ $self->render(
+ 'landingpage',
+ with_autocomplete => 1,
+ with_geolocation => 1
+ );
}
else {
$self->render( 'landingpage', intro => 1 );
@@ -216,8 +220,9 @@ sub station {
if ( $status->{errstr} ) {
$self->render(
'landingpage',
- with_geolocation => 1,
- error => $status->{errstr}
+ with_autocomplete => 1,
+ with_geolocation => 1,
+ error => $status->{errstr}
);
}
else {
@@ -517,7 +522,68 @@ sub edit_journey {
sub add_journey_form {
my ($self) = @_;
- $self->render( 'add_journey', error => undef );
+ 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'
+ );
+ my %opt;
+
+ my @parts = split( qr{\s+}, $self->param('train') );
+
+ if ( @parts == 2 ) {
+ @opt{ 'train_type', 'train_no' } = @parts;
+ }
+ elsif ( @parts == 3 ) {
+ @opt{ 'train_type', 'train_line', 'train_no' } = @parts;
+ }
+ else {
+ $self->render(
+ 'add_journey',
+ with_autocomplete => 1,
+ error =>
+'Zug muss als „Typ Nummer“ oder „Typ Linie Nummer“ eingegeben werden.'
+ );
+ return;
+ }
+
+ for my $key (qw(sched_departure rt_departure sched_arrival rt_arrival))
+ {
+ my $datetime = $parser->parse_datetime( $self->param($key) );
+ if ( not $datetime ) {
+ $self->render(
+ 'add_journey',
+ with_autocomplete => 1,
+ error => "${key}: Ungültiges Datums-/Zeitformat"
+ );
+ return;
+ }
+ $opt{$key} = $datetime;
+ }
+
+ for my $key (qw(dep_station arr_station)) {
+ $opt{$key} = $self->param($key);
+ }
+
+ $self->app->dbh->begin_work;
+
+ my ( $checkin_id, $checkout_id, $error ) = $self->add_journey(%opt);
+
+ $self->app->dbh->rollback;
+ $self->render(
+ 'add_journey',
+ with_autocomplete => 1,
+ error => $error
+ );
+ return;
+ }
+
+ $self->render(
+ 'add_journey',
+ with_autocomplete => 1,
+ error => undef
+ );
}
1;
diff --git a/templates/add_journey.html.ep b/templates/add_journey.html.ep
index 9ef00f5..e07f78f 100644
--- a/templates/add_journey.html.ep
+++ b/templates/add_journey.html.ep
@@ -30,6 +30,10 @@
</div>
<div class="row">
<div class="input-field col s12">
+ %= text_field 'dep_station', id => 'dep_station', class => 'autocomplete validate', required => undef
+ <label for="dep_station">Startbahnhof (Name oder DS100)</label>
+ </div>
+ <div class="input-field col s12">
%= text_field 'sched_departure', id => 'sched_departure', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
<label for="sched_departure">Geplante Abfahrt</label>
</div>
@@ -40,6 +44,10 @@
</div>
<div class="row">
<div class="input-field col s12">
+ %= text_field 'arr_station', id => 'arr_station', class => 'autocomplete validate', required => undef
+ <label for="arr_station">Zielbahnhof (Name oder DS100)</label>
+ </div>
+ <div class="input-field col s12">
%= text_field 'sched_arrival', id => 'sched_arrival', class => 'validate', required => undef, pattern => '[0-9][0-9]?[.][0-9][0-9]?[.][0-9][0-9][0-9][0-9] +[0-9][0-9]:[0-9][0-9]'
<label for="sched_arrival">Geplante Ankunft</label>
</div>
diff --git a/templates/layouts/default.html.ep b/templates/layouts/default.html.ep
index fa8dacf..b76f1ab 100644
--- a/templates/layouts/default.html.ep
+++ b/templates/layouts/default.html.ep
@@ -13,9 +13,11 @@
%= javascript "/static/${av}/js/materialize.min.js"
%= javascript "/static/${av}/js/travelynx-actions.min.js"
% if (stash('with_geolocation')) {
- %= javascript "/static/${av}/js/autocomplete.min.js"
%= javascript "/static/${av}/js/geolocation.min.js"
% }
+ % if (stash('with_autocomplete')) {
+ %= javascript "/static/${av}/js/autocomplete.min.js"
+ % }
</head>
<body>