Speichern, Laden, Löschen von Importprofilen implementiert
authorMoritz Bunkus <m.bunkus@linet-services.de>
Wed, 23 Feb 2011 17:03:31 +0000 (18:03 +0100)
committerMoritz Bunkus <m.bunkus@linet-services.de>
Thu, 16 Jun 2011 06:44:14 +0000 (08:44 +0200)
SL/Controller/CsvImport.pm [new file with mode: 0644]
SL/DB/CsvImportProfile.pm
templates/webpages/csv_import/form_customers_vendors.html [new file with mode: 0644]

diff --git a/SL/Controller/CsvImport.pm b/SL/Controller/CsvImport.pm
new file mode 100644 (file)
index 0000000..2406362
--- /dev/null
@@ -0,0 +1,194 @@
+package SL::Controller::CsvImport;
+
+use strict;
+
+use SL::DB::CsvImportProfile;
+use SL::Helper::Flash;
+
+use List::MoreUtils qw(none);
+
+use parent qw(SL::Controller::Base);
+
+use Rose::Object::MakeMethods::Generic
+(
+ scalar => [ qw(type profile all_profiles all_charsets sep_char all_sep_chars quote_char all_quote_chars escape_char all_escape_chars) ],
+);
+
+__PACKAGE__->run_before('check_auth');
+__PACKAGE__->run_before('ensure_form_structure');
+__PACKAGE__->run_before('check_type');
+__PACKAGE__->run_before('load_all_profiles');
+
+#
+# actions
+#
+
+sub action_new {
+  my ($self) = @_;
+
+  $self->load_default_profile unless $self->profile;
+  $self->render_inputs;
+}
+
+sub action_test {
+  my ($self) = @_;
+  $self->test_and_import(test => 1);
+}
+
+sub action_import {
+  my $self = shift;
+  $self->test_and_import(test => 0);
+}
+
+sub action_save {
+  my ($self) = @_;
+
+  $self->profile_from_form(SL::DB::Manager::CsvImportProfile->find_by(name => $::form->{profile}->{name}));
+  $self->profile->save;
+
+  flash_later('info', $::locale->text("The profile has been saved under the name '#1'.", $self->profile->name));
+  $self->redirect_to(action => 'new', 'profile.type' => $self->type, 'profile.id' => $self->profile->id);
+}
+
+sub action_destroy {
+  my $self = shift;
+
+  my $profile = SL::DB::CsvImportProfile->new(id => $::form->{profile}->{id});
+  $profile->delete(cascade => 1);
+
+  flash_later('info', $::locale->text('The profile \'#1\' has been deleted.', $profile->name));
+  $self->redirect_to(action => 'new', 'profile.type' => $self->type);
+}
+
+#
+# filters
+#
+
+sub check_auth {
+  $::auth->assert('config');
+}
+
+sub check_type {
+  my ($self) = @_;
+
+  die "Invalid CSV import type" if none { $_ eq $::form->{profile}->{type} } qw(parts customers_vendors addresses contacts);
+  $self->type($::form->{profile}->{type});
+}
+
+sub ensure_form_structure {
+  my ($self, %params) = @_;
+
+  $::form->{profile}  = {} unless ref $::form->{profile}  eq 'HASH';
+  $::form->{settings} = {} unless ref $::form->{settings} eq 'HASH';
+}
+
+#
+# helpers
+#
+
+sub render_inputs {
+  my ($self, %params) = @_;
+
+  $self->all_charsets([ [ 'UTF-8',       'UTF-8'                 ],
+                        [ 'ISO-8859-1',  'ISO-8859-1 (Latin 1)'  ],
+                        [ 'ISO-8859-15', 'ISO-8859-15 (Latin 9)' ],
+                        [ 'CP850',       'CP850 (DOS/ANSI)'      ],
+                        [ 'CP1252',      'CP1252 (Windows)'      ],
+                      ]);
+
+  my %char_map = $self->char_map;
+
+  foreach my $type (qw(sep quote escape)) {
+    my $sub = "all_${type}_chars";
+    $self->$sub([ sort { $a->[0] cmp $b->[0] } values %{ $char_map{$type} } ]);
+
+    my $char = $self->profile->get($type . '_char');
+    $sub     = "${type}_char";
+    $self->$sub(($char_map{$type}->{$char} || [])->[0] || $char);
+  }
+
+  if ($self->type eq 'customers_vendors') {
+    $self->render('csv_import/form_customers_vendors', title => $::locale->text('CSV import: customers and vendors'));
+
+  } elsif ($self->type eq 'addresses') {
+    $self->render('csv_import/form_addresses',         title => $::locale->text('CSV import: shipping addresses'));
+
+  } elsif ($self->type eq 'contacts') {
+    $self->render('csv_import/form_contacts',          title => $::locale->text('CSV import: contacts'));
+
+  } elsif ($self->type eq 'parts') {
+    $self->render('csv_import/form_parts',             title => $::locale->text('CSV import: parts, services and assemblies'));
+
+  } else {
+    die;
+  }
+}
+
+sub test_and_import {
+  my ($self, %params) = @_;
+
+  $self->profile_from_form;
+
+  # do the import thingy...
+  $self->action_new;
+}
+
+sub load_default_profile {
+  my ($self) = @_;
+
+  if ($::form->{profile}->{id}) {
+    $self->profile(SL::DB::CsvImportProfile->new(id => $::form->{profile}->{id})->load);
+
+  } else {
+    $self->profile(SL::DB::Manager::CsvImportProfile->find_by(type => $self->{type}, is_default => 1));
+    $self->profile(SL::DB::CsvImportProfile->new(type => $self->{type})) unless $self->profile;
+  }
+
+  $self->profile->set_defaults;
+}
+
+sub load_all_profiles {
+  my ($self, %params) = @_;
+
+  $self->all_profiles(SL::DB::Manager::CsvImportProfile->get_all(where => [ type => $self->type ], sort_by => 'name'));
+}
+
+sub profile_from_form {
+  my ($self, $existing_profile) = @_;
+
+  delete $::form->{profile}->{id};
+
+  my %char_map = $self->char_map;
+  my @settings;
+
+  foreach my $type (qw(sep quote escape)) {
+    my %rev_chars = map { $char_map{$type}->{$_}->[0] => $_ } keys %{ $char_map{$type} };
+    my $char      = $::form->{"${type}_char"} eq 'custom' ? $::form->{"custom_${type}_char"} : $rev_chars{ $::form->{"${type}_char"} };
+
+    push @settings, { key => "${type}_char", value => $char };
+  }
+
+  delete $::form->{profile}->{id};
+  $self->profile($existing_profile || SL::DB::CsvImportProfile->new);
+  $self->profile->assign_attributes(%{ $::form->{profile} });
+  $self->profile->settings(map({ { key => $_, value => $::form->{settings}->{$_} } } keys %{ $::form->{settings} }),
+                           @settings);
+  $self->profile->set_defaults;
+}
+
+sub char_map {
+  return ( sep    => { ','  => [ 'comma',     $::locale->text('Comma')     ],
+                       ';'  => [ 'semicolon', $::locale->text('Semicolon') ],
+                       "\t" => [ 'tab',       $::locale->text('Tab')       ],
+                       ' '  => [ 'space',     $::locale->text('Space')     ],
+                     },
+           quote  => { '"' => [ 'quote', $::locale->text('Quotes') ],
+                       "'" => [ 'singlequote', $::locale->text('Single quotes') ],
+                     },
+           escape => { '"' => [ 'quote', $::locale->text('Quotes') ],
+                       "'" => [ 'singlequote', $::locale->text('Single quotes') ],
+                     },
+         );
+}
+
+1;
index 85033e1..c7c0f91 100644 (file)
@@ -24,6 +24,41 @@ __PACKAGE__->before_save('_before_save_unset_default_on_others');
 # public functions
 #
 
+sub new_with_default {
+  my ($class, $type) = @_;
+
+  return $class->new(type => $type)->set_defaults;
+}
+
+sub set_defaults {
+  my ($self) = @_;
+
+  $self->_set_defaults(sep_char     => ',',
+                       quote_char   => '"',
+                       escape_char  => '"',
+                       charset      => 'CP850',
+                       numberformat => $::myconfig{numberformat},
+                      );
+
+  if ($self->type eq 'parts') {
+    my $bugru = SL::DB::Manager::Buchungsgruppe->find_by(name => { like => 'Standard%19%' });
+
+    $self->_set_defaults(sellprice_places          => 2,
+                         sellprice_adjustment      => 0,
+                         sellprice_adjustment_type => 'percent',
+                         article_number_policy     => 'update_price',
+                         price_group_sep_char      => '!',
+                         shoparticle_if_missing    => 0,
+                         parts_type                => 'part',
+                         default_buchungsgruppe    => ($bugru ? $bugru->name : undef),
+                        );
+  } else {
+    $self->_set_defaults(table => 'customer');
+  }
+
+  return $self;
+}
+
 sub set {
   my ($self, %params) = @_;
 
@@ -32,7 +67,7 @@ sub set {
 
     if (!$setting) {
       $setting = SL::DB::CsvImportProfileSetting->new(key => $key);
-      $self->add_settings($setting);
+      $self->settings(@{ $self->settings || [] }, $setting);
     }
 
     $setting->value($value);
@@ -48,6 +83,16 @@ sub get {
   return $setting ? $setting->value : $default;
 }
 
+sub _set_defaults {
+  my ($self, %params) = @_;
+
+  while (my ($key, $value) = each %params) {
+    $self->settings(@{ $self->settings || [] }, { key => $key, value => $value }) if !$self->_get_setting($key);
+  }
+
+  return $self;
+}
+
 #
 # hooks
 #
@@ -70,7 +115,7 @@ sub _before_save_unset_default_on_others {
 
 sub _get_setting {
   my ($self, $key) = @_;
-  return first { $_->key eq $key } @{ $self->settings };
+  return first { $_->key eq $key } @{ $self->settings || [] };
 }
 
 1;
diff --git a/templates/webpages/csv_import/form_customers_vendors.html b/templates/webpages/csv_import/form_customers_vendors.html
new file mode 100644 (file)
index 0000000..50b2438
--- /dev/null
@@ -0,0 +1,123 @@
+[% USE HTML %][% USE LxERP %][% USE L %]
+<body>
+
+ <div class="listtop">[% FORM.title %]</div>
+
+ [%- INCLUDE 'common/flash.html' %]
+
+ <form method="post" action="controller.pl">
+  [% L.hidden_tag('action', 'CsvImport/dispatch') %]
+  [% L.hidden_tag('profile.type', SELF.profile.type) %]
+
+  <h2>[%- LxERP.t8('Import profiles') %]</h2>
+
+  <table>
+   [%- IF SELF.profile.id %]
+    <tr>
+     <th align="right">[%- LxERP.t8('Current profile') %]:</th>
+     <td>[%- HTML.escape(SELF.profile.name) %]</td>
+    </tr>
+   [%- END %]
+
+   [%- IF SELF.all_profiles.size %]
+    <tr>
+     <th align="right">[%- LxERP.t8('Existing profiles') %]:</th>
+     <td>
+      [% L.select_tag('profile.id', L.options_for_select(SELF.all_profiles, title => 'name', default => SELF.profile.id), style => 'width: 300px') %]
+     </td>
+     <td>
+      [% L.submit_tag('action_new', LxERP.t8('Load profile')) %]
+      [% L.submit_tag('action_destroy', LxERP.t8('Delete profile'), confirm => LxERP.t8('Do you really want to delete this object?')) %]
+     </td>
+    </tr>
+   [%- END %]
+
+   <tr>
+    <th align="right" valign="top">[%- LxERP.t8('Save settings as') %]:</th>
+    <td valign="top">
+     [% L.input_tag('profile.name', '', style => 'width: 300px') %]
+     <br>
+     [% L.checkbox_tag('profile.is_default', label => LxERP.t8('Make default profile')) %]
+    </td>
+    <td valign="top">[% L.submit_tag('action_save', LxERP.t8('Save profile')) %]</td>
+   </tr>
+  </table>
+
+  <hr>
+
+  <h2>[%- LxERP.t8('Settings') %]</h2>
+
+  <table>
+   <tr>
+    <th align="right">[%- LxERP.t8('Charset') %]:</th>
+    <td colspan="10">[% L.select_tag('settings.charset', L.options_for_select(SELF.all_charsets, default => SELF.profile.get('charset'))) %]</td>
+   </tr>
+
+   <tr>
+    <th align="right">[%- LxERP.t8('Separator') %]:</th>
+    [% SET custom_sep_char = SELF.sep_char %]
+    [% FOREACH entry = SELF.all_sep_chars %]
+     <td>
+      [% IF SELF.sep_char == entry.first %] [% SET custom_sep_char = '' %] [%- END %]
+      [% L.radio_button_tag('sep_char', value => entry.first, label => entry.last, checked => SELF.sep_char == entry.first) %]
+     </td>
+    [%- END %]
+
+    <td>
+     [% L.radio_button_tag('sep_char', value => 'custom', checked => custom_sep_char != '') %]
+     [% L.input_tag('custom_sep_char', custom_sep_char, size => 3, maxlength => 1) %]
+    </td>
+   </tr>
+
+   <tr>
+    <th align="right">[%- LxERP.t8('Quote character') %]:</th>
+    [% SET custom_quote_char = SELF.quote_char %]
+    [% FOREACH entry = SELF.all_quote_chars %]
+     <td>
+      [% IF SELF.quote_char == entry.first %] [% SET custom_quote_char = '' %] [%- END %]
+      [% L.radio_button_tag('quote_char', value => entry.first, label => entry.last, checked => SELF.quote_char == entry.first) %]
+     </td>
+    [%- END %]
+
+    <td>
+     [% L.radio_button_tag('quote_char', value => 'custom', checked => custom_quote_char != '') %]
+     [% L.input_tag('custom_quote_char', custom_quote_char, size => 3, maxlength => 1) %]
+    </td>
+   </tr>
+
+   <tr>
+    <th align="right">[%- LxERP.t8('Escape character') %]:</th>
+    [% SET custom_escape_char = SELF.escape_char %]
+    [% FOREACH entry = SELF.all_escape_chars %]
+     <td>
+      [% IF SELF.escape_char == entry.first %] [% SET custom_escape_char = '' %] [%- END %]
+      [% L.radio_button_tag('escape_char', value => entry.first, label => entry.last, checked => SELF.escape_char == entry.first) %]
+     </td>
+    [%- END %]
+
+    <td>
+     [% L.radio_button_tag('escape_char', value => 'custom', checked => custom_escape_char != '') %]
+     [% L.input_tag('custom_escape_char', custom_escape_char, size => 3, maxlength => 1) %]
+    </td>
+   </tr>
+
+  </table>
+
+  [% L.submit_tag('action_test', LxERP.t8('Gogogo')) %]
+
+ </form>
+
+ <script type="text/javascript">
+  <!--
+    $(document).ready(function() {
+      $('#action_save').click(function() {
+        if ($('#profile_name').attr('value') != '')
+          return true;
+        alert('[% LxERP.t8('Please enter a profile name.') %]');
+        return false;
+      })
+    });
+    -->
+ </script>
+</body>
+</html>