Projekt

Allgemein

Profil

« Zurück | Weiter » 

Revision a0d9f09a

Von Sven Schöling vor fast 8 Jahren hinzugefügt

  • ID a0d9f09a2e63f0be9eda333ab7fa78679ea55759
  • Vorgänger f74b0dac
  • Nachfolger 6acefaf5

CsvImport: Spaltenzuordnung für non multiplexed

Unterschiede anzeigen:

SL/BackgroundJob/CsvImport.pm
5 5
use parent qw(SL::BackgroundJob::Base);
6 6

  
7 7
use YAML ();
8
use SL::JSON;
8 9
use SL::DB::CsvImportProfile;
9 10
use SL::SessionFile::Random;
10 11

  
......
60 61
  my $job = $self->{db_obj};
61 62

  
62 63
  $c->profile($self->profile);
64
  $c->mappings(SL::JSON::from_json($self->profile->get('json_mappings'))) if $self->profile->get('json_mappings');
63 65
  $c->type($job->data_as_hash->{type});
64 66
  $c->{employee_id} = $job->data_as_hash->{employee_id};
65 67

  
SL/Controller/CsvImport.pm
32 32
(
33 33
 scalar                  => [ qw(type profile file all_profiles all_charsets sep_char all_sep_chars quote_char all_quote_chars escape_char all_escape_chars all_buchungsgruppen all_units
34 34
                                 import_status errors headers raw_data_headers info_headers data num_importable displayable_columns file all_taxzones) ],
35
 'scalar --get_set_init' => [ qw(worker task_server num_imported) ],
35
 'scalar --get_set_init' => [ qw(worker task_server num_imported mappings) ],
36 36
 'array'                 => [
37 37
   progress_tracker     => { },
38 38
   add_progress_tracker => {  interface => 'add', hash_key => 'progress_tracker' },
......
213 213
  $self->render('csv_import/report', { layout => !($params{no_layout} || $::form->{no_layout}) });
214 214
}
215 215

  
216
sub action_add_empty_mapping_line {
217
  my ($self) = @_;
218

  
219
  $self->profile_from_form;
220
  $self->setup_help;
221

  
222
  $self->js
223
    ->append('#csv_import_mappings', $self->render('csv_import/_mapping_item', { layout => 0, output => 0 }))
224
    ->hide('#mapping_empty')
225
    ->render;
226
}
227

  
228
sub action_add_mapping_from_upload {
229
  my ($self) = @_;
230

  
231
  $self->profile_from_form;
232
  $self->setup_help;
233

  
234
  my $file = SL::SessionFile->new($self->csv_file_name, mode => '<', encoding => $self->profile->get('charset'));
235
  if (!$file->fh) {
236
    $self->js
237
      ->flash('error', t8('No file has been uploaded yet.'))
238
      ->render;
239
    return;
240
  }
241

  
242
  my $csv = Text::CSV_XS->new({
243
    binary      => 1,
244
    sep_char    => $self->profile->get('sep_char'),
245
    quote_char  => $self->profile->get('quote_char'),
246
    escape_char => $self->profile->get('escape_char'),
247
  });
248

  
249
  my $header = $csv->getline($file->fh) or do {
250
    $self->js
251
      ->flash('error', t8('No header found'))
252
      ->render;
253
    return;
254
  };
255

  
256
  for my $field (@$header) {
257
    next if $self->mappings_for_profile->{$field};
258
    $self->js->append(
259
      '#csv_import_mappings',
260
      $self->render('csv_import/_mapping_item', { layout => 0, output => 0 }, item => { from => $field }),
261
    );
262
  }
263

  
264
  $self->js
265
    ->hide('#mapping_empty')
266
    ->render;
267
}
268

  
216 269

  
217 270
#
218 271
# filters
......
372 425
  $profile ||= SL::DB::CsvImportProfile->new(type => $self->{type}, login => $::myconfig{login});
373 426

  
374 427
  $self->profile($profile);
428
  $self->mappings(SL::JSON::from_json($self->profile->get('json_mappings'))) if $self->profile->get('json_mappings');
375 429
  $self->worker->set_profile_defaults;
376 430
  $self->profile->set_defaults;
377 431
}
......
416 470
  $self->profile->assign_attributes(%{ $::form->{profile} });
417 471
  $self->profile->settings(map({ { key => $_, value => $::form->{settings}->{$_} } } keys %{ $::form->{settings} }),
418 472
                           @settings);
473

  
474
  $self->profile->set('json_mappings', JSON::to_json($self->mappings));
475

  
419 476
  $self->profile->set_defaults;
420 477
}
421 478

  
......
664 721
  1;
665 722
}
666 723

  
724
sub mappings_for_profile {
725
  +{ map { $_->{from} => $_->{to} } @{ $_[0]->mappings } }
726
}
727

  
728
sub init_mappings {
729
  $::form->{mappings} || []
730
}
731

  
667 732
1;
SL/Controller/CsvImport/Base.pm
34 34
  my $profile = $self->profile;
35 35
  $self->csv(SL::Helper::Csv->new(file                   => $self->file->file_name,
36 36
                                  encoding               => $self->controller->profile->get('charset'),
37
                                  profile                => [{ profile => $profile, class => $self->class }],
37
                                  profile                => [{ profile => $profile, class => $self->class, mapping => $self->controller->mappings_for_profile }],
38 38
                                  ignore_unknown_columns => 1,
39 39
                                  strict_profile         => 1,
40 40
                                  case_insensitive_header => 1,
......
54 54

  
55 55
  return if ( !$self->csv->header || $self->csv->errors );
56 56

  
57
  my $headers         = { headers => [ grep { $profile->{$_} } @{ $self->csv->header } ] };
58
  $headers->{methods} = [ map { $profile->{$_} } @{ $headers->{headers} } ];
59
  $headers->{used}    = { map { ($_ => 1) }      @{ $headers->{headers} } };
57
  my $headers         = { headers => [ map {; $_->{key} } @{ $self->csv->specs->[0] } ] };
58
  $headers->{methods} = [ map { $_->{path} } @{ $self->csv->specs->[0] } ];
59
  $headers->{used}    = { map { ($_ => 1) }  @{ $headers->{headers} } };
60 60
  $self->controller->headers($headers);
61 61
  $self->controller->raw_data_headers({ used => { }, headers => [ ] });
62 62
  $self->controller->info_headers({ used => { }, headers => [ ] });
SL/Helper/Csv.pm
341 341
  $self->_errors(\@new_errors);
342 342
}
343 343

  
344
sub specs {
345
  $_[0]->dispatcher->_specs
346
}
344 347

  
345 348
1;
346 349

  
SL/Helper/Csv/Dispatcher.pm
160 160
sub make_spec {
161 161
  my ($self, $col, $path, $cur_class) = @_;
162 162

  
163
  my $spec = { key => $col, steps => [] };
163
  my $spec = { key => $col, path => $path, steps => [] };
164 164

  
165 165
  return unless $path;
166 166

  
locale/de/all
183 183
  'Add bank account'            => 'Bankkonto erfassen',
184 184
  'Add booking group'           => 'Buchungsgruppe erfassen',
185 185
  'Add custom variable'         => 'Benutzerdefinierte Variable erfassen',
186
  'Add empty line (csv_import)' => 'Leere Zeile einfügen',
186 187
  'Add function block'          => 'Funktionsblock hinzufügen',
188
  'Add headers from last uploaded file (csv_import)' => 'Spalten aus der hochgeladenen Datei einfügen',
187 189
  'Add invoices'                => 'Rechnungen hinzufügen',
188 190
  'Add link: select records to link with' => 'Verknüpfungen hinzufügen: zu verknüpfende Belege auswählen',
189 191
  'Add linked record'           => 'Verknüpften Beleg hinzufügen',
......
220 222
  'All clients'                 => 'Alle Mandanten',
221 223
  'All general ledger entries'  => 'Alle Hauptbucheinträge',
222 224
  'All groups'                  => 'Alle Gruppen',
223
  'All linked transactions'     => 'Alle verknüpften Transaktionen',
224 225
  'All modules'                 => 'Alle Module',
225 226
  'All of the exports you have selected were already closed.' => 'Alle von Ihnen ausgewählten Exporte sind bereits abgeschlossen.',
226 227
  'All partsgroups'             => 'Alle Warengruppen',
......
858 859
  'Delete Contact'              => 'Ansprechperson löschen',
859 860
  'Delete Dataset'              => 'Datenbank löschen',
860 861
  'Delete Shipto'               => 'Lieferadresse löschen',
861
  'Delete bank transactions'    => '',
862 862
  'Delete drafts'               => 'Entwürfe löschen',
863 863
  'Delete links'                => 'Verknüpfungen löschen',
864 864
  'Delete picture'              => 'Bild löschen',
......
1365 1365
  'Help Template Variables'     => 'Hilfe zu Dokumenten-Variablen',
1366 1366
  'Help on column names'        => 'Hilfe zu Spaltennamen',
1367 1367
  'Here'                        => 'Hier',
1368
  'Here we are!'                => '',
1369 1368
  'Here you only provide the credentials for logging into the database.' => 'Hier geben Sie nur die Logindaten für die Anmeldung an der Datenbank ein.',
1370 1369
  'Here\'s an example command line:' => 'Hier ist eine Kommandozeile, die als Beispiel dient:',
1371 1370
  'Hide Filter'                 => 'Filter verbergen',
......
1373 1372
  'Hide chart details'          => 'Konteninformation verstecken',
1374 1373
  'Hide details'                => 'Details verbergen',
1375 1374
  'Hide help text'              => 'Hilfetext verbergen',
1375
  'Hide mappings (csv_import)'  => 'Spaltenzuordnungen verbergen',
1376 1376
  'Hide settings'               => 'Einstellungen verbergen',
1377 1377
  'Hints'                       => 'Hinweise',
1378 1378
  'History'                     => 'Historie',
......
1541 1541
  'KNr. beim Kunden'            => 'KNr. beim Kunden',
1542 1542
  'Keep the project link the way it is.' => 'Die aktuelle Verknüpfung beibehalten.',
1543 1543
  'Keine Suchergebnisse gefunden!' => 'Keine Suchergebnisse gefunden!',
1544
  'Known Column'                => 'Bekannte Spalte',
1544 1545
  'Konten'                      => 'Konten',
1545 1546
  'L'                           => 'L',
1546 1547
  'LIABILITIES'                 => 'PASSIVA',
......
1658 1659
  'Mandatory Departments'       => 'Benutzer muss Abteilungen vergeben',
1659 1660
  'Manually sent E-Mails will have their BCC field appended with this address. Will not trigger for employees without the right to send bcc, and will not apply to mails sent by automated jobs.' => 'Diese Mailadresse wird automatisch in das BCC Feld bei Mailversand kopiert. Hat keine Auswirkungen für Mitarbeiter ohne das Recht BCC zu versenden, und ignoriert wenn Mails automatisch versendet werden.',
1660 1661
  'Map'                         => 'Karte',
1662
  'Mappings (csv_import)'       => 'Spaltenzuordnungen',
1661 1663
  'Mar'                         => 'März',
1662 1664
  'March'                       => 'März',
1663 1665
  'Margepercent'                => 'Ertrag prozentual',
......
1788 1790
  'No file has been uploaded yet.' => 'Es wurde noch keine Datei hochgeladen.',
1789 1791
  'No function blocks have been created yet.' => 'Es wurden noch keine Funktionsblöcke angelegt.',
1790 1792
  'No groups have been created yet.' => 'Es wurden noch keine Gruppen angelegt.',
1793
  'No header found'             => 'Keine Kopfzeile gefunden',
1791 1794
  'No internal phone extensions have been configured yet.' => 'Es wurden noch keine internen Durchwahlen konfiguriert.',
1792 1795
  'No invoices have been selected.' => 'Es wurden keine Rechnungen ausgewählt.',
1793 1796
  'No or an unknown authenticantion module specified in "config/kivitendo.conf".' => 'Es wurde kein oder ein unbekanntes Authentifizierungsmodul in "config/kivitendo.conf" angegeben.',
......
2534 2537
  'Show help text'              => 'Hilfetext anzeigen',
2535 2538
  'Show history'                => 'Verlauf anzeigen',
2536 2539
  'Show items from invoices individually' => 'Artikel aus Rechnungen anzeigen',
2540
  'Show mappings (csv_import)'  => 'Spaltenzuordnungen anzeigen',
2537 2541
  'Show old dunnings'           => 'Alte Mahnungen anzeigen',
2538 2542
  'Show overdue sales quotations and requests for quotations...' => 'Überfällige Angebote und Preisanfragen anzeigen...',
2539 2543
  'Show parts'                  => 'Artikel anzeigen',
......
2705 2709
  'Text blocks front'           => 'Textblöcke vorne',
2706 2710
  'Text field'                  => 'Textfeld',
2707 2711
  'Text field variables: \'WIDTH=w HEIGHT=h\' sets the width and height of the text field. They default to 30 and 5 respectively.' => 'Textfelder: \'WIDTH=w HEIGHT=h\' setzen die Breite und die H&ouml;he des Textfeldes. Wenn nicht anders angegeben, so werden sie 30 Zeichen breit und f&uuml;nf Zeichen hoch dargestellt.',
2712
  'Text in CSV File'            => 'Spalte in der CSV Datei',
2708 2713
  'Text variables: \'MAXLENGTH=n\' sets the maximum entry length to \'n\'.' => 'Textzeilen: \'MAXLENGTH=n\' setzt eine Maximall&auml;nge von n Zeichen.',
2709 2714
  'Text, text field and number variables: The default value will be used as-is.' => 'Textzeilen, Textfelder und Zahlenvariablen: Der Standardwert wird so wie er ist &uuml;bernommen.',
2710 2715
  'Texts for invoices'          => 'Texte für Rechnungen',
......
3041 3046
  'There is not enough available of \'#1\' at warehouse \'#2\', bin \'#3\', #4, #5, for the transfer of #6.' => 'Von \'#1\' ist in Lager \'#2\', Lagerplatz \'#3\', #4, #5, nicht gen&uuml;gend eingelagert, um insgesamt #6 auszulagern.',
3042 3047
  'There is not enough available of \'#1\' at warehouse \'#2\', bin \'#3\', #4, for the transfer of #5.' => 'Von \'#1\' ist in Lager \'#2\', Lagerplatz \'#3\', #4 nicht gen&uuml;gend eingelagert, um insgesamt #5 auszulagern.',
3043 3048
  'There is not enough left of \'#1\' in bin \'#2\' for the removal of #3.' => 'In Lagerplatz \'#2\' ist nicht genug von \'#1\' vorhanden, um #3 zu entnehmen.',
3049
  'There is nothing here yet (csv_import)' => 'Noch keine Zuordnungen',
3044 3050
  'There is one or more sections for which no part has been assigned yet; therefore creating the new record is not possible yet.' => 'Es gibt einen oder mehrere Abschnitte ohne Artikelzuweisung; daher kann der neue Beleg noch nicht erstellt werden.',
3045 3051
  'There was an error deleting the draft' => 'Beim Löschen des Entwurfs ist ein Fehler aufgetretetn',
3046 3052
  'There was an error executing the background job.' => 'Bei der Ausführung des Hintergrund-Jobs trat ein Fehler auf.',
......
3051 3057
  'There you can let kivitendo create the basic tables for you, even in an already existing database.' => 'Dort können Sie kivitendo diese grundlegenden Tabellen erstellen lassen, selbst in einer bereits existierenden Datenbank.',
3052 3058
  'Therefore several settings that had to be made for each user in the past have been consolidated into the client configuration.' => 'Dazu wurden gewisse Einstellungen, die vorher bei jedem Benutzer vorgenommen werden mussten, in die Konfiguration eines Mandanten verschoben.',
3053 3059
  'Therefore the definition of "kg" with the base unit "g" and a factor of 1000 is valid while defining "g" with a base unit of "kg" and a factor of "0.001" is not.' => 'So ist die Definition von "kg" mit der Basiseinheit "g" und dem Faktor 1000 zulässig, die Definition von "g" mit der Basiseinheit "kg" und dem Faktor "0,001" hingegen nicht.',
3060
  'These mappings can be used to map heading from non standard csv files to known columns. These will also be saved in profiles, so you can save profiles for every source of formats.' => 'Mit diesen Spaltenzuordnungen können die Kopfzeilen aus beliebigen CSV-Dateien verarbeitet werden. Die Zuordnungen werden im Profil mitgespeichert, so dass regelmäßige Quellen behandelt werden können.',
3054 3061
  'These wrong entries cannot be fixed automatically.' => 'Diese Einträge können nicht automatisch bereinigt werden.',
3055 3062
  'They will be updated, new ones for additional parts without a line item added automatically.' => 'Diese Positionen werden automatisch aktualisiert bzw. ergänzt, wenn es noch keine Position zu einem zusätzlichen Artikel gibt.',
3056 3063
  'This Price Rule is no longer valid' => 'Diese Preisregel ist nicht mehr gültig',
......
3205 3212
  'Unknown dependency \'%s\'.'  => 'Unbekannte Abh&auml;ngigkeit \'%s\'.',
3206 3213
  'Unknown module: #1'          => 'Unbekanntes Modul #1',
3207 3214
  'Unknown problem type.'       => 'Unbekannter Problem-Typ',
3208
  'Unlink Bank Transactions'    => 'Bankverknüpfungen aufheben',
3209
  'Unlink bank transaction'     => 'Bankverknüpfung aufheben',
3210 3215
  'Unlock System'               => 'System entsperren',
3211 3216
  'Unsuccessfully executed:\n'  => 'Erfolglos ausgeführt:',
3212 3217
  'Unsupported image type (supported types: #1)' => 'Nicht unterstützter Bildtyp (unterstützte Typen: #1)',
templates/webpages/csv_import/_mapping_item.html
1
[%- USE HTML %]
2
[%- USE LxERP %]
3
[%- USE L %]
4
[%- USE T8 %]
5
 <tr class=listrow>
6
    <td><a class='remove_line interact cursor-pointer'>✘</a></td>
7
[%- IF item.from %]
8
  <td>[% L.hidden_tag('mappings[+].from', item.from) %][% item.from | html %]</td>
9
[%- ELSE %]
10
  <td>[% L.input_tag('mappings[+].from', '') %]</td>
11
[%- END %]
12
  <td>[% L.select_tag('mappings[].to', SELF.displayable_columns, value_key='name', title_key='name', default=item.to) %]</td>
13
 </tr>
14

  
templates/webpages/csv_import/form.html
292 292
  </div>
293 293
  <hr>
294 294

  
295
[%- UNLESS SELF.worker.is_multiplexed %]
296
  <h2>[% 'Mappings (csv_import)' | $T8 %]</h2>
297

  
298
  <div class="mappings_toggle"[% UNLESS SELF.deferred || SELF.import_status %] style="display:none"[% END %]>
299
   <a href="#" onClick="javascript:$('.mappings_toggle').toggle()">[% LxERP.t8("Show mappings (csv_import)") %]</a>
300
  </div>
301
  <div class="mappings_toggle"[% IF SELF.deferred || SELF.import_status %] style="display:none"[% END %]>
302
   <p><a href="#" onClick="javascript:$('.mappings_toggle').toggle()">[% LxERP.t8("Hide mappings (csv_import)") %]</a></p>
303

  
304
    <p>[% 'These mappings can be used to map heading from non standard csv files to known columns. These will also be saved in profiles, so you can save profiles for every source of formats.' | $T8 %]</p>
305

  
306
  <table id="csv_import_mappings">
307
   <tr class=listheading>
308
    <th></th>
309
    <th>[% 'Text in CSV File' | $T8 %]</th>
310
    <th>[% 'Known Column' | $T8 %]</th>
311
   </tr>
312
   <tr id='mapping_empty' style='display:none'>
313
    <td colspan=3>[% 'There is nothing here yet (csv_import)' | $T8 %]</td>
314
   </tr>
315
[%- FOREACH row = SELF.mappings %]
316
   [% PROCESS 'csv_import/_mapping_item.html', item=row IF row.from %]
317
[%- END %]
318
   [% PROCESS 'csv_import/_mapping_item.html', item={} %]
319
  </table>
320

  
321
  <input type=button id='add_empty_mapping_line' value='[% 'Add empty line (csv_import)' | $T8 %]'>
322
  <input type=button id='add_mapping_from_upload' value='[% 'Add headers from last uploaded file (csv_import)' | $T8 %]'>
323

  
324
  </div>
325
  <hr>
326
[%- END %]
295 327
  [% L.submit_tag('action_test', LxERP.t8('Test and preview')) %]
296 328
  [% L.submit_tag('action_import', LxERP.t8('Import'), style='display:none') %]
297 329

  
......
314 346
          return true;
315 347
        alert('[% LxERP.t8('Please enter a profile name.') %]');
316 348
        return false;
317
      })
349
      });
350
      $('#add_empty_mapping_line').click(function(){
351
        $.get('controller.pl', { action: 'CsvImport/add_empty_mapping_line', 'profile.type': $('#profile_type').val() }, kivi.eval_json_result);
352
      });
353
      $('#add_mapping_from_upload').click(function(){
354
        $.get('controller.pl?action_add_mapping_from_upload=1', $('form').serialize() , kivi.eval_json_result);
355
      });
356
      $('#csv_import_mappings').on('click', '.remove_line', function(){ $(this).closest('tr').remove(); if (1==$('#csv_import_mappings tr:visible').length) $('#mapping_empty').show() });
318 357
    });
319 358
    -->
320 359
 </script>

Auch abrufbar als: Unified diff