allow non-integer minutes in CDR usage pools, #5738, see also #28308
[freeside.git] / FS / FS / part_pkg_usage.pm
1 package FS::part_pkg_usage;
2
3 use strict;
4 use base qw( FS::m2m_Common FS::Record );
5 use FS::Record qw( qsearch qsearchs );
6 use Scalar::Util qw(blessed);
7
8 =head1 NAME
9
10 FS::part_pkg_usage - Object methods for part_pkg_usage records
11
12 =head1 SYNOPSIS
13
14   use FS::part_pkg_usage;
15
16   $record = new FS::part_pkg_usage \%hash;
17   $record = new FS::part_pkg_usage { 'column' => 'value' };
18
19   $error = $record->insert;
20
21   $error = $new_record->replace($old_record);
22
23   $error = $record->delete;
24
25   $error = $record->check;
26
27 =head1 DESCRIPTION
28
29 An FS::part_pkg_usage object represents a stock of usage minutes (generally
30 for voice services) included in a package definition.  FS::part_pkg_usage 
31 inherits from FS::Record.  The following fields are currently supported:
32
33 =over 4
34
35 =item pkgusagepart - primary key
36
37 =item pkgpart - the package definition (L<FS::part_pkg>)
38
39 =item minutes - the number of minutes included per billing cycle
40
41 =item priority - the relative order in which to use this stock of minutes.
42
43 =item shared - 'Y' to allow these minutes to be shared with other packages
44 belonging to the same customer.  Otherwise, only usage allocated to this
45 package will use this stock of minutes.
46
47 =item rollover - 'Y' to allow unused minutes to carry over between billing
48 cycles.  Otherwise, the available minutes will reset to the value of the 
49 "minutes" field upon billing.
50
51 =item description - a text description of this stock of minutes
52
53 =back
54
55 =head1 METHODS
56
57 =over 4
58
59 =item new HASHREF
60
61 =item insert CLASSES
62
63 =item replace CLASSES
64
65 CLASSES can be an array or hash of usage classnums (see L<FS::usage_class>)
66 to link to this record.
67
68 =item delete
69
70 =cut
71
72 sub table { 'part_pkg_usage'; }
73
74 sub insert {
75   my $self = shift;
76   my $opt = ref($_[0]) eq 'HASH' ? shift : { @_ };
77
78   $self->SUPER::insert
79   || $self->process_m2m( 'link_table'   => 'part_pkg_usage_class',
80                          'target_table' => 'usage_class',
81                          'params'       => $opt,
82   );
83 }
84
85 sub replace {
86   my $self = shift;
87   my $old = ( blessed($_[0]) && $_[0]->isa('FS::Record') )
88               ? shift
89               : $self->replace_old;
90   my $opt = ref($_[0]) eq 'HASH' ? $_[0] : { @_ };
91   $self->SUPER::replace($old)
92   || $self->process_m2m( 'link_table'   => 'part_pkg_usage_class',
93                          'target_table' => 'usage_class',
94                          'params'       => $opt,
95   );
96 }
97
98 sub delete {
99   my $self = shift;
100   $self->process_m2m( 'link_table'   => 'part_pkg_usage_class',
101                       'target_table' => 'usage_class',
102                       'params'       => {},
103   ) || $self->SUPER::delete;
104 }
105
106 =item check
107
108 Checks all fields to make sure this is a valid example.  If there is
109 an error, returns the error, otherwise returns false.  Called by the insert
110 and replace methods.
111
112 =cut
113
114 sub check {
115   my $self = shift;
116
117   my $error = 
118     $self->ut_numbern('pkgusagepart')
119     || $self->ut_foreign_key('pkgpart', 'part_pkg', 'pkgpart')
120     || $self->ut_float('minutes')
121     || $self->ut_numbern('priority')
122     || $self->ut_flag('shared')
123     || $self->ut_flag('rollover')
124     || $self->ut_textn('description')
125   ;
126   return $error if $error;
127
128   $self->SUPER::check;
129 }
130
131 =item classnums
132
133 Returns the usage class numbers that are allowed to use minutes from this
134 pool.
135
136 =cut
137
138 sub classnums {
139   my $self = shift;
140   if (!$self->get('classnums')) {
141     my $classnums = [
142       map { $_->classnum }
143       qsearch('part_pkg_usage_class', { 'pkgusagepart' => $self->pkgusagepart })
144     ];
145     $self->set('classnums', $classnums);
146   }
147   @{ $self->get('classnums') };
148 }
149
150 =back
151
152 =head1 SEE ALSO
153
154 L<FS::Record>, schema.html from the base documentation.
155
156 =cut
157
158 1;
159