1 package FS::ClientAPI::MyAccount::quotation;
4 use FS::Record qw(qsearch qsearchs);
10 sub _custoragent_session_custnum {
11 FS::ClientAPI::MyAccount::_custoragent_session_custnum(@_);
15 # the currently active quotation
18 if ( my $quotationnum = $session->{'quotationnum'} ) {
19 $quotation = FS::quotation->by_key($quotationnum);
22 # find the last quotation created through selfservice
23 $quotation = qsearchs( 'quotation', {
24 'custnum' => $session->{'custnum'},
25 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
28 warn "found selfservice quotation #". $quotation->quotationnum."\n"
29 if $quotation and $DEBUG;
32 $quotation = FS::quotation->new({
33 'custnum' => $session->{'custnum'},
34 'usernum' => $FS::CurrentUser::CurrentUser->usernum,
37 $quotation->insert; # what to do on error? call the police?
38 warn "started new selfservice quotation #". $quotation->quotationnum."\n"
39 if $quotation and $DEBUG;
41 $session->{'quotationnum'} = $quotation->quotationnum;
45 =item quotation_info { session }
47 Returns a hashref describing the current quotation, containing:
49 - "sections", an arrayref containing one section for each billing frequency.
53 - "detail_items", an arrayref of detail items, each with:
54 - "pkgnum", the reference number (actually the quotationpkgnum field)
55 - "description", the package name (or tax name)
64 my($context, $session, $custnum) = _custoragent_session_custnum($p);
65 return { 'error' => $session } if $context eq 'error';
67 my $quotation = _quotation($session);
68 return { 'error' => "No current quotation for this customer" } if !$quotation;
69 warn "quotation_info #".$quotation->quotationnum
73 my $null_escape = sub { @_ };
74 my ($sections) = $quotation->_items_sections(escape => $null_escape);
75 foreach my $section (@$sections) {
76 $section->{'detail_items'} =
77 [ $quotation->_items_pkg('section' => $section, escape_function => $null_escape) ];
79 return { 'error' => '', 'sections' => $sections }
82 =item quotation_print { session, 'format' }
84 Renders the quotation. 'format' can be either 'html' or 'pdf'; the resulting
85 hashref will contain 'document' => the HTML or PDF contents.
92 my($context, $session, $custnum) = _custoragent_session_custnum($p);
93 return { 'error' => $session } if $context eq 'error';
95 my $quotation = _quotation($session);
96 return { 'error' => "No current quotation for this customer" } if !$quotation;
97 warn "quotation_print #".$quotation->quotationnum
100 my $format = $p->{'format'}
101 or return { 'error' => "No rendering format specified" };
104 if ($format eq 'html') {
105 $document = $quotation->print_html;
106 } elsif ($format eq 'pdf') {
107 $document = $quotation->print_pdf;
109 warn "$format, ".length($document)." bytes\n"
111 return { 'error' => '', 'document' => $document };
114 =item quotation_add_pkg { session, 'pkgpart', 'quantity', [ location opts ] }
116 Adds a package to the user's current quotation. Session info and 'pkgpart' are
117 required. 'quantity' defaults to 1.
119 Location can be specified as 'locationnum' to use an existing location, or
120 'address1', 'address2', 'city', 'state', 'zip', 'country' to create a new one,
121 or it will default to the customer's service location.
125 sub quotation_add_pkg {
128 my($context, $session, $custnum) = _custoragent_session_custnum($p);
129 return { 'error' => $session } if $context eq 'error';
131 my $quotation = _quotation($session);
132 my $cust_main = $quotation->cust_main;
134 my $pkgpart = $p->{'pkgpart'};
135 my $allowed_pkgpart = $cust_main->agent->pkgpart_hashref;
137 my $part_pkg = FS::part_pkg->by_key($pkgpart);
140 (!$allowed_pkgpart->{$pkgpart} and
141 $cust_main->agentnum != ($part_pkg->agentnum || 0))
143 warn "disallowed quotation_pkg pkgpart $pkgpart\n"
145 return { 'error' => "unknown package $pkgpart" };
148 warn "creating quotation_pkg with pkgpart $pkgpart\n"
150 my $quotation_pkg = FS::quotation_pkg->new({
151 'quotationnum' => $quotation->quotationnum,
152 'pkgpart' => $p->{'pkgpart'},
153 'quantity' => $p->{'quantity'} || 1,
155 if ( $p->{locationnum} > 0 ) {
156 $quotation_pkg->set('locationnum', $p->{locationnum});
157 } elsif ( $p->{address1} ) {
158 my $location = FS::cust_location->find_or_insert(
159 'custnum' => $cust_main->custnum,
160 map { $_ => $p->{$_} }
161 qw( address1 address2 city county state zip country )
163 $quotation_pkg->set('locationnum', $location->locationnum);
166 my $error = $quotation_pkg->insert
167 || $quotation->estimate;
170 'quotationnum' => $quotation->quotationnum };
173 =item quotation_remove_pkg { session, 'pkgnum' }
175 Removes the package from the user's current quotation. 'pkgnum' is required.
179 sub quotation_remove_pkg {
182 my($context, $session, $custnum) = _custoragent_session_custnum($p);
183 return { 'error' => $session } if $context eq 'error';
185 my $quotation = _quotation($session);
186 my $quotationpkgnum = $p->{pkgnum};
187 my $quotation_pkg = FS::quotation_pkg->by_key($quotationpkgnum);
189 or $quotation_pkg->quotationnum != $quotation->quotationnum) {
190 return { 'error' => "unknown quotation item $quotationpkgnum" };
192 warn "removing quotation_pkg with pkgpart ".$quotation_pkg->pkgpart."\n"
195 my $error = $quotation_pkg->delete
196 || $quotation->estimate;
199 'quotationnum' => $quotation->quotationnum };
202 =item quotation_order
204 Convert the current quotation to a package order.
208 sub quotation_order {
211 my($context, $session, $custnum) = _custoragent_session_custnum($p);
212 return { 'error' => $session } if $context eq 'error';
214 my $quotation = _quotation($session);
216 my $error = $quotation->order;
218 return { 'error' => $error };