[freeside-commits] freeside/FS/FS cdr.pm, 1.1, 1.2 Schema.pm, 1.13,
1.14 svc_acct.pm, 1.191, 1.192 cdr_upstream_rate.pm, NONE,
1.1 cust_svc.pm, 1.62, 1.63 rate_detail.pm, 1.4,
1.5 cust_main.pm, 1.208, 1.209 Conf.pm, 1.149, 1.150
Ivan,,,
ivan at wavetail.420.am
Mon Mar 20 11:13:28 PST 2006
Update of /home/cvs/cvsroot/freeside/FS/FS
In directory wavetail:/tmp/cvs-serv20016/FS/FS
Modified Files:
cdr.pm Schema.pm svc_acct.pm cust_svc.pm rate_detail.pm
cust_main.pm Conf.pm
Added Files:
cdr_upstream_rate.pm
Log Message:
add price plan to bill on internal or external CDRs directly, add option to export CDRs to a per-customer downstream file
Index: Conf.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Conf.pm,v
retrieving revision 1.149
retrieving revision 1.150
diff -u -d -r1.149 -r1.150
--- Conf.pm 22 Feb 2006 13:07:47 -0000 1.149
+++ Conf.pm 20 Mar 2006 19:13:26 -0000 1.150
@@ -1681,6 +1681,20 @@
'type' => 'text',
},
+ {
+ 'key' => 'echeck-nonus',
+ 'section' => 'billing',
+ 'description' => 'Disable ABA-format account checking for Electronic Check payment info',
+ 'type' => 'checkbox',
+ },
+
+ {
+ 'key' => 'voip-cust_cdr_spools',
+ 'section' => '',
+ 'description' => 'Enable the per-customer option for individual CDR spools.',
+ 'type' => 'checkbox',
+ },
+
);
1;
Index: cust_svc.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_svc.pm,v
retrieving revision 1.62
retrieving revision 1.63
diff -u -d -r1.62 -r1.63
--- cust_svc.pm 30 Dec 2005 02:41:22 -0000 1.62
+++ cust_svc.pm 20 Mar 2006 19:13:26 -0000 1.63
@@ -16,6 +16,7 @@
use FS::svc_external;
use FS::domain_record;
use FS::part_export;
+use FS::cdr;
@ISA = qw( FS::Record );
@@ -570,6 +571,50 @@
}
+=item get_cdrs_for_update
+
+Returns (and SELECTs "FOR UPDATE") all unprocessed (freesidestatus NULL) CDR
+objects (see L<FS::cdr>) associated with this service.
+
+Currently CDRs are associated with svc_acct services via a DID in the
+username. This part is rather tenative and still subject to change...
+
+=cut
+
+sub get_cdrs_for_update {
+ my($self, %options) = @_;
+
+ my $default_prefix = $options{'default_prefix'};
+
+ #Currently CDRs are associated with svc_acct services via a DID in the
+ #username. This part is rather tenative and still subject to change...
+ #return () unless $self->svc_x->isa('FS::svc_acct');
+ return () unless $self->part_svc->svcdb eq 'svc_acct';
+ my $number = $self->svc_x->username;
+
+ my @cdrs =
+ qsearch(
+ 'table' => 'cdr',
+ 'hashref' => { 'freesidestatus' => '',
+ 'charged_party' => $number
+ },
+ 'extra_sql' => 'FOR UPDATE',
+ );
+
+ if ( length($default_prefix) ) {
+ push @cdrs,
+ qsearch(
+ 'table' => 'cdr',
+ 'hashref' => { 'freesidestatus' => '',
+ 'charged_party' => "$default_prefix$number",
+ },
+ 'extra_sql' => 'FOR UPDATE',
+ );
+ }
+
+ @cdrs;
+}
+
=item pkg_svc
Returns the pkg_svc record for for this service, if applicable.
Index: rate_detail.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/rate_detail.pm,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- rate_detail.pm 18 Feb 2006 02:11:44 -0000 1.4
+++ rate_detail.pm 20 Mar 2006 19:13:26 -0000 1.5
@@ -114,7 +114,11 @@
|| $self->ut_foreign_keyn('orig_regionnum', 'rate_region', 'regionnum' )
|| $self->ut_foreign_key('dest_regionnum', 'rate_region', 'regionnum' )
|| $self->ut_number('min_included')
- || $self->ut_money('min_charge')
+
+ #|| $self->ut_money('min_charge')
+ #good enough for now...
+ || $self->ut_float('min_charge')
+
|| $self->ut_number('sec_granularity')
;
return $error if $error;
@@ -122,6 +126,30 @@
$self->SUPER::check;
}
+=item orig_region
+
+Returns the origination region (see L<FS::rate_region>) associated with this
+call plan rate.
+
+=cut
+
+sub orig_region {
+ my $self = shift;
+ qsearchs('rate_region', { 'regionnum' => $self->orig_regionnum } );
+}
+
+=item dest_region
+
+Returns the destination region (see L<FS::rate_region>) associated with this
+call plan rate.
+
+=cut
+
+sub dest_region {
+ my $self = shift;
+ qsearchs('rate_region', { 'regionnum' => $self->dest_regionnum } );
+}
+
=back
=head1 BUGS
Index: svc_acct.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/svc_acct.pm,v
retrieving revision 1.191
retrieving revision 1.192
diff -u -d -r1.191 -r1.192
--- svc_acct.pm 7 Feb 2006 13:49:44 -0000 1.191
+++ svc_acct.pm 20 Mar 2006 19:13:26 -0000 1.192
@@ -20,6 +20,7 @@
use FS::UID qw( datasrc );
use FS::Conf;
use FS::Record qw( qsearch qsearchs fields dbh dbdef );
+use FS::Msgcat qw(gettext);
use FS::svc_Common;
use FS::cust_svc;
use FS::part_svc;
@@ -31,9 +32,9 @@
use FS::radius_usergroup;
use FS::export_svc;
use FS::part_export;
-use FS::Msgcat qw(gettext);
use FS::svc_forward;
use FS::svc_www;
+use FS::cdr;
@ISA = qw( FS::svc_Common );
@@ -1344,6 +1345,67 @@
$self->cust_svc->get_session_history(@_);
}
+=item get_cdrs TIMESTAMP_START TIMESTAMP_END [ 'OPTION' => 'VALUE ... ]
+
+=cut
+
+sub get_cdrs {
+ my($self, $start, $end, %opt ) = @_;
+
+ my $did = $self->username; #yup
+
+ my $prefix = $opt{'default_prefix'}; #convergent.au '+61'
+
+ my $for_update = $opt{'for_update'} ? 'FOR UPDATE' : '';
+
+ #SELECT $for_update * FROM cdr
+ # WHERE calldate >= $start #need a conversion
+ # AND calldate < $end #ditto
+ # AND ( charged_party = "$did"
+ # OR charged_party = "$prefix$did" #if length($prefix);
+ # OR ( ( charged_party IS NULL OR charged_party = '' )
+ # AND
+ # ( src = "$did" OR src = "$prefix$did" ) # if length($prefix)
+ # )
+ # )
+ # AND ( freesidestatus IS NULL OR freesidestatus = '' )
+
+ my $charged_or_src;
+ if ( length($prefix) ) {
+ $charged_or_src =
+ " AND ( charged_party = '$did'
+ OR charged_party = '$prefix$did'
+ OR ( ( charged_party IS NULL OR charged_party = '' )
+ AND
+ ( src = '$did' OR src = '$prefix$did' )
+ )
+ )
+ ";
+ } else {
+ $charged_or_src =
+ " AND ( charged_party = '$did'
+ OR ( ( charged_party IS NULL OR charged_party = '' )
+ AND
+ src = '$did'
+ )
+ )
+ ";
+
+ }
+
+ qsearch(
+ 'select' => "$for_update *",
+ 'table' => 'cdr',
+ 'hashref' => {
+ #( freesidestatus IS NULL OR freesidestatus = '' )
+ 'freesidestatus' => '',
+ },
+ 'extra_sql' => $charged_or_src,
+
+ );
+
+}
+
=item radius_groups
Returns all RADIUS groups for this account (see L<FS::radius_usergroup>).
Index: cdr.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cdr.pm,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -d -r1.1 -r1.2
--- cdr.pm 18 Feb 2006 11:14:19 -0000 1.1
+++ cdr.pm 20 Mar 2006 19:13:26 -0000 1.2
@@ -3,11 +3,13 @@
use strict;
use vars qw( @ISA );
use Date::Parse;
+use Date::Format;
use FS::UID qw( dbh );
use FS::Record qw( qsearch qsearchs );
use FS::cdr_type;
use FS::cdr_calltype;
use FS::cdr_carrier;
+use FS::cdr_upstream_rate;
@ISA = qw(FS::Record);
@@ -99,6 +101,8 @@
=item upstream_rateplanid - Upstream rate plan ID
+=item rated_price - Rated (or re-rated) price
+
=item distance - km (need units field?)
=item islocal - Local - 1, Non Local = 0
@@ -121,7 +125,7 @@
=item svcnum - Link to customer service (see L<FS::cust_svc>)
-=item freesidestatus - NULL, done, skipped, pushed_downstream (or something)
+=item freesidestatus - NULL, done (or something)
=back
@@ -241,7 +245,184 @@
$self->SUPER::check;
}
-my %formats = (
+=item set_status_and_rated_price STATUS [ RATED_PRICE ]
+
+Sets the status to the provided string. If there is an error, returns the
+error, otherwise returns false.
+
+=cut
+
+sub set_status_and_rated_price {
+ my($self, $status, $rated_price) = @_;
+ $self->status($status);
+ $self->rated_price($rated_price);
+ $self->replace();
+}
+
+=item calldate_unix
+
+Parses the calldate in SQL string format and returns a UNIX timestamp.
+
+=cut
+
+sub calldate_unix {
+ str2time(shift->calldate);
+}
+
+=item cdr_carrier
+
+Returns the FS::cdr_carrier object associated with this CDR, or false if no
+carrierid is defined.
+
+=cut
+
+my %carrier_cache = ();
+
+sub cdr_carrier {
+ my $self = shift;
+ return '' unless $self->carrierid;
+ $carrier_cache{$self->carrierid} ||=
+ qsearchs('cdr_carrier', { 'carrierid' => $self->carrierid } );
+}
+
+=item carriername
+
+Returns the carrier name (see L<FS::cdr_carrier>), or the empty string if
+no FS::cdr_carrier object is assocated with this CDR.
+
+=cut
+
+sub carriername {
+ my $self = shift;
+ my $cdr_carrier = $self->cdr_carrier;
+ $cdr_carrier ? $cdr_carrier->carriername : '';
+}
+
+=item cdr_calltype
+
+Returns the FS::cdr_calltype object associated with this CDR, or false if no
+calltypenum is defined.
+
+=cut
+
+my %calltype_cache = ();
+
+sub cdr_calltype {
+ my $self = shift;
+ return '' unless $self->calltypenum;
+ $calltype_cache{$self->calltypenum} ||=
+ qsearchs('cdr_calltype', { 'calltypenum' => $self->calltypenum } );
+}
+
+=item calltypename
+
+Returns the call type name (see L<FS::cdr_calltype>), or the empty string if
+no FS::cdr_calltype object is assocated with this CDR.
+
+=cut
+
+sub calltypename {
+ my $self = shift;
+ my $cdr_calltype = $self->cdr_calltype;
+ $cdr_calltype ? $cdr_calltype->calltypename : '';
+}
+
+=item cdr_upstream_rate
+
+Returns the upstream rate mapping (see L<FS::cdr_upstream_rate>), or the empty
+string if no FS::cdr_upstream_rate object is associated with this CDR.
+
+=cut
+
+sub cdr_upstream_rate {
+ my $self = shift;
+ return '' unless $self->upstream_rateid;
+ qsearchs('cdr_upstream_rate', { 'upstream_rateid' => $self->upstream_rateid })
+ or '';
+}
+
+=item _convergent_format COLUMN [ COUNTRYCODE ]
+
+Returns the number in COLUMN formatted as follows:
+
+If the country code does not match COUNTRYCODE (default "61"), it is returned
+unchanged.
+
+If the country code does match COUNTRYCODE (default "61"), it is removed. In
+addiiton, "0" is prepended unless the number starts with 13, 18 or 19. (???)
+
+=cut
+
+sub _convergent_format {
+ my( $self, $field ) = ( shift, shift );
+ my $countrycode = scalar(@_) ? shift : '61'; #+61 = australia
+ #my $number = $self->$field();
+ my $number = $self->get($field);
+ #if ( $number =~ s/^(\+|011)$countrycode// ) {
+ if ( $number =~ s/^\+$countrycode// ) {
+ $number = "0$number"
+ unless $number =~ /^1[389]/; #???
+ }
+ $number;
+}
+
+=item downstream_csv [ OPTION => VALUE, ... ]
+
+=cut
+
+my %export_formats = (
+ 'convergent' => [
+ 'carriername', #CARRIER
+ sub { shift->_convergent_format('src') }, #SERVICE_NUMBER
+ sub { shift->_convergent_format('charged_party') }, #CHARGED_NUMBER
+ sub { time2str('%Y-%m-%d', shift->calldate_unix ) }, #DATE
+ sub { time2str('%T', shift->calldate_unix ) }, #TIME
+ 'billsec', #'duration', #DURATION
+ sub { shift->_convergent_format('dst') }, #NUMBER_DIALED
+ '', #XXX add (from prefixes in most recent email) #FROM_DESC
+ '', #XXX add (from prefixes in most recent email) #TO_DESC
+ 'calltypename', #CLASS_CODE
+ 'rated_price', #PRICE
+ sub { shift->rated_price ? 'Y' : 'N' }, #RATED
+ '', #OTHER_INFO
+ ],
+);
+
+sub downstream_csv {
+ my( $self, %opt ) = @_;
+
+ my $format = $opt{'format'}; # 'convergent';
+ return "Unknown format $format" unless exists $export_formats{$format};
+
+ eval "use Text::CSV_XS;";
+ die $@ if $@;
+ my $csv = new Text::CSV_XS;
+
+ my @columns =
+ map {
+ ref($_) ? &{$_}($self) : $self->$_();
+ }
+ @{ $export_formats{$format} };
+
+ my $status = $csv->combine(@columns);
+ die "FS::CDR: error combining ". $csv->error_input(). "into downstream CSV"
+ unless $status;
+
+ $csv->string;
+
+}
+
+=back
+
+=head1 CLASS METHODS
+
+=over 4
+
+=item batch_import
+
+=cut
+
+my %import_formats = (
'asterisk' => [
'accountcode',
'src',
@@ -264,14 +445,15 @@
],
'unitel' => [
'uniqueid',
- 'cdr_type',
- 'calldate', # XXX may need massaging
- 'billsec', #XXX duration and billsec?
- # sub { $_[0]->billsec( $_[1] );
- # $_[0]->duration( $_[1] );
- # },
+ #'cdr_type',
+ 'cdrtypenum',
+ 'calldate', # may need massaging? huh maybe not...
+ #'billsec', #XXX duration and billsec?
+ sub { $_[0]->billsec( $_[1] );
+ $_[0]->duration( $_[1] );
+ },
'src',
- 'dst',
+ 'dst', # XXX needs to have "+61" prepended unless /^\+/ ???
'charged_party',
'upstream_currency',
'upstream_price',
@@ -279,8 +461,8 @@
'distance',
'islocal',
'calltypenum',
- 'startdate', # XXX will definitely need massaging
- 'enddate', # XXX same
+ 'startdate', #XXX needs massaging
+ 'enddate', #XXX same
'description',
'quantity',
'carrierid',
@@ -294,7 +476,7 @@
my $fh = $param->{filehandle};
my $format = $param->{format};
- return "Unknown format $format" unless exists $formats{$format};
+ return "Unknown format $format" unless exists $import_formats{$format};
eval "use Text::CSV_XS;";
die $@ if $@;
@@ -339,7 +521,7 @@
}
}
- @{ $formats{$format} }
+ @{ $import_formats{$format} }
;
my $cdr = new FS::cdr ( \%cdr );
--- NEW FILE: cdr_upstream_rate.pm ---
package FS::cdr_upstream_rate;
use strict;
use vars qw( @ISA );
use FS::Record qw( qsearch qsearchs );
use FS::rate_detail;
@ISA = qw(FS::Record);
=head1 NAME
FS::cdr_upstream_rate - Object methods for cdr_upstream_rate records
=head1 SYNOPSIS
use FS::cdr_upstream_rate;
$record = new FS::cdr_upstream_rate \%hash;
$record = new FS::cdr_upstream_rate { 'column' => 'value' };
$error = $record->insert;
$error = $new_record->replace($old_record);
$error = $record->delete;
$error = $record->check;
=head1 DESCRIPTION
An FS::cdr_upstream_rate object represents an upstream rate mapping to
internal rate detail (see L<FS::rate_detail>). FS::cdr_upstream_rate inherits
from FS::Record. The following fields are currently supported:
=over 4
=item upstreamratenum - primary key
=item upstream_rateid - CDR upstream Rate ID (cdr.upstream_rateid - see L<FS::cdr>)
=item ratedetailnum - Rate detail - see L<FS::rate_detail>
=back
=head1 METHODS
=over 4
=item new HASHREF
Creates a new upstream rate mapping. To add the upstream rate to the database,
see L<"insert">.
Note that this stores the hash reference, not a distinct copy of the hash it
points to. You can ask the object for a copy with the I<hash> method.
=cut
# the new method can be inherited from FS::Record, if a table method is defined
sub table { 'cdr_upstream_rate'; }
=item insert
Adds this record to the database. If there is an error, returns the error,
otherwise returns false.
=cut
# the insert method can be inherited from FS::Record
=item delete
Delete this record from the database.
=cut
# the delete method can be inherited from FS::Record
=item replace OLD_RECORD
Replaces the OLD_RECORD with this one in the database. If there is an error,
returns the error, otherwise returns false.
=cut
# the replace method can be inherited from FS::Record
=item check
Checks all fields to make sure this is a valid upstream rate. If there is
an error, returns the error, otherwise returns false. Called by the insert
and replace methods.
=cut
# the check method should currently be supplied - FS::Record contains some
# data checking routines
sub check {
my $self = shift;
my $error =
$self->ut_numbern('upstreamratenum')
#|| $self->ut_number('upstream_rateid')
|| $self->ut_alpha('upstream_rateid')
#|| $self->ut_text('upstream_rateid')
|| $self->ut_foreign_key('ratedetailnum', 'rate_detail', 'ratedetailnum' )
;
return $error if $error;
$self->SUPER::check;
}
=item rate_detail
Returns the internal rate detail object for this upstream rate (see
L<FS::rate_detail>).
=cut
sub rate_detail {
my $self = shift;
qsearchs('rate_detail', { 'ratedetailnum' => $self->ratedetailnum } );
}
=back
=head1 BUGS
=head1 SEE ALSO
L<FS::Record>, schema.html from the base documentation.
=cut
1;
Index: cust_main.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/cust_main.pm,v
retrieving revision 1.208
retrieving revision 1.209
diff -u -d -r1.208 -r1.209
--- cust_main.pm 18 Feb 2006 11:14:19 -0000 1.208
+++ cust_main.pm 20 Mar 2006 19:13:26 -0000 1.209
@@ -284,6 +284,8 @@
=item referral_custnum - referring customer number
+=item spool_cdr - Enable individual CDR spooling, empty or `Y'
+
=back
=head1 METHODS
@@ -1257,7 +1259,11 @@
my $payinfo = $self->payinfo;
$payinfo =~ s/[^\d\@]//g;
- $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account at aba';
+ if ( $conf->exists('echeck-nonus') ) {
+ $payinfo =~ /^(\d+)\@(\d+)$/ or return 'invalid echeck account at aba';
+ } else {
+ $payinfo =~ /^(\d+)\@(\d{9})$/ or return 'invalid echeck account at aba';
+ }
$payinfo = "$1\@$2";
$self->payinfo($payinfo);
$self->paycvv('') if $self->dbdef_table->column('paycvv');
@@ -1336,8 +1342,10 @@
$self->payname($1);
}
- $self->tax =~ /^(Y?)$/ or return "Illegal tax: ". $self->tax;
- $self->tax($1);
+ foreach my $flag (qw( tax spool_cdr )) {
+ $self->$flag() =~ /^(Y?)$/ or return "Illegal $flag: ". $self->$flag();
+ $self->$flag($1);
+ }
$self->otaker(getotaker) unless $self->otaker;
@@ -1640,6 +1648,7 @@
my( $total_setup, $total_recur ) = ( 0, 0 );
my %tax;
+ my @precommit_hooks = ();
foreach my $cust_pkg (
qsearch('cust_pkg', { 'custnum' => $self->custnum } )
@@ -1673,7 +1682,7 @@
$setup = eval { $cust_pkg->calc_setup( $time ) };
if ( $@ ) {
$dbh->rollback if $oldAutoCommit;
- return $@;
+ return "$@ running calc_setup for $cust_pkg\n";
}
$cust_pkg->setfield('setup', $time) unless $cust_pkg->setup;
@@ -1695,10 +1704,13 @@
# XXX shared with $recur_prog
$sdate = $cust_pkg->bill || $cust_pkg->setup || $time;
- $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details ) };
+ #over two params! lets at least switch to a hashref for the rest...
+ my %param = ( 'precommit_hooks' => \@precommit_hooks, );
+
+ $recur = eval { $cust_pkg->calc_recur( \$sdate, \@details, \%param ) };
if ( $@ ) {
$dbh->rollback if $oldAutoCommit;
- return $@;
+ return "$@ running calc_recur for $cust_pkg\n";
}
#change this bit to use Date::Manip? CAREFUL with timezones (see
@@ -1970,6 +1982,16 @@
$dbh->rollback if $oldAutoCommit;
return "can't update charged for invoice #$invnum: $error";
}
+
+ foreach my $hook ( @precommit_hooks ) {
+ eval {
+ &{$hook}; #($self) ?
+ };
+ if ( $@ ) {
+ $dbh->rollback if $oldAutoCommit;
+ return "$@ running precommit hook $hook\n";
+ }
+ }
$dbh->commit or die $dbh->errstr if $oldAutoCommit;
''; #no error
Index: Schema.pm
===================================================================
RCS file: /home/cvs/cvsroot/freeside/FS/FS/Schema.pm,v
retrieving revision 1.13
retrieving revision 1.14
diff -u -d -r1.13 -r1.14
--- Schema.pm 8 Mar 2006 10:05:00 -0000 1.13
+++ Schema.pm 20 Mar 2006 19:13:26 -0000 1.14
@@ -437,6 +437,7 @@
'refnum', 'int', '', '', '', '',
'referral_custnum', 'int', 'NULL', '', '', '',
'comments', 'text', 'NULL', '', '', '',
+ 'spool_cdr','char', 'NULL', 1, '', '',
],
'primary_key' => 'custnum',
'unique' => [],
@@ -1146,7 +1147,8 @@
'orig_regionnum', 'int', 'NULL', '', '', '',
'dest_regionnum', 'int', '', '', '', '',
'min_included', 'int', '', '', '', '',
- 'min_charge', @money_type, '', '',
+ #'min_charge', @money_type, '', '',
+ 'min_charge', 'decimal', '', '10,5', '', '',
'sec_granularity', 'int', '', '', '', '',
#time period (link to table of periods)?
],
@@ -1416,14 +1418,14 @@
'index' => [],
},
- #map upstream rateid (XXX or rateplanid?) to ours...
- 'cdr_upstream_rate' => { # XXX or 'cdr_upstream_rateplan' ??
+ #map upstream rateid to ours...
+ 'cdr_upstream_rate' => {
'columns' => [
- # XXX or 'upstream_rateplanid' ??
- 'upstream_rateid', 'int', 'NULL', '', '', '',
+ 'upstreamratenum', 'serial', '', '', '', '',
+ 'upstream_rateid', 'varchar', '', $char_d, '', '',
'ratedetailnum', 'int', 'NULL', '', '', '',
],
- 'primary_key' => '', #XXX need a primary key
+ 'primary_key' => 'upstreamratenum', #XXX need a primary key
'unique' => [ [ 'upstream_rateid' ] ], #unless we add another field, yeah
'index' => [],
},
More information about the freeside-commits
mailing list