Verzeichnis SL/DB/Helpers in SL/DB/Helper umbenannt (Konsistenz)
authorMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 30 Dec 2010 15:56:32 +0000 (16:56 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 30 Dec 2010 15:56:32 +0000 (16:56 +0100)
25 files changed:
SL/DB/Helper/ALL.pm [new file with mode: 0644]
SL/DB/Helper/Attr.pm [new file with mode: 0644]
SL/DB/Helper/ConventionManager.pm [new file with mode: 0644]
SL/DB/Helper/Manager.pm [new file with mode: 0644]
SL/DB/Helper/Mappings.pm [new file with mode: 0644]
SL/DB/Helper/Metadata.pm [new file with mode: 0644]
SL/DB/Helper/Sorted.pm [new file with mode: 0644]
SL/DB/Helpers/ALL.pm [deleted file]
SL/DB/Helpers/Attr.pm [deleted file]
SL/DB/Helpers/ConventionManager.pm [deleted file]
SL/DB/Helpers/Manager.pm [deleted file]
SL/DB/Helpers/Mappings.pm [deleted file]
SL/DB/Helpers/Metadata.pm [deleted file]
SL/DB/Helpers/Sorted.pm [deleted file]
SL/DB/Manager/DeliveryOrder.pm
SL/DB/Manager/Employee.pm
SL/DB/Manager/Invoice.pm
SL/DB/Manager/Order.pm
SL/DB/Manager/Part.pm
SL/DB/Manager/PurchaseInvoice.pm
SL/DB/Manager/TransferType.pm
SL/DB/Object.pm
bin/mozilla/common.pl
scripts/rose_auto_create_model.pl
t/helper/mapping.t

diff --git a/SL/DB/Helper/ALL.pm b/SL/DB/Helper/ALL.pm
new file mode 100644 (file)
index 0000000..50f4b3d
--- /dev/null
@@ -0,0 +1,107 @@
+package SL::DB::Helper::ALL;
+
+use strict;
+
+use SL::DB::AccTrans;
+use SL::DB::AccTransaction;
+use SL::DB::Assembly;
+use SL::DB::AuditTrail;
+use SL::DB::BankAccount;
+use SL::DB::Bin;
+use SL::DB::Buchungsgruppe;
+use SL::DB::Business;
+use SL::DB::Chart;
+use SL::DB::Contact;
+use SL::DB::CustomVariable;
+use SL::DB::CustomVariableConfig;
+use SL::DB::CustomVariableValidity;
+use SL::DB::Customer;
+use SL::DB::CustomerTax;
+use SL::DB::Datev;
+use SL::DB::Default;
+use SL::DB::DeliveryOrder;
+use SL::DB::DeliveryOrderItem;
+use SL::DB::DeliveryOrderItemsStock;
+use SL::DB::Department;
+use SL::DB::DptTrans;
+use SL::DB::Draft;
+use SL::DB::Dunning;
+use SL::DB::DunningConfig;
+use SL::DB::Employee;
+use SL::DB::Exchangerate;
+use SL::DB::Finanzamt;
+use SL::DB::FollowUp;
+use SL::DB::FollowUpAccess;
+use SL::DB::FollowUpLink;
+use SL::DB::GLTransaction;
+use SL::DB::GenericTranslation;
+use SL::DB::Gifi;
+use SL::DB::History;
+use SL::DB::Inventory;
+use SL::DB::Invoice;
+use SL::DB::InvoiceItem;
+use SL::DB::Language;
+use SL::DB::License;
+use SL::DB::LicenseInvoice;
+use SL::DB::MakeModel;
+use SL::DB::Note;
+use SL::DB::Order;
+use SL::DB::OrderItem;
+use SL::DB::Part;
+use SL::DB::PartsGroup;
+use SL::DB::PartsTax;
+use SL::DB::PaymentTerm;
+use SL::DB::PriceFactor;
+use SL::DB::Pricegroup;
+use SL::DB::Prices;
+use SL::DB::Printer;
+use SL::DB::Project;
+use SL::DB::PurchaseInvoice;
+use SL::DB::RMA;
+use SL::DB::RMAItem;
+use SL::DB::RecordLink;
+use SL::DB::SchemaInfo;
+use SL::DB::SepaExport;
+use SL::DB::SepaExportItem;
+use SL::DB::Shipto;
+use SL::DB::Status;
+use SL::DB::Tax;
+use SL::DB::TaxKey;
+use SL::DB::TaxZone;
+use SL::DB::TodoUserConfig;
+use SL::DB::TransferType;
+use SL::DB::Translation;
+use SL::DB::TranslationPaymentTerm;
+use SL::DB::Unit;
+use SL::DB::UnitsLanguage;
+use SL::DB::Vendor;
+use SL::DB::VendorTax;
+use SL::DB::Warehouse;
+
+1;
+
+__END__
+
+=pod
+
+=head1 NAME
+
+SL::DB::Helper::ALL: Dependency-only package for all SL::DB::* modules
+
+=head1 SYNOPSIS
+
+  use SL::DB::Helper::ALL;
+
+=head1 DESCRIPTION
+
+This module depends on all modules in SL/DB/*.pm for the convenience
+of being able to write a simple \C<use SL::DB::Helper::ALL> and
+having everything loaded. This is supposed to be used only in the
+Lx-Office console. Normal modules should C<use> only the modules they
+actually need.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
diff --git a/SL/DB/Helper/Attr.pm b/SL/DB/Helper/Attr.pm
new file mode 100644 (file)
index 0000000..463bfd6
--- /dev/null
@@ -0,0 +1,135 @@
+package SL::DB::Helper::Attr;
+
+use strict;
+
+sub auto_make {
+  my ($package, %params) = @_;
+
+  for my $col ($package->meta->columns) {
+    next if $col->primary_key_position; # don't make attr helper for primary keys
+    _make_by_type($package, $col->name, $col->type);
+  }
+
+  return $package;
+}
+
+sub make {
+  my ($package, %params) = @_;
+
+  for my $name (keys %params) {
+    my @types = ref $params{$name} eq 'ARRAY' ? @{ $params{$name} } : ($params{$name});
+    for my $type (@types) {
+      _make_by_type($package, $name, $type);
+    }
+  }
+  return $package;
+}
+
+
+
+sub _make_by_type {
+  my ($package, $name, $type) = @_;
+  _as_number ($package, $name, places => -2) if $type =~ /numeric | real | float/xi;
+  _as_percent($package, $name, places =>  0) if $type =~ /numeric | real | float/xi;
+  _as_number ($package, $name, places =>  0) if $type =~ /int/xi;
+  _as_date   ($package, $name)               if $type =~ /date | timestamp/xi;
+}
+
+sub _as_number {
+  my $package     = shift;
+  my $attribute   = shift;
+  my %params      = @_;
+
+  $params{places} = 2 if !defined($params{places});
+
+  no strict 'refs';
+  *{ $package . '::' . $attribute . '_as_number' } = sub {
+    my ($self, $string) = @_;
+
+    $self->$attribute($::form->parse_amount(\%::myconfig, $string)) if @_ > 1;
+
+    return $::form->format_amount(\%::myconfig, $self->$attribute, $params{places});
+  };
+}
+
+sub _as_percent {
+  my $package     = shift;
+  my $attribute   = shift;
+  my %params      = @_;
+
+  $params{places} = 2 if !defined($params{places});
+
+  no strict 'refs';
+  *{ $package . '::' . $attribute . '_as_percent' } = sub {
+    my ($self, $string) = @_;
+
+    $self->$attribute($::form->parse_amount(\%::myconfig, $string) / 100) if @_ > 1;
+
+    return $::form->format_amount(\%::myconfig, 100 * $self->$attribute, $params{places});
+  };
+
+  return 1;
+}
+
+sub _as_date {
+  my $package     = shift;
+  my $attribute   = shift;
+  my %params      = @_;
+
+  no strict 'refs';
+  *{ $package . '::' . $attribute . '_as_date' } = sub {
+    my ($self, $string) = @_;
+
+    if (@_ > 1) {
+      if ($string) {
+        my ($yy, $mm, $dd) = $::locale->parse_date(\%::myconfig, $string);
+        $self->$attribute(DateTime->new(year => $yy, month => $mm, day => $dd));
+      } else {
+        $self->$attribute(undef);
+      }
+    }
+
+    return $self->$attribute
+      ? $::locale->reformat_date(
+          { dateformat => 'yy-mm-dd' },
+          ( $self->$attribute eq 'now'
+             ? DateTime->now
+             : $self->$attribute
+          )->ymd,
+          $::myconfig{dateformat}
+        )
+      : undef;
+  };
+
+  return 1;
+}
+
+1;
+
+
+1;
+
+__END__
+
+=head1 NAME
+
+SL::DB::Helper::Attr - attribute helpers
+
+=head1 SYNOPSIS
+
+  use SL::DB::Helper::Attr;
+  SL::DB::Helper::Attr::make($class,
+    method_name => 'numeric(15,5)',
+    datemethod  => 'date'
+  );
+  SL::DB::Helper::Attr::auto_make($class);
+
+=head1 DESCRIPTION
+
+=head1 FUNCTIONS
+
+=head1 BUGS
+
+=head1 AUTHOR
+
+=cut
diff --git a/SL/DB/Helper/ConventionManager.pm b/SL/DB/Helper/ConventionManager.pm
new file mode 100644 (file)
index 0000000..35c6b1e
--- /dev/null
@@ -0,0 +1,29 @@
+package SL::DB::Helper::ConventionManager;
+
+use strict;
+
+use Rose::DB::Object::ConventionManager;
+
+use base qw(Rose::DB::Object::ConventionManager);
+
+sub auto_manager_class_name {
+  my $self         = shift;
+  my $object_class = shift || $self->meta->class;
+
+  my @parts        = split m/::/, $object_class;
+  my $last         = pop @parts;
+
+  return join('::', @parts, 'Manager', $last);
+}
+
+# Base name used for 'make_manager_class', e.g. 'get_all',
+# 'update_all'
+sub auto_manager_base_name {
+  return 'all';
+}
+
+sub auto_manager_base_class {
+  return 'SL::DB::Helper::Manager';
+}
+
+1;
diff --git a/SL/DB/Helper/Manager.pm b/SL/DB/Helper/Manager.pm
new file mode 100644 (file)
index 0000000..5290533
--- /dev/null
@@ -0,0 +1,27 @@
+package SL::DB::Helper::Manager;
+
+use strict;
+
+use Rose::DB::Object::Manager;
+use base qw(Rose::DB::Object::Manager);
+
+sub make_manager_methods {
+  my $class  = shift;
+  my @params = scalar(@_) ? @_ : qw(all);
+  return $class->SUPER::make_manager_methods(@params);
+}
+
+sub find_by {
+  my $class = shift;
+
+  return if !@_;
+  return $class->get_all(query => [ @_ ], limit => 1)->[0];
+}
+
+sub get_first {
+  shift->get_all(
+    limit => 1,
+  )->[0];
+}
+
+1;
diff --git a/SL/DB/Helper/Mappings.pm b/SL/DB/Helper/Mappings.pm
new file mode 100644 (file)
index 0000000..48c4863
--- /dev/null
@@ -0,0 +1,187 @@
+package SL::DB::Helpers::Mappings;
+
+use utf8;
+use strict;
+
+# these will not be managed as Rose::DB models, because they are not normalized,
+# significant changes are needed to get them done, or they were done by CRM.
+my @lxoffice_blacklist_permanent = qw(
+  leads
+);
+
+# these are not managed _yet_, but will hopefully at some point.
+# if you are confident that one of these works, remove it here.
+my @lxoffice_blacklist_temp = qw(
+);
+
+my @lxoffice_blacklist = (@lxoffice_blacklist_permanent, @lxoffice_blacklist_temp);
+
+# map table names to their models.
+# unlike rails we have no singular<->plural magic.
+# remeber: tables should be named as the plural of the model name.
+my %lxoffice_package_names = (
+  acc_trans                      => 'acc_transaction',
+  audittrail                     => 'audit_trail',
+  ar                             => 'invoice',
+  ap                             => 'purchase_invoice',
+  bank_accounts                  => 'bank_account',
+  buchungsgruppen                => 'buchungsgruppe',
+  contacts                       => 'contact',
+  custom_variable_configs        => 'custom_variable_config',
+  custom_variables               => 'custom_variable',
+  custom_variables_validity      => 'custom_variable_validity',
+  customertax                    => 'customer_tax',
+  datev                          => 'datev',
+  defaults                       => 'default',
+  delivery_orders                => 'delivery_order',
+  delivery_order_items           => 'delivery_order_item',
+  department                     => 'department',
+  dpt_trans                      => 'dpt_trans',
+  drafts                         => 'draft',
+  dunning                        => 'dunning',
+  dunning_config                 => 'dunning_config',
+  employee                       => 'employee',
+  exchangerate                   => 'exchangerate',
+  finanzamt                      => 'finanzamt',
+  follow_up_access               => 'follow_up_access',
+  follow_up_links                => 'follow_up_link',
+  follow_ups                     => 'follow_up',
+  generic_translations           => 'generic_translation',
+  gifi                           => 'gifi',
+  gl                             => 'GLTransaction',
+  history_erp                    => 'history',
+  inventory                      => 'inventory',
+  invoice                        => 'invoice_item',
+  language                       => 'language',
+  license                        => 'license',
+  licenseinvoice                 => 'license_invoice',
+  makemodel                      => 'make_model',
+  notes                          => 'note',
+  orderitems                     => 'order_item',
+  oe                             => 'order',
+  parts                          => 'part',
+  partsgroup                     => 'parts_group',
+  partstax                       => 'parts_tax',
+  payment_terms                  => 'payment_term',
+  prices                         => 'prices',
+  price_factors                  => 'price_factor',
+  pricegroup                     => 'pricegroup',
+  printers                       => 'Printer',
+  record_links                   => 'record_link',
+  rma                            => 'RMA',
+  rmaitems                       => 'RMA_item',
+  sepa_export                    => 'sepa_export',
+  sepa_export_items              => 'sepa_export_item',
+  schema_info                    => 'schema_info',
+  status                         => 'status',
+  tax                            => 'tax',
+  taxkeys                        => 'tax_key',
+  tax_zones                      => 'tax_zone',
+  todo_user_config               => 'todo_user_config',
+  translation                    => 'translation',
+  translation_payment_terms      => 'translation_payment_term',
+  units                          => 'unit',
+  units_language                 => 'units_language',
+  vendortax                      => 'vendor_tax',
+);
+
+sub get_blacklist {
+  return LXOFFICE => \@lxoffice_blacklist;
+}
+
+sub get_package_names {
+  return LXOFFICE => \%lxoffice_package_names;
+}
+
+sub db {
+  my $string = $_[0];
+  my $lookup = $lxoffice_package_names{$_[0]} ||
+      plurify($lxoffice_package_names{singlify($_[0])});
+
+  for my $thing ($string, $lookup) {
+
+    # best guess? its already the name. like part. camelize it first
+    my $class = "SL::DB::" . camelify($thing);
+    return $class if defined *{ $class. '::' };
+
+    # next, someone wants a manager and pluralized.
+    my $manager = "SL::DB::Manager::" . singlify(camelify($thing));
+    return $manager if defined *{ $manager . '::' };
+  }
+
+  die "Can't resolve '$string' as a database model, sorry. Did you perhaps forgot to load it?";
+}
+
+sub camelify {
+  my ($str) = @_;
+  $str =~ s/_+(.)/uc($1)/ge;
+  ucfirst $str;
+}
+
+sub snakify {
+  my ($str) = @_;
+  $str =~ s/(?<!^)\u(.)/'_' . lc($1)/ge;
+  lcfirst $str;
+}
+
+sub plurify {
+  my ($str) = @_;
+  $str . 's';
+}
+
+sub singlify {
+  my ($str) = @_;
+  local $/ = 's';
+  chomp $str;
+  $str;
+}
+
+1;
+
+__END__
+
+=head1 NAME
+
+SL::DB::Helpers::Mappings - Rose Table <-> Model mapping information
+
+=head1 SYNOPSIS
+
+  use SL::DB::Helpers::Mappings qw(@blacklist %table2model);
+
+=head1 DESCRIPTION
+
+This modul stores table <-> model mappings used by the
+L<scripts/rose_auto_create_model.pl> script.  If you add a new table that has
+custom mappings, add it here.
+
+=head2 db
+
+A special function provided here is E<db>. Without it you'd have to write:
+
+  my $part = SL::DB::Part->new(id => 1234);
+  my @all_parts = SL::DB::Manager::Part->get_all;
+
+with them it becomes:
+
+  my $part = db('part')->new(id => 123);
+  my @all_parts = db('parts')->get_all;
+
+You don't have to care about add that SL::DB:: incantation anymore. Also, a
+simple s at the end will get you the associated Manager class.
+
+db is written to try to make sense of what you give it, but if all fails, it
+will die with an error.
+
+=head1 BUGS
+
+nothing yet
+
+=head1 SEE ALSO
+
+L<scripts/rose_auto_create_model.pl>
+
+=head1 AUTHOR
+
+Sven Schöling <s.schoeling@linet-services.de>
+
+=cut
diff --git a/SL/DB/Helper/Metadata.pm b/SL/DB/Helper/Metadata.pm
new file mode 100644 (file)
index 0000000..9ce1f11
--- /dev/null
@@ -0,0 +1,34 @@
+package SL::DB::Helper::Metadata;
+
+use strict;
+
+use Rose::DB::Object::Metadata;
+use SL::DB::Helper::ConventionManager;
+
+use base qw(Rose::DB::Object::Metadata);
+
+sub convention_manager_class {
+  return 'SL::DB::Helper::ConventionManager';
+}
+
+sub default_manager_base_class {
+  return 'SL::DB::Helper::Manager';
+}
+
+sub initialize {
+  my $self = shift;
+  $self->make_attr_auto_helpers unless $self->is_initialized;
+  $self->SUPER::initialize(@_);
+}
+
+sub make_attr_helpers {
+  my ($self, %params) = @_;
+  SL::DB::Helper::Attr::make($self->class, %params);
+}
+
+sub make_attr_auto_helpers {
+  my ($self) = @_;
+  SL::DB::Helper::Attr::auto_make($self->class);
+}
+
+1;
diff --git a/SL/DB/Helper/Sorted.pm b/SL/DB/Helper/Sorted.pm
new file mode 100644 (file)
index 0000000..9442c84
--- /dev/null
@@ -0,0 +1,226 @@
+package SL::DB::Helper::Sorted;
+
+use strict;
+
+require Exporter;
+our @ISA    = qw(Exporter);
+our @EXPORT = qw(get_all_sorted make_sort_string);
+
+my %sort_spec;
+
+sub make_sort_string {
+  my ($class, %params) = @_;
+
+  my $sort_spec        = _get_sort_spec($class);
+
+  my $sort_dir         = defined($params{sort_dir}) ? $params{sort_dir} * 1 : $sort_spec->{default}->[1];
+  my $sort_dir_str     = $sort_dir ? 'ASC' : 'DESC';
+
+  my $sort_by          = $params{sort_by};
+  $sort_by             = $sort_spec->{default}->[0] unless $sort_spec->{columns}->{$sort_by};
+
+  my $nulls_str        = '';
+  if ($sort_spec->{nulls}) {
+    $nulls_str = ref($sort_spec->{nulls}) ? ($sort_spec->{nulls}->{$sort_by} || $sort_spec->{nulls}->{default}) : $sort_spec->{nulls};
+    $nulls_str = " NULLS ${nulls_str}" if $nulls_str;
+  }
+
+  my $sort_by_str = $sort_spec->{columns}->{$sort_by};
+  $sort_by_str    = [ $sort_by_str ] unless ref($sort_by_str) eq 'ARRAY';
+  $sort_by_str    = join(', ', map { "${_} ${sort_dir_str}${nulls_str}" } @{ $sort_by_str });
+
+  return wantarray ? ($sort_by, $sort_dir, $sort_by_str) : $sort_by_str;
+}
+
+sub get_all_sorted {
+  my ($class, %params) = @_;
+  my $sort_str         = $class->make_sort_string(sort_by => delete($params{sort_by}), sort_dir => delete($params{sort_dir}));
+
+  return $class->get_all(sort_by => $sort_str, %params);
+}
+
+sub _get_sort_spec {
+  my ($class) = @_;
+  return $sort_spec{$class} ||= _make_sort_spec($class);
+}
+
+sub _make_sort_spec {
+  my ($class) = @_;
+
+  my %sort_spec = $class->_sort_spec if defined &{ "${class}::_sort_spec" };
+
+  my $meta = $class->object_class->meta;
+
+  if (!$sort_spec{default}) {
+    my @primary_keys = $meta->primary_key;
+    $sort_spec{default} = [ "" . $primary_keys[0], 1 ];
+  }
+
+  $sort_spec{columns} ||= { SIMPLE => [ map { "$_" } $meta->columns ] };
+
+  if ($sort_spec{columns}->{SIMPLE}) {
+    my $table = $meta->table;
+
+    if (!ref($sort_spec{columns}->{SIMPLE}) && ($sort_spec{columns}->{SIMPLE} eq 'ALL')) {
+      map { $sort_spec{columns}->{"$_"} ||= "${table}.${_}"} @{ $meta->columns };
+      delete $sort_spec{columns}->{SIMPLE};
+    } else {
+      map { $sort_spec{columns}->{$_} = "${table}.${_}" } @{ delete($sort_spec{columns}->{SIMPLE}) };
+    }
+  }
+
+  return \%sort_spec;
+}
+
+1;
+
+__END__
+
+=encoding utf8
+
+=head1 NAME
+
+SL::DB::Helper::Sorted - Mixin for a manager class that handles
+sorting of database records
+
+=head1 SYNOPSIS
+
+  package SL::DB::Manager::Message;
+
+  use SL::DB::Helper::Sorted;
+
+  sub _sort_spec {
+    return ( columns => { recipient_id => [ 'CASE
+                                             WHEN recipient_group_id IS NULL THEN lower(recipient.name)
+                                             ELSE                                 lower(recipient_group.name)
+                                             END',                                      ],
+                          sender_id    => [ 'lower(sender.name)',                       ],
+                          created_at   => [ 'created_at',                               ],
+                          subject      => [ 'lower(subject)',                           ],
+                          status       => [ 'NOT COALESCE(unread, FALSE)', 'created_at' ],
+                        },
+             default => [ 'status', 1 ],
+             nulls   => { default => 'LAST',
+                          subject => 'FIRST',
+                        }
+           );
+  }
+
+  package SL::Controller::Message;
+
+  sub action_list {
+    my $messages = SL::DB::Manager::Message->get_all_sorted(sort_by  => $::form->{sort_by},
+                                                            sort_dir => $::form->{sort_dir});
+  }
+
+=head1 CLASS FUNCTIONS
+
+=over 4
+
+=item C<make_sort_string %params>
+
+Evaluates C<$params{sort_by}> and C<$params{sort_dir}> and returns an
+SQL string suitable for sorting. The package this package is mixed
+into has to provide a method L</_sort_spec> that returns a hash whose
+structure is explained below. That hash is authoritive in which
+columns may be sorted, which column to sort by by default and how to
+handle C<NULL> values.
+
+Returns the SQL string in scalar context. In array context it returns
+three values: the actual column it sorts by (suitable for another call
+to L</make_sort_string>), the actual sort direction (either 0 or 1)
+and the SQL string.
+
+=item C<get_all_sorted %params>
+
+Returns C<< $class->get_all >> with C<sort_by> set to the value
+returned by c<< $class->make_sort_string(%params) >>.
+
+=back
+
+=head1 CLASS FUNCTIONS PROVIDED BY THE MIXING PACKAGE
+
+=over 4
+
+=item C<_sort_spec>
+
+This method is actually not part of this package but can be provided
+by the package this helper is mixed into. If it isn't then all columns
+of the corresponding table (as returned by the model's meta data) will
+be eligible for sorting.
+
+Returns a hash with the following keys:
+
+=over 2
+
+=item C<default>
+
+A two-element array containing the name and direction by which to sort
+in default cases. Example:
+
+  default => [ 'name', 1 ],
+
+Defaults to the table's primary key column (the first column if the
+primary key is composited).
+
+=item C<columns>
+
+A hash reference. Its keys are column names, and its values are SQL
+strings by which to sort. Example:
+
+  columns => { SIMPLE                  => [ 'transaction_description', 'orddate' ],
+               the_date                => 'CASE WHEN oe.quotation THEN oe.quodate ELSE oe.orddate END',
+               customer_name           => 'lower(customer.name)',
+             },
+
+If sorting by a column is requested that is not a key in this hash
+then the default column name will be used.
+
+The value can be either a scalar or an array reference. If it's the
+latter then both the sort direction as well as the null handling will
+be appended to each of its members.
+
+The special key C<SIMPLE> can be a scalar or an array reference. If it
+is an array reference then it contains column names that are mapped
+1:1 onto the table's columns. If it is the scalar 'ALL' then all
+columns in that model's meta data are mapped 1:1 unless the C<columns>
+hash already contains a key for that column.
+
+If C<columns> is missing then all columns of the model will be
+eligible for sorting. The list of columns is looked up in the model's
+meta data.
+
+=item C<nulls>
+
+Either a scalar or a hash reference determining where C<NULL> values
+will be sorted. If undefined then the decision is left to the
+database.
+
+If it is a scalar then all the same value will be used for all
+classes. The value is either C<FIRST> or C<LAST>.
+
+If it is a hash reference then its keys are column names (not SQL
+names). The values are either C<FIRST> or C<LAST>. If a column name is
+not found in this hash then the special keu C<default> will be looked
+up and used if it is found.
+
+Example:
+
+  nulls => { transaction_description => 'FIRST',
+             customer_name           => 'FIRST',
+             default                 => 'LAST',
+           },
+
+=back
+
+=back
+
+=head1 BUGS
+
+Nothing here yet.
+
+=head1 AUTHOR
+
+Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
+
+=cut
diff --git a/SL/DB/Helpers/ALL.pm b/SL/DB/Helpers/ALL.pm
deleted file mode 100644 (file)
index 16184c5..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-package SL::DB::Helpers::ALL;
-
-use strict;
-
-use SL::DB::AccTrans;
-use SL::DB::AccTransaction;
-use SL::DB::Assembly;
-use SL::DB::AuditTrail;
-use SL::DB::BankAccount;
-use SL::DB::Bin;
-use SL::DB::Buchungsgruppe;
-use SL::DB::Business;
-use SL::DB::Chart;
-use SL::DB::Contact;
-use SL::DB::CustomVariable;
-use SL::DB::CustomVariableConfig;
-use SL::DB::CustomVariableValidity;
-use SL::DB::Customer;
-use SL::DB::CustomerTax;
-use SL::DB::Datev;
-use SL::DB::Default;
-use SL::DB::DeliveryOrder;
-use SL::DB::DeliveryOrderItem;
-use SL::DB::DeliveryOrderItemsStock;
-use SL::DB::Department;
-use SL::DB::DptTrans;
-use SL::DB::Draft;
-use SL::DB::Dunning;
-use SL::DB::DunningConfig;
-use SL::DB::Employee;
-use SL::DB::Exchangerate;
-use SL::DB::Finanzamt;
-use SL::DB::FollowUp;
-use SL::DB::FollowUpAccess;
-use SL::DB::FollowUpLink;
-use SL::DB::GLTransaction;
-use SL::DB::GenericTranslation;
-use SL::DB::Gifi;
-use SL::DB::History;
-use SL::DB::Inventory;
-use SL::DB::Invoice;
-use SL::DB::InvoiceItem;
-use SL::DB::Language;
-use SL::DB::License;
-use SL::DB::LicenseInvoice;
-use SL::DB::MakeModel;
-use SL::DB::Note;
-use SL::DB::Order;
-use SL::DB::OrderItem;
-use SL::DB::Part;
-use SL::DB::PartsGroup;
-use SL::DB::PartsTax;
-use SL::DB::PaymentTerm;
-use SL::DB::PriceFactor;
-use SL::DB::Pricegroup;
-use SL::DB::Prices;
-use SL::DB::Printer;
-use SL::DB::Project;
-use SL::DB::PurchaseInvoice;
-use SL::DB::RMA;
-use SL::DB::RMAItem;
-use SL::DB::RecordLink;
-use SL::DB::SchemaInfo;
-use SL::DB::SepaExport;
-use SL::DB::SepaExportItem;
-use SL::DB::Shipto;
-use SL::DB::Status;
-use SL::DB::Tax;
-use SL::DB::TaxKey;
-use SL::DB::TaxZone;
-use SL::DB::TodoUserConfig;
-use SL::DB::TransferType;
-use SL::DB::Translation;
-use SL::DB::TranslationPaymentTerm;
-use SL::DB::Unit;
-use SL::DB::UnitsLanguage;
-use SL::DB::Vendor;
-use SL::DB::VendorTax;
-use SL::DB::Warehouse;
-
-1;
-
-__END__
-
-=pod
-
-=head1 NAME
-
-SL::DB::Helpers::ALL: Dependency-only package for all SL::DB::* modules
-
-=head1 SYNOPSIS
-
-  use SL::DB::Helpers::ALL;
-
-=head1 DESCRIPTION
-
-This module depends on all modules in SL/DB/*.pm for the convenience
-of being able to write a simple \C<use SL::DB::Helpers::ALL> and
-having everything loaded. This is supposed to be used only in the
-Lx-Office console. Normal modules should C<use> only the modules they
-actually need.
-
-=head1 AUTHOR
-
-Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
-
-=cut
diff --git a/SL/DB/Helpers/Attr.pm b/SL/DB/Helpers/Attr.pm
deleted file mode 100644 (file)
index 01c97c2..0000000
+++ /dev/null
@@ -1,135 +0,0 @@
-package SL::DB::Helper::Attr;
-
-use strict;
-
-sub auto_make {
-  my ($package, %params) = @_;
-
-  for my $col ($package->meta->columns) {
-    next if $col->primary_key_position; # don't make attr helper for primary keys
-    _make_by_type($package, $col->name, $col->type);
-  }
-
-  return $package;
-}
-
-sub make {
-  my ($package, %params) = @_;
-
-  for my $name (keys %params) {
-    my @types = ref $params{$name} eq 'ARRAY' ? @{ $params{$name} } : ($params{$name});
-    for my $type (@types) {
-      _make_by_type($package, $name, $type);
-    }
-  }
-  return $package;
-}
-
-
-
-sub _make_by_type {
-  my ($package, $name, $type) = @_;
-  _as_number ($package, $name, places => -2) if $type =~ /numeric | real | float/xi;
-  _as_percent($package, $name, places =>  0) if $type =~ /numeric | real | float/xi;
-  _as_number ($package, $name, places =>  0) if $type =~ /int/xi;
-  _as_date   ($package, $name)               if $type =~ /date | timestamp/xi;
-}
-
-sub _as_number {
-  my $package     = shift;
-  my $attribute   = shift;
-  my %params      = @_;
-
-  $params{places} = 2 if !defined($params{places});
-
-  no strict 'refs';
-  *{ $package . '::' . $attribute . '_as_number' } = sub {
-    my ($self, $string) = @_;
-
-    $self->$attribute($::form->parse_amount(\%::myconfig, $string)) if @_ > 1;
-
-    return $::form->format_amount(\%::myconfig, $self->$attribute, $params{places});
-  };
-}
-
-sub _as_percent {
-  my $package     = shift;
-  my $attribute   = shift;
-  my %params      = @_;
-
-  $params{places} = 2 if !defined($params{places});
-
-  no strict 'refs';
-  *{ $package . '::' . $attribute . '_as_percent' } = sub {
-    my ($self, $string) = @_;
-
-    $self->$attribute($::form->parse_amount(\%::myconfig, $string) / 100) if @_ > 1;
-
-    return $::form->format_amount(\%::myconfig, 100 * $self->$attribute, $params{places});
-  };
-
-  return 1;
-}
-
-sub _as_date {
-  my $package     = shift;
-  my $attribute   = shift;
-  my %params      = @_;
-
-  no strict 'refs';
-  *{ $package . '::' . $attribute . '_as_date' } = sub {
-    my ($self, $string) = @_;
-
-    if (@_ > 1) {
-      if ($string) {
-        my ($yy, $mm, $dd) = $::locale->parse_date(\%::myconfig, $string);
-        $self->$attribute(DateTime->new(year => $yy, month => $mm, day => $dd));
-      } else {
-        $self->$attribute(undef);
-      }
-    }
-
-    return $self->$attribute
-      ? $::locale->reformat_date(
-          { dateformat => 'yy-mm-dd' },
-          ( $self->$attribute eq 'now'
-             ? DateTime->now
-             : $self->$attribute
-          )->ymd,
-          $::myconfig{dateformat}
-        )
-      : undef;
-  };
-
-  return 1;
-}
-
-1;
-
-
-1;
-
-__END__
-
-=head1 NAME
-
-SL::DB::Helpers::Attr - attribute helpers
-
-=head1 SYNOPSIS
-
-  use SL::DB::Helpers::Attr;
-  SL::DB::Helpers::Attr::make($class,
-    method_name => 'numeric(15,5)',
-    datemethod  => 'date'
-  );
-  SL::DB::Helpers::Attr::auto_make($class);
-
-=head1 DESCRIPTION
-
-=head1 FUNCTIONS
-
-=head1 BUGS
-
-=head1 AUTHOR
-
-=cut
diff --git a/SL/DB/Helpers/ConventionManager.pm b/SL/DB/Helpers/ConventionManager.pm
deleted file mode 100644 (file)
index 1d9cd84..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-package SL::DB::Helpers::ConventionManager;
-
-use strict;
-
-use Rose::DB::Object::ConventionManager;
-
-use base qw(Rose::DB::Object::ConventionManager);
-
-sub auto_manager_class_name {
-  my $self         = shift;
-  my $object_class = shift || $self->meta->class;
-
-  my @parts        = split m/::/, $object_class;
-  my $last         = pop @parts;
-
-  return join('::', @parts, 'Manager', $last);
-}
-
-# Base name used for 'make_manager_class', e.g. 'get_all',
-# 'update_all'
-sub auto_manager_base_name {
-  return 'all';
-}
-
-sub auto_manager_base_class {
-  return 'SL::DB::Helpers::Manager';
-}
-
-1;
diff --git a/SL/DB/Helpers/Manager.pm b/SL/DB/Helpers/Manager.pm
deleted file mode 100644 (file)
index 4399f5d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-package SL::DB::Helpers::Manager;
-
-use strict;
-
-use Rose::DB::Object::Manager;
-use base qw(Rose::DB::Object::Manager);
-
-sub make_manager_methods {
-  my $class  = shift;
-  my @params = scalar(@_) ? @_ : qw(all);
-  return $class->SUPER::make_manager_methods(@params);
-}
-
-sub find_by {
-  my $class = shift;
-
-  return if !@_;
-  return $class->get_all(query => [ @_ ], limit => 1)->[0];
-}
-
-sub get_first {
-  shift->get_all(
-    limit => 1,
-  )->[0];
-}
-
-1;
diff --git a/SL/DB/Helpers/Mappings.pm b/SL/DB/Helpers/Mappings.pm
deleted file mode 100644 (file)
index 48c4863..0000000
+++ /dev/null
@@ -1,187 +0,0 @@
-package SL::DB::Helpers::Mappings;
-
-use utf8;
-use strict;
-
-# these will not be managed as Rose::DB models, because they are not normalized,
-# significant changes are needed to get them done, or they were done by CRM.
-my @lxoffice_blacklist_permanent = qw(
-  leads
-);
-
-# these are not managed _yet_, but will hopefully at some point.
-# if you are confident that one of these works, remove it here.
-my @lxoffice_blacklist_temp = qw(
-);
-
-my @lxoffice_blacklist = (@lxoffice_blacklist_permanent, @lxoffice_blacklist_temp);
-
-# map table names to their models.
-# unlike rails we have no singular<->plural magic.
-# remeber: tables should be named as the plural of the model name.
-my %lxoffice_package_names = (
-  acc_trans                      => 'acc_transaction',
-  audittrail                     => 'audit_trail',
-  ar                             => 'invoice',
-  ap                             => 'purchase_invoice',
-  bank_accounts                  => 'bank_account',
-  buchungsgruppen                => 'buchungsgruppe',
-  contacts                       => 'contact',
-  custom_variable_configs        => 'custom_variable_config',
-  custom_variables               => 'custom_variable',
-  custom_variables_validity      => 'custom_variable_validity',
-  customertax                    => 'customer_tax',
-  datev                          => 'datev',
-  defaults                       => 'default',
-  delivery_orders                => 'delivery_order',
-  delivery_order_items           => 'delivery_order_item',
-  department                     => 'department',
-  dpt_trans                      => 'dpt_trans',
-  drafts                         => 'draft',
-  dunning                        => 'dunning',
-  dunning_config                 => 'dunning_config',
-  employee                       => 'employee',
-  exchangerate                   => 'exchangerate',
-  finanzamt                      => 'finanzamt',
-  follow_up_access               => 'follow_up_access',
-  follow_up_links                => 'follow_up_link',
-  follow_ups                     => 'follow_up',
-  generic_translations           => 'generic_translation',
-  gifi                           => 'gifi',
-  gl                             => 'GLTransaction',
-  history_erp                    => 'history',
-  inventory                      => 'inventory',
-  invoice                        => 'invoice_item',
-  language                       => 'language',
-  license                        => 'license',
-  licenseinvoice                 => 'license_invoice',
-  makemodel                      => 'make_model',
-  notes                          => 'note',
-  orderitems                     => 'order_item',
-  oe                             => 'order',
-  parts                          => 'part',
-  partsgroup                     => 'parts_group',
-  partstax                       => 'parts_tax',
-  payment_terms                  => 'payment_term',
-  prices                         => 'prices',
-  price_factors                  => 'price_factor',
-  pricegroup                     => 'pricegroup',
-  printers                       => 'Printer',
-  record_links                   => 'record_link',
-  rma                            => 'RMA',
-  rmaitems                       => 'RMA_item',
-  sepa_export                    => 'sepa_export',
-  sepa_export_items              => 'sepa_export_item',
-  schema_info                    => 'schema_info',
-  status                         => 'status',
-  tax                            => 'tax',
-  taxkeys                        => 'tax_key',
-  tax_zones                      => 'tax_zone',
-  todo_user_config               => 'todo_user_config',
-  translation                    => 'translation',
-  translation_payment_terms      => 'translation_payment_term',
-  units                          => 'unit',
-  units_language                 => 'units_language',
-  vendortax                      => 'vendor_tax',
-);
-
-sub get_blacklist {
-  return LXOFFICE => \@lxoffice_blacklist;
-}
-
-sub get_package_names {
-  return LXOFFICE => \%lxoffice_package_names;
-}
-
-sub db {
-  my $string = $_[0];
-  my $lookup = $lxoffice_package_names{$_[0]} ||
-      plurify($lxoffice_package_names{singlify($_[0])});
-
-  for my $thing ($string, $lookup) {
-
-    # best guess? its already the name. like part. camelize it first
-    my $class = "SL::DB::" . camelify($thing);
-    return $class if defined *{ $class. '::' };
-
-    # next, someone wants a manager and pluralized.
-    my $manager = "SL::DB::Manager::" . singlify(camelify($thing));
-    return $manager if defined *{ $manager . '::' };
-  }
-
-  die "Can't resolve '$string' as a database model, sorry. Did you perhaps forgot to load it?";
-}
-
-sub camelify {
-  my ($str) = @_;
-  $str =~ s/_+(.)/uc($1)/ge;
-  ucfirst $str;
-}
-
-sub snakify {
-  my ($str) = @_;
-  $str =~ s/(?<!^)\u(.)/'_' . lc($1)/ge;
-  lcfirst $str;
-}
-
-sub plurify {
-  my ($str) = @_;
-  $str . 's';
-}
-
-sub singlify {
-  my ($str) = @_;
-  local $/ = 's';
-  chomp $str;
-  $str;
-}
-
-1;
-
-__END__
-
-=head1 NAME
-
-SL::DB::Helpers::Mappings - Rose Table <-> Model mapping information
-
-=head1 SYNOPSIS
-
-  use SL::DB::Helpers::Mappings qw(@blacklist %table2model);
-
-=head1 DESCRIPTION
-
-This modul stores table <-> model mappings used by the
-L<scripts/rose_auto_create_model.pl> script.  If you add a new table that has
-custom mappings, add it here.
-
-=head2 db
-
-A special function provided here is E<db>. Without it you'd have to write:
-
-  my $part = SL::DB::Part->new(id => 1234);
-  my @all_parts = SL::DB::Manager::Part->get_all;
-
-with them it becomes:
-
-  my $part = db('part')->new(id => 123);
-  my @all_parts = db('parts')->get_all;
-
-You don't have to care about add that SL::DB:: incantation anymore. Also, a
-simple s at the end will get you the associated Manager class.
-
-db is written to try to make sense of what you give it, but if all fails, it
-will die with an error.
-
-=head1 BUGS
-
-nothing yet
-
-=head1 SEE ALSO
-
-L<scripts/rose_auto_create_model.pl>
-
-=head1 AUTHOR
-
-Sven Schöling <s.schoeling@linet-services.de>
-
-=cut
diff --git a/SL/DB/Helpers/Metadata.pm b/SL/DB/Helpers/Metadata.pm
deleted file mode 100644 (file)
index e6020a2..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-package SL::DB::Helpers::Metadata;
-
-use strict;
-
-use Rose::DB::Object::Metadata;
-use SL::DB::Helpers::ConventionManager;
-
-use base qw(Rose::DB::Object::Metadata);
-
-sub convention_manager_class {
-  return 'SL::DB::Helpers::ConventionManager';
-}
-
-sub default_manager_base_class {
-  return 'SL::DB::Helpers::Manager';
-}
-
-sub initialize {
-  my $self = shift;
-  $self->make_attr_auto_helpers unless $self->is_initialized;
-  $self->SUPER::initialize(@_);
-}
-
-sub make_attr_helpers {
-  my ($self, %params) = @_;
-  SL::DB::Helper::Attr::make($self->class, %params);
-}
-
-sub make_attr_auto_helpers {
-  my ($self) = @_;
-  SL::DB::Helper::Attr::auto_make($self->class);
-}
-
-1;
diff --git a/SL/DB/Helpers/Sorted.pm b/SL/DB/Helpers/Sorted.pm
deleted file mode 100644 (file)
index d5c2772..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-package SL::DB::Helpers::Sorted;
-
-use strict;
-
-require Exporter;
-our @ISA    = qw(Exporter);
-our @EXPORT = qw(get_all_sorted make_sort_string);
-
-my %sort_spec;
-
-sub make_sort_string {
-  my ($class, %params) = @_;
-
-  my $sort_spec        = _get_sort_spec($class);
-
-  my $sort_dir         = defined($params{sort_dir}) ? $params{sort_dir} * 1 : $sort_spec->{default}->[1];
-  my $sort_dir_str     = $sort_dir ? 'ASC' : 'DESC';
-
-  my $sort_by          = $params{sort_by};
-  $sort_by             = $sort_spec->{default}->[0] unless $sort_spec->{columns}->{$sort_by};
-
-  my $nulls_str        = '';
-  if ($sort_spec->{nulls}) {
-    $nulls_str = ref($sort_spec->{nulls}) ? ($sort_spec->{nulls}->{$sort_by} || $sort_spec->{nulls}->{default}) : $sort_spec->{nulls};
-    $nulls_str = " NULLS ${nulls_str}" if $nulls_str;
-  }
-
-  my $sort_by_str = $sort_spec->{columns}->{$sort_by};
-  $sort_by_str    = [ $sort_by_str ] unless ref($sort_by_str) eq 'ARRAY';
-  $sort_by_str    = join(', ', map { "${_} ${sort_dir_str}${nulls_str}" } @{ $sort_by_str });
-
-  return wantarray ? ($sort_by, $sort_dir, $sort_by_str) : $sort_by_str;
-}
-
-sub get_all_sorted {
-  my ($class, %params) = @_;
-  my $sort_str         = $class->make_sort_string(sort_by => delete($params{sort_by}), sort_dir => delete($params{sort_dir}));
-
-  return $class->get_all(sort_by => $sort_str, %params);
-}
-
-sub _get_sort_spec {
-  my ($class) = @_;
-  return $sort_spec{$class} ||= _make_sort_spec($class);
-}
-
-sub _make_sort_spec {
-  my ($class) = @_;
-
-  my %sort_spec = $class->_sort_spec if defined &{ "${class}::_sort_spec" };
-
-  my $meta = $class->object_class->meta;
-
-  if (!$sort_spec{default}) {
-    my @primary_keys = $meta->primary_key;
-    $sort_spec{default} = [ "" . $primary_keys[0], 1 ];
-  }
-
-  $sort_spec{columns} ||= { SIMPLE => [ map { "$_" } $meta->columns ] };
-
-  if ($sort_spec{columns}->{SIMPLE}) {
-    my $table = $meta->table;
-
-    if (!ref($sort_spec{columns}->{SIMPLE}) && ($sort_spec{columns}->{SIMPLE} eq 'ALL')) {
-      map { $sort_spec{columns}->{"$_"} ||= "${table}.${_}"} @{ $meta->columns };
-      delete $sort_spec{columns}->{SIMPLE};
-    } else {
-      map { $sort_spec{columns}->{$_} = "${table}.${_}" } @{ delete($sort_spec{columns}->{SIMPLE}) };
-    }
-  }
-
-  return \%sort_spec;
-}
-
-1;
-
-__END__
-
-=encoding utf8
-
-=head1 NAME
-
-SL::DB::Helpers::Sorted - Mixin for a manager class that handles
-sorting of database records
-
-=head1 SYNOPSIS
-
-  package SL::DB::Manager::Message;
-
-  use SL::DB::Helpers::Sorted;
-
-  sub _sort_spec {
-    return ( columns => { recipient_id => [ 'CASE
-                                             WHEN recipient_group_id IS NULL THEN lower(recipient.name)
-                                             ELSE                                 lower(recipient_group.name)
-                                             END',                                      ],
-                          sender_id    => [ 'lower(sender.name)',                       ],
-                          created_at   => [ 'created_at',                               ],
-                          subject      => [ 'lower(subject)',                           ],
-                          status       => [ 'NOT COALESCE(unread, FALSE)', 'created_at' ],
-                        },
-             default => [ 'status', 1 ],
-             nulls   => { default => 'LAST',
-                          subject => 'FIRST',
-                        }
-           );
-  }
-
-  package SL::Controller::Message;
-
-  sub action_list {
-    my $messages = SL::DB::Manager::Message->get_all_sorted(sort_by  => $::form->{sort_by},
-                                                            sort_dir => $::form->{sort_dir});
-  }
-
-=head1 CLASS FUNCTIONS
-
-=over 4
-
-=item C<make_sort_string %params>
-
-Evaluates C<$params{sort_by}> and C<$params{sort_dir}> and returns an
-SQL string suitable for sorting. The package this package is mixed
-into has to provide a method L</_sort_spec> that returns a hash whose
-structure is explained below. That hash is authoritive in which
-columns may be sorted, which column to sort by by default and how to
-handle C<NULL> values.
-
-Returns the SQL string in scalar context. In array context it returns
-three values: the actual column it sorts by (suitable for another call
-to L</make_sort_string>), the actual sort direction (either 0 or 1)
-and the SQL string.
-
-=item C<get_all_sorted %params>
-
-Returns C<< $class->get_all >> with C<sort_by> set to the value
-returned by c<< $class->make_sort_string(%params) >>.
-
-=back
-
-=head1 CLASS FUNCTIONS PROVIDED BY THE MIXING PACKAGE
-
-=over 4
-
-=item C<_sort_spec>
-
-This method is actually not part of this package but can be provided
-by the package this helper is mixed into. If it isn't then all columns
-of the corresponding table (as returned by the model's meta data) will
-be eligible for sorting.
-
-Returns a hash with the following keys:
-
-=over 2
-
-=item C<default>
-
-A two-element array containing the name and direction by which to sort
-in default cases. Example:
-
-  default => [ 'name', 1 ],
-
-Defaults to the table's primary key column (the first column if the
-primary key is composited).
-
-=item C<columns>
-
-A hash reference. Its keys are column names, and its values are SQL
-strings by which to sort. Example:
-
-  columns => { SIMPLE                  => [ 'transaction_description', 'orddate' ],
-               the_date                => 'CASE WHEN oe.quotation THEN oe.quodate ELSE oe.orddate END',
-               customer_name           => 'lower(customer.name)',
-             },
-
-If sorting by a column is requested that is not a key in this hash
-then the default column name will be used.
-
-The value can be either a scalar or an array reference. If it's the
-latter then both the sort direction as well as the null handling will
-be appended to each of its members.
-
-The special key C<SIMPLE> can be a scalar or an array reference. If it
-is an array reference then it contains column names that are mapped
-1:1 onto the table's columns. If it is the scalar 'ALL' then all
-columns in that model's meta data are mapped 1:1 unless the C<columns>
-hash already contains a key for that column.
-
-If C<columns> is missing then all columns of the model will be
-eligible for sorting. The list of columns is looked up in the model's
-meta data.
-
-=item C<nulls>
-
-Either a scalar or a hash reference determining where C<NULL> values
-will be sorted. If undefined then the decision is left to the
-database.
-
-If it is a scalar then all the same value will be used for all
-classes. The value is either C<FIRST> or C<LAST>.
-
-If it is a hash reference then its keys are column names (not SQL
-names). The values are either C<FIRST> or C<LAST>. If a column name is
-not found in this hash then the special keu C<default> will be looked
-up and used if it is found.
-
-Example:
-
-  nulls => { transaction_description => 'FIRST',
-             customer_name           => 'FIRST',
-             default                 => 'LAST',
-           },
-
-=back
-
-=back
-
-=head1 BUGS
-
-Nothing here yet.
-
-=head1 AUTHOR
-
-Moritz Bunkus E<lt>m.bunkus@linet-services.deE<gt>
-
-=cut
index f63987e..1b76830 100644 (file)
@@ -2,8 +2,8 @@ package SL::DB::Manager::DeliveryOrder;
 
 use strict;
 
-use SL::DB::Helpers::Manager;
-use base qw(SL::DB::Helpers::Manager);
+use SL::DB::Helper::Manager;
+use base qw(SL::DB::Helper::Manager);
 
 sub object_class { 'SL::DB::DeliveryOrder' }
 
index e52eebb..6577c77 100644 (file)
@@ -2,8 +2,8 @@ package SL::DB::Manager::Employee;
 
 use strict;
 
-use SL::DB::Helpers::Manager;
-use base qw(SL::DB::Helpers::Manager);
+use SL::DB::Helper::Manager;
+use base qw(SL::DB::Helper::Manager);
 
 sub object_class { 'SL::DB::Employee' }
 
index 025f7f2..c3a9a7b 100644 (file)
@@ -2,7 +2,7 @@ package SL::DB::Manager::Invoice;
 
 use strict;
 
-use base qw(SL::DB::Helpers::Manager);
+use base qw(SL::DB::Helper::Manager);
 
 sub object_class { 'SL::DB::Invoice' }
 
index 451a43a..fc2b796 100644 (file)
@@ -2,8 +2,8 @@ package SL::DB::Manager::Order;
 
 use strict;
 
-use SL::DB::Helpers::Manager;
-use base qw(SL::DB::Helpers::Manager);
+use SL::DB::Helper::Manager;
+use base qw(SL::DB::Helper::Manager);
 
 sub object_class { 'SL::DB::Order' }
 
index 1564b9b..e6aca1f 100644 (file)
@@ -2,8 +2,8 @@ package SL::DB::Manager::Part;
 
 use strict;
 
-use SL::DB::Helpers::Manager;
-use base qw(SL::DB::Helpers::Manager);
+use SL::DB::Helper::Manager;
+use base qw(SL::DB::Helper::Manager);
 
 use Carp;
 use SL::DBUtils;
index c717a04..1cc5737 100644 (file)
@@ -2,8 +2,8 @@ package SL::DB::Manager::PurchaseInvoice;
 
 use strict;
 
-use SL::DB::Helpers::Manager;
-use base qw(SL::DB::Helpers::Manager);
+use SL::DB::Helper::Manager;
+use base qw(SL::DB::Helper::Manager);
 
 sub object_class { 'SL::DB::PurchaseInvoice' }
 
index 82bcc5f..2b4f1e6 100644 (file)
@@ -2,7 +2,7 @@ package SL::DB::Manager::TransferType;
 
 use strict;
 
-use base qw(SL::DB::Helpers::Manager);
+use base qw(SL::DB::Helper::Manager);
 
 use Carp;
 
index 5e58ed9..0a69826 100644 (file)
@@ -7,9 +7,9 @@ use Rose::DB::Object;
 use List::MoreUtils qw(any);
 
 use SL::DB;
-use SL::DB::Helpers::Attr;
-use SL::DB::Helpers::Metadata;
-use SL::DB::Helpers::Manager;
+use SL::DB::Helper::Attr;
+use SL::DB::Helper::Metadata;
+use SL::DB::Helper::Manager;
 
 use base qw(Rose::DB::Object);
 
@@ -31,7 +31,7 @@ sub init_db {
 }
 
 sub meta_class {
-  return 'SL::DB::Helpers::Metadata';
+  return 'SL::DB::Helper::Metadata';
 }
 
 sub _get_manager_class {
index 143551f..a6f7ef4 100644 (file)
@@ -730,9 +730,9 @@ sub gl_transaction {
 
 if ($::use_rdbo) {
   eval {
-    require SL::DB::Helpers::Mappings;
+    require SL::DB::Helper::Mappings;
     sub db {
-      goto &SL::DB::Helpers::Mappings::db;
+      goto &SL::DB::Helper::Mappings::db;
     }
   } or die $@;
 }
index b1a7040..f222cfa 100755 (executable)
@@ -18,8 +18,8 @@ use SL::DB;
 use SL::Form;
 use SL::Locale;
 use SL::LXDebug;
-use SL::DB::Helpers::ALL;
-use SL::DB::Helpers::Mappings;
+use SL::DB::Helper::ALL;
+use SL::DB::Helper::Mappings;
 
 our $form;
 our $cgi;
@@ -131,8 +131,8 @@ CODE
 
 setup();
 
-my %blacklist     = SL::DB::Helpers::Mappings->get_blacklist;
-my %package_names = SL::DB::Helpers::Mappings->get_package_names;
+my %blacklist     = SL::DB::Helper::Mappings->get_blacklist;
+my %package_names = SL::DB::Helper::Mappings->get_package_names;
 
 my @tables = ();
 if (($ARGV[0] eq '--all') || ($ARGV[0] eq '-a') || ($ARGV[0] eq '--sugar') || ($ARGV[0] eq '-s')) {
index d0c015c..96a8f03 100644 (file)
@@ -1,7 +1,7 @@
 use Test::More tests => 12;
 
-use_ok 'SL::DB::Helpers::ALL';
-use_ok 'SL::DB::Helpers::Mappings', qw(db);
+use_ok 'SL::DB::Helper::ALL';
+use_ok 'SL::DB::Helper::Mappings', qw(db);
 
 is db('part'), 'SL::DB::Part';
 is db('parts'), 'SL::DB::Manager::Part';