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