package csc::Controller::callforward; use strict; use warnings; use base 'Catalyst::Controller'; use csc::Utils; use HTML::Entities; use POSIX; sub base :Chained('/') PathPrefix CaptureArgs(0) { my ( $self, $c ) = @_; return unless ( $c->stash->{subscriber} = $c->forward ('load_subscriber') ); return unless ( $c->stash->{cf_maps} = $c->forward ('load_maps') ); $c->stash->{subscriber}{active_number} = csc::Utils::get_active_number_string($c); } ############################################################################## ### mapping ### # 302 to old callforward-link sub mapping_oldskool : Chained('base') PathPart('') Args(0) { my ( $self, $c ) = @_; $c->response->redirect($c->uri_for ('/callforward/mapping'), 301); } sub mapping : Chained('base') PathPart('mapping') CaptureArgs(0) { my ( $self, $c ) = @_; $c->stash->{template} = 'tt/callforward_mapping.tt'; return unless ( $c->stash->{cf_types} = $c->forward ('load_cf_types') ); return unless ( $c->stash->{time_sets} = $c->forward ('load_time_sets') ); return unless ( $c->stash->{destination_sets} = $c->forward ('load_destination_sets') ); return unless ( $c->stash->{preferences} = $c->forward ('load_preferences') ); } sub mapping_list : Chained('mapping') PathPart('') Args(0) { my ( $self, $c ) = @_; if (defined $c->session->{refill}) { $c->stash->{preferences}->{ringtimeout} = $c->session->{refill}->{ringtimeout}; $c->session->{refill} = undef; } } sub mapping_id : Chained('mapping') PathPart('') CaptureArgs(1) { my ( $self, $c, $map_id ) = @_; $c->stash->{map_id} = $map_id; } sub mapping_edit : Chained('mapping_id') PathPart('edit') Args(0) { my ( $self, $c ) = @_; } sub mapping_save : Chained('mapping') PathPart('save') Args(0) { my ( $self, $c ) = @_; my $map = { id => $c->request->params->{map_id}, type => $c->request->params->{type}, destination_set_id => ($c->request->params->{destset_id} != 0) ? $c->request->params->{destset_id}: undef, time_set_id => ($c->request->params->{timeset_id} != 0) ? $c->request->params->{timeset_id} : undef, }; unless (defined $map->{destination_set_id}) { $c->session->{messages} = { toperr => 'Client.Syntax.MissingDestinationSet' }; $c->response->redirect($c->uri_for ('/callforward/mapping')); $c->detach; } my $ret; if ($map->{id}) { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'update_subscriber_cf_map', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, data => $map, }, undef, ); } else { delete $map->{id}; $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'create_subscriber_cf_map', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, data => $map, }, undef, ); } if ($ret) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' }; } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound' }; } $c->response->redirect($c->uri_for ('/callforward/mapping')); } sub mapping_delete : Chained('mapping') PathPart('delete') Args(0) { my ( $self, $c ) = @_; if ($c->model('Provisioning')->call_prov( $c, 'voip', 'delete_subscriber_cf_map', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, id => $c->request->params->{map_id}, }, undef, )) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' } ; } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound' } ; } $c->response->redirect($c->uri_for ('/callforward/mapping')); } ############################################################################## ### destination ### sub destination : Chained('base') PathPart('destination') CaptureArgs(0) { my ( $self, $c ) = @_; $c->stash->{template} = 'tt/callforward_destination.tt'; return unless ( $c->stash->{destination_sets} = $c->forward ('load_destination_sets') ); # collect data about different sets being mapped my $mapped = {}; foreach my $set (@{$c->stash->{destination_sets}}) { $mapped->{$set->{id}} = 0; if ($c->stash->{cf_maps}) { foreach my $map (values %{$c->stash->{cf_maps}}) { foreach my $part (@$map) { $mapped->{$set->{id}}++ if ($part->{destination_set_id} == $set->{id}); } } } } $c->stash->{mapped} = $mapped; # refill/update datastructure presented to template. necessary if user # edits, errs and form is redisplayed. # if (defined $c->session->{refill}) { foreach my $set (@{$c->stash->{destination_sets}}) { next if ($set->{id} != $c->session->{refill}->{set_id}); delete $c->session->{refill}->{set_id}; if (defined $c->session->{refill}->{item_id}) { foreach my $item (@{$set->{destinations}}) { next if ($item->{id} != $c->session->{refill}->{item_id}); delete $c->session->{refill}->{item_id}; $c->stash->{dtarget_id} = $item->{id}; foreach my $key (keys %{$c->session->{refill}}) { $item->{$key} = $c->session->{refill}->{$key}; } } # all new item if (exists $c->session->{refill}->{item_id}) { delete $c->session->{refill}->{item_id}; # indicate that this is not yet in the database my $item = { id => -1 }; $c->stash->{dtarget_id} = $item->{id}; foreach my $key (keys %{$c->session->{refill}}) { $item->{$key} = $c->session->{refill}->{$key}; } push @{$set->{destinations}}, $item; } } foreach my $key (keys %{$c->session->{refill}}) { $set->{$key} = $c->session->{refill}->{$key}; } } delete $c->session->{refill}; } } sub destination_list : Chained('destination') PathPart('') Args(0) { my ( $self, $c ) = @_; } sub destination_set_get : Chained('destination') PathPart('set') CaptureArgs(1) { my ( $self, $c, $dset_id ) = @_; $c->stash->{dset_id} = $dset_id; } sub destination_set_post : Chained('destination') PathPart('set') CaptureArgs(0) { my ( $self, $c, $dset_id ) = @_; $c->stash->{dset_id} = $c->request->params->{dset_id}; } ### join with destination_set_get? sub destination_set_edit : Chained('destination_set_get') PathPart('edit') Args(0) { my ( $self, $c ) = @_; } sub destination_set_save : Chained('destination_set_post') PathPart('save') Args(0) { my ( $self, $c ) = @_; my $ret; if ($c->stash->{dset_id}) { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'update_subscriber_cf_destination_set', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, data => { name => $c->request->params->{dsetname}, id => $c->stash->{dset_id}, }, }, undef, ); # only if user fiddeled with priorities if ($c->request->params->{priority_changed}) { foreach my $s (@{$c->stash->{destination_sets}}) { next if ($s->{id} != $c->stash->{dset_id}); foreach my $d (@{$s->{destinations}}) { my $prio = $c->request->params->{'priority-' . $d->{id}}; my $id = $d->{id}; $c->model('Provisioning')->call_prov( $c, 'voip', 'update_subscriber_cf_destination_by_id', { id => $id, data => { priority => $prio }, }, undef ); } } } } else { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'create_subscriber_cf_destination_set', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, data => { name => $c->request->params->{dsetname}, }, }, undef, ) } if ($ret) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings'}; $c->response->redirect($c->uri_for ('/callforward/destination')); } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound'}; $c->response->redirect($c->uri_for('/callforward/destination/set/' . $c->stash->{dset_id} . '/edit')); } } sub destination_set_delete : Chained('destination_set_post') PathPart('delete') Args(0) { my ( $self, $c ) = @_; if ($c->model('Provisioning')->call_prov( $c, 'voip', 'delete_subscriber_cf_destination_set', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, id => $c->stash->{dset_id}, }, undef, )) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' }; } else { $c->session->{messages} = { toperr => 'Server.Voip.SavedSettings' }; } $c->response->redirect($c->uri_for('/callforward/destination')); } ### destination target ### sub destination_target_get : Chained('destination') PathPart('target') CaptureArgs(1) { my ( $self, $c, $dtarget_id ) = @_; $c->stash->{dtarget_id} = $dtarget_id; } sub destination_target_post : Chained('destination') PathPart('target') CaptureArgs(0) { my ( $self, $c ) = @_; $c->stash->{dset_id} = $c->request->params->{dset_id}; $c->stash->{dtarget_id} = $c->request->params->{dtarget_id}; } sub destination_target_edit : Chained('destination_target_get') PathPart('edit') Args(0) { my ( $self, $c ) = @_; } # does save and create sub destination_target_save : Chained('destination_target_post') PathPart('save') Args(0) { my ( $self, $c ) = @_; my $prio = $c->request->params->{priority}; my $fwtype = $c->request->params->{fwtype}; ### $c->stash->{type} = $fwtype; my %messages; my %dest; my $vbdom = $c->config->{voicebox_domain}; my $fmdom = $c->config->{fax2mail_domain}; my $confdom = $c->config->{conference_domain}; my $fw_timeout = $c->request->params->{'dest_timeout'} || 300; my $fw_target_select = $c->request->params->{'dest_target'} || 'disable'; my $fw_target; if ($fw_target_select eq 'sipuri') { $dest{timeout} = $fw_timeout; $fw_target = $c->request->params->{'dest_sipuri'}; # normalize, so we can do some checks. $fw_target =~ s/^sip://i; if($fw_target =~ /^\+?\d+$/) { $fw_target = csc::Utils::get_qualified_number_for_subscriber($c, $fw_target); my $checkresult; return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'check_E164_number', $fw_target, \$checkresult); unless($checkresult) { $messages{toperr} = 'Client.Voip.MalformedNumber' } else { $fw_target = 'sip:'.$fw_target.'@'.$c->stash->{subscriber}->{domain}; } } elsif($fw_target =~ /^[a-z0-9&=+\$,;?\/_.!~*'()-]+\@[a-z0-9.-]+(:\d{1,5})?$/i) { $fw_target = 'sip:'. lc $fw_target; } elsif($fw_target =~ /^[a-z0-9&=+\$,;?\/_.!~*'()-]+$/) { $fw_target = 'sip:'. lc($fw_target) .'@'. $c->stash->{subscriber}->{domain}; } else { $messages{err_target} = 'Client.Voip.MalformedTarget'; $fw_target = $c->request->params->{'dest_sipuri'}; } if ($fw_timeout !~ /^\d+$/) { $messages{err_timeout} = 'Client.Voip.MalformedTimeout'; $fw_timeout = $c->request->params->{'dest_timeout'}; } } elsif($fw_target_select eq 'voicebox') { $fw_target = 'sip:vmu'.$c->stash->{subscriber}->{cc}.$c->stash->{subscriber}->{ac}.$c->stash->{subscriber}->{sn}."\@$vbdom"; } elsif($fw_target_select eq 'fax2mail') { $fw_target = 'sip:'.$c->stash->{subscriber}->{cc}.$c->stash->{subscriber}->{ac}.$c->stash->{subscriber}->{sn}."\@$fmdom"; } elsif($fw_target_select eq 'conference') { $fw_target = 'sip:conf='.$c->stash->{subscriber}->{cc}.$c->stash->{subscriber}->{ac}.$c->stash->{subscriber}->{sn}."\@$confdom"; } if (keys %messages) { $messages{topterr} = 'Client.Voip.InputErrorFound'; $c->session->{messages} = \%messages; $c->session->{refill} = { set_id => $c->stash->{dset_id}, item_id => $c->stash->{dtarget_id}, destination => $fw_target, timeout => $fw_timeout }; if ($c->stash->{dtarget_id}) { $c->response->redirect($c->uri_for('/callforward/destination/target/'.$c->stash->{dtarget_id}.'/edit#dest-'.$c->stash->{dtarget_id})); } else { # XXX create a new target "inside" existing set $c->session->{refill}->{item_id} = -1; $c->response->redirect($c->uri_for('/callforward/destination#dset-'.$c->stash->{dset_id})); } $c->detach; } $dest{destination} = $fw_target; $dest{priority} = $prio; my $ret; if ($c->stash->{dtarget_id}) { $dest{id} = $c->stash->{dtarget_id}; $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'update_subscriber_cf_destination', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, set_id => $c->stash->{dset_id}, data => \%dest, }, undef, ) } else { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'create_subscriber_cf_destination', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, set_id => $c->stash->{dset_id}, data => \%dest, }, undef, ) } if ($ret) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' }; } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound' } ; } $c->response->redirect($c->uri_for('/callforward/destination')); } sub destination_target_delete : Chained('destination_target_post') PathPart('delete') Args(0) { my ( $self, $c ) = @_; if ($c->model('Provisioning')->call_prov( $c, 'voip', 'delete_subscriber_cf_destination', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, set_id => $c->stash->{dset_id}, id => $c->stash->{dtarget_id}, }, undef, )) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' }; } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound' }; } $c->response->redirect($c->uri_for('/callforward/destination')); } ############################################################################## ### period ### sub time : Chained('base') PathPart('time') CaptureArgs(0) { my ( $self, $c ) = @_; $c->stash->{template} = 'tt/callforward_time.tt'; return unless ( $c->stash->{time_sets} = $c->forward ('load_time_sets') ); foreach my $tset (@{$c->stash->{time_sets}}) { foreach my $period (@{$tset->{periods}}) { $self->period_expand($period); } } my $year = strftime("%Y", localtime(time())); $c->stash->{years} = [ $year .. $year + 10 ]; my $mapped = {}; foreach my $set (@{$c->stash->{time_sets}}) { $mapped->{$set->{id}} = 0; if ($c->stash->{cf_maps}) { foreach my $map (values %{$c->stash->{cf_maps}}) { foreach my $part (@$map) { $mapped->{$set->{id}}++ if ($part->{time_set_id} == $set->{id}); } } } } $c->stash->{mapped} = $mapped; if (defined $c->session->{refill}) { foreach my $set (@{$c->stash->{time_sets}}) { next if ($set->{id} != $c->session->{refill}->{set_id}); delete $c->session->{refill}->{set_id}; if (defined $c->session->{refill}->{item_id}) { foreach my $item (@{$set->{periods}}) { next if ($item->{id} != $c->session->{refill}->{item_id}); delete $c->session->{refill}->{item_id}; foreach my $key (keys %{$c->session->{refill}}) { $item->{$key} = $c->session->{refill}->{$key}; } } # all new item if (exists $c->session->{refill}->{item_id}) { delete $c->session->{refill}->{item_id}; my $item = { id => -1 }; # indicate that this is not yet in the database $c->stash->{tperiod_id} = $item->{id}; foreach my $key (keys %{$c->session->{refill}}) { $item->{$key} = $c->session->{refill}->{$key}; } push @{$set->{periods}}, $item; } } foreach my $key (keys %{$c->session->{refill}}) { $set->{$key} = $c->session->{refill}->{$key}; } } delete $c->session->{refill}; } } # sub time_list : Chained('time') PathPart('list') Args(0) { sub time_list : Chained('time') PathPart('') Args(0) { my ( $self, $c ) = @_; } sub time_set_get : Chained('time') PathPart('set') CaptureArgs(1) { my ( $self, $c, $tset_id ) = @_; $c->stash->{tset_id} = $tset_id; } sub time_set_post : Chained('time') PathPart('set') CaptureArgs(0) { my ( $self, $c ) = @_; $c->stash->{tset_id} = $c->request->params->{tset_id}; } sub time_set_edit : Chained('time_set_get') PathPart('edit') Args(0) { my ( $self, $c ) = @_; } sub time_set_save : Chained('time_set_post') PathPart('save') Args(0) { my ( $self, $c ) = @_; my $ret; if (defined $c->stash->{tset_id}) { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'update_subscriber_cf_time_set', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, data => { name => $c->request->params->{tsetname}, id => $c->request->params->{tset_id}, } }, undef, ) } else { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'create_subscriber_cf_time_set', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, data => { name => $c->request->params->{tsetname}, } }, undef, ) } if ($ret) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' } } else { $c->session->{messages} = { toperr => 'Client.Voip.Client.Voip.InputErrorFound' } } $c->response->redirect($c->uri_for('/callforward/time')); } sub time_set_delete : Chained('time_set_post') PathPart('delete') Args(0) { my ( $self, $c ) = @_; if ($c->model('Provisioning')->call_prov( $c, 'voip', 'delete_subscriber_cf_time_set', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, id => $c->stash->{tset_id}, }, undef, )) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' } } else { $c->session->{messages} = { toperr => 'Client.Voip.Client.Voip.InputErrorFound' } } $c->response->redirect($c->uri_for('/callforward/time')); } sub time_period_get : Chained('time') PathPart('period') CaptureArgs(1) { my ( $self, $c, $tperiod_id ) = @_; $c->stash->{tperiod_id} = $tperiod_id; } sub time_period_post : Chained('time') PathPart('period') CaptureArgs(0) { my ( $self, $c ) = @_; $c->stash->{tset_id} = $c->request->params->{tset_id}; $c->stash->{tperiod_id} = $c->request->params->{tperiod_id}; } sub time_period_edit : Chained('time_period_get') PathPart('edit') Args(0) { my ( $self, $c ) = @_; } sub time_period_save : Chained('time_period_post') PathPart('save') Args(0) { my ( $self, $c ) = @_; my %period; $period{from_year} = $c->request->params->{from_year}; $period{to_year} = $c->request->params->{to_year}; $period{from_month} = $c->request->params->{from_month}; $period{to_month} = $c->request->params->{to_month}; $period{from_mday} = $c->request->params->{from_mday}; $period{to_mday} = $c->request->params->{to_mday}; $period{from_wday} = $c->request->params->{from_wday}; $period{to_wday} = $c->request->params->{to_wday}; $period{from_hour} = $c->request->params->{from_hour}; $period{to_hour} = $c->request->params->{to_hour}; $period{from_minute} = $c->request->params->{from_minute}; $period{to_minute} = $c->request->params->{to_minute}; $c->session->{messages} = $self->period_collapse(\%period); if (keys %{$c->session->{messages}}) { $c->session->{refill} = { set_id => $c->stash->{tset_id}, item_id => $c->stash->{tperiod_id}, from_year => $c->request->params->{from_year}, to_year => $c->request->params->{to_year}, from_month => $c->request->params->{from_month}, to_month => $c->request->params->{to_month}, from_mday => $c->request->params->{from_mday}, to_mday => $c->request->params->{to_mday}, from_wday => $c->request->params->{from_wday}, to_wday => $c->request->params->{to_wday}, from_hour => $c->request->params->{from_hour}, to_hour => $c->request->params->{to_hour}, from_minute => $c->request->params->{from_minute}, to_minute => $c->request->params->{to_minute}, }; if ($c->stash->{tperiod_id}) { $c->response->redirect($c->uri_for('/callforward/time/period/' . $c->stash->{tperiod_id} . '/edit#tperiod-'.$c->stash->{tperiod_id})); } else { $c->session->{refill}->{item_id} = -1; $c->response->redirect($c->uri_for('/callforward/time#tset-'.$c->stash->{tset_id})); } $c->detach; } $period{id} = $c->stash->{tperiod_id} if ($c->stash->{tperiod_id}); my $ret; if ($c->stash->{tperiod_id}) { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'update_subscriber_cf_time_period', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, set_id => $c->stash->{tset_id}, data => \%period, }, undef, ); } else { $ret = $c->model('Provisioning')->call_prov( $c, 'voip', 'create_subscriber_cf_time_period', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, set_id => $c->stash->{tset_id}, data => \%period, }, undef, ); } if ($ret) { $c->session->{messages}{topmsg} = 'Server.Voip.SavedSettings'; } else { $c->session->{messages}{toperr} = 'Client.Voip.InputErrorFound'; } $c->response->redirect($c->uri_for('/callforward/time')); } sub time_period_delete : Chained('time_period_post') PathPart('delete') Args(0) { my ( $self, $c ) = @_; if ($c->model('Provisioning')->call_prov( $c, 'voip', 'delete_subscriber_cf_time_period', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, set_id => $c->stash->{tset_id}, id => $c->stash->{tperiod_id}, }, undef, )) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' }; } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound' }; } $c->response->redirect($c->uri_for('/callforward/time')); } sub set_ringtimeout : Chained('base') PathPart('set_ringtimeout') Args(0) { my ($self, $c) = @_; my %messages; my $ringtimeout = $c->request->params->{ringtimeout} || 666; if ($ringtimeout =~ /^\d+$/ and $ringtimeout ~~ [5..300]) { if ($c->model('Provisioning')->call_prov( $c, 'voip', 'set_subscriber_preferences', { username => $c->session->{user}->{data}->{username}, domain => $c->session->{user}->{data}->{domain}, preferences => { ringtimeout => $ringtimeout } })) { $c->session->{messages} = { topmsg => 'Server.Voip.SavedSettings' }; } } else { $c->session->{messages} = { toperr => 'Client.Voip.InputErrorFound', ringtimeout_error => 'Client.Voip.MissingRingtimeout', }; $c->session->{refill} = { ringtimeout => $ringtimeout }; } $c->response->redirect($c->uri_for('/callforward/mapping')); } ### helpers ### sub load_destination_sets :Private { my ( $self, $c ) = @_; my $destination_sets; return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_cf_destination_sets', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, }, \$destination_sets, ); my $vbdom = $c->config->{voicebox_domain}; my $fmdom = $c->config->{fax2mail_domain}; my $confdom = $c->config->{conference_domain}; foreach my $set (@{$destination_sets}) { foreach my $dest (@{$set->{destinations}}) { if($dest->{destination} =~ /\@$vbdom$/) { $dest->{destination} = 'voicebox'; } elsif ($dest->{destination} =~ /\@$fmdom$/) { $dest->{destination} = 'fax2mail'; } elsif ($dest->{destination} =~ /\@$confdom$/) { $dest->{destination} = 'conference'; } elsif ($dest->{destination} =~ /^sip:\+?[0-9]+\@/) { $dest->{destination} =~ s/^sip:([^\@]+)\@.+$/$1/; } #else { # die; #} } } return $destination_sets; } sub load_time_sets :Private { my ( $self, $c ) = @_; my $time_sets; return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_cf_time_sets', { username => $c->session->{user}->{data}->{username}, domain => $c->session->{user}->{data}->{domain}, }, \$time_sets, ); return $time_sets; } sub load_subscriber :Private { my ( $self, $c ) = @_; my $subscriber; return unless $c->model('Provisioning')->call_prov( $c, 'billing', 'get_voip_account_subscriber_by_id', { subscriber_id => $c->session->{user}->{data}->{subscriber_id} }, \$subscriber, ); $subscriber->{active_number} = csc::Utils::get_active_number_string($c); return $subscriber; } sub load_maps :Private { my ( $self, $c ) = @_; my $maps; return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_cf_maps', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, }, \$maps, ); return $maps; } sub load_cf_types :Private { my ( $self, $c ) = @_; return [ { name => 'cfu', description => 'Call Forward Unconditional' }, { name => 'cfb', description => 'Call Forward Busy' }, { name => 'cft', description => 'Call Forward Timeout' }, { name => 'cfna', description => 'Call Forward Unavailable' }, ]; } sub period_expand : Private { my ($self, $period) = @_; foreach my $part ('year', 'month', 'mday', 'wday', 'hour', 'minute') { if (defined $period->{$part} && $period->{$part} =~ /^(\d+)$/) { $period->{'from_' . $part} = $1; } elsif(defined $period->{$part} && $period->{$part} =~ /^(\d+)\-(\d+)$/) { $period->{'from_' . $part} = $1; $period->{'to_' . $part} = $2; } delete $period->{$part}; } return 0; } sub period_collapse : Private { my ($self, $period) = @_; my %messages; foreach my $part ('year', 'month', 'mday', 'wday', 'hour', 'minute') { my $from = ( $period->{'from_' . $part} >= 0 ) ? $period->{'from_' . $part} : undef; my $to = ( $period->{'to_' . $part} >= 0 ) ? $period->{'to_' . $part} : undef; my $collapsed; if (defined $from) { $collapsed = $from; if (defined $to) { if ($part eq 'year' && $from > $to) { $messages{err_year} = 'Client.Syntax.FromAfterTo'; } $collapsed .= '-' . $to; } } elsif (defined $to) { $messages{'err_'.$part} = 'Client.Syntax.FromMissing'; } delete $period->{'from_' . $part}; delete $period->{'to_' . $part}; $period->{$part} = $collapsed; } return \%messages; } sub load_preferences :Private { my ( $self, $c ) = @_; my $prefs; return unless $c->model('Provisioning')->call_prov( $c, 'voip', 'get_subscriber_preferences', { username => $c->stash->{subscriber}->{username}, domain => $c->stash->{subscriber}->{domain}, }, \$prefs, ); return $prefs; } 1;