seedlot upload with accession synonyms. seedlot upload works to update existing seedlots
[sgn.git] / lib / SGN / Controller / AJAX / Trial.pm
blobe5e05dcda421d611c12ae82c8eed533570ac7731
2 =head1 NAME
4 SGN::Controller::AJAX::Trial - a REST controller class to provide the
5 backend for adding trials and viewing trials
7 =head1 DESCRIPTION
9 Creating, viewing and deleting trials
11 =head1 AUTHOR
13 Jeremy Edwards <jde22@cornell.edu>
16 =cut
18 package SGN::Controller::AJAX::Trial;
20 use Moose;
21 use Try::Tiny;
22 use Scalar::Util qw(looks_like_number);
23 use DateTime;
24 use File::Basename qw | basename dirname|;
25 use File::Copy;
26 use File::Slurp;
27 use File::Spec::Functions;
28 use Digest::MD5;
29 use List::MoreUtils qw /any /;
30 use Data::Dumper;
31 use CXGN::Trial;
32 use CXGN::Trial::TrialDesign;
33 use CXGN::Trial::TrialCreate;
34 use JSON -support_by_pp;
35 use SGN::View::Trial qw/design_layout_view design_info_view design_layout_map_view/;
36 use CXGN::Location::LocationLookup;
37 use CXGN::Stock::StockLookup;
38 use CXGN::Trial::TrialLayout;
39 use CXGN::BreedersToolbox::Projects;
40 use CXGN::BreedersToolbox::Delete;
41 use CXGN::UploadFile;
42 use CXGN::Trial::ParseUpload;
43 use CXGN::List::Transform;
44 use CXGN::List::Validate;
45 use SGN::Model::Cvterm;
46 use JSON;
47 use CXGN::BreedersToolbox::Accessions;
48 use CXGN::BreederSearch;
50 BEGIN { extends 'Catalyst::Controller::REST' }
52 __PACKAGE__->config(
53 default => 'application/json',
54 stash_key => 'rest',
55 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
58 has 'schema' => (
59 is => 'rw',
60 isa => 'DBIx::Class::Schema',
61 lazy_build => 1,
65 sub generate_experimental_design : Path('/ajax/trial/generate_experimental_design') : ActionClass('REST') { }
67 sub generate_experimental_design_POST : Args(0) {
68 my ($self, $c) = @_;
69 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
70 my $trial_design = CXGN::Trial::TrialDesign->new();
71 my %design;
72 my %design_info;
73 my $error;
74 my $project_name = $c->req->param('project_name');
75 my $project_description = $c->req->param('project_description');
76 my $year = $c->req->param('year');
77 my @stock_names;
78 my $design_layout_view_html;
79 my $design_info_view_html;
80 my $design_map_view;
81 if ($c->req->param('stock_list')) {
82 @stock_names = @{_parse_list_from_json($c->req->param('stock_list'))};
85 my $seedlot_hash_json = $c->req->param('seedlot_hash');
86 my @control_names;
87 if ($c->req->param('control_list')) {
88 @control_names = @{_parse_list_from_json($c->req->param('control_list'))};
91 my @control_names_crbd;
92 if ($c->req->param('control_list_crbd')) {
93 @control_names_crbd = @{_parse_list_from_json($c->req->param('control_list_crbd'))};
96 my $design_type = $c->req->param('design_type');
97 my $rep_count = $c->req->param('rep_count');
98 my $block_number = $c->req->param('block_number');
100 my $row_number = $c->req->param('row_number');
101 my $block_row_number=$c->req->param('row_number_per_block');
102 my $block_col_number=$c->req->param('col_number_per_block');
103 my $col_number =$c->req->param('col_number');
105 my $block_size = $c->req->param('block_size');
106 my $max_block_size = $c->req->param('max_block_size');
107 my $plot_prefix = $c->req->param('plot_prefix');
108 my $start_number = $c->req->param('start_number');
109 my $increment = $c->req->param('increment');
110 my $trial_location = $c->req->param('trial_location');
111 my $fieldmap_col_number = $c->req->param('fieldmap_col_number');
112 my $fieldmap_row_number = $c->req->param('fieldmap_row_number');
113 my $plot_layout_format = $c->req->param('plot_layout_format');
114 my @treatments = $c->req->param('treatments[]');
115 my $num_plants_per_plot = $c->req->param('num_plants_per_plot');
116 my $num_seed_per_plot = $c->req->param('num_seed_per_plot');
118 #if (!$num_seed_per_plot){
119 # $c->stash->{rest} = { error => "You need to provide number of seeds per plot so that your breeding material can be tracked."};
120 # return;
123 if ($design_type eq 'splitplot'){
124 if (scalar(@treatments)<1){
125 $c->stash->{rest} = { error => "You need to provide at least one treatment for a splitplot design."};
126 return;
128 if (!$num_plants_per_plot){
129 $c->stash->{rest} = { error => "You need to provide number of plants per treatment for a splitplot design."};
130 return;
132 if ($num_plants_per_plot <1){
133 $c->stash->{rest} = { error => "You need to provide number of plants per treatment for a splitplot design."};
134 return;
136 if (($num_plants_per_plot%(scalar(@treatments)))!=0){
137 $c->stash->{rest} = {error => "Number of plants per plot needs to divide evenly by the number of treatments. For example: if you have two treatments and there are 3 plants per treatment, that means you have 6 plants per plot." };
138 return;
142 my $row_in_design_number = $c->req->param('row_in_design_number');
143 my $col_in_design_number = $c->req->param('col_in_design_number');
144 my $no_of_rep_times = $c->req->param('no_of_rep_times');
145 my $no_of_block_sequence = $c->req->param('no_of_block_sequence');
146 my $unreplicated_accession_list = $c->req->param('unreplicated_accession_list');
147 my $replicated_accession_list = $c->req->param('replicated_accession_list');
148 my $no_of_sub_block_sequence = $c->req->param('no_of_sub_block_sequence');
150 my @replicated_accession;
151 if ($c->req->param('replicated_accession_list')) {
152 @replicated_accession = @{_parse_list_from_json($c->req->param('replicated_accession_list'))};
154 my $number_of_replicated_accession = scalar(@replicated_accession);
156 my @unreplicated_accession;
157 if ($c->req->param('unreplicated_accession_list')) {
158 @unreplicated_accession = @{_parse_list_from_json($c->req->param('unreplicated_accession_list'))};
160 my $number_of_unreplicated_accession = scalar(@unreplicated_accession);
163 my $greenhouse_num_plants = $c->req->param('greenhouse_num_plants');
164 my $use_same_layout = $c->req->param('use_same_layout');
165 my $number_of_checks = scalar(@control_names_crbd);
167 if ($design_type eq "RCBD" || $design_type eq "Alpha" || $design_type eq "CRD" || $design_type eq "Lattice") {
168 if (@control_names_crbd) {
169 @stock_names = (@stock_names, @control_names_crbd);
172 if($design_type eq "p-rep"){
173 @stock_names = (@replicated_accession, @unreplicated_accession);
175 #print STDERR Dumper(\@stock_names);
176 my $number_of_prep_accession = scalar(@stock_names);
177 my $p_rep_total_plots = $row_in_design_number * $col_in_design_number;
178 my $replicated_plots = $no_of_rep_times * $number_of_replicated_accession;
179 my $unreplicated_plots = scalar(@unreplicated_accession);
180 my $calculated_total_plot = $replicated_plots + $unreplicated_plots;
182 my @locations;
183 my $trial_locations;
184 my $multi_location;
186 try {
187 $multi_location = decode_json($trial_location);
188 foreach my $loc (@$multi_location) {
189 push @locations, $loc;
193 catch {
194 push @locations, $trial_location;
197 my $location_number = scalar(@locations);
199 #print STDERR Dumper(@locations);
201 if (!$c->user()) {
202 $c->stash->{rest} = {error => "You need to be logged in to add a trial" };
203 return;
206 if (!any { $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) { #user must have privileges to add a trial
207 $c->stash->{rest} = {error => "You have insufficient privileges to add a trial." };
208 return;
210 #print "TOTAL PLOTS $p_rep_total_plots AND CALCULATED PLOTS $calculated_total_plot\n";
211 if($p_rep_total_plots != $calculated_total_plot){
212 $c->stash->{rest} = {error => "Treatment repeats do not equal number of plots in design" };
213 return;
216 my @design_array;
217 my @design_layout_view_html_array;
219 foreach $trial_locations (@locations) {
221 my $trial_name = $c->req->param('project_name');
222 my $geolocation_lookup = CXGN::Location::LocationLookup->new(schema => $schema);
224 $geolocation_lookup->set_location_name($trial_locations);
225 #print STDERR Dumper(\$geolocation_lookup);
226 if (!$geolocation_lookup->get_geolocation()){
227 $c->stash->{rest} = { error => "Trial location not found" };
228 return;
233 if (scalar(@locations) > 1) {
234 $trial_name = $trial_name."_".$trial_locations;
237 $trial_design->set_trial_name($trial_name);
239 my $design_created = 0;
240 if ($use_same_layout) {
241 $design_created = 1;
244 if ($design_created) {
245 $trial_design->set_randomization_seed($design_created);
249 if (@stock_names) {
250 $trial_design->set_stock_list(\@stock_names);
251 $design_info{'number_of_stocks'} = scalar(@stock_names);
252 } else {
253 $c->stash->{rest} = {error => "No list of stocks supplied." };
254 return;
256 if ($seedlot_hash_json){
257 my $json = JSON->new();
258 $trial_design->set_seedlot_hash($json->decode($seedlot_hash_json));
260 if ($num_seed_per_plot){
261 $trial_design->set_num_seed_per_plot($num_seed_per_plot);
263 if (@control_names) {
264 $trial_design->set_control_list(\@control_names);
265 $design_info{'number_of_controls'} = scalar(@control_names);
267 if (@control_names_crbd) {
268 $trial_design->set_control_list_crbd(\@control_names_crbd);
269 $design_info{'number_of_controls_crbd'} = scalar(@control_names_crbd);
271 if ($start_number) {
272 $trial_design->set_plot_start_number($start_number);
273 } else {
274 $trial_design->clear_plot_start_number();
276 if ($increment) {
277 $trial_design->set_plot_number_increment($increment);
278 } else {
279 $trial_design->clear_plot_number_increment();
281 if ($plot_prefix) {
282 $trial_design->set_plot_name_prefix($plot_prefix);
284 if ($rep_count) {
285 $trial_design->set_number_of_reps($rep_count);
287 if ($block_number) {
288 $trial_design->set_number_of_blocks($block_number);
289 #$trial_design->set_number_of_blocks(8);
291 if($row_number){
292 $trial_design->set_number_of_rows($row_number);
293 #$trial_design->set_number_of_rows(9);
295 if($block_row_number){
296 $trial_design->set_block_row_numbers($block_row_number);
297 #$trial_design->set_number_of_rows(9);
299 if($block_col_number){
300 $trial_design->set_block_col_numbers($block_col_number);
301 #$trial_design->set_number_of_rows(9);
303 if($col_number){
304 $trial_design->set_number_of_cols($col_number);
305 #$trial_design->set_number_of_rows(9);
307 if ($block_size) {
308 $trial_design->set_block_size($block_size);
310 if ($max_block_size) {
311 $trial_design->set_maximum_block_size($max_block_size);
313 if ($greenhouse_num_plants) {
314 my $json = JSON->new();
315 $trial_design->set_greenhouse_num_plants($json->decode($greenhouse_num_plants));
317 if ($location_number) {
318 $design_info{'number_of_locations'} = $location_number;
320 if($number_of_checks){
321 $design_info{'number_of_checks'} = $number_of_checks;
323 if ($design_type) {
324 $trial_design->set_design_type($design_type);
325 $design_info{'design_type'} = $design_type;
326 } else {
327 $c->stash->{rest} = {error => "No design type supplied." };
328 return;
330 if (!$trial_design->has_design_type()) {
331 $c->stash->{rest} = {error => "Design type not supported." };
332 return;
334 if ($fieldmap_col_number) {
335 $trial_design->set_fieldmap_col_number($fieldmap_col_number);
337 if ($fieldmap_row_number) {
338 $trial_design->set_fieldmap_row_number($fieldmap_row_number);
340 if ($plot_layout_format) {
341 $trial_design->set_plot_layout_format($plot_layout_format);
343 if ($number_of_replicated_accession) {
344 $trial_design->set_replicated_accession_no($number_of_replicated_accession);
346 if ($number_of_unreplicated_accession) {
347 $trial_design->set_unreplicated_accession_no($number_of_unreplicated_accession);
349 if ($row_in_design_number) {
350 $trial_design->set_row_in_design_number($row_in_design_number);
352 if ($col_in_design_number) {
353 $trial_design->set_col_in_design_number($col_in_design_number);
355 if ($no_of_rep_times) {
356 $trial_design->set_num_of_replicated_times($no_of_rep_times);
358 if ($no_of_block_sequence) {
359 $trial_design->set_block_sequence($no_of_block_sequence);
361 if ($no_of_sub_block_sequence) {
362 $trial_design->set_sub_block_sequence($no_of_sub_block_sequence);
365 if (scalar(@treatments)>0) {
366 $trial_design->set_treatments(\@treatments);
368 if($num_plants_per_plot){
369 $trial_design->set_num_plants_per_plot($num_plants_per_plot);
372 try {
373 $trial_design->calculate_design();
374 } catch {
375 $c->stash->{rest} = {error => "Could not calculate design: $_"};
376 $error=1;
378 if ($error) {return;}
379 if ($trial_design->get_design()) {
380 %design = %{$trial_design->get_design()};
381 #print STDERR "DESIGN: ". Dumper(%design);
382 } else {
383 $c->stash->{rest} = {error => "Could not generate design" };
384 return;
386 my $design_level;
387 if ($design_type eq 'greenhouse'){
388 $design_level = 'plants';
389 } elsif ($design_type eq 'splitplot') {
390 $design_level = 'subplots';
391 } else {
392 $design_level = 'plots';
395 $design_map_view = design_layout_map_view(\%design, $design_type);
396 $design_layout_view_html = design_layout_view(\%design, \%design_info, $design_level);
397 $design_info_view_html = design_info_view(\%design, \%design_info);
398 my $design_json = encode_json(\%design);
399 push @design_array, $design_json;
400 push @design_layout_view_html_array, $design_layout_view_html;
403 $c->stash->{rest} = {
404 success => "1",
405 design_layout_view_html => encode_json(\@design_layout_view_html_array),
406 #design_layout_view_html => $design_layout_view_html,
407 design_info_view_html => $design_info_view_html,
408 design_map_view => $design_map_view,
409 #design_json => $design_json,
410 design_json => encode_json(\@design_array),
417 sub save_experimental_design : Path('/ajax/trial/save_experimental_design') : ActionClass('REST') { }
419 sub save_experimental_design_POST : Args(0) {
420 my ($self, $c) = @_;
421 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
422 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
423 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
424 my $dbh = $c->dbc->dbh;
426 print STDERR "Saving trial... :-)\n";
429 if (!$c->user()) {
430 $c->stash->{rest} = {error => "You need to be logged in to add a trial" };
431 return;
433 if (!any { $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) {
434 $c->stash->{rest} = {error => "You have insufficient privileges to add a trial." };
435 return;
437 my $user_id = $c->user()->get_object()->get_sp_person_id();
439 my $user_name = $c->user()->get_object()->get_username();
440 my $error;
442 my $design = _parse_design_from_json($c->req->param('design_json'));
443 #print STDERR "\nDesign: " . Dumper $design;
445 my @locations;
446 my $trial_location;
447 my $multi_location;
448 my $trial_locations = $c->req->param('trial_location');
449 my $trial_name = $c->req->param('project_name');
450 my $trial_type = $c->req->param('trial_type');
451 my $breeding_program = $c->req->param('breeding_program_name');
452 my $schema = $c->dbic_schema("Bio::Chado::Schema");
453 my $breeding_program_id = $schema->resultset("Project::Project")->find({name=>$breeding_program})->project_id();
454 my $folder;
455 my $new_trial_id;
457 try {
458 $multi_location = decode_json($trial_locations);
459 foreach my $loc (@$multi_location) {
460 push @locations, $loc;
464 catch {
465 push @locations, $trial_locations;
467 my $folder_id;
468 my $parent_folder_id = 0;
469 if (scalar(@locations) > 1) {
471 my $existing = $schema->resultset("Project::Project")->find( { name => $trial_name });
473 if ($existing) {
474 $c->stash->{rest} = { error => "An folder or trial with that name already exists in the database. Please select another name." };
475 return;
478 $folder = CXGN::Trial::Folder->create({
479 bcs_schema => $schema,
480 parent_folder_id => $parent_folder_id,
481 name => $trial_name,
482 breeding_program_id => $breeding_program_id,
483 folder_for_trials => 1
485 $folder_id = $folder->folder_id();
488 my $design_index = 0;
490 foreach $trial_location (@locations) {
491 my $trial_name = $c->req->param('project_name');
492 if (scalar(@locations) > 1) {
493 $trial_name = $trial_name."_".$trial_location;
496 my $trial_location_design = decode_json($design->[$design_index]);
497 #print STDERR Dumper $trial_location_design;
499 my $trial_create = CXGN::Trial::TrialCreate->new({
500 chado_schema => $chado_schema,
501 dbh => $dbh,
502 user_name => $user_name, #not implemented
503 design => $trial_location_design,
504 program => $breeding_program,
505 trial_year => $c->req->param('year'),
506 trial_description => $c->req->param('project_description'),
507 trial_location => $trial_location,
508 trial_name => $trial_name,
509 design_type => $c->req->param('design_type'),
510 trial_type => $trial_type,
511 trial_has_plant_entries => $c->req->param('has_plant_entries'),
512 trial_has_subplot_entries => $c->req->param('has_subplot_entries'),
513 operator => $user_name
517 if ($trial_create->trial_name_already_exists()) {
518 $c->stash->{rest} = {error => "Trial name \"".$trial_create->get_trial_name()."\" already exists" };
519 return;
522 my $save;
523 try {
524 $save = $trial_create->save_trial();
525 } catch {
526 $save->{'error'} = $_;
529 if ($save->{'error'}) {
530 my $folder = CXGN::Trial::Folder->new({
531 bcs_schema => $chado_schema,
532 folder_id => $folder_id,
534 my $delete_folder = $folder->delete_folder();
535 print STDERR "Error saving trial: ".$save->{'error'};
536 $c->stash->{rest} = {error => $save->{'error'}};
537 return;
538 } elsif ($save->{'trial_id'}) {
540 $design_index++;
542 if ($folder_id) {
544 my $folder1 = CXGN::Trial::Folder->new(
546 bcs_schema => $chado_schema,
547 folder_id => $save->{'trial_id'},
549 $folder1->associate_parent($folder_id);
554 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
555 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop');
557 $c->stash->{rest} = {success => "1",};
558 return;
562 sub verify_stock_list : Path('/ajax/trial/verify_stock_list') : ActionClass('REST') { }
564 sub verify_stock_list_POST : Args(0) {
565 my ($self, $c) = @_;
566 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
567 my @stock_names;
568 my $error;
569 my %errors;
570 if ($c->req->param('stock_list')) {
571 @stock_names = @{_parse_list_from_json($c->req->param('stock_list'))};
574 if (!@stock_names) {
575 $c->stash->{rest} = {error => "No stock names supplied"};
576 $c->detach;
579 my $lv = CXGN::List::Validate->new();
580 my @accessions_missing = @{$lv->validate($schema,'accessions',\@stock_names)->{'missing'}};
582 if (scalar(@accessions_missing) > 0){
583 my $error = 'The following accessions are not valid in the database, so you must add them first: '.join ',', @accessions_missing;
584 $c->stash->{rest} = {error => $error};
585 } else {
586 $c->stash->{rest} = {
587 success => "1",
592 sub verify_seedlot_list : Path('/ajax/trial/verify_seedlot_list') : ActionClass('REST') { }
594 sub verify_seedlot_list_POST : Args(0) {
595 my ($self, $c) = @_;
596 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
597 my $people_schema = $c->dbic_schema('CXGN::People::Schema');
598 my $phenome_schema = $c->dbic_schema('CXGN::Phenome::Schema');
599 my @stock_names;
600 my @seedlot_names;
601 if ($c->req->param('stock_list')) {
602 @stock_names = @{_parse_list_from_json($c->req->param('stock_list'))};
604 if ($c->req->param('seedlot_list')) {
605 @seedlot_names = @{_parse_list_from_json($c->req->param('seedlot_list'))};
607 my $return = CXGN::Stock::Seedlot->verify_seedlot_stock_lists($schema, $people_schema, $phenome_schema, \@stock_names, \@seedlot_names);
609 if (exists($return->{error})){
610 $c->stash->{rest} = { error => $return->{error} };
611 $c->detach();
613 if (exists($return->{success})){
614 $c->stash->{rest} = {
615 success => "1",
616 seedlot_hash => $return->{seedlot_hash}
621 sub _parse_list_from_json {
622 my $list_json = shift;
623 my $json = new JSON;
624 if ($list_json) {
625 my $decoded_list = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($list_json);
626 #my $decoded_list = decode_json($list_json);
627 my @array_of_list_items = @{$decoded_list};
628 return \@array_of_list_items;
630 else {
631 return;
635 sub _parse_design_from_json {
636 my $design_json = shift;
637 my $json = new JSON;
638 if ($design_json) {
639 my $decoded_json = $json->allow_nonref->utf8->relaxed->escape_slash->loose->allow_singlequote->allow_barekey->decode($design_json);
640 #my $decoded_json = decode_json($design_json);
641 #my %design = %{$decoded_json};
642 return $decoded_json;
644 else {
645 return;
649 ###################################################################################
651 sub upload_trial_file : Path('/ajax/trial/upload_trial_file') : ActionClass('REST') { }
653 sub upload_trial_file_POST : Args(0) {
654 my ($self, $c) = @_;
656 print STDERR "Check 1: ".localtime()."\n";
658 my $chado_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
659 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
660 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
661 my $dbh = $c->dbc->dbh;
662 my $program = $c->req->param('trial_upload_breeding_program');
663 my $trial_location = $c->req->param('trial_upload_location');
664 my $trial_name = $c->req->param('trial_upload_name');
665 my $trial_year = $c->req->param('trial_upload_year');
666 my $trial_type = $c->req->param('trial_upload_trial_type');
667 my $trial_description = $c->req->param('trial_upload_description');
668 my $trial_design_method = $c->req->param('trial_upload_design_method');
669 my $upload = $c->req->upload('trial_uploaded_file');
670 my $parser;
671 my $parsed_data;
672 my $upload_original_name = $upload->filename();
673 my $upload_tempfile = $upload->tempname;
674 my $subdirectory = "trial_upload";
675 my $archived_filename_with_path;
676 my $md5;
677 my $validate_file;
678 my $parsed_file;
679 my $parse_errors;
680 my %parsed_data;
681 my %upload_metadata;
682 my $time = DateTime->now();
683 my $timestamp = $time->ymd()."_".$time->hms();
684 my $user_id;
685 my $user_name;
686 my $error;
688 print STDERR "Check 2: ".localtime()."\n";
690 if ($upload_original_name =~ /\s/ || $upload_original_name =~ /\// || $upload_original_name =~ /\\/ ) {
691 print STDERR "File name must not have spaces or slashes.\n";
692 $c->stash->{rest} = {error => "Uploaded file name must not contain spaces or slashes." };
693 return;
696 if (!$c->user()) {
697 print STDERR "User not logged in... not uploading a trial.\n";
698 $c->stash->{rest} = {error => "You need to be logged in to upload a trial." };
699 return;
701 if (!any { $_ eq "curator" || $_ eq "submitter" } ($c->user()->roles) ) {
702 $c->stash->{rest} = {error => "You have insufficient privileges to upload a trial." };
703 return;
706 $user_id = $c->user()->get_object()->get_sp_person_id();
708 $user_name = $c->user()->get_object()->get_username();
710 ## Store uploaded temporary file in archive
711 my $uploader = CXGN::UploadFile->new({
712 tempfile => $upload_tempfile,
713 subdirectory => $subdirectory,
714 archive_path => $c->config->{archive_path},
715 archive_filename => $upload_original_name,
716 timestamp => $timestamp,
717 user_id => $user_id,
718 user_role => $c->user->get_object->get_user_type()
720 $archived_filename_with_path = $uploader->archive();
721 $md5 = $uploader->get_md5($archived_filename_with_path);
722 if (!$archived_filename_with_path) {
723 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
724 return;
726 unlink $upload_tempfile;
728 print STDERR "Check 3: ".localtime()."\n";
730 $upload_metadata{'archived_file'} = $archived_filename_with_path;
731 $upload_metadata{'archived_file_type'}="trial upload file";
732 $upload_metadata{'user_id'}=$user_id;
733 $upload_metadata{'date'}="$timestamp";
735 #parse uploaded file with appropriate plugin
736 $parser = CXGN::Trial::ParseUpload->new(chado_schema => $chado_schema, filename => $archived_filename_with_path);
737 $parser->load_plugin('TrialExcelFormat');
738 $parsed_data = $parser->parse();
740 if (!$parsed_data) {
741 my $return_error = '';
743 if (! $parser->has_parse_errors() ){
744 $return_error = "Could not get parsing errors";
745 $c->stash->{rest} = {error_string => $return_error,};
748 else {
749 $parse_errors = $parser->get_parse_errors();
750 #print STDERR Dumper $parse_errors;
752 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
753 $return_error=$return_error.$error_string."<br>";
757 $c->stash->{rest} = {error_string => $return_error, missing_accessions => $parse_errors->{'missing_accessions'}};
758 return;
761 print STDERR "Check 4: ".localtime()."\n";
763 #print STDERR Dumper $parsed_data;
765 my $save;
766 my $coderef = sub {
768 my $trial_create = CXGN::Trial::TrialCreate->new({
769 chado_schema => $chado_schema,
770 dbh => $dbh,
771 trial_year => $trial_year,
772 trial_description => $trial_description,
773 trial_location => $trial_location,
774 trial_type => $trial_type,
775 trial_name => $trial_name,
776 user_name => $user_name, #not implemented
777 design_type => $trial_design_method,
778 design => $parsed_data,
779 program => $program,
780 upload_trial_file => $upload,
781 operator => $c->user()->get_object()->get_username()
783 $save = $trial_create->save_trial();
785 if ($save->{error}){
786 $chado_schema->txn_rollback();
791 try {
792 $chado_schema->txn_do($coderef);
793 } catch {
794 print STDERR "Transaction Error: $_\n";
795 $save->{'error'} = $_;
798 #print STDERR "Check 5: ".localtime()."\n";
799 if ($save->{'error'}) {
800 print STDERR "Error saving trial: ".$save->{'error'};
801 $c->stash->{rest} = {error => $save->{'error'}};
802 return;
803 } elsif ($save->{'trial_id'}) {
805 my $dbh = $c->dbc->dbh();
806 my $bs = CXGN::BreederSearch->new( { dbh=>$dbh, dbname=>$c->config->{dbname}, } );
807 my $refresh = $bs->refresh_matviews($c->config->{dbhost}, $c->config->{dbname}, $c->config->{dbuser}, $c->config->{dbpass}, 'stockprop');
809 $c->stash->{rest} = {success => "1"};
810 return;