aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHakim Cassimally <hakim@mysociety.org>2015-01-23 12:35:05 +0000
committerDave Arter <davea@mysociety.org>2015-10-06 09:09:22 +0100
commit66e1e8922259cc0841550f39242a801ef72b0c69 (patch)
tree334f9bb7c381647ea6d6ed7e4ea096bcfbf708fd
parentae49214c011fa1d8794ebce589d319494cb65407 (diff)
[Zurich] Provide a setup-contacts command.
for Zurich (and generic data), progressing mysociety/FixMyStreet-Commercial/issues/663, to provide a way for body/contact config to be consistent across dev/staging/live. Run like so: bin/setup-contacts zurich e.g. with the lower-case sigil describing the cobrand to run setup-contacts for.
-rwxr-xr-xbin/setup-contacts204
-rw-r--r--perllib/FixMyStreet/Cobrand/Default.pm44
-rw-r--r--perllib/FixMyStreet/Cobrand/Zurich.pm95
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;