Skip to content

Commit

Permalink
[Bromley] ICal generation.
Browse files Browse the repository at this point in the history
  • Loading branch information
dracos committed Jun 29, 2020
1 parent 70a08c8 commit 72a8be0
Show file tree
Hide file tree
Showing 7 changed files with 173 additions and 1 deletion.
18 changes: 18 additions & 0 deletions perllib/Data/ICal/Entry/Event7986.pm
@@ -0,0 +1,18 @@
package Data::ICal::Entry::Event7986;

use parent 'Data::ICal::Entry::Event';

sub optional_unique_properties {
return (
shift->SUPER::optional_unique_properties,
"color",
);
}

sub optional_repeatable_properties {
return (
shift->SUPER::optional_repeatable_properties,
"conference", "image",
);
}

17 changes: 17 additions & 0 deletions perllib/Data/ICal/RFC7986.pm
@@ -0,0 +1,17 @@
package Data::ICal::RFC7986;

use parent 'Data::ICal';

sub optional_unique_properties {
qw( calscale method
uid last-modified url refresh-interval source color
);
}

# name/description are only repeatable to provide
# translations with language param
sub optional_repeatable_properties {
qw( name description categories image );
}

1;
38 changes: 38 additions & 0 deletions perllib/FixMyStreet/App/Controller/Waste.pm
Expand Up @@ -92,6 +92,44 @@ sub bin_days : Chained('uprn') : PathPart('') : Args(0) {
my ($self, $c) = @_;
}

sub calendar : Chained('uprn') : PathPart('calendar.ics') : Args(0) {
my ($self, $c) = @_;
$c->res->header(Content_Type => 'text/calendar');
require Data::ICal::RFC7986;
require Data::ICal::Entry::Event;
my $calendar = Data::ICal::RFC7986->new(
calname => 'Bin calendar',
rfc_strict => 1,
auto_uid => 1,
);
$calendar->add_properties(
prodid => '//FixMyStreet//Bin Collection Calendars//EN',
method => 'PUBLISH',
'refresh-interval' => [ 'P1D', { value => 'DURATION' } ],
'x-published-ttl' => 'P1D',
calscale => 'GREGORIAN',
'x-wr-timezone' => 'Europe/London',
source => [ $c->uri_for_action($c->action, [ $c->stash->{uprn} ]), { value => 'URI' } ],
url => $c->uri_for_action('waste/bin_days', [ $c->stash->{uprn} ]),
);

my $events = $c->cobrand->bin_future_collections;
my $stamp = DateTime->now->strftime('%Y%m%dT%H%M%SZ');
foreach (@$events) {
my $event = Data::ICal::Entry::Event->new;
$event->add_properties(
summary => $_->{summary},
description => $_->{desc},
dtstamp => $stamp,
dtstart => [ $_->{date}->ymd(''), { value => 'DATE' } ],
dtend => [ $_->{date}->add(days=>1)->ymd(''), { value => 'DATE' } ],
);
$calendar->add_entry($event);
}

$c->res->body($calendar->as_string);
}

sub construct_bin_request_form {
my $c = shift;

Expand Down
29 changes: 29 additions & 0 deletions perllib/FixMyStreet/Cobrand/Bromley.pm
Expand Up @@ -562,6 +562,35 @@ sub _parse_schedules {
};
}

sub bin_future_collections {
my $self = shift;

my $services = $self->{c}->stash->{service_data};
my @tasks;
my %names;
foreach (@$services) {
push @tasks, $_->{service_task_id};
$names{$_->{service_task_id}} = $_->{service_name};
}

my $echo = $self->feature('echo');
$echo = Integrations::Echo->new(%$echo);
my $result = $echo->GetServiceTaskInstances(@tasks);

my $events = [];
foreach (@$result) {
my $task_id = $_->{ServiceTaskRef}{Value}{anyType};
my $tasks = Integrations::Echo::force_arrayref($_->{Instances}, 'ScheduledTaskInfo');
foreach (@$tasks) {
my $dt = construct_bin_date($_->{CurrentScheduledDate});
my $summary = $names{$task_id} . ' collection';
my $desc = '';
push @$events, { date => $dt, summary => $summary, desc => $desc };
}
}
return $events;
}

=over
=item within_working_days
Expand Down
58 changes: 58 additions & 0 deletions perllib/Integrations/Echo.pm
Expand Up @@ -2,8 +2,10 @@ package Integrations::Echo;

use strict;
use warnings;
use DateTime;
use Moo;
use Tie::IxHash;
use FixMyStreet;

has attr => ( is => 'ro', default => 'http://www.twistedfish.com/xmlns/echo/api/v1' );
has action => ( is => 'lazy', default => sub { $_[0]->attr . "/Service/" } );
Expand All @@ -21,6 +23,7 @@ has endpoint => (
SOAP::Lite->soapversion(1.2);
my $soap = SOAP::Lite->on_action( sub { $self->action . $_[1]; } )->proxy($self->url);
$soap->serializer->register_ns("http://schemas.microsoft.com/2003/10/Serialization/Arrays", 'msArray'),
$soap->serializer->register_ns("http://schemas.datacontract.org/2004/07/System", 'dataContract');
return $soap;
},
);
Expand Down Expand Up @@ -228,6 +231,61 @@ sub GetServiceUnitsForObject {
return force_arrayref($res, 'ServiceUnit');
}

sub GetServiceTaskInstances {
my ($self, @tasks) = @_;

my @objects;
foreach (@tasks) {
my $obj = ixhash(
Key => 'Id',
Type => 'ServiceTask',
Value => [
{ 'msArray:anyType' => $_ },
],
);
push @objects, { ObjectRef => $obj };
}
my $start = DateTime->now->set_time_zone(FixMyStreet->local_time_zone)->truncate( to => 'day' );
my $end = $start->clone->add(months => 3);
my $query = ixhash(
From => dt_to_hash($start),
To => dt_to_hash($end),
);
return [
{ ServiceTaskRef => { Value => { anyType => 401 } },
Instances => { ScheduledTaskInfo => [
{ CurrentScheduledDate => { DateTime => '2020-07-01T00:00:00Z' } },
] }
},
{ ServiceTaskRef => { Value => { anyType => 402 } },
Instances => { ScheduledTaskInfo => [
{ CurrentScheduledDate => { DateTime => '2020-07-08T00:00:00Z' } },
] }
},
] if $self->sample_data;
# uncoverable statement
my $res = $self->call('GetServiceTaskInstances',
serviceTaskRefs => \@objects,
query => $query,
);
return force_arrayref($res, 'ServiceTaskInstances');
}

sub ixhash {
tie (my %data, 'Tie::IxHash', @_);
return \%data;
}

sub dt_to_hash {
my $dt = shift;
my $utc = $dt->clone->set_time_zone('UTC');
$dt = ixhash(
'dataContract:DateTime' => $utc->ymd . 'T' . $utc->hms . 'Z',
'dataContract:OffsetMinutes' => $dt->offset / 60,
);
return $dt;
}

sub force_arrayref {
my ($res, $key) = @_;
return [] unless $res;
Expand Down
12 changes: 12 additions & 0 deletions t/app/controller/waste.t
Expand Up @@ -129,6 +129,18 @@ FixMyStreet::override_config {
$mech->get_ok('/waste/uprn/1000000002/enquiry?service=1');
is $mech->uri->path, '/waste/uprn/1000000002';
};
subtest 'Checking calendar' => sub {
$mech->follow_link_ok({ text => 'Add to your calendar (.ics file)' });
$mech->content_contains('BEGIN:VCALENDAR');
my @events = split /BEGIN:VEVENT/, $mech->encoded_content;
shift @events; # Header
my $i = 0;
foreach (@events) {
$i++ if /DTSTART;VALUE=DATE:20200701/ && /SUMMARY:Refuse collection/;
$i++ if /DTSTART;VALUE=DATE:20200708/ && /SUMMARY:Paper & Cardboard/;
}
is $i, 2, 'Two events from the sample data in the calendar';
};
subtest 'General enquiry, on behalf of someone else' => sub {
$mech->log_in_ok($staff_user->email);
$mech->get_ok('/waste/uprn/1000000002/enquiry?category=General+enquiry&service_id=537');
Expand Down
2 changes: 1 addition & 1 deletion templates/web/base/waste/bin_days.html
Expand Up @@ -63,7 +63,7 @@ <h3 class="govuk-heading-m waste-service-name">[% unit.service_name %]</h3>
<div class="aside-download">
<h3>Download your collection schedule</h3>
<ul>
<li><a href="#">Add to your calendar (.ics file)</a></li>
<li><a href="[% c.uri_for_action('waste/calendar', [ uprn ]) %]">Add to your calendar (.ics file)</a></li>
</ul>
</div>
<div class="aside-services">
Expand Down

0 comments on commit 72a8be0

Please sign in to comment.