import package definitions, RT#32639
authorIvan Kohler <ivan@freeside.biz>
Mon, 19 Jan 2015 10:29:23 +0000 (02:29 -0800)
committerIvan Kohler <ivan@freeside.biz>
Mon, 19 Jan 2015 10:29:23 +0000 (02:29 -0800)
FS/FS/Record.pm
FS/FS/Schema.pm
FS/FS/part_pkg/Import.pm [new file with mode: 0644]
FS/bin/freeside-queued
httemplate/browse/part_pkg.cgi
httemplate/elements/menu.html
httemplate/misc/cust_pkg-import.html
httemplate/misc/part_pkg-import.html [new file with mode: 0644]
httemplate/misc/process/part_pkg-import.html [new file with mode: 0644]

index 991c56e..f8282c0 100644 (file)
@@ -1809,6 +1809,7 @@ sub process_batch_import {
     #?
     default_csv                => $opt->{default_csv},
     postinsert_callback        => $opt->{postinsert_callback},
+    insert_args_callback       => $opt->{insert_args_callback},
   );
 
   if ( $opt->{'batch_namecol'} ) {
@@ -1895,6 +1896,9 @@ sub batch_import {
   my $preinsert_callback = '';
   $preinsert_callback = $param->{'preinsert_callback'}
          if $param->{'preinsert_callback'};
+  my $insert_args_callback = '';
+  $insert_args_callback = $param->{'insert_args_callback'}
+         if $param->{'insert_args_callback'};
 
   if ( $param->{'format'} ) {
 
@@ -2204,7 +2208,12 @@ sub batch_import {
       next if exists $param->{skiprow} && $param->{skiprow};
     }
 
-    my $error = $record->insert;
+    my @insert_args = ();
+    if ( $insert_args_callback ) {
+      @insert_args = &{$insert_args_callback}($record, $param);
+    }
+
+    my $error = $record->insert(@insert_args);
 
     if ( $error ) {
       $dbh->rollback if $oldAutoCommit;
index 8d33f92..f51b576 100644 (file)
@@ -3052,6 +3052,7 @@ sub tables_hashref {
     'part_pkg' => {
       'columns' => [
         'pkgpart',       'serial',    '',   '', '', '', 
+        'pkgpartbatch',  'varchar', 'NULL', $char_d, '', '',
         'pkg',           'varchar',   '',   $char_d, '', '', 
         'comment',       'varchar', 'NULL', 2*$char_d, '', '', 
         'promo_code',    'varchar', 'NULL', $char_d, '', '', 
diff --git a/FS/FS/part_pkg/Import.pm b/FS/FS/part_pkg/Import.pm
new file mode 100644 (file)
index 0000000..9e9044e
--- /dev/null
@@ -0,0 +1,76 @@
+package FS::part_pkg::Import;
+
+use strict;
+use FS::Record;
+use FS::part_pkg;
+
+=head1 NAME
+
+FS::part_pkg::Import - Batch customer importing
+
+=head1 SYNOPSIS
+
+  use FS::part_pkg::Import;
+
+  #ajax helper
+  use FS::UI::Web::JSRPC;
+  my $server =
+    new FS::UI::Web::JSRPC 'FS::part_pkg::Import::process_batch_import', $cgi;
+  print $server->process;
+
+=head1 DESCRIPTION
+
+Batch package definition importing.
+
+=head1 SUBROUTINES
+
+=item process_batch_import
+
+Load a batch import as a queued JSRPC job
+
+=cut
+
+sub process_batch_import {
+  my $job = shift;
+
+  my $opt = { 'table'       => 'part_pkg',
+              'params'      => [qw( agentnum pkgpartbatch )],
+              'formats'     => { 'default' => [
+                                   'agent_pkgpartid',
+                                   'pkg',
+                                   'comment',
+                                   'freq',
+                                   'plan',
+                                   'setup_fee',
+                                   'recur_fee',
+                                   'setup_cost',
+                                   'recur_cost',
+                                   'classnum',
+                                   'taxclass',
+                                 ],
+                               },
+              'insert_args_callback' => sub {
+                my $part_pkg = shift;
+                ( 'options' => { 'setup_fee' => $part_pkg->get('setup_fee'),
+                                 'recur_fee' => $part_pkg->get('recur_fee'),
+                               },
+                );
+              },
+              #'default_csv' => 1,
+            };
+
+  FS::Record::process_batch_import( $job, $opt, @_ );
+
+}
+
+=head1 BUGS
+
+Not enough documentation.
+
+=head1 SEE ALSO
+
+L<FS::cust_main>, L<FS::part_pkg>
+
+=cut
+
+1;
index 70d8534..7c4cf1b 100644 (file)
@@ -196,7 +196,7 @@ while (1) {
       dbh->{'private_profile'} = {} if UNIVERSAL::can(dbh, 'sprintProfile');
 
       #auto-use classes...
-      if (    $ljob->job =~ /(FS::(part_export|cust_main|cust_pkg|Cron)::\w+)::/
+      if (    $ljob->job =~ /(FS::(part_export|cust_main|cust_pkg|part_pkg|Cron)::\w+)::/
            || $ljob->job =~ /(FS::\w+)::/
          )
       {
index 87aa792..87e7aad 100755 (executable)
@@ -76,6 +76,10 @@ if ( $cgi->param('classnum') =~ /^(\d+)$/ ) {
 }
 $cgi->delete('classnum');
 
+if ( $cgi->param('pkgpartbatch') =~ /^([\w\/\-\:\. ]+)$/ ) {
+  push @where, "pkgpartbatch = '$1' ";
+}
+
 if ( $cgi->param('missing_recur_fee') ) {
   push @where, "NOT EXISTS ( SELECT 1 FROM part_pkg_option
                                WHERE optionname = 'recur_fee'
index 03ce201..816f74a 100644 (file)
@@ -445,12 +445,13 @@ $report_menu{'SQL Query'}      = [ $fsurl.'search/report_sql.html', 'SQL Query']
   if $curuser->access_right('Raw SQL');
 
 tie my %tools_importing, 'Tie::IxHash',
-  'Customers' => [ $fsurl.'misc/cust_main-import.cgi', '' ],
-  'Customer packages' => [ $fsurl.'misc/cust_pkg-import.html', '' ],
-  'Customer comments' => [ $fsurl.'misc/cust_main_note-import.html', '' ],
-  'One-time charges' => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ],
-  'Payments' => [ $fsurl.'misc/cust_pay-import.cgi', '' ],
-  'Credits' => [ $fsurl.'misc/cust_credit-import.html', '' ],
+  'Customers'            => [ $fsurl.'misc/cust_main-import.cgi', '' ],
+  'Package definitions'  => [ $fsurl.'misc/part_pkg-import.html', '' ],
+  'Customer packages'    => [ $fsurl.'misc/cust_pkg-import.html', '' ],
+  'Customer comments'    => [ $fsurl.'misc/cust_main_note-import.html', '' ],
+  'One-time charges'     => [ $fsurl.'misc/cust_main-import_charges.cgi', '' ],
+  'Payments'             => [ $fsurl.'misc/cust_pay-import.cgi', '' ],
+  'Credits'              => [ $fsurl.'misc/cust_credit-import.html', '' ],
   'Phone numbers (DIDs)' => [ $fsurl.'misc/phone_avail-import.html', '' ],
   'Call Detail Records (CDRs)' => [ $fsurl.'misc/cdr-import.html', '' ],
 ;
index 94e7dd9..e0c0c7f 100644 (file)
@@ -1,6 +1,6 @@
-<% include("/elements/header.html",'Batch Package Import') %>
+<& /elements/header.html, 'Customer package import' &>
 
-Import a file containing package records.
+Import a file containing customer packages.
 <BR><BR>
 
 <& /elements/form-file_upload.html,
@@ -8,19 +8,18 @@ Import a file containing package records.
      'action'    => 'process/cust_pkg-import.html',
      'num_files' => 1,
      'fields'    => [ 'agentnum', 'pkgbatch', 'format' ],
-     'message'   => 'Package import successful',
+     'message'   => 'Customer package import successful',
      'url'       => $p."search/cust_pkg.cgi?pkgbatch=$pkgbatch",
      'onsubmit'  => "document.PackageImportForm.submitButton.disabled=true;"
 &>
 
 <% &ntable("#cccccc", 2) %>
 
-  <% include( '/elements/tr-select-agent.html',
-                 #'curr_value' => '', #$agentnum,
-                 'label'       => "<B>Agent</B>",
-                 'empty_label' => 'Select agent',
-             )
-  %>
+  <& /elements/tr-select-agent.html,
+       #'curr_value' => '', #$agentnum,
+       'label'       => "<B>Agent</B>",
+       'empty_label' => 'Select agent',
+  &>
 
   <INPUT TYPE="hidden" NAME="pkgbatch" VALUE="<% $pkgbatch %>"%>
 
@@ -43,11 +42,10 @@ Import a file containing package records.
     </TD>
   </TR>
 
-  <% include( '/elements/file-upload.html',
-                'field' => 'file',
-                'label' => 'Filename',
-            )
-  %>
+  <& /elements/file-upload.html,
+       'field' => 'file',
+       'label' => 'Filename',
+  &>
 
   <TR>
     <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
@@ -171,7 +169,7 @@ Field information:
 
 <BR>
 
-<% include('/elements/footer.html') %>
+<& /elements/footer.html &>
 
 <%once>
 
diff --git a/httemplate/misc/part_pkg-import.html b/httemplate/misc/part_pkg-import.html
new file mode 100644 (file)
index 0000000..aed734a
--- /dev/null
@@ -0,0 +1,116 @@
+<& /elements/header.html, 'Import package definitions' &>
+
+Import a file containing package definitions.
+<BR><BR>
+
+<& /elements/form-file_upload.html,
+     'name'      => 'PackageDefImportForm',
+     'action'    => 'process/part_pkg-import.html',
+     'num_files' => 1,
+     'fields'    => [ 'agentnum', 'pkgpartbatch', 'format' ],
+     'message'   => 'Package definition import successful',
+     'url'       => $p."browse/part_pkg.cgi?pkgpartbatch=$pkgpartbatch",
+     'onsubmit'  => "document.PackageDefImportForm.submitButton.disabled=true;"
+&>
+
+<% &ntable("#cccccc", 2) %>
+
+  <& /elements/tr-select-agent.html,
+       #'curr_value' => '', #$agentnum,
+       'label'       => "<B>Agent</B>",
+
+       'disable_empty' => 1,
+       #this doesn't work yet, no type_pkgs records are inserted
+       #'empty_label' => '(global)',
+
+       #disable_empty => ! $acl_edit_global,
+  &>
+
+
+  <INPUT TYPE="hidden" NAME="pkgpartbatch" VALUE="<% $pkgpartbatch %>"%>
+
+  <TR>
+    <TH ALIGN="right">Format</TH>
+    <TD>
+      <SELECT NAME="format">
+        <OPTION VALUE="default" SELECTED>Default
+      </SELECT>
+    </TD>
+  </TR>
+
+  <& /elements/file-upload.html,
+       'field' => 'file',
+       'label' => 'Filename',
+  &>
+
+  <TR>
+    <TD COLSPAN=2 ALIGN="center" STYLE="padding-top:6px">
+      <INPUT TYPE    = "submit"
+             NAME    = "submitButton"
+             ID      = "submitButton"
+             VALUE   = "Import file"
+      >
+    </TD>
+  </TR>
+
+</TABLE>
+
+</FORM>
+
+<BR>
+Uploaded files can be CSV (comma-separated value) files or Excel spreadsheets.  The file should have a .CSV or .XLS extension.
+<BR><BR>
+
+<b>Default</b> format has the following field order: <i>agent_pkgpartid, pkg<%$req%>, comment<%$req%>, freq<%$req%>, plan<%$req%>, setup_fee<%$req%>, recur_fee<%$req%>, setup_cost, recur_cost, classnum, taxclass
+</i>
+<BR><BR>
+
+<%$req%> Required fields
+<BR><BR>
+
+Field information:
+
+<ul>
+
+  <li><i>agent_pkgpartid</i>: Current product ID or code
+
+  <li><i>pkg</i>: Package name (customer-visible)
+
+  <li><i>comment</i>: Package comment (customer-hidden)
+
+  <li><i>freq</i>: Recurring fee frequency - 0 for one-time charges, a number of months (i.e. 1 for months, 12 for yearly), or a number followed by h, d or w for hours, days or weeks.
+
+  <li><i>plan</i>: Price plan, i.e. flat, prorate, voip_cdr, etc.
+
+  <li><i>setup_fee</i>: Setup price
+
+  <li><i>recur_fee</i>: Recurring price
+
+  <li><i>setup_cost</i>: Setup cost
+
+  <li><i>recur_cost</i>: Recurring cost
+
+  <li><i>classnum</i>: Package class (integer)
+
+  <li><i>taxclass</i>: Tax class (string)
+
+</ul>
+
+<BR>
+
+<& /elements/footer.html &>
+
+<%once>
+
+my $req = qq!<font color="#ff0000">*</font>!;
+
+</%once>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $pkgpartbatch =
+  time2str('webimport-%Y/%m/%d-%T'. "-$$-". rand() * 2**32, time);
+
+</%init>
diff --git a/httemplate/misc/process/part_pkg-import.html b/httemplate/misc/process/part_pkg-import.html
new file mode 100644 (file)
index 0000000..f951a21
--- /dev/null
@@ -0,0 +1,10 @@
+<% $server->process %>
+<%init>
+
+die "access denied"
+  unless $FS::CurrentUser::CurrentUser->access_right('Import');
+
+my $server =
+  new FS::UI::Web::JSRPC 'FS::part_pkg::Import::process_batch_import', $cgi;
+
+</%init>