fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2010-07-02 06:37 am

[dw-free] massclose support requests that are awaiting close

[commit: http://hg.dwscoalition.org/dw-free/rev/a5d459a0e358]

http://bugs.dwscoalition.org/show_bug.cgi?id=2113

Allow for mass-processing of requests -- close and assign points to the last
answer on the request.

Patch by LiveJournal; packaged for Dreamwidth by kareila.

Files modified:
  • cgi-bin/LJ/Support.pm
  • htdocs/support/actmulti.bml
  • htdocs/support/help.bml
--------------------------------------------------------------------------------
diff -r 77110236993c -r a5d459a0e358 cgi-bin/LJ/Support.pm
--- a/cgi-bin/LJ/Support.pm	Fri Jul 02 14:21:44 2010 +0800
+++ b/cgi-bin/LJ/Support.pm	Fri Jul 02 14:43:08 2010 +0800
@@ -143,13 +143,13 @@ sub load_email_to_cat_map
     return $map;
 }
 
-sub calc_points
-{
-    my ($sp, $secs) = @_;
-    my $base = $sp->{_cat}->{'basepoints'} || 1;
+sub calc_points {
+    my ( $sp, $secs, $spcat ) = @_;
+    $spcat ||= $sp->{_cat};
+    my $base = $spcat->{basepoints} || 1;
     $secs = int($secs / (3600*6));
     my $total = ($base + $secs);
-    if ($total > 10) { $total = 10; }
+    $total = 10 if $total > 10;
     return $total;
 }
 
@@ -467,6 +467,27 @@ sub load_request
     }
 
     return $sp;
+}
+
+# load_requests:
+# Given an arrayref, fetches information about the requests
+# with these spid's; unlike load_request(), it doesn't fetch information
+# about supportcats.
+
+sub load_requests {
+    my ( $spids ) = @_;
+    my $dbr = LJ::get_db_reader() or return;
+
+    my $list = join( ',', map { '?' } @$spids );
+    my $requests = $dbr->selectall_arrayref(
+        "SELECT spid, reqtype, requserid, reqname, reqemail, state," .
+        " authcode, spcatid, subject, timecreate, timetouched, timeclosed," .
+        " timelasthelp FROM support WHERE spid IN ($list)",
+        { Slice => {} }, map { $_ + 0 } @$spids
+    );
+    die $dbr->errstr if $dbr->err;
+
+    return $requests;
 }
 
 sub load_response
@@ -797,6 +818,59 @@ sub set_points
     }
 }
 
+# closes request, assigning points for the last response left to the request
+
+sub close_request_with_points {
+    my ( $sp, $spcat, $remote ) = @_;
+
+    my $spid = $sp->{spid} + 0;
+    my $dbh = LJ::get_db_writer() or return;
+
+    # close the request
+    $dbh->do( 'UPDATE support SET state="closed", '.
+              'timeclosed=UNIX_TIMESTAMP() WHERE spid=?', undef, $spid );
+    die $dbh->errstr if $dbh->err;
+
+    # check to see who should get the points
+    my $response = $dbh->selectrow_hashref(
+        'SELECT splid, timelogged, userid FROM supportlog '.
+        'WHERE spid=? AND type="answer" '.
+        'ORDER BY timelogged DESC LIMIT 1', undef, $spid );
+    die $dbh->errstr if $dbh->err;
+
+    # deliberately not using LJ::Support::append_request
+    # to avoid sysban checks etc.; this sub is supposed to be fast.
+
+    my $sth = $dbh->prepare(
+            'INSERT INTO supportlog '.
+            '(spid, timelogged, type, userid, message) VALUES '.
+            '(?, UNIX_TIMESTAMP(), "internal", ?, ?)' );
+
+    unless ( defined $response ) {
+        # no points awarded
+        $sth->execute( $spid, LJ::want_userid( $remote ),
+            "(Request has been closed as part of mass closure)" );
+        die $sth->errstr if $sth->err;
+        return 1;
+    }
+
+    # award the points
+    my $userid = $response->{userid};
+    my $points = LJ::Support::calc_points(
+        $sp, $response->{timelogged} - $sp->{timecreate}, $spcat );
+
+    LJ::Support::set_points( $spid, $userid, $points );
+
+    my $username = LJ::want_user( $userid )->display_name;
+
+    $sth->execute( $spid, LJ::want_userid( $remote ),
+        "(Request has been closed as part of mass closure, " .
+        "granting $points points to $username for response #" .
+        $response->{splid} . ")" );
+    die $sth->errstr if $sth->err;
+    return 1;
+}
+
 sub touch_request
 {
     my ($spid) = @_;
diff -r 77110236993c -r a5d459a0e358 htdocs/support/actmulti.bml
--- a/htdocs/support/actmulti.bml	Fri Jul 02 14:21:44 2010 +0800
+++ b/htdocs/support/actmulti.bml	Fri Jul 02 14:43:08 2010 +0800
@@ -19,7 +19,7 @@ body<=
 {
     use strict;
     use vars qw(%POST);
-    
+
     my $remote = LJ::get_remote();
     return "<?needlogin?>" unless $remote;
 
@@ -49,7 +49,7 @@ body<=
         my $in = join ',', @ids;
         $dbh->do("UPDATE support SET state='closed', timeclosed=UNIX_TIMESTAMP() " .
                  "WHERE spid IN ($in) AND spcatid = ?", undef, $spcatid);
-        
+
         # and now insert a log comment for all of these... note that we're not using
         # LJ::Support::append_request because that'd require us to load a bunch of requests
         # and then do a bunch of individual queries, and that sucks.
@@ -61,9 +61,28 @@ body<=
         my $sql = "INSERT INTO supportlog (spid, timelogged, type, userid, message) VALUES ";
         $sql .= join ',', @stmts;
         $dbh->do($sql);
-        
+
         # return redirection back? or success message otherwise
-        return BML::redirect($POST{ret}) if $POST{ret};
+        return BML::redirect( sprintf( $POST{ret}, '' ) ) if $POST{ret};
+        return "<?h1 $ML{'.success'} h1?><?p $ML{'.request.specified'} p?>";
+    } elsif ( $POST{'action:closewithpoints'} ) {
+        my $can_close = 0;
+        $can_close = 1 if LJ::Support::can_close_cat( { _cat => $cat }, $remote );
+        return "<?h1 $ML{'.error'} h1?><?p $ML{'.not.have.access'} p?>" unless $can_close;
+
+        # let's implement a limit so that we don't overload
+        # the DB and/or timeout
+        my @filtered_ids = splice( @ids, 0, 50 );
+
+        my $requests = LJ::Support::load_requests( \@filtered_ids );
+
+        foreach my $sp ( @$requests ) {
+            LJ::Support::close_request_with_points( $sp, $cat, $remote );
+        }
+
+        return BML::redirect( sprintf( $POST{ret},
+                                       '&mark=' . join( ',', @ids ) ) )
+            if $POST{ret};
         return "<?h1 $ML{'.success'} h1?><?p $ML{'.request.specified'} p?>";
     } elsif ($POST{'action:move'}) {
         return "<?h1 $ML{'.error'} h1?><?p $ML{'.not.have.access.move.request'} p?>"
@@ -90,7 +109,7 @@ body<=
         $dbh->do($sql);
 
         # done now
-        return BML::redirect($POST{ret}) if $POST{ret};
+        return BML::redirect( sprintf( $POST{ret}, '' ) ) if $POST{ret};
         return "<?h1 $ML{'.success'} h1?><?p $ML{'.request.moved'} p?>";
     }
 }
diff -r 77110236993c -r a5d459a0e358 htdocs/support/help.bml
--- a/htdocs/support/help.bml	Fri Jul 02 14:21:44 2010 +0800
+++ b/htdocs/support/help.bml	Fri Jul 02 14:43:08 2010 +0800
@@ -255,9 +255,14 @@ body<=
  $ret .= "<form method='post' action='/support/actmulti'>" . LJ::form_auth() if $can_close && $rct;
 
  # start the rest of the table
+
+ my %marked = map { $_ => 1 } split( ',', $GET{mark} );
  my $uri = "$LJ::SITEROOT/support/help?cat=$filtercat&state=$state";
  $ret .= "<p><table class='supporttable'><tr bgcolor='#d0d0d0'>\n";
- $ret .= "<td>&nbsp;<b>X</b></td>\n" if $can_close;
+ if ( $can_close ) {
+    my $link = "$uri&sort=$sort&closeall=" . ( $GET{closeall} ? 0 : 1 );
+    $ret .= "<td>&nbsp;<b><a href='$link'>X</a></b></td>\n";
+ }
  my @headers = ( id => "ID#", summary => $ML{'.th.summary'}, area => $ML{'.th.problemarea'}, date => $ML{'.th.posted'} );
  while (my ($sorttype, $desc) = splice(@headers, 0, 2)) {
      if ($sort eq $sorttype) {
@@ -288,6 +293,9 @@ body<=
          $status = "answered<br /><b>still needs help</b>";
          $barbg = "green";
      }
+     my $original_barbg = $barbg;
+     $barbg = 'clicked' if ( $GET{closeall} && $original_barbg eq 'yellow' )
+                        || $marked{$sp->{spid}};
 
      next if $state eq "green" && $barbg ne "green";
 
@@ -337,9 +345,13 @@ body<=
      # generate the HTML for this row
      $ret .= "<tr valign='top' $style $js>\n";
      if ($can_close) {
-         $ret .= "<td>" . LJ::html_check({ name => "check_$sp->{spid}", id => "check_$sp->{spid}",
-                                           onclick => "doClick($sp->{spid});", selected => $GET{closeall}, }) .
-                 "<input type='hidden' name='c$sp->{spid}' id='c$sp->{spid}' value='$barbg' /></td>\n";
+         $ret .= "<td>";
+         $ret .= LJ::html_check( { name => "check_$sp->{spid}",
+                                   id   => "check_$sp->{spid}",
+                                   onclick => "doClick($sp->{spid});",
+                                   selected => $barbg eq 'clicked' } );
+         $ret .= "<input type='hidden' name='c$sp->{spid}' id='c$sp->{spid}' value='$original_barbg' />";
+         $ret .= "</td>\n";
          $js = "onclick='return doClick($sp->{spid});'";
      }
      $ret .= "<td><b><a href=\"$LJ::SITEROOT/support/see_request?id=$sp->{'spid'}\" $js>$sp->{'spid'}</a></b></td>";
@@ -357,7 +369,7 @@ body<=
      my $time = time();
      $ret .= LJ::html_hidden('ids', join(':', map { $_->{spid} } @support_log),
                              'spcatid', $fcat->{spcatid},
-                             'ret', "/support/help?state=$state&cat=$filtercat&time=$time");
+                             'ret', "/support/help?state=$state&cat=$filtercat&time=$time%s");
      $ret .= "<br />";
      $ret .= LJ::html_submit('action:move', 'Move Marked Requests');
      $ret .= " to ";
@@ -371,6 +383,9 @@ body<=
      $ret .= LJ::html_submit('action:close', 'Close Marked Requests',
                              { onclick => 'return confirm("Are you sure you want to close the marked requests?");' });
      $ret .= " (this is permanent)";
+     $ret .= "<br /><br />";
+     $ret .= LJ::html_submit('action:closewithpoints', 'Close Marked Requests, granting points to last responses',
+                             { onclick => 'return confirm("Are you sure you want to close the marked requests?");' });
      $ret .= "</form>";
  }
  $ret .= "<?hr?>";
--------------------------------------------------------------------------------