REST API, RT#28181
authorIvan Kohler <ivan@freeside.biz>
Thu, 17 Jul 2014 13:45:02 +0000 (06:45 -0700)
committerIvan Kohler <ivan@freeside.biz>
Thu, 17 Jul 2014 13:45:02 +0000 (06:45 -0700)
FS/FS/API.pm
FS/FS/Record.pm
FS/FS/cust_main/API.pm
httemplate/REST/1.0/cust_main

index a0f1dba..45f8f5e 100644 (file)
@@ -1,5 +1,6 @@
 package FS::API;
 
+use strict;
 use FS::Conf;
 use FS::Record qw( qsearch qsearchs );
 use FS::cust_main;
@@ -406,66 +407,18 @@ Referring customer number
 
 sub new_customer {
   my( $class, %opt ) = @_;
+
   my $conf = new FS::Conf;
   return { 'error' => 'Incorrect shared secret' }
     unless $opt{secret} eq $conf->config('api_shared_secret');
 
   #default agentnum like signup_server-default_agentnum?
+  #$opt{agentnum} ||= $conf->config('signup_server-default_agentnum');
  
   #same for refnum like signup_server-default_refnum
+  $opt{refnum} ||= $conf->config('signup_server-default_refnum');
 
-  my $cust_main = new FS::cust_main ( {
-      'agentnum'      => $agentnum,
-      'refnum'        => $opt{refnum}
-                         || $conf->config('signup_server-default_refnum'),
-      'payby'         => 'BILL',
-
-      map { $_ => $opt{$_} } qw(
-        agentnum refnum agent_custid referral_custnum
-        last first company 
-        daytime night fax mobile
-        payby payinfo paydate paycvv payname
-      ),
-
-  } );
-
-  my @invoicing_list = $opt{'invoicing_list'}
-                         ? split( /\s*\,\s*/, $opt{'invoicing_list'} )
-                         : ();
-  push @invoicing_list, 'POST' if $opt{'postal_invoicing'};
-
-  my ($bill_hash, $ship_hash);
-  foreach my $f (FS::cust_main->location_fields) {
-    # avoid having to change this in front-end code
-    $bill_hash->{$f} = $opt{"bill_$f"} || $opt{$f};
-    $ship_hash->{$f} = $opt{"ship_$f"};
-  }
-
-  my $bill_location = FS::cust_location->new($bill_hash);
-  my $ship_location;
-  # we don't have an equivalent of the "same" checkbox in selfservice^Wthis API
-  # so is there a ship address, and if so, is it different from the billing 
-  # address?
-  if ( length($ship_hash->{address1}) > 0 and
-          grep { $bill_hash->{$_} ne $ship_hash->{$_} } keys(%$ship_hash)
-         ) {
-
-    $ship_location = FS::cust_location->new( $ship_hash );
-  
-  } else {
-    $ship_location = $bill_location;
-  }
-
-  $cust_main->set('bill_location' => $bill_location);
-  $cust_main->set('ship_location' => $ship_location);
-
-  $error = $cust_main->insert( {}, \@invoicing_list );
-  return { 'error'   => $error } if $error;
-  
-  return { 'error'   => '',
-           'custnum' => $cust_main->custnum,
-         };
-
+  $class->API_insert( %opt );
 }
 
 =back 
@@ -486,8 +439,7 @@ sub customer_info {
     or return { 'error' => 'Unknown custnum' };
 
   $cust_main->API_getinfo;
-
-}
+:
 
 =item location_info
 
index b226e17..24f2a25 100644 (file)
@@ -1127,13 +1127,27 @@ sub hashref {
   $self->{'Hash'};
 }
 
-#fallback
+#fallbacks/generics
+
 sub API_getinfo {
   my $self = shift;
   +{ ( map { $_=>$self->$_ } $self->fields ),
    };
 }
 
+sub API_insert {
+  my( $class, %opt ) = @_;
+  my $table = $class->table;
+  my $self = $class->new( { map { $_ => $opt{$_} } fields($table) } );
+  my $error = $self->insert;
+  return +{ 'error' => $error } if $error;
+  my $pkey = $self->pkey;
+  return +{ 'error'       => '',
+            'primary_key' => $pkey,
+            $pkey         => $self->$pkey,
+          };
+}
+
 =item modified
 
 Returns true if any of this object's values have been modified with set (or via
index 2637c7e..1e17234 100644 (file)
@@ -1,6 +1,11 @@
 package FS::cust_main::API;
 
 use strict;
+use FS::Conf;
+
+=item API_getinfo FIELD => VALUE, ...
+
+=cut
 
 #some false laziness w/ClientAPI::Myaccount customer_info/customer_info_short
 
@@ -60,4 +65,93 @@ sub API_getinfo {
 
 }
 
+
+#or maybe all docs go in FS::API ?  argh
+
+=item API_insert
+
+Class method (constructor).
+
+Example:
+
+  use FS::cust_main;
+  FS::cust_main->API_insert(
+    'agentnum' => 1,
+    'refnum'   => 1,
+    'first'    => 'Harvey',
+    'last'     => 'Black',
+    'address1' => '5354 Pink Rabbit Lane',
+    'city'     => 'Farscape',
+    'state'    => 'CA',
+    'zip'      => '54144',
+
+    'invoicing_list' => 'harvey2@example.com',
+  );
+
+=cut
+
+#certainly false laziness w/ClientAPI::Signup new_customer/new_customer_minimal
+# but approaching this from a clean start / back-office perspective
+#  i.e. no package/service, no immediate credit card run, etc.
+
+sub API_insert {
+  my( $class, %opt ) = @_;
+
+  my $conf = new FS::Conf;
+
+  #default agentnum like signup_server-default_agentnum?
+  #same for refnum like signup_server-default_refnum?
+
+  my $cust_main = new FS::cust_main ( { # $class->new( {
+      'payby'         => 'BILL',
+
+      map { $_ => $opt{$_} } qw(
+        agentnum refnum agent_custid referral_custnum
+        last first company 
+        daytime night fax mobile
+        payby payinfo paydate paycvv payname
+      ),
+
+  } );
+
+  my @invoicing_list = $opt{'invoicing_list'}
+                         ? split( /\s*\,\s*/, $opt{'invoicing_list'} )
+                         : ();
+  push @invoicing_list, 'POST' if $opt{'postal_invoicing'};
+
+  my ($bill_hash, $ship_hash);
+  foreach my $f (FS::cust_main->location_fields) {
+    # avoid having to change this in front-end code
+    $bill_hash->{$f} = $opt{"bill_$f"} || $opt{$f};
+    $ship_hash->{$f} = $opt{"ship_$f"};
+  }
+
+  my $bill_location = FS::cust_location->new($bill_hash);
+  my $ship_location;
+  # we don't have an equivalent of the "same" checkbox in selfservice^Wthis API
+  # so is there a ship address, and if so, is it different from the billing 
+  # address?
+  if ( length($ship_hash->{address1}) > 0 and
+          grep { $bill_hash->{$_} ne $ship_hash->{$_} } keys(%$ship_hash)
+         ) {
+
+    $ship_location = FS::cust_location->new( $ship_hash );
+  
+  } else {
+    $ship_location = $bill_location;
+  }
+
+  $cust_main->set('bill_location' => $bill_location);
+  $cust_main->set('ship_location' => $ship_location);
+
+  my $error = $cust_main->insert( {}, \@invoicing_list );
+  return { 'error'   => $error } if $error;
+  
+  return { 'error'   => '',
+           'custnum' => $cust_main->custnum,
+         };
+
+}
+
 1;
index 89c558c..4656bcb 100644 (file)
@@ -74,6 +74,75 @@ if ( $r->method eq 'GET' ) {
 
 } elsif ( $r->method eq 'POST' ) { #create new
 
+  if ( !$custnum && $command eq '' ) {
+
+    my @param = grep { $_ ne 'secret' } $cgi->param;
+
+    $return = FS::cust_main->API_insert(
+      map { $_ => scalar($cgi->param($_)) } @param
+        #qw(
+        #  agentnum refnum agent_custid referral_custnum
+        #  last first company daytime night fax mobile
+        #  invoicing_list postal_invoicing
+        #  payby payinfo paydate paycvv payname
+
+        #  address1 address2 city county state zip country
+        #  ship_company ship_address1 ship_address2 ship_city ship_county
+        #    ship_state ship_zip ship_country
+        #)
+    );
+
+    if ( $return->{error} ) {
+      #XXX RESTful error handline
+      die $return->{error};
+    } elsif ( $return->{custnum} ) {
+      # Return a 201 Status code and the newly created id
+      my $custnum = $return->{custnum};
+      #$r->headers_out('Location' => );
+      #$m->abort(201);
+      $m->redirect( $r->uri."/$custnum", 201);
+    } else {
+      #XXX RESTful exception handling (cust_main->API_insert didn't even behave like we expect!?)
+      die 'guru meditation #159';
+    }
+
+  } elsif ( $custnum && $command eq 'cust_pkg' ) {
+
+    #XXX this needs to order a package, not just insert a record :/
+
+  # #XXX does this need to do anything special?  what's a "wallet payment"?
+  # } elsif ( $custnum && $command eq 'cust_pay' ) {
+
+  } elsif ( $custnum && $command =~ /^(cust_(attachment|pay))$/ ) {
+
+    my $table = $1;
+    my $class = 'FS::'.$table;
+
+    my @param = grep { $_ ne 'secret' } $cgi->param;
+
+    my $return =
+      $class->API_insert( 'custnum' => $custnum, 
+                          map { $_ => scalar($cgi->param($_)) } @param
+                        );
+
+    my $pkey = FS::Record->dbdef_table->$table->primary_key;
+
+    if ( $return->{error} ) {
+      #XXX RESTful error handline
+      die $return->{error};
+    } elsif ( $return->{$pkey} ) {
+      # Return a 201 Status code and the newly created id
+      my $pkey_value = $return->{$pkey};
+      #$r->headers_out('Location' => );
+      #$m->abort(201);
+      $m->redirect( $r->uri."/$pkey_value", 201);
+    } else {
+      #XXX RESTful exception handling (cust_main->API_insert didn't even behave like we expect!?)
+      die 'guru meditation #160';
+    }
+
+  }
+
 } elsif ( $r->method eq 'PUT' ) { #modify
 
 }