Bugs 6634: manager_id not recorded for payments and rental charges
[koha.git] / C4 / Creators / Lib.pm
1 package C4::Creators::Lib;
2
3 # Copyright 2009 Foundations Bible College.
4 #
5 # This file is part of Koha.
6 #
7 # Koha is free software; you can redistribute it and/or modify it under the
8 # terms of the GNU General Public License as published by the Free Software
9 # Foundation; either version 2 of the License, or (at your option) any later
10 # version.
11 #
12 # Koha is distributed in the hope that it will be useful, but WITHOUT ANY
13 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
14 # A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License along
17 # with Koha; if not, write to the Free Software Foundation, Inc.,
18 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19
20 use strict;
21 use warnings;
22
23 use autouse 'Data::Dumper' => qw(Dumper);
24
25 use C4::Context;
26 use C4::Debug;
27
28 BEGIN {
29     use version; our $VERSION = qv('1.0.0_1');
30     use base qw(Exporter);
31     our @EXPORT = qw(get_all_templates
32                      get_all_layouts
33                      get_all_profiles
34                      get_all_image_names
35                      get_batch_summary
36                      get_label_summary
37                      get_card_summary
38                      get_barcode_types
39                      get_label_types
40                      get_font_types
41                      get_text_justification_types
42                      get_output_formats
43                      get_column_names
44                      get_table_names
45                      get_unit_values
46                      html_table
47     );
48 }
49
50 =head1 NAME
51
52 C4::Creators::Lib
53
54 =cut
55
56 =head1 FUNCTIONS
57
58 =cut
59
60 #=head2 C4::Creators::Lib::_SELECT()
61 #
62 #    This function returns a recordset upon success and 1 upon failure. Errors are logged to the Apache log.
63 #
64 #    examples:
65 #
66 #        my $field_value = _SELECT(field_name, table_name, condition);
67 #
68 #=cut
69
70 sub _SELECT {
71     my @params = @_;
72     my $query = "SELECT $params[0] FROM $params[1]";
73     $params[2] ? $query .= " WHERE $params[2];" : $query .= ';';
74     my $sth = C4::Context->dbh->prepare($query);
75 #    $sth->{'TraceLevel'} = 3;
76     $sth->execute();
77     if ($sth->err) {
78         warn sprintf('Database returned the following error: %s', $sth->errstr);
79         return 1;
80     }
81     my $record_set = [];
82     while (my $row = $sth->fetchrow_hashref()) {
83         push(@$record_set, $row);
84     }
85     return $record_set;
86 }
87
88 my $barcode_types = [
89     {type => 'CODE39',          name => 'Code 39',              desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern.',                                  selected => 0},
90     {type => 'CODE39MOD',       name => 'Code 39 + Modulo43',   desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 43 checksum.',         selected => 0},
91     {type => 'CODE39MOD10',     name => 'Code 39 + Modulo10',   desc => 'Translates the characters 0-9, A-Z, \'-\', \'*\', \'+\', \'$\', \'%\', \'/\', \'.\' and \' \' to a barcode pattern. Encodes Mod 10 checksum.',         selected => 0},
92     {type => 'COOP2OF5',        name => 'COOP2of5',             desc => 'Creates COOP2of5 barcodes from a string consisting of the numeric characters 0-9',                                                                     selected => 0},
93 #    {type => 'EAN13',           name => 'EAN13',                desc => 'Creates EAN13 barcodes from a string of 12 or 13 digits. The check number (the 13:th digit) is calculated if not supplied.',                           selected => 0},
94 #    {type => 'EAN8',            name => 'EAN8',                 desc => 'Translates a string of 7 or 8 digits to EAN8 barcodes. The check number (the 8:th digit) is calculated if not supplied.',                              selected => 0},
95 #    {type => 'IATA2of5',        name => 'IATA2of5',             desc => 'Creates IATA2of5 barcodes from a string consisting of the numeric characters 0-9',                                                                     selected => 0},
96     {type => 'INDUSTRIAL2OF5',  name => 'Industrial2of5',       desc => 'Creates Industrial2of5 barcodes from a string consisting of the numeric characters 0-9',                                                               selected => 0},
97 #    {type => 'ITF',             name => 'Interleaved2of5',      desc => 'Translates the characters 0-9 to a barcodes. These barcodes could also be called 'Interleaved2of5'.',                                                  selected => 0},
98 #    {type => 'MATRIX2OF5',      name => 'Matrix2of5',           desc => 'Creates Matrix2of5 barcodes from a string consisting of the numeric characters 0-9',                                                                   selected => 0},
99 #    {type => 'NW7',             name => 'NW7',                  desc => 'Creates a NW7 barcodes from a string consisting of the numeric characters 0-9',                                                                        selected => 0},
100 #    {type => 'UPCA',            name => 'UPCA',                 desc => 'Translates a string of 11 or 12 digits to UPCA barcodes. The check number (the 12:th digit) is calculated if not supplied.',                           selected => 0},
101 #    {type => 'UPCE',            name => 'UPCE',                 desc => 'Translates a string of 6, 7 or 8 digits to UPCE barcodes. If the string is 6 digits long, '0' is added first in the string. The check number (the 8:th digit) is calculated if not supplied.',                                 selected => 0},
102 ];
103
104 my $label_types = [
105     {type => 'BIB',     name => 'Biblio',               desc => 'Only the bibliographic data is printed.',                              selected => 0},
106     {type => 'BARBIB',  name => 'Barcode/Biblio',       desc => 'Barcode proceeds bibliographic data.',                                 selected => 0},
107     {type => 'BIBBAR',  name => 'Biblio/Barcode',       desc => 'Bibliographic data proceeds barcode.',                                 selected => 0},
108     {type => 'ALT',     name => 'Alternating',          desc => 'Barcode and bibliographic data are printed on alternating labels.',    selected => 0},
109     {type => 'BAR',     name => 'Barcode',              desc => 'Only the barcode is printed.',                                         selected => 0},
110 ];
111
112 my $font_types = [
113     {type => 'TR',      name => 'Times-Roman',                  selected => 0},
114     {type => 'TB',      name => 'Times-Bold',                   selected => 0},
115     {type => 'TI',      name => 'Times-Italic',                 selected => 0},
116     {type => 'TBI',     name => 'Times-Bold-Italic',            selected => 0},
117     {type => 'C',       name => 'Courier',                      selected => 0},
118     {type => 'CB',      name => 'Courier-Bold',                 selected => 0},
119     {type => 'CO',      name => 'Courier-Oblique',              selected => 0},
120     {type => 'CBO',     name => 'Courier-Bold-Oblique',         selected => 0},
121     {type => 'H',       name => 'Helvetica',                    selected => 0},
122     {type => 'HB',      name => 'Helvetica-Bold',               selected => 0},
123     {type => 'HBO',     name => 'Helvetica-Bold-Oblique',       selected => 0},
124 ];
125
126 my $text_justification_types = [
127     {type => 'L',       name => 'Left',                         selected => 0},
128     {type => 'C',       name => 'Center',                       selected => 0},
129     {type => 'R',       name => 'Right',                        selected => 0},
130 #    {type => 'F',       name => 'Full',                         selected => 0},
131 ];
132
133 my $unit_values = [
134     {type       => 'POINT',      desc    => 'PostScript Points',  value   => 1,                 selected => 0},
135     {type       => 'AGATE',      desc    => 'Adobe Agates',       value   => 5.1428571,         selected => 0},
136     {type       => 'INCH',       desc    => 'US Inches',          value   => 72,                selected => 0},
137     {type       => 'MM',         desc    => 'SI Millimeters',     value   => 2.83464567,        selected => 0},
138     {type       => 'CM',         desc    => 'SI Centimeters',     value   => 28.3464567,        selected => 0},
139 ];
140
141 my $output_formats = [
142     {type       => 'pdf',       desc    => 'PDF File'},
143     {type       => 'csv',       desc    => 'CSV File'},
144 ];
145
146 =head2 C4::Creators::Lib::get_all_templates()
147
148   my $templates = get_all_templates();
149
150 This function returns a reference to a hash containing all templates upon success and 1 upon failure. Errors are logged to the Apache log.
151
152 =cut
153
154 sub get_all_templates {
155     my %params = @_;
156     my @templates = ();
157     my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM creator_templates";
158     $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
159     my $sth = C4::Context->dbh->prepare($query);
160     $sth->execute();
161     if ($sth->err) {
162         warn sprintf('Database returned the following error: %s', $sth->errstr);
163         return -1;
164     }
165     ADD_TEMPLATES:
166     while (my $template = $sth->fetchrow_hashref) {
167         push(@templates, $template);
168     }
169     return \@templates;
170 }
171
172 =head2 C4::Creators::Lib::get_all_layouts()
173
174   my $layouts = get_all_layouts();
175
176 This function returns a reference to a hash containing all layouts upon success and 1 upon failure. Errors are logged to the Apache log.
177
178 =cut
179
180 sub get_all_layouts {
181     my %params = @_;
182     my @layouts = ();
183     my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM creator_layouts";
184     $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
185     my $sth = C4::Context->dbh->prepare($query);
186     $sth->execute();
187     if ($sth->err) {
188         warn sprintf('Database returned the following error: %s', $sth->errstr);
189         return -1;
190     }
191     ADD_LAYOUTS:
192     while (my $layout = $sth->fetchrow_hashref) {
193         push(@layouts, $layout);
194     }
195     return \@layouts;
196 }
197
198 =head2 C4::Creators::Lib::get_all_profiles()
199
200   my $profiles = get_all_profiles();
201
202   my $profiles = get_all_profiles(field_list => field_list, filter => filter_string);
203
204 This function returns an arrayref whose elements are hashes containing all profiles upon success and 1 upon failure. Errors are logged
205 to the Apache log. Two parameters are accepted. The first limits the field(s) returned. This parameter should be string of comma separted
206 fields. ie. "field_1, field_2, ...field_n" The second limits the records returned based on a string containing a valud SQL 'WHERE' filter.
207
208 NOTE: Do not pass in the keyword 'WHERE.'
209
210 =cut
211
212 sub get_all_profiles {
213     my %params = @_;
214     my @profiles = ();
215     my $query = "SELECT " . ($params{'field_list'} ? $params{'field_list'} : '*') . " FROM printers_profile";
216     $query .= ($params{'filter'} ? " WHERE $params{'filter'};" : ';');
217     my $sth = C4::Context->dbh->prepare($query);
218 #    $sth->{'TraceLevel'} = 3 if $debug;
219     $sth->execute();
220     if ($sth->err) {
221         warn sprintf('Database returned the following error: %s', $sth->errstr);
222         return -1;
223     }
224     ADD_PROFILES:
225     while (my $profile = $sth->fetchrow_hashref) {
226         push(@profiles, $profile);
227     }
228     return \@profiles;
229 }
230
231 =head2 C4::Creators::Lib::get_all_image_names()
232
233 =cut
234
235 sub get_all_image_names {
236     my $image_names = [];
237     my $query = "SELECT image_name FROM creator_images";
238     my $sth = C4::Context->dbh->prepare($query);
239 #    $sth->{'TraceLevel'} = 3 if $debug;
240     $sth->execute();
241     if ($sth->err) {
242         warn sprintf('Database returned the following error: %s', $sth->errstr);
243         return -1;
244     }
245     grep {push @$image_names, {type => $$_[0], name => $$_[0], selected => 0}} @{$sth->fetchall_arrayref([0])};
246     return $image_names;
247 }
248
249 =head2 C4::Creators::Lib::get_batch_summary()
250
251   my $batches = get_batch_summary();
252
253   my $batches = get_batch_summary(filter => filter_string);
254
255 This function returns an arrayref whose elements are hashes containing the batch_ids of current batches along with the item count
256 for each batch upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log.
257 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
258
259 NOTE: Do not pass in the keyword 'WHERE.'
260
261 =cut
262
263 sub get_batch_summary {
264     my %params = @_;
265     my @batches = ();
266     my $query = "SELECT DISTINCT batch_id FROM creator_batches WHERE creator=?";
267     $query .= ($params{'filter'} ? " AND $params{'filter'};" : ';');
268     my $sth = C4::Context->dbh->prepare($query);
269 #    $sth->{'TraceLevel'} = 3;
270     $sth->execute($params{'creator'});
271     if ($sth->err) {
272         warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
273         return -1;
274     }
275     ADD_BATCHES:
276     while (my $batch = $sth->fetchrow_hashref) {
277         my $query = "SELECT count(batch_id) FROM creator_batches WHERE batch_id=? AND creator=?;";
278         my $sth1 = C4::Context->dbh->prepare($query);
279         $sth1->execute($batch->{'batch_id'}, $params{'creator'});
280         if ($sth1->err) {
281             warn sprintf('Database returned the following error on attempted SELECT count: %s', $sth1->errstr);
282             return -1;
283         }
284         my $count = $sth1->fetchrow_arrayref;
285         $batch->{'_item_count'} = @$count[0];
286         push(@batches, $batch);
287     }
288     return \@batches;
289 }
290
291 =head2 C4::Creators::Lib::get_label_summary()
292
293   my $labels = get_label_summary();
294
295   my $labels = get_label_summary(items => @item_list);
296
297 This function returns an arrayref whose elements are hashes containing the label_ids of current labels along with the item count
298 for each label upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log.
299 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
300
301 NOTE: Do not pass in the keyword 'WHERE.'
302
303 =cut
304
305 sub get_label_summary {
306     my %params = @_;
307     my $label_number = 0;
308     my @label_summaries = ();
309     my $query = "     SELECT b.title, b.author, bi.itemtype, i.barcode, i.biblionumber, i.itype
310                       FROM creator_batches AS c LEFT JOIN items AS i ON (c.item_number=i.itemnumber)
311                       LEFT JOIN biblioitems AS bi ON (i.biblioitemnumber=bi.biblioitemnumber)
312                       LEFT JOIN biblio AS b ON (bi.biblionumber=b.biblionumber)
313                       WHERE itemnumber=? AND batch_id=?;
314                   ";
315     my $sth = C4::Context->dbh->prepare($query);
316     foreach my $item (@{$params{'items'}}) {
317         $label_number++;
318         $sth->execute($item->{'item_number'}, $params{'batch_id'});
319         if ($sth->err) {
320             warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
321             return -1;
322         }
323         my $record = $sth->fetchrow_hashref;
324         my $label_summary;
325         $label_summary->{'_label_number'} = $label_number;
326         $record->{'author'} =~ s/[^\.|\w]$// if $record->{'author'};  # strip off ugly trailing chars... but not periods or word chars
327         $record->{'title'} =~ s/\W*$//;  # strip off ugly trailing chars
328         # FIXME contructing staff interface URLs should be done *much* higher up the stack - for the most part, C4 module code
329         # should not know that it's part of a web app
330         $record->{'title'} = '<a href="/cgi-bin/koha/catalogue/detail.pl?biblionumber=' . $record->{'biblionumber'} . '"> ' . $record->{'title'} . '</a>';
331         $label_summary->{'_summary'} = $record->{'title'} . " | " . ($record->{'author'} ? $record->{'author'} : 'N/A');
332         $label_summary->{'_item_type'} = C4::Context->preference("item-level_itypes") ? $record->{'itype'} : $record->{'itemtype'};
333         $label_summary->{'_barcode'} = $record->{'barcode'};
334         $label_summary->{'_item_number'} = $item->{'item_number'};
335         $label_summary->{'_label_id'} = $item->{'label_id'};
336         push (@label_summaries, $label_summary);
337     }
338     return \@label_summaries;
339 }
340
341 =head2 C4::Creators::Lib::get_card_summary()
342
343   my $cards = get_card_summary();
344
345   my $cards = get_card_summary(items => @item_list);
346
347 This function returns an arrayref whose elements are hashes containing the label_ids of current cards along with the item count
348 for each card upon success and 1 upon failure. Item counts are stored under the key '_item_count' Errors are logged to the Apache log.
349 One parameter is accepted which limits the records returned based on a string containing a valud SQL 'WHERE' filter.
350
351 NOTE: Do not pass in the keyword 'WHERE.'
352
353 =cut
354
355 sub get_card_summary {
356     my %params = @_;
357     my $card_number = 0;
358     my @card_summaries = ();
359     my $query = "SELECT CONCAT_WS(', ', surname, firstname) AS name, cardnumber FROM borrowers WHERE borrowernumber=?;";
360     my $sth = C4::Context->dbh->prepare($query);
361     foreach my $item (@{$params{'items'}}) {
362         $card_number++;
363         $sth->execute($item->{'borrower_number'});
364         if ($sth->err) {
365             warn sprintf('Database returned the following error on attempted SELECT: %s', $sth->errstr);
366             return -1;
367         }
368         my $record = $sth->fetchrow_hashref;
369         my $card_summary->{'_card_number'} = $card_number;
370         $card_summary->{'_summary'} = $record->{'name'};
371         $card_summary->{'borrowernumber'} = $item->{'borrower_number'};
372         $card_summary->{'_label_id'} = $item->{'label_id'};
373         push (@card_summaries, $card_summary);
374     }
375     return \@card_summaries;
376 }
377
378 =head2 C4::Creators::Lib::get_barcode_types()
379
380   my $barcode_types = get_barcode_types();
381
382 This function returns a reference to an array of hashes containing all barcode types along with their name and description.
383
384 =cut
385
386 sub get_barcode_types {
387     return $barcode_types;
388 }
389
390 =head2 C4::Creators::Lib::get_label_types()
391
392   my $label_types = get_label_types();
393
394 This function returns a reference to an array of hashes containing all label types along with their name and description.
395
396 =cut
397
398 sub get_label_types {
399     return $label_types;
400 }
401
402 =head2 C4::Creators::Lib::get_font_types()
403
404   my $font_types = get_font_types();
405
406 This function returns a reference to an array of hashes containing all font types along with their name and description.
407
408 =cut
409
410 sub get_font_types {
411     return $font_types;
412 }
413
414 =head2 C4::Creators::Lib::get_text_justification_types()
415
416   my $text_justification_types = get_text_justification_types();
417
418 This function returns a reference to an array of hashes containing all text justification types along with their name and description.
419
420 =cut
421
422 sub get_text_justification_types {
423     return $text_justification_types;
424 }
425
426 =head2 C4::Creators::Lib::get_unit_values()
427
428   my $unit_values = get_unit_values();
429
430 This function returns a reference to an array of  hashes containing all unit types along with their description and multiplier.
431 NOTE: All units are relative to a PostScript Point.
432 There are 72 PS points to the inch.
433
434 =cut
435
436 sub get_unit_values {
437     return $unit_values;
438 }
439
440 =head2 C4::Creators::Lib::get_output_formats()
441
442   my $label_output_formats = get_output_formats();
443
444 This function returns a reference to an array of hashes containing all label output formats along with their description.
445
446 =cut
447
448 sub get_output_formats {
449     return $output_formats;
450 }
451
452 =head2 C4::Creators::Lib::get_column_names($table_name)
453
454 Return an arrayref of an array containing the column names of the supplied table.
455
456 =cut
457
458 sub get_column_names {
459     my $table = shift;
460     my $dbh = C4::Context->dbh();
461     my $column_names = [];
462     my $sth = $dbh->column_info(undef,undef,$table,'%');
463     while (my $info = $sth->fetchrow_hashref()){
464         $$column_names[$info->{'ORDINAL_POSITION'}] = $info->{'COLUMN_NAME'};
465     }
466     return $column_names;
467 }
468
469 =head2 C4::Creators::Lib::get_table_names($search_term)
470
471 Return an arrayref of an array containing the table names which contain the supplied search term.
472
473 =cut
474
475 sub get_table_names {
476     my $search_term = shift;
477     my $dbh = C4::Context->dbh();
478     my $table_names = [];
479     my $sth = $dbh->table_info(undef,undef,"%$search_term%");
480     while (my $info = $sth->fetchrow_hashref()){
481         push (@$table_names, $info->{'TABLE_NAME'});
482     }
483     return $table_names;
484 }
485
486 =head2 C4::Creators::Lib::html_table()
487
488 This function returns an arrayref of an array of hashes contianing the supplied data formatted suitably to
489 be passed off as a T::P template parameter and used to build an html table.
490
491    my $table = html_table(header_fields, array_of_row_data);
492    $template->param(
493        TABLE => $table,
494    );
495
496     html example:
497
498        <table>
499             <!-- TMPL_LOOP NAME="TABLE" -->
500             <!-- TMPL_IF NAME="header_fields" -->
501             <tr>
502             <!-- TMPL_LOOP NAME="header_fields" -->
503                 <th><!-- TMPL_VAR NAME="field_label" --></th>
504             <!-- /TMPL_LOOP -->
505             </tr>
506             <!-- TMPL_ELSE -->
507             <tr>
508             <!-- TMPL_LOOP NAME="text_fields" -->
509             <!-- TMPL_IF NAME="select_field" -->
510                 <td align="center"><input type="checkbox" name="action" value="<!-- TMPL_VAR NAME="field_value" -->" /></td>
511             <!-- TMPL_ELSIF NAME="field_value" -->
512                 <td><!-- TMPL_VAR NAME="field_value" --></td>
513             <!-- TMPL_ELSE -->
514                 <td>&nbsp;</td>
515             <!-- /TMPL_IF -->
516             <!-- /TMPL_LOOP -->
517             </tr>
518             <!-- /TMPL_IF -->
519             <!-- /TMPL_LOOP -->
520         </table>
521
522 =cut
523
524 sub html_table {
525     my $headers = shift;
526     my $data = shift;
527     return undef if scalar(@$data) == 0;      # no need to generate a table if there is not data to display
528     my $table = [];
529     my $fields = [];
530     my @table_columns = ();
531     my ($row_index, $col_index) = (0,0);
532     my $cols = 0;       # number of columns to wrap on
533     my $field_count = 0;
534     my $select_value = undef;
535     my $link_field = undef;
536     POPULATE_HEADER:
537     foreach my $header (@$headers) {
538         my @key = keys %$header;
539         if ($key[0] eq 'select' ) {
540             push (@table_columns, $key[0]);
541             $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}};
542             # do special formatting stuff....
543             $select_value = $header->{$key[0]}{'value'};
544         }
545         else {
546             # do special formatting stuff....
547             $link_field->{$key[0]} = ($header->{$key[0]}{'link_field'} == 1 ? 1 : 0);
548             push (@table_columns, $key[0]);
549             $$fields[$col_index] = {hidden => 0, select_field => 0, field_name => ($key[0]), field_label => $header->{$key[0]}{'label'}};
550         }
551         $field_count++;
552         $col_index++;
553     }
554     $$table[$row_index] = {header_fields => $fields};
555     $cols = $col_index;
556     $field_count *= scalar(@$data);     # total fields to be displayed in the table
557     $col_index = 0;
558     $row_index++;
559     $fields = [];
560     POPULATE_TABLE:
561     foreach my $db_row (@$data) {
562         POPULATE_ROW:
563         foreach my $table_column (@table_columns) {
564             if (grep {$table_column eq $_} keys %$db_row) {
565                 $$fields[$col_index] = {hidden => 0, link_field => $link_field->{$table_column}, select_field => 0, field_name => ($table_column . "_tbl"), field_value => $db_row->{$table_column}};
566                 $col_index++;
567                 next POPULATE_ROW;
568             }
569             elsif ($table_column =~ m/^_((.*)_(.*$))/) {   # this a special case
570                 my $table_name = get_table_names($2);
571                 my $record_set = _SELECT($1, @$table_name[0], $2 . "_id = " . $db_row->{$2 . "_id"});
572                 $$fields[$col_index] = {hidden => 0, link_field => $link_field->{$table_column}, select_field => 0, field_name => ($table_column . "_tbl"), field_value => $$record_set[0]{$1}};
573                 $col_index++;
574                 next POPULATE_ROW;
575             }
576             elsif ($table_column eq 'select' ) {
577                 $$fields[$col_index] = {hidden => 0, select_field => 1, field_name => 'select', field_value => $db_row->{$select_value}};
578             }
579         }
580         $$table[$row_index] = {text_fields => $fields};
581         $col_index = 0;
582         $row_index++;
583         $fields = [];
584     }
585     return $table;
586 }
587
588 1;
589 __END__
590
591 =head1 AUTHOR
592
593 Chris Nighswonger <cnighswonger AT foundations DOT edu>
594
595 =cut