add rate copying, RT#4431
authorivan <ivan>
Mon, 5 Jan 2009 00:26:54 +0000 (00:26 +0000)
committerivan <ivan>
Mon, 5 Jan 2009 00:26:54 +0000 (00:26 +0000)
FS/FS/rate_prefix.pm
httemplate/browse/rate.cgi
httemplate/elements/checkboxes-table-name.html
httemplate/elements/checkboxes.html [new file with mode: 0644]
httemplate/elements/select-rate.html [new file with mode: 0644]
httemplate/elements/tr-select-rate.html [new file with mode: 0644]
httemplate/misc/copy-rate_detail.html [new file with mode: 0644]
httemplate/misc/process/copy-rate_detail.html [new file with mode: 0644]

index 42b004f..ce780fe 100644 (file)
@@ -2,7 +2,7 @@ package FS::rate_prefix;
 
 use strict;
 use vars qw( @ISA );
 
 use strict;
 use vars qw( @ISA );
-use FS::Record qw( qsearch qsearchs );
+use FS::Record qw( qsearch qsearchs dbh );
 use FS::rate_region;
 
 @ISA = qw(FS::Record);
 use FS::rate_region;
 
 @ISA = qw(FS::Record);
@@ -127,6 +127,27 @@ sub rate_region {
 
 =back
 
 
 =back
 
+=head1 CLASS METHODS
+
+=over 4
+
+=item all_countrycodes
+
+Returns a list of all countrycodes listed in rate_prefix
+
+=cut
+
+sub all_countrycodes { 
+  #my $class = shift;
+  my $sql =
+    "SELECT DISTINCT(countrycode) FROM rate_prefix ORDER BY countrycode";
+  my $sth = dbh->prepare($sql) or die  dbh->errstr;
+  $sth->execute                or die $sth->errstr;
+  map $_->[0], @{ $sth->fetchall_arrayref };
+}
+
+=back
+
 =head1 BUGS
 
 =head1 SEE ALSO
 =head1 BUGS
 
 =head1 SEE ALSO
index b20c45c..911b2fd 100644 (file)
 %>
 <%once>
 
 %>
 <%once>
 
-my $sth = dbh->prepare("SELECT DISTINCT(countrycode) FROM rate_prefix")
-  or die dbh->errstr;
-$sth->execute or die $sth->errstr;
-my @all_countrycodes = map $_->[0], @{ $sth->fetchall_arrayref };
 my $all_countrycodes = join("\n", map qq(<OPTION VALUE="$_">$_),
 my $all_countrycodes = join("\n", map qq(<OPTION VALUE="$_">$_),
-                                      @all_countrycodes
+                                      FS::rate_prefix->all_countrycodes
                            );
 
 my $rates_sub = sub {
                            );
 
 my $rates_sub = sub {
@@ -51,6 +47,7 @@ die "access denied"
 my $html_init = 
   'Rate plans for VoIP and call billing.<BR><BR>'.
   qq!<A HREF="${p}edit/rate.cgi"><I>Add a rate plan</I></A>!.
 my $html_init = 
   'Rate plans for VoIP and call billing.<BR><BR>'.
   qq!<A HREF="${p}edit/rate.cgi"><I>Add a rate plan</I></A>!.
+  qq! | <A HREF="${p}misc/copy-rate_detail.html"><I>Copy rates between plans</I></A>!.
   '<BR><BR>
    <SCRIPT>
    function rate_areyousure(href) {
   '<BR><BR>
    <SCRIPT>
    function rate_areyousure(href) {
index b236787..31652f3 100644 (file)
@@ -41,79 +41,12 @@ Example:
 
 </%doc>
 
 
 </%doc>
 
-<TABLE CELLSPACING=0 CELLPADDING=0>
-
-<TR>
-  <TD COLSPAN=2 ALIGN="center"><FONT SIZE="-1">(
-    <A HREF="javascript:setAll<%$prefix%>(true)">select all</A> |
-    <A HREF="javascript:setAll<%$prefix%>(false)">unselect all</A> |
-    <A HREF="javascript:toggleAll<%$prefix%>()">toggle all</A>
-  )</FONT></TD>
-</TR>
-
-% my $num=0;
-% foreach my $item ( @{ $opt{'names_list'} } ) {
-%
-%     my $name = ref($item) ? $item->[0] : $item;
-%     ( my $display = $name ) =~ s/ /&nbsp;/g;
-%     $display .= $item->[1]{note} if ref($item) && $item->[1]{note};
-%     my $desc = ref($item) && $item->[1]{desc} ? $item->[1]{desc} : '';
-%
-%     my $checked;
-%     if ( $cgi->param('error') ) {
-%
-%       $checked = $cgi->param($opt{'link_table'}. ".$name" )
-%                    ? 'CHECKED'
-%                    : '';
-%
-%     } else {
-%
-%       $checked =
-%         qsearchs( $opt{'link_table'}, {
-%                                         $source_pkey     => $sourcenum,
-%                                         $opt{'name_col'} => $name,
-%                                         %$link_static,
-%                                       }                                 )
-%                    ? 'CHECKED'
-%                    : ''
-%
-%     }
-
-  <TR>
-    <TD VALIGN="top">
-      <INPUT TYPE="checkbox" NAME="<% $opt{'link_table'}. ".$name" %>" <% $checked %> ID="<%$prefix.$num++%>" VALUE="ON">
-    </TD>
-    <TD><% $display %>
-%     if ( $desc ) {
-        <BR><FONT SIZE="-2"><% $desc %></FONT>
-%     }
-    </TD>
-  </TR>
-
-% } 
-
-</TABLE>
-
-<SCRIPT TYPE="text/javascript">
-
-  function setAll<%$prefix%>(setTo) {
-%   for ( 0 .. ($num-1) ) {
-      document.getElementById('<%$prefix.$_%>').checked = setTo;
-%   }
-  }
-
-  function toggleAll<%$prefix%>(setTo) {
-%   for ( 0 .. ($num-1) ) {
-      var element = document.getElementById('<%$prefix.$_%>');
-      if ( element.checked == true ) {
-        element.checked = false;
-      } else {
-        element.checked = true;
-      }
-%   }
-  }
-
-</SCRIPT>
+<% include('checkboxes.html',
+             'names_list'             => $opt{'names_list'},
+             'checked_callback'       => $checked_callback,
+             'element_name_prefix'    => $opt{'link_table'}. '.',
+          )
+%>
 
 <%init>
 
 
 <%init>
 
@@ -145,4 +78,13 @@ $source_pkey = $opt{'num_col'} || $source_pkey;
 
 my $link_static = $opt{'link_static'} || {};
 
 
 my $link_static = $opt{'link_static'} || {};
 
+my $checked_callback = sub {
+  my( $cgi, $name ) = @_;
+  qsearchs( $opt{'link_table'}, {
+    $source_pkey     => $sourcenum,
+    $opt{'name_col'} => $name,
+    %$link_static,
+  });
+};
+
 </%init>
 </%init>
diff --git a/httemplate/elements/checkboxes.html b/httemplate/elements/checkboxes.html
new file mode 100644 (file)
index 0000000..1262245
--- /dev/null
@@ -0,0 +1,103 @@
+<%doc>
+
+Example:
+
+  include( '/elements/checkboxes.html',
+
+    # required
+   
+    #? 'name_callback' => sub { },
+   
+    'names_list' => [ 'value',
+                      'other value',
+                      [ 'complex value' => { 'desc' => "Add'l description",
+                                             'note' => '&nbsp;*',
+                                           }
+                      ],
+                    ],
+
+    'element_name_prefix' => "$link_table.",
+
+    #recommended
+
+    'checked_callback' => sub { my( $cgi, $name ) = @_; },
+
+  )
+
+</%doc>
+
+<TABLE CELLSPACING=0 CELLPADDING=0>
+
+<TR>
+  <TD COLSPAN=2 ALIGN="center"><FONT SIZE="-1">(
+    <A HREF="javascript:setAll<%$prefix%>(true)">select all</A> |
+    <A HREF="javascript:setAll<%$prefix%>(false)">unselect all</A> |
+    <A HREF="javascript:toggleAll<%$prefix%>()">toggle all</A>
+  )</FONT></TD>
+</TR>
+
+% my $num=0;
+% foreach my $item ( @{ $opt{'names_list'} } ) {
+%
+%     my $name = ref($item) ? $item->[0] : $item;
+%     ( my $display = $name ) =~ s/ /&nbsp;/g;
+%     $display .= $item->[1]{note} if ref($item) && $item->[1]{note};
+%     my $desc = ref($item) && $item->[1]{desc} ? $item->[1]{desc} : '';
+%
+%     my $callback =
+%       ( $cgi->param('error') ? 'error_' : '' ). 'checked_callback';
+%     my $checked = &{ $opt{$callback} }( $cgi, $name ) ? 'CHECKED' : '';
+
+  <TR>
+    <TD VALIGN="top">
+      <INPUT TYPE="checkbox" NAME="<% $opt{'element_name_prefix'}. $name %>" <% $checked %> ID="<%$prefix.$num++%>" VALUE="ON">
+    </TD>
+    <TD><% $display %>
+%     if ( $desc ) {
+        <BR><FONT SIZE="-2"><% $desc %></FONT>
+%     }
+    </TD>
+  </TR>
+
+% } 
+
+</TABLE>
+
+<SCRIPT TYPE="text/javascript">
+
+  function setAll<%$prefix%>(setTo) {
+%   for ( 0 .. ($num-1) ) {
+      document.getElementById('<%$prefix.$_%>').checked = setTo;
+%   }
+  }
+
+  function toggleAll<%$prefix%>(setTo) {
+%   for ( 0 .. ($num-1) ) {
+      var element = document.getElementById('<%$prefix.$_%>');
+      if ( element.checked == true ) {
+        element.checked = false;
+      } else {
+        element.checked = true;
+      }
+%   }
+  }
+
+</SCRIPT>
+
+<%init>
+
+my( %opt ) = @_;
+
+my @pset = ( 'a'..'z', 'A'..'Z', '0'..'9' );
+
+my $prefix = $opt{prefix}
+             || join('', map $pset[ int(rand $#pset) ], (0..20) );
+
+$opt{checked_callback} ||= sub {};
+
+$opt{'error_checked_callback'} ||= sub {
+  my( $cgi, $name ) = @_;
+  $cgi->param($opt{'element_name_prefix'}. $name );
+};
+
+</%init>
diff --git a/httemplate/elements/select-rate.html b/httemplate/elements/select-rate.html
new file mode 100644 (file)
index 0000000..83a7add
--- /dev/null
@@ -0,0 +1,9 @@
+<% include( '/elements/select-table.html',
+                 'table'       => 'rate',
+                 'name_col'    => 'ratename',
+                 'empty_label' => 'Select rate plan',
+                 #'hashref'     => { 'disabled' => '' },
+                 'order_by'    => ' ORDER BY ratenum', #ratename ?
+                 @_,
+             )
+%>
diff --git a/httemplate/elements/tr-select-rate.html b/httemplate/elements/tr-select-rate.html
new file mode 100644 (file)
index 0000000..27f2645
--- /dev/null
@@ -0,0 +1,21 @@
+% unless ( $opt{'js_only'} ) {
+
+    <% include('tr-td-label.html', @_ ) %>
+
+      <TD <% $style %>>
+% }
+
+        <% include( '/elements/select-rate.html', %opt ) %>
+
+% unless ( $opt{'js_only'} ) {
+      </TD>
+    </TR>
+% }
+<%init>
+
+my( %opt ) = @_;
+
+my $style = $opt{'cell_style'} ? 'STYLE="'. $opt{'cell_style'}. '"' : '';
+
+</%init>
+
diff --git a/httemplate/misc/copy-rate_detail.html b/httemplate/misc/copy-rate_detail.html
new file mode 100644 (file)
index 0000000..3d328ce
--- /dev/null
@@ -0,0 +1,61 @@
+<% include( '/elements/header.html', 'Copy rates between plans', menubar(
+       'View all rate plans' => "${p}browse/rate.cgi",
+   ))
+%>
+
+<% include('/elements/error.html') %>
+
+<FORM ACTION="process/copy-rate_detail.html">
+
+<% ntable('#cccccc') %>
+
+  <% include( '/elements/tr-justtitle.html', 'value' => 'Copy rates' ) %>
+
+  <% include( '/elements/tr-select-rate.html',
+                'label'        => 'From rate plan',
+                'element_name' => 'src_ratenum',
+            )
+  %>
+
+  <% include( '/elements/tr-select-rate.html',
+                'label'        => 'To rate plan',
+                'element_name' => 'dst_ratenum',
+            )
+  %>
+
+  <TR>
+    <TD COLSPAN=2>Copy country codes</TD>
+  </TR>
+
+  <TR>
+    <TD COLSPAN=2>
+
+      <% include( '/elements/checkboxes.html',
+                    'names_list' => [ FS::rate_prefix->all_countrycodes ],
+                    'element_name_prefix' => 'countrycode',
+                )
+      %>
+    </TD>
+  </TR>
+
+  <TR>
+    <TD COLSPAN=2 ALIGN="center">
+      <INPUT TYPE="submit" VALUE="Copy rates">
+    </TD>
+  </TR>
+
+</TABLE>
+
+</FORM>
+
+<% include('/elements/footer.html') %>
+
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+#should have some javascript that enables submit button only when both src & dst
+#rates are chosen
+
+</%init>
diff --git a/httemplate/misc/process/copy-rate_detail.html b/httemplate/misc/process/copy-rate_detail.html
new file mode 100644 (file)
index 0000000..87a6745
--- /dev/null
@@ -0,0 +1,61 @@
+%# if ( $error ) {
+%# <% $cgi->redirect(popurl(2).'copy-rate_detail.html?'. $cgi->query_string ) %>
+%# } else {
+<% include('/elements/header.html', 'Rates copied',
+              menubar( 'View all rate plans' => popurl(3).'browse/rate.cgi' ),
+ ) %>
+%# }
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Configuration');
+
+$cgi->param('src_ratenum') =~ /^(\d+)$/ or die 'Illegal src_ratenum';
+my $src_ratenum = $1;
+
+$cgi->param('dst_ratenum') =~ /^(\d+)$/ or die 'Illegal src_ratenum';
+my $dst_ratenum = $1;
+
+my @countrycodes = map  { /^countrycode(\d+)$/ or die; $1 }
+                   grep { /^countrycode(\d+)$/ && $cgi->param($_) }
+                        $cgi->param;
+
+foreach my $countrycode ( @countrycodes ) {
+
+  my @src_rate_detail = qsearch({
+    'table'     => 'rate_detail',
+    'addl_from' => 'JOIN rate_region'.
+                   ' ON ( rate_detail.dest_regionnum = rate_region.regionnum )',
+    'hashref' => { 'ratenum' => $src_ratenum },
+    'extra_sql' =>
+      "AND 0 < ( SELECT COUNT(*) FROM rate_prefix
+                   WHERE rate_prefix.regionnum = rate_region.regionnum
+                     AND countrycode = '$countrycode'
+               )
+      ",
+  });
+
+  foreach my $src_rate_detail ( @src_rate_detail ) {
+
+    my %hash = (
+        'ratenum' => $dst_ratenum,
+        map { $_ => $src_rate_detail->get($_) }
+            qw( orig_regionnum dest_regionnum )
+      );
+
+    my $dst_rate_detail = qsearchs( 'rate_detail', \%hash)
+                          || new FS::rate_detail   \%hash;
+
+    $dst_rate_detail->$_( $src_rate_detail->get($_) )
+      foreach qw( min_included min_charge sec_granularity classnum );
+
+    my $method = $dst_rate_detail->ratedetailnum ? 'replace' : 'insert';
+
+    my $error = $dst_rate_detail->$method();
+
+    die $error if $error; # "shouldn't" happen
+
+  }
+}
+
+</%init>