diff options
-rwxr-xr-x | bin/setup-contacts | 204 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Default.pm | 44 | ||||
-rw-r--r-- | perllib/FixMyStreet/Cobrand/Zurich.pm | 95 |
3 files changed, 343 insertions, 0 deletions
diff --git a/bin/setup-contacts b/bin/setup-contacts new file mode 100755 index 000000000..d562ae71d --- /dev/null +++ b/bin/setup-contacts @@ -0,0 +1,204 @@ +#!/usr/bin/env perl + +use strict; +use warnings; +require 5.8.0; +use feature 'say'; + +BEGIN { + use File::Basename qw(dirname); + use File::Spec; + my $d = dirname(File::Spec->rel2abs($0)); + require "$d/../setenv.pl"; +} + +use FixMyStreet::App; + +my $moniker = $ARGV[0]; + +my $c = FixMyStreet::App->new(); +my $cobrand = FixMyStreet::Cobrand->get_class_for_moniker($moniker)->new({ c => $c }); +$c->stash->{cobrand} = $cobrand; + +die "Not a staging site, bailing out" unless $c->config->{STAGING_SITE}; # TODO, allow override via --force +say "Applying contacts for $cobrand"; + + +ensure_bodies(); +setup_contacts(); + +=head2 setup_contacts, ensure_bodies + +routines to update extra data for contacts. These can be called by +a script: + + bin/setup-contacts zurich + +=cut + +sub ensure_bodies { + my @bodies = $cobrand->body_details_data; + + my $bodies_rs = $c->model('DB::Body'); + + for my $body (@bodies) { + # following should work (having added Unique name/parent constraint, but doesn't) + # $bodies_rs->find_or_create( $body, { $parent ? ( key => 'body_name_parent_key' ) : () } ); + # let's keep it simple and just allow unique names + next if $bodies_rs->search({ name => $body->{name} })->count; + if (my $area_id = delete $body->{area_id}) { + $body->{body_areas} = [ { area_id => $area_id } ]; + } + my $parent = $body->{parent}; + if ($parent and ! ref $parent) { + $body->{parent} = { name => $parent }; + } + $bodies_rs->find_or_create( $body ); + } +} + +sub setup_contacts { + die "Not a staging site, bailing out" unless $c->config->{STAGING_SITE}; # TODO, allow override via --force + + my @contact_details = $cobrand->contact_details_data; + + for my $detail (@contact_details) { + update_contact( $detail, $description ); + } +} + +sub update_contact { + my ($contact_data, $description) = @_; + + my $contact_rs = $c->model('DB::Contact'); + + my $category = $contact_data->{category} or die "No category provided"; + $description ||= "Update contact"; + + my $contact = ensure_contact($contact_data, $description) + or return; # e.g. nothing returned if deleted + + if (my $fields = $contact_data->{fields}) { + + my @fields = map { get_field_extra($_) } @$fields; + my $note = sprintf 'Fields edited by automated script%s', $description ? " ($description)" : ''; + $contact->set_extra_fields(@fields); + $contact->set_inflated_columns({ + confirmed => 1, + deleted => 0, + editor => 'automated script', + whenedited => \'NOW()', + note => "Updated fields $description", + }); + $contact->update; + } +} + +sub ensure_contact { + my ($contact_data, $description) = @_; + + my $category = $contact_data->{category} or die "No category provided"; + $description ||= "Ensure contact exists $category"; + + my $email = temp_email_to_update(); # will only be set if newly created + + my $body = get_body_for_contact($contact_data) or die "No body found for $category"; + + my $contact_rs = $c->model('DB::Contact'); + + my $category_details = $contact_data->{category_details} || {}; + + if (my $old_name = delete $contact_data->{rename_from}) { + if (my $old_category = $contact_rs->find({ + category => $old_name, + , body => $body, + })) { + $old_category->update({ + category => $category, + whenedited => \'NOW()', + note => "Renamed $description", + %{ $category_details || {} }, + }); + return $old_category; + } + } + + if ($contact_data->{delete}) { + my $contact = $contact_rs->search({ + body_id => $body->id, + category => $category, + deleted => 0 + }); + if ($contact->count) { + print sprintf "Deleting: %s\n", $category; + $contact->update({ + deleted => 1, + editor => 'automated script', + whenedited => \'NOW()', + note => "Deleted by script $description", + }); + } + return; + } + + return $contact_rs->find_or_create( + { + body => $body, + category => $category, + + confirmed => 1, + deleted => 0, + email => $email, + editor => 'automated script', + note => 'created by automated script', + send_method => '', + whenedited => \'NOW()', + %{ $category_details || {} }, + }, + { + key => 'contacts_body_id_category_idx' + } + ); +} + +sub get_field_extra { + my ($field) = @_; + + my %default = ( + variable => 'true', + order => '1', + required => 'no', + datatype => 'string', + datatype_description => 'a string', + ); + + if (($field->{datatype} || '') eq 'boolean') { + %default = ( + %default, + datatype => 'singlevaluelist', + datatype_description => 'Yes or No', + values => { value => [ + { key => ['No'], name => ['No'] }, + { key => ['Yes'], name => ['Yes'] }, + ] }, + ); + } + + return { %default, %$field }; +} + +sub temp_email_to_update { 'test@example.com' } + +sub get_body_for_contact { + my ($contact_data) = @_; + if (my $body_name = $contact_data->{body_name}) { + return $c->model('DB::Body')->find({ name => $body_name }); + } + if ($cobrand->can('contact_details_data_body_default')) { + return $cobrand->contact_details_data_body_default; + } + return; + # TODO: for UK Councils use + # $c->model('DB::Body')->find(id => $cobrand->council_id); + # # NB: (or better that's the area in BodyAreas) +} diff --git a/perllib/FixMyStreet/Cobrand/Default.pm b/perllib/FixMyStreet/Cobrand/Default.pm index c347d5750..9541f2601 100644 --- a/perllib/FixMyStreet/Cobrand/Default.pm +++ b/perllib/FixMyStreet/Cobrand/Default.pm @@ -913,4 +913,48 @@ sub jurisdiction_id_example { return $self->moniker; } +=head2 body_details_data + +Returns a list of bodies to create with ensure_body. These +are mostly just passed to ->find_or_create, but there is some +pre-processing so that you can enter: + + area_id => 123, + parent => 'Big Town', + +instead of + + body_areas => [ { area_id => 123 } ], + parent => { name => 'Big Town' }, + +For example: + + return ( + { + name => 'Big Town', + }, + { + name => 'Small town', + parent => 'Big Town', + area_id => 1234, + }, + + +=cut + +sub body_details_data { + return (); +} + +=head2 contact_details_data + +Returns a list of contact_data to create with setup_contacts. +See Zurich for an example. + +=cut + +sub contact_details_data { + return () +} + 1; diff --git a/perllib/FixMyStreet/Cobrand/Zurich.pm b/perllib/FixMyStreet/Cobrand/Zurich.pm index 5c6566b62..dc93467a6 100644 --- a/perllib/FixMyStreet/Cobrand/Zurich.pm +++ b/perllib/FixMyStreet/Cobrand/Zurich.pm @@ -8,6 +8,7 @@ use Scalar::Util 'blessed'; use strict; use warnings; +use feature 'say'; =head1 NAME @@ -860,4 +861,98 @@ sub problem_confirm_email_extras { $self->{c}->stash->{email_confirmed} = $confirmed_reports; } +sub body_details_data { + return ( + { + name => 'Stadt Zurich' + }, + { + name => 'Elektrizitäwerk Stadt Zürich', + parent => 'Stadt Zurich', + area_id => 423017, + }, + { + name => 'ERZ Entsorgung + Recycling Zürich', + parent => 'Stadt Zurich', + area_id => 423017, + }, + { + name => 'Fachstelle Graffiti', + parent => 'Stadt Zurich', + area_id => 423017, + }, + { + name => 'Grün Stadt Zürich', + parent => 'Stadt Zurich', + area_id => 423017, + }, + { + name => 'Tiefbauamt Stadt Zürich', + parent => 'Stadt Zurich', + area_id => 423017, + }, + { + name => 'Dienstabteilung Verkehr', + parent => 'Stadt Zurich', + area_id => 423017, + }, + ); +} + +sub contact_details_data { + return ( + { + category => 'Beleuchtung/Uhren', + body_name => 'Elektrizitätswerk Stadt Zürich', + fields => [ + { + code => 'strasse', + description => 'Strasse', + datatype => 'string', + required => 'yes', + }, + { + code => 'haus_nr', + description => 'Haus-Nr.', + datatype => 'string', + }, + { + code => 'mast_nr', + description => 'Mast-Nr.', + datatype => 'string', + } + ], + }, + { + category => 'Brunnen/Hydranten', + # body_name ??? + fields => [ + { + code => 'hydranten_nr', + description => 'Hydranten-Nr.', + datatype => 'string', + }, + ], + }, + { + category => "Grünflächen/Spielplätze", + body_name => 'Grün Stadt Zürich', + rename_from => "Tiere/Grünflächen", + }, + { + category => 'Spielplatz/Sitzbank', + body_name => 'Grün Stadt Zürich', + delete => 1, + }, + ); +} + +sub contact_details_data_body_default { + my ($self) = @_; + # temporary measure to assign un-bodied contacts to parent + # (this isn't at all how things will be setup in live, but is + # handy during dev.) + return $self->{c}->model('DB::Body')->find({ name => 'Stadt Zurich' }); +} + 1; |