Finishing off CSV import functionality
This commit is contained in:
parent
423c68aca2
commit
91677034ca
6 changed files with 149 additions and 31 deletions
|
@ -39,6 +39,7 @@ sub startup {
|
||||||
$self->plugin('Pear::LocalLoop::Plugin::BootstrapPagination', { bootstrap4 => 1 } );
|
$self->plugin('Pear::LocalLoop::Plugin::BootstrapPagination', { bootstrap4 => 1 } );
|
||||||
$self->plugin('Pear::LocalLoop::Plugin::Validators');
|
$self->plugin('Pear::LocalLoop::Plugin::Validators');
|
||||||
$self->plugin('Pear::LocalLoop::Plugin::Datetime');
|
$self->plugin('Pear::LocalLoop::Plugin::Datetime');
|
||||||
|
$self->plugin('Pear::LocalLoop::Plugin::Currency');
|
||||||
$self->plugin('Pear::LocalLoop::Plugin::Postcodes');
|
$self->plugin('Pear::LocalLoop::Plugin::Postcodes');
|
||||||
$self->plugin('Pear::LocalLoop::Plugin::TemplateHelpers');
|
$self->plugin('Pear::LocalLoop::Plugin::TemplateHelpers');
|
||||||
|
|
||||||
|
@ -209,6 +210,7 @@ sub startup {
|
||||||
$admin_routes->get('/import/:set_id/org')->to('admin-import#get_org');
|
$admin_routes->get('/import/:set_id/org')->to('admin-import#get_org');
|
||||||
|
|
||||||
$admin_routes->get('/import/:set_id/ignore/:value_id')->to('admin-import#ignore_value');
|
$admin_routes->get('/import/:set_id/ignore/:value_id')->to('admin-import#ignore_value');
|
||||||
|
$admin_routes->get('/import/:set_id/import')->to('admin-import#run_import');
|
||||||
# my $user_routes = $r->under('/')->to('root#under');
|
# my $user_routes = $r->under('/')->to('root#under');
|
||||||
|
|
||||||
# $user_routes->get('/home')->to('root#home');
|
# $user_routes->get('/home')->to('root#home');
|
||||||
|
|
|
@ -28,11 +28,12 @@ sub list {
|
||||||
my $set_id = $c->param('set_id');
|
my $set_id = $c->param('set_id');
|
||||||
|
|
||||||
my $include_ignored = $c->param('ignored');
|
my $include_ignored = $c->param('ignored');
|
||||||
|
my $include_imported = $c->param('imported');
|
||||||
|
|
||||||
my $import_set = $c->result_set->find($set_id);
|
my $import_set = $c->result_set->find($set_id);
|
||||||
my $import_value_rs = $c->result_set->get_values($set_id, $include_ignored);
|
my $import_value_rs = $c->result_set->get_values($set_id, $include_ignored, $include_imported);
|
||||||
my $import_users_rs = $c->result_set->get_users($set_id, $include_ignored);
|
my $import_users_rs = $c->result_set->get_users($set_id, $include_ignored, $include_imported);
|
||||||
my $import_org_rs = $c->result_set->get_orgs($set_id, $include_ignored);
|
my $import_org_rs = $c->result_set->get_orgs($set_id, $include_ignored, $include_imported);
|
||||||
my $import_lookup_rs = $c->result_set->get_lookups($set_id);
|
my $import_lookup_rs = $c->result_set->get_lookups($set_id);
|
||||||
|
|
||||||
$c->stash(
|
$c->stash(
|
||||||
|
@ -270,4 +271,55 @@ sub ignore_value {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub run_import {
|
||||||
|
my $c = shift;
|
||||||
|
my $set_id = $c->param('set_id');
|
||||||
|
|
||||||
|
my $set_result = $c->result_set->find($set_id);
|
||||||
|
unless ( defined $set_result ) {
|
||||||
|
$c->flash( error => "Set does not exist" );
|
||||||
|
return $c->redirect_to( '/admin/import' );
|
||||||
|
}
|
||||||
|
|
||||||
|
my $import_value_rs = $c->result_set->get_values($set_id, undef, undef);
|
||||||
|
my $import_lookup = $c->result_set->get_lookups($set_id);
|
||||||
|
my $entity_rs = $c->schema->resultset('Entity');
|
||||||
|
|
||||||
|
$c->schema->txn_do(
|
||||||
|
sub {
|
||||||
|
for my $value_result ( $import_value_rs->all ) {
|
||||||
|
my $user_lookup = $import_lookup->{ $value_result->user_name };
|
||||||
|
my $org_lookup = $import_lookup->{ $value_result->org_name };
|
||||||
|
my $value_lookup = $c->parse_currency( $value_result->purchase_value );
|
||||||
|
|
||||||
|
if ( defined $user_lookup && defined $org_lookup && $value_lookup ) {
|
||||||
|
my $user_entity = $entity_rs->find($user_lookup->{entity_id});
|
||||||
|
my $org_entity = $entity_rs->find($org_lookup->{entity_id});
|
||||||
|
my $distance = $c->get_distance_from_coords( $user_entity->type_object, $org_entity->type_object );
|
||||||
|
my $transaction = $c->schema->resultset('Transaction')->create(
|
||||||
|
{
|
||||||
|
buyer => $user_entity,
|
||||||
|
seller => $org_entity,
|
||||||
|
value => $value_lookup * 100000,
|
||||||
|
purchase_time => $value_result->purchase_date,
|
||||||
|
distance => $distance,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$value_result->update({transaction_id => $transaction->id });
|
||||||
|
} else {
|
||||||
|
$c->app->log->warn("Failed value import for value id [" . $value_result->id . "], ignoring");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$c->flash( success => "Import completed for ready values" );
|
||||||
|
my $referer = $c->req->headers->header('Referer');
|
||||||
|
return $c->redirect_to(
|
||||||
|
defined $referer
|
||||||
|
? $c->url_for($referer)->path_query
|
||||||
|
: '/admin/import/' . $set_id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
17
lib/Pear/LocalLoop/Plugin/Currency.pm
Normal file
17
lib/Pear/LocalLoop/Plugin/Currency.pm
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
package Pear::LocalLoop::Plugin::Currency;
|
||||||
|
use Mojo::Base 'Mojolicious::Plugin';
|
||||||
|
|
||||||
|
sub register {
|
||||||
|
my ( $plugin, $app, $cong ) = @_;
|
||||||
|
|
||||||
|
$app->helper( parse_currency => sub {
|
||||||
|
my ( $c, $currency_string ) = @_;
|
||||||
|
my $value;
|
||||||
|
if ( $currency_string =~ /^£([\d.]+)/ ) {
|
||||||
|
$value = $1 * 1;
|
||||||
|
}
|
||||||
|
return $value;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
1;
|
|
@ -9,10 +9,14 @@ sub get_values {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $id = shift;
|
my $id = shift;
|
||||||
my $include_ignored = shift;
|
my $include_ignored = shift;
|
||||||
|
my $include_imported = shift;
|
||||||
|
|
||||||
return $self->find($id)->search_related(
|
return $self->find($id)->search_related(
|
||||||
'values',
|
'values',
|
||||||
( $include_ignored ? {} : { ignore_value => 0 } ),
|
{
|
||||||
|
( $include_ignored ? () : ( ignore_value => 0 ) ),
|
||||||
|
( $include_imported ? () : ( transaction_id => undef ) ),
|
||||||
|
},
|
||||||
{
|
{
|
||||||
order_by => { '-asc' => 'id' },
|
order_by => { '-asc' => 'id' },
|
||||||
},
|
},
|
||||||
|
@ -21,10 +25,8 @@ sub get_values {
|
||||||
|
|
||||||
sub get_users {
|
sub get_users {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $id = shift;
|
|
||||||
my $include_ignored = shift;
|
|
||||||
|
|
||||||
return $self->get_values($id, $include_ignored)->search({},
|
return $self->get_values(@_)->search({},
|
||||||
{
|
{
|
||||||
group_by => 'user_name',
|
group_by => 'user_name',
|
||||||
},
|
},
|
||||||
|
@ -33,10 +35,8 @@ sub get_users {
|
||||||
|
|
||||||
sub get_orgs {
|
sub get_orgs {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $id = shift;
|
|
||||||
my $include_ignored = shift;
|
|
||||||
|
|
||||||
return $self->get_values($id, $include_ignored)->search({},
|
return $self->get_values(@_)->search({},
|
||||||
{
|
{
|
||||||
group_by => 'org_name',
|
group_by => 'org_name',
|
||||||
},
|
},
|
||||||
|
@ -47,13 +47,23 @@ sub get_lookups {
|
||||||
my $self = shift;
|
my $self = shift;
|
||||||
my $id = shift;
|
my $id = shift;
|
||||||
|
|
||||||
return $self->find($id)->search_related(
|
my $lookup_rs = $self->find($id)->search_related(
|
||||||
'lookups',
|
'lookups',
|
||||||
undef,
|
undef,
|
||||||
{
|
{
|
||||||
order_by => { '-asc' => 'id' },
|
prefetch => { entity => [ qw/ organisation customer / ] },
|
||||||
|
order_by => { '-asc' => 'me.id' },
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
my $lookup_map = {
|
||||||
|
map {
|
||||||
|
$_->name => {
|
||||||
|
entity_id => $_->entity->id,
|
||||||
|
name => $_->entity->name,
|
||||||
|
},
|
||||||
|
} $lookup_rs->all
|
||||||
|
};
|
||||||
|
return $lookup_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
|
|
|
@ -12,22 +12,31 @@
|
||||||
</div>
|
</div>
|
||||||
% }
|
% }
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12">
|
<div class="col-12 mb-3">
|
||||||
<div class="card">
|
<h3 class="float-left">CSV Import</h3>
|
||||||
<h3 class="card-header">
|
<a href="<%= url_for . '/add' %>" class="btn btn-success float-right">Import Data</a>
|
||||||
CSV Import
|
|
||||||
<a href="<%= url_for . '/add' %>" class="btn btn-success" style="float: right">Import Data</a>
|
|
||||||
</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
% for my $import ( $import_rs->all ) {
|
% for my $import ( $import_rs->all ) {
|
||||||
|
% my $total = $import_rs->get_values( $import->id, 1, 1 )->count;
|
||||||
|
% my $unimported = $import_rs->get_values( $import->id, undef, undef )->count;
|
||||||
|
% my $with_ignored = $import_rs->get_values( $import->id, 1, undef )->count;
|
||||||
|
% my $with_imported = $import_rs->get_values( $import->id, undef, 1 )->count;
|
||||||
|
% my $ignored_total = $with_ignored - $unimported;
|
||||||
|
% my $imported_total = $with_imported - $unimported;
|
||||||
<div class="col col-md-4 mb-3">
|
<div class="col col-md-4 mb-3">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header text-white <%= $unimported ? 'bg-danger' : 'bg-success' %>">
|
||||||
<span class="font-bold"><%= $import->id %></span>
|
<span><%= format_human_datetime $import->date %></span>
|
||||||
%= format_human_datetime $import->date;
|
<span class=" float-right font-bold"><%= $import->id %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
|
<span>Unimported: <%= $unimported %></span>
|
||||||
|
<br>
|
||||||
|
<span>Ignored: <%= $ignored_total %></span>
|
||||||
|
<br>
|
||||||
|
<span>Imported: <%= $imported_total %></span>
|
||||||
|
<br>
|
||||||
|
<span>Total: <%= $total %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-footer text-right">
|
<div class="card-footer text-right">
|
||||||
<a href="<%= url_for . '/' . $import->id %>" class="card-link">
|
<a href="<%= url_for . '/' . $import->id %>" class="card-link">
|
||||||
|
|
|
@ -28,8 +28,8 @@
|
||||||
%= $user->user_name
|
%= $user->user_name
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
% if ( my $lookup = $import_lookup_rs->find({ name => $user->user_name }) ) {
|
% if ( defined $import_lookup_rs->{ $user->user_name } ) {
|
||||||
<span class="text-muted"><%= $lookup->entity->name %></span>
|
<span class="text-muted"><%= $import_lookup_rs->{ $user->user_name }->{name} %></span>
|
||||||
% } else {
|
% } else {
|
||||||
<span class="text-muted font-italic">Unassigned</span>
|
<span class="text-muted font-italic">Unassigned</span>
|
||||||
% }
|
% }
|
||||||
|
@ -59,8 +59,8 @@
|
||||||
%= $org->org_name
|
%= $org->org_name
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
% if ( my $lookup = $import_lookup_rs->find({ name => $org->org_name }) ) {
|
% if ( defined $import_lookup_rs->{ $org->org_name } ) {
|
||||||
<span class="text-muted"><%= $lookup->entity->name %></span>
|
<span class="text-muted"><%= $import_lookup_rs->{ $org->org_name }->{name} %></span>
|
||||||
% } else {
|
% } else {
|
||||||
<span class="text-muted font-italic">Unassigned</span>
|
<span class="text-muted font-italic">Unassigned</span>
|
||||||
% }
|
% }
|
||||||
|
@ -74,40 +74,65 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12 mb-3">
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<h3 class="card-header">
|
<h3 class="card-header">
|
||||||
%= format_human_datetime $import_set->date;
|
%= format_human_datetime $import_set->date;
|
||||||
<a href="<%= url_for->query({ignored => $c->param('ignored') ? 0 : 1 }) %>"
|
<a href="<%= url_for->query({ignored => $c->param('ignored') ? 0 : 1 }) %>"
|
||||||
class="btn btn-primary float-right">
|
class="btn btn-primary float-right">
|
||||||
Toggle show Ignored
|
<%= $c->param('ignored') ? 'Hide' : 'Show' %> Ignored
|
||||||
</a>
|
</a>
|
||||||
|
<a href="<%= url_for->query({imported => $c->param('imported') ? 0 : 1 }) %>"
|
||||||
|
class="btn btn-secondary float-right">
|
||||||
|
<%= $c->param('imported') ? 'Hide' : 'Show' %> Imported
|
||||||
|
</a>
|
||||||
|
|
||||||
</h3>
|
</h3>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
Content listed in original order of import
|
Content listed in original order of import
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group list-group-flush">
|
<div class="list-group list-group-flush">
|
||||||
% for my $import_value ( $import_value_rs->all ) {
|
% for my $import_value ( $import_value_rs->all ) {
|
||||||
|
% my $user_lookup = $import_lookup_rs->{ $import_value->user_name };
|
||||||
|
% my $purchase_lookup = parse_currency $import_value->purchase_value;
|
||||||
|
% my $org_lookup = $import_lookup_rs->{ $import_value->org_name };
|
||||||
<div class="list-group-item">
|
<div class="list-group-item">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<%= $import_value->user_name %>
|
<%= $import_value->user_name %>
|
||||||
|
% if ( defined $user_lookup ) {
|
||||||
|
<br>
|
||||||
|
<span class="text-muted"><%= $user_lookup->{name} %></span>
|
||||||
|
% }
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<%= format_human_datetime $import_value->purchase_date %>
|
<%= format_human_datetime $import_value->purchase_date %>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<%= $import_value->purchase_value %>
|
<%= $import_value->purchase_value %>
|
||||||
|
<br>
|
||||||
|
<span class="text-muted"><%= $purchase_lookup %></span>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-3">
|
<div class="col-3">
|
||||||
<%= $import_value->org_name %>
|
<%= $import_value->org_name %>
|
||||||
|
% if ( defined $org_lookup ) {
|
||||||
|
<br>
|
||||||
|
<span class="text-muted"><%= $org_lookup->{name} %></span>
|
||||||
|
% }
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
|
% if ( defined $import_value->transaction_id ) {
|
||||||
|
<button class="btn btn-primary">Imported</button>
|
||||||
|
% } else {
|
||||||
|
% if ( defined $user_lookup && defined $org_lookup && $purchase_lookup ) {
|
||||||
|
<button class="btn btn-success">Ready</button>
|
||||||
|
% }
|
||||||
% if ( $import_value->ignore_value ) {
|
% if ( $import_value->ignore_value ) {
|
||||||
<a href="<%= url_for . '/ignore/' . $import_value->id %>" class="btn btn-success">Un Ignore</a>
|
<a href="<%= url_for . '/ignore/' . $import_value->id %>" class="btn btn-success">Un Ignore</a>
|
||||||
% } else {
|
% } else {
|
||||||
<a href="<%= url_for . '/ignore/' . $import_value->id %>" class="btn btn-danger">Ignore</a>
|
<a href="<%= url_for . '/ignore/' . $import_value->id %>" class="btn btn-danger">Ignore</a>
|
||||||
% }
|
% }
|
||||||
|
% }
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -115,4 +140,7 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col-12">
|
||||||
|
<a href="<%= url_for . '/import' %>" class="btn btn-info float-right">Import Ready Items</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
Reference in a new issue