per-agent disable_previous_balance, #15863
[freeside.git] / FS / FS / agent_type.pm
1 package FS::agent_type;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record qw( qsearch dbh );
6 use FS::m2m_Common;
7 use FS::agent;
8 use FS::type_pkgs;
9
10 @ISA = qw( FS::m2m_Common FS::Record );
11
12 =head1 NAME
13
14 FS::agent_type - Object methods for agent_type records
15
16 =head1 SYNOPSIS
17
18   use FS::agent_type;
19
20   $record = new FS::agent_type \%hash;
21   $record = new FS::agent_type { 'column' => 'value' };
22
23   $error = $record->insert;
24
25   $error = $new_record->replace($old_record);
26
27   $error = $record->delete;
28
29   $error = $record->check;
30
31   $hashref = $record->pkgpart_hashref;
32   #may purchase $pkgpart if $hashref->{$pkgpart};
33
34   @type_pkgs = $record->type_pkgs;
35
36   @pkgparts = $record->pkgpart;
37
38 =head1 DESCRIPTION
39
40 An FS::agent_type object represents an agent type.  Every agent (see
41 L<FS::agent>) has an agent type.  Agent types define which packages (see
42 L<FS::part_pkg>) may be purchased by customers (see L<FS::cust_main>), via 
43 FS::type_pkgs records (see L<FS::type_pkgs>).  FS::agent_type inherits from
44 FS::Record.  The following fields are currently supported:
45
46 =over 4
47
48 =item typenum - primary key (assigned automatically for new agent types)
49
50 =item atype - Text name of this agent type
51
52 =back
53
54 =head1 METHODS
55
56 =over 4
57
58 =item new HASHREF
59
60 Creates a new agent type.  To add the agent type to the database, see
61 L<"insert">.
62
63 =cut
64
65 sub table { 'agent_type'; }
66
67 =item insert
68
69 Adds this agent type to the database.  If there is an error, returns the error,
70 otherwise returns false.
71
72 =item delete
73
74 Deletes this agent type from the database.  Only agent types with no agents
75 can be deleted.  If there is an error, returns the error, otherwise returns
76 false.
77
78 =cut
79
80 sub delete {
81   my $self = shift;
82
83   return "Can't delete an agent_type with agents!"
84     if qsearch( 'agent', { 'typenum' => $self->typenum } );
85
86   $self->SUPER::delete;
87 }
88
89 =item replace OLD_RECORD
90
91 Replaces OLD_RECORD with this one in the database.  If there is an error,
92 returns the error, otherwise returns false.
93
94 =item check
95
96 Checks all fields to make sure this is a valid agent type.  If there is an
97 error, returns the error, otherwise returns false.  Called by the insert and
98 replace methods.
99
100 =cut
101
102 sub check {
103   my $self = shift;
104
105   $self->ut_numbern('typenum')
106   or $self->ut_text('atype')
107   or $self->SUPER::check;
108
109 }
110
111 =item pkgpart_hashref
112
113 Returns a hash reference.  The keys of the hash are pkgparts.  The value is
114 true iff this agent may purchase the specified package definition.  See
115 L<FS::part_pkg>.
116
117 =cut
118
119 sub pkgpart_hashref {
120   my $self = shift;
121   my %pkgpart;
122   $pkgpart{$_}++ foreach $self->pkgpart;
123   \%pkgpart;
124 }
125
126 =item type_pkgs
127
128 Returns all FS::type_pkgs objects (see L<FS::type_pkgs>) for this agent type.
129
130 =cut
131
132 sub type_pkgs {
133   my $self = shift;
134   qsearch('type_pkgs', { 'typenum' => $self->typenum } );
135 }
136
137 =item type_pkgs_enabled
138
139 Returns all FS::type_pkg objects (see L<FS::type_pkgs>) that link to enabled
140 package definitions (see L<FS::part_pkg>).
141
142 An additional strange feature is that the returned type_pkg objects also have
143 all fields of the associated part_pkg object.
144
145 =cut
146
147 sub type_pkgs_enabled {
148   my $self = shift;
149   qsearch({
150     'table'     => 'type_pkgs',
151     'addl_from' => 'JOIN part_pkg USING ( pkgpart )',
152     'hashref'   => { 'typenum' => $self->typenum },
153     'extra_sql' => " AND ( disabled = '' OR disabled IS NULL )".
154                    " ORDER BY pkg",
155   });
156 }
157
158 =item pkgpart
159
160 Returns the pkgpart of all package definitions (see L<FS::part_pkg>) for this
161 agent type.
162
163 =cut
164
165 sub pkgpart {
166   my $self = shift;
167
168   #map $_->pkgpart, $self->type_pkgs;
169
170   my $sql = 'SELECT pkgpart FROM type_pkgs WHERE typenum = ?';
171   my $sth = dbh->prepare($sql)    or die  dbh->errstr;
172   $sth->execute( $self->typenum ) or die $sth->errstr;
173   map $_->[0], @{ $sth->fetchall_arrayref };
174 }
175
176 =back
177
178 =head1 BUGS
179
180 type_pkgs_enabled should order itself by something (pkg?)
181
182 type_pkgs_enabled should populate something that caches for the part_pkg method
183 rather than add fields to this object, right?  In fact we need a "poop" object
184 framework that does that automatically for any joined search at some point....
185 right?
186
187 =head1 SEE ALSO
188
189 L<FS::Record>, L<FS::agent>, L<FS::type_pkgs>, L<FS::cust_main>,
190 L<FS::part_pkg>, schema.html from the base documentation.
191
192 =cut
193
194 1;
195