seedlot upload with accession synonyms. seedlot upload works to update existing seedlots
[sgn.git] / lib / SGN / Controller / AJAX / ODK.pm
blobb518184eb91dc3534a3cc4f2a0b913c1afc08310
2 =head1 NAME
4 SGN::Controller::AJAX::ODK - a REST controller class to provide the
5 backend for ODK services
7 =head1 DESCRIPTION
9 =head1 AUTHOR
11 =cut
13 package SGN::Controller::AJAX::ODK;
15 use Moose;
16 use List::MoreUtils qw /any /;
17 use Data::Dumper;
18 use Try::Tiny;
19 use CXGN::Phenome::Schema;
20 use Bio::Chado::Schema;
21 use DateTime;
22 use SGN::Model::Cvterm;
23 use LWP::UserAgent;
24 use JSON;
25 use CXGN::ODK::Crosses;
26 use Carp;
27 use File::Spec::Functions qw / catfile catdir/;
28 use File::Path qw(make_path);
30 BEGIN { extends 'Catalyst::Controller::REST' }
32 __PACKAGE__->config(
33 default => 'application/json',
34 stash_key => 'rest',
35 map => { 'application/json' => 'JSON', 'text/html' => 'JSON' },
39 sub get_phenotyping_data : Path('/ajax/odk/get_phenotyping_data') : ActionClass('REST') { }
41 sub get_phenotyping_data_GET {
42 my ( $self, $c ) = @_;
43 my $odk_phenotyping_data_service_name = $c->config->{odk_phenotyping_data_service_name};
44 my $odk_phenotyping_data_service_username = $c->config->{odk_phenotyping_data_service_username};
45 my $odk_phenotyping_data_service_password = $c->config->{odk_phenotyping_data_service_password};
46 if ($odk_phenotyping_data_service_name eq 'SMAP'){
47 my $ua = LWP::UserAgent->new;
48 my $server_endpoint = "https://".$odk_phenotyping_data_service_username.":".$odk_phenotyping_data_service_password."\@bio.smap.com.au/api/v1/data";
49 print STDERR $server_endpoint."\n";
51 my $resp = $ua->get($server_endpoint);
52 if ($resp->is_success) {
53 my $message = $resp->decoded_content;
54 my $message_hash = decode_json $message;
55 print STDERR Dumper $message_hash;
56 } else {
57 print STDERR Dumper $resp;
60 } else {
61 $c->stash->{rest} = { error => 'Error: We only support SMAP as an ODK phenotyping service for now.' };
62 $c->detach();
64 $c->stash->{rest} = { success => 1 };
67 sub get_crossing_available_forms : Path('/ajax/odk/get_crossing_available_forms') : ActionClass('REST') { }
69 sub get_crossing_available_forms_GET {
70 my ( $self, $c ) = @_;
71 my $odk_crossing_data_service_name = $c->config->{odk_crossing_data_service_name};
72 my $message_hash;
73 if ($odk_crossing_data_service_name eq 'ONA'){
74 my $ua = LWP::UserAgent->new;
75 $ua->credentials( 'api.ona.io:443', 'DJANGO', $c->config->{odk_crossing_data_service_username}, $c->config->{odk_crossing_data_service_password} );
76 my $login_resp = $ua->get("https://api.ona.io/api/v1/user.json");
77 my $server_endpoint = "https://api.ona.io/api/v1/data";
78 my $resp = $ua->get($server_endpoint);
80 if ($resp->is_success) {
81 my $message = $resp->decoded_content;
82 $message_hash = decode_json $message;
84 } else {
85 $c->stash->{rest} = { error => 'Error: We only support ONA as an ODK crossing service for now.' };
86 $c->detach();
88 $c->stash->{rest} = { success => 1, forms=>$message_hash };
91 sub get_crossing_data : Path('/ajax/odk/get_crossing_data') : ActionClass('REST') { }
93 sub get_crossing_data_GET {
94 my ( $self, $c ) = @_;
95 my $cross_wishlist_id = $c->req->param('cross_wishlist_md_file_id');
96 my $cross_wishlist_file_name = $c->req->param('cross_wishlist_file_name');
97 my $form_id = $c->req->param('form_id');
98 my $session_id = $c->req->param("sgn_session_id");
99 my $user_id;
100 my $user_name;
101 my $user_role;
102 if ($session_id){
103 my $dbh = $c->dbc->dbh;
104 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
105 if (!$user_info[0]){
106 $c->stash->{rest} = {error=>'You must be logged in to request ODK crossing data import!'};
107 $c->detach();
109 $user_id = $user_info[0];
110 $user_role = $user_info[1];
111 my $p = CXGN::People::Person->new($dbh, $user_id);
112 $user_name = $p->get_username;
113 } else{
114 if (!$c->user){
115 $c->stash->{rest} = {error=>'You must be logged in to request ODK crossing data import!'};
116 $c->detach();
118 $user_id = $c->user()->get_object()->get_sp_person_id();
119 $user_name = $c->user()->get_object()->get_username();
120 $user_role = $c->user->get_object->get_user_type();
122 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
123 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
124 my $phenome_schema = $c->dbic_schema("CXGN::Phenome::Schema");
125 my $tempfiles_dir = $c->tempfiles_subdir('ODK_ONA_cross_info');
126 my ($temp_file, $uri1) = $c->tempfile( TEMPLATE => 'ODK_ONA_cross_info/ODK_ONA_cross_info_downloadXXXXX');
127 my $temp_file_path = $temp_file->filename;
129 my $progress_tree_dir = catdir($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
131 my $odk_crosses = CXGN::ODK::Crosses->new({
132 bcs_schema=>$bcs_schema,
133 metadata_schema=>$metadata_schema,
134 phenome_schema=>$phenome_schema,
135 sp_person_id=>$user_id,
136 sp_person_username=>$user_name,
137 sp_person_role=>$user_role,
138 archive_path=>$c->config->{archive_path},
139 temp_file_dir=>$c->config->{basepath}.$tempfiles_dir,
140 temp_file_path=>$temp_file_path,
141 cross_wishlist_md_file_id=>$cross_wishlist_id,
142 cross_wishlist_file_name=>$cross_wishlist_file_name,
143 allowed_cross_properties=>$c->config->{cross_properties},
144 odk_crossing_data_service_url=>$c->config->{odk_crossing_data_service_url},
145 odk_crossing_data_service_username=>$c->config->{odk_crossing_data_service_username},
146 odk_crossing_data_service_password=>$c->config->{odk_crossing_data_service_password},
147 odk_crossing_data_service_form_id=>$form_id,
148 odk_cross_progress_tree_file_dir=>$progress_tree_dir
151 my $odk_crossing_data_service_name = $c->config->{odk_crossing_data_service_name};
152 if ($odk_crossing_data_service_name eq 'ONA'){
153 my $result = $odk_crosses->save_ona_cross_info($c);
154 if ($result->{error}){
155 $c->stash->{rest} = { error => $result->{error} };
156 $c->detach();
157 } elsif ($result->{success}){
158 $c->stash->{rest} = { success => 1 };
159 $c->detach();
161 } else {
162 $c->stash->{rest} = { error => 'Error: We only support ONA as an ODK crossing service for now.' };
163 $c->detach();
167 sub schedule_get_crossing_data : Path('/ajax/odk/schedule_get_crossing_data') : ActionClass('REST') { }
169 sub schedule_get_crossing_data_GET {
170 my ( $self, $c ) = @_;
171 if ($c->config->{production_server}){
172 $c->stash->{rest} = { error=>'Please use contact form. Currently this cannot be set through the website.' };
173 $c->detach();
175 my $form_id = $c->req->param('form_id');
176 my $cross_wishlist_id = $c->req->param('cross_wishlist_md_file_id');
177 my $cross_wishlist_file_name = $c->req->param('cross_wishlist_file_name');
178 my $timing_select = $c->req->param('timing');
179 my $session_id = $c->req->param("sgn_session_id");
180 my $user_id;
181 my $user_name;
182 my $user_role;
183 if ($session_id){
184 my $dbh = $c->dbc->dbh;
185 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
186 if (!$user_info[0]){
187 $c->stash->{rest} = {error=>'You must be logged in to schedule ODK crossing data import!'};
188 $c->detach();
190 $user_id = $user_info[0];
191 $user_role = $user_info[1];
192 my $p = CXGN::People::Person->new($dbh, $user_id);
193 $user_name = $p->get_username;
194 } else{
195 if (!$c->user){
196 $c->stash->{rest} = {error=>'You must be logged in to schedule ODK crossing data import!'};
197 $c->detach();
199 $user_id = $c->user()->get_object()->get_sp_person_id();
200 $user_name = $c->user()->get_object()->get_username();
201 $user_role = $c->user->get_object->get_user_type();
203 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
204 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
205 my $tempfiles_dir = $c->tempfiles_subdir('ODK_ONA_cross_info');
206 my ($temp_file, $uri1) = $c->tempfile( TEMPLATE => 'ODK_ONA_cross_info/ODK_ONA_cross_info_downloadXXXXX');
207 my $temp_file_path = $temp_file->filename;
209 my $progress_tree_dir = catdir($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
211 my $cross_properties = $c->config->{cross_properties};
212 my $rootpath = $c->config->{rootpath};
213 my $basepath = $c->config->{basepath};
214 my $archive_path = $c->config->{archive_path};
215 my $ODK_url = $c->config->{odk_crossing_data_service_url};
216 my $ODk_username = $c->config->{odk_crossing_data_service_username};
217 my $ODK_password = $c->config->{odk_crossing_data_service_password};
218 my $database_name = $c->config->{dbname};
219 my $database_user = $c->config->{dbuser};
220 my $database_pass = $c->config->{dbpass};
221 my $database_host = $c->config->{dbhost};
222 my $www_user = $c->config->{www_user};
223 my $crontab_log = $c->config->{crontab_log_filepath};
224 my $include_path = 'export PERL5LIB="$PERL5LIB:'.$basepath.'/lib:'.$rootpath.'/cxgn-corelibs/lib:'.$rootpath.'/Phenome/lib:'.$rootpath.'/local-lib/lib/perl5"';
225 my $perl_command = "$include_path; perl $basepath/bin/ODK/ODK_ONA_get_crosses.pl -u $user_id -i $user_name -r $user_role -a $archive_path -d $basepath.$tempfiles_dir -t $temp_file_path -n $ODk_username -m $ODK_password -o $form_id -w $cross_wishlist_id -x $cross_wishlist_file_name -f $progress_tree_dir -l $ODK_url -c $cross_properties -D $database_name -U $database_user -p $database_pass -H $database_host >> $crontab_log 2>&1";
226 my $timing = '';
227 if ($timing_select eq 'everyminute'){
228 $timing = "0-59/1 * * * * ";
229 } elsif ($timing_select eq 'everyday'){
230 $timing = "1 0 * * * ";
231 } elsif ($timing_select eq 'everyhour'){
232 $timing = "0 * * * * ";
233 } elsif ($timing_select eq 'twicedaily'){
234 $timing = "0 0,12 * * * ";
236 my $crontab_line = $timing.$perl_command."\n";
237 #print STDERR $crontab_line;
238 my $crontab_file = $c->config->{crontab_file};
239 open (my $F, ">", $crontab_file) || die "Could not open $crontab_file: $!\n";
240 if ($timing){
241 print $F $crontab_line;
243 close $F;
245 my $enable_new_crontab = "crontab -u $www_user $crontab_file";
246 system($enable_new_crontab);
248 $c->stash->{rest} = { success => 1 };
249 $c->detach();
253 sub get_crossing_data_cronjobs : Path('/ajax/odk/get_crossing_data_cronjobs') : ActionClass('REST') { }
255 sub get_crossing_data_cronjobs_GET {
256 my ( $self, $c ) = @_;
257 my $session_id = $c->req->param("sgn_session_id");
258 my $user_id;
259 my $user_name;
260 my $user_role;
261 if ($session_id){
262 my $dbh = $c->dbc->dbh;
263 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
264 if (!$user_info[0]){
265 $c->stash->{rest} = {error=>'You must be logged in to see scheduled ODK crossing data import!'};
266 $c->detach();
268 $user_id = $user_info[0];
269 $user_role = $user_info[1];
270 my $p = CXGN::People::Person->new($dbh, $user_id);
271 $user_name = $p->get_username;
272 } else{
273 if (!$c->user){
274 $c->stash->{rest} = {error=>'You must be logged in to see scheduled ODK crossing data import!'};
275 $c->detach();
277 $user_id = $c->user()->get_object()->get_sp_person_id();
278 $user_name = $c->user()->get_object()->get_username();
279 $user_role = $c->user->get_object->get_user_type();
282 my @entries;
283 my $crontab_file = $c->config->{crontab_file};
284 open(my $fh, '<:encoding(UTF-8)', $crontab_file)
285 or die "Could not open file '$crontab_file' $!";
287 while (my $row = <$fh>) {
288 chomp $row;
289 my @c = split 'export', $row;
290 push @entries, $c[0];
292 close $fh;
294 $c->stash->{rest} = { success => 1, entries=>\@entries };
295 $c->detach();
298 sub get_crossing_available_wishlists : Path('/ajax/odk/get_crossing_available_wishlists') : ActionClass('REST') { }
300 sub get_crossing_available_wishlists_GET {
301 my ( $self, $c ) = @_;
302 my $session_id = $c->req->param("sgn_session_id");
303 my $user_id;
304 my $user_name;
305 my $user_role;
306 if ($session_id){
307 my $dbh = $c->dbc->dbh;
308 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
309 if (!$user_info[0]){
310 $c->stash->{rest} = {error=>'You must be logged in to see ODK cross wishlists!'};
311 $c->detach();
313 $user_id = $user_info[0];
314 $user_role = $user_info[1];
315 my $p = CXGN::People::Person->new($dbh, $user_id);
316 $user_name = $p->get_username;
317 } else{
318 if (!$c->user){
319 $c->stash->{rest} = {error=>'You must be logged in to see ODK cross wishlists!'};
320 $c->detach();
322 $user_id = $c->user()->get_object()->get_sp_person_id();
323 $user_name = $c->user()->get_object()->get_username();
324 $user_role = $c->user->get_object->get_user_type();
326 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
327 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
329 my $wishlist_md_files = $metadata_schema->resultset("MdFiles")->search({filetype=> { '-like' => 'cross_wishlist_%', }});
330 my @wishlists;
331 while (my $r=$wishlist_md_files->next){
332 if (index($r->filetype, 'cross_wishlist_germplasm_info_') == -1) {
333 push @wishlists, [$r->file_id, $r->filetype];
336 #print STDERR Dumper \@wishlists;
338 $c->stash->{rest} = { success => 1, wishlists => \@wishlists };
339 $c->detach();
342 sub get_odk_cross_progress_cached : Path('/ajax/odk/get_odk_cross_progress_cached') : ActionClass('REST') { }
344 sub get_odk_cross_progress_cached_GET {
345 my ( $self, $c ) = @_;
346 my $wishlist_file_id = $c->req->param("cross_wishlist_file_id");
347 my $session_id = $c->req->param("sgn_session_id");
348 my $user_id;
349 my $user_name;
350 my $user_role;
351 if ($session_id){
352 my $dbh = $c->dbc->dbh;
353 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
354 if (!$user_info[0]){
355 $c->stash->{rest} = {error=>'You must be logged in to see ODK crossing data progress!'};
356 $c->detach();
358 $user_id = $user_info[0];
359 $user_role = $user_info[1];
360 my $p = CXGN::People::Person->new($dbh, $user_id);
361 $user_name = $p->get_username;
362 } else{
363 if (!$c->user){
364 $c->stash->{rest} = {error=>'You must be logged in to see ODK crossing data progress!'};
365 $c->detach();
367 $user_id = $c->user()->get_object()->get_sp_person_id();
368 $user_name = $c->user()->get_object()->get_username();
369 $user_role = $c->user->get_object->get_user_type();
371 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
372 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
374 my $dir = catdir($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
375 eval { make_path($dir) };
376 if ($@) {
377 print "Couldn't create $dir: $@";
379 my $filename = $dir."/entire_odk_cross_progress_html_".$wishlist_file_id.".txt";
380 print STDERR "Opening $filename \n";
381 my $contents;
382 open(my $fh, '<', $filename) or die "cannot open file $filename";
384 local $/;
385 $contents = decode_json <$fh>;
387 close($fh);
388 my $json = $contents->{top_level_json};
390 my $top_level_id = $c->req->param('id');
391 print STDERR "ODK Cross Tree Progress Node: ".$top_level_id."\n";
392 if ($top_level_id eq '#'){
393 $top_level_id = undef;
395 if ($top_level_id){
396 my $top_level_contents = $contents->{top_level_contents};
397 $json = $top_level_contents->{$top_level_id};
400 #print STDERR Dumper $json;
401 $c->stash->{rest} = $json;
404 sub get_odk_cross_summary_cached : Path('/ajax/odk/get_odk_cross_summary_cached') : ActionClass('REST') { }
406 sub get_odk_cross_summary_cached_GET {
407 my ( $self, $c ) = @_;
408 my $wishlist_file_id = $c->req->param("cross_wishlist_file_id");
409 my $session_id = $c->req->param("sgn_session_id");
410 my $user_id;
411 my $user_name;
412 my $user_role;
413 if ($session_id){
414 my $dbh = $c->dbc->dbh;
415 my @user_info = CXGN::Login->new($dbh)->query_from_cookie($session_id);
416 if (!$user_info[0]){
417 $c->stash->{rest} = {error=>'You must be logged in to see ODK crossing data progress!'};
418 $c->detach();
420 $user_id = $user_info[0];
421 $user_role = $user_info[1];
422 my $p = CXGN::People::Person->new($dbh, $user_id);
423 $user_name = $p->get_username;
424 } else{
425 if (!$c->user){
426 $c->stash->{rest} = {error=>'You must be logged in to see ODK crossing data progress!'};
427 $c->detach();
429 $user_id = $c->user()->get_object()->get_sp_person_id();
430 $user_name = $c->user()->get_object()->get_username();
431 $user_role = $c->user->get_object->get_user_type();
433 my $bcs_schema = $c->dbic_schema('Bio::Chado::Schema', 'sgn_chado');
434 my $metadata_schema = $c->dbic_schema("CXGN::Metadata::Schema");
436 my $dir = catdir($c->site_cluster_shared_dir, "ODK_ONA_cross_info");
437 eval { make_path($dir) };
438 if ($@) {
439 print "Couldn't create $dir: $@";
441 my $filename = $dir."/entire_odk_cross_progress_html_".$wishlist_file_id.".txt";
442 print STDERR "Opening $filename \n";
443 my $contents;
444 open(my $fh, '<', $filename) or die "cannot open file $filename";
446 local $/;
447 $contents = decode_json <$fh>;
449 close($fh);
450 my $summary = $contents->{summary_info};
451 my $plant_status_summary = $contents->{summary_plant_status_info};
453 #print STDERR Dumper $summary;
454 $c->stash->{rest} = { summary => $summary, plant_status_summary => $plant_status_summary };