=over 4
-=item order CUSTNUM, PKGPARTS_ARYREF, [ REMOVE_PKGNUMS_ARYREF ]
+=item order CUSTNUM, PKGPARTS_ARYREF, [ REMOVE_PKGNUMS_ARYREF [ RETURN_CUST_PKG_ARRAYREF ] ]
CUSTNUM is a customer (see L<FS::cust_main>)
REMOVE_PKGNUMS is an optional list of pkgnums specifying the billing items to
remove for this customer. The services (see L<FS::cust_svc>) are moved to the
new billing items. An error is returned if this is not possible (see
-L<FS::pkg_svc>).
+L<FS::pkg_svc>). An empty arrayref is equivalent to not specifying this
+parameter.
+
+RETURN_CUST_PKG_ARRAYREF, if specified, will be filled in with the
+newly-created cust_pkg objects.
=cut
sub order {
- my($custnum,$pkgparts,$remove_pkgnums)=@_;
+ my($custnum, $pkgparts, $remove_pkgnums, $return_cust_pkg) = @_;
+ $remove_pkgnums = [] unless defined($remove_pkgnums);
my $oldAutoCommit = $FS::UID::AutoCommit;
local $FS::UID::AutoCommit = 0;
my($old) = qsearchs('cust_pkg',{'pkgnum'=>$pkgnum});
unless ( $old ) {
$dbh->rollback if $oldAutoCommit;
- die "Package $pkgnum not found to remove!";
+ return "Package $pkgnum not found to remove!";
}
my(%hash) = $old->hash;
$hash{'cancel'}=time;
my($error)=$new->replace($old);
if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- die "Couldn't update package $pkgnum: $error";
+ return "Couldn't update package $pkgnum: $error";
}
}
# my($pkgpart);
while ($pkgpart=shift @{$pkgparts} ) {
- my($new) = new FS::cust_pkg ( {
- 'custnum' => $custnum,
- 'pkgpart' => $pkgpart,
- } );
- my($error) = $new->insert;
- if ( $error ) {
+ my $new = new FS::cust_pkg {
+ 'custnum' => $custnum,
+ 'pkgpart' => $pkgpart,
+ };
+ my $error = $new->insert;
+ if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- die "Couldn't insert new cust_pkg record: $error";
+ return "Couldn't insert new cust_pkg record: $error";
}
- my($pkgnum)=$new->getfield('pkgnum');
+ push @{$return_cust_pkg}, $new if $return_cust_pkg;
+ my $pkgnum = $new->pkgnum;
- my($cust_svc);
- foreach $cust_svc ( @{ shift @cust_svc } ) {
+ foreach my $cust_svc ( @{ shift @cust_svc } ) {
my(%hash) = $cust_svc->hash;
$hash{'pkgnum'}=$pkgnum;
my($new) = new FS::cust_svc ( \%hash );
my($error)=$new->replace($cust_svc);
- if ( $error ) {
+ if ( $error ) {
$dbh->rollback if $oldAutoCommit;
- die "Couldn't link old service to new package: $error";
+ return "Couldn't link old service to new package: $error";
}
}
}
=head1 VERSION
-$Id: cust_pkg.pm,v 1.5 2001-04-09 23:05:15 ivan Exp $
+$Id: cust_pkg.pm,v 1.6 2001-09-04 14:44:06 ivan Exp $
=head1 BUGS
<%
-#<!-- $Id: agent.cgi,v 1.3 2001-08-21 09:34:13 ivan Exp $ -->
+#<!-- $Id: agent.cgi,v 1.4 2001-09-04 14:44:06 ivan Exp $ -->
use strict;
use vars qw( $ui $cgi $p $agent );
print <<END;
<TR>
- <TD COLSPAN=2><A HREF="${p}edit/agent.cgi"><I>Add new agent</I></A></TD>
- <TD><A HREF="${p}edit/agent_type.cgi"><I>Add new agent type</I></A></TD>
+ <TD COLSPAN=2><A HREF="${p}edit/agent.cgi"><I>Add a new agent</I></A></TD>
+ <TD><A HREF="${p}edit/agent_type.cgi"><I>Add a new agent type</I></A></TD>
</TR>
</TABLE>
<%
-#<!-- $Id: agent_type.cgi,v 1.3 2001-08-21 09:34:13 ivan Exp $ -->
+#<!-- $Id: agent_type.cgi,v 1.4 2001-09-04 14:44:06 ivan Exp $ -->
use strict;
use vars qw( $cgi $p $agent_type );
}
print <<END;
- <TR><TD COLSPAN=2><I><A HREF="${p}edit/agent_type.cgi">Add new agent type</A></I></TD></TR>
+ <TR><TD COLSPAN=2><I><A HREF="${p}edit/agent_type.cgi">Add a new agent type</A></I></TD></TR>
</TABLE>
</BODY>
</HTML>
<%
-#<!-- $Id: part_pkg.cgi,v 1.3 2001-08-21 09:34:13 ivan Exp $ -->
+#<!-- $Id: part_pkg.cgi,v 1.4 2001-09-04 14:44:06 ivan Exp $ -->
use strict;
use vars qw( $cgi $p $part_pkg );
$p = popurl(2);
-print $cgi->header( '-expires' => 'now' ), header("Package Part Listing",menubar(
+print $cgi->header( '-expires' => 'now' ), header("Package Definition Listing",menubar(
'Main Menu' => $p,
)), "One or more services are grouped together into a package and given",
" pricing information. Customers purchase packages, not services.<BR><BR>",
}
print <<END;
- <TR><TD COLSPAN=2><I><A HREF="${p}edit/part_pkg.cgi">Add new package</A></I></TD></TR>
+ <TR><TD COLSPAN=8><I><A HREF="${p}edit/part_pkg.cgi">Add a new package definition</A></I></TD></TR>
</TABLE>
</BODY>
</HTML>
<%
-#<!-- $Id: part_referral.cgi,v 1.3 2001-08-21 09:34:13 ivan Exp $ -->
+#<!-- $Id: part_referral.cgi,v 1.4 2001-09-04 14:44:06 ivan Exp $ -->
use strict;
use vars qw( $cgi $p $part_referral );
print <<END;
<TR>
- <TD COLSPAN=2><A HREF="${p}edit/part_referral.cgi"><I>Add new referral</I></A></TD>
+ <TD COLSPAN=2><A HREF="${p}edit/part_referral.cgi"><I>Add a new referral</I></A></TD>
</TR>
</TABLE>
</CENTER>
-<!-- $Id: part_svc.cgi,v 1.2 2001-08-11 23:18:30 ivan Exp $ -->
-<%= header('Service Part Listing', menubar( 'Main Menu' => $p) ) %>
+<!-- $Id: part_svc.cgi,v 1.3 2001-09-04 14:44:06 ivan Exp $ -->
+<%= header('Service Definition Listing', menubar( 'Main Menu' => $p) ) %>
Services are items you offer to your customers.<BR><BR>
<TABLE BORDER=1>
<% } %>
<TR>
- <TD COLSPAN=2><A HREF="<%= $p %>edit/part_svc.cgi"><I>Add new service</I></A></TD>
+ <TD COLSPAN=6><A HREF="<%= $p %>edit/part_svc.cgi"><I>Add a new service definition</I></A></TD>
</TR>
</TABLE>
</BODY>
<li>Open up the root of the Freeside document tree in your web
browser. For example, if you created the Freeside document tree in
/home/httpd/html/freeside, and your web browser's DocumentRoot is
- /home/httpd/html, open http://your_host/freeside/. Replace
+ /home/httpd/html, open https://your_host/freeside/. Replace
"your_host" with the name or network address of your web server.
<li>Once in the Freeside web interface, you must first create a
- service. An example of a service would be a dial-up account or a
- hosted virtual domain.
-
- <li>After you create your first service or services, you must then
- create a package of that service or services which you will sell to
- your customer. To allow flexibility in changing your service
- offerings, Freeside requires that you bundle your services into a
- package before customers may purchase them. For instance, you could
- create a leased line package which would consist of a one-time
- charge for the customer premise equipment, the monthly service fee
- for the leased line, a backup dial-up account, and a support
- contract. You could also create a leased line package which omits
- the support contract simply by adding a new package that does not
- include the support contract.
-
+ service definition. An example of a service definition would be a dial-up
+ account or a domain. For starters, it is necessary to create a domain
+ definition. Click on <u>View/Edit service definitions</u> and
+ <u>Add a new service definition</u> with <i>Table</i> <b>svc_domain</b>
+ (and no modifiers).
+
+ <li>Now that you have created your first service, you must create a package
+ including this service which you can sell to customers. Zero, one, or many
+ services are bundled into a package. Click on <u>View/Edit package
+ definitions</u> and <u>Add a new package definition</u> which includes
+ quantity <b>1</b> of the svc_domain service you created above.
+
<li>After you create your first package, then you must define who is
able to sell that package by creating an agent type. An example of
an agent type would be an internal sales representitive which sells
regular and promotional packages, as opposed to an external sales
- representitive which would only sell regular packages of services.
-
- <li>After creating a new agent type, you must create an agent, and
- assign the the agent type you just created to it.
-
- <li>If the service you created was of type svc_acct, you may have to
- create a POP from the main menu before you can create your first new
- customer.
-
- <li>If you are using Freeside to keep track of sales taxes, you must
- define tax information for your locale by clicking on the "View/Edit
- locales and tax rates" link on the Freeside main menu.
-
- <li>Finally, set up at least one referral by clicking on the
- "View/Edit referrals" link in the Freeside main menu. Referrals
- will help you keep track of how effective your advertising is, by
- helping you keep track of where customers heard of your service
- offerings. You must create at least one referral. If you do not wish to
- use the referral functionality, simply create a single referral only.
-
- <li>You should now be ready to sign up your first customer by
- clicking on the "New Customer" link at the top of the Freeside main
- menu.
+ representitive which would only sell regular packages of services. Click on
+ <u>View/Edit agent types</u> and <u>Add a new agent type</u>. Allow this
+ agent type to sell the package you created above.
+
+ <li>After creating a new agent type, you must create an agent. Click on
+ <u>View/Edit agents</u> and <u>Add a new agent</u>.
+
+ <li>Set up at least one referral. Referrals will help you keep track of how
+ effective your advertising is, by helping you keep track of where customers
+ heard of your service offerings. You must create at least one referral. If
+ you do not wish to use the referral functionality, simply create a single
+ referral only. Click on <u>View/Edit referrals</u> and <u>Add a new
+ referral</u>.
+
+ <li>Click on <u>New Customer</u> and create a new customer for your system
+ accounts with billing type <b>Complimentary</b>.
+
+ <li>From the Customer View screen of the newly created customer, order the
+ package you defined above.
+
+ <li>From the Package View screen of the newly cretaed package, choose
+ <u>(Add)</u> to add the customer's service for this new package.
+
+ <li>Add your own domain, and note down the assigned <b>Service #</b>.
+
+ <li>Go back to <u>View/Edit service definitions</u> on the main menu, and
+ <u>Add a new service definition</u> with <i>Table</i> <b>svc_acct</b>. Put
+ the <b>Service #</b> for your domain in the <b>domsvc</b> Modifier. Set
+ <b>Fixed</b> to define a service locked-in to this domain, or <b>Default</b>
+ to define a service which may select from among this domain and the
+ customer's domains.
+
+ <li><table><tr>
+ <td> Create at least POP (Point of Presence) by selecting
+ <u>View/Edit POPs</u> from the main menu.</td>
+ <th align="left"> OR </th>
+ <td>If you are not doing dialup, set slipip to fixed and blank for all your
+ Service Definitions which have Table <b>svc_acct</b>.</td>
+ </tr></table>
+
+ <li>If you are using Freeside to keep track of sales taxes, define tax
+ information for your locales by clicking on the <u>View/Edit locales and tax
+ rates</b> on the main menu.
+
</ul>
</body>
</html>
-<!-- $Id: part_svc.cgi,v 1.5 2001-08-30 15:30:26 ivan Exp $ -->
+<!-- $Id: part_svc.cgi,v 1.6 2001-09-04 14:44:06 ivan Exp $ -->
<%
my $part_svc;
if ( $cgi->param('error') ) { #error
<%= header("$action Service Definition",
menubar( 'Main Menu' => $p,
- 'View all services' => "${p}browse/part_svc.cgi"
+ 'View all service definitions' => "${p}browse/part_svc.cgi"
),
" onLoad=\"visualize()\""
)
</PRE>
Services are items you offer to your customers.
<UL><LI>svc_acct - Shell accounts, POP mailboxes, SLIP/PPP and ISDN accounts
- <LI>svc_domain - Virtual domains
- <LI>svc_acct_sm - Virtual domain mail aliasing (*depreciated*)
+ <LI>svc_domain - Domains
+ <LI>svc_acct_sm - <B>depreciated</B> (use svc_forward for new installations) Virtual domain mail aliasing.
<LI>svc_forward - mail forwarding
<LI>svc_www - Virtual domain website
<!-- <LI>svc_charge - One-time charges (Partially unimplemented)
--- /dev/null
+<%
+#<!-- $Id: quick-cust_pkg.cgi,v 1.1 2001-09-04 14:44:07 ivan Exp $ -->
+
+use strict;
+use vars qw( $cgi $custnum $pkgpart $error ); #@remove_pkgnums @pkgparts
+use CGI;
+use CGI::Carp qw(fatalsToBrowser);
+use FS::UID qw(cgisuidsetup);
+use FS::CGI qw(popurl);
+use FS::cust_pkg;
+
+$cgi = new CGI; # create form object
+&cgisuidsetup($cgi);
+$error = '';
+
+#untaint custnum
+$cgi->param('custnum') =~ /^(\d+)$/
+ or die 'illegal custnum '. $cgi->param('custnum');
+$custnum = $1;
+$cgi->param('pkgpart') =~ /^(\d+)$/
+ or die 'illegal pkgpart '. $cgi->param('pkgpart');
+$pkgpart = $1;
+
+my @cust_pkg = ();
+$error ||= FS::cust_pkg::order($custnum, [ $pkgpart ], [], \@cust_pkg, );
+
+if ($error) {
+ eidiot($error);
+} else {
+ print $cgi->redirect(popurl(3). "view/cust_pkg.cgi?". $cust_pkg[0]->pkgnum );
+}
+
+%>
+
<%
-#<!-- $Id: svc_acct.cgi,v 1.5 2001-08-21 10:27:11 ivan Exp $ -->
+#<!-- $Id: svc_acct.cgi,v 1.6 2001-09-04 14:44:06 ivan Exp $ -->
use strict;
use vars qw( $conf $cgi @shells $action $svcnum $svc_acct $pkgnum $svcpart
#domain
$domsvc = $svc_acct->domsvc || 0;
-if ( $part_svc->svc_acct__domsvc_flag eq "F" ) {
+if ( $part_svc->svc_acct__domsvc_flag eq 'F' ) {
print qq!<INPUT TYPE="hidden" NAME="domsvc" VALUE="$domsvc">!;
} else {
my @svc_domain = ();
+ if ( $part_svc->svc_acct__domsvc_flag eq 'D' ) {
+ my $svc_domain =
+ qsearchs('svc_domain', { 'svcnum' => $part_svc->svc_acct__domsvc } );
+ if ( $svc_domain ) {
+ push @svc_domain, $svc_domain;
+ } else {
+ warn "unknown svc_domain.svcnum for part_svc.svc_acct__domsvc: ".
+ $part_svc->svc_acct__domsvc;
+ }
+ }
my $cust_pkg = qsearchs('cust_pkg', { 'pkgnum' => $pkgnum } );
if ($cust_pkg) {
my @cust_svc =
<%
-#<!-- $Id: cust_main.cgi,v 1.8 2001-09-03 22:07:39 ivan Exp $ -->
+#<!-- $Id: cust_main.cgi,v 1.9 2001-09-04 14:44:07 ivan Exp $ -->
use strict;
use vars qw ( $cgi $query $custnum $cust_main $hashref $agent $referral
@agents = qsearch( 'agent', {} );
unless ( scalar(@agents) == 1 ) {
- $agent = qsearchs('agent',{
- 'agentnum' => $cust_main->agentnum
- } );
+ $agent = qsearchs('agent',{ 'agentnum' => $cust_main->agentnum } );
print '<TR><TD ALIGN="right">Agent</TD><TD BGCOLOR="#ffffff">',
$agent->agentnum, ": ", $agent->agent, '</TD></TR>';
+ } else {
+ $agent = $agents[0];
}
@referrals = qsearch( 'part_referral', {} );
unless ( scalar(@referrals) == 1 ) {
print '</TD></TR></TABLE>';
+print '<BR>'.
+ '<FORM ACTION="'.popurl(2).'edit/process/quick-cust_pkg.cgi" METHOD="POST">'.
+ qq!<INPUT TYPE="hidden" NAME="custnum" VALUE="$custnum">!.
+ '<SELECT NAME="pkgpart"><OPTION>';
+
+foreach my $type_pkgs ( qsearch('type_pkgs',{'typenum'=> $agent->typenum }) ) {
+ my $pkgpart = $type_pkgs->pkgpart;
+ my $part_pkg = qsearchs('part_pkg', { 'pkgpart' => $pkgpart } )
+ or do { warn "unknown type_pkgs.pkgpart $pkgpart"; next; };
+ print qq!<OPTION VALUE="$pkgpart">!. $part_pkg->pkg. ' - '.
+ $part_pkg->comment;
+}
+
+print '</SELECT><INPUT TYPE="submit" VALUE="Order Package"><BR>';
+
print qq!<BR><A NAME="cust_pkg">Packages</A> !,
# qq!<BR>Click on package number to view/edit package.!,
qq!( <A HREF="!, popurl(2), qq!edit/cust_pkg.cgi?$custnum">Order and cancel packages</A> (preserves services) )!,