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 .= _sales_invoice_list(          $groups{sales_invoices},           %params) if $groups{sales_invoices};
 
  52   $output .= _ar_transaction_list(         $groups{ar_transactions},          %params) if $groups{ar_transactions};
 
  54   $output .= _request_quotation_list(      $groups{purchase_quotations},      %params) if $groups{purchase_quotations};
 
  55   $output .= _purchase_order_list(         $groups{purchase_orders},          %params) if $groups{purchase_orders};
 
  56   $output .= _purchase_delivery_order_list($groups{purchase_delivery_orders}, %params) if $groups{purchase_delivery_orders};
 
  57   $output .= _purchase_invoice_list(       $groups{purchase_invoices},        %params) if $groups{purchase_invoices};
 
  58   $output .= _ap_transaction_list(         $groups{ap_transactions},          %params) if $groups{ap_transactions};
 
  60   $output .= _gl_transaction_list(         $groups{gl_transactions},          %params) if $groups{gl_transactions};
 
  62   $output .= _bank_transactions(           $groups{bank_transactions},        %params) if $groups{bank_transactions};
 
  64   $output .= _sepa_collection_list(        $groups{sepa_collections},         %params) if $groups{sepa_collections};
 
  65   $output .= _sepa_transfer_list(          $groups{sepa_transfers},           %params) if $groups{sepa_transfers};
 
  67   $output .= _letter_list(                 $groups{letters},                  %params) if $groups{letters};
 
  68   $output .= _email_journal_list(          $groups{email_journals},           %params) if $groups{email_journals};
 
  70   $output .= _dunning_list(                $groups{dunnings},                 %params) if $groups{dunnings};
 
  72   $output  = SL::Presenter->get->render('presenter/record/grouped_record_list', %params, output => $output);
 
  77 sub grouped_list { goto &grouped_record_list }
 
  79 sub empty_record_list {
 
  81   return grouped_record_list([], %params);
 
  84 sub empty_list { goto &empty_record_list }
 
  87   my ($list, %params) = @_;
 
  91   if (ref($params{columns}) eq 'ARRAY') {
 
  93       if (ref($_) eq 'ARRAY') {
 
  94         { title => $_->[0], data => $_->[1], link => $_->[2] }
 
  98     } @{ delete $params{columns} };
 
 101     croak "Wrong type for 'columns' argument: not an array reference";
 
 104   my %with_columns = map { ($_ => 1) } @{ _arrayify($params{with_columns}) };
 
 105   if ($with_columns{record_link_direction}) {
 
 107       title => $::locale->text('Link direction'),
 
 109           $_[0]->{_record_link_depth} > 1
 
 110         ? $::locale->text('Row was linked to another record')
 
 111         : $_[0]->{_record_link_direction} eq 'from'
 
 112         ? $::locale->text('Row was source for current record')
 
 113         : $::locale->text('Row was created from current record') },
 
 117   my %column_meta   = map { $_->name => $_ } @{ $list->[0]->meta->columns       };
 
 118   my %relationships = map { $_->name => $_ } @{ $list->[0]->meta->relationships };
 
 121     my ($obj, $method, @args) = @_;
 
 122     $obj->$method(@args);
 
 126   foreach my $obj (@{ $list }) {
 
 129     foreach my $spec (@columns) {
 
 132       my $method       =  $spec->{column} || $spec->{data};
 
 133       my $meta         =  $column_meta{ $spec->{data} };
 
 134       my $type         =  ref $meta;
 
 135       my $relationship =  $relationships{ $spec->{data} };
 
 136       my $rel_type     =  !$relationship ? '' : $relationship->class;
 
 137       $rel_type        =~ s/^SL::DB:://;
 
 138       $rel_type        =  SL::Util::snakify($rel_type);
 
 140       if (ref($spec->{data}) eq 'CODE') {
 
 141         $cell{value} = $spec->{data}->($obj);
 
 144         $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')
 
 145                      : $type eq 'Rose::DB::Object::Metadata::Column::Date'                      ? $call->($obj, $method . '_as_date')
 
 146                      : $type =~ m/^Rose::DB::Object::Metadata::Column::(?:Float|Numeric|Real)$/ ? $::form->format_amount(\%::myconfig, $call->($obj, $method), 2)
 
 147                      : $type eq 'Rose::DB::Object::Metadata::Column::Boolean'                   ? $call->($obj, $method . '_as_bool_yn')
 
 148                      : $type =~ m/^Rose::DB::Object::Metadata::Column::(?:Integer|Serial)$/     ? $spec->{data} * 1
 
 149                      :                                                                            $call->($obj, $method);
 
 152       $cell{alignment} = 'right' if $type =~ m/int|serial|float|real|numeric/;
 
 157     push @data, { columns => \@row, record_link => $obj->{_record_link} };
 
 161     map +{ value     => $columns[$_]->{title},
 
 162            alignment => $data[0]->{columns}->[$_]->{alignment},
 
 163          }, (0..scalar(@columns) - 1);
 
 165   return SL::Presenter->get->render(
 
 166     'presenter/record/record_list',
 
 168     TABLE_HEADER => \@header,
 
 169     TABLE_ROWS   => \@data,
 
 173 sub list { goto &record_list }
 
 182     requirement_specs        => sub { (ref($_[0]) eq 'SL::DB::RequirementSpec')                                         },
 
 183     shop_orders              => sub { (ref($_[0]) eq 'SL::DB::ShopOrder')       &&  $_[0]->id                           },
 
 184     sales_quotations         => sub { (ref($_[0]) eq 'SL::DB::Order')           &&  $_[0]->is_type('sales_quotation')   },
 
 185     sales_orders             => sub { (ref($_[0]) eq 'SL::DB::Order')           &&  $_[0]->is_type('sales_order')       },
 
 186     sales_delivery_orders    => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder')   &&  $_[0]->is_sales                     },
 
 187     sales_invoices           => sub { (ref($_[0]) eq 'SL::DB::Invoice')         &&  $_[0]->invoice                      },
 
 188     ar_transactions          => sub { (ref($_[0]) eq 'SL::DB::Invoice')         && !$_[0]->invoice                      },
 
 189     purchase_quotations      => sub { (ref($_[0]) eq 'SL::DB::Order')           &&  $_[0]->is_type('request_quotation') },
 
 190     purchase_orders          => sub { (ref($_[0]) eq 'SL::DB::Order')           &&  $_[0]->is_type('purchase_order')    },
 
 191     purchase_delivery_orders => sub { (ref($_[0]) eq 'SL::DB::DeliveryOrder')   && !$_[0]->is_sales                     },
 
 192     purchase_invoices        => sub { (ref($_[0]) eq 'SL::DB::PurchaseInvoice') &&  $_[0]->invoice                      },
 
 193     ap_transactions          => sub { (ref($_[0]) eq 'SL::DB::PurchaseInvoice') && !$_[0]->invoice                      },
 
 194     sepa_collections         => sub { (ref($_[0]) eq 'SL::DB::SepaExportItem')  &&  $_[0]->ar_id                        },
 
 195     sepa_transfers           => sub { (ref($_[0]) eq 'SL::DB::SepaExportItem')  &&  $_[0]->ap_id                        },
 
 196     gl_transactions          => sub { (ref($_[0]) eq 'SL::DB::GLTransaction')                                           },
 
 197     bank_transactions        => sub { (ref($_[0]) eq 'SL::DB::BankTransaction') &&  $_[0]->id                           },
 
 198     letters                  => sub { (ref($_[0]) eq 'SL::DB::Letter')          &&  $_[0]->id                           },
 
 199     email_journals           => sub { (ref($_[0]) eq 'SL::DB::EmailJournal')    &&  $_[0]->id                           },
 
 200     dunnings                 => sub { (ref($_[0]) eq 'SL::DB::Dunning')                                                 },
 
 205   foreach my $record (@{ $list || [] }) {
 
 206     my $type         = (first { $matchers{$_}->($record) } keys %matchers) || 'other';
 
 207     $groups{$type} ||= [];
 
 208     push @{ $groups{$type} }, $record;
 
 214 sub _sort_grouped_lists {
 
 217   foreach my $group (keys %groups) {
 
 218     next unless @{ $groups{$group} };
 
 219     if ($groups{$group}->[0]->can('compare_to')) {
 
 220       $groups{$group} = [ sort { $a->compare_to($b)    } @{ $groups{$group} } ];
 
 222       $groups{$group} = [ sort { $a->date <=> $b->date } @{ $groups{$group} } ];
 
 229 sub _requirement_spec_list {
 
 230   my ($list, %params) = @_;
 
 234     title   => $::locale->text('Requirement specs'),
 
 235     type    => 'requirement_spec',
 
 237       [ $::locale->text('Requirement spec number'), sub { $_[0]->presenter->requirement_spec(display => 'table-cell') } ],
 
 238       [ $::locale->text('Customer'),                'customer'                                                      ],
 
 239       [ $::locale->text('Title'),                   'title'                                                         ],
 
 240       [ $::locale->text('Project'),                 'project',                                                      ],
 
 241       [ $::locale->text('Status'),                  sub { $_[0]->status->description }                              ],
 
 247 sub _shop_order_list {
 
 248   my ($list, %params) = @_;
 
 252     title   => $::locale->text('Shop Orders'),
 
 253     type    => 'shop_order',
 
 255       [ $::locale->text('Shop Order Date'),         sub { $_[0]->order_date->to_kivitendo }                         ],
 
 256       [ $::locale->text('Shop Order Number'),       sub { $_[0]->presenter->shop_order(display => 'table-cell') }   ],
 
 257       [ $::locale->text('Transfer Date'),           'transfer_date'                                                 ],
 
 258       [ $::locale->text('Amount'),                  'amount'                                                        ],
 
 264 sub _sales_quotation_list {
 
 265   my ($list, %params) = @_;
 
 269     title   => $::locale->text('Sales Quotations'),
 
 270     type    => 'sales_quotation',
 
 272       [ $::locale->text('Quotation Date'),          'transdate'                                                                ],
 
 273       [ $::locale->text('Quotation Number'),        sub { $_[0]->presenter->sales_quotation(display => 'table-cell') }         ],
 
 274       [ $::locale->text('Customer'),                'customer'                                                                 ],
 
 275       [ $::locale->text('Net amount'),              'netamount'                                                                ],
 
 276       [ $::locale->text('Transaction description'), 'transaction_description'                                                  ],
 
 277       [ $::locale->text('Project'),                 'globalproject', ],
 
 278       [ $::locale->text('Closed'),                  'closed'                                                                   ],
 
 284 sub _request_quotation_list {
 
 285   my ($list, %params) = @_;
 
 289     title   => $::locale->text('Request Quotations'),
 
 290     type    => 'request_quotation',
 
 292       [ $::locale->text('Quotation Date'),          'transdate'                                                                ],
 
 293       [ $::locale->text('Quotation Number'),        sub { $_[0]->presenter->request_quotation(display => 'table-cell') }       ],
 
 294       [ $::locale->text('Vendor'),                  'vendor'                                                                   ],
 
 295       [ $::locale->text('Net amount'),              'netamount'                                                                ],
 
 296       [ $::locale->text('Transaction description'), 'transaction_description'                                                  ],
 
 297       [ $::locale->text('Project'),                 'globalproject', ],
 
 298       [ $::locale->text('Closed'),                  'closed'                                                                   ],
 
 304 sub _sales_order_list {
 
 305   my ($list, %params) = @_;
 
 309     title   => $::locale->text('Sales Orders'),
 
 310     type    => 'sales_order',
 
 312       [ $::locale->text('Order Date'),              'transdate'                                                                ],
 
 313       [ $::locale->text('Order Number'),            sub { $_[0]->presenter->sales_order(display => 'table-cell') }             ],
 
 314       [ $::locale->text('Quotation'),               'quonumber' ],
 
 315       [ $::locale->text('Customer'),                'customer'                                                                 ],
 
 316       [ $::locale->text('Net amount'),              'netamount'                                                                ],
 
 317       [ $::locale->text('Transaction description'), 'transaction_description'                                                  ],
 
 318       [ $::locale->text('Project'),                 'globalproject', ],
 
 319       [ $::locale->text('Closed'),                  'closed'                                                                   ],
 
 325 sub _purchase_order_list {
 
 326   my ($list, %params) = @_;
 
 330     title   => $::locale->text('Purchase Orders'),
 
 331     type    => 'purchase_order',
 
 333       [ $::locale->text('Order Date'),              'transdate'                                                                ],
 
 334       [ $::locale->text('Order Number'),            sub { $_[0]->presenter->purchase_order(display => 'table-cell') }          ],
 
 335       [ $::locale->text('Request for Quotation'),   'quonumber' ],
 
 336       [ $::locale->text('Vendor'),                  'vendor'                                                                 ],
 
 337       [ $::locale->text('Net amount'),              'netamount'                                                                ],
 
 338       [ $::locale->text('Transaction description'), 'transaction_description'                                                  ],
 
 339       [ $::locale->text('Project'),                 'globalproject', ],
 
 340       [ $::locale->text('Closed'),                  'closed'                                                                   ],
 
 346 sub _sales_delivery_order_list {
 
 347   my ($list, %params) = @_;
 
 351     title   => $::locale->text('Sales Delivery Orders'),
 
 352     type    => 'sales_delivery_order',
 
 354       [ $::locale->text('Delivery Order Date'),     'transdate'                                                                ],
 
 355       [ $::locale->text('Delivery Order Number'),   sub { $_[0]->presenter->sales_delivery_order(display => 'table-cell') }    ],
 
 356       [ $::locale->text('Order Number'),            'ordnumber' ],
 
 357       [ $::locale->text('Customer'),                'customer'                                                                 ],
 
 358       [ $::locale->text('Transaction description'), 'transaction_description'                                                  ],
 
 359       [ $::locale->text('Project'),                 'globalproject', ],
 
 360       [ $::locale->text('Delivered'),               'delivered'                                                                ],
 
 361       [ $::locale->text('Closed'),                  'closed'                                                                   ],
 
 367 sub _purchase_delivery_order_list {
 
 368   my ($list, %params) = @_;
 
 372     title   => $::locale->text('Purchase Delivery Orders'),
 
 373     type    => 'purchase_delivery_order',
 
 375       [ $::locale->text('Delivery Order Date'),     'transdate'                                                                ],
 
 376       [ $::locale->text('Delivery Order Number'),   sub { $_[0]->presenter->purchase_delivery_order(display => 'table-cell') } ],
 
 377       [ $::locale->text('Order Number'),            'ordnumber' ],
 
 378       [ $::locale->text('Vendor'),                  'vendor'                                                                 ],
 
 379       [ $::locale->text('Transaction description'), 'transaction_description'                                                  ],
 
 380       [ $::locale->text('Project'),                 'globalproject', ],
 
 381       [ $::locale->text('Delivered'),               'delivered'                                                                ],
 
 382       [ $::locale->text('Closed'),                  'closed'                                                                   ],
 
 388 sub _sales_invoice_list {
 
 389   my ($list, %params) = @_;
 
 393     title   => $::locale->text('Sales Invoices'),
 
 394     type    => 'sales_invoice',
 
 396       [ $::locale->text('Invoice Date'),            'transdate'               ],
 
 397       [ $::locale->text('Type'),                    sub { $_[0]->displayable_type } ],
 
 398       [ $::locale->text('Invoice Number'),          sub { $_[0]->presenter->sales_invoice(display => 'table-cell') } ],
 
 399       [ $::locale->text('Quotation Number'),        'quonumber' ],
 
 400       [ $::locale->text('Order Number'),            'ordnumber' ],
 
 401       [ $::locale->text('Customer'),                'customer'                ],
 
 402       [ $::locale->text('Net amount'),              'netamount'               ],
 
 403       [ $::locale->text('Paid'),                    'paid'                    ],
 
 404       [ $::locale->text('Transaction description'), 'transaction_description' ],
 
 410 sub _purchase_invoice_list {
 
 411   my ($list, %params) = @_;
 
 415     title   => $::locale->text('Purchase Invoices'),
 
 416     type    => 'purchase_invoice',
 
 418       [ $::locale->text('Invoice Date'),                 'transdate'               ],
 
 419       [ $::locale->text('Invoice Number'),               sub { $_[0]->presenter->purchase_invoice(display => 'table-cell') } ],
 
 420       [ $::locale->text('Request for Quotation Number'), 'quonumber' ],
 
 421       [ $::locale->text('Order Number'),                 'ordnumber' ],
 
 422       [ $::locale->text('Vendor'),                       'vendor'                 ],
 
 423       [ $::locale->text('Net amount'),                   'netamount'               ],
 
 424       [ $::locale->text('Paid'),                         'paid'                    ],
 
 425       [ $::locale->text('Transaction description'),      'transaction_description' ],
 
 431 sub _ar_transaction_list {
 
 432   my ($list, %params) = @_;
 
 436     title   => $::locale->text('AR Transactions'),
 
 437     type    => 'ar_transaction',
 
 439       [ $::locale->text('Invoice Date'),            'transdate'               ],
 
 440       [ $::locale->text('Type'),                    sub { $_[0]->displayable_type } ],
 
 441       [ $::locale->text('Invoice Number'),          sub { $_[0]->presenter->ar_transaction(display => 'table-cell') } ],
 
 442       [ $::locale->text('Customer'),                'customer'                ],
 
 443       [ $::locale->text('Net amount'),              'netamount'               ],
 
 444       [ $::locale->text('Paid'),                    'paid'                    ],
 
 445       [ $::locale->text('Transaction description'), 'transaction_description' ],
 
 451 sub _ap_transaction_list {
 
 452   my ($list, %params) = @_;
 
 456     title   => $::locale->text('AP Transactions'),
 
 457     type    => 'ap_transaction',
 
 459       [ $::locale->text('Invoice Date'),            'transdate'                      ],
 
 460       [ $::locale->text('Invoice Number'),          sub { $_[0]->presenter->ap_transaction(display => 'table-cell') } ],
 
 461       [ $::locale->text('Vendor'),                  'vendor'                         ],
 
 462       [ $::locale->text('Net amount'),              'netamount'                      ],
 
 463       [ $::locale->text('Paid'),                    'paid'                           ],
 
 464       [ $::locale->text('Transaction description'), 'transaction_description'        ],
 
 470 sub _gl_transaction_list {
 
 471   my ($list, %params) = @_;
 
 475     title   => $::locale->text('GL Transactions'),
 
 476     type    => 'gl_transaction',
 
 478       [ $::locale->text('Transdate'),        'transdate'                                                    ],
 
 479       [ $::locale->text('Reference'),   'reference'                                                    ],
 
 480       [ $::locale->text('Description'), sub { $_[0]->presenter->gl_transaction(display => 'table-cell') } ],
 
 486 sub _bank_transactions {
 
 487   my ($list, %params) = @_;
 
 491     title   => $::locale->text('Bank transactions'),
 
 492     type    => 'bank_transactions',
 
 494       [ $::locale->text('Transdate'),            'transdate'                      ],
 
 495       [ $::locale->text('Local Bank Code'),      sub { $_[0]->local_bank_account->presenter->bank_code }  ],
 
 496       [ $::locale->text('Local account number'), sub { $_[0]->local_bank_account->presenter->account_number }  ],
 
 497       [ $::locale->text('Remote Bank Code'),     'remote_bank_code' ],
 
 498       [ $::locale->text('Remote account number'),'remote_account_number' ],
 
 499       [ $::locale->text('Valutadate'),           'valutadate' ],
 
 500       [ $::locale->text('Amount'),               'amount' ],
 
 501       [ $::locale->text('Currency'),             sub { $_[0]->currency->name } ],
 
 502       [ $::locale->text('Remote name'),          'remote_name' ],
 
 503       [ $::locale->text('Purpose'),              'purpose' ],
 
 509 sub _sepa_export_list {
 
 510   my ($list, %params) = @_;
 
 512   my ($source, $destination) = $params{type} eq 'sepa_transfer' ? qw(our vc)                                 : qw(vc our);
 
 513   $params{title}             = $params{type} eq 'sepa_transfer' ? $::locale->text('Bank transfers via SEPA') : $::locale->text('Bank collections via SEPA');
 
 514   $params{with_columns}      = [ grep { $_ ne 'record_link_direction' } @{ $params{with_columns} || [] } ];
 
 516   delete $params{edit_record_links};
 
 521       [ $::locale->text('Export Number'),    'sepa_export',                                  ],
 
 522       [ $::locale->text('Execution date'),   'execution_date'                                ],
 
 523       [ $::locale->text('Export date'),      sub { $_[0]->sepa_export->itime->to_kivitendo } ],
 
 524       [ $::locale->text('Source BIC'),       "${source}_bic"                                 ],
 
 525       [ $::locale->text('Source IBAN'),      "${source}_iban"                                ],
 
 526       [ $::locale->text('Destination BIC'),  "${destination}_bic"                            ],
 
 527       [ $::locale->text('Destination IBAN'), "${destination}_iban"                           ],
 
 528       [ $::locale->text('Amount'),           'amount'                                        ],
 
 534 sub _sepa_transfer_list {
 
 535   my ($list, %params) = @_;
 
 536   _sepa_export_list($list, %params, type => 'sepa_transfer');
 
 539 sub _sepa_collection_list {
 
 540   my ($list, %params) = @_;
 
 541   _sepa_export_list($list, %params, type => 'sepa_collection');
 
 545   my ($list, %params) = @_;
 
 549     title   => $::locale->text('Letters'),
 
 552       [ $::locale->text('Date'),         'date'                                                ],
 
 553       [ $::locale->text('Letternumber'), sub { $_[0]->presenter->letter(display => 'table-cell') } ],
 
 554       [ $::locale->text('Customer'),     'customer'                                            ],
 
 555       [ $::locale->text('Reference'),    'reference'                                           ],
 
 556       [ $::locale->text('Subject'),      'subject'                                             ],
 
 562 sub _email_journal_list {
 
 563   my ($list, %params) = @_;
 
 567     title   => $::locale->text('Email'),
 
 568     type    => 'email_journal',
 
 570       [ $::locale->text('Sent on'), sub { $_[0]->sent_on->to_kivitendo(precision => 'seconds') } ],
 
 571       [ $::locale->text('Subject'), sub { $_[0]->presenter->email_journal(display => 'table-cell') } ],
 
 572       [ $::locale->text('Status'),  'status'                                                     ],
 
 573       [ $::locale->text('From'),    'from'                                                       ],
 
 574       [ $::locale->text('To'),      'recipients'                                                 ],
 
 580   my ($list, %params) = @_;
 
 584     title   => $::locale->text('Dunnings'),
 
 587       [ $::locale->text('Dunning Level'),   sub { $_[0]->presenter->dunning(display => 'table-cell') } ],
 
 588       [ $::locale->text('Dunning Date'),    'transdate'                                                ],
 
 589       [ $::locale->text('Dunning Duedate'), 'duedate'                                                  ],
 
 590       [ $::locale->text('Total Fees'),      'fee'                                                      ],
 
 591       [ $::locale->text('Interest'),        'interest'                                                 ],
 
 607 SL::Presenter::Record - Presenter module for lists of
 
 608 sales/purchase/general ledger record Rose::DB objects
 
 612   # Retrieve a number of documents from somewhere, e.g.
 
 613   my $order   = SL::DB::Manager::Order->get_first(where => [ SL::DB::Manager::Order->type_filter('sales_order') ]);
 
 614   my $records = $order->linked_records(destination => 'to');
 
 616   # Give HTML representation:
 
 617   my $html = SL::Presenter->get->grouped_record_list($records);
 
 629 Returns a rendered version (actually an instance of
 
 630 L<SL::Presenter::EscapedText>) of a single ar, ap or gl object.
 
 633   # fetch the record from a random acc_trans object and print its link (could be ar, ap or gl)
 
 634   my $record = SL::DB::Manager::AccTransaction->get_first()->record;
 
 635   my $html   = SL::Presenter->get->record($record, display => 'inline');
 
 637 =item C<grouped_record_list $list, %params>
 
 639 =item C<empty_record_list>
 
 641 Returns a rendered version (actually an instance of
 
 642 L<SL::Presenter::EscapedText>) of an empty list of records. Is usually
 
 643 only called by L<grouped_record_list> if its list is empty.
 
 645 =item C<grouped_record_list $list, %params>
 
 647 Given a number of Rose::DB objects in the array reference C<$list>
 
 648 this function first groups them by type. Then it calls L<record_list>
 
 649 with each non-empty type-specific sub-list and the appropriate
 
 650 parameters for outputting a list of those records.
 
 652 Returns a rendered version (actually an instance of
 
 653 L<SL::Presenter::EscapedText>) of all the lists.
 
 655 The order in which the records are grouped is:
 
 659 =item * sales quotations
 
 663 =item * sales delivery orders
 
 665 =item * sales invoices
 
 667 =item * AR transactions
 
 669 =item * requests for quotations
 
 671 =item * purchase orders
 
 673 =item * purchase delivery orders
 
 675 =item * purchase invoices
 
 677 =item * AP transactions
 
 679 =item * GL transactions
 
 681 =item * SEPA collections
 
 683 =item * SEPA transfers
 
 687 Objects of unknown types are skipped.
 
 689 Parameters are passed to C<record_list> include C<with_objects> and
 
 690 C<edit_record_links>.
 
 692 =item C<record_list $list, %params>
 
 694 Returns a rendered version (actually an instance of
 
 695 L<SL::Presenter::EscapedText>) of a list of records. This list
 
 696 consists of a heading and a tabular representation of the list.
 
 698 The parameters include:
 
 704 Mandatory. The title to use in the heading. Must already be
 
 709 Mandatory. An array reference of column specs to output. Each column
 
 710 spec can be either an array reference or a hash reference.
 
 712 If a column spec is an array reference then the first element is the
 
 713 column's name shown in the table header. It must already be translated.
 
 715 The second element can be either a string or a code reference. A
 
 716 string is taken as the name of a function to call on the Rose::DB
 
 717 object for the current row. Its return value is formatted depending on
 
 718 the column's type (e.g. dates are output as the user expects them,
 
 719 floating point numbers are rounded to two decimal places and
 
 720 right-aligned etc). If it is a code reference then that code is called
 
 721 with the object as the first argument. Its return value should be an
 
 722 instance of L<SL::Presenter::EscapedText> and contain the rendered
 
 723 representation of the content to output.
 
 725 The third element, if present, can be a link to which the column will
 
 728 If the column spec is a hash reference then the same arguments are
 
 729 expected. The corresponding hash keys are C<title>, C<data> and
 
 732 =item C<with_columns>
 
 734 Can be set by the caller to indicate additional columns to
 
 735 be listed. Currently supported:
 
 739 =item C<record_link_destination>
 
 741 The record link destination. Requires that the records to be listed have
 
 742 been retrieved via the L<SL::DB::Helper::LinkedRecords> helper.
 
 746 =item C<edit_record_links>
 
 748 If trueish additional controls will be rendered that allow the user to
 
 749 remove and add record links. Requires that the records to be listed have
 
 750 been retrieved via the L<SL::DB::Helper::LinkedRecords> helper.
 
 762 Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>