aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xbin/fixmystreet.com/fixture155
-rw-r--r--cpanfile1
-rw-r--r--cpanfile.snapshot260
-rw-r--r--perllib/FixMyStreet/DB/Factories.pm155
4 files changed, 545 insertions, 26 deletions
diff --git a/bin/fixmystreet.com/fixture b/bin/fixmystreet.com/fixture
index 93982af8a..d0b23ede5 100755
--- a/bin/fixmystreet.com/fixture
+++ b/bin/fixmystreet.com/fixture
@@ -1,11 +1,12 @@
#!/usr/bin/env perl
#
-# This script will create a test body and its categories, covering the area of
-# Westminster, and a user associated with that body, which should help testing
+# This script will create a test body and its categories, covering the area
+# provided, and users associated with that body, which should help testing
# of report interactions.
use strict;
use warnings;
+use v5.14;
BEGIN {
use File::Basename qw(dirname);
@@ -14,26 +15,136 @@ BEGIN {
require "$d/../../setenv.pl";
}
-use FixMyStreet::DB;
-
-my $body = FixMyStreet::DB->resultset("Body")->find_or_create({ name => 'Test City Council' });
-$body->body_areas->find_or_create({ area_id => 2504 });
-foreach ("Potholes", "Street lighting", "Graffiti") {
- (my $email = lc $_) =~ s/ /-/g;
- $body->contacts->find_or_create({
- category => $_,
- email => $email . '@example.net',
- confirmed => 't',
- deleted => 'f',
- whenedited => \'current_timestamp',
- editor => 'fixture',
- note => 'Created by fixture'
- });
+use FixMyStreet::Cobrand;
+use FixMyStreet::DB::Factories;
+use DateTime::Format::Pg;
+use Getopt::Long::Descriptive;
+use Path::Tiny 'path';
+
+my ($opt, $usage) = describe_options(
+ '%c %o',
+ [ 'area-id=i', "MapIt area ID to create body for", { required => 1 } ],
+ [ 'name:s', "Name of body to use (defaults to MapIt area name)" ],
+ [ 'empty', "Empty all tables of the database first" ],
+ [ 'commit', "Actually commit changes to the database" ],
+ [ 'help', "print usage message and exit", { shortcircuit => 1 } ],
+);
+print($usage->text), exit if $opt->help;
+
+my $db = FixMyStreet::DB->storage;
+$db->txn_begin;
+END {
+ if ($db) {
+ $opt->commit ? $db->txn_commit : $db->txn_rollback;
+ }
+}
+if (!$opt->commit) {
+ say "NOT COMMITTING TO DATABASE";
+}
+
+if ($opt->empty) {
+ $db->dbh->do(q{
+DO
+$func$
+BEGIN
+ EXECUTE
+ (SELECT 'TRUNCATE TABLE ' || string_agg(quote_ident(tablename), ', ') || ' RESTART IDENTITY CASCADE '
+ FROM pg_tables WHERE schemaname='public');
+END
+$func$;
+}) or die $!;
+ $db->dbh->do( path('db/alert_types.sql')->slurp ) or die $!;
+ $db->dbh->do( path('db/generate_secret.sql')->slurp ) or die $!;
+ say "Emptied database";
}
-FixMyStreet::DB->resultset("User")->find_or_create({
- email => 'council@example.net',
- name => 'Test City Council User',
- from_body => $body,
- password => 'password',
+# Body + categories
+my $categories = ['Potholes', 'Street lighting', 'Graffiti', 'Other'];
+my $body = FixMyStreet::DB::Factory::Body->find_or_create({
+ area_id => $opt->area_id,
+ categories => $categories,
+ $opt->name ? (name => $opt->name) : (),
});
+say "Created body " . $body->name . " for MapIt area ID " . $opt->area_id . ', categories ' . join(', ', @$categories);
+
+# Users
+say "Created users, all with password 'password':";
+my $user; # Will store the final (normal) user of the loop for later user
+my $perms_inspector = ['report_inspect', 'planned_reports'];
+my $perms_cs = [
+ 'contribute_as_body', 'contribute_as_another_user',
+ 'moderate', 'view_body_contribute_details',
+];
+foreach (
+ { name => 'Inspector Gadget', email => 'inspector@example.org', body => $body, permissions => $perms_inspector },
+ { name => 'Harriet Helpful', email => 'cs@example.org', body => $body, permissions => $perms_cs },
+ { name => 'Super User', email => 'super@example.org', body => $body, permissions => [
+ @$perms_cs, @$perms_inspector, 'report_edit',
+ 'category_edit', 'template_edit', 'responsepriority_edit',
+ 'user_assign_body', 'user_manage_permissions', 'user_edit',
+ ] },
+ { name => 'Wizard of Oz', email => 'admin@example.org', is_superuser => 't' },
+ { name => "Norma User", email => 'user@example.org' },
+) {
+ $user = FixMyStreet::DB::Factory::User->find_or_create($_);
+ my $perms = $_->{permissions} ? " (" . join(', ', @{$_->{permissions} || []}) . ")" : "";
+ my $su = $_->{is_superuser} ? " (superuser)" : "";
+ say "* $_->{email}$perms$su";
+}
+
+# Problems
+
+my %titles = (
+ 'Potholes' => ['Deep pothole', 'Small pothole', 'Pothole in cycle lane', 'Pothole on busy pavement', 'Large pothole', 'Sinking manhole'],
+ 'Street lighting' => ['Faulty light', 'Street light not working', 'Lights out in tunnel', 'Light not coming on', 'Light not going off'],
+ 'Graffiti' => ['Graffiti', 'Graffiti', 'Offensive graffiti', 'Graffiti on the bridge', 'Remove graffiti'],
+ 'Other' => ['Loose drain cover', 'Flytipping on country lane', 'Vehicle blocking footpath', 'Hedge encroaching pavement', 'Full litter bins'],
+);
+my $postcode = mySociety::MaPit::call('area/example_postcode', $opt->area_id);
+$postcode = mySociety::MaPit::call('postcode', $postcode);
+
+my $cobrand = 'default';
+foreach (FixMyStreet::Cobrand->available_cobrand_classes) {
+ my $sub = $_->{class} && $_->{class}->can('council_id');
+ if ($sub && &$sub == $opt->area_id) {
+ $cobrand = $_->{class}->moniker;
+ last;
+ }
+}
+
+my $num = 10;
+say "Created $num problems around '$postcode->{postcode}' in cobrand '$cobrand'";
+my $inaccurate_km = 0.01;
+my $confirmed = DateTime->today->subtract(days => 1)->add(hours => 8);
+my $problems = [];
+for (1..$num) {
+ $confirmed->add(seconds => rand(7000));
+ my $category = $categories->[int(rand(@$categories))];
+ my $titles = $titles{$category};
+ push @$problems, FixMyStreet::DB::Factory::Problem->create({
+ body => $body,
+ user => $user,
+ postcode => $postcode->{postcode},
+ latitude => $postcode->{wgs84_lat} + rand($inaccurate_km) - $inaccurate_km / 2,
+ longitude => $postcode->{wgs84_lon} + rand($inaccurate_km) - $inaccurate_km / 2,
+ category => $category,
+ cobrand => $cobrand,
+ title => $titles->[int(rand(@$titles))],
+ detail => 'The details of the report would be here, provided by the user, including exact location and how long it has been here.',
+ confirmed => DateTime::Format::Pg->format_datetime($confirmed),
+ });
+}
+
+# Comment
+
+my $updates = [];
+for (1..$num) {
+ $confirmed->add(seconds => rand(1000));
+ push @$updates, FixMyStreet::DB::Factory::Comment->create({
+ problem => $problems->[int(rand(@$problems))],
+ user => $user,
+ text => 'This is an update on this problem, perhaps providing further relevant information or letting everyone know it is being worked on or fixed.',
+ confirmed => DateTime::Format::Pg->format_datetime($confirmed),
+ });
+}
+say "Created $num updates on problems " . join(', ', map { $_->problem_id } @$updates);
diff --git a/cpanfile b/cpanfile
index 569136f84..6c449a479 100644
--- a/cpanfile
+++ b/cpanfile
@@ -42,6 +42,7 @@ requires 'DBD::Pg', '2.9.2';
requires 'DBI';
requires 'DBIx::Class::EncodedColumn', '0.00013';
requires 'DBIx::Class::EncodedColumn::Crypt::Eksblowfish::Bcrypt';
+requires 'DBIx::Class::Factory';
requires 'DBIx::Class::FilterColumn';
requires 'DBIx::Class::InflateColumn::DateTime';
requires 'DBIx::Class::ResultSet';
diff --git a/cpanfile.snapshot b/cpanfile.snapshot
index 4c3098bdb..0f475c659 100644
--- a/cpanfile.snapshot
+++ b/cpanfile.snapshot
@@ -63,6 +63,18 @@ DISTRIBUTIONS
Sub::Exporter::Progressive 0.001006
Test::More 0.88
Variable::Magic 0.48
+ B-Hooks-OP-Check-0.21
+ pathname: E/ET/ETHER/B-Hooks-OP-Check-0.21.tar.gz
+ provides:
+ B::Hooks::OP::Check 0.21
+ requirements:
+ DynaLoader 0
+ ExtUtils::Depends 0.302
+ ExtUtils::MakeMaker 0
+ parent 0
+ perl 5.008001
+ strict 0
+ warnings 0
CGI-4.28
pathname: L/LE/LEEJO/CGI-4.28.tar.gz
provides:
@@ -1236,6 +1248,19 @@ DISTRIBUTIONS
File::Temp 0
Sub::Name 0.04
Test::More 0
+ DBIx-Class-Factory-0.04
+ pathname: P/PU/PUSHTAEV/DBIx-Class-Factory-0.04.tar.gz
+ provides:
+ DBIx::Class::Factory 0.04
+ DBIx::Class::Factory::Fields undef
+ requirements:
+ DBIx::Class 0
+ ExtUtils::MakeMaker 6.36
+ SQL::Translator 0
+ Test::Deep 0
+ Test::More 0
+ strict 0
+ warnings 0
DBIx-Class-IntrospectableM2M-0.001001
pathname: G/GR/GRODITI/DBIx-Class-IntrospectableM2M-0.001001.tar.gz
provides:
@@ -2797,6 +2822,16 @@ DISTRIBUTIONS
Capture::Tiny 0
ExtUtils::MakeMaker 0
File::Basename 0
+ ExtUtils-Depends-0.405
+ pathname: X/XA/XAOC/ExtUtils-Depends-0.405.tar.gz
+ provides:
+ ExtUtils::Depends 0.405
+ requirements:
+ Data::Dumper 0
+ ExtUtils::MakeMaker 0
+ File::Spec 0
+ IO::File 0
+ perl 5.006
ExtUtils-Helpers-0.022
pathname: L/LE/LEONT/ExtUtils-Helpers-0.022.tar.gz
provides:
@@ -3365,6 +3400,16 @@ DISTRIBUTIONS
File::Spec 0.8
Module::Build 0.4
Test::More 0.80
+ Import-Into-1.002005
+ pathname: H/HA/HAARG/Import-Into-1.002005.tar.gz
+ provides:
+ Import::Into 1.002005
+ requirements:
+ ExtUtils::MakeMaker 0
+ Module::Runtime 0
+ perl 5.006
+ strict 0
+ warnings 0
JSON-2.59
pathname: M/MA/MAKAMAKA/JSON-2.59.tar.gz
provides:
@@ -3429,6 +3474,16 @@ DISTRIBUTIONS
Mozilla::CA 20110101
Net::HTTPS 6
perl 5.008001
+ Lexical-SealRequireHints-0.010
+ pathname: Z/ZE/ZEFRAM/Lexical-SealRequireHints-0.010.tar.gz
+ provides:
+ Lexical::SealRequireHints 0.010
+ requirements:
+ Module::Build 0
+ Test::More 0.41
+ perl 5.006
+ strict 0
+ warnings 0
Lingua-EN-FindNumber-1.2
pathname: T/TM/TMTM/Lingua-EN-FindNumber-1.2.tar.gz
provides:
@@ -4604,6 +4659,16 @@ DISTRIBUTIONS
constant 0
strict 0
warnings 0
+ Package-Variant-1.003002
+ pathname: M/MS/MSTROUT/Package-Variant-1.003002.tar.gz
+ provides:
+ Package::Variant 1.003002
+ requirements:
+ Carp 0
+ Import::Into 1.000000
+ Module::Runtime 0.013
+ perl 5.006
+ strictures 2.000000
PadWalker-2.2
pathname: R/RO/ROBIN/PadWalker-2.2.tar.gz
provides:
@@ -4680,6 +4745,31 @@ DISTRIBUTIONS
JSON::PP 2.27200
Test::More 0.47
strict 0
+ Parse-RecDescent-1.967015
+ pathname: J/JT/JTBRAUN/Parse-RecDescent-1.967015.tar.gz
+ provides:
+ Parse::RecDescent 1.967015
+ Parse::RecDescent::Action 1.967015
+ Parse::RecDescent::ColCounter 1.967015
+ Parse::RecDescent::Directive 1.967015
+ Parse::RecDescent::Error 1.967015
+ Parse::RecDescent::Expectation 1.967015
+ Parse::RecDescent::InterpLit 1.967015
+ Parse::RecDescent::LineCounter 1.967015
+ Parse::RecDescent::Literal 1.967015
+ Parse::RecDescent::OffsetCounter 1.967015
+ Parse::RecDescent::Operator 1.967015
+ Parse::RecDescent::Production 1.967015
+ Parse::RecDescent::Repetition 1.967015
+ Parse::RecDescent::Result 1.967015
+ Parse::RecDescent::Rule 1.967015
+ Parse::RecDescent::Subrule 1.967015
+ Parse::RecDescent::Token 1.967015
+ Parse::RecDescent::UncondReject 1.967015
+ requirements:
+ ExtUtils::MakeMaker 6.5702
+ Test::More 0
+ Text::Balanced 1.95
Path-Class-0.31
pathname: K/KW/KWILLIAMS/Path-Class-0.31.tar.gz
provides:
@@ -5089,6 +5179,111 @@ DISTRIBUTIONS
Test::More 0.92
Test::Warn 0
perl 5.006002
+ SQL-Translator-0.11021
+ pathname: I/IL/ILMARI/SQL-Translator-0.11021.tar.gz
+ provides:
+ Parse::RecDescent::SQL::Translator::Parser::DB2::Grammar undef
+ SQL::Translator 0.11021
+ SQL::Translator::Diff undef
+ SQL::Translator::Filter::DefaultExtra 1.59
+ SQL::Translator::Filter::Globals 1.59
+ SQL::Translator::Filter::Names 1.59
+ SQL::Translator::Generator::DDL::MySQL undef
+ SQL::Translator::Generator::DDL::PostgreSQL undef
+ SQL::Translator::Generator::DDL::SQLServer undef
+ SQL::Translator::Generator::DDL::SQLite undef
+ SQL::Translator::Generator::Role::DDL undef
+ SQL::Translator::Generator::Role::Quote undef
+ SQL::Translator::Parser 1.60
+ SQL::Translator::Parser::Access 1.59
+ SQL::Translator::Parser::DB2 undef
+ SQL::Translator::Parser::DB2::Grammar undef
+ SQL::Translator::Parser::DBI 1.59
+ SQL::Translator::Parser::DBI::DB2 undef
+ SQL::Translator::Parser::DBI::MySQL 1.59
+ SQL::Translator::Parser::DBI::Oracle 1.59
+ SQL::Translator::Parser::DBI::PostgreSQL 1.59
+ SQL::Translator::Parser::DBI::SQLServer 1.59
+ SQL::Translator::Parser::DBI::SQLite 1.59
+ SQL::Translator::Parser::DBI::Sybase 1.59
+ SQL::Translator::Parser::Excel 1.59
+ SQL::Translator::Parser::JSON 1.00
+ SQL::Translator::Parser::MySQL 1.59
+ SQL::Translator::Parser::Oracle 1.59
+ SQL::Translator::Parser::PostgreSQL 1.59
+ SQL::Translator::Parser::SQLServer 1.59
+ SQL::Translator::Parser::SQLite 1.59
+ SQL::Translator::Parser::Storable 1.59
+ SQL::Translator::Parser::Sybase 1.59
+ SQL::Translator::Parser::XML 1.59
+ SQL::Translator::Parser::XML::SQLFairy 1.59
+ SQL::Translator::Parser::YAML 1.59
+ SQL::Translator::Parser::xSV 1.59
+ SQL::Translator::Producer 1.59
+ SQL::Translator::Producer::ClassDBI 1.59
+ SQL::Translator::Producer::DB2 1.59
+ SQL::Translator::Producer::DiaUml 1.59
+ SQL::Translator::Producer::Diagram 1.59
+ SQL::Translator::Producer::Dumper 1.59
+ SQL::Translator::Producer::GraphViz 1.59
+ SQL::Translator::Producer::HTML 1.59
+ SQL::Translator::Producer::JSON 1.00
+ SQL::Translator::Producer::Latex 1.59
+ SQL::Translator::Producer::MySQL 1.59
+ SQL::Translator::Producer::Oracle 1.59
+ SQL::Translator::Producer::POD 1.59
+ SQL::Translator::Producer::PostgreSQL 1.59
+ SQL::Translator::Producer::SQLServer 1.59
+ SQL::Translator::Producer::SQLite 1.59
+ SQL::Translator::Producer::Storable 1.59
+ SQL::Translator::Producer::Sybase 1.59
+ SQL::Translator::Producer::TT::Base 1.59
+ SQL::Translator::Producer::TT::Table 1.59
+ SQL::Translator::Producer::TTSchema 1.59
+ SQL::Translator::Producer::XML 1.59
+ SQL::Translator::Producer::XML::SQLFairy 1.59
+ SQL::Translator::Producer::YAML 1.59
+ SQL::Translator::Role::BuildArgs undef
+ SQL::Translator::Role::Debug undef
+ SQL::Translator::Role::Error undef
+ SQL::Translator::Role::ListAttr undef
+ SQL::Translator::Schema 1.59
+ SQL::Translator::Schema::Constants 1.59
+ SQL::Translator::Schema::Constraint 1.59
+ SQL::Translator::Schema::Field 1.59
+ SQL::Translator::Schema::Index 1.59
+ SQL::Translator::Schema::Object 1.59
+ SQL::Translator::Schema::Procedure 1.59
+ SQL::Translator::Schema::Role::Compare undef
+ SQL::Translator::Schema::Role::Extra undef
+ SQL::Translator::Schema::Table 1.59
+ SQL::Translator::Schema::Trigger 1.59
+ SQL::Translator::Schema::View 1.59
+ SQL::Translator::Types undef
+ SQL::Translator::Utils 1.59
+ SQL::Translator::Utils::Error 1.59
+ Test::SQL::Translator 1.59
+ requirements:
+ Carp::Clan 0
+ DBI 1.54
+ Digest::SHA 0
+ ExtUtils::MakeMaker 6.59
+ File::ShareDir 1.0
+ JSON 2.0
+ List::MoreUtils 0.09
+ Moo 1.000003
+ Package::Variant 1.001001
+ Parse::RecDescent 1.967009
+ Scalar::Util 0
+ Sub::Quote 0
+ Test::Differences 0
+ Test::Exception 0.31
+ Test::More 0.88
+ Text::ParseWords 0
+ Try::Tiny 0.04
+ XML::Writer 0.500
+ YAML 0.66
+ perl 5.008001
SUPER-1.20141117
pathname: C/CH/CHROMATIC/SUPER-1.20141117.tar.gz
provides:
@@ -6344,6 +6539,14 @@ DISTRIBUTIONS
XML::NamespaceSupport 1.04
XML::SAX 0.15
XML::SAX::Expat 0
+ XML-Writer-0.625
+ pathname: J/JO/JOSEPHW/XML-Writer-0.625.tar.gz
+ provides:
+ XML::Writer 0.625
+ XML::Writer::_PrintChecker 0.625
+ XML::Writer::_String 0.625
+ requirements:
+ ExtUtils::MakeMaker 0
XML-XPathEngine-0.13
pathname: M/MI/MIROD/XML-XPathEngine-0.13.tar.gz
provides:
@@ -6435,6 +6638,18 @@ DISTRIBUTIONS
constant 0
if 0
overload 0
+ bareword-filehandles-0.005
+ pathname: I/IL/ILMARI/bareword-filehandles-0.005.tar.gz
+ provides:
+ bareword::filehandles 0.005
+ requirements:
+ B::Hooks::OP::Check 0
+ ExtUtils::Depends 0
+ ExtUtils::MakeMaker 0
+ Lexical::SealRequireHints 0
+ Test::More 0.88
+ XSLoader 0
+ perl 5.008001
strict 0
warnings 0
gettext-1.05
@@ -6443,6 +6658,24 @@ DISTRIBUTIONS
Locale::gettext 1.05
requirements:
ExtUtils::MakeMaker 0
+ indirect-0.37
+ pathname: V/VP/VPIT/indirect-0.37.tar.gz
+ provides:
+ indirect 0.37
+ requirements:
+ Carp 0
+ Config 0
+ ExtUtils::MakeMaker 0
+ File::Spec 0
+ IO::Handle 0
+ IO::Select 0
+ IPC::Open3 0
+ POSIX 0
+ Socket 0
+ Test::More 0
+ XSLoader 0
+ lib 0
+ perl 5.008001
libnet-3.10
pathname: S/SH/SHAY/libnet-3.10.tar.gz
provides:
@@ -6552,6 +6785,21 @@ DISTRIBUTIONS
ExtUtils::MakeMaker 6.59
Module::Build 0.36
perl 5.008001
+ multidimensional-0.013
+ pathname: I/IL/ILMARI/multidimensional-0.013.tar.gz
+ provides:
+ multidimensional 0.013
+ requirements:
+ B::Hooks::OP::Check 0.19
+ CPAN::Meta 2.112580
+ ExtUtils::Depends 0
+ ExtUtils::MakeMaker 0
+ Lexical::SealRequireHints 0.005
+ Test::More 0.88
+ XSLoader 0
+ perl 5.008
+ strict 0
+ warnings 0
namespace-autoclean-0.13
pathname: B/BO/BOBTFISH/namespace-autoclean-0.13.tar.gz
provides:
@@ -6576,12 +6824,16 @@ DISTRIBUTIONS
ExtUtils::CBuilder 0.27
Package::Stash 0.23
Test::More 0.88
- strictures-1.004004
- pathname: E/ET/ETHER/strictures-1.004004.tar.gz
+ strictures-2.000003
+ pathname: H/HA/HAARG/strictures-2.000003.tar.gz
provides:
- strictures 1.004004
+ strictures 2.000003
+ strictures::extra undef
requirements:
- ExtUtils::MakeMaker 0
+ bareword::filehandles 0
+ indirect 0
+ multidimensional 0
+ perl 5.006
version-0.9902
pathname: J/JP/JPEACOCK/version-0.9902.tar.gz
provides:
diff --git a/perllib/FixMyStreet/DB/Factories.pm b/perllib/FixMyStreet/DB/Factories.pm
new file mode 100644
index 000000000..e877ffd9f
--- /dev/null
+++ b/perllib/FixMyStreet/DB/Factories.pm
@@ -0,0 +1,155 @@
+use FixMyStreet::DB;
+
+package FixMyStreet::DB::Factory::Base;
+
+use parent "DBIx::Class::Factory";
+
+sub find_or_create {
+ my ($class, $fields) = @_;
+ my $key_field = $class->key_field;
+ my $id = $class->get_fields($fields)->{$key_field};
+ my $rs = $class->_class_data->{resultset};
+ my $obj = $rs->find({ $key_field => $id });
+ return $obj if $obj;
+ return $class->create($fields);
+}
+
+#######################
+
+package FixMyStreet::DB::Factory::Problem;
+
+use parent "DBIx::Class::Factory";
+
+__PACKAGE__->resultset(FixMyStreet::DB->resultset("Problem"));
+
+__PACKAGE__->exclude(['body']);
+
+__PACKAGE__->fields({
+ postcode => '',
+ title => __PACKAGE__->seq(sub { 'Title #' . (shift()+1) }),
+ detail => __PACKAGE__->seq(sub { 'Detail #' . (shift()+1) }),
+ name => __PACKAGE__->callback(sub { shift->get('user')->name }),
+ bodies_str => __PACKAGE__->callback(sub { shift->get('body')->id }),
+ confirmed => \'current_timestamp',
+ whensent => \'current_timestamp',
+ state => 'confirmed',
+ cobrand => 'default',
+ latitude => 0,
+ longitude => 0,
+ areas => '',
+ used_map => 't',
+ anonymous => 'f',
+ category => 'Other',
+});
+
+#######################
+
+# This currently creates special 'UK' bodies, with ID == MapIt area_id.
+# We should try and end this, it is just confusing.
+package FixMyStreet::DB::Factory::Body;
+
+use parent -norequire, "FixMyStreet::DB::Factory::Base";
+use mySociety::MaPit;
+
+__PACKAGE__->resultset(FixMyStreet::DB->resultset("Body"));
+
+__PACKAGE__->exclude(['area_id', 'categories']);
+
+__PACKAGE__->fields({
+ id => __PACKAGE__->callback(sub {
+ my $area_id = shift->get('area_id');
+ $area_id;
+ }),
+ name => __PACKAGE__->callback(sub {
+ my $area_id = shift->get('area_id');
+ my $area = mySociety::MaPit::call('area', $area_id);
+ $area->{name};
+ }),
+ body_areas => __PACKAGE__->callback(sub {
+ my $area_id = shift->get('area_id');
+ [ { area_id => $area_id } ]
+ }),
+ contacts => __PACKAGE__->callback(sub {
+ my $categories = shift->get('categories');
+ push @$categories, 'Other' unless @$categories;
+ [ map { FixMyStreet::DB::Factory::Contact->get_fields({ category => $_ }) } @$categories ];
+ }),
+});
+
+sub key_field { 'id' }
+
+#######################
+
+package FixMyStreet::DB::Factory::Contact;
+
+use parent "DBIx::Class::Factory";
+
+__PACKAGE__->resultset(FixMyStreet::DB->resultset("Contact"));
+
+__PACKAGE__->fields({
+ body_id => __PACKAGE__->callback(sub {
+ my $fields = shift;
+ return $fields->get('body')->id if $fields->get('body');
+ }),
+ category => 'Other',
+ email => __PACKAGE__->callback(sub {
+ my $category = shift->get('category');
+ (my $email = lc $_) =~ s/ /-/g;
+ lc $category . '@example.org';
+ }),
+ confirmed => 1,
+ deleted => 0,
+ editor => 'Factory',
+ whenedited => \'current_timestamp',
+ note => 'Created by factory',
+});
+
+#######################
+
+package FixMyStreet::DB::Factory::Comment;
+
+use parent "DBIx::Class::Factory";
+
+__PACKAGE__->resultset(FixMyStreet::DB->resultset("Comment"));
+
+__PACKAGE__->fields({
+ anonymous => 'f',
+ name => __PACKAGE__->callback(sub { shift->get('user')->name }),
+ text => __PACKAGE__->seq(sub { 'Comment #' . (shift()+1) }),
+ confirmed => \'current_timestamp',
+ state => 'confirmed',
+ cobrand => 'default',
+ mark_fixed => 0,
+});
+
+#######################
+
+package FixMyStreet::DB::Factory::User;
+
+use parent -norequire, "FixMyStreet::DB::Factory::Base";
+
+__PACKAGE__->resultset(FixMyStreet::DB->resultset("User"));
+
+__PACKAGE__->exclude(['body', 'permissions']);
+
+__PACKAGE__->fields({
+ name => 'User',
+ email => 'user@example.org',
+ password => 'password',
+ from_body => __PACKAGE__->callback(sub {
+ my $fields = shift;
+ if (my $body = $fields->get('body')) {
+ return $body->id;
+ }
+ }),
+ user_body_permissions => __PACKAGE__->callback(sub {
+ my $fields = shift;
+ my $body = $fields->get('body');
+ my $permissions = $fields->get('permissions');
+ [ map { { body_id => $body->id, permission_type => $_ } } @$permissions ];
+ }),
+});
+
+sub key_field { 'email' }
+
+1;