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)
65 my($context, $session, $custnum) = _custoragent_session_custnum($p);
66 return { 'error' => $session } if $context eq 'error';
68 my $quotation = _quotation($session);
69 return { 'error' => "No current quotation for this customer" } if !$quotation;
70 warn "quotation_info #".$quotation->quotationnum
73 my $null_escape = sub { @_ };
74 # 3.x only; 4.x quotation redesign uses actual sections for this
75 # and isn't a weird hack
77 map { $_->{'pkgnum'} = $_->{'preref_html'}; $_ }
78 $quotation->_items_pkg(escape_function => $null_escape,
79 preref_callback => sub { shift->quotationpkgnum });
80 push @items, $quotation->_items_total();
83 { 'description' => 'Estimated Charges',
84 'detail_items' => \@items
87 warn Dumper $sections;
89 return { 'error' => '', 'sections' => $sections }
92 =item quotation_print { session, 'format' }
94 Renders the quotation. 'format' can be either 'html' or 'pdf'; the resulting
95 hashref will contain 'document' => the HTML or PDF contents.
102 my($context, $session, $custnum) = _custoragent_session_custnum($p);
103 return { 'error' => $session } if $context eq 'error';
105 my $quotation = _quotation($session);
106 return { 'error' => "No current quotation for this customer" } if !$quotation;
107 warn "quotation_print #".$quotation->quotationnum
110 my $format = $p->{'format'}
111 or return { 'error' => "No rendering format specified" };
114 if ($format eq 'html') {
115 $document = $quotation->print_html;
116 } elsif ($format eq 'pdf') {
117 $document = $quotation->print_pdf;
119 warn "$format, ".length($document)." bytes\n"
121 return { 'error' => '', 'document' => $document };
124 =item quotation_add_pkg { session, 'pkgpart', 'quantity', [ location opts ] }
126 Adds a package to the user's current quotation. Session info and 'pkgpart' are
127 required. 'quantity' defaults to 1.
129 Location can be specified as 'locationnum' to use an existing location, or
130 'address1', 'address2', 'city', 'state', 'zip', 'country' to create a new one,
131 or it will default to the customer's service location.
135 sub quotation_add_pkg {
138 my($context, $session, $custnum) = _custoragent_session_custnum($p);
139 return { 'error' => $session } if $context eq 'error';
141 my $quotation = _quotation($session);
142 my $cust_main = $quotation->cust_main;
144 my $pkgpart = $p->{'pkgpart'};
145 my $allowed_pkgpart = $cust_main->agent->pkgpart_hashref;
147 my $part_pkg = FS::part_pkg->by_key($pkgpart);
150 (!$allowed_pkgpart->{$pkgpart} and
151 $cust_main->agentnum != ($part_pkg->agentnum || 0))
153 warn "disallowed quotation_pkg pkgpart $pkgpart\n"
155 return { 'error' => "unknown package $pkgpart" };
158 warn "creating quotation_pkg with pkgpart $pkgpart\n"
160 my $quotation_pkg = FS::quotation_pkg->new({
161 'quotationnum' => $quotation->quotationnum,
162 'pkgpart' => $p->{'pkgpart'},
163 'quantity' => $p->{'quantity'} || 1,
165 if ( $p->{locationnum} > 0 ) {
166 $quotation_pkg->set('locationnum', $p->{locationnum});
167 } elsif ( $p->{address1} ) {
168 my $location = FS::cust_location->find_or_insert(
169 'custnum' => $cust_main->custnum,
170 map { $_ => $p->{$_} }
171 qw( address1 address2 city county state zip country )
173 $quotation_pkg->set('locationnum', $location->locationnum);
176 my $error = $quotation_pkg->insert
177 || $quotation->estimate;
180 'quotationnum' => $quotation->quotationnum };
183 =item quotation_remove_pkg { session, 'pkgnum' }
185 Removes the package from the user's current quotation. 'pkgnum' is required.
189 sub quotation_remove_pkg {
192 my($context, $session, $custnum) = _custoragent_session_custnum($p);
193 return { 'error' => $session } if $context eq 'error';
195 my $quotation = _quotation($session);
196 my $quotationpkgnum = $p->{pkgnum};
197 my $quotation_pkg = FS::quotation_pkg->by_key($quotationpkgnum);
199 or $quotation_pkg->quotationnum != $quotation->quotationnum) {
200 return { 'error' => "unknown quotation item $quotationpkgnum" };
202 warn "removing quotation_pkg with pkgpart ".$quotation_pkg->pkgpart."\n"
205 my $error = $quotation_pkg->delete
206 || $quotation->estimate;
209 'quotationnum' => $quotation->quotationnum };
212 =item quotation_order
214 Convert the current quotation to a package order.
218 sub quotation_order {
221 my($context, $session, $custnum) = _custoragent_session_custnum($p);
222 return { 'error' => $session } if $context eq 'error';
224 my $quotation = _quotation($session);
226 my $error = $quotation->order;
228 return { 'error' => $error };