[freeside-commits] branch master updated. 8cc48c6059d05fb54bf714aaddc168c8043e24ed

Jonathan Prykop jonathan at 420.am
Mon Jul 18 17:30:53 PDT 2016


The branch, master has been updated
       via  8cc48c6059d05fb54bf714aaddc168c8043e24ed (commit)
      from  fe25108857542f5d7c460ab831bc782f608179fa (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8cc48c6059d05fb54bf714aaddc168c8043e24ed
Author: Jonathan Prykop <jonathan at freeside.biz>
Date:   Mon Jul 18 19:29:59 2016 -0500

    RT#38973: Bill for time worked on ticket resolution [fully functional]

diff --git a/FS/FS/TicketSystem/RT_Internal.pm b/FS/FS/TicketSystem/RT_Internal.pm
index 01806c1..99e7044 100644
--- a/FS/FS/TicketSystem/RT_Internal.pm
+++ b/FS/FS/TicketSystem/RT_Internal.pm
@@ -3,6 +3,7 @@ package FS::TicketSystem::RT_Internal;
 use strict;
 use vars qw( @ISA $DEBUG $me );
 use Data::Dumper;
+use Date::Format qw( time2str );
 use MIME::Entity;
 use FS::UID qw(dbh);
 use FS::CGI qw(popurl);
@@ -101,17 +102,43 @@ sub init {
   warn "$me init: complete" if $DEBUG;
 }
 
-=item customer_tickets CUSTNUM [ LIMIT ] [ PRIORITYVALUE ]
+=item customer_tickets CUSTNUM [ PARAMS ]
 
 Replacement for the one in RT_External so that we can access custom fields 
-properly.
+properly.  Accepts a hashref with the following parameters:
+
+number - custnum/svcnum
+
+limit 
+
+priority 
+
+status
+
+queueid
+
+resolved - only return tickets resolved after this timestamp
 
 =cut
 
 # create an RT::Tickets object for a specified custnum or svcnum
 
 sub _tickets_search {
-  my( $self, $type, $number, $limit, $priority, $status, $queueid ) = @_;
+  my $self = shift;
+  my $type = shift;
+
+  my( $number, $limit, $priority, $status, $queueid, $opt );
+  if ( ref($_[0]) eq 'HASH' ) {
+    $opt = shift;
+    $number   = $$opt{'number'};
+    $limit    = $$opt{'limit'};
+    $priority = $$opt{'priority'};
+    $status   = $$opt{'status'};
+    $queueid  = $$opt{'queueid'};
+  } else {
+    ( $number, $limit, $priority, $status, $queueid ) = @_;
+    $opt = {};
+  }
 
   $type =~ /^Customer|Service$/ or die "invalid type: $type";
   $number =~ /^\d+$/ or die "invalid custnum/svcnum: $number";
@@ -161,6 +188,10 @@ sub _tickets_search {
 
   $rtql .= " AND Queue = $queueid " if $queueid;
 
+  if ($$opt{'resolved'}) {
+    $rtql .= " AND Resolved >= " . dbh->quote(time2str('%Y-%m-%d %H:%M:%S',$$opt{'resolved'}));
+  }
+
   warn "$me _customer_tickets_search:\n$rtql\n" if $DEBUG;
   $Tickets->FromSQL($rtql);
 
diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm
index 8d16fe0..bbb281a 100644
--- a/FS/FS/cust_pkg.pm
+++ b/FS/FS/cust_pkg.pm
@@ -533,6 +533,7 @@ sub delete {
   # cust_bill_pay.pkgnum (wtf, shouldn't reference pkgnum)
   # cust_pkg_usage.pkgnum
   # cust_pkg.uncancel_pkgnum, change_pkgnum, main_pkgnum, and change_to_pkgnum
+  # rt_field_charge.pkgnum
 
   # cust_svc is handled by canceling the package before deleting it
   # cust_pkg_option is handled via option_Common
@@ -2624,6 +2625,19 @@ sub change {
     return "canceling old package: $error";
   }
 
+  # transfer rt_field_charge, if we're not changing pkgpart
+  # after billing of old package, before billing of new package
+  if ( $same_pkgpart ) {
+    foreach my $rt_field_charge ($self->rt_field_charge) {
+      $rt_field_charge->set('pkgnum', $cust_pkg->pkgnum);
+      $error = $rt_field_charge->replace;
+      if ( $error ) {
+        $dbh->rollback if $oldAutoCommit;
+        return "transferring rt_field_charge: $error";
+      }
+    }
+  }
+
   if ( $conf->exists('cust_pkg-change_pkgpart-bill_now') ) {
     #$self->cust_main
     my $error = $cust_pkg->cust_main->bill( 
diff --git a/FS/FS/part_pkg/rt_field.pm b/FS/FS/part_pkg/rt_field.pm
index 1b18720..657a8d7 100644
--- a/FS/FS/part_pkg/rt_field.pm
+++ b/FS/FS/part_pkg/rt_field.pm
@@ -24,12 +24,21 @@ my %custom_field = (
   'lookuptype'  => 'RT::Queue-RT::Ticket',
 );
 
+my %multiple = (
+  'multiple' => 1,
+  'parse' => sub { @_ }, # because /edit/process/part_pkg.pm doesn't grok select multiple
+);
+
 our %info = (
   'name'      =>  'Bill from custom fields in resolved RT tickets',
   'shortname' =>  'RT custom rate',
   'weight'    => 65,
   'inherit_fields' => [ 'global_Mixin' ],
   'fields'    =>  {
+    'queueids'       => { 'name' => 'Queues',
+                          'type' => 'select-rt-queue',
+                          %multiple,
+                        },
     'unit_field'     => { 'name' => 'Units field',
                           %custom_field,
                           'validate' => sub { return ${$_[1]} ? '' : 'Units field must be specified' },
@@ -42,8 +51,7 @@ our %info = (
                           'validate' => \&FS::part_pkg::global_Mixin::validate_moneyn },
     'display_fields' => { 'name' => 'Display fields',
                           %custom_field,
-                          'multiple' => 1,
-                          'parse' => sub { @_ }, # because /edit/process/part_pkg.pm doesn't grok select multiple
+                          %multiple,
                         },
     # from global_Mixin, but don't get used by this at all
     'unused_credit_cancel'  => {'disabled' => 1},
@@ -58,22 +66,24 @@ our %info = (
       if $options->{'rate_field'} and $options->{'rate_flat'};
     return '';
   },
-  'fieldorder' => [ 'unit_field', 'rate_field', 'rate_flat', 'display_fields' ]
+  'fieldorder' => [ 'queueids', 'unit_field', 'rate_field', 'rate_flat', 'display_fields' ]
 );
 
 sub price_info {
     my $self = shift;
     my $str = $self->SUPER::price_info;
     $str .= ' plus ' if $str;
-    FS::TicketSystem->init();
-    my %custom_fields = FS::TicketSystem->custom_fields();
-    my $rate = $self->option('rate_flat',1);
-    my $rate_field = $self->option('rate_field',1);
-    my $unit_field = $self->option('unit_field');
-    $str .= $rate
-            ? $money_char . sprintf("%.2",$rate)
-            : $custom_fields{$rate_field};
-    $str .= ' x ' . $custom_fields{$unit_field};
+    $str .= 'charge from RT';
+# takes way too long just to get a package label
+#    FS::TicketSystem->init();
+#    my %custom_fields = FS::TicketSystem->custom_fields();
+#    my $rate = $self->option('rate_flat',1);
+#    my $rate_field = $self->option('rate_field',1);
+#    my $unit_field = $self->option('unit_field');
+#    $str .= $rate
+#            ? $money_char . sprintf("%.2",$rate)
+#            : $custom_fields{$rate_field};
+#    $str .= ' x ' . $custom_fields{$unit_field};
     return $str;
 }
 
@@ -103,11 +113,31 @@ sub calc_usage {
 
   FS::TicketSystem->init();
 
-  # not date delimited--load all resolved tickets
-  # will subtract previous charges below
-  # only way to be sure we've caught everything
-  # limit set to be arbitrarily large (10000)
-  my $tickets = FS::TicketSystem->customer_tickets( $cust_pkg->custnum, 10000, undef, 'resolved');
+  my %queues = FS::TicketSystem->queues(undef,'SeeCustomField');
+
+  my @tickets;
+  foreach my $queueid (
+    split(', ',$self->option('queueids',1) || '')
+  ) {
+
+    die "Insufficient permission to invoice package"
+      unless exists $queues{$queueid};
+
+    # load all resolved tickets since pkg was ordered
+    # will subtract previous charges below
+    # only way to be sure we've caught everything
+    my $tickets = FS::TicketSystem->customer_tickets({
+      number   => $cust_pkg->custnum, 
+      limit    => 10000, # arbitrarily large
+      status   => 'resolved',
+      queueid  => $queueid,
+      resolved => $cust_pkg->order_date, # or setup? but this is mainly for installations,
+                                         # and workflow might resolve tickets before first bill...
+                                         # for now, expect pkg to be ordered before tickets get resolved,
+                                         # easy enough to make a pkg option to use setup/sdate instead
+    });
+    push @tickets, @$tickets;
+  };
 
   my $rate = $self->option('rate_flat',1);
   my $rate_field = $self->option('rate_field',1);
@@ -124,7 +154,7 @@ sub calc_usage {
   $unit_field = 'CF.{' . $unit_field . '}';
 
   my $charges = 0;
-  foreach my $ticket ( @$tickets ) {
+  foreach my $ticket ( @tickets ) {
     next unless $ticket->{$unit_field};
     next unless $rate || $ticket->{$rate_field};
     my $trate = $rate || $ticket->{$rate_field};
diff --git a/httemplate/edit/part_pkg.cgi b/httemplate/edit/part_pkg.cgi
index 2c8477d..7fe659f 100755
--- a/httemplate/edit/part_pkg.cgi
+++ b/httemplate/edit/part_pkg.cgi
@@ -988,9 +988,9 @@ my $html_bottom = sub {
                    : ''
                  ). '>';
 
-      } elsif ( $href->{$field}{'type'} eq 'select-rt-customfield' ) {
+      } elsif ( $href->{$field}{'type'} =~ /^select-rt-/ ) {
 
-        $html .= include('/elements/select-rt-customfield.html',
+        $html .= include('/elements/'.$href->{$field}{'type'}.'.html',
                            'name'       => $layer.'__'.$field,
                            'curr_value' => $options{$field},
                            map { $_ => $href->{$field}{$_} }
diff --git a/httemplate/elements/select-rt-queue.html b/httemplate/elements/select-rt-queue.html
new file mode 100644
index 0000000..4ae8bc9
--- /dev/null
+++ b/httemplate/elements/select-rt-queue.html
@@ -0,0 +1,24 @@
+<SELECT NAME="<% $opt{'name'} %>"<% $opt{'multiple'} ? ' MULTIPLE' : '' %>>
+% while ( @fields ) {
+%   my $value = shift @fields;
+%   my $label = shift @fields;
+<OPTION VALUE="<% $value %>"<% $curr_value{$value} ? ' SELECTED' : '' %>><% $label %></OPTION>
+% }
+</SELECT>
+<%init>
+my %opt = @_;
+
+my %curr_value = map { $_ => 1 } split(', ',$opt{'curr_value'});
+
+my @fields;
+push @fields, '', $opt{empty_label} if exists($opt{empty_label});
+
+my $conf = new FS::Conf;
+
+if ($conf->config('ticket_system') eq 'RT_Internal') {
+
+  push @fields, FS::TicketSystem->queues();
+
+}
+
+</%init>

-----------------------------------------------------------------------

Summary of changes:
 FS/FS/TicketSystem/RT_Internal.pm                  |   37 ++++++++++-
 FS/FS/cust_pkg.pm                                  |   14 +++++
 FS/FS/part_pkg/rt_field.pm                         |   66 ++++++++++++++------
 httemplate/edit/part_pkg.cgi                       |    4 +-
 ...ct-rt-customfield.html => select-rt-queue.html} |    5 +-
 5 files changed, 99 insertions(+), 27 deletions(-)
 copy httemplate/elements/{select-rt-customfield.html => select-rt-queue.html} (80%)




More information about the freeside-commits mailing list