RT# 77332 - Fixed error where all packages updated with new next bill date, instead...
[freeside.git] / FS / FS / part_virtual_field.pm
1 package FS::part_virtual_field;
2
3 use strict;
4 use vars qw( @ISA );
5 use FS::Record;
6 use FS::Schema qw( dbdef );
7 use CGI qw(escapeHTML);
8
9 @ISA = qw( FS::Record );
10
11 =head1 NAME
12
13 FS::part_virtual_field - Object methods for part_virtual_field records
14
15 =head1 SYNOPSIS
16
17   use FS::part_virtual_field;
18
19   $record = new FS::part_virtual_field \%hash;
20   $record = new FS::part_virtual_field { 'column' => 'value' };
21
22   $error = $record->insert;
23
24   $error = $new_record->replace($old_record);
25
26   $error = $record->delete;
27
28   $error = $record->check;
29
30 =head1 DESCRIPTION
31
32 An FS::part_virtual_field object represents the definition of a custom field 
33 (see the BACKGROUND section).  FS::part_virtual_field contains the name and 
34 base table of the field. 
35
36 FS::part_virtual_field inherits from FS::Record.  The following fields are 
37 currently supported:
38
39 =over 2
40
41 =item vfieldpart - primary key (assigned automatically)
42
43 =item name - name of the field
44
45 =item dbtable - table for which this virtual field is defined
46
47 =item length - expected length of the value (UI hint)
48
49 =item label - descriptive label for the field (UI hint)
50
51 =back
52
53 =head1 METHODS
54
55 =over 4
56
57 =item new HASHREF
58
59 Create a new record.  To add the record to the database, see "insert".
60
61 =cut
62
63 sub table { 'part_virtual_field'; }
64 sub virtual_fields { () }
65
66 =item widget UI_TYPE MODE [ VALUE ]
67
68 Generates UI code for a widget suitable for editing/viewing the field, based on 
69 list_source and length.  
70
71 The only UI_TYPE currently supported is 'HTML', and possible MODEs are 'view'
72 and 'edit'.
73
74 In HTML, all widgets are assumed to be table rows.  View widgets look like
75 <TR><TD ALIGN="right">Label</TD><TD BGCOLOR="#ffffff">Value</TD></TR>
76
77 (Most of the display style stuff, such as the colors, should probably go into 
78 a separate module specific to the UI.  That can wait, though.  The API for 
79 this function won't change.)
80
81 VALUE (optional) is the current value of the field.
82
83 =cut
84
85 sub widget {
86   my $self = shift;
87   my ($ui_type, $mode, $value) = @_;
88   my $text;
89   my $label = $self->label || $self->name;
90
91   if ($ui_type eq 'HTML') {
92     if ($mode eq 'view') {
93       $text = q!<TR><TD ALIGN="right">! . $label . 
94               q!</TD><TD BGCOLOR="#ffffff">! . $value .
95               q!</TD></TR>! . "\n";
96     } elsif ($mode eq 'edit') {
97       $text = q!<TR><TD ALIGN="right">! . $label .
98               q!</TD><TD>!;
99         $text .= q!<INPUT NAME="! . $self->name .
100                 q!" VALUE="! . escapeHTML($value) . q!"!;
101         if ($self->length) {
102           $text .= q! SIZE="! . $self->length . q!"!;
103         }
104         $text .= '>';
105       $text .= q!</TD></TR>! . "\n";
106     } else {
107       return '';
108     }
109   } else {
110     return '';
111   }
112   return $text;
113 }
114
115
116 =item insert
117
118 Adds this record to the database.  If there is an error, returns the error,
119 otherwise returns false.
120
121 =item delete
122
123 Deletes this record from the database.  If there is an error, returns the
124 error, otherwise returns false.
125
126 =item replace OLD_RECORD
127
128 Replaces OLD_RECORD with this one in the database.  If there is an error,
129 returns the error, otherwise returns false.
130
131 =item check
132
133 If there is an error, returns the error, otherwise returns false.
134 Called by the insert and replace methods.
135
136 =back
137
138 =cut
139
140 sub check {
141   my $self = shift;
142
143   my $error = $self->ut_text('name') ||
144               $self->ut_text('dbtable') ||
145               $self->ut_number('length')
146               ;
147   return $error if $error;
148
149   # Make sure it's a real table with a numeric primary key
150   my ($table, $pkey);
151   if($table = dbdef->table($self->dbtable)) {
152     if($pkey = $table->primary_key) {
153       if($table->column($pkey)->type =~ /int/i) {
154         # this is what it should be
155       } else {
156         $error = "$table.$pkey is not an integer";
157       }
158     } else {
159       $error = "$table does not have a single-field primary key";
160     }
161   } else {
162     $error = "$table does not exist in the schema";
163   }
164   return $error if $error;
165
166   $self->SUPER::check;  
167 }
168
169 =head1 NOTES
170
171 =head1 BUGS
172
173 =head1 SEE ALSO
174
175 L<FS::Record>
176
177 =cut
178
179 1;
180
181