eliminate some false laziness in FS::Misc::send_email vs. msg_template/email.pm send_...
[freeside.git] / FS / FS / inventory_class.pm
1 package FS::inventory_class;
2 use base qw(FS::Record);
3
4 use strict;
5 use FS::Record qw( dbh ); # qsearch qsearchs dbh );
6
7 =head1 NAME
8
9 FS::inventory_class - Object methods for inventory_class records
10
11 =head1 SYNOPSIS
12
13   use FS::inventory_class;
14
15   $record = new FS::inventory_class \%hash;
16   $record = new FS::inventory_class { 'column' => 'value' };
17
18   $error = $record->insert;
19
20   $error = $new_record->replace($old_record);
21
22   $error = $record->delete;
23
24   $error = $record->check;
25
26 =head1 DESCRIPTION
27
28 An FS::inventory_class object represents a class of inventory, such as "DID 
29 numbers" or "physical equipment serials".  FS::inventory_class inherits from
30 FS::Record.  The following fields are currently supported:
31
32 =over 4
33
34 =item classnum - primary key
35
36 =item classname - Name of this class
37
38
39 =back
40
41 =head1 METHODS
42
43 =over 4
44
45 =item new HASHREF
46
47 Creates a new inventory class.  To add the class to the database, see
48 L<"insert">.
49
50 Note that this stores the hash reference, not a distinct copy of the hash it
51 points to.  You can ask the object for a copy with the I<hash> method.
52
53 =cut
54
55 # the new method can be inherited from FS::Record, if a table method is defined
56
57 sub table { 'inventory_class'; }
58
59 =item insert
60
61 Adds this record to the database.  If there is an error, returns the error,
62 otherwise returns false.
63
64 =cut
65
66 # the insert method can be inherited from FS::Record
67
68 =item delete
69
70 Delete this record from the database.
71
72 =cut
73
74 # the delete method can be inherited from FS::Record
75
76 =item replace OLD_RECORD
77
78 Replaces the OLD_RECORD with this one in the database.  If there is an error,
79 returns the error, otherwise returns false.
80
81 =cut
82
83 # the replace method can be inherited from FS::Record
84
85 =item check
86
87 Checks all fields to make sure this is a valid inventory class.  If there is
88 an error, returns the error, otherwise returns false.  Called by the insert
89 and replace methods.
90
91 =cut
92
93 # the check method should currently be supplied - FS::Record contains some
94 # data checking routines
95
96 sub check {
97   my $self = shift;
98
99   my $error = 
100     $self->ut_numbern('classnum')
101     || $self->ut_textn('classname')
102   ;
103   return $error if $error;
104
105   $self->SUPER::check;
106 }
107
108 =item num_avail 
109
110 Returns the number of available (unused/unallocated) inventory items of this
111 class (see L<FS::inventory_item>).
112
113 =cut
114
115 sub num_avail {
116   my( $self, $sql ) = @_;
117   $sql .= ' AND ' if length($sql);
118   $sql .= '( svcnum IS NULL OR svcnum = 0 )';
119   $self->num_sql($sql);
120 }
121
122 sub num_sql {
123   my( $self, $sql ) = @_;
124   $sql = "AND $sql" if length($sql);
125
126   my $agentnums_sql = $FS::CurrentUser::CurrentUser->agentnums_sql(
127     'null'  => 1,
128     'table' => 'inventory_item',
129   );
130
131   my $st = "SELECT COUNT(*) FROM inventory_item ".
132            " WHERE classnum = ? AND $agentnums_sql $sql";
133   my $sth = dbh->prepare($st)    or die  dbh->errstr. " preparing $st";
134   $sth->execute($self->classnum) or die $sth->errstr. " executing $st";
135   $sth->fetchrow_arrayref->[0];
136 }
137
138 =item num_used
139
140 Returns the number of used (allocated) inventory items of this class (see
141 L<FS::inventory_class>).
142
143 =cut
144
145 sub num_used {
146   my( $self, $sql ) = @_;
147   $sql .= ' AND ' if length($sql);
148   $sql .= 'svcnum IS NOT NULL AND svcnum > 0 ';
149   $self->num_sql($sql);
150 }
151
152 =item num_total
153
154 Returns the total number of inventory items of this class (see
155 L<FS::inventory_class>).
156
157 =cut
158
159 sub num_total {
160   my( $self, $sql ) = @_;
161   $self->num_sql($sql);
162 }
163
164 =back
165
166 =head1 CLASS METHODS
167
168 =over 4
169
170 =item searchcell_factory
171
172 =cut
173
174 sub countcell_factory {
175   my($class, %opt) = @_;
176
177   my $p = $opt{p};
178
179   my $sql = $opt{'agentnum'} ? 'agentnum = '.$opt{'agentnum'} : '';
180
181   use Tie::IxHash;
182   tie my %labels, 'Tie::IxHash',
183     'num_avail' => 'Available', #  <FONT SIZE="-1"><A HREF="eventually">(upload batch)</A></FONT>',
184     'num_used'  => 'In use', #'Used', #'Allocated',
185     'num_total' => 'Total',
186   ;
187
188   my %link = (
189     'num_avail' => ';avail=1',
190     'num_used'  => ';used=1',
191     'num_total' => '',
192   );
193
194   my %inv_action_link = (
195     'num_avail' => [ 'upload batch',
196                      $p.'misc/inventory_item-import.html?classnum=',
197                      'classnum'
198                    ],
199   );
200
201   sub {
202     my $inventory_class = shift;
203
204     my $link =
205       $p. 'search/inventory_item.html?'.
206       'classnum='. $inventory_class->classnum;
207     $link .= ';agentnum='.$opt{'agentnum'} if $opt{'agentnum'};
208
209     my %actioncol = ();
210     foreach ( keys %inv_action_link ) {
211       my($label, $baseurl, $method) =
212         @{ $inv_action_link{$_} };
213       my $url = $baseurl. $inventory_class->$method();
214       $actioncol{$_} =
215         '<FONT SIZE="-1">'.
216         '('.
217         '<A HREF="'.$url.'">'.
218         $label.
219         '</A>'.
220         ')'.
221         '</FONT>';
222     }
223
224     my %num = map { 
225       $_ => $inventory_class->$_($sql);
226     } keys %labels;
227
228     [ map {
229             [
230               {
231                 'data'  => '<B>'. $num{$_}. '</B>',
232                 'align' => 'right',
233               },
234               {
235                 'data'  => $labels{$_},
236                 'align' => 'left',
237                 'link'  => ( $num{$_}
238                                ? $link.$link{$_}
239                                : ''
240                            ),
241               },
242               { 'data'  => $actioncol{$_},
243                 'align'  => 'left',
244               },
245             ]
246           } keys %labels
247     ];
248   };
249 }
250
251 =back
252
253 =head1 BUGS
254
255 =head1 SEE ALSO
256
257 L<FS::inventory_item>, L<FS::Record>, schema.html from the base documentation.
258
259 =cut
260
261 1;
262