From 5f8111de04a4a914c72a1642722476db4728339c Mon Sep 17 00:00:00 2001 From: Ivan Kohler Date: Wed, 16 Jul 2014 06:17:05 -0700 Subject: [PATCH] REST API, RT#28181 --- FS/FS/API.pm | 44 +------------------ FS/FS/Mason.pm | 1 + FS/FS/Record.pm | 12 ++++++ FS/FS/UI/REST.pm | 38 ++++++++++++++++ FS/FS/cust_bill.pm | 8 ++++ FS/FS/cust_main.pm | 1 + FS/FS/cust_main/API.pm | 63 +++++++++++++++++++++++++++ FS/FS/cust_pay.pm | 7 +++ FS/FS/cust_pkg.pm | 2 +- FS/FS/cust_pkg/API.pm | 13 ++++++ FS/FS/cust_svc.pm | 7 +++ FS/FS/part_export/internal_diddb.pm | 12 +++++- FS/FS/part_pkg.pm | 8 ++-- FS/FS/part_pkg/API.pm | 17 ++++++++ htetc/freeside-base2.4.conf | 7 +++ htetc/freeside-base2.conf | 6 +++ httemplate/REST/1.0/.cust_bill.swp | Bin 0 -> 12288 bytes httemplate/REST/1.0/.cust_main.swp | Bin 0 -> 12288 bytes httemplate/REST/1.0/.cust_pkg.swp | Bin 0 -> 12288 bytes httemplate/REST/1.0/.part_pkg.swp | Bin 0 -> 12288 bytes httemplate/REST/1.0/.phone_avail.swp | Bin 0 -> 12288 bytes httemplate/REST/1.0/.rate_detail.swp | Bin 0 -> 12288 bytes httemplate/REST/1.0/cust_bill | 28 ++++++++++++ httemplate/REST/1.0/cust_main | 81 +++++++++++++++++++++++++++++++++++ httemplate/REST/1.0/cust_pkg | 39 +++++++++++++++++ httemplate/REST/1.0/part_pkg | 40 +++++++++++++++++ httemplate/REST/1.0/phone_avail | 25 +++++++++++ httemplate/REST/1.0/rate_detail | 35 +++++++++++++++ 28 files changed, 445 insertions(+), 49 deletions(-) create mode 100644 FS/FS/UI/REST.pm create mode 100644 FS/FS/cust_main/API.pm create mode 100644 FS/FS/cust_pkg/API.pm create mode 100644 FS/FS/part_pkg/API.pm create mode 100644 httemplate/REST/1.0/.cust_bill.swp create mode 100644 httemplate/REST/1.0/.cust_main.swp create mode 100644 httemplate/REST/1.0/.cust_pkg.swp create mode 100644 httemplate/REST/1.0/.part_pkg.swp create mode 100644 httemplate/REST/1.0/.phone_avail.swp create mode 100644 httemplate/REST/1.0/.rate_detail.swp create mode 100644 httemplate/REST/1.0/cust_bill create mode 100644 httemplate/REST/1.0/cust_main create mode 100644 httemplate/REST/1.0/cust_pkg create mode 100644 httemplate/REST/1.0/part_pkg create mode 100644 httemplate/REST/1.0/phone_avail create mode 100644 httemplate/REST/1.0/rate_detail diff --git a/FS/FS/API.pm b/FS/FS/API.pm index 2105409c5..a0f1dba2a 100644 --- a/FS/FS/API.pm +++ b/FS/FS/API.pm @@ -476,19 +476,6 @@ Returns general customer information. Takes a hash reference as parameter with t =cut -#some false laziness w/ClientAPI::Myaccount customer_info/customer_info_short - -use vars qw( @cust_main_editable_fields @location_editable_fields ); -@cust_main_editable_fields = qw( - first last company daytime night fax mobile -); -# locale -# payby payinfo payname paystart_month paystart_year payissue payip -# ss paytype paystate stateid stateid_state -@location_editable_fields = qw( - address1 address2 city county state zip country -); - sub customer_info { my( $class, %opt ) = @_; my $conf = new FS::Conf; @@ -498,39 +485,10 @@ sub customer_info { my $cust_main = qsearchs('cust_main', { 'custnum' => $opt{custnum} }) or return { 'error' => 'Unknown custnum' }; - my %return = ( - 'error' => '', - 'display_custnum' => $cust_main->display_custnum, - 'name' => $cust_main->first. ' '. $cust_main->get('last'), - 'balance' => $cust_main->balance, - 'status' => $cust_main->status, - 'statuscolor' => $cust_main->statuscolor, - ); - - $return{$_} = $cust_main->get($_) - foreach @cust_main_editable_fields; - - for (@location_editable_fields) { - $return{$_} = $cust_main->bill_location->get($_) - if $cust_main->bill_locationnum; - $return{'ship_'.$_} = $cust_main->ship_location->get($_) - if $cust_main->ship_locationnum; - } - - my @invoicing_list = $cust_main->invoicing_list; - $return{'invoicing_list'} = - join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ); - $return{'postal_invoicing'} = - 0 < ( grep { $_ eq 'POST' } @invoicing_list ); - - #generally, the more useful data from the cust_main record the better. - # well, tell me what you want - - return \%return; + $cust_main->API_getinfo; } - =item location_info Returns location specific information for the customer. Takes a hash reference as parameter with the following keys: custnum,secret diff --git a/FS/FS/Mason.pm b/FS/FS/Mason.pm index 5476fd83e..b7aa35543 100644 --- a/FS/FS/Mason.pm +++ b/FS/FS/Mason.pm @@ -138,6 +138,7 @@ if ( -e $addl_handler_use_file ) { use FS::UI::Web qw(svc_url); use FS::UI::Web::small_custview qw(small_custview); use FS::UI::bytecount; + use FS::UI::REST qw( rest_auth rest_uri_remain encode_rest ); use FS::Msgcat qw(gettext geterror); use FS::Misc qw( send_email send_fax ocr_image states_hash counties cities state_label diff --git a/FS/FS/Record.pm b/FS/FS/Record.pm index a68442582..b226e177b 100644 --- a/FS/FS/Record.pm +++ b/FS/FS/Record.pm @@ -367,6 +367,9 @@ sub qsearch { my @bind_type = (); my $dbh = dbh; foreach my $stable ( @stable ) { + + carp '->qsearch on cust_main called' if $stable eq 'cust_main' && $DEBUG; + #stop altering the caller's hashref my $record = { %{ shift(@record) || {} } };#and be liberal in receipt my $select = shift @select; @@ -994,6 +997,8 @@ sub AUTOLOAD { eval "use FS::$table"; die $@ if $@; + carp '->cust_main called' if $table eq 'cust_main' && $DEBUG; + my $pkey_value = $self->$column(); my %search = ( $foreign_column => $pkey_value ); @@ -1122,6 +1127,13 @@ sub hashref { $self->{'Hash'}; } +#fallback +sub API_getinfo { + my $self = shift; + +{ ( map { $_=>$self->$_ } $self->fields ), + }; +} + =item modified Returns true if any of this object's values have been modified with set (or via diff --git a/FS/FS/UI/REST.pm b/FS/FS/UI/REST.pm new file mode 100644 index 000000000..b6503ba51 --- /dev/null +++ b/FS/FS/UI/REST.pm @@ -0,0 +1,38 @@ +package FS::UI::REST; +use base qw( Exporter ); + +use strict; +use vars qw( @EXPORT_OK ); +use JSON::XS; +use FS::UID qw( adminsuidsetup ); +use FS::Conf; + +@EXPORT_OK = qw( rest_auth rest_uri_remain encode_rest ); + +sub rest_auth { + my $cgi = shift; + adminsuidsetup('fs_api'); + my $conf = new FS::Conf; + die 'Incorrect shared secret' + unless $cgi->param('secret') eq $conf->config('api_shared_secret'); +} + +sub rest_uri_remain { + my($r, $m) = @_; + + #wacky way to get this... surely there must be a better way + + my $path = $m->request_comp->path; + + $r->uri =~ /\Q$path\E\/?(.*)$/ or die "$path not in ". $r->uri; + + $1; + +} + +sub encode_rest { + #XXX HTTP Accept header to send other formats besides JSON + encode_json(shift); +} + +1; diff --git a/FS/FS/cust_bill.pm b/FS/FS/cust_bill.pm index 4fb4a7d47..7cee5d78a 100644 --- a/FS/FS/cust_bill.pm +++ b/FS/FS/cust_bill.pm @@ -3243,6 +3243,14 @@ sub re_X { } +sub API_getinfo { + my $self = shift; + +{ ( map { $_=>$self->$_ } $self->fields ), + 'owed' => $self->owed, + #XXX last payment applied date + }; +} + =back =head1 CLASS METHODS diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm index 9f382ac4f..f0a479997 100644 --- a/FS/FS/cust_main.pm +++ b/FS/FS/cust_main.pm @@ -8,6 +8,7 @@ use base qw( FS::cust_main::Packages FS::cust_main::Billing_ThirdParty FS::cust_main::Location FS::cust_main::Credit_Limit + FS::cust_main::API FS::otaker_Mixin FS::payinfo_Mixin FS::cust_main_Mixin FS::geocode_Mixin FS::Quotable_Mixin FS::Sales_Mixin FS::o2m_Common diff --git a/FS/FS/cust_main/API.pm b/FS/FS/cust_main/API.pm new file mode 100644 index 000000000..2637c7eba --- /dev/null +++ b/FS/FS/cust_main/API.pm @@ -0,0 +1,63 @@ +package FS::cust_main::API; + +use strict; + +#some false laziness w/ClientAPI::Myaccount customer_info/customer_info_short + +use vars qw( + @cust_main_addl_fields @cust_main_editable_fields @location_editable_fields +); +@cust_main_addl_fields = qw( + agentnum salesnum refnum classnum usernum referral_custnum +); +@cust_main_editable_fields = qw( + first last company daytime night fax mobile +); +# locale +# payby payinfo payname paystart_month paystart_year payissue payip +# ss paytype paystate stateid stateid_state +@location_editable_fields = qw( + address1 address2 city county state zip country +); + +sub API_getinfo { + my( $self, %opt ) = @_; + + my %return = ( + 'error' => '', + 'display_custnum' => $self->display_custnum, + 'name' => $self->first. ' '. $self->get('last'), + 'balance' => $self->balance, + 'status' => $self->status, + 'statuscolor' => $self->statuscolor, + ); + + $return{$_} = $self->get($_) + foreach @cust_main_editable_fields; + + unless ( $opt{'selfservice'} ) { + $return{$_} = $self->get($_) + foreach @cust_main_addl_fields; + } + + for (@location_editable_fields) { + $return{$_} = $self->bill_location->get($_) + if $self->bill_locationnum; + $return{'ship_'.$_} = $self->ship_location->get($_) + if $self->ship_locationnum; + } + + my @invoicing_list = $self->invoicing_list; + $return{'invoicing_list'} = + join(', ', grep { $_ !~ /^(POST|FAX)$/ } @invoicing_list ); + $return{'postal_invoicing'} = + 0 < ( grep { $_ eq 'POST' } @invoicing_list ); + + #generally, the more useful data from the cust_main record the better. + # well, tell me what you want + + return \%return; + +} + +1; diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm index 775c353e4..1044e436e 100644 --- a/FS/FS/cust_pay.pm +++ b/FS/FS/cust_pay.pm @@ -892,6 +892,13 @@ sub unapplied_sql { } +sub API_getinfo { + my $self = shift; + my @fields = grep { $_ ne 'payinfo' } $self->fields; + +{ ( map { $_=>$self->$_ } @fields ), + }; +} + # _upgrade_data # # Used by FS::Upgrade to migrate to a new database. diff --git a/FS/FS/cust_pkg.pm b/FS/FS/cust_pkg.pm index af1bd835e..915f2297b 100644 --- a/FS/FS/cust_pkg.pm +++ b/FS/FS/cust_pkg.pm @@ -1,5 +1,5 @@ package FS::cust_pkg; -use base qw( FS::cust_pkg::Search +use base qw( FS::cust_pkg::Search FS::cust_pkg::API FS::otaker_Mixin FS::cust_main_Mixin FS::Sales_Mixin FS::contact_Mixin FS::location_Mixin FS::m2m_Common FS::option_Common diff --git a/FS/FS/cust_pkg/API.pm b/FS/FS/cust_pkg/API.pm new file mode 100644 index 000000000..f87eed345 --- /dev/null +++ b/FS/FS/cust_pkg/API.pm @@ -0,0 +1,13 @@ +package FS::cust_pkg::API; + +use strict; + +sub API_getinfo { + my $self = shift; + + +{ ( map { $_=>$self->$_ } $self->fields ), + }; + +} + +1; diff --git a/FS/FS/cust_svc.pm b/FS/FS/cust_svc.pm index 8fc929f29..df179f58a 100644 --- a/FS/FS/cust_svc.pm +++ b/FS/FS/cust_svc.pm @@ -904,6 +904,13 @@ sub tickets { (@tickets); } +sub API_getinfo { + my $self = shift; + my $svc_x = $self->svc_x; + +{ ( map { $_=>$self->$_ } $self->fields ), + ( map { $svc_x=>$svc_x->$_ } $svc_x->fields ), + }; +} =back diff --git a/FS/FS/part_export/internal_diddb.pm b/FS/FS/part_export/internal_diddb.pm index bb9743328..8771ae883 100644 --- a/FS/FS/part_export/internal_diddb.pm +++ b/FS/FS/part_export/internal_diddb.pm @@ -81,7 +81,7 @@ sub get_dids { }) ]; - } elsif ( $opt{'state'} ) { #return aracodes + } elsif ( $opt{'state'} ) { #return areacodes $hash{state} = $opt{state}; @@ -94,7 +94,15 @@ sub get_dids { ]; } else { - die "FS::part_export::internal_diddb::get_dids called without options\n"; + + #die "FS::part_export::internal_diddb::get_dids called without options\n"; + return [ map { $_->npa. '-'. $_->nxx. '-'. $_->station } + qsearch({ 'table' => 'phone_avail', + 'hashref' => \%hash, + 'order_by' => 'ORDER BY station', + }) + ]; + } } diff --git a/FS/FS/part_pkg.pm b/FS/FS/part_pkg.pm index 2f0646740..2ad785939 100644 --- a/FS/FS/part_pkg.pm +++ b/FS/FS/part_pkg.pm @@ -1,5 +1,7 @@ package FS::part_pkg; -use base qw( FS::m2m_Common FS::o2m_Common FS::option_Common ); +use base qw( FS::part_pkg::API + FS::m2m_Common FS::o2m_Common FS::option_Common + ); use strict; use vars qw( %plans $DEBUG $setup_hack $skip_pkg_svc_hack ); @@ -2017,8 +2019,8 @@ sub _pkgs_sql { #false laziness w/part_export & cdr my %info; foreach my $INC ( @INC ) { - warn "globbing $INC/FS/part_pkg/*.pm\n" if $DEBUG; - foreach my $file ( glob("$INC/FS/part_pkg/*.pm") ) { + warn "globbing $INC/FS/part_pkg/[a-z]*.pm\n" if $DEBUG; + foreach my $file ( glob("$INC/FS/part_pkg/[a-z]*.pm") ) { warn "attempting to load plan info from $file\n" if $DEBUG; $file =~ /\/(\w+)\.pm$/ or do { warn "unrecognized file in $INC/FS/part_pkg/: $file\n"; diff --git a/FS/FS/part_pkg/API.pm b/FS/FS/part_pkg/API.pm new file mode 100644 index 000000000..3210aa0f2 --- /dev/null +++ b/FS/FS/part_pkg/API.pm @@ -0,0 +1,17 @@ +package FS::part_pkg::API; + +use strict; + +sub API_getinfo { + my $self = shift; + #my( $self, %opt ) = @_; + + +{ ( map { $_=>$self->$_ } $self->fields ), + ( map { $_=>$self->option($_) } + qw(setup_fee recur_fee) + ), + }; + +} + +1; diff --git a/htetc/freeside-base2.4.conf b/htetc/freeside-base2.4.conf index c4e93f839..36ce3a515 100644 --- a/htetc/freeside-base2.4.conf +++ b/htetc/freeside-base2.4.conf @@ -1,5 +1,6 @@ PerlModule Apache2::compat +PerlModule DBIx::Profile #PerlModule Apache::DBI PerlModule HTML::Mason @@ -72,3 +73,9 @@ PerlSetVar FreesideHttpOnly 1 Satisfy any + + + Satisfy any + SetHandler perl-script + PerlHandler HTML::Mason + diff --git a/htetc/freeside-base2.conf b/htetc/freeside-base2.conf index 1bbe90a59..e2d507a52 100644 --- a/htetc/freeside-base2.conf +++ b/htetc/freeside-base2.conf @@ -59,3 +59,9 @@ PerlSetVar FreesideHttpOnly 1 Satisfy any + + Satisfy any + SetHandler perl-script + PerlHandler HTML::Mason + + diff --git a/httemplate/REST/1.0/.cust_bill.swp b/httemplate/REST/1.0/.cust_bill.swp new file mode 100644 index 0000000000000000000000000000000000000000..44d4de7a94a29acefde64d29436755153ef9f719 GIT binary patch literal 12288 zcmeI2%Wl&^6o#j)DIhMpE)Jq{aO1(uX0 zh!>!|3ld1IS-=K~x1bCDN!%uBfvC%hGt#GtJ?ES`^EsO+-mE;nd!KHu+z=QSgjg(p z+}K;cEf$u9P+d3Fw`Yx(FJ&6Jy;*TDbV0inOPMH7+U+!zLFBuswAb%!JhWF=Dt0qV zQfE{7{;XQO&IZ`PNe#@4wd<=DowZoFN|!D^I%xrpX9H}24X^<=zy{a=8(;%$;1nB3 zqdD;s{h!Itu#nGlN9O#JCpN$a*Z><~18jf|umLu}2G{@_U;}L66dG_nA@D>fzRL*cnx;JJz#<*a0Ofj`{#uC1-^nk@E-I)7d!w3@B@2%0Uy9S z@D{uQdhb_&2OD4mY=8~00XDz}*Z><~18m@bFi^9LDpYAhh=HJq@vJ&^saK4{m!!*$ z!;en1y>%>-Xu6or*5g{A0ym;Q8BV=1E~jgh8-_yzy46zB_YxZD?TuKbSsYTGp5%GK z^NB8W8rBR)$71Cmw@#xXC3C7v)2iZ-B>hCSsDwJ5AaFyEt@ z-N>+s~w+hL~{k_x+F7LYNT3so`Y1U_~W>Bh}=GI4x! z8P3g7h6(d|jR9E#>2NW+u{@Syp->X}DlM5dvSW$YY}T7{{j^cyB@Np(mt=bj|JxCyrAj4vj5JYapU&OPoR_+FBEPY_GDrc6Qed zAur_s0xlJwpnL%&Bsg-U6sSa7P9RZ%gt*aifD_OI|Jj{gn>3MQaVnZse%{%6eda&& zJYy@nF!}1tEIm8%48!#}V|(AcQhlQOJTsnR%sJ0}nLX@kxRQ6O)B{FN|s)cXl-Hu<>-cRzNE-sK9P^aH=>da}JC>N&EJm z8Z6Xlt$mKr3($D!?0zHSTBZ@&hm)|Nl>a|NrtBV>iJM;41hUyaV0_ zEzks2FbB$@1peH^*bQ(Udl8GH`j0vEt(upj*XC}Tf? zAHnzFJ8%Vj0WN}BkOO8><3pLX6zDp7i@rOaPuL?z62kDBVZr6 z^B`k?fZN~}xCTA~7l8)^Xn-P^1bOf@xC7n(2H%1k;2QV_NIky-AA(EZ95@ROf+=td zn*Rzu1NzbmXa%$aT7gj%n4T`=9N&q`jIHC3gc~|dvd9R=%btkZod$^|GEbhGH_4_| zIxunruhVdvE1UZsp_>t^CMIqkac3QjD#Yed?$+!?H5IKM2)v+2zQEgkL=c*A8G(p; zflnoRojl$pqc&bXd~&AN5|QIKJ9&C8dykLK9!lD*+lS(|M5cHn3V1DCa!o3g$;ckF z3T+;?1JN`w6e`e}oXp6l%_F|x3RxDHn%PihQo~yr9KJ+Lq2NKiZLKOhR5xSkXmLmV z4_lS@a|Tj}j~}Im2qT&~HuG|Y44K}({%bE)<|>rgHz8Ag&x34PUd{2(cbvLN%d*ar zww2Q})%hwmb+vM=a%7&0^upYU*}I#oW_>9!#+b^49dTp$R+E#gg}sF^3LL*>+V%vYwOY;rzZ)s zh_{3vZ~TzEB9tD0mhx72c^E(ULJ=S%?f|yN{th#(IJ&GNzQ{PRg;qw*wv(U~??WNO zyz9Ux zja9<}Wnw3hoU`fz)0P9tNy8@-d*tkkv`$7AH^$3x66I-l?Vo@3j^}YdIsGy#zl2v1ulJueiMdr41^avtmOnSh~ieh}YX5HpAM2Snpg^2$dv zlgq1;SPff_rVLS$UB)zI%6|Jtq*QLJZzeBRl0z0hFjsH{tB&(XscG3TDeSsVWSIrn z5y&{)3!GXYbD1-(z8_8JNci+mtJx GVgCRGY3p79 literal 0 HcmV?d00001 diff --git a/httemplate/REST/1.0/.cust_pkg.swp b/httemplate/REST/1.0/.cust_pkg.swp new file mode 100644 index 0000000000000000000000000000000000000000..451a98554b9bfb2e7d243f943a2e1aa8e7b0788d GIT binary patch literal 12288 zcmeI2O=}ZD7{{j`^kA!^M?s$^8#jTr+g8Ct+w}#C^dOcd^`a8i%_JF`-A#9ATdGvO z=vhC3SBriD{Q!b~fcBtA!EYh{XLmzW5kilJXULD)%*!*+{AMp9^K|y%%6+;yb3>q9 z5aRN)ul2pPyCS(Jgxc~#(>$uQds6DYw>@gy3lq?3$5JM$C7rI;GU)d_EuFRHdc&EU znRWa$(aruwXH+QeX9H~D*ajxV_4&D3Gp$^jq)Qjqj~#(0umLu}2G{@_U;}J`4X^<= zaB>ak{+M`)^iLIAu#0-^pSt+U6&qj!Y=8~00XDz}*Z><~18jf|umLu30u6XAA%2ew z@qPlyzJSl*9e4{mpbe_P z29tomRd5B2gR|faI1LVv&p!ABK7u{)0hl~r0WNHS4X^<=zy{a=8(;%$fDN#LlV)Ji zsi;tCSBPDFNcIxdrYc$Sv>Qm>9nl@NNN$q7y56ve1g@z&ytyF}}T@6P&5+#bMr6iToa3hSi zL&C-KFb&Ac>(YWSdkS_Av&P0Y6Y0f%H>uiLVu7bZdkRAAe3HH77Sm~$Y9`%0haxl% z!L*r}hpLQ#Bd1!N#l7YHD1-=haO8Oiw~YWW>yS{92}Yq3Hy^rM!<%tT{ec8E2qxR1qO|IY8X literal 0 HcmV?d00001 diff --git a/httemplate/REST/1.0/.part_pkg.swp b/httemplate/REST/1.0/.part_pkg.swp new file mode 100644 index 0000000000000000000000000000000000000000..547a79eee70e909867fa3ae423c06424560a50df GIT binary patch literal 12288 zcmeI2O-~a+7{>>%iZ6IXlSf$G-GowniAX2~Ogvy>Vg!{$Ofz(+bi=;1yHg1g^r(IT zJ!+)GwfsqZhx0|Jk;**bqcdB+n*4c6VN$dFD4$0_m)b-<`in6JwVJu9HGM z@;)uhOkNXb&kNx{l#wak@2Uh!>6%>Muiax4FkeZON_|h|t6HnD7D%n~x34cO<}Zwm z=W8<2rP|u+exbOY4X}ZO7-;B9?rOidbn(Kt={7ucj!qBUIY90fS%woC4bz`#pFI-T)0!Pykb465y*#F#)aslj|V(io9QgSKv7?^SB2r@aw1$ z?*LzHfDNz#Hoykh02^QfY~YX@DC9@{$k#=a{ucg{?z$dK?RqsevpYv=o9+Ii_dj&q zyUSiRS$R)op{K-3lx`#uP1Ah}WsR)%JaY$VTAaHzUs_e#k1FwKM-{;%M1~t#QE$B7 zl0B38s}ZuJ&X`F(RWd189lJdjdz6+(sxqy*SwhVf%zmPv>#g}%Uw6p!Q@Ii-kII2e z)2I=Wi-wp<76xNDnXOH-N;F-hv@8ReI97Sp&lNGM3>~ZFx`chTMJh-YZ5k6>0N3!+ z(h?=g^AlCpq+^m)Zlt;tN0-M#=HlXzd^VSMfs8dO_1PA+|)mno1m!SO}Fv4_qi82SC==-X<&Twd>s^t*XLv z01v@|6E9F6fpS8;1s5b{9h)FHM7>dIR{G11v-6*s-|ofo?suNIXDvswrt*OYuG->gwQe+?XfW;P9tta`_Y5F$L(&b(@w{U z5>Y5g-CYfCvzQOGto+jD5VqSZ@`J z$M65;`~UZAjD1C&qdud~Q14K0Q5uz@dZ-mt1@+}BW1mnd>KSSsbrbayeSe@npg3xX z8lY^xEfftRKm>>Y5g-CYfCvx)B0vO)z<*3&(5_1*jmH=)8*YF39P4p7b0EWm(1B1! zWS|Y+1J48xl2Cv+3dUTG1h_0dhFX3`T1{dNL#T7_j5u~YM17f$oCa<{p`!b(5yyzDbOA(R5DDuJEd9Z0ieDnqG8Sd2{w z+!!8=MF=JVJq^&?K&`l`VmydQ%L8y=1Mba3G`Mh5+QvyHz+hK^=e=!)=0!8)=0$&H z1{XZ&=4p^q`Ovmz%k#0i9D?!Z1zBEw#_~2N>Xk}n>fcsiq9UR7!lFN4gTfHa54GS~ zFxF0^%+k1n3(zQFG=^Tu1x^7sL>^xv!`l8>o8K{Z+NNy8u+O!`HH?mdgO+$&9(PA9 tbud3DZ#O{;4-NnT literal 0 HcmV?d00001 diff --git a/httemplate/REST/1.0/.rate_detail.swp b/httemplate/REST/1.0/.rate_detail.swp new file mode 100644 index 0000000000000000000000000000000000000000..8d46a280f00f95becd547d1b0486b5d0f3e090a5 GIT binary patch literal 12288 zcmeI2&1w@-6vt0p7HdT}?mV{B&V;s^Mn#1-Y5j<_U{#uaxCjonnVV)LNz<7dwS?5C zP`c1Z@F8^JUQ|#J7lP>0NATR-nK~(AyDgjxe=g_T^L2kSn~>RomZR z!FQ!|FK@v4ae&~lXlnOit6G;*wZxOd;&ydGw;D#^+3c2^^U~TUDp74Xs|fn48u)qazpa?3vXgr*j|^U;<2l2`~XBzyz28 z6JP?zpMYu&z%#nWiTEm`@jh^1k4@f~025#WOn?b60Vco%m;e)C0!)AjFo9!8K==Sx zP6B)*>Hq(e-~V5S0X~vGklvEskY1B^NP={qG)nq(3g8uKkMx4{ob-q^M=FpeNfv34 z^koR(GwD5PkK~coNo%A9(l}|D^qXe+Mfw@f^\ +<%init> + +rest_auth($cgi); + +my( $invnum, $command ) = split('/', rest_uri_remain($r, $m) ); + +my $cust_bill = qsearchs('cust_bill', { 'invnum'=>$invnum } ) + or die "unknown invnum $invnum"; + +my $return = []; + +if ( $command eq '' ) { + + my @fields = fields('cust_bill'); + $return = +{ map { $_=>$cust_bill->$_ } @fields }; + +} elsif ( $command eq 'cust_bill_pkg' ) { + + my @fields = fields('cust_bill_pkg'); + $return = [ map { my $cust_bill_pkg = $_; + +{ map { $_=>$cust_bill_pkg->$_ } @fields }; + } + $cust_bill->cust_bill_pkg + ]; +} + + diff --git a/httemplate/REST/1.0/cust_main b/httemplate/REST/1.0/cust_main new file mode 100644 index 000000000..89c558cc2 --- /dev/null +++ b/httemplate/REST/1.0/cust_main @@ -0,0 +1,81 @@ +<% encode_rest($return) %>\ +<%init> + +rest_auth($cgi); + +my( $custnum, $command ) = split('/', rest_uri_remain($r, $m), 2 ); + +if ( $r->method eq 'GET' ) { + + my $return = []; + + if ( $custnum ) { + + my $cust_main = qsearchs('cust_main', { 'custnum'=>$custnum } ) + or die "unknown custnum $custnum"; + + if ( $command eq '' ) { + + $return = $cust_main->API_getinfo; + + } elsif ( $command =~ /^(cust_(pkg|attachment|bill|pay))$/ ) { + + my $method = $1; + + $return = [ map $_->API_getinfo, $cust_main->$method ]; + + } elsif ( $command eq 'part_pkg' ) { + + my %pkgpart = map { $_->pkgpart => 1 } $cust_main->cust_pkg; + + $return = [ map $_->API_getinfo, + map qsearchs('part_pkg', { 'pkgpart'=>$_ }), + keys %pkgpart; + ]; + + } + + } else { #list + + my %hash = ( map { $_ => scalar($cgi->param($_)) } + qw( agentnum salesnum refnum classnum usernum + referral_custnum + ) + ); + + my $extra_sql = ''; + if ( $cgi->param('cust_main_invoice_dest') ) { + my $dest = dbh->quote(scalar($cgi->param('cust_main_invoice_dest'))); + $extra_sql = " + WHERE EXISTS ( SELECT 1 FROM cust_main_invoice + WHERE cust_main.custnum = cust_main_invoice.custnum + AND dest = $dest + ) + "; + } elsif ( $cgi->param('cust_main_invoice_dest_substring') ) { + my $dest = dbh->quote('%'. scalar($cgi->param('cust_main_invoice_dest_substring')). '%'); + $extra_sql = " + WHERE EXISTS ( SELECT 1 FROM cust_main_invoice + WHERE cust_main.custnum = cust_main_invoice.custnum + AND dest ILIKE $dest + ) + "; + } + + my @cust_main = qsearch({ + 'table' => 'cust_main', + 'hashref' => \%hash, + 'extra_sql' => $extra_sql; + }); + + $return = [ map $_->API_getinfo, @cust_main ]; + + } + +} elsif ( $r->method eq 'POST' ) { #create new + +} elsif ( $r->method eq 'PUT' ) { #modify + +} + + diff --git a/httemplate/REST/1.0/cust_pkg b/httemplate/REST/1.0/cust_pkg new file mode 100644 index 000000000..3c58bcf31 --- /dev/null +++ b/httemplate/REST/1.0/cust_pkg @@ -0,0 +1,39 @@ +<% encode_rest($return) %>\ +<%init> + +rest_auth($cgi); + +my( $pkgnum, $command ) = split('/', rest_uri_remain($r, $m), 2 ); + +if ( $r->method eq 'GET' ) { + + my $return = []; + + if ( $pkgnum ) { + + my $cust_pkg = qsearchs('cust_main', { 'pkgnum'=>$pkgnum } ) + or die "unknown pkgnum $pkgnum"; + + if ( $command eq '' ) { + + $return = $cust_pkg->API_getinfo; + + } elsif ( $command eq 'cust_svc' ) { + + $return = [ map $_->API_getinfo, $cust_pkg->cust_svc ]; + + } + + + + #} else { #list + + } + +} elsif ( $r->method eq 'POST' ) { #create new + +} elsif ( $r->method eq 'PUT' ) { #modify + +} + + diff --git a/httemplate/REST/1.0/part_pkg b/httemplate/REST/1.0/part_pkg new file mode 100644 index 000000000..c81b7b89b --- /dev/null +++ b/httemplate/REST/1.0/part_pkg @@ -0,0 +1,40 @@ +<% encode_rest($return) %>\ +<%init> + +rest_auth($cgi); + +my( $pkgpart, $command ) = split('/', rest_uri_remain($r, $m) ); + +my @fields = fields('part_pkg'); + +my $return = []; + +if ( $pkgpart ) { + + my $part_pkg = qsearchs('part_pkg', { 'pkgpart'=>$pkgpart } ) + or die "unknown pkgpart $pkgpart"; + + if ( $command eq '' ) { + + $return = $part_pkg->API_getinfo; + + } elsif ( $command eq 'customers' ) { + die 'XXX not yet implemented'; + #XXX redirect to a cust_main search? + } + +} else { + + my %hash = ( map { $_ => scalar($cgi->param($_)) } + qw( disabled classnum ) + ); + + my @part_pkg = qsearch('part_pkg', \%hash); + + $return = [ map $part_pkg->API_getinfo, @part_pkg ]; + +} + + + + diff --git a/httemplate/REST/1.0/phone_avail b/httemplate/REST/1.0/phone_avail new file mode 100644 index 000000000..ef9d3e7f0 --- /dev/null +++ b/httemplate/REST/1.0/phone_avail @@ -0,0 +1,25 @@ +<% encode_rest($phonenums) %>\ +<%init> + +rest_auth($cgi); + +#i'm basically a simpler misc/phonenums.cgi + +my $svcpart = $cgi->param('svcpart'); + +my $part_svc = qsearchs('part_svc', { 'svcpart'=>$svcpart } ); +die "unknown svcpart $svcpart" unless $part_svc; + +my @exports = $part_svc->part_export_did; +if ( scalar(@exports) > 1 ) { + die "more than one DID-providing export attached to svcpart $svcpart"; +} elsif ( ! @exports ) { + die "no DID providing export attached to svcpart $svcpart"; +} +my $export = $exports[0]; + +my $phonenums = $export->get_dids( map { $_ => scalar($cgi->param($_)) } + qw( ratecenter state areacode exchange ) + ); + + diff --git a/httemplate/REST/1.0/rate_detail b/httemplate/REST/1.0/rate_detail new file mode 100644 index 000000000..54e55de6c --- /dev/null +++ b/httemplate/REST/1.0/rate_detail @@ -0,0 +1,35 @@ +<% encode_rest( \@rate_detail ) %>\ +<%init> + +rest_auth($cgi); + +my $extra_sql = ''; +if ( $cgi->param('countrycode') =~ /^\+?(\d+)$/ ) { + my $countrycode = $1; + $extra_sql = " + WHERE EXISTS ( SELECT 1 rate_region + WHERE rate_detail.dest_regionnum = rate_region.regionnum + AND countrycode = '$countrycode' + "; +} + +my @detail_fields = fields('rate_detail'); +my @region_fields = fields('rate_region'); + +my @rate_detail = + map { + my $rate_detail = $_; + my $rate_region = $rate_detail->dest_region; + + +{ + ( map { $_ => $rate_detail->$_ } @detail_fields ), + ( map { $_ => $rate_region->$_ } @region_fields ), + }; + + } qsearch({ + 'table' => 'rate_detail', + 'hashref' => {}, + extra_sql => $extra_sql, + }); + + -- 2.11.0