]>
Commit | Line | Data |
---|---|---|
37dd20ad TC |
1 | package BSE::UI::AdminSeminar; |
2 | use strict; | |
3 | use base qw(BSE::UI::AdminDispatch); | |
20d6805f | 4 | use BSE::Util::Tags qw(tag_hash tag_error_img tag_hash_plain); |
37dd20ad TC |
5 | use BSE::Util::DynSort qw(sorter tag_sorthelp); |
6 | use BSE::Template; | |
7 | use BSE::Util::Iterate; | |
8 | use BSE::TB::Locations; | |
2076966c | 9 | use DevHelp::HTML qw(:default popup_menu); |
37dd20ad | 10 | use constant SECT_LOCATION_VALIDATION => "BSE Location Validation"; |
2076966c | 11 | use BSE::CfgInfo 'product_options'; |
11c35ec9 | 12 | use DevHelp::Date qw(dh_strftime_sql_datetime); |
37dd20ad TC |
13 | |
14 | my %rights = | |
15 | ( | |
20d6805f TC |
16 | loclist => 'bse_location_list', |
17 | locaddform => 'bse_location_add', | |
18 | locadd => 'bse_location_add', | |
19 | locedit => 'bse_location_edit', | |
20 | locsave => 'bse_location_edit', | |
21 | locview => 'bse_location_view', | |
22 | locdelask => 'bse_location_delete', | |
23 | locdelete => 'bse_location_delete', | |
24 | # detail => 'bse_subscr_detail', | |
25 | # update => 'bse_subscr_update', | |
26 | addattendseminar => 'bse_session_booking_add', | |
27 | addattendsession => 'bse_session_booking_add', | |
28 | addattendsave => 'bse_session_booking_add', | |
29 | cancelbookingconfirm => 'bse_session_booking_cancel', | |
30 | cancelbooking => 'bse_session_booking_cancel', | |
31 | editbooking => 'bse_session_booking_edit', | |
32 | savebooking => 'bse_session_booking_edit', | |
37dd20ad TC |
33 | ); |
34 | ||
35 | sub actions { \%rights } | |
36 | ||
37 | sub rights { \%rights } | |
38 | ||
39 | sub default_action { 'loclist' } | |
40 | ||
41 | sub req_loclist { | |
42 | my ($class, $req, $errors) = @_; | |
43 | ||
44 | my $msg = $req->message($errors); | |
45 | my $cgi = $req->cgi; | |
46 | my @locations = BSE::TB::Locations->all; | |
47 | my ($sortby, $reverse) = | |
48 | sorter(data=>\@locations, cgi=>$cgi, sortby=>'description', | |
49 | session=>$req->session, | |
50 | name=>'locations', fields=> { id => {numeric => 1 } }); | |
51 | my $it = BSE::Util::Iterate->new; | |
52 | my $current_loc; | |
53 | ||
54 | my %acts; | |
55 | %acts = | |
56 | ( | |
57 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
58 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
59 | BSE::Util::Tags->secure($req), | |
60 | msg => $msg, | |
61 | message => $msg, | |
62 | $it->make_paged_iterator('ilocation', 'locations', \@locations, undef, | |
63 | $cgi, undef, 'pp=20', $req->session, | |
64 | 'locations', \$current_loc), | |
65 | sorthelp => [ \&tag_sorthelp, $sortby, $reverse ], | |
66 | sortby=>$sortby, | |
67 | reverse=>$reverse, | |
68 | ifRemovable => [ \&tag_ifRemovable, \$current_loc ], | |
69 | ); | |
70 | ||
71 | return $req->dyn_response('admin/locations/list', \%acts); | |
72 | } | |
73 | ||
74 | sub tag_ifRemovable { | |
75 | my ($rlocation) = @_; | |
76 | ||
77 | $$rlocation or return; | |
78 | ||
79 | $$rlocation->is_removable; | |
80 | } | |
81 | ||
82 | sub tag_field { | |
83 | my ($fields, $args) = @_; | |
84 | ||
85 | my ($name, $parm) = split ' ', $args; | |
86 | ||
87 | exists $fields->{$name} | |
88 | or return "** Unknown field $name **"; | |
89 | exists $fields->{$name}{$parm} | |
90 | or return ''; | |
91 | ||
92 | return escape_html($fields->{$name}{$parm}); | |
93 | } | |
94 | ||
95 | sub req_locaddform { | |
96 | my ($class, $req, $errors) = @_; | |
97 | ||
98 | my $msg = $req->message($errors); | |
99 | ||
100 | my %fields = BSE::TB::Location->valid_fields(); | |
16ac5598 | 101 | my $cfg_fields = $req->configure_fields(\%fields, SECT_LOCATION_VALIDATION); |
37dd20ad TC |
102 | |
103 | my %acts; | |
104 | %acts = | |
105 | ( | |
106 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
107 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
108 | BSE::Util::Tags->secure($req), | |
109 | msg => $msg, | |
110 | message => $msg, | |
111 | error_img => [ \&tag_error_img, $req->cfg, $errors ], | |
16ac5598 | 112 | field => [ \&tag_field, $cfg_fields ], |
37dd20ad TC |
113 | ); |
114 | ||
115 | return $req->dyn_response('admin/locations/add', \%acts); | |
116 | } | |
117 | ||
118 | sub req_locadd { | |
119 | my ($class, $req) = @_; | |
120 | ||
121 | my $cgi = $req->cgi; | |
122 | my $cfg = $req->cfg; | |
123 | my %fields = BSE::TB::Location->valid_fields($cfg); | |
124 | my %rules = BSE::TB::Location->valid_rules($cfg); | |
125 | my %errors; | |
126 | $req->validate(errors=> \%errors, | |
127 | fields=> \%fields, | |
128 | rules => \%rules, | |
129 | section => SECT_LOCATION_VALIDATION); | |
130 | ||
131 | keys %errors | |
132 | and return $class->req_locaddform($req, \%errors); | |
133 | ||
134 | my %location; | |
135 | for my $field (keys %fields) { | |
136 | $location{$field} = $cgi->param($field); | |
137 | } | |
138 | $location{disabled} = 0; | |
139 | my @cols = BSE::TB::Location->columns; | |
140 | shift @cols; | |
141 | my $loc = BSE::TB::Locations->add(@location{@cols}); | |
142 | ||
143 | my $r = $class->_loclist_refresh($req, "Location $location{description} added"); | |
144 | ||
145 | return BSE::Template->get_refresh($r, $req->cfg); | |
146 | } | |
147 | ||
148 | sub _loc_show_common { | |
149 | my ($class, $req, $errors, $template) = @_; | |
150 | ||
151 | my $loc_id = $req->cgi->param('id'); | |
152 | $loc_id && $loc_id =~ /^\d+/ | |
153 | or return $class->req_loclist | |
154 | ($req, { id=>'Missing or invalid location id' }); | |
155 | my $location = BSE::TB::Locations->getByPkey($loc_id); | |
156 | $location | |
157 | or return $class->req_loclist | |
158 | ($req, { id=>'Unknown location id' }); | |
159 | ||
160 | my $msg = $req->message($errors); | |
161 | ||
162 | my %fields = BSE::TB::Location->valid_fields(); | |
16ac5598 | 163 | my $cfg_fields = $req->configure_fields(\%fields, SECT_LOCATION_VALIDATION); |
37dd20ad | 164 | |
2076966c TC |
165 | my $it = BSE::Util::Iterate->new; |
166 | ||
37dd20ad TC |
167 | my %acts; |
168 | %acts = | |
169 | ( | |
170 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
171 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
172 | BSE::Util::Tags->secure($req), | |
173 | msg => $msg, | |
174 | message => $msg, | |
175 | error_img => [ \&tag_error_img, $req->cfg, $errors ], | |
176 | location => [ \&tag_hash, $location ], | |
16ac5598 | 177 | field => [ \&tag_field, $cfg_fields ], |
2076966c TC |
178 | $it->make_iterator([ \&iter_locsessions, $location ], |
179 | 'session', 'sessions'), | |
37dd20ad TC |
180 | ); |
181 | ||
2076966c TC |
182 | my $t = $req->cgi->param('_t'); |
183 | if ($t && $t =~ /^\w+$/) { | |
184 | $template .= "_$t"; | |
185 | } | |
186 | ||
37dd20ad TC |
187 | return $req->dyn_response($template, \%acts); |
188 | } | |
189 | ||
2076966c TC |
190 | sub iter_locsessions { |
191 | my ($location) = @_; | |
192 | ||
193 | $location->sessions_detail; | |
194 | } | |
195 | ||
37dd20ad TC |
196 | sub req_locedit { |
197 | my ($class, $req, $errors) = @_; | |
198 | ||
199 | return $class->_loc_show_common($req, $errors, 'admin/locations/edit'); | |
200 | } | |
201 | ||
202 | sub req_locsave { | |
203 | my ($class, $req) = @_; | |
204 | ||
205 | my $loc_id = $req->cgi->param('id'); | |
206 | $loc_id && $loc_id =~ /^\d+/ | |
207 | or return $class->req_loclist | |
208 | ($req, { id=>'Missing or invalid location id' }); | |
209 | my $location = BSE::TB::Locations->getByPkey($loc_id); | |
210 | $location | |
211 | or return $class->req_loclist | |
212 | ($req, { id=>'Unknown location id' }); | |
213 | ||
214 | my $cgi = $req->cgi; | |
215 | my $cfg = $req->cfg; | |
216 | my %fields = $location->valid_fields($cfg); | |
217 | my %rules = $location->valid_rules($cfg); | |
218 | my %errors; | |
219 | $req->validate(errors=> \%errors, | |
220 | fields=> \%fields, | |
221 | rules => \%rules, | |
222 | section => SECT_LOCATION_VALIDATION); | |
223 | ||
224 | keys %errors | |
225 | and return $class->req_locedit($req, \%errors); | |
226 | ||
227 | for my $field (keys %fields) { | |
228 | my $value = $cgi->param($field); | |
229 | $location->{$field} = $value if defined $value; | |
230 | } | |
231 | ||
232 | if ($cgi->param('save_disabled')) { | |
233 | $location->{disabled} = $cgi->param('disabled') ? 1 : 0; | |
234 | } | |
235 | ||
236 | $location->save; | |
237 | ||
238 | my $r = $class->_loclist_refresh($req, | |
239 | "Location $location->{description} saved"); | |
240 | ||
241 | return BSE::Template->get_refresh($r, $req->cfg); | |
242 | } | |
243 | ||
2076966c TC |
244 | sub req_locview { |
245 | my ($class, $req, $errors) = @_; | |
246 | ||
247 | return $class->_loc_show_common($req, $errors, 'admin/locations/view'); | |
248 | } | |
249 | ||
37dd20ad TC |
250 | sub req_locdelask { |
251 | my ($class, $req, $errors) = @_; | |
252 | ||
253 | return $class->_loc_show_common($req, $errors, 'admin/locations/delete'); | |
254 | } | |
255 | ||
256 | sub req_locdelete { | |
257 | my ($class, $req) = @_; | |
258 | ||
259 | my $loc_id = $req->cgi->param('id'); | |
260 | $loc_id && $loc_id =~ /^\d+/ | |
261 | or return $class->req_loclist | |
262 | ($req, { id=>'Missing or invalid location id' }); | |
263 | my $location = BSE::TB::Locations->getByPkey($loc_id); | |
264 | $location | |
265 | or return $class->req_loclist | |
266 | ($req, { id=>'Unknown location id' }); | |
267 | ||
268 | $location->is_removable | |
269 | or return $class->req_loclist | |
270 | ($req, { id=>"Location $location->{description} cannot be removed" }); | |
271 | ||
272 | my $description = $location->{description}; | |
273 | $location->remove; | |
274 | ||
275 | my $r = $class->_loclist_refresh($req, | |
276 | "Location $description removed"); | |
277 | ||
278 | return BSE::Template->get_refresh($r, $req->cfg); | |
279 | } | |
280 | ||
281 | sub _loclist_refresh { | |
282 | my ($class, $req, $msg) = @_; | |
283 | ||
284 | my $r = $req->cgi->param('r') || $req->cgi->param('refreshto'); | |
285 | unless ($r) { | |
286 | $r = "/cgi-bin/admin/admin_seminar.pl"; | |
287 | } | |
288 | if ($msg && $r !~ /[&?]m=/) { | |
289 | my $sep = $r =~ /\?/ ? '&' : '?'; | |
290 | ||
291 | $r .= $sep . "m=" . escape_uri($msg); | |
292 | } | |
293 | ||
294 | return $r; | |
295 | } | |
296 | ||
718a070d TC |
297 | sub req_addattendseminar { |
298 | my ($class, $req, $errors) = @_; | |
299 | ||
300 | # make sure we're passed a valid siteuser_id | |
301 | my $cgi = $req->cgi; | |
302 | my $siteuser_id = $cgi->param('siteuser_id'); | |
303 | defined $siteuser_id && $siteuser_id =~ /^\d+$/ | |
304 | or return $class->req_loclist($req, { siteuser_id => | |
305 | "Missing or invalid siteuser_id" }); | |
306 | require SiteUsers; | |
307 | my $siteuser = SiteUsers->getByPkey($siteuser_id) | |
308 | or return $class->req_loclist($req, { siteuser_id => "Unknown siteuser_id" }); | |
309 | my $msg = $req->message($errors); | |
310 | require BSE::TB::Seminars; | |
311 | my @seminars = BSE::TB::Seminars->all; | |
312 | ||
313 | my $it = BSE::Util::Iterate->new; | |
314 | my %acts; | |
315 | %acts = | |
316 | ( | |
317 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
318 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
319 | BSE::Util::Tags->secure($req), | |
320 | $it->make_iterator(undef, 'seminar', 'seminars', \@seminars), | |
321 | siteuser => [ \&tag_hash, $siteuser ], | |
322 | msg => $msg, | |
323 | message => $msg, | |
324 | error_img => [ \&tag_error_img, $req->cfg, $errors ], | |
325 | ); | |
326 | ||
327 | return $req->dyn_response('admin/addattendee1.tmpl', \%acts); | |
328 | } | |
329 | ||
330 | sub req_addattendsession { | |
331 | my ($class, $req, $errors) = @_; | |
332 | ||
333 | # make sure we're passed a valid siteuser_id | |
334 | my $cgi = $req->cgi; | |
335 | my $siteuser_id = $cgi->param('siteuser_id'); | |
336 | defined $siteuser_id && $siteuser_id =~ /^\d+$/ | |
337 | or return $class->req_loclist($req, { siteuser_id => | |
338 | "Missing or invalid siteuser_id" }); | |
339 | require SiteUsers; | |
340 | my $siteuser = SiteUsers->getByPkey($siteuser_id) | |
341 | or return $class->req_loclist($req, { siteuser_id => "Unknown siteuser_id" }); | |
342 | ||
343 | # make sure we got a valid seminar | |
344 | require BSE::TB::Seminars; | |
345 | my $seminar_id = $cgi->param('seminar_id'); | |
346 | defined $seminar_id && $seminar_id =~ /^\d*$/ | |
347 | or return $class->req_addattendseminar | |
348 | ($req, { seminar_id => "Missing or invalid seminar_id" }); | |
349 | $seminar_id | |
350 | or return $class->req_addattendseminar | |
351 | ($req, { seminar_id => "Please select a seminar" }); | |
352 | my $seminar = BSE::TB::Seminars->getByPkey($seminar_id) | |
353 | or return $class->req_addattendseminar | |
354 | ($req, { seminar_id => "Unknown seminar_id" }); | |
355 | my $msg = $req->message($errors); | |
356 | ||
20d6805f | 357 | my @sem_options = _get_sem_options($req->cfg, $seminar); |
2076966c TC |
358 | my $current_option; |
359 | ||
718a070d TC |
360 | my @sessions = $seminar->session_info; |
361 | my %user_booked = map { $_=>1 } | |
362 | $siteuser->seminar_sessions_booked($seminar_id); | |
363 | @sessions = grep !$user_booked{$_->{id}}, @sessions; | |
364 | ||
365 | my $it = BSE::Util::Iterate->new; | |
366 | my %acts; | |
367 | %acts = | |
368 | ( | |
369 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
370 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
371 | BSE::Util::Tags->secure($req), | |
372 | siteuser => [ \&tag_hash, $siteuser ], | |
373 | seminar => [ \&tag_hash, $seminar ], | |
374 | msg => $msg, | |
375 | message => $msg, | |
376 | error_img => [ \&tag_error_img, $req->cfg, $errors ], | |
377 | $it->make_iterator(undef, 'session', 'sessions', \@sessions), | |
2076966c TC |
378 | $it->make_iterator(undef, 'option', 'options', \@sem_options, |
379 | undef, undef, \$current_option), | |
380 | option_popup => [ \&tag_option_popup, $req->cgi, \$current_option ], | |
718a070d TC |
381 | ); |
382 | ||
383 | return $req->dyn_response('admin/addattendee2.tmpl', \%acts); | |
384 | } | |
385 | ||
2076966c TC |
386 | sub tag_option_popup { |
387 | my ($cgi, $roption) = @_; | |
388 | ||
389 | $$roption | |
390 | or return '** popup_option not in options iterator **'; | |
391 | ||
392 | my $option = $$roption; | |
393 | ||
394 | my @extras; | |
20d6805f TC |
395 | my $value = $cgi->param($option->{id}); |
396 | defined $value or $value = $option->{value}; | |
397 | if ($value) { | |
398 | push @extras, -default => $value; | |
2076966c TC |
399 | } |
400 | ||
401 | return popup_menu(-name => $option->{id}, | |
402 | -values => $option->{values}, | |
403 | -labels => $option->{labels}, | |
404 | @extras); | |
405 | } | |
406 | ||
718a070d TC |
407 | sub req_addattendsave { |
408 | my ($class, $req, $errors) = @_; | |
409 | ||
410 | # make sure we're passed a valid siteuser_id | |
411 | my $cgi = $req->cgi; | |
412 | my $siteuser_id = $cgi->param('siteuser_id'); | |
413 | defined $siteuser_id && $siteuser_id =~ /^\d+$/ | |
414 | or return $class->req_loclist($req, { siteuser_id => | |
415 | "Missing or invalid siteuser_id" }); | |
416 | require SiteUsers; | |
417 | my $siteuser = SiteUsers->getByPkey($siteuser_id) | |
418 | or return $class->req_loclist($req, { siteuser_id => "Unknown siteuser_id" }); | |
419 | ||
420 | # make sure we got a valid seminar | |
421 | require BSE::TB::Seminars; | |
422 | my $seminar_id = $cgi->param('seminar_id'); | |
423 | defined $seminar_id && $seminar_id =~ /^\d*$/ | |
424 | or return $class->req_addattendseminar | |
425 | ($req, { seminar_id => "Missing or invalid seminar_id" }); | |
426 | $seminar_id | |
427 | or return $class->req_addattendseminar | |
428 | ($req, { seminar_id => "Please select a seminar" }); | |
429 | my $seminar = BSE::TB::Seminars->getByPkey($seminar_id) | |
430 | or return $class->req_addattendseminar | |
431 | ($req, { seminar_id => "Unknown seminar_id" }); | |
432 | my $msg = $req->message($errors); | |
433 | ||
434 | # make sure we get a valid session | |
435 | require BSE::TB::SeminarSessions; | |
436 | my $session_id = $cgi->param('session_id'); | |
437 | defined $session_id && $session_id =~ /^\d*$/ | |
438 | or return $class->req_addattendsession | |
439 | ($req, { session_id => "Missing or invalid session_id" }); | |
440 | $session_id | |
441 | or return $class->req_addattendsession | |
442 | ($req, { session_id => "Please select a session" }); | |
443 | my $session = BSE::TB::SeminarSessions->getByPkey($session_id) | |
444 | or return $class->req_addattendsession | |
445 | ($req, { session_id => "Unknown session_id" }); | |
446 | ||
2076966c TC |
447 | # accumulate the options |
448 | my %errors; | |
449 | my @options; | |
450 | for my $opt_name (split /,/, $seminar->{options}) { | |
451 | my $value = $cgi->param($opt_name); | |
452 | defined $value | |
453 | or return $class->req_addattendsession | |
454 | ($req, { opt_name => "Missing value for $opt_name" }); | |
455 | ||
456 | push @options, $value; | |
457 | } | |
458 | ||
459 | my %more; | |
460 | for my $name (qw/customer_instructions support_notes roll_present/) { | |
461 | my $value = $cgi->param($name); | |
462 | $value and $more{$name} = $value; | |
463 | } | |
464 | $more{roll_present} ||= 0; | |
20d6805f | 465 | $more{options} = join(',', @options); |
2076966c | 466 | |
718a070d | 467 | eval { |
20d6805f | 468 | $session->add_attendee($siteuser, %more); |
718a070d TC |
469 | }; |
470 | if ($@) { | |
471 | if ($@ =~ /duplicate/i) { | |
472 | return $class->req_addattendsession | |
473 | ($req, { session_id => "User already booked for this session" }); | |
474 | } | |
11c35ec9 TC |
475 | else { |
476 | return $class->req_addattendsession | |
477 | ($req, { _error => $@ }); | |
478 | } | |
718a070d TC |
479 | } |
480 | ||
20d6805f TC |
481 | require BSE::ComposeMail; |
482 | my $cfg = $req->cfg; | |
483 | my $mailer = BSE::ComposeMail->new(cfg => $cfg); | |
484 | my $subject = $cfg->entry('seminars', 'booked_notify_subject', | |
485 | 'You have been booked for seminar'); | |
486 | my @sem_options = _get_sem_options($cfg, $seminar, @options); | |
487 | my $it = DevHelp::Tags::Iterate->new; | |
488 | my %acts; | |
489 | %acts = | |
490 | ( | |
491 | BSE::Util::Tags->static(undef, $cfg), | |
11c35ec9 | 492 | user => [ \&tag_hash_plain, $siteuser ], |
20d6805f TC |
493 | seminar => [ \&tag_hash_plain, $seminar ], |
494 | session => [ \&tag_hash_plain, $session ], | |
495 | booking => [ \&tag_hash_plain, \%more ], | |
496 | location => [ \&tag_hash_plain, $session->location ], | |
497 | $it->make_iterator(undef, 'option', 'options', \@sem_options), | |
498 | ); | |
499 | ||
500 | unless ($mailer->send(to => $siteuser, | |
501 | subject => $subject, | |
502 | template => 'user/admin_book_seminar', | |
503 | acts => \%acts)) { | |
504 | return $class->req_addattendsession | |
505 | ($req, { _email => "The user has been booked, but there was an error seding the email notification:".$mailer->errstr }); | |
506 | } | |
507 | ||
508 | ||
718a070d TC |
509 | my $r = $cgi->param('r'); |
510 | unless ($r) { | |
511 | $r = "/cgi-bin/admin/siteusers.pl?a_edit=1&id=" . $siteuser->{id}; | |
512 | } | |
718a070d TC |
513 | |
514 | return BSE::Template->get_refresh($r, $req->cfg); | |
515 | } | |
516 | ||
20d6805f TC |
517 | sub req_cancelbookingconfirm { |
518 | my ($class, $req, $message) = @_; | |
519 | ||
520 | my $cgi = $req->cgi; | |
521 | ||
11c35ec9 TC |
522 | my $id = $cgi->param('id'); |
523 | defined $id && $id =~ /^\d+$/ | |
524 | or return $class->error($req, "id parameter invalid"); | |
20d6805f | 525 | |
11c35ec9 TC |
526 | require BSE::TB::SeminarBookings; |
527 | my $booking = BSE::TB::SeminarBookings->getByPkey($id) | |
528 | or return $class->error($req, "booking $id not found"); | |
20d6805f | 529 | |
11c35ec9 TC |
530 | my $session = $booking->session; |
531 | my $siteuser = $booking->siteuser; | |
20d6805f TC |
532 | |
533 | my $seminar = $session->seminar; | |
534 | my @sem_options = _get_sem_options($req->cfg, $seminar, | |
535 | split /,/, $session->{options}); | |
536 | ||
537 | defined $message or $message = ''; | |
538 | $message = escape_html($message); | |
539 | ||
540 | my $it = BSE::Util::Iterate->new; | |
541 | my %acts; | |
542 | %acts = | |
543 | ( | |
544 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
545 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
546 | BSE::Util::Tags->secure($req), | |
547 | siteuser => [ \&tag_hash, $siteuser ], | |
548 | session => [ \&tag_hash, $session ], | |
549 | seminar => [ \&tag_hash, $seminar ], | |
550 | location => [ \&tag_hash, $session->location ], | |
551 | booking => [ \&tag_hash, $booking ], | |
552 | message => $message, | |
553 | $it->make_iterator(undef, 'option', 'options', \@sem_options), | |
554 | ); | |
555 | ||
556 | return $req->dyn_response('admin/semcancelbooking', \%acts); | |
557 | } | |
558 | ||
559 | sub req_cancelbooking { | |
560 | my ($class, $req) = @_; | |
561 | ||
562 | my $cgi = $req->cgi; | |
563 | ||
11c35ec9 TC |
564 | my $id = $cgi->param('id'); |
565 | defined $id && $id =~ /^\d+$/ | |
566 | or return $class->error($req, "id parameter invalid"); | |
20d6805f | 567 | |
11c35ec9 TC |
568 | require BSE::TB::SeminarBookings; |
569 | my $booking = BSE::TB::SeminarBookings->getByPkey($id) | |
570 | or return $class->error($req, "booking $id not found"); | |
20d6805f | 571 | |
11c35ec9 TC |
572 | my $session = $booking->session; |
573 | my $siteuser = $booking->siteuser; | |
20d6805f TC |
574 | |
575 | my @options = split /,/, $booking->{options}; | |
576 | local $SIG{__DIE__}; | |
577 | eval { | |
578 | $session->remove_booking($siteuser); | |
579 | }; | |
580 | $@ and return $class->req_cancelbookingconfirm | |
581 | ($req, "Could not remove booking $@"); | |
582 | ||
583 | my $seminar = $session->seminar; | |
584 | ||
585 | my @sem_options = _get_sem_options($req->cfg, $seminar, @options); | |
586 | ||
587 | require BSE::ComposeMail; | |
588 | my $cfg = $req->cfg; | |
589 | my $mailer = BSE::ComposeMail->new(cfg => $cfg); | |
590 | my $subject = $cfg->entry('seminars', 'unbooked_notify_subject', | |
591 | 'Your seminar booking has been cancelled'); | |
592 | my $it = DevHelp::Tags::Iterate->new; | |
593 | my %acts; | |
594 | %acts = | |
595 | ( | |
596 | BSE::Util::Tags->static(undef, $cfg), | |
11c35ec9 | 597 | user => [ \&tag_hash_plain, $siteuser ], |
20d6805f TC |
598 | seminar => [ \&tag_hash_plain, $seminar ], |
599 | session => [ \&tag_hash_plain, $session ], | |
600 | booking => [ \&tag_hash_plain, $booking ], | |
601 | location => [ \&tag_hash_plain, $session->location ], | |
602 | $it->make_iterator(undef, 'option', 'options', \@sem_options), | |
603 | ); | |
604 | ||
605 | unless ($mailer->send(to => $siteuser, | |
606 | subject => $subject, | |
607 | template => 'user/admin_unbook_seminar', | |
608 | acts => \%acts)) { | |
609 | return $class->req_cancelbookingconfirm | |
610 | ($req, "The user booking was cancelled, but there was an error sending the email notification:".$mailer->errstr ); | |
611 | } | |
612 | ||
613 | my $r = $cgi->param('r'); | |
614 | unless ($r) { | |
615 | $r = '/cgi-bin/admin/siteusers.pl?a_view=1&id='.$siteuser->{id}; | |
616 | } | |
617 | $r .= $r =~ /\?/ ? '&' : '?'; | |
618 | $r .= "m=Booking+cancelled"; | |
619 | ||
620 | return BSE::Template->get_refresh($r, $req->cfg); | |
621 | } | |
622 | ||
623 | sub req_editbooking { | |
624 | my ($class, $req, $errors) = @_; | |
625 | ||
626 | my $cgi = $req->cgi; | |
627 | ||
11c35ec9 TC |
628 | my $id = $cgi->param('id'); |
629 | defined $id && $id =~ /^\d+$/ | |
630 | or return $class->error($req, "id parameter invalid"); | |
20d6805f | 631 | |
11c35ec9 TC |
632 | require BSE::TB::SeminarBookings; |
633 | my $booking = BSE::TB::SeminarBookings->getByPkey($id) | |
634 | or return $class->error($req, "booking $id not found"); | |
20d6805f | 635 | |
11c35ec9 | 636 | my $session = $booking->session; |
20d6805f | 637 | |
11c35ec9 | 638 | my $siteuser = $booking->siteuser; |
20d6805f TC |
639 | |
640 | my $message = $req->message($errors); | |
641 | ||
642 | my $seminar = $session->seminar; | |
643 | my @sem_options = _get_sem_options($req->cfg, $seminar, | |
644 | split /,/, $booking->{options}); | |
11c35ec9 TC |
645 | my @unbooked = $seminar->get_unbooked_by_user($siteuser); |
646 | @unbooked = sort { $b->{when_at} cmp $a->{when_at} } ( @unbooked, $session ); | |
20d6805f TC |
647 | |
648 | my $current_option; | |
649 | my $it = BSE::Util::Iterate->new; | |
650 | my %acts; | |
651 | %acts = | |
652 | ( | |
653 | BSE::Util::Tags->basic(\%acts, $req->cgi, $req->cfg), | |
654 | BSE::Util::Tags->admin(\%acts, $req->cfg), | |
655 | BSE::Util::Tags->secure($req), | |
656 | siteuser => [ \&tag_hash, $siteuser ], | |
657 | session => [ \&tag_hash, $session ], | |
658 | seminar => [ \&tag_hash, $seminar ], | |
659 | location => [ \&tag_hash, $session->location ], | |
660 | booking => [ \&tag_hash, $booking ], | |
661 | message => $message, | |
662 | error_img => [ \&tag_error_img, $req->cfg, $errors ], | |
663 | $it->make_iterator(undef, 'option', 'options', \@sem_options, | |
664 | undef, undef, \$current_option), | |
665 | option_popup => [ \&tag_option_popup, $req->cgi, \$current_option ], | |
11c35ec9 TC |
666 | $it->make_iterator(undef, 'isession', 'sessions', \@unbooked), |
667 | session_popup => [ \&tag_session_popup, $booking, $req->cgi, \@unbooked ], | |
20d6805f TC |
668 | ); |
669 | ||
670 | return $req->dyn_response('admin/semeditbooking', \%acts); | |
671 | } | |
672 | ||
673 | sub req_savebooking { | |
674 | my ($class, $req, $message) = @_; | |
675 | ||
676 | my $cgi = $req->cgi; | |
677 | ||
11c35ec9 TC |
678 | my $id = $cgi->param('id'); |
679 | defined $id && $id =~ /^\d+$/ | |
680 | or return $class->error($req, "id parameter invalid"); | |
20d6805f | 681 | |
11c35ec9 TC |
682 | require BSE::TB::SeminarBookings; |
683 | my $booking = BSE::TB::SeminarBookings->getByPkey($id) | |
684 | or return $class->error($req, "booking $id not found"); | |
20d6805f | 685 | |
11c35ec9 TC |
686 | my @cols = $booking->columns; |
687 | shift @cols; | |
688 | for my $name (@cols) { | |
20d6805f | 689 | my $value = $cgi->param($name); |
11c35ec9 | 690 | defined $value and $booking->set($name => $value); |
20d6805f | 691 | } |
11c35ec9 | 692 | my $seminar = $booking->session->seminar; |
20d6805f TC |
693 | my @options; |
694 | for my $name (split /,/, $seminar->{options}) { | |
695 | push @options, ($cgi->param($name))[0]; | |
696 | } | |
11c35ec9 | 697 | $booking->{options} = join ',', @options; |
20d6805f TC |
698 | |
699 | eval { | |
11c35ec9 | 700 | $booking->save; |
20d6805f TC |
701 | }; |
702 | $@ | |
703 | and return $class->req_editbooking($req, { error => $@ }); | |
704 | ||
705 | my @sem_options = _get_sem_options($req->cfg, $seminar, @options); | |
706 | ||
11c35ec9 TC |
707 | my $session = $booking->session; |
708 | my $siteuser = $booking->siteuser; | |
20d6805f TC |
709 | require BSE::ComposeMail; |
710 | my $cfg = $req->cfg; | |
711 | my $mailer = BSE::ComposeMail->new(cfg => $cfg); | |
712 | my $subject = $cfg->entry('seminars', 'edit_notify_subject', | |
713 | 'Your seminar booking has been changed'); | |
714 | my $it = DevHelp::Tags::Iterate->new; | |
715 | my %acts; | |
716 | %acts = | |
717 | ( | |
718 | BSE::Util::Tags->static(undef, $cfg), | |
11c35ec9 | 719 | user => [ \&tag_hash_plain, $siteuser ], |
20d6805f TC |
720 | seminar => [ \&tag_hash_plain, $seminar ], |
721 | session => [ \&tag_hash_plain, $session ], | |
722 | booking => [ \&tag_hash_plain, $booking ], | |
723 | location => [ \&tag_hash_plain, $session->location ], | |
724 | $it->make_iterator(undef, 'option', 'options', \@sem_options), | |
725 | ); | |
726 | ||
727 | unless ($mailer->send(to => $siteuser, | |
728 | subject => $subject, | |
729 | template => 'user/admin_edit_seminar', | |
730 | acts => \%acts)) { | |
731 | return $class->req_editbooking | |
732 | ($req, _email => "The user booking was changed, but there was an error sending the email notification:".$mailer->errstr ); | |
733 | } | |
734 | ||
735 | my $r = $cgi->param('r'); | |
736 | unless ($r) { | |
737 | $r = '/cgi-bin/admin/siteusers.pl?a_view=1&id='.$siteuser->{id}; | |
738 | } | |
739 | $r .= $r =~ /\?/ ? '&' : '?'; | |
740 | $r .= "m=Booking+updated"; | |
741 | ||
742 | return BSE::Template->get_refresh($r, $req->cfg); | |
743 | } | |
744 | ||
745 | sub _get_sem_options { | |
746 | my ($cfg, $seminar, @values) = @_; | |
747 | ||
748 | my $avail_options = product_options($cfg); | |
749 | my @opt_names = split /,/, $seminar->{options}; | |
750 | push @values, '' while @values < @opt_names; | |
751 | my %values; | |
752 | @values{@opt_names} = @values; | |
753 | ||
754 | my @sem_options = map | |
755 | +{ | |
756 | id => $_, | |
757 | %{$avail_options->{$_}}, | |
758 | value => $values{$_}, | |
759 | }, @opt_names; | |
760 | for my $option (@sem_options) { | |
761 | $option->{display} = $option->{labels}{$option->{value}}; | |
762 | } | |
763 | ||
764 | return @sem_options; | |
765 | } | |
766 | ||
11c35ec9 TC |
767 | sub tag_session_popup { |
768 | my ($booking, $cgi, $unbooked) = @_; | |
769 | ||
770 | my $default = $cgi->param('session_id'); | |
771 | defined $default or $default = $booking->{session_id}; | |
772 | my %locations; | |
773 | for my $session (@$unbooked) { | |
774 | unless ($locations{$session->{location_id}}) { | |
775 | $locations{$session->{location_id}} = $session->location; | |
776 | } | |
777 | } | |
778 | ||
779 | return popup_menu | |
780 | (-name => 'session_id', | |
781 | -values => [ map $_->{id}, @$unbooked ], | |
782 | -labels => | |
783 | { map | |
784 | { $_->{id} => | |
785 | _session_desc($_, $locations{$_->{location_id}}) | |
786 | } @$unbooked | |
787 | }, | |
788 | -default => $default); | |
789 | } | |
790 | ||
791 | sub _session_desc { | |
792 | my ($session, $location) = @_; | |
793 | ||
794 | $location->{description} . ' ' . | |
795 | dh_strftime_sql_datetime("%H:%M %d %b %Y", $session->{when_at}); | |
796 | } | |
797 | ||
37dd20ad | 798 | 1; |