aboutsummaryrefslogtreecommitdiffstats
path: root/perllib/FixMyStreet/DB/Result/Problem.pm
diff options
context:
space:
mode:
Diffstat (limited to 'perllib/FixMyStreet/DB/Result/Problem.pm')
-rw-r--r--perllib/FixMyStreet/DB/Result/Problem.pm386
1 files changed, 386 insertions, 0 deletions
diff --git a/perllib/FixMyStreet/DB/Result/Problem.pm b/perllib/FixMyStreet/DB/Result/Problem.pm
new file mode 100644
index 000000000..ab05c3157
--- /dev/null
+++ b/perllib/FixMyStreet/DB/Result/Problem.pm
@@ -0,0 +1,386 @@
+package FixMyStreet::DB::Result::Problem;
+
+# Created by DBIx::Class::Schema::Loader
+# DO NOT MODIFY THE FIRST PART OF THIS FILE
+
+use strict;
+use warnings;
+
+use base 'DBIx::Class::Core';
+
+__PACKAGE__->load_components("FilterColumn", "InflateColumn::DateTime");
+__PACKAGE__->table("problem");
+__PACKAGE__->add_columns(
+ "id",
+ {
+ data_type => "integer",
+ is_auto_increment => 1,
+ is_nullable => 0,
+ sequence => "problem_id_seq",
+ },
+ "postcode",
+ { data_type => "text", is_nullable => 0 },
+ "latitude",
+ { data_type => "double precision", is_nullable => 0 },
+ "longitude",
+ { data_type => "double precision", is_nullable => 0 },
+ "council",
+ { data_type => "text", is_nullable => 1 },
+ "areas",
+ { data_type => "text", is_nullable => 0 },
+ "category",
+ { data_type => "text", default_value => "Other", is_nullable => 0 },
+ "title",
+ { data_type => "text", is_nullable => 0 },
+ "detail",
+ { data_type => "text", is_nullable => 0 },
+ "photo",
+ { data_type => "bytea", is_nullable => 1 },
+ "used_map",
+ { data_type => "boolean", is_nullable => 0 },
+ "user_id",
+ { data_type => "integer", is_foreign_key => 1, is_nullable => 0 },
+ "name",
+ { data_type => "text", is_nullable => 0 },
+ "anonymous",
+ { data_type => "boolean", is_nullable => 0 },
+ "external_id",
+ { data_type => "text", is_nullable => 1 },
+ "external_body",
+ { data_type => "text", is_nullable => 1 },
+ "external_team",
+ { data_type => "text", is_nullable => 1 },
+ "created",
+ {
+ data_type => "timestamp",
+ default_value => \"ms_current_timestamp()",
+ is_nullable => 0,
+ },
+ "confirmed",
+ { data_type => "timestamp", is_nullable => 1 },
+ "state",
+ { data_type => "text", is_nullable => 0 },
+ "lang",
+ { data_type => "text", default_value => "en-gb", is_nullable => 0 },
+ "service",
+ { data_type => "text", default_value => "", is_nullable => 0 },
+ "cobrand",
+ { data_type => "text", default_value => "", is_nullable => 0 },
+ "cobrand_data",
+ { data_type => "text", default_value => "", is_nullable => 0 },
+ "lastupdate",
+ {
+ data_type => "timestamp",
+ default_value => \"ms_current_timestamp()",
+ is_nullable => 0,
+ },
+ "whensent",
+ { data_type => "timestamp", is_nullable => 1 },
+ "send_questionnaire",
+ { data_type => "boolean", default_value => \"true", is_nullable => 0 },
+);
+__PACKAGE__->set_primary_key("id");
+__PACKAGE__->has_many(
+ "comments",
+ "FixMyStreet::DB::Result::Comment",
+ { "foreign.problem_id" => "self.id" },
+ { cascade_copy => 0, cascade_delete => 0 },
+);
+__PACKAGE__->belongs_to(
+ "user",
+ "FixMyStreet::DB::Result::User",
+ { id => "user_id" },
+ { is_deferrable => 1, on_delete => "CASCADE", on_update => "CASCADE" },
+);
+__PACKAGE__->has_many(
+ "questionnaires",
+ "FixMyStreet::DB::Result::Questionnaire",
+ { "foreign.problem_id" => "self.id" },
+ { cascade_copy => 0, cascade_delete => 0 },
+);
+
+
+# Created by DBIx::Class::Schema::Loader v0.07010 @ 2011-05-24 15:32:43
+# DO NOT MODIFY THIS OR ANYTHING ABOVE! md5sum:U3aYCRwE4etekKaHdhEkIw
+
+# Add fake relationship to stored procedure table
+__PACKAGE__->has_many(
+ "nearby",
+ "FixMyStreet::DB::Result::Nearby",
+ { "foreign.problem_id" => "self.id" },
+ { cascade_copy => 0, cascade_delete => 0 },
+);
+
+use DateTime::TimeZone;
+use Image::Size;
+use Moose;
+use namespace::clean -except => [ 'meta' ];
+use Utils;
+
+with 'FixMyStreet::Roles::Abuser';
+
+my $tz = DateTime::TimeZone->new( name => "local" );
+
+sub confirmed_local {
+ my $self = shift;
+
+ return $self->confirmed
+ ? $self->confirmed->set_time_zone($tz)
+ : $self->confirmed;
+}
+
+sub created_local {
+ my $self = shift;
+
+ return $self->created
+ ? $self->created->set_time_zone($tz)
+ : $self->created;
+}
+
+sub whensent_local {
+ my $self = shift;
+
+ return $self->whensent
+ ? $self->whensent->set_time_zone($tz)
+ : $self->whensent;
+}
+
+sub lastupdate_local {
+ my $self = shift;
+
+ return $self->lastupdate
+ ? $self->lastupdate->set_time_zone($tz)
+ : $self->lastupdate;
+}
+
+around service => sub {
+ my ( $orig, $self ) = ( shift, shift );
+ my $s = $self->$orig(@_);
+ $s =~ s/_/ /g;
+ return $s;
+};
+
+=head2 check_for_errors
+
+ $error_hashref = $problem->check_for_errors();
+
+Look at all the fields and return a hashref with all errors found, keyed on the
+field name. This is intended to be passed back to the form to display the
+errors.
+
+TODO - ideally we'd pass back error codes which would be humanised in the
+templates (eg: 'missing','email_not_valid', etc).
+
+=cut
+
+sub check_for_errors {
+ my $self = shift;
+
+ my %errors = ();
+
+ $errors{title} = _('Please enter a subject')
+ unless $self->title =~ m/\S/;
+
+ $errors{detail} = _('Please enter some details')
+ unless $self->detail =~ m/\S/;
+
+ $errors{council} = _('No council selected')
+ unless $self->council
+ && $self->council =~ m/^(?:-1|[\d,]+(?:\|[\d,]+)?)$/;
+
+ if ( $self->name !~ m/\S/ ) {
+ $errors{name} = _('Please enter your name');
+ }
+ elsif (length( $self->name ) < 5
+ || $self->name !~ m/\s/
+ || $self->name =~ m/\ba\s*n+on+((y|o)mo?u?s)?(ly)?\b/i )
+ {
+ $errors{name} = _(
+'Please enter your full name, councils need this information - if you do not wish your name to be shown on the site, untick the box'
+ );
+ }
+
+ if ( $self->category
+ && $self->category eq _('-- Pick a category --') )
+ {
+ $errors{category} = _('Please choose a category');
+ $self->category(undef);
+ }
+ elsif ($self->category
+ && $self->category eq _('-- Pick a property type --') )
+ {
+ $errors{category} = _('Please choose a property type');
+ $self->category(undef);
+ }
+
+ return \%errors;
+}
+
+=head2 confirm
+
+ $bool = $problem->confirm( );
+ $problem->update;
+
+
+Set the state to 'confirmed' and put current time into 'confirmed' field. This
+is a no-op if the report is already confirmed.
+
+NOTE - does not update storage - call update or insert to do that.
+
+=cut
+
+sub confirm {
+ my $self = shift;
+
+ return if $self->state eq 'confirmed';
+
+ $self->state('confirmed');
+ $self->confirmed( \'ms_current_timestamp()' );
+ return 1;
+}
+
+=head2 councils
+
+Returns an array of councils to which a report was sent.
+
+=cut
+
+sub councils {
+ my $self = shift;
+ return () unless $self->council;
+ (my $council = $self->council) =~ s/\|.*$//;
+ my @council = split( /,/, $council );
+ return @council;
+}
+
+=head2 url
+
+Returns a URL for this problem report.
+
+=cut
+
+sub url {
+ my $self = shift;
+ return "/report/" . $self->id;
+}
+
+=head2 get_photo_params
+
+Returns a hashref of details of any attached photo for use in templates.
+Hashref contains height, width and url keys.
+
+=cut
+
+sub get_photo_params {
+ my $self = shift;
+
+ return {} unless $self->photo;
+
+ my $photo = {};
+ ( $photo->{width}, $photo->{height} ) =
+ Image::Size::imgsize( \$self->photo );
+ $photo->{url} = '/photo?id=' . $self->id;
+
+ return $photo;
+}
+
+=head2 meta_line
+
+Returns a string to be used on a problem report page, describing some of the
+meta data about the report.
+
+=cut
+
+sub meta_line {
+ my ( $problem, $c ) = @_;
+
+ my $date_time =
+ Utils::prettify_epoch( $problem->confirmed_local->epoch );
+ my $meta = '';
+
+ # FIXME Should be in cobrand
+ if ($c->cobrand->moniker eq 'emptyhomes') {
+
+ my $category = _($problem->category);
+ utf8::decode($category);
+ if ($problem->anonymous) {
+ $meta = sprintf(_('%s, reported anonymously at %s'), $category, $date_time);
+ } else {
+ $meta = sprintf(_('%s, reported by %s at %s'), $category, $problem->name, $date_time);
+ }
+
+ } else {
+
+ if ( $problem->anonymous ) {
+ if ( $problem->service
+ and $problem->category && $problem->category ne _('Other') )
+ {
+ $meta =
+ sprintf( _('Reported by %s in the %s category anonymously at %s'),
+ $problem->service, $problem->category, $date_time );
+ }
+ elsif ( $problem->service ) {
+ $meta = sprintf( _('Reported by %s anonymously at %s'),
+ $problem->service, $date_time );
+ }
+ elsif ( $problem->category and $problem->category ne _('Other') ) {
+ $meta = sprintf( _('Reported in the %s category anonymously at %s'),
+ $problem->category, $date_time );
+ }
+ else {
+ $meta = sprintf( _('Reported anonymously at %s'), $date_time );
+ }
+ }
+ else {
+ if ( $problem->service
+ and $problem->category && $problem->category ne _('Other') )
+ {
+ $meta = sprintf(
+ _('Reported by %s in the %s category by %s at %s'),
+ $problem->service, $problem->category,
+ $problem->name, $date_time
+ );
+ }
+ elsif ( $problem->service ) {
+ $meta = sprintf( _('Reported by %s by %s at %s'),
+ $problem->service, $problem->name, $date_time );
+ }
+ elsif ( $problem->category and $problem->category ne _('Other') ) {
+ $meta = sprintf( _('Reported in the %s category by %s at %s'),
+ $problem->category, $problem->name, $date_time );
+ }
+ else {
+ $meta =
+ sprintf( _('Reported by %s at %s'), $problem->name, $date_time );
+ }
+ }
+
+ }
+
+ $meta .= $c->cobrand->extra_problem_meta_text($problem);
+ $meta .= '; ' . _('the map was not used so pin location may be inaccurate')
+ unless $problem->used_map;
+
+ return $meta;
+}
+
+sub duration_string {
+ my $problem = shift;
+ my $body;
+ if ($problem->external_body) {
+ $body = $problem->external_body;
+ } else {
+ (my $council = $problem->council) =~ s/\|.*//g;
+ my @councils = split( /,/, $council );
+ my $areas_info = mySociety::MaPit::call('areas', \@councils);
+ $body = join(' and ', map { $areas_info->{$_}->{name} } @councils);
+ }
+ return sprintf(_('Sent to %s %s later'), $body,
+ Utils::prettify_duration($problem->whensent_local->epoch - $problem->confirmed_local->epoch, 'minute')
+ );
+}
+
+# we need the inline_constructor bit as we don't inherit from Moose
+__PACKAGE__->meta->make_immutable( inline_constructor => 0 );
+
+1;