diff options
| -rwxr-xr-x | lib/Travelynx.pm | 1 | ||||
| -rw-r--r-- | lib/Travelynx/Controller/Passengerrights.pm | 184 | ||||
| -rw-r--r-- | templates/history.html.ep | 36 | ||||
| -rw-r--r-- | templates/passengerrights.html.ep | 69 | 
4 files changed, 264 insertions, 26 deletions
| diff --git a/lib/Travelynx.pm b/lib/Travelynx.pm index 44273e5..7d3548e 100755 --- a/lib/Travelynx.pm +++ b/lib/Travelynx.pm @@ -2890,6 +2890,7 @@ sub startup {  	$authed_r->get('/account/insight')->to('account#insight');  	$authed_r->get('/ajax/status_card.html')->to('traveling#status_card');  	$authed_r->get('/cancelled')->to('traveling#cancelled'); +	$authed_r->get('/fgr')->to('passengerrights#list_candidates');  	$authed_r->get('/account/password')->to('account#password_form');  	$authed_r->get('/account/mail')->to('account#change_mail');  	$authed_r->get('/export.json')->to('account#json_export'); diff --git a/lib/Travelynx/Controller/Passengerrights.pm b/lib/Travelynx/Controller/Passengerrights.pm index aab8d76..1188e19 100644 --- a/lib/Travelynx/Controller/Passengerrights.pm +++ b/lib/Travelynx/Controller/Passengerrights.pm @@ -4,6 +4,82 @@ use Mojo::Base 'Mojolicious::Controller';  use DateTime;  use CAM::PDF; +sub mark_if_missed_connection { +	my ( $self, $journey, $next_journey ) = @_; + +	my $possible_delay +	  = (   $next_journey->{rt_departure}->epoch +		  - $journey->{sched_arrival}->epoch ) / 60; +	my $wait_time +	  = ( $next_journey->{rt_departure}->epoch - $journey->{rt_arrival}->epoch ) +	  / 60; +	if ( +		$wait_time < 120 +		and ( $possible_delay >= 120 +			or ( $journey->{delay} < 60 and $possible_delay >= 60 ) ) +	  ) +	{ +		$journey->{connection_missed} = 1; +		$journey->{connection}        = $next_journey; +		$journey->{possible_delay}    = $possible_delay; +		$journey->{wait_time}         = $wait_time; +		return 1; +	} +	return 0; +} + +sub list_candidates { +	my ($self) = @_; + +	my $now         = DateTime->now( time_zone => 'Europe/Berlin' ); +	my $range_start = $now->clone->subtract( months => 12 ); + +	my @journeys = $self->get_user_travels( +		after  => $range_start, +		before => $now +	); +	@journeys = grep { $_->{sched_arrival}->epoch and $_->{rt_arrival}->epoch } +	  @journeys; + +	for my $i ( 0 .. $#journeys ) { +		my $journey = $journeys[$i]; + +		$journey->{delay} +		  = ( $journey->{rt_arrival}->epoch - $journey->{sched_arrival}->epoch ) +		  / 60; + +		if ( $journey->{delay} < 3 or $journey->{delay} >= 120 ) { +			next; +		} +		if ( $i > 0 ) { +			$self->mark_if_missed_connection( $journey, $journeys[ $i - 1 ] ); +		} +	} + +	@journeys = grep { $_->{delay} >= 60 or $_->{connection_missed} } @journeys; + +	push( +		@journeys, +		map { $_->{cancelled} = 1; $_ } $self->get_user_travels( +			after     => $range_start, +			before    => $now, +			cancelled => 1 +		) +	); + +	@journeys +	  = sort { $b->{sched_departure}->epoch <=> $a->{sched_departure}->epoch } +	  @journeys; + +	$self->respond_to( +		json => { json => [@journeys] }, +		any  => { +			template => 'passengerrights', +			journeys => [@journeys] +		} +	); +} +  sub generate {  	my ($self) = @_;  	my $journey_id = $self->param('id'); @@ -34,44 +110,128 @@ sub generate {  		return;  	} +	$journey->{delay} +	  = ( $journey->{rt_arrival}->epoch - $journey->{sched_arrival}->epoch ) +	  / 60; + +	if ( $journey->{delay} < 120 ) { +		my @connections = $self->get_user_travels( +			uid    => $uid, +			after  => $journey->{rt_arrival}, +			before => $journey->{rt_arrival}->clone->add( hours => 2 ) +		); +		if (@connections) { +			$self->mark_if_missed_connection( $journey, $connections[-1] ); +		} +	} +  	my $pdf = CAM::PDF->new('public/static/pdf/fahrgastrechteformular.pdf'); +	# from station  	$pdf->fillFormFields( 'S1F4', $journey->{from_name} ); -	$pdf->fillFormFields( 'S1F7', $journey->{to_name} ); + +	if ( $journey->{connection} ) { + +		# to station +		$pdf->fillFormFields( 'S1F7', $journey->{connection}{to_name} ); + +		# missed connection in: +		$pdf->fillFormFields( 'S1F22', $journey->{to_name} ); + +		# last change in: +		$pdf->fillFormFields( 'S1F24', $journey->{to_name} ); +	} +	else { +		# to station +		$pdf->fillFormFields( 'S1F7', $journey->{to_name} ); +	} +  	if ( not $journey->{cancelled} ) { -		$pdf->fillFormFields( 'S1F13', $journey->{type} ); -		$pdf->fillFormFields( 'S1F14', $journey->{no} ); + +		# arived with: TRAIN NO +		if ( $journey->{connection} ) { +			$pdf->fillFormFields( 'S1F13', $journey->{connection}{type} ); +			$pdf->fillFormFields( 'S1F14', $journey->{connection}{no} ); +		} +		else { +			$pdf->fillFormFields( 'S1F13', $journey->{type} ); +			$pdf->fillFormFields( 'S1F14', $journey->{no} ); +		}  	} + +	# first delayed train: TRAIN NO  	$pdf->fillFormFields( 'S1F17', $journey->{type} );  	$pdf->fillFormFields( 'S1F18', $journey->{no} ); +  	if ( $journey->{sched_departure}->epoch ) { + +		# journey YYMMDD  		$pdf->fillFormFields( 'S1F1',  			$journey->{sched_departure}->strftime('%d') );  		$pdf->fillFormFields( 'S1F2',  			$journey->{sched_departure}->strftime('%m') );  		$pdf->fillFormFields( 'S1F3',  			$journey->{sched_departure}->strftime('%y') ); + +		# sched departure HHMM  		$pdf->fillFormFields( 'S1F5',  			$journey->{sched_departure}->strftime('%H') );  		$pdf->fillFormFields( 'S1F6',  			$journey->{sched_departure}->strftime('%M') ); + +		# first delayed train: sched departure HHMM  		$pdf->fillFormFields( 'S1F19',  			$journey->{sched_departure}->strftime('%H') );  		$pdf->fillFormFields( 'S1F20',  			$journey->{sched_departure}->strftime('%M') );  	}  	if ( $journey->{sched_arrival}->epoch ) { -		$pdf->fillFormFields( 'S1F8', -			$journey->{sched_arrival}->strftime('%H') ); -		$pdf->fillFormFields( 'S1F9', -			$journey->{sched_arrival}->strftime('%M') ); + +		# sched arrival HHMM +		if ( $journey->{connection} ) { + +			# TODO (needs plan data for non-journey trains) +		} +		else { +			$pdf->fillFormFields( 'S1F8', +				$journey->{sched_arrival}->strftime('%H') ); +			$pdf->fillFormFields( 'S1F9', +				$journey->{sched_arrival}->strftime('%M') ); +		}  	}  	if ( $journey->{rt_arrival}->epoch and not $journey->{cancelled} ) { -		$pdf->fillFormFields( 'S1F10', $journey->{rt_arrival}->strftime('%d') ); -		$pdf->fillFormFields( 'S1F11', $journey->{rt_arrival}->strftime('%m') ); -		$pdf->fillFormFields( 'S1F12', $journey->{rt_arrival}->strftime('%y') ); -		$pdf->fillFormFields( 'S1F15', $journey->{rt_arrival}->strftime('%H') ); -		$pdf->fillFormFields( 'S1F16', $journey->{rt_arrival}->strftime('%M') ); + +		if ( $journey->{connection} ) { + +			# arrival YYMMDD +			$pdf->fillFormFields( 'S1F10', +				$journey->{connection}{rt_arrival}->strftime('%d') ); +			$pdf->fillFormFields( 'S1F11', +				$journey->{connection}{rt_arrival}->strftime('%m') ); +			$pdf->fillFormFields( 'S1F12', +				$journey->{connection}{rt_arrival}->strftime('%y') ); + +			# arrival HHMM +			$pdf->fillFormFields( 'S1F15', +				$journey->{connection}{rt_arrival}->strftime('%H') ); +			$pdf->fillFormFields( 'S1F16', +				$journey->{connection}{rt_arrival}->strftime('%M') ); +		} +		else { +			# arrival YYMMDD +			$pdf->fillFormFields( 'S1F10', +				$journey->{rt_arrival}->strftime('%d') ); +			$pdf->fillFormFields( 'S1F11', +				$journey->{rt_arrival}->strftime('%m') ); +			$pdf->fillFormFields( 'S1F12', +				$journey->{rt_arrival}->strftime('%y') ); + +			# arrival HHMM +			$pdf->fillFormFields( 'S1F15', +				$journey->{rt_arrival}->strftime('%H') ); +			$pdf->fillFormFields( 'S1F16', +				$journey->{rt_arrival}->strftime('%M') ); +		}  	}  	$self->res->headers->content_type('application/pdf'); diff --git a/templates/history.html.ep b/templates/history.html.ep index a2f607a..607a356 100644 --- a/templates/history.html.ep +++ b/templates/history.html.ep @@ -7,20 +7,6 @@  	</div>  </div> -<div class="row"> -	<div class="col s12 m12 l3 center-align"> -		<a href="/cancelled" class="waves-effect waves-light btn"><i class="material-icons left">cancel</i> Zugausfälle</a> -	</div> -	<div class="col s12 m12 l1"> </div> -	<div class="col s12 m12 l4 center-align"> -		<a href="/journey/add" class="waves-effect waves-light btn"><i class="material-icons left">add</i> Neue Fahrt</a> -	</div> -	<div class="col s12 m12 l1"> </div> -	<div class="col s12 m12 l3 center-align"> -		<a href="/history.json" class="waves-effect waves-light btn"><i class="material-icons left">cloud</i> JSON-Export</a> -	</div> -</div> -  <h2>Nach Jahr</h2>  %= include '_history_years', current => '';  % if(0) { @@ -41,6 +27,28 @@  	</div>  % } +<h2>Ausfälle und Verspätungen</h2> +<div class="row"> +	<div class="col s12 m12 l5 center-align"> +		<a href="/cancelled" class="waves-effect waves-light btn"><i class="material-icons left">cancel</i> Zugausfälle</a> +	</div> +	<div class="col s12 m12 l2"> </div> +	<div class="col s12 m12 l5 center-align"> +		<a href="/fgr" class="waves-effect waves-light btn"><i class="material-icons left">feedback</i> Fahrgastrechte</a> +	</div> +</div> + +<h2>Rohdaten</h2> +<div class="row"> +	<div class="col s12 m12 l5 center-align"> +		<a href="/history.json" class="waves-effect waves-light btn"><i class="material-icons left">cloud</i> JSON-Export</a> +	</div> +	<div class="col s12 m12 l2"> </div> +	<div class="col s12 m12 l5 center-align"> +		<a href="/journey/add" class="waves-effect waves-light btn"><i class="material-icons left">add</i> Neue Fahrt</a> +	</div> +</div> +  % if (stash('statistics')) {  	%= include '_history_stats', stats => stash('statistics');  % } diff --git a/templates/passengerrights.html.ep b/templates/passengerrights.html.ep new file mode 100644 index 0000000..09c50d9 --- /dev/null +++ b/templates/passengerrights.html.ep @@ -0,0 +1,69 @@ +<h1>Fahrgastrechte</h1> +<div class="row"> +	<div class="col s12"> +		<p> +			Gemäß der Fahrgastrechte im Eisenbahnverkehr besteht ab 60 Minuten +			Verspätung am Ziel ein Entschädigungsanspruch gegenüber dem +			Eisenbahnverkehrsunternehmen. Dieser kann mit dem +			Fahrgastrechteformular geltend gemacht werden. +		</p> +		<p> +			Die folgenden Zugfahrten sind wahrscheinliche Kandidaten dafür. +			Details zur jeweiligen Zugfahrt sind bereits im Formular eingetragen. +		</p> +	</div> +</div> + +<div class="row"> +	<div class="col s12"> +		<table class="striped"> +			<thead> +				<tr> +					<th>Datum</th> +					<th>Zug</th> +					<th>Grund</th> +					<th>Formular</th> +				</tr> +			</thead> +			<tbody> +				% for my $journey (@{$journeys}) { +					% my $detail_link = '/journey/' . $journey->{id}; +					<tr> +						<td><%= $journey->{sched_departure}->strftime('%d.%m.%Y') %></td> +						<td><a href="<%= $detail_link %>"> +							<%= $journey->{type} %> <%= $journey->{line} // $journey->{no} %> +							→ <%= $journey->{to_name} %> +							% if ($journey->{connection}) { +								<br/> +								<%= $journey->{connection}{type} %> <%= $journey->{connection}{line} // $journey->{connection}{no} %> +								→ <%= $journey->{connection}{to_name} %> +							% } +						</a></td> +						<td> +							% if ($journey->{cancelled}) { +								Ausfall +							% } +							% else { +								%= sprintf('%+d',  $journey->{delay}) +								% if ($journey->{connection}) { +									<br/> +									%= sprintf('Mit Anschluss: %+d?',  $journey->{possible_delay}) +								% } +							% } +						</td> +						<td> +							% my $form_target = sprintf('/journey/passenger_rights/FGR %s %s %s.pdf', $journey->{sched_departure}->ymd, $journey->{type}, $journey->{no}); +							%= form_for $form_target => (method => 'POST') => begin +								%= csrf_field +								%= hidden_field id => $journey->{id} +								<button class="btn waves-effect waves-light grey darken-3" type="submit" name="action" value="generate"> +									<i class="material-icons">file_download</i> +								</button> +							%= end +						</td> +					</tr> +				% } +			</tbody> +		</table> +	</div> +</div> | 
