4 use base qw( FS::svc_External_Common );
5 use FS::Record qw( qsearch qsearchs dbh );
13 FS::svc_pbx - Object methods for svc_pbx records
19 $record = new FS::svc_pbx \%hash;
20 $record = new FS::svc_pbx { 'column' => 'value' };
22 $error = $record->insert;
24 $error = $new_record->replace($old_record);
26 $error = $record->delete;
28 $error = $record->check;
30 $error = $record->suspend;
32 $error = $record->unsuspend;
34 $error = $record->cancel;
38 An FS::svc_pbx object represents a PBX tenant. FS::svc_pbx inherits from
39 FS::svc_Common. The following fields are currently supported:
45 Primary key (assigned automatcially for new accounts)
49 (Unique?) number of external record
57 Maximum number of extensions
59 =item max_simultaneous
61 Maximum number of simultaneous users
71 Creates a new PBX tenant. To add the PBX tenant to the database, see
74 Note that this stores the hash reference, not a distinct copy of the hash it
75 points to. You can ask the object for a copy with the I<hash> method.
79 sub table { 'svc_pbx'; }
84 'name_plural' => 'PBXs',
85 'lcname_plural' => 'PBXs',
86 'longname_plural' => 'PBXs',
87 'sorts' => 'svcnum', # optional sort field (or arrayref of sort fields, main first)
88 'display_weight' => 70,
89 'cancel_weight' => 90,
93 'max_extensions' => 'Maximum number of User Extensions',
94 'max_simultaneous' => 'Maximum number of simultaneous users',
99 =item search_sql STRING
101 Class method which returns an SQL fragment to search for the given string.
106 #or something more complicated if necessary
108 # my($class, $string) = @_;
109 # $class->search_sql_field('title', $string);
114 Returns the title field for this PBX tenant.
125 Adds this record to the database. If there is an error, returns the error,
126 otherwise returns false.
128 The additional fields pkgnum and svcpart (see L<FS::cust_svc>) should be
129 defined. An FS::cust_svc record will be created and inserted.
137 $error = $self->SUPER::insert;
138 return $error if $error;
145 Delete this record from the database.
152 local $SIG{HUP} = 'IGNORE';
153 local $SIG{INT} = 'IGNORE';
154 local $SIG{QUIT} = 'IGNORE';
155 local $SIG{TERM} = 'IGNORE';
156 local $SIG{TSTP} = 'IGNORE';
157 local $SIG{PIPE} = 'IGNORE';
159 my $oldAutoCommit = $FS::UID::AutoCommit;
160 local $FS::UID::AutoCommit = 0;
163 foreach my $svc_phone (qsearch('svc_phone', { 'pbxsvc' => $self->svcnum } )) {
164 $svc_phone->pbxsvc('');
165 my $error = $svc_phone->replace;
167 $dbh->rollback if $oldAutoCommit;
172 foreach my $svc_acct (qsearch('svc_acct', { 'pbxsvc' => $self->svcnum } )) {
173 my $error = $svc_acct->delete;
175 $dbh->rollback if $oldAutoCommit;
180 my $error = $self->SUPER::delete;
182 $dbh->rollback if $oldAutoCommit;
186 $dbh->commit or die $dbh->errstr if $oldAutoCommit;
191 =item replace OLD_RECORD
193 Replaces the OLD_RECORD with this one in the database. If there is an error,
194 returns the error, otherwise returns false.
199 # my ( $new, $old ) = ( shift, shift );
202 # $error = $new->SUPER::replace($old);
203 # return $error if $error;
210 Called by the suspend method of FS::cust_pkg (see L<FS::cust_pkg>).
214 Called by the unsuspend method of FS::cust_pkg (see L<FS::cust_pkg>).
218 Called by the cancel method of FS::cust_pkg (see L<FS::cust_pkg>).
222 Checks all fields to make sure this is a valid PBX tenant. If there is
223 an error, returns the error, otherwise returns false. Called by the insert
231 my $x = $self->setfixed;
232 return $x unless ref($x);
239 sub _check_duplicate {
242 my $conf = new FS::Conf;
246 foreach my $field ('title', 'id') {
247 my $global_unique = $conf->config("global_unique-pbx_$field");
248 # can be 'disabled', 'enabled', or empty.
249 # if empty, check per exports; if not empty or disabled, check
251 next if $global_unique eq 'disabled';
252 my @dup = $self->find_duplicates(
253 ($global_unique ? 'global' : 'export') , $field
256 return "duplicate $field '".$self->getfield($field).
257 "': conflicts with svcnum ".$dup[0]->svcnum;
264 Returns a set of Call Detail Records (see L<FS::cdr>) associated with this
265 service. By default, "associated with" means that the "charged_party" field of
266 the CDR matches the "title" field of the service.
270 Accepts the following options:
272 =item for_update => 1: SELECT the CDRs "FOR UPDATE".
274 =item status => "" (or "done"): Return only CDRs with that processing status.
276 =item inbound => 1: No-op for svc_pbx CDR processing.
278 =item default_prefix => "XXX": Also accept the phone number of the service prepended
279 with the chosen prefix.
281 =item disable_src => 1: No-op for svc_pbx CDR processing.
283 =item by_svcnum => 1: Select CDRs where the svcnum field matches, instead of
284 title/charged_party. Normally this field is set after processing.
286 =item by_ip_addr => 'src' or 'dst': Select CDRs where the src_ip_addr or
287 dst_ip_addr field matches title. In this case, some special logic is applied
288 to allow title to indicate a range of IP addresses.
290 =item begin, end: Start and end of date range, as unix timestamp.
292 =item cdrtypenum: Only return CDRs with this type number.
299 my($self, %options) = @_;
303 my @fields = ( 'charged_party' );
304 $hash{'freesidestatus'} = $options{'status'}
305 if exists($options{'status'});
307 if ($options{'cdrtypenum'}) {
308 $hash{'cdrtypenum'} = $options{'cdrtypenum'};
311 my $for_update = $options{'for_update'} ? 'FOR UPDATE' : '';
313 if ( $options{'by_svcnum'} ) {
314 $hash{'svcnum'} = $self->svcnum;
316 elsif ( $options{'by_ip_addr'} =~ /^src|dst$/) {
317 my $field = 'cdr.'.$options{'by_ip_addr'}.'_ip_addr';
318 push @where, FS::cdr->ip_addr_sql($field, $self->title);
322 my $title = $self->title;
324 my $prefix = $options{'default_prefix'};
326 my @orwhere = map " $_ = '$title' ", @fields;
327 push @orwhere, map " $_ = '$prefix$title' ", @fields
329 if ( $prefix =~ /^\+(\d+)$/ ) {
330 push @orwhere, map " $_ = '$1$title' ", @fields
333 push @where, ' ( '. join(' OR ', @orwhere ). ' ) ';
336 if ( $options{'begin'} ) {
337 push @where, 'startdate >= '. $options{'begin'};
339 if ( $options{'end'} ) {
340 push @where, 'startdate < '. $options{'end'};
343 my $extra_sql = ( keys(%hash) ? ' AND ' : ' WHERE ' ). join(' AND ', @where )
350 'extra_sql' => $extra_sql,
351 'order_by' => "ORDER BY startdate $for_update",
363 L<FS::svc_Common>, L<FS::Record>, L<FS::cust_svc>, L<FS::part_svc>,
364 L<FS::cust_pkg>, schema.html from the base documentation.