summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorivan <ivan>2001-09-01 20:11:07 +0000
committerivan <ivan>2001-09-01 20:11:07 +0000
commitcdd5aa1d86cd5b266e02bed58570c97c2d7698ba (patch)
treef83c2929f38cc9c334332059afe7afec338f6796
parentd70e3f97ae64081dc724c77e64d71f3747fdddf1 (diff)
cust_bill_pay and cust_credit_refund.
payments can apply to multiple invoices and refunds can apply to multiple credits.
-rw-r--r--FS/FS/cust_bill_pay.pm190
-rw-r--r--FS/FS/cust_credit_refund.pm175
-rw-r--r--FS/FS/cust_main.pm4
-rw-r--r--FS/FS/cust_pay.pm63
-rw-r--r--FS/FS/cust_refund.pm60
-rwxr-xr-xbin/fs-setup34
-rw-r--r--httemplate/docs/schema.html18
7 files changed, 505 insertions, 39 deletions
diff --git a/FS/FS/cust_bill_pay.pm b/FS/FS/cust_bill_pay.pm
new file mode 100644
index 000000000..045a9490b
--- /dev/null
+++ b/FS/FS/cust_bill_pay.pm
@@ -0,0 +1,190 @@
+package cust_bill_pay;
+
+use strict;
+use vars qw( @ISA );
+use FS::Record qw( qsearch qsearchs dbh );
+#use FS::cust_bill
+
+@ISA = qw( FS::Record );
+
+=head1 NAME
+
+FS::cust_bill_pay - Object methods for cust_bill_pay records
+
+=head1 SYNOPSIS
+
+ use FS::cust_bill_pay;
+
+ $record = new FS::cust_bill_pay \%hash;
+ $record = new FS::cust_bill_pay { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_bill_pay object represents the application of a payment to a
+specific invoice. FS::cust_bill_pay inherits from FS::Record. The following
+fields are currently supported:
+
+=over 4
+
+=item billpaynum - primary key (assigned automatically)
+
+=item invnum - Invoice (see L<FS::cust_bill>)
+
+=item paynum - Payment (see L<FS::cust_pay>)
+
+=item amount - Amount of the payment to apply to the specific invoice.
+
+=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+=cut
+
+sub table { 'cust_bill_pay'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+sub insert {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->check;
+ return $error if $error;
+
+ $error = $self->SUPER::insert;
+
+ my $cust_pay = qsearchs('cust_pay', { 'paynum' => $self->paynum } ) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "unknown cust_pay.paynum: ". $self->paynum;
+ };
+
+ my $pay_total = 0;
+ $pay_total += $_ foreach map { $_->amount }
+ qsearch('cust_bill_pay', { 'paynum' => $self->paynum } );
+
+ if ( $pay_total > $cust_pay->paid ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "total cust_bill_pay.amount $pay_total for paynum ". $self->paynum.
+ " greater than cust_pay.paid ". $cust_pay->paid;
+ }
+
+ my $cust_bill = qsearchs('cust_bill', { 'invnum' => $self->invnum } ) or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "unknown cust_bill.invnum: ". $self->invnum;
+ };
+
+ my $bill_total = 0;
+ $bill_total += foreach map { $_->amount }
+ qsearch('cust_bill_pay', { 'invnum' => $self->invnum } );
+# $bill_total += foreach map { $_->amount }
+# qsearch('cust_credit_bill', { 'invnum' => $self->invnum } );
+ if ( $bill_total > $cust_bill->charged ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "total cust_bill_pay.amount and cust_credit_bill.amount $bill_total".
+ "for invnum ". $self->invnum.
+ " greater than cust_bill.charged ". $cust_bill->charged;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+}
+
+=item delete
+
+Currently unimplemented (accounting reasons).
+
+=cut
+
+sub delete {
+ return "Can't (yet?) delete cust_bill_pay records!";
+}
+
+=item replace OLD_RECORD
+
+Currently unimplemented (accounting reasons).
+
+=cut
+
+sub replace {
+ return "Can't (yet?) modify cust_bill_pay records!";
+}
+
+=item check
+
+Checks all fields to make sure this is a valid payment. If there is an error,
+returns the error, otherwise returns false. Called by the insert method.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('billpaynum')
+ || $self->ut_number('invnum')
+ || $self->ut_numner('paynum')
+ || $self->ut_money('amount')
+ || $self->ut_numbern('_date')
+ ;
+ return $error if $error;
+
+ $self->_date(time) unless $self->_date;
+
+
+ ''; #no error
+}
+
+=back
+
+=head1 VERSION
+
+$Id: cust_bill_pay.pm,v 1.1 2001-09-01 20:11:07 ivan Exp $
+
+=head1 BUGS
+
+Delete and replace methods.
+
+cust_credit_bill isn't checked yet (uncomment around line 111)
+
+=head1 SEE ALSO
+
+L<FS::cust_pay>, L<FS::cust_bill>, L<FS::Record>, schema.html from the
+base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_credit_refund.pm b/FS/FS/cust_credit_refund.pm
new file mode 100644
index 000000000..f366eb147
--- /dev/null
+++ b/FS/FS/cust_credit_refund.pm
@@ -0,0 +1,175 @@
+package cust_credit_refund;
+
+use strict;
+use vars qw( @ISA );
+use FS::Record qw( qsearch qsearchs dbh );
+#use FS::UID qw(getotaker);
+#use FS::cust_credit
+
+@ISA = qw( FS::Record );
+
+=head1 NAME
+
+FS::cust_credit_refund - Object methods for cust_bill_pay records
+
+=head1 SYNOPSIS
+
+ use FS::cust_credit_refund;
+
+ $record = new FS::cust_credit_refund \%hash;
+ $record = new FS::cust_credit_refund { 'column' => 'value' };
+
+ $error = $record->insert;
+
+ $error = $new_record->replace($old_record);
+
+ $error = $record->delete;
+
+ $error = $record->check;
+
+=head1 DESCRIPTION
+
+An FS::cust_credit_refund represents the application of a refund to a specific
+credit. FS::cust_credit_refund inherits from FS::Record. The following fields
+are currently supported:
+
+=over 4
+
+=item creditrefundnum - primary key (assigned automatically)
+
+=item crednum - Credit (see L<FS::cust_credit>)
+
+=item refundnum - Refund (see L<FS::cust_refund>)
+
+=item amount - Amount of the refund to apply to the specific credit.
+
+=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
+L<Time::Local> and L<Date::Parse> for conversion functions.
+
+=back
+
+=head1 METHODS
+
+=over 4
+
+=item new HASHREF
+
+Creates a new record. To add the record to the database, see L<"insert">.
+
+sub table { 'cust_credit_refund'; }
+
+=item insert
+
+Adds this record to the database. If there is an error, returns the error,
+otherwise returns false.
+
+=cut
+
+sub insert {
+ my $self = shift;
+
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
+ my $error = $self->check;
+ return $error if $error;
+
+ $error = $self->SUPER::insert;
+
+ my $cust_refund =
+ qsearchs('cust_refund', { 'refundnum' => $self->refundnum } )
+ or do {
+ $dbh->rollback if $oldAutoCommit;
+ return "unknown cust_refund.refundnum: ". $self->refundnum
+ };
+
+ my $refund_total = 0;
+ $refund_total += $_ foreach map { $_->amount }
+ qsearch('cust_credit_refund', { 'refundnum' => $self->refundnum } );
+
+ if ( $refund_total > $cust_refund->refund ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "total cust_credit_refund.amount $refund_total for refundnum ".
+ $self->refundnum.
+ " greater than cust_refund.refund ". $cust_refund->refund;
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
+}
+
+=item delete
+
+Currently unimplemented (accounting reasons).
+
+=cut
+
+sub delete {
+ return "Can't (yet?) delete cust_credit_refund records!";
+}
+
+=item replace OLD_RECORD
+
+Currently unimplemented (accounting reasons).
+
+=cut
+
+sub replace {
+ return "Can't (yet?) modify cust_credit_refund records!";
+}
+
+=item check
+
+Checks all fields to make sure this is a valid payment. If there is an error,
+returns the error, otherwise returns false. Called by the insert method.
+
+=cut
+
+sub check {
+ my $self = shift;
+
+ my $error =
+ $self->ut_numbern('creditrefundnum')
+ || $self->ut_number('crednum')
+ || $self->ut_numner('refundnum')
+ || $self->ut_money('amount')
+ || $self->ut_numbern('_date')
+ ;
+ return $error if $error;
+
+ $self->_date(time) unless $self->_date;
+
+ return "unknown cust_credit.crednum: ". $self->crednum
+ unless qsearchs( 'cust_credit', { 'crednum' => $self->crednum } );
+
+ ''; #no error
+}
+
+=back
+
+=head1 VERSION
+
+$Id: cust_credit_refund.pm,v 1.1 2001-09-01 20:11:07 ivan Exp $
+
+=head1 BUGS
+
+Delete and replace methods.
+
+=head1 SEE ALSO
+
+L<FS::cust_credit>, L<FS::cust_refund>, L<FS::Record>, schema.html from the
+base documentation.
+
+=cut
+
+1;
+
diff --git a/FS/FS/cust_main.pm b/FS/FS/cust_main.pm
index 682b43d95..31f6d5e3e 100644
--- a/FS/FS/cust_main.pm
+++ b/FS/FS/cust_main.pm
@@ -1398,7 +1398,7 @@ sub rebuild_fuzzyfiles {
=head1 VERSION
-$Id: cust_main.pm,v 1.22 2001-08-28 14:34:14 ivan Exp $
+$Id: cust_main.pm,v 1.23 2001-09-01 20:11:07 ivan Exp $
=head1 BUGS
@@ -1415,8 +1415,6 @@ CyberCash v2 forces us to define some variables in package main.
There should probably be a configuration file with a list of allowed credit
card types.
-CyberCash is the only processor.
-
No multiple currency support (probably a larger project than just this module).
=head1 SEE ALSO
diff --git a/FS/FS/cust_pay.pm b/FS/FS/cust_pay.pm
index f0d945060..b1c35d76f 100644
--- a/FS/FS/cust_pay.pm
+++ b/FS/FS/cust_pay.pm
@@ -3,8 +3,9 @@ package FS::cust_pay;
use strict;
use vars qw( @ISA );
use Business::CreditCard;
-use FS::Record qw( qsearchs );
+use FS::Record qw( dbh );
use FS::cust_bill;
+use FS::cust_bill_pay;
@ISA = qw( FS::Record );
@@ -37,8 +38,6 @@ currently supported:
=item paynum - primary key (assigned automatically for new payments)
-=item invnum - Invoice (see L<FS::cust_bill>)
-
=item paid - Amount of this payment
=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
@@ -66,21 +65,55 @@ sub table { 'cust_pay'; }
=item insert
-Adds this payment to the databse, and updates the invoice (see
-L<FS::cust_bill>).
+Adds this payment to the database.
+
+For backwards-compatibility and convenience, if the additional field invnum
+is defined, an FS::cust_bill_pay record for the full amount of the payment
+will be created.
=cut
sub insert {
my $self = shift;
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
my $error = $self->check;
return $error if $error;
- my $old_cust_bill = qsearchs( 'cust_bill', { 'invnum' => $self->invnum } );
- return "Unknown invnum" unless $old_cust_bill;
+ $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ if ( $self->invnum ) {
+ my $cust_bill_pay = new FS::cust_bill_pay {
+ 'invnum' => $self->invnum,
+ 'paynum' => $self->paynum,
+ 'amount' => $self->paid,
+ '_date' => $self->_date,
+ };
+ $error = $cust_bill_pay->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
- $self->SUPER::insert;
}
=item delete
@@ -113,13 +146,11 @@ returns the error, otherwise returns false. Called by the insert method.
sub check {
my $self = shift;
- my $error;
-
- $error =
+ my $error =
$self->ut_numbern('paynum')
- || $self->ut_number('invnum')
|| $self->ut_money('paid')
|| $self->ut_numbern('_date')
+ || $self->ut_textn('paybatch')
;
return $error if $error;
@@ -147,9 +178,6 @@ sub check {
return $error if $error;
}
- $error = $self->ut_textn('paybatch');
- return $error if $error;
-
''; #no error
}
@@ -158,7 +186,7 @@ sub check {
=head1 VERSION
-$Id: cust_pay.pm,v 1.3 2001-04-09 23:05:15 ivan Exp $
+$Id: cust_pay.pm,v 1.4 2001-09-01 20:11:07 ivan Exp $
=head1 BUGS
@@ -166,7 +194,8 @@ Delete and replace methods.
=head1 SEE ALSO
-L<FS::Record>, L<FS::cust_bill>, schema.html from the base documentation.
+L<FS::cust_bill_pay>, L<FS::cust_bill>, L<FS::Record>, schema.html from the
+base documentation.
=cut
diff --git a/FS/FS/cust_refund.pm b/FS/FS/cust_refund.pm
index 729dc02b0..8e4ef0d4e 100644
--- a/FS/FS/cust_refund.pm
+++ b/FS/FS/cust_refund.pm
@@ -3,9 +3,10 @@ package FS::cust_refund;
use strict;
use vars qw( @ISA );
use Business::CreditCard;
-use FS::Record qw( qsearchs );
+use FS::Record qw( qsearchs dbh );
use FS::UID qw(getotaker);
use FS::cust_credit;
+use FS::cust_credit_refund;
@ISA = qw( FS::Record );
@@ -38,8 +39,6 @@ inherits from FS::Record. The following fields are currently supported:
=item refundnum - primary key (assigned automatically for new refunds)
-=item crednum - Credit (see L<FS::cust_credit>)
-
=item refund - Amount of the refund
=item _date - specified as a UNIX timestamp; see L<perlfunc/"time">. Also see
@@ -49,6 +48,8 @@ L<Time::Local> and L<Date::Parse> for conversion functions.
=item payinfo - card number, P.O.#, or comp issuer (4-8 lowercase alphanumerics; think username)
+=item paybatch - text field for tracking card processing
+
=item otaker - order taker (assigned automatically, see L<FS::UID>)
=back
@@ -67,22 +68,55 @@ sub table { 'cust_refund'; }
=item insert
-Adds this refund to the database, and updates the credit (see
-L<FS::cust_credit>).
+Adds this refund to the database.
+
+For backwards-compatibility and convenience, if the additional field crednum is
+defined, an FS::cust_credit_refund record for the full amount of the refund
+will be created.
=cut
sub insert {
my $self = shift;
+ local $SIG{HUP} = 'IGNORE';
+ local $SIG{INT} = 'IGNORE';
+ local $SIG{QUIT} = 'IGNORE';
+ local $SIG{TERM} = 'IGNORE';
+ local $SIG{TSTP} = 'IGNORE';
+ local $SIG{PIPE} = 'IGNORE';
+
+ my $oldAutoCommit = $FS::UID::AutoCommit;
+ local $FS::UID::AutoCommit = 0;
+ my $dbh = dbh;
+
my $error = $self->check;
return $error if $error;
- my $old_cust_credit =
- qsearchs( 'cust_credit', { 'crednum' => $self->crednum } );
- return "Unknown crednum" unless $old_cust_credit;
+ $error = $self->SUPER::insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+
+ if ( $self->crednum ) {
+ my $cust_credit_refund = new FS::cust_credit_refund {
+ 'cred' => $self->cred,
+ 'refundnum' => $self->refundnum,
+ 'amount' => $self->refund,
+ '_date' => $self->_date,
+ };
+ $error = $cust_bill_pay->insert;
+ if ( $error ) {
+ $dbh->rollback if $oldAutoCommit;
+ return $error;
+ }
+ }
+
+ $dbh->commit or die $dbh->errstr if $oldAutoCommit;
+
+ '';
- $self->SUPER::insert;
}
=item delete
@@ -115,13 +149,11 @@ returns the error, otherwise returns false. Called by the insert method.
sub check {
my $self = shift;
- my $error;
-
- $error =
+ my $error =
$self->ut_number('refundnum')
- || $self->ut_number('crednum')
|| $self->ut_money('amount')
|| $self->ut_numbern('_date')
+ || $self->ut_textn('paybatch')
;
return $error if $error;
@@ -157,7 +189,7 @@ sub check {
=head1 VERSION
-$Id: cust_refund.pm,v 1.3 2001-04-09 23:05:15 ivan Exp $
+$Id: cust_refund.pm,v 1.4 2001-09-01 20:11:07 ivan Exp $
=head1 BUGS
diff --git a/bin/fs-setup b/bin/fs-setup
index faa0e07f1..2cba840ef 100755
--- a/bin/fs-setup
+++ b/bin/fs-setup
@@ -1,6 +1,6 @@
#!/usr/bin/perl -Tw
#
-# $Id: fs-setup,v 1.44 2001-08-29 08:45:04 ivan Exp $
+# $Id: fs-setup,v 1.45 2001-09-01 20:11:07 ivan Exp $
#to delay loading dbdef until we're ready
BEGIN { $FS::Record::setup_hack = 1; }
@@ -398,7 +398,7 @@ sub tables_hash_hack {
'cust_pay' => {
'columns' => [
'paynum', 'int', '', '',
- 'invnum', 'int', '', '',
+ #now cust_bill_pay #'invnum', 'int', '', '',
'paid', @money_type,
'_date', @date_type,
'payby', 'char', '', 4, # CARD/BILL/COMP, should be index into
@@ -411,6 +411,19 @@ sub tables_hash_hack {
'index' => [ ['invnum'] ],
},
+ 'cust_bill_pay' => {
+ 'column' => [
+ 'billpaynum', 'int', '', '',
+ 'invnum', 'int', '', '',
+ 'paynum', 'int', '', '',
+ 'amount', @money_type,
+ '_date', @date_type
+ ],
+ 'primary_key' => 'billpaynum'
+ 'unique' => [ [] ],
+ 'index' => [ [ 'paynum', 'invnum' ] ],
+ },
+
'cust_pay_batch' => { #what's this used for again? list of customers
#in current CARD batch? (necessarily CARD?)
'columns' => [
@@ -456,7 +469,7 @@ sub tables_hash_hack {
'cust_refund' => {
'columns' => [
'refundnum', 'int', '', '',
- 'crednum', 'int', '', '',
+ #now cust_credit_refund #'crednum', 'int', '', '',
'_date', @date_type,
'refund', @money_type,
'otaker', 'varchar', '', 8,
@@ -464,12 +477,27 @@ sub tables_hash_hack {
'payby', 'char', '', 4, # CARD/BILL/COMP, should be index
# into payment type table.
'payinfo', 'varchar', 'NULL', 16, #see cust_main above
+ 'paybatch', 'varchar', 'NULL', $char_d,
],
'primary_key' => 'refundnum',
'unique' => [ [] ],
'index' => [ ['crednum'] ],
},
+ 'cust_credit_refund' => {
+ 'column' => [
+ 'creditrefundnum', 'int', '', '',
+ 'crednum', 'int', '', '',
+ 'refundnum', 'int', '', '',
+ 'amount', @money_type,
+ '_date', @date_type
+ ],
+ 'primary_key' => 'creditrefundnum'
+ 'unique' => [ [] ],
+ 'index' => [ [ 'crednum', 'refundnum' ] ],
+ },
+
+
'cust_svc' => {
'columns' => [
'svcnum', 'int', '', '',
diff --git a/httemplate/docs/schema.html b/httemplate/docs/schema.html
index 0da33a5c2..818547e1c 100644
--- a/httemplate/docs/schema.html
+++ b/httemplate/docs/schema.html
@@ -100,13 +100,20 @@
<li><a name="cust_pay" href="man/FS/cust_pay.html">cust_pay</a> - Payments. Money being transferred from a customer.
<ul>
<li>paynum - primary key
- <li>invnum - <a href="#cust_bill">invoice</a>
<li>paid - amount
<li>_date
<li>payby - CARD, BILL, or COMP
<li>payinfo - card number, P.O.#, or comp issuer
<li>paybatch - text field for tracking card processor batches
</ul>
+ <li><a name="cust_bill_pay" href="man/FS/cust_bill_pay.html">cust_bill_pay</a> - Applicaton of a payment to a specific invoice.
+ <ul>
+ <li>billpaynum
+ <li>invnum - <a href="#cust_bill">invoice</a>
+ <li>paynum - <a href="#cust_pay">payment</a>
+ <li>amount
+ <li>_date
+ </ul>
<li><a name="cust_pay_batch" href="man/FS/cust_pay_batch.html">cust_pay_batch</a> - Pending batch
<ul>
<li>trancode - 77 for charges
@@ -140,13 +147,20 @@
<li><a name="cust_refund" href="man/FS/cust_refund.html">cust_refund</a> - Refunds. The transfer of money to a customer; equivalent to a negative <a href="#cust_pay">cust_pay</a> record.
<ul>
<li>refundnum - primary key
- <li>crednum - <a href="#cust_credit">credit</a>
<li>refund - amount
<li>_date
<li>payby - CARD, BILL or COMP
<li>payinfo - card number, P.O.#, or comp issuer
<li>otaker - order taker
</ul>
+ <li><a name="cust_credit_refund" href="man/FS/cust_credit_refund.html">cust_credit_refund</a> - Applicaton of a refund to a specific credit.
+ <ul>
+ <li>creditrefundnum - primary key
+ <li>crednum - <a href="#cust_credit">credit</a>
+ <li>refundnum - <a href="#cust_refund">refund</a>
+ <li>amount
+ <li>_date
+ </ul>
<li><a name="cust_svc" href="man/FS/cust_svc.html">cust_svc</a> - Customer services
<ul>
<li>svcnum - primary key