summaryrefslogtreecommitdiff
path: root/FS/FS/ClientAPI/MyAccount
diff options
context:
space:
mode:
authorMark Wells <mark@freeside.biz>2015-04-25 15:02:15 -0700
committerMark Wells <mark@freeside.biz>2015-04-25 15:02:23 -0700
commitc110da0da864245e47cae019b8a347367cc6430c (patch)
treee406be890446095b8cd59a5b5c827c62dd063fff /FS/FS/ClientAPI/MyAccount
parent4fda726fa9f8e709c68ec823edc5ae702723281c (diff)
selfservice quotations, #33852
Diffstat (limited to 'FS/FS/ClientAPI/MyAccount')
-rw-r--r--FS/FS/ClientAPI/MyAccount/quotation.pm218
1 files changed, 218 insertions, 0 deletions
diff --git a/FS/FS/ClientAPI/MyAccount/quotation.pm b/FS/FS/ClientAPI/MyAccount/quotation.pm
new file mode 100644
index 0000000..ce2debd
--- /dev/null
+++ b/FS/FS/ClientAPI/MyAccount/quotation.pm
@@ -0,0 +1,218 @@
+package FS::ClientAPI::MyAccount::quotation;
+
+use strict;
+use FS::Record qw(qsearch qsearchs);
+use FS::quotation;
+use FS::quotation_pkg;
+
+our $DEBUG = 1;
+
+sub _custoragent_session_custnum {
+ FS::ClientAPI::MyAccount::_custoragent_session_custnum(@_);
+}
+
+sub _quotation {
+ # the currently active quotation
+ my $session = shift;
+ my $quotation;
+ if ( my $quotationnum = $session->{'quotationnum'} ) {
+ $quotation = FS::quotation->by_key($quotationnum);
+ }
+ if ( !$quotation ) {
+ # find the last quotation created through selfservice
+ $quotation = qsearchs( 'quotation', {
+ 'custnum' => $session->{'custnum'},
+ 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
+ 'disabled' => '',
+ });
+ warn "found selfservice quotation #". $quotation->quotationnum."\n"
+ if $quotation and $DEBUG;
+ }
+ if ( !$quotation ) {
+ $quotation = FS::quotation->new({
+ 'custnum' => $session->{'custnum'},
+ 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
+ '_date' => time,
+ });
+ $quotation->insert; # what to do on error? call the police?
+ warn "started new selfservice quotation #". $quotation->quotationnum."\n"
+ if $quotation and $DEBUG;
+ }
+ $session->{'quotationnum'} = $quotation->quotationnum;
+ return $quotation;
+}
+
+=item quotation_info { session }
+
+Returns a hashref describing the current quotation, containing:
+
+- "sections", an arrayref containing one section for each billing frequency.
+ Each one will have:
+ - "description"
+ - "subtotal"
+ - "detail_items", an arrayref of detail items, each with:
+ - "pkgnum", the reference number (actually the quotationpkgnum field)
+ - "description", the package name (or tax name)
+ - "quantity"
+ - "amount"
+
+=cut
+
+sub quotation_info {
+ my $p = shift;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $quotation = _quotation($session);
+ return { 'error' => "No current quotation for this customer" } if !$quotation;
+ warn "quotation_info #".$quotation->quotationnum
+ if $DEBUG;
+
+ # code reuse ftw
+ my $null_escape = sub { @_ };
+ my ($sections) = $quotation->_items_sections(escape => $null_escape);
+ foreach my $section (@$sections) {
+ $section->{'detail_items'} =
+ [ $quotation->_items_pkg('section' => $section, escape_function => $null_escape) ];
+ }
+ return { 'error' => '', 'sections' => $sections }
+}
+
+=item quotation_print { session, 'format' }
+
+Renders the quotation. 'format' can be either 'html' or 'pdf'; the resulting
+hashref will contain 'document' => the HTML or PDF contents.
+
+=cut
+
+sub quotation_print {
+ my $p = shift;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $quotation = _quotation($session);
+ return { 'error' => "No current quotation for this customer" } if !$quotation;
+ warn "quotation_print #".$quotation->quotationnum
+ if $DEBUG;
+
+ my $format = $p->{'format'}
+ or return { 'error' => "No rendering format specified" };
+
+ my $document;
+ if ($format eq 'html') {
+ $document = $quotation->print_html;
+ } elsif ($format eq 'pdf') {
+ $document = $quotation->print_pdf;
+ }
+ warn "$format, ".length($document)." bytes\n"
+ if $DEBUG;
+ return { 'error' => '', 'document' => $document };
+}
+
+=item quotation_add_pkg { session, 'pkgpart', 'quantity', [ location opts ] }
+
+Adds a package to the user's current quotation. Session info and 'pkgpart' are
+required. 'quantity' defaults to 1.
+
+Location can be specified as 'locationnum' to use an existing location, or
+'address1', 'address2', 'city', 'state', 'zip', 'country' to create a new one,
+or it will default to the customer's service location.
+
+=cut
+
+sub quotation_add_pkg {
+ my $p = shift;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $quotation = _quotation($session);
+ my $cust_main = $quotation->cust_main;
+
+ my $pkgpart = $p->{'pkgpart'};
+ my $allowed_pkgpart = $cust_main->agent->pkgpart_hashref;
+
+ my $part_pkg = FS::part_pkg->by_key($pkgpart);
+
+ if (!$part_pkg or !$allowed_pkgpart->{$pkgpart}) {
+ warn "disallowed quotation_pkg pkgpart $pkgpart\n"
+ if $DEBUG;
+ return { 'error' => "unknown package $pkgpart" };
+ }
+
+ warn "creating quotation_pkg with pkgpart $pkgpart\n"
+ if $DEBUG;
+ my $quotation_pkg = FS::quotation_pkg->new({
+ 'quotationnum' => $quotation->quotationnum,
+ 'pkgpart' => $p->{'pkgpart'},
+ 'quantity' => $p->{'quantity'} || 1,
+ });
+ if ( $p->{locationnum} > 0 ) {
+ $quotation_pkg->set('locationnum', $p->{locationnum});
+ } elsif ( $p->{address1} ) {
+ my $location = FS::cust_location->find_or_insert(
+ 'custnum' => $cust_main->custnum,
+ map { $_ => $p->{$_} }
+ qw( address1 address2 city county state zip country )
+ );
+ $quotation_pkg->set('locationnum', $location->locationnum);
+ }
+
+ my $error = $quotation_pkg->insert
+ || $quotation->estimate;
+
+ { 'error' => $error,
+ 'quotationnum' => $quotation->quotationnum };
+}
+
+=item quotation_remove_pkg { session, 'pkgnum' }
+
+Removes the package from the user's current quotation. 'pkgnum' is required.
+
+=cut
+
+sub quotation_remove_pkg {
+ my $p = shift;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $quotation = _quotation($session);
+ my $quotationpkgnum = $p->{pkgnum};
+ my $quotation_pkg = FS::quotation_pkg->by_key($quotationpkgnum);
+ if (!$quotation_pkg
+ or $quotation_pkg->quotationnum != $quotation->quotationnum) {
+ return { 'error' => "unknown quotation item $quotationpkgnum" };
+ }
+ warn "removing quotation_pkg with pkgpart ".$quotation_pkg->pkgpart."\n"
+ if $DEBUG;
+
+ my $error = $quotation_pkg->delete
+ || $quotation->estimate;
+
+ { 'error' => $error,
+ 'quotationnum' => $quotation->quotationnum };
+}
+
+=item quotation_order
+
+Convert the current quotation to a package order.
+
+=cut
+
+sub quotation_order {
+ my $p = shift;
+
+ my($context, $session, $custnum) = _custoragent_session_custnum($p);
+ return { 'error' => $session } if $context eq 'error';
+
+ my $quotation = _quotation($session);
+
+ my $error = $quotation->order;
+
+ return { 'error' => $error };
+}
+
+1;