diff --git a/CHANGELOG.md b/CHANGELOG.md index 8afc62fd088..3a4bdf2e1e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -38,6 +38,7 @@ - Mark non-Open311 updates as processed by daemon. #4552 - Changes: - Switch to OpenStreetMap for reverse geocoding. #4444 + - Convert all uploaded images to JPEGs. * v5.0 (10th May 2023) - Front end improvements: diff --git a/bin/fixmystreet.com/waste-echo-reservation-update b/bin/fixmystreet.com/waste-echo-reservation-update new file mode 100644 index 00000000000..e3b5aebfb8c --- /dev/null +++ b/bin/fixmystreet.com/waste-echo-reservation-update @@ -0,0 +1,22 @@ +#!/usr/bin/env perl +# +# Fallback manual script to be used if a report needs resending to Echo but +# contains an expired task reservation, to fetch new data if possible + +use v5.14; +use warnings; + +BEGIN { + use File::Basename qw(dirname); + use File::Spec; + my $d = dirname(File::Spec->rel2abs($0)); + require "$d/../../setenv.pl"; +} + +use FixMyStreet::Cobrand; +use FixMyStreet::DB; + +my $id = shift @ARGV or die "Provide a report ID"; +my $p = FixMyStreet::DB->resultset("Problem")->find($id) or die "Could not find ID $id"; +my $cobrand = $p->get_cobrand_logged; +$cobrand->bulky_refetch_slots($p, 1); diff --git a/perllib/FixMyStreet/App/Model/PhotoSet.pm b/perllib/FixMyStreet/App/Model/PhotoSet.pm index 4083d32d93c..d58753bbf49 100644 --- a/perllib/FixMyStreet/App/Model/PhotoSet.pm +++ b/perllib/FixMyStreet/App/Model/PhotoSet.pm @@ -155,11 +155,8 @@ has ids => ( # Arrayref of $fileid tuples (always, so post upload/raw data proc return (); } - my %params; - # Brent has a quite-small file size limit, make sure we convert to JPEGs - if ($self->c->cobrand->moniker eq 'brent') { - $params{magick} = 'JPEG'; - } + # Convert all images to JPEGs + my %params = ( magick => 'JPEG' ); # we have an image we can use - save it to storage $photo_blob = try { diff --git a/perllib/FixMyStreet/Cobrand/Bromley.pm b/perllib/FixMyStreet/Cobrand/Bromley.pm index 44d3742501f..b4f93329d7a 100644 --- a/perllib/FixMyStreet/Cobrand/Bromley.pm +++ b/perllib/FixMyStreet/Cobrand/Bromley.pm @@ -318,6 +318,9 @@ sub open311_post_send { $row2->state('duplicate'); $row2->update; $row->discard_changes; + } elsif ($error =~ /Selected reservations expired/) { + $self->bulky_refetch_slots($row2); + $row->discard_changes; } }); } diff --git a/perllib/FixMyStreet/Roles/CobrandEcho.pm b/perllib/FixMyStreet/Roles/CobrandEcho.pm index 68e81828f91..504089bc66a 100644 --- a/perllib/FixMyStreet/Roles/CobrandEcho.pm +++ b/perllib/FixMyStreet/Roles/CobrandEcho.pm @@ -1,6 +1,6 @@ package FixMyStreet::Roles::CobrandEcho; -use strict; +use v5.14; use warnings; use DateTime; use DateTime::Format::Strptime; @@ -609,6 +609,58 @@ sub clear_cached_lookups_bulky_slots { $echo->CancelReservedSlotsForEvent($guid); } +sub bulky_refetch_slots { + my ($self, $row, $verbose) = @_; + + my $property_id = $row->get_extra_field_value('property_id'); + my $date = $self->collection_date($row); + my $guid = $row->get_extra_field_value('GUID'); + my $window = $self->_bulky_collection_window(); + + my $cfg = $self->feature('echo'); + my $echo = Integrations::Echo->new(%$cfg); + + my $service_id = $cfg->{bulky_service_id}; + my $event_type_id = $cfg->{bulky_event_type_id}; + + if ($row->whensent || !$guid) { + if ($row->whensent) { + say "Already sent, creating new GUID and fetching new reservation and resending" if $verbose; + } else { + say "No GUID? Creating new GUID and fetching new reservation and sending" if $verbose; + } + require UUID::Tiny; + $guid = UUID::Tiny::create_uuid_as_string(); + $row->update_extra_field({ name => 'GUID', value => $guid }); + $row->state('confirmed'); + $row->resend; + } else { + say "Not already sent, fetching new reservation and trying again" if $verbose; + say "Cancelling existing slots for $guid" if $verbose; + $echo->CancelReservedSlotsForEvent($guid); + } + + say "Getting more slots for $property_id $guid" if $verbose; + my $slots = $echo->ReserveAvailableSlotsForEvent($service_id, $event_type_id, $property_id, $guid, $window->{date_from}, $window->{date_to}); + + my $slot_found = 0; + foreach (@$slots) { + my $slot_date = construct_bin_date($_->{StartDate}); + my $ref = $_->{Reference}; + if ($slot_date->ymd eq $date->ymd) { + $slot_found = 1; + say "Updating reservation to slot $ref for $slot_date" if $verbose; + $row->update_extra_field({ name => 'reservation', value => $ref }); + } + } + if ($slot_found) { + $row->send_fail_count(0); # Assuming it's been failing, for an instant retry + $row->update; + } else { + say "No replacement slot for $date could be found" if $verbose; + } +} + sub bulky_check_missed_collection { my ($self, $events, $blocked_codes) = @_; diff --git a/perllib/FixMyStreet/Roles/CobrandSLWP.pm b/perllib/FixMyStreet/Roles/CobrandSLWP.pm index 1df9aea691f..aa78a8cb09e 100644 --- a/perllib/FixMyStreet/Roles/CobrandSLWP.pm +++ b/perllib/FixMyStreet/Roles/CobrandSLWP.pm @@ -103,6 +103,9 @@ sub open311_post_send { $row2->state('duplicate'); $row2->update; $row->discard_changes; + } elsif ($error =~ /Selected reservations expired/) { + $self->bulky_refetch_slots($row2); + $row->discard_changes; } elsif ($error =~ /Duplicate Event! Original eventID: (\d+)/) { my $id = $1; my $cfg = $self->feature('echo'); diff --git a/t/app/controller/waste_bromley_bulky.t b/t/app/controller/waste_bromley_bulky.t index 9dad665e962..c9127cf96d3 100644 --- a/t/app/controller/waste_bromley_bulky.t +++ b/t/app/controller/waste_bromley_bulky.t @@ -15,8 +15,9 @@ my $minimum_charge = 500; my $user = $mech->create_user_ok('bob@example.org'); -my $body = $mech->create_body_ok( 2482, 'Bromley Council', - {}, { cobrand => 'bromley' } ); +my $body = $mech->create_body_ok( 2482, 'Bromley Council', { + endpoint => 'http://endpoint.example.com', jurisdiction => 'FMS', api_key => 'test', + }, { cobrand => 'bromley' } ); $body->set_extra_metadata( wasteworks_config => { per_item_costs => 1, @@ -144,7 +145,8 @@ FixMyStreet::override_config { }; }); $echo->mock('GetServiceUnitsForObject', \&domestic_waste_service_units ); - $echo->mock('ReserveAvailableSlotsForEvent', sub { + + my $reserve_mock = sub { my ($self, $service, $event_type, $property, $guid, $start, $end) = @_; is $service, 413; is $event_type, 2175; @@ -166,7 +168,8 @@ FixMyStreet::override_config { Expiry => { DateTime => '2023-06-25T10:10:00Z' }, Reference => 'reserve3==', }, - ] }); + ] }; + $echo->mock('ReserveAvailableSlotsForEvent', $reserve_mock); my $sent_params; my $call_params; @@ -428,7 +431,34 @@ FixMyStreet::override_config { $mech->content_lacks('Report a bulky waste collection as missed', "Can't report missing when closed collection but after two working days"); }; + }; + + subtest 'Bulky goods collection, reservation expired' => sub { + $report->discard_changes; + $report->update({ whensent => undef }); + $report->discard_changes; + my $sender = FixMyStreet::SendReport::Open311->new( + bodies => [ $body ], body_config => { $body->id => $body }, + ); + $echo->mock('ReserveAvailableSlotsForEvent', sub { + [ { + StartDate => { OffsetMinutes => 0, DateTime => '2023-07-01T00:00:00Z' }, + Expiry => { OffsetMinutes => 0, DateTime => '2023-07-02T00:00:00Z' }, + Reference => 'NewRes', + } ]; + }); + Open311->_inject_response('/requests.xml', 'Selected reservations expired', 500); + $sender->send($report, { + easting => 1, + northing => 2, + url => 'http://example.org/', + }); + $report->discard_changes; + is $report->get_extra_field_value('reservation'), 'NewRes'; + $echo->mock('ReserveAvailableSlotsForEvent', $reserve_mock); + }; + subtest 'Bulky goods collection, cancelling' => sub { # Collection time: 2023-07-01T:07:00:00 my $full_refund_time = '2023-06-30T05:59:59Z'; # 06:59:59 UK time my $partial_refund_time = '2023-07-01T05:59:59Z'; # 06:59:59 UK time