Added eval; site now shows clean dataset missing message instead of server error...
[sgn.git] / lib / SGN / Controller / AJAX / Catalog.pm
blobf53f6e6017816780b7ed94e12eb4d7c7b0d1361b
1 package SGN::Controller::AJAX::Catalog;
3 use Moose;
4 use CXGN::Stock::Catalog;
5 use Data::Dumper;
6 use JSON;
7 use CXGN::People::Person;
8 use SGN::Image;
9 use CXGN::Stock::StockLookup;
10 use SGN::Model::Cvterm;
11 use CXGN::List::Validate;
12 use CXGN::List;
13 use CXGN::Stock::Seedlot;
15 BEGIN { extends 'Catalyst::Controller::REST' }
17 __PACKAGE__->config(
18 default => 'application/json',
19 stash_key => 'rest',
20 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
24 sub add_catalog_item : Path('/ajax/catalog/add_item') : ActionClass('REST'){ }
26 sub add_catalog_item_POST : Args(0) {
27 my $self = shift;
28 my $c = shift;
29 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
30 my $dbh = $c->dbc->dbh;
32 my $item_name = $c->req->param('name');
33 my $item_category = $c->req->param('category');
34 my $item_additional_info = $c->req->param('additional_info');
35 my $item_material_source = $c->req->param('material_source');
36 my $item_breeding_program_id = $c->req->param('breeding_program_id');
37 my $contact_person = $c->req->param('contact_person');
38 my $item_prop_id = $c->req->param('item_prop_id');
39 my $availability = $c->req->param('availability');
40 if (!defined $availability) {
41 $availability = 'available';
44 if (!$c->user()) {
45 print STDERR "User not logged in... not adding a catalog item.\n";
46 $c->stash->{rest} = {error_string => "You must be logged in to add a catalog item." };
47 return;
50 my $item_material_type;
51 my $item_type;
52 my $item_stock_id;
53 my $item_species;
54 my $item_variety;
56 my $accession_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'accession', 'stock_type')->cvterm_id();
57 my $seedlot_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'seedlot', 'stock_type')->cvterm_id();
58 my $vector_construct_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'vector_construct', 'stock_type')->cvterm_id();
59 my $population_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'population', 'stock_type')->cvterm_id();
61 my $stock_lookup = CXGN::Stock::StockLookup->new(schema => $schema);
62 $stock_lookup->set_stock_name($item_name);
63 my $item_rs = $stock_lookup->get_stock_exact();
65 if (!defined $item_rs) {
66 $c->stash->{rest} = {error_string => "Item name is not in the database or not unique in the database!",};
67 return;
68 } else {
69 $item_stock_id = $item_rs->stock_id();
70 my $item_type_id = $item_rs->type_id();
72 my $variety_result = $stock_lookup->get_stock_variety();
73 if (defined $variety_result) {
74 $item_variety = $variety_result;
75 } else {
76 $item_variety = 'NA';
79 if ($item_type_id == $accession_cvterm_id) {
80 my $organism_id = $item_rs->organism_id();
81 my $organism = $schema->resultset("Organism::Organism")->find({organism_id => $organism_id});
82 $item_species = $organism->species();
83 $item_material_type = 'plant';
84 $item_type = 'single item';
86 } elsif ($item_type_id == $seedlot_cvterm_id) {
87 my $seedlot_species = CXGN::Stock::Seedlot->new(schema => $schema, seedlot_id=>$item_stock_id);
88 $item_species = $seedlot_species->get_seedlot_species();
89 $item_material_type = 'seed';
90 $item_type = 'single item';
92 } elsif ($item_type_id == $vector_construct_cvterm_id) {
93 $item_material_type = 'construct';
94 $item_type = 'single item';
96 } elsif ($item_type_id == $population_cvterm_id) {
97 $item_material_type = 'plant';
98 $item_type = 'set of items';
103 my $sp_person_id = CXGN::People::Person->get_person_by_username($dbh, $contact_person);
104 if (!$sp_person_id) {
105 $c->stash->{rest} = {error_string => "Contact person has no record in the database!",};
106 return;
108 # print STDERR "PERSON ID =".Dumper($sp_person_id)."\n";
109 my $program_rs = $schema->resultset('Project::Project')->find({project_id => $item_breeding_program_id});
110 if (!$program_rs) {
111 $c->stash->{rest} = {error_string => "Breeding program is not in the database!",};
112 return;
115 my $stock_catalog = CXGN::Stock::Catalog->new({
116 bcs_schema => $schema,
117 parent_id => $item_stock_id,
118 prop_id => $item_prop_id
121 $stock_catalog->item_type($item_type);
122 $stock_catalog->material_type($item_material_type);
123 $stock_catalog->material_source($item_material_source);
124 $stock_catalog->category($item_category);
125 $stock_catalog->species($item_species);
126 $stock_catalog->variety($item_variety);
127 $stock_catalog->breeding_program($item_breeding_program_id);
128 $stock_catalog->availability($availability);
129 $stock_catalog->additional_info($item_additional_info);
130 $stock_catalog->contact_person_id($sp_person_id);
132 $stock_catalog->store();
134 if (!$stock_catalog->store()){
135 $c->stash->{rest} = {error_string => "Error saving catalog item",};
136 return;
139 $c->stash->{rest} = {success => "1",};
144 sub upload_catalog_items : Path('/ajax/catalog/upload_items') : ActionClass('REST'){ }
146 sub upload_catalog_items_POST : Args(0) {
147 my $self = shift;
148 my $c = shift;
149 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
150 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
151 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
152 my $dbh = $c->dbc->dbh;
153 my $upload = $c->req->upload('catalog_items_upload_file');
154 my $upload_type = 'CatalogXLS';
155 my $parser;
156 my $parsed_data;
157 my $upload_original_name = $upload->filename();
158 my $upload_tempfile = $upload->tempname;
159 my $subdirectory = "catalog_upload";
160 my $archived_filename_with_path;
161 my $md5;
162 my $validate_file;
163 my $parsed_file;
164 my $parse_errors;
165 my %parsed_data;
166 my $time = DateTime->now();
167 my $timestamp = $time->ymd()."_".$time->hms();
168 my $user_role;
169 my $user_id;
170 my $user_name;
171 my $owner_name;
172 my $session_id = $c->req->param("sgn_session_id");
174 if ($session_id){
175 my $dbh = $c->dbc->dbh;
176 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
177 if (!$user_info[0]){
178 $c->stash->{rest} = {error=>'You must be logged in to upload!'};
179 $c->detach();
181 $user_id = $user_info[0];
182 $user_role = $user_info[1];
183 my $p = CXGN::People::Person->new($dbh, $user_id);
184 $user_name = $p->get_username;
185 } else{
186 if (!$c->user){
187 $c->stash->{rest} = {error=>'You must be logged in to upload catalog items!'};
188 $c->detach();
190 $user_id = $c->user()->get_object()->get_sp_person_id();
191 $user_name = $c->user()->get_object()->get_username();
192 $user_role = $c->user->get_object->get_user_type();
194 my $uploader = CXGN::UploadFile->new({
195 tempfile => $upload_tempfile,
196 subdirectory => $subdirectory,
197 archive_path => $c->config->{archive_path},
198 archive_filename => $upload_original_name,
199 timestamp => $timestamp,
200 user_id => $user_id,
201 user_role => $user_role
204 ## Store uploaded temporary file in arhive
205 $archived_filename_with_path = $uploader->archive();
206 $md5 = $uploader->get_md5($archived_filename_with_path);
207 if (!$archived_filename_with_path) {
208 $c->stash->{rest} = {error => "Could not save file $upload_original_name in archive",};
209 return;
211 unlink $upload_tempfile;
212 #parse uploaded file with appropriate plugin
213 my @stock_props = ('stock_catalog_json');
214 $parser = CXGN::Stock::ParseUpload->new(chado_schema => $schema, filename => $archived_filename_with_path, editable_stock_props=>\@stock_props);
215 $parser->load_plugin($upload_type);
216 $parsed_data = $parser->parse();
218 if (!$parsed_data){
219 my $return_error = '';
220 my $parse_errors;
221 if (!$parser->has_parse_errors() ){
222 $c->stash->{rest} = {error_string => "Could not get parsing errors"};
223 } else {
224 $parse_errors = $parser->get_parse_errors();
225 #print STDERR Dumper $parse_errors;
227 foreach my $error_string (@{$parse_errors->{'error_messages'}}){
228 $return_error .= $error_string."<br>";
231 $c->stash->{rest} = {error_string => $return_error};
232 $c->detach();
235 if ($parsed_data) {
236 my $variety_type_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'variety', 'stock_property')->cvterm_id();
237 my %catalog_info = %{$parsed_data};
238 foreach my $item_name (keys %catalog_info) {
239 my $item_stock_id;
240 my $item_species;
241 my $item_variety;
242 my $item_type;
243 my $item_material_type;
244 my $accession_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'accession', 'stock_type')->cvterm_id();
245 my $seedlot_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'seedlot', 'stock_type')->cvterm_id();
246 my $vector_construct_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'vector_construct', 'stock_type')->cvterm_id();
247 my $population_cvterm_id = SGN::Model::Cvterm->get_cvterm_row($schema, 'population', 'stock_type')->cvterm_id();
249 my $stock_lookup = CXGN::Stock::StockLookup->new(schema => $schema);
250 $stock_lookup->set_stock_name($item_name);
251 my $item_rs = $stock_lookup->get_stock_exact();
253 if (!defined $item_rs) {
254 $c->stash->{rest} = {error_string => "Item name is not unique in the database!",};
255 return;
256 } else {
257 $item_stock_id = $item_rs->stock_id();
258 my $item_type_id = $item_rs->type_id();
260 my $variety_result = $stock_lookup->get_stock_variety();
261 if (defined $variety_result) {
262 $item_variety = $variety_result;
263 } else {
264 $item_variety = 'NA';
267 if ($item_type_id == $accession_cvterm_id) {
268 my $organism_id = $item_rs->organism_id();
269 my $organism = $schema->resultset("Organism::Organism")->find({organism_id => $organism_id});
270 $item_species = $organism->species();
271 $item_material_type = 'plant';
272 $item_type = 'single item';
274 } elsif ($item_type_id == $seedlot_cvterm_id) {
275 my $seedlot_species = CXGN::Stock::Seedlot->new(schema => $schema, seedlot_id=>$item_stock_id);
276 $item_species = $seedlot_species->get_seedlot_species();
277 $item_material_type = 'seed';
278 $item_type = 'single item';
280 } elsif ($item_type_id == $vector_construct_cvterm_id) {
281 $item_material_type = 'construct';
282 $item_type = 'single item';
284 } elsif ($item_type_id == $population_cvterm_id) {
285 $item_material_type = 'plant';
286 $item_type = 'set of items';
291 my %catalog_info_hash = %{$catalog_info{$item_name}};
293 my $stock_catalog = CXGN::Stock::Catalog->new({
294 bcs_schema => $schema,
295 item_type => $item_type,
296 material_type => $item_material_type,
297 species => $item_species,
298 variety => $item_variety,
299 category => $catalog_info_hash{category},
300 availability => 'available',
301 additional_info => $catalog_info_hash{additional_info},
302 material_source => $catalog_info_hash{material_source},
303 breeding_program => $catalog_info_hash{breeding_program},
304 contact_person_id => $catalog_info_hash{contact_person_id},
305 parent_id => $item_stock_id
308 $stock_catalog->store();
310 if (!$stock_catalog->store()){
311 $c->stash->{rest} = {error_string => "Error saving catalog items",};
312 return;
317 $c->stash->{rest} = {success => "1"};
322 sub get_catalog :Path('/ajax/catalog/items') :Args(0) {
323 my $self = shift;
324 my $c = shift;
325 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
326 my @catalog_items;
328 my $catalog_obj = CXGN::Stock::Catalog->new({ bcs_schema => $schema});
329 my $catalog_ref = $catalog_obj->get_catalog_items();
330 # print STDERR "ITEM RESULTS =".Dumper($catalog_ref)."\n";
331 my @catalog_list = @$catalog_ref;
332 foreach my $catalog_item (@catalog_list) {
333 my @item_details = ();
334 @item_details = @$catalog_item;
335 my $item_id = shift @item_details;
336 my $stock_rs = $schema->resultset("Stock::Stock")->find({stock_id => $item_id });
337 my $item_name = $stock_rs->uniquename();
339 my $program_id = $item_details[7];
340 my $program_rs = $schema->resultset('Project::Project')->find({project_id => $program_id});
341 my $program_name = $program_rs->name();
342 my $availability = $item_details[8];
343 if (!defined $availability) {
344 $availability = 'available';
347 push @catalog_items, {
348 item_id => $item_id,
349 item_name => $item_name,
350 item_type => $item_details[0],
351 species => $item_details[1],
352 variety => $item_details[2],
353 material_type => $item_details[3],
354 category => $item_details[4],
355 material_source => $item_details[5],
356 additional_info => $item_details[6],
357 breeding_program => $program_name,
358 availability => $availability
362 $c->stash->{rest} = {data => \@catalog_items};
367 sub item_image_list :Path('/ajax/catalog/image_list') :Args(1) {
368 my $self = shift;
369 my $c = shift;
370 my $item_id = shift;
371 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
372 my $dbh = $c->dbc->dbh;
373 # print STDERR "ITEM ID =".Dumper($item_id)."\n";
375 my @image_ids;
376 my $q = "select distinct image_id, cvterm.name, stock_image.display_order FROM phenome.stock_image JOIN stock USING(stock_id) JOIN cvterm ON(type_id=cvterm_id) WHERE stock_id = ? ORDER BY stock_image.display_order ASC";
377 my $h = $schema->storage->dbh()->prepare($q);
378 $h->execute($item_id);
379 while (my ($image_id, $stock_type) = $h->fetchrow_array()){
380 push @image_ids, [$image_id, $stock_type];
382 # print STDERR "IMAGE IDS =".Dumper(\@image_ids)."\n";
383 my @image_list;
384 foreach my $image_info(@image_ids) {
385 my $image_obj = SGN::Image->new($dbh, $image_info->[0]);
386 my $image_obj_id = $image_obj->get_image_id;
387 my $image_obj_name = $image_obj->get_name();
388 my $image_obj_description = $image_obj->get_description();
389 if (!$image_obj_description) {
390 $image_obj_description = 'N/A';
392 my $medium_image = $image_obj->get_image_url("medium");
393 my $image_page = "/image/view/$image_obj_id";
394 my $small_image = $image_obj->get_image_url("thumbnail");
396 push @image_list, {
397 image_id => $image_obj_id,
398 image_name => $image_obj_name,
399 small_image => qq|<a href="$medium_image" title="<a href=$image_page>Go to image page ($image_obj_name)</a>" class="stock_image_group" rel="gallery-figures"><img src="$small_image"/></a> |,
400 image_description => $image_obj_description,
404 $c->stash->{rest} = {data => \@image_list};
408 sub edit_catalog_image : Path('/ajax/catalog/edit_image') : ActionClass('REST'){ }
410 sub edit_catalog_image_POST : Args(0) {
411 my $self = shift;
412 my $c = shift;
413 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
414 my $dbh = $c->dbc->dbh;
416 my $item_name = $c->req->param('item_name');
417 my $item_prop_id = $c->req->param('item_prop_id');
418 my $image_id = $c->req->param('image_id');
419 my @images;
420 my $item_stock_id;
421 push @images, $image_id;
422 print STDERR "IMAGE ID =".Dumper(\@images)."\n";
423 if (!$c->user()) {
424 print STDERR "User not logged in... not adding a catalog item.\n";
425 $c->stash->{rest} = {error_string => "You must be logged in to add a catalog image." };
426 return;
429 my $item_rs = $schema->resultset("Stock::Stock")->find({uniquename => $item_name});
430 if (!$item_rs) {
431 $c->stash->{rest} = {error_string => "Item name is not in the database!",};
432 return;
433 } else {
434 $item_stock_id = $item_rs->stock_id();
437 my $stock_catalog = CXGN::Stock::Catalog->new({
438 bcs_schema => $schema,
439 parent_id => $item_stock_id,
440 prop_id => $item_prop_id
443 $stock_catalog->images(\@images);
445 $stock_catalog->store();
447 if (!$stock_catalog->store()){
448 $c->stash->{rest} = {error_string => "Error saving catalog image",};
449 return;
452 $c->stash->{rest} = {success => "1",};
457 sub delete_catalog_item : Path('/ajax/catalog/delete') : ActionClass('REST'){ }
459 sub delete_catalog_item_POST : Args(0) {
460 my $self = shift;
461 my $c = shift;
462 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
464 my $item_prop_id = $c->req->param('item_prop_id');
465 print STDERR "ITEM PROP ID =".Dumper($item_prop_id)."\n";
466 my $catalog_obj = CXGN::Stock::Catalog->new({ bcs_schema => $schema, prop_id => $item_prop_id });
467 $catalog_obj->delete();
468 if ($catalog_obj->delete() == 0) {
469 $c->stash->{rest} = { error_string => "An error occurred attempting to delete a catalog item." };
470 return;
473 $c->stash->{rest} = { success => 1 };
477 sub add_catalog_item_list : Path('/ajax/catalog/add_item_list') : ActionClass('REST'){ }
479 sub add_catalog_item_list_POST : Args(0) {
480 my $self = shift;
481 my $c = shift;
482 my $schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
483 my $dbh = $c->dbc->dbh;
485 my $list_type = $c->req->param('list_type');
486 my $list_id = $c->req->param('catalog_list');
487 my $list_category = $c->req->param('category');
488 my $list_additional_info = $c->req->param('additional_info');
489 my $list_material_source = $c->req->param('material_source');
490 my $list_breeding_program_id = $c->req->param('breeding_program_id');
491 my $list_contact_person = $c->req->param('contact_person');
493 if (!$c->user()) {
494 print STDERR "User not logged in... not adding catalog items.\n";
495 $c->stash->{rest} = {error_string => "You must be logged in to add catalog items." };
496 return;
499 my $sp_person_id = CXGN::People::Person->get_person_by_username($dbh, $list_contact_person);
500 if (!$sp_person_id) {
501 $c->stash->{rest} = {error_string => "Contact person has no record in the database!",};
502 return;
505 my $item_type;
506 my $item_material_type;
508 if ($list_type eq 'accessions') {
509 $item_material_type = 'plant';
510 $item_type = 'single item';
511 } elsif ($list_type eq 'seedlots') {
512 $item_material_type = 'seed';
513 $item_type = 'single item';
514 } elsif ($list_type eq 'vector_constructs') {
515 $item_material_type = 'construct';
516 $item_type = 'single item';
517 } elsif ($list_type eq 'populations') {
518 $item_material_type = 'plant';
519 $item_type = 'set of items';
522 my $item_list = CXGN::List->new({dbh => $dbh, list_id => $list_id});
523 my $items = $item_list->retrieve_elements($list_id);
524 my @item_names = @$items;
526 my $list_error_message;
527 my $item_validator = CXGN::List::Validate->new();
528 my @item_missing = @{$item_validator->validate($schema, $list_type,\@item_names)->{'missing'}};
529 if (scalar(@item_missing) > 0) {
530 $list_error_message = "The following items are not in database or are not the specified list type: ".join("\n", @item_missing);
531 $c->stash->{rest} = { error_string => $list_error_message };
532 $c->detach();
533 } else {
534 foreach my $item (@item_names) {
535 my $item_stock_id;
536 my $item_species;
537 my $item_variety;
539 my $stock_lookup = CXGN::Stock::StockLookup->new(schema => $schema);
540 $stock_lookup->set_stock_name($item);
541 my $item_rs = $stock_lookup->get_stock_exact();
543 if (!defined $item_rs) {
544 $c->stash->{rest} = {error_string => "Item name is not unique in the database!",};
545 return;
546 } else {
547 $item_stock_id = $item_rs->stock_id();
549 my $variety_result = $stock_lookup->get_stock_variety();
550 if (defined $variety_result) {
551 $item_variety = $variety_result;
552 } else {
553 $item_variety = 'NA';
556 if ($list_type eq 'accessions') {
557 my $organism_id = $item_rs->organism_id();
558 my $organism = $schema->resultset("Organism::Organism")->find({organism_id => $organism_id});
559 $item_species = $organism->species();
561 } elsif ($list_type eq 'seedlots') {
562 my $seedlot_species = CXGN::Stock::Seedlot->new(schema => $schema, seedlot_id=>$item_stock_id);
563 $item_species = $seedlot_species->get_seedlot_species();
568 my $stock_catalog = CXGN::Stock::Catalog->new({
569 bcs_schema => $schema,
570 item_type => $item_type,
571 material_type => $item_material_type,
572 species => $item_species,
573 variety => $item_variety,
574 category => $list_category,
575 availability => 'available',
576 additional_info => $list_additional_info,
577 material_source => $list_material_source,
578 breeding_program => $list_breeding_program_id,
579 contact_person_id => $sp_person_id,
580 parent_id => $item_stock_id
583 $stock_catalog->store();
585 if (!$stock_catalog->store()){
586 $c->stash->{rest} = {error_string => "Error saving catalog items",};
587 return;
593 $c->stash->{rest} = {success => "1",};