1 package SL::Presenter::Record;
6 use SL::Presenter::EscapedText qw(escape is_escaped);
8 use Exporter qw(import);
9 our @EXPORT_OK = qw(grouped_record_list empty_record_list record_list record);
14 use List::Util qw(first);
18 return [] if !defined $array;
19 return $array if ref $array;
24 my ($record, %params) = @_;
26 my %grouped = _group_records( [ $record ] ); # pass $record as arrayref
27 my $type = (keys %grouped)[0];
29 $record->presenter->sales_invoice( $record, %params) if $type eq 'sales_invoices';
30 $record->presenter->purchase_invoice($record, %params) if $type eq 'purchase_invoices';
31 $record->presenter->ar_transaction( $record, %params) if $type eq 'ar_transactions';
32 $record->presenter->ap_transaction( $record, %params) if $type eq 'ap_transactions';
33 $record->presenter->gl_transaction( $record, %params) if $type eq 'gl_transactions';
38 sub grouped_record_list {
39 my ($list, %params) = @_;
41 %params = map { exists $params{$_} ? ($_ => $params{$_}) : () } qw(edit_record_links with_columns object_id object_model);
43 my %groups = _sort_grouped_lists(_group_records($list));
46 $output .= _requirement_spec_list( $groups{requirement_specs}, %params) if $groups{requirement_specs};
47 $output .= _shop_order_list( $groups{shop_orders}, %params) if $groups{shop_orders};
48 $output .= _sales_quotation_list( $groups{sales_quotations}, %params) if $groups{sales_quotations};
49 $output .= _sales_order_list( $groups{sales_orders}, %params) if $groups{sales_orders};
50 $output .= _sales_delivery_order_list( $groups{sales_delivery_orders}, %params) if $groups{sales_delivery_orders};
51 $output .= _rma_delivery_order_list( $groups{rma_delivery_orders}, %params) if $groups{rma_delivery_orders};
52 $output .= _sales_invoice_list( $groups{sales_invoices}, %params) if $groups{sales_invoices};
53 $output .= _ar_transaction_list( $groups{ar_transactions}, %params) if $groups{ar_transactions};
55 $output .= _request_quotation_list( $groups{purchase_quotations}, %params) if $groups{purchase_quotations};
56 $output .= _purchase_order_list( $groups{purchase_orders}, %params) if $groups{purchase_orders};
57 $output .= _purchase_delivery_order_list($groups{purchase_delivery_orders}, %params) if $groups{purchase_delivery_orders};
58 $output .= _supplier_delivery_order_list($groups{supplier_delivery_orders}, %params) if $groups{supplier_delivery_orders};
59 $output .= _purchase_invoice_list( $groups{purchase_invoices}, %params) if $groups{purchase_invoices};
60 $output .= _ap_transaction_list( $groups{ap_transactions}, %params) if $groups{ap_transactions};
62 $output .= _gl_transaction_list( $groups{gl_transactions}, %params) if $groups{gl_transactions};
64 $output .= _bank_transactions( $groups{bank_transactions}, %params) if $groups{bank_transactions};
66 $output .= _sepa_collection_list( $groups{sepa_collections}, %params) if $groups{sepa_collections};
67 $output .= _sepa_transfer_list( $groups{sepa_transfers}, %params) if $groups{sepa_transfers};
69 $output .= _letter_list( $groups{letters}, %params) if $groups{letters};
70 $output .= _email_journal_list( $groups{email_journals}, %params) if $groups{email_journals};
72 $output .= _dunning_list( $groups{dunnings}, %params) if $groups{dunnings};
74 $output = SL::Presenter->get->render('presenter/record/grouped_record_list', %params, output => $output);
79 sub grouped_list { goto &grouped_record_list }
81 sub empty_record_list {
83 return grouped_record_list([], %params);
86 sub empty_list { goto &empty_record_list }
89 my ($list, %params) = @_;
93 if (ref($params{columns}) eq 'ARRAY') {
95 if (ref($_) eq 'ARRAY') {
96 { title => $_->[0], data => $_->[1], link => $_->[2] }
100 } @{ delete $params{columns} };
103 croak "Wrong type for 'columns' argument: not an array reference";
106 my %with_columns = map { ($_ => 1) } @{ _arrayify($params{with_columns}) };
107 if ($with_columns{record_link_direction}) {
109 title => $::locale->text('Link direction'),
111 $_[0]->{_record_link_depth} > 1
112 ? $::locale->text('Row was linked to another record')
113 : $_[0]->{_record_link_direction} eq 'from'
114 ? $::locale->text('Row was source for current record')
115 : $::locale->text('Row was created from current record') },
119 my %column_meta = map { $_->name => $_ } @{ $list->[0]->meta->columns };
120 my %relationships = map { $_->name => $_ } @{ $list->[0]->meta->relationships };
123 my ($obj, $method, @args) = @_;
124 $obj->$method(@args);
128 foreach my $obj (@{ $list }) {
131 foreach my $spec (@columns) {
134 my $method = $spec->{column} || $spec->{data};
135 my $meta = $column_meta{ $spec->{data} };
136 my $type = ref $meta;
137 my $relationship = $relationships{ $spec->{data} };
138 my $rel_type = !$relationship ? '' : $relationship->class;
139 $rel_type =~ s/^SL::DB:://;
140 $rel_type = SL::Util::snakify($rel_type);
142 if (ref($spec->{data}) eq 'CODE') {
143 $cell{value} = $spec->{data}->($obj);
146 $cell{value} = ref $obj->$method && $obj->$method->isa('SL::DB::Object') && $obj->$method->presenter->can($rel_type) ? $obj->$method->presenter->$rel_type(display => 'table-cell')
147 : $type eq 'Rose::DB::Object::Metadata::Column::Date' ? $call->($obj, $method . '_as_date')
148 : $type =~ m/^Rose::DB::Object::Metadata::Column::(?:Float|Numeric|Real)$/ ? $::form->format_amount(\%::myconfig, $call->($obj, $method), 2)
149 : $type eq 'Rose::DB::Object::Metadata::Column::Boolean' ? $call->($obj, $method . '_as_bool_yn')
150 : $type =~ m/^Rose::DB::Object::Metadata::Column::(?:Integer|Serial)$/ ? $spec->{data} * 1
151 : $call->($obj, $method);
154 $cell{alignment} = 'right' if $type =~ m/int|serial|float|real|numeric/;
159 push @data, { columns => \@row, record_link => $obj->{_record_link} };
163 map +{ value => $columns[$_]->{title},
164 alignment => $data[0]->{columns}->[$_]->{alignment},
165 }, (0..scalar(@columns) - 1);
167 return SL::Presenter->get->render(
168 'presenter/record/record_list',
170 TABLE_HEADER => \@header,
171 TABLE_ROWS => \@data,
175 sub list { goto &record_list }
184 requirement_specs => sub { (ref($_[0]) eq 'SL::DB::RequirementSpec') },
185 shop_orders => sub { (ref($_[0]) eq 'SL::DB::ShopOrder') && $_[0]->id },
186 sales_quotations => sub { (ref($_[0]) eq 'SL::DB::Order') && $_[0]->is_type('sales_quotation') },
187 sales_orders => sub { (ref($_[0]) eq 'SL::DB::Order') && $_[0]->is_type('sales_order') },
188 sales_delivery_orders => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder') && $_[0]->is_type('sales_delivery_order') },
189 rma_delivery_orders => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder') && $_[0]->is_type('rma_delivery_order') },
190 sales_invoices => sub { (ref($_[0]) eq 'SL::DB::Invoice') && $_[0]->invoice },
191 ar_transactions => sub { (ref($_[0]) eq 'SL::DB::Invoice') && !$_[0]->invoice },
192 purchase_quotations => sub { (ref($_[0]) eq 'SL::DB::Order') && $_[0]->is_type('request_quotation') },
193 purchase_orders => sub { (ref($_[0]) eq 'SL::DB::Order') && $_[0]->is_type('purchase_order') },
194 purchase_delivery_orders => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder') && $_[0]->is_type('purchase_delivery_order') },
195 supplier_delivery_orders => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder') && $_[0]->is_type('supplier_delivery_order') },
196 purchase_invoices => sub { (ref($_[0]) eq 'SL::DB::PurchaseInvoice') && $_[0]->invoice },
197 ap_transactions => sub { (ref($_[0]) eq 'SL::DB::PurchaseInvoice') && !$_[0]->invoice },
198 sepa_collections => sub { (ref($_[0]) eq 'SL::DB::SepaExportItem') && $_[0]->ar_id },
199 sepa_transfers => sub { (ref($_[0]) eq 'SL::DB::SepaExportItem') && $_[0]->ap_id },
200 gl_transactions => sub { (ref($_[0]) eq 'SL::DB::GLTransaction') },
201 bank_transactions => sub { (ref($_[0]) eq 'SL::DB::BankTransaction') && $_[0]->id },
202 letters => sub { (ref($_[0]) eq 'SL::DB::Letter') && $_[0]->id },
203 email_journals => sub { (ref($_[0]) eq 'SL::DB::EmailJournal') && $_[0]->id },
204 dunnings => sub { (ref($_[0]) eq 'SL::DB::Dunning') },
209 foreach my $record (@{ $list || [] }) {
210 my $type = (first { $matchers{$_}->($record) } keys %matchers) || 'other';
211 $groups{$type} ||= [];
212 push @{ $groups{$type} }, $record;
218 sub _sort_grouped_lists {
221 foreach my $group (keys %groups) {
222 next unless @{ $groups{$group} };
223 if ($groups{$group}->[0]->can('compare_to')) {
224 $groups{$group} = [ sort { $a->compare_to($b) } @{ $groups{$group} } ];
226 $groups{$group} = [ sort { $a->date <=> $b->date } @{ $groups{$group} } ];
233 sub _requirement_spec_list {
234 my ($list, %params) = @_;
238 title => $::locale->text('Requirement specs'),
239 type => 'requirement_spec',
241 [ $::locale->text('Requirement spec number'), sub { $_[0]->presenter->requirement_spec(display => 'table-cell') } ],
242 [ $::locale->text('Customer'), 'customer' ],
243 [ $::locale->text('Title'), 'title' ],
244 [ $::locale->text('Project'), 'project', ],
245 [ $::locale->text('Status'), sub { $_[0]->status->description } ],
251 sub _shop_order_list {
252 my ($list, %params) = @_;
256 title => $::locale->text('Shop Orders'),
257 type => 'shop_order',
259 [ $::locale->text('Shop Order Date'), sub { $_[0]->order_date->to_kivitendo } ],
260 [ $::locale->text('Shop Order Number'), sub { $_[0]->presenter->shop_order(display => 'table-cell') } ],
261 [ $::locale->text('Transfer Date'), 'transfer_date' ],
262 [ $::locale->text('Amount'), 'amount' ],
268 sub _sales_quotation_list {
269 my ($list, %params) = @_;
273 title => $::locale->text('Sales Quotations'),
274 type => 'sales_quotation',
276 [ $::locale->text('Quotation Date'), 'transdate' ],
277 [ $::locale->text('Quotation Number'), sub { $_[0]->presenter->sales_quotation(display => 'table-cell') } ],
278 [ $::locale->text('Customer'), 'customer' ],
279 [ $::locale->text('Net amount'), 'netamount' ],
280 [ $::locale->text('Transaction description'), 'transaction_description' ],
281 [ $::locale->text('Project'), 'globalproject', ],
282 [ $::locale->text('Closed'), 'closed' ],
288 sub _request_quotation_list {
289 my ($list, %params) = @_;
293 title => $::locale->text('Request Quotations'),
294 type => 'request_quotation',
296 [ $::locale->text('Quotation Date'), 'transdate' ],
297 [ $::locale->text('Quotation Number'), sub { $_[0]->presenter->request_quotation(display => 'table-cell') } ],
298 [ $::locale->text('Vendor'), 'vendor' ],
299 [ $::locale->text('Net amount'), 'netamount' ],
300 [ $::locale->text('Transaction description'), 'transaction_description' ],
301 [ $::locale->text('Project'), 'globalproject', ],
302 [ $::locale->text('Closed'), 'closed' ],
308 sub _sales_order_list {
309 my ($list, %params) = @_;
313 title => $::locale->text('Sales Orders'),
314 type => 'sales_order',
316 [ $::locale->text('Order Date'), 'transdate' ],
317 [ $::locale->text('Order Number'), sub { $_[0]->presenter->sales_order(display => 'table-cell') } ],
318 [ $::locale->text('Quotation'), 'quonumber' ],
319 [ $::locale->text('Customer'), 'customer' ],
320 [ $::locale->text('Net amount'), 'netamount' ],
321 [ $::locale->text('Transaction description'), 'transaction_description' ],
322 [ $::locale->text('Project'), 'globalproject', ],
323 [ $::locale->text('Closed'), 'closed' ],
329 sub _purchase_order_list {
330 my ($list, %params) = @_;
334 title => $::locale->text('Purchase Orders'),
335 type => 'purchase_order',
337 [ $::locale->text('Order Date'), 'transdate' ],
338 [ $::locale->text('Order Number'), sub { $_[0]->presenter->purchase_order(display => 'table-cell') } ],
339 [ $::locale->text('Request for Quotation'), 'quonumber' ],
340 [ $::locale->text('Vendor'), 'vendor' ],
341 [ $::locale->text('Net amount'), 'netamount' ],
342 [ $::locale->text('Transaction description'), 'transaction_description' ],
343 [ $::locale->text('Project'), 'globalproject', ],
344 [ $::locale->text('Closed'), 'closed' ],
350 sub _sales_delivery_order_list {
351 my ($list, %params) = @_;
355 title => $::locale->text('Sales Delivery Orders'),
356 type => 'sales_delivery_order',
358 [ $::locale->text('Delivery Order Date'), 'transdate' ],
359 [ $::locale->text('Delivery Order Number'), sub { $_[0]->presenter->sales_delivery_order(display => 'table-cell') } ],
360 [ $::locale->text('Order Number'), 'ordnumber' ],
361 [ $::locale->text('Customer'), 'customer' ],
362 [ $::locale->text('Transaction description'), 'transaction_description' ],
363 [ $::locale->text('Project'), 'globalproject', ],
364 [ $::locale->text('Delivered'), 'delivered' ],
365 [ $::locale->text('Closed'), 'closed' ],
371 sub _rma_delivery_order_list {
372 my ($list, %params) = @_;
376 title => $::locale->text('RMA Delivery Orders'),
377 type => 'rma_delivery_order',
379 [ $::locale->text('Delivery Order Date'), 'transdate' ],
380 [ $::locale->text('Delivery Order Number'), sub { $_[0]->presenter->rma_delivery_order(display => 'table-cell') } ],
381 [ $::locale->text('Order Number'), 'ordnumber' ],
382 [ $::locale->text('Customer'), 'customer' ],
383 [ $::locale->text('Transaction description'), 'transaction_description' ],
384 [ $::locale->text('Project'), 'globalproject', ],
385 [ $::locale->text('Delivered'), 'delivered' ],
386 [ $::locale->text('Closed'), 'closed' ],
392 sub _purchase_delivery_order_list {
393 my ($list, %params) = @_;
397 title => $::locale->text('Purchase Delivery Orders'),
398 type => 'purchase_delivery_order',
400 [ $::locale->text('Delivery Order Date'), 'transdate' ],
401 [ $::locale->text('Delivery Order Number'), sub { $_[0]->presenter->purchase_delivery_order(display => 'table-cell') } ],
402 [ $::locale->text('Order Number'), 'ordnumber' ],
403 [ $::locale->text('Vendor'), 'vendor' ],
404 [ $::locale->text('Transaction description'), 'transaction_description' ],
405 [ $::locale->text('Project'), 'globalproject', ],
406 [ $::locale->text('Delivered'), 'delivered' ],
407 [ $::locale->text('Closed'), 'closed' ],
413 sub _supplier_delivery_order_list {
414 my ($list, %params) = @_;
418 title => $::locale->text('Supplier Delivery Orders'),
419 type => 'supplier_delivery_order',
421 [ $::locale->text('Delivery Order Date'), 'transdate' ],
422 [ $::locale->text('Delivery Order Number'), sub { $_[0]->presenter->supplier_delivery_order(display => 'table-cell') } ],
423 [ $::locale->text('Order Number'), 'ordnumber' ],
424 [ $::locale->text('Vendor'), 'vendor' ],
425 [ $::locale->text('Transaction description'), 'transaction_description' ],
426 [ $::locale->text('Project'), 'globalproject', ],
427 [ $::locale->text('Delivered'), 'delivered' ],
428 [ $::locale->text('Closed'), 'closed' ],
434 sub _sales_invoice_list {
435 my ($list, %params) = @_;
439 title => $::locale->text('Sales Invoices'),
440 type => 'sales_invoice',
442 [ $::locale->text('Invoice Date'), 'transdate' ],
443 [ $::locale->text('Type'), sub { $_[0]->displayable_type } ],
444 [ $::locale->text('Invoice Number'), sub { $_[0]->presenter->sales_invoice(display => 'table-cell') } ],
445 [ $::locale->text('Quotation Number'), 'quonumber' ],
446 [ $::locale->text('Order Number'), 'ordnumber' ],
447 [ $::locale->text('Customer'), 'customer' ],
448 [ $::locale->text('Net amount'), 'netamount' ],
449 [ $::locale->text('Paid'), 'paid' ],
450 [ $::locale->text('Transaction description'), 'transaction_description' ],
456 sub _purchase_invoice_list {
457 my ($list, %params) = @_;
461 title => $::locale->text('Purchase Invoices'),
462 type => 'purchase_invoice',
464 [ $::locale->text('Invoice Date'), 'transdate' ],
465 [ $::locale->text('Invoice Number'), sub { $_[0]->presenter->purchase_invoice(display => 'table-cell') } ],
466 [ $::locale->text('Request for Quotation Number'), 'quonumber' ],
467 [ $::locale->text('Order Number'), 'ordnumber' ],
468 [ $::locale->text('Vendor'), 'vendor' ],
469 [ $::locale->text('Net amount'), 'netamount' ],
470 [ $::locale->text('Paid'), 'paid' ],
471 [ $::locale->text('Transaction description'), 'transaction_description' ],
477 sub _ar_transaction_list {
478 my ($list, %params) = @_;
482 title => $::locale->text('AR Transactions'),
483 type => 'ar_transaction',
485 [ $::locale->text('Invoice Date'), 'transdate' ],
486 [ $::locale->text('Type'), sub { $_[0]->displayable_type } ],
487 [ $::locale->text('Invoice Number'), sub { $_[0]->presenter->ar_transaction(display => 'table-cell') } ],
488 [ $::locale->text('Customer'), 'customer' ],
489 [ $::locale->text('Net amount'), 'netamount' ],
490 [ $::locale->text('Paid'), 'paid' ],
491 [ $::locale->text('Transaction description'), 'transaction_description' ],
497 sub _ap_transaction_list {
498 my ($list, %params) = @_;
502 title => $::locale->text('AP Transactions'),
503 type => 'ap_transaction',
505 [ $::locale->text('Invoice Date'), 'transdate' ],
506 [ $::locale->text('Invoice Number'), sub { $_[0]->presenter->ap_transaction(display => 'table-cell') } ],
507 [ $::locale->text('Vendor'), 'vendor' ],
508 [ $::locale->text('Net amount'), 'netamount' ],
509 [ $::locale->text('Paid'), 'paid' ],
510 [ $::locale->text('Transaction description'), 'transaction_description' ],
516 sub _gl_transaction_list {
517 my ($list, %params) = @_;
521 title => $::locale->text('GL Transactions'),
522 type => 'gl_transaction',
524 [ $::locale->text('Transdate'), 'transdate' ],
525 [ $::locale->text('Reference'), 'reference' ],
526 [ $::locale->text('Description'), sub { $_[0]->presenter->gl_transaction(display => 'table-cell') } ],
532 sub _bank_transactions {
533 my ($list, %params) = @_;
537 title => $::locale->text('Bank transactions'),
538 type => 'bank_transactions',
540 [ $::locale->text('Transdate'), 'transdate' ],
541 [ $::locale->text('Local Bank Code'), sub { $_[0]->local_bank_account->presenter->bank_code } ],
542 [ $::locale->text('Local account number'), sub { $_[0]->local_bank_account->presenter->account_number } ],
543 [ $::locale->text('Remote Bank Code'), 'remote_bank_code' ],
544 [ $::locale->text('Remote account number'),'remote_account_number' ],
545 [ $::locale->text('Valutadate'), 'valutadate' ],
546 [ $::locale->text('Amount'), 'amount' ],
547 [ $::locale->text('Currency'), sub { $_[0]->currency->name } ],
548 [ $::locale->text('Remote name'), 'remote_name' ],
549 [ $::locale->text('Purpose'), 'purpose' ],
555 sub _sepa_export_list {
556 my ($list, %params) = @_;
558 my ($source, $destination) = $params{type} eq 'sepa_transfer' ? qw(our vc) : qw(vc our);
559 $params{title} = $params{type} eq 'sepa_transfer' ? $::locale->text('Bank transfers via SEPA') : $::locale->text('Bank collections via SEPA');
560 $params{with_columns} = [ grep { $_ ne 'record_link_direction' } @{ $params{with_columns} || [] } ];
562 delete $params{edit_record_links};
567 [ $::locale->text('Export Number'), 'sepa_export', ],
568 [ $::locale->text('Execution date'), 'execution_date' ],
569 [ $::locale->text('Export date'), sub { $_[0]->sepa_export->itime->to_kivitendo } ],
570 [ $::locale->text('Source BIC'), "${source}_bic" ],
571 [ $::locale->text('Source IBAN'), "${source}_iban" ],
572 [ $::locale->text('Destination BIC'), "${destination}_bic" ],
573 [ $::locale->text('Destination IBAN'), "${destination}_iban" ],
574 [ $::locale->text('Amount'), 'amount' ],
580 sub _sepa_transfer_list {
581 my ($list, %params) = @_;
582 _sepa_export_list($list, %params, type => 'sepa_transfer');
585 sub _sepa_collection_list {
586 my ($list, %params) = @_;
587 _sepa_export_list($list, %params, type => 'sepa_collection');
591 my ($list, %params) = @_;
595 title => $::locale->text('Letters'),
598 [ $::locale->text('Date'), 'date' ],
599 [ $::locale->text('Letternumber'), sub { $_[0]->presenter->letter(display => 'table-cell') } ],
600 [ $::locale->text('Customer'), 'customer' ],
601 [ $::locale->text('Reference'), 'reference' ],
602 [ $::locale->text('Subject'), 'subject' ],
608 sub _email_journal_list {
609 my ($list, %params) = @_;
613 title => $::locale->text('Email'),
614 type => 'email_journal',
616 [ $::locale->text('Sent on'), sub { $_[0]->sent_on->to_kivitendo(precision => 'seconds') } ],
617 [ $::locale->text('Subject'), sub { $_[0]->presenter->email_journal(display => 'table-cell') } ],
618 [ $::locale->text('Status'), 'status' ],
619 [ $::locale->text('From'), 'from' ],
620 [ $::locale->text('To'), 'recipients' ],
626 my ($list, %params) = @_;
630 title => $::locale->text('Dunnings'),
633 [ $::locale->text('Dunning Level'), sub { $_[0]->presenter->dunning(display => 'table-cell') } ],
634 [ $::locale->text('Dunning Date'), 'transdate' ],
635 [ $::locale->text('Dunning Duedate'), 'duedate' ],
636 [ $::locale->text('Total Fees'), 'fee' ],
637 [ $::locale->text('Interest'), 'interest' ],
653 SL::Presenter::Record - Presenter module for lists of
654 sales/purchase/general ledger record Rose::DB objects
658 # Retrieve a number of documents from somewhere, e.g.
659 my $order = SL::DB::Manager::Order->get_first(where => [ SL::DB::Manager::Order->type_filter('sales_order') ]);
660 my $records = $order->linked_records(destination => 'to');
662 # Give HTML representation:
663 my $html = SL::Presenter->get->grouped_record_list($records);
675 Returns a rendered version (actually an instance of
676 L<SL::Presenter::EscapedText>) of a single ar, ap or gl object.
679 # fetch the record from a random acc_trans object and print its link (could be ar, ap or gl)
680 my $record = SL::DB::Manager::AccTransaction->get_first()->record;
681 my $html = SL::Presenter->get->record($record, display => 'inline');
683 =item C<grouped_record_list $list, %params>
685 =item C<empty_record_list>
687 Returns a rendered version (actually an instance of
688 L<SL::Presenter::EscapedText>) of an empty list of records. Is usually
689 only called by L<grouped_record_list> if its list is empty.
691 =item C<grouped_record_list $list, %params>
693 Given a number of Rose::DB objects in the array reference C<$list>
694 this function first groups them by type. Then it calls L<record_list>
695 with each non-empty type-specific sub-list and the appropriate
696 parameters for outputting a list of those records.
698 Returns a rendered version (actually an instance of
699 L<SL::Presenter::EscapedText>) of all the lists.
701 The order in which the records are grouped is:
705 =item * sales quotations
709 =item * sales delivery orders
711 =item * rma delivery orders
713 =item * sales invoices
715 =item * AR transactions
717 =item * requests for quotations
719 =item * purchase orders
721 =item * purchase delivery orders
723 =item * supplier delivery orders
725 =item * purchase invoices
727 =item * AP transactions
729 =item * GL transactions
731 =item * SEPA collections
733 =item * SEPA transfers
737 Objects of unknown types are skipped.
739 Parameters are passed to C<record_list> include C<with_objects> and
740 C<edit_record_links>.
742 =item C<record_list $list, %params>
744 Returns a rendered version (actually an instance of
745 L<SL::Presenter::EscapedText>) of a list of records. This list
746 consists of a heading and a tabular representation of the list.
748 The parameters include:
754 Mandatory. The title to use in the heading. Must already be
759 Mandatory. An array reference of column specs to output. Each column
760 spec can be either an array reference or a hash reference.
762 If a column spec is an array reference then the first element is the
763 column's name shown in the table header. It must already be translated.
765 The second element can be either a string or a code reference. A
766 string is taken as the name of a function to call on the Rose::DB
767 object for the current row. Its return value is formatted depending on
768 the column's type (e.g. dates are output as the user expects them,
769 floating point numbers are rounded to two decimal places and
770 right-aligned etc). If it is a code reference then that code is called
771 with the object as the first argument. Its return value should be an
772 instance of L<SL::Presenter::EscapedText> and contain the rendered
773 representation of the content to output.
775 The third element, if present, can be a link to which the column will
778 If the column spec is a hash reference then the same arguments are
779 expected. The corresponding hash keys are C<title>, C<data> and
782 =item C<with_columns>
784 Can be set by the caller to indicate additional columns to
785 be listed. Currently supported:
789 =item C<record_link_destination>
791 The record link destination. Requires that the records to be listed have
792 been retrieved via the L<SL::DB::Helper::LinkedRecords> helper.
796 =item C<edit_record_links>
798 If trueish additional controls will be rendered that allow the user to
799 remove and add record links. Requires that the records to be listed have
800 been retrieved via the L<SL::DB::Helper::LinkedRecords> helper.
812 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>