175392240c4cc2d99b4820ea3e2e6af6f06f63b2
[kivitendo-erp.git] / SL / Controller / CsvImport / Base.pm
1 package SL::Controller::CsvImport::Base;
2
3 use strict;
4
5 use SL::Helper::Csv;
6
7 use parent qw(Rose::Object);
8
9 use Rose::Object::MakeMethods::Generic
10 (
11  scalar                  => [ qw(controller file csv) ],
12  'scalar --get_set_init' => [ qw(profile existing_objects class manager_class) ],
13 );
14
15 sub run {
16   my ($self) = @_;
17
18   my $profile = $self->profile;
19   $self->csv(SL::Helper::Csv->new(file                   => $self->file->file_name,
20                                   encoding               => $self->controller->profile->get('charset'),
21                                   class                  => $self->class,
22                                   profile                => $profile,
23                                   ignore_unknown_columns => 1,
24                                   map { ( $_ => $self->controller->profile->get($_) ) } qw(sep_char escape_char quote_char),
25                                  ));
26   $self->csv->parse;
27
28   $self->controller->errors([ $self->csv->errors ]) if $self->csv->errors;
29
30   return unless $self->csv->header;
31
32   my $headers         = { headers => [ grep { $profile->{$_} } @{ $self->csv->header } ] };
33   $headers->{methods} = [ map { $profile->{$_} } @{ $headers->{headers} } ];
34   $self->controller->headers($headers);
35
36   $self->controller->data([ map { { object => $_, errors => [] } } $self->csv->get_objects ]);
37
38   $self->check_objects;
39   $self->check_duplicates if $self->controller->profile->get('duplicates', 'no_check') ne 'no_check';
40   $self->fix_field_lenghts;
41 }
42
43 sub init_profile {
44   my ($self) = @_;
45
46   eval "require " . $self->class;
47
48   my %profile;
49   for my $col ($self->class->meta->columns) {
50     my $name = $col->isa('Rose::DB::Object::Metadata::Column::Numeric')   ? "$col\_as_number"
51       :        $col->isa('Rose::DB::Object::Metadata::Column::Date')      ? "$col\_as_date"
52       :        $col->isa('Rose::DB::Object::Metadata::Column::Timestamp') ? "$col\_as_date"
53       :                                                                     $col->name;
54
55     $profile{$col} = $name;
56   }
57
58   $self->profile(\%profile);
59 }
60
61 sub init_existing_objects {
62   my ($self) = @_;
63
64   eval "require " . $self->class;
65   $self->existing_objects($self->manager_class->get_all);
66 }
67
68 sub init_class {
69   die "class not set";
70 }
71
72 sub init_manager_class {
73   my ($self) = @_;
74
75   $self->class =~ m/^SL::DB::(.+)/;
76   $self->manager_class("SL::DB::Manager::" . $1);
77 }
78
79 sub check_objects {
80 }
81
82 sub check_duplicates {
83 }
84
85 sub save_objects {
86   my ($self, %params) = @_;
87
88   my $data = $params{data} || $self->controller->data;
89
90   foreach my $entry (@{ $data }) {
91     next if @{ $entry->{errors} };
92
93     if (!$entry->{object}->save) {
94       push @{ $entry->{errors} }, $::locale->text('Error when saving: #1', $entry->{object}->db->error);
95     } else {
96       $self->controller->num_imported($self->controller->num_imported + 1);
97     }
98   }
99 }
100
101 sub field_lengths {
102   return ();
103 }
104
105 sub fix_field_lenghts {
106   my ($self) = @_;
107
108   my %field_lengths = $self->field_lengths;
109   foreach my $entry (@{ $self->controller->data }) {
110     next unless @{ $entry->{errors} };
111     map { $entry->{object}->$_(substr($entry->{object}->$_, 0, $field_lengths{$_})) if $entry->{object}->$_ } keys %field_lengths;
112   }
113 }
114
115 1;