1 use Test::More tests => 91;
 
   7 use Support::TestSetup;
 
   9 use_ok 'SL::Helper::Csv';
 
  11 Support::TestSetup::login();
 
  13 my $csv = SL::Helper::Csv->new(
 
  14   file    => \"Kaffee\n",       # " # make emacs happy
 
  15   header  => [ 'description' ],
 
  16   profile => [{ class  => 'SL::DB::Part', }],
 
  19 isa_ok $csv->_csv, 'Text::CSV_XS';
 
  20 isa_ok $csv->_io, 'IO::File';
 
  21 isa_ok $csv->parse, 'SL::Helper::Csv', 'parsing returns self';
 
  22 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'simple case works';
 
  24 is $csv->get_objects->[0]->description, 'Kaffee', 'get_object works';
 
  27 $::myconfig{numberformat} = '1.000,00';
 
  28 $::myconfig{dateformat} = 'dd.mm.yyyy';
 
  30 $csv = SL::Helper::Csv->new(
 
  31   file    => \"Kaffee;0.12;12,2;1,5234\n",            # " # make emacs happy
 
  32   header  => [ 'description', 'sellprice', 'lastcost_as_number', 'listprice' ],
 
  33   profile => [{profile => { listprice => 'listprice_as_number' },
 
  34                class   => 'SL::DB::Part',}],
 
  38 is $csv->get_objects->[0]->sellprice, 0.12, 'numeric attr works';
 
  39 is $csv->get_objects->[0]->lastcost, 12.2, 'attr helper works';
 
  40 is $csv->get_objects->[0]->listprice, 1.5234, 'dispatch works';
 
  45 $csv = SL::Helper::Csv->new(
 
  47 description,sellprice,lastcost_as_number,listprice,
 
  48 Kaffee,0.12,'12,2','1,5234'
 
  52   profile => [{profile => { listprice => 'listprice_as_number' },
 
  53                class   => 'SL::DB::Part',}]
 
  56 is scalar @{ $csv->get_objects }, 1, 'auto header works';
 
  57 is $csv->get_objects->[0]->description, 'Kaffee', 'get_object works on auto header';
 
  62 $csv = SL::Helper::Csv->new(
 
  64 ;;description;sellprice;lastcost_as_number;
 
  65 #####;Puppy;Kaffee;0.12;12,2;1,5234
 
  67   profile => [{class  => 'SL::DB::Part'}],
 
  70 is scalar @{ $csv->get_objects }, 1, 'bozo header doesn\'t blow things up';
 
  74 $csv = SL::Helper::Csv->new(
 
  76 description;partnumber;sellprice;lastcost_as_number;
 
  77 Kaffee;;0.12;12,2;1,5234
 
  78 Beer;1123245;0.12;12,2;1,5234
 
  80   profile => [{class  => 'SL::DB::Part'}],
 
  83 is scalar @{ $csv->get_objects }, 2, 'multiple objects work';
 
  84 is $csv->get_objects->[0]->description, 'Kaffee', 'first object';
 
  85 is $csv->get_objects->[1]->partnumber, '1123245', 'second object';
 
  89 $csv = SL::Helper::Csv->new(
 
  91 description;partnumber;sellprice;lastcost_as_number;
 
  93 Beer;1123245;0.12;1.5234
 
  95   numberformat => '1,000.00',
 
  96   profile => [{class  => 'SL::DB::Part'}],
 
  99 is $csv->get_objects->[0]->lastcost, '1221.52', 'formatnumber';
 
 103 $csv = SL::Helper::Csv->new(
 
 105 "description;partnumber;sellprice;lastcost_as_number;
 
 106 Kaffee;;0.12;1,221.52
 
 107 Beer;1123245;0.12;1.5234
 
 109 # " # make emacs happy
 
 110   numberformat => '1,000.00',
 
 111   profile => [{class  => 'SL::DB::Part'}],
 
 113 is $csv->parse, undef, 'broken csv header won\'t get parsed';
 
 117 $csv = SL::Helper::Csv->new(
 
 119 description;partnumber;sellprice;lastcost_as_number;
 
 120 "Kaf"fee";;0.12;1,221.52
 
 121 Beer;1123245;0.12;1.5234
 
 123 # " # make emacs happy
 
 124   numberformat => '1,000.00',
 
 125   profile => [{class  => 'SL::DB::Part'}],
 
 127 is $csv->parse, undef, 'broken csv content won\'t get parsed';
 
 128 is_deeply $csv->errors, [ '"Kaf"fee";;0.12;1,221.52'."\n", 2023, 'EIQ - QUO character not allowed', 5, 2 ], 'error';
 
 129 isa_ok( ($csv->errors)[0], 'SL::Helper::Csv::Error', 'Errors get objectified');
 
 133 $csv = SL::Helper::Csv->new(
 
 135 description;partnumber;sellprice;lastcost_as_number;wiener;
 
 136 Kaffee;;0.12;1,221.52;ja wiener
 
 137 Beer;1123245;0.12;1.5234;nein kein wieder
 
 139   numberformat => '1,000.00',
 
 140   ignore_unknown_columns => 1,
 
 141   profile => [{class  => 'SL::DB::Part'}],
 
 144 is $csv->get_objects->[0]->lastcost, '1221.52', 'ignore_unknown_columns works';
 
 148 $csv = SL::Helper::Csv->new(
 
 150 description;partnumber;sellprice;lastcost_as_number;buchungsgruppe;
 
 151 Kaffee;;0.12;1,221.52;Standard 7%
 
 152 Beer;1123245;0.12;1.5234;16 %
 
 154   numberformat => '1,000.00',
 
 156     profile => {buchungsgruppe => "buchungsgruppen.description"},
 
 157     class  => 'SL::DB::Part',
 
 161 isa_ok $csv->get_objects->[0]->buchungsgruppe, 'SL::DB::Buchungsgruppe', 'deep dispatch auto vivify works';
 
 162 is $csv->get_objects->[0]->buchungsgruppe->description, 'Standard 7%', '...and gets set correctly';
 
 167 $csv = SL::Helper::Csv->new(
 
 169 description;partnumber;sellprice;lastcost_as_number;make_1;model_1;
 
 170   Kaffee;;0.12;1,221.52;213;Chair 0815
 
 171 Beer;1123245;0.12;1.5234;
 
 173   numberformat => '1,000.00',
 
 176       make_1 => "makemodels.0.make",
 
 177       model_1 => "makemodels.0.model",
 
 179     class  => 'SL::DB::Part',
 
 183 my @mm = $csv->get_objects->[0]->makemodel;
 
 184 is scalar @mm,  1, 'one-to-many dispatch';
 
 185 is $csv->get_objects->[0]->makemodels->[0]->model, 'Chair 0815', '... and works';
 
 190 $csv = SL::Helper::Csv->new(
 
 192 description;partnumber;sellprice;lastcost_as_number;make_1;model_1;make_2;model_2;
 
 193  Kaffee;;0.12;1,221.52;213;Chair 0815;523;Table 15
 
 195   numberformat => '1,000.00',
 
 198       make_1 => "makemodels.0.make",
 
 199       model_1 => "makemodels.0.model",
 
 200       make_2 => "makemodels.1.make",
 
 201       model_2 => "makemodels.1.model",
 
 203     class  => 'SL::DB::Part',
 
 208 print Dumper($csv->errors);
 
 210 @mm = $csv->get_objects->[0]->makemodel;
 
 211 is scalar @mm,  1, 'multiple one-to-many dispatch';
 
 212 is $csv->get_objects->[0]->makemodels->[0]->model, 'Chair 0815', '...check 1';
 
 213 is $csv->get_objects->[0]->makemodels->[0]->make, '213', '...check 2';
 
 214 is $csv->get_objects->[0]->makemodels->[1]->model, 'Table 15', '...check 3';
 
 215 is $csv->get_objects->[0]->makemodels->[1]->make, '523', '...check 4';
 
 219 $csv = SL::Helper::Csv->new(
 
 221 description;partnumber;sellprice;lastcost_as_number;buchungsgruppe;
 
 223   numberformat => '1,000.00',
 
 225     profile => {buchungsgruppe => "buchungsgruppen.1.description"},
 
 226     class  => 'SL::DB::Part',
 
 229 is $csv->parse, undef, 'wrong profile gets rejected';
 
 230 is_deeply $csv->errors, [ 'buchungsgruppen.1.description', undef, "Profile path error. Indexed relationship is not OneToMany around here: 'buchungsgruppen.1'", undef ,0 ], 'error indicates wrong header';
 
 231 isa_ok( ($csv->errors)[0], 'SL::Helper::Csv::Error', 'Errors get objectified');
 
 235 $csv = SL::Helper::Csv->new(
 
 237 description;partnumber;sellprice;lastcost;wiener;
 
 238 Kaffee;;0.12;1,221.52;ja wiener
 
 239 Beer;1123245;0.12;1.5234;nein kein wieder
 
 241   numberformat => '1,000.00',
 
 242   ignore_unknown_columns => 1,
 
 245     profile => {lastcost => 'lastcost_as_number'},
 
 246     class  => 'SL::DB::Part',
 
 250 is $csv->get_objects->[0]->lastcost, '1221.52', 'strict_profile with ignore';
 
 251 is $csv->get_objects->[0]->sellprice, undef,  'strict profile with ignore 2';
 
 255 $csv = SL::Helper::Csv->new(
 
 257 description;partnumber;sellprice;lastcost;wiener;
 
 258 Kaffee;;0.12;1,221.52;ja wiener
 
 259 Beer;1123245;0.12;1.5234;nein kein wieder
 
 261   numberformat => '1,000.00',
 
 264     profile => {lastcost => 'lastcost_as_number'},
 
 265     class  => 'SL::DB::Part',
 
 270 is_deeply( ($csv->errors)[0], [ 'description', undef, 'header field \'description\' is not recognized', undef, 0 ], 'strict_profile without ignore_columns throws error');
 
 274 $csv = SL::Helper::Csv->new(
 
 275   file   => \"Kaffee",       # " # make emacs happy
 
 276   header =>  [ 'description' ],
 
 277   profile => [{class  => 'SL::DB::Part'}],
 
 280 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'eol bug at the end of files';
 
 284 $csv = SL::Helper::Csv->new(
 
 285   file   => \"Description\nKaffee",        # " # make emacs happy
 
 286   case_insensitive_header => 1,
 
 288     profile => { description => 'description' },
 
 289     class  => 'SL::DB::Part'
 
 293 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive header from csv works';
 
 297 $csv = SL::Helper::Csv->new(
 
 298   file   => \"Kaffee",          # " # make emacs happy
 
 299   header =>  [ 'Description' ],
 
 300   case_insensitive_header => 1,
 
 302     profile => { description => 'description' },
 
 303     class  => 'SL::DB::Part'
 
 307 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'case insensitive header as param works';
 
 311 $csv = SL::Helper::Csv->new(
 
 312   file   => \"\x{EF}\x{BB}\x{BF}description\nKaffee",           # " # make emacs happy
 
 313   profile => [{class  => 'SL::DB::Part'}],
 
 317 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'utf8 BOM works (bug 1872)';
 
 321 $csv = SL::Helper::Csv->new(
 
 322   file   => \"Kaffee",            # " # make emacs happy
 
 323   header => [ 'Description' ],
 
 324   profile => [{class  => 'SL::DB::Part'}],
 
 327 is_deeply $csv->get_data, undef, 'case insensitive header without flag ignores';
 
 331 $csv = SL::Helper::Csv->new(
 
 332   file   => \"Kaffee",            # " # make emacs happy
 
 335     profile => { foo => '' },
 
 336     class  => 'SL::DB::Part',
 
 341 is_deeply $csv->get_data, [ { foo => 'Kaffee' } ], 'empty path still gets parsed into data';
 
 342 ok $csv->get_objects->[0], 'empty path gets ignored in object creation';
 
 346 $csv = SL::Helper::Csv->new(
 
 347   file   => \"Kaffee",            # " # make emacs happy
 
 351     profile => { foo => '' },
 
 352     class  => 'SL::DB::Part',
 
 357 is_deeply $csv->get_data, [ { foo => 'Kaffee' } ], 'empty path still gets parsed into data (strict profile)';
 
 358 ok $csv->get_objects->[0], 'empty path gets ignored in object creation (strict profile)';
 
 360 $csv = SL::Helper::Csv->new(
 
 361   file   => \"Phil",            # " # make emacs happy
 
 362   header => [ 'CVAR_grOUnDHog' ],
 
 364   case_insensitive_header => 1,
 
 366     profile => { cvar_Groundhog => '' },
 
 367     class  => 'SL::DB::Part',
 
 373 is_deeply $csv->get_data, [ { cvar_Groundhog => 'Phil' } ], 'using empty path to get cvars working';
 
 374 ok $csv->get_objects->[0], '...and not destorying the objects';
 
 378 $csv = SL::Helper::Csv->new(
 
 379   file   => \"description\nKaffee",            # " # make emacs happy
 
 382 is_deeply $csv->get_data, [ { description => 'Kaffee' } ], 'without profile and class works';
 
 386 $csv = SL::Helper::Csv->new(
 
 388 description;partnumber
 
 395 # Note: The second last line is not empty. The description is a space character.
 
 398 is_deeply $csv->get_data, [ {partnumber => 1, description => 'Kaffee'}, {partnumber => '', description => ' '}, {partnumber => 3, description => 'Tee'} ], 'ignoring empty lines works (header in csv file)';
 
 402 $csv = SL::Helper::Csv->new(
 
 410 # Note: The second last line is not empty. The description is a space character.
 
 411   header => ['description', 'partnumber'],
 
 414 is_deeply $csv->get_data, [ {partnumber => 1, description => 'Kaffee'}, {partnumber => '', description => ' '}, {partnumber => 3, description => 'Tee'} ], 'ignoring empty lines works';
 
 418 $csv = SL::Helper::Csv->new(
 
 419   file    => \"Kaffee;1,50\nSchoke;0,89\n",
 
 421     [ 'datatype', 'description', 'sellprice' ],
 
 424     { profile   => { sellprice => 'sellprice_as_number' },
 
 425       class     => 'SL::DB::Part',}
 
 429 ok $csv->_check_multiplexed, 'multiplex check works on not-multiplexed data';
 
 430 ok !$csv->is_multiplexed, 'not-multiplexed data is recognized';
 
 433 $csv = SL::Helper::Csv->new(
 
 434   file    => \"P;Kaffee;1,50\nC;Meier\n",
 
 436     [ 'datatype', 'description', 'listprice' ],
 
 437     [ 'datatype', 'name' ],
 
 440     { profile   => { listprice => 'listprice_as_number' },
 
 441       class     => 'SL::DB::Part',
 
 443     { class  => 'SL::DB::Customer',
 
 448 ok $csv->_check_multiplexed, 'multiplex check works on multiplexed data';
 
 449 ok $csv->is_multiplexed, 'multiplexed data is recognized';
 
 452 $csv = SL::Helper::Csv->new(
 
 453   file    => \"P;Kaffee;1,50\nC;Meier\n",
 
 455     [ 'datatype', 'description', 'listprice' ],
 
 456     [ 'datatype', 'name' ],
 
 459     { profile   => { listprice => 'listprice_as_number' },
 
 460       class     => 'SL::DB::Part', },
 
 461     { class  => 'SL::DB::Customer',
 
 466 ok !$csv->_check_multiplexed, 'multiplex check works on multiplexed data and detects missing row_ident';
 
 469 $csv = SL::Helper::Csv->new(
 
 470   file    => \"P;Kaffee;1,50\nC;Meier\n",
 
 472     [ 'datatype', 'description', 'listprice' ],
 
 473     [ 'datatype', 'name' ],
 
 476     { profile   => { listprice => 'listprice_as_number' },
 
 478     { class  => 'SL::DB::Customer',
 
 483 ok !$csv->_check_multiplexed, 'multiplex check works on multiplexed data and detects missing class';
 
 486 $csv = SL::Helper::Csv->new(
 
 487   file    => \"P;Kaffee;1,50\nC;Meier\n",  # " # make emacs happy
 
 489     [ 'datatype', 'description', 'listprice' ],
 
 492     { profile   => { listprice => 'listprice_as_number' },
 
 493       class     => 'SL::DB::Part',
 
 495     { class  => 'SL::DB::Customer',
 
 500 ok !$csv->_check_multiplexed, 'multiplex check works on multiplexed data and detects missing header';
 
 504 $csv = SL::Helper::Csv->new(
 
 505   file    => \"P;Kaffee;1,50\nC;Meier\n",  # " # make emacs happy
 
 507     [ 'datatype', 'description', 'listprice' ],
 
 508     [ 'datatype', 'name' ],
 
 511     { profile   => { listprice => 'listprice_as_number' },
 
 512       class     => 'SL::DB::Part',
 
 514     { class  => 'SL::DB::Customer',
 
 517   ignore_unknown_columns => 1,
 
 521 is_deeply $csv->get_data,
 
 522     [ { datatype => 'P', description => 'Kaffee', listprice => '1,50' }, { datatype => 'C', name => 'Meier' } ],
 
 523     'multiplex: simple case works';
 
 524 is scalar @{ $csv->get_objects }, 2, 'multiplex: multiple objects work';
 
 525 is $csv->get_objects->[0]->description, 'Kaffee', 'multiplex: first object';
 
 526 is $csv->get_objects->[1]->name,        'Meier',  'multiplex: second object';
 
 530 $csv = SL::Helper::Csv->new(
 
 531   file    => \"datatype;description;listprice\ndatatype;name\nP;Kaffee;1,50\nC;Meier\n",  # " # make emacs happy
 
 533     { profile   => { listprice => 'listprice_as_number' },
 
 534       class     => 'SL::DB::Part',
 
 536     { class  => 'SL::DB::Customer',
 
 539   ignore_unknown_columns => 1,
 
 543 is scalar @{ $csv->get_objects }, 2, 'multiplex: auto header works';
 
 544 is $csv->get_objects->[0]->description, 'Kaffee', 'multiplex: auto header first object';
 
 545 is $csv->get_objects->[1]->name,        'Meier',  'multiplex: auto header second object';
 
 549 $csv = SL::Helper::Csv->new(
 
 557 # " # make emacs happy
 
 559               {class  => 'SL::DB::Part',     row_ident => 'P'},
 
 560               {class  => 'SL::DB::Customer', row_ident => 'C'},
 
 562   ignore_unknown_columns => 1,
 
 564 is $csv->parse, undef, 'multiplex: broken csv header won\'t get parsed';
 
 568 $csv = SL::Helper::Csv->new(
 
 575 # " # make emacs happy
 
 577               {class  => 'SL::DB::Part',     row_ident => 'P'},
 
 578               {class  => 'SL::DB::Customer', row_ident => 'C'},
 
 580   header  => [ [], ['name'] ],
 
 581   ignore_unknown_columns => 1,
 
 583 ok !$csv->_check_multiplexed, 'multiplex check detects empty header';
 
 587 $csv = SL::Helper::Csv->new(
 
 588   file   => \ Encode::encode('utf-8', <<EOL),
 
 589 description;longdescription;datatype
 
 590 name;customernumber;datatype
 
 591 Kaffee;"lecker Kaffee";P
 
 596 # " # make emacs happy
 
 598               {class  => 'SL::DB::Part',     row_ident => 'P'},
 
 599               {class  => 'SL::DB::Customer', row_ident => 'C'},
 
 601   ignore_unknown_columns => 1,
 
 604 is $csv->_multiplex_datatype_position, 2, 'multiplex check detects datatype field position right';
 
 606 is_deeply $csv->get_data, [ { datatype => 'P', description => 'Kaffee', longdescription => 'lecker Kaffee' },
 
 607                             { datatype => 'C', name => 'Meier', customernumber => 1},
 
 608                             { datatype => 'P', description => 'Bier', longdescription => 'kühles Bier' },
 
 609                             { datatype => 'C', name => 'Mueller', customernumber => 2}
 
 611                           'multiplex: datatype not at first position works';
 
 615 $csv = SL::Helper::Csv->new(
 
 616   file   => \ Encode::encode('utf-8', <<EOL),
 
 617 datatype;description;longdescription
 
 618 name;datatype;customernumber
 
 619 P;Kaffee;"lecker Kaffee"
 
 624 # " # make emacs happy
 
 626               {class  => 'SL::DB::Part',     row_ident => 'P'},
 
 627               {class  => 'SL::DB::Customer', row_ident => 'C'},
 
 629   ignore_unknown_columns => 1,
 
 631 ok !$csv->parse, 'multiplex check detects incosistent datatype field position';
 
 632 is_deeply( ($csv->errors)[0], [ 0, 'datatype field must be at the same position for all datatypes for multiplexed data', 0, 0 ], 'multiplex data with inconsistent datatype field posiotion throws error');
 
 636 $csv = SL::Helper::Csv->new(
 
 637   file   => \"Datatype;Description\nDatatype;Name\nP;Kaffee\nC;Meier",        # " # make emacs happy
 
 638   case_insensitive_header => 1,
 
 639   ignore_unknown_columns => 1,
 
 642       profile   => { datatype => 'datatype', description => 'description' },
 
 643       class     => 'SL::DB::Part',
 
 647       profile   => { datatype => 'datatype', name => 'name' },
 
 648       class     => 'SL::DB::Customer',
 
 654 is_deeply $csv->get_data, [ { datatype => 'P', description => 'Kaffee' },
 
 655                             { datatype => 'C', name => 'Meier'} ],
 
 656                           'multiplex: case insensitive header from csv works';
 
 660 $csv = SL::Helper::Csv->new(
 
 661   file   => \"P;Kaffee\nC;Meier",          # " # make emacs happy
 
 662   header =>  [[ 'Datatype', 'Description' ], [ 'Datatype', 'Name']],
 
 663   case_insensitive_header => 1,
 
 664   ignore_unknown_columns => 1,
 
 667       profile   => { datatype => 'datatype', description => 'description' },
 
 668       class     => 'SL::DB::Part',
 
 672       profile => { datatype => 'datatype', name => 'name' },
 
 673       class  => 'SL::DB::Customer',
 
 679 is_deeply $csv->get_data, [ { datatype => 'P', description => 'Kaffee' },
 
 680                             { datatype => 'C', name => 'Meier' } ],
 
 681                           'multiplex: case insensitive header as param works';
 
 686 $csv = SL::Helper::Csv->new(
 
 687   file   => \"P;Kaffee\nC;Meier",          # " # make emacs happy
 
 688   header =>  [[ 'Datatype', 'Description' ], [ 'Datatype', 'Name']],
 
 691       profile   => { datatype => 'datatype', description => 'description' },
 
 692       class     => 'SL::DB::Part',
 
 696       profile => { datatype => 'datatype', name => 'name' },
 
 697       class  => 'SL::DB::Customer',
 
 703 is_deeply $csv->get_data, undef, 'multiplex: case insensitive header without flag ignores';
 
 707 $csv = SL::Helper::Csv->new(
 
 712 # " # make emacs happy
 
 713   header => [[ 'datatype', 'Afoo', 'Abar' ], [ 'datatype', 'Bfoo', 'Bbar']],
 
 715     profile   => { datatype => '', Afoo => '', Abar => '' },
 
 716     class     => 'SL::DB::Part',
 
 720     profile   => { datatype => '', Bfoo => '', Bbar => '' },
 
 721     class     => 'SL::DB::Customer',
 
 727 is_deeply $csv->get_data,
 
 728     [ { datatype => 'P', Afoo => 'Kaffee', Abar => 'lecker' }, { datatype => 'C', Bfoo => 'Meier', Bbar => 'froh' } ],
 
 729     'multiplex: empty path still gets parsed into data';
 
 730 ok $csv->get_objects->[0], 'multiplex: empty path gets ignored in object creation';
 
 734 $csv = SL::Helper::Csv->new(
 
 739 # " # make emacs happy
 
 740   header => [[ 'datatype', 'Afoo', 'Abar' ], [ 'datatype', 'Bfoo', 'Bbar']],
 
 743     profile   => { datatype => '', Afoo => '', Abar => '' },
 
 744     class     => 'SL::DB::Part',
 
 748     profile   => { datatype => '', Bfoo => '', Bbar => '' },
 
 749     class     => 'SL::DB::Customer',
 
 755 is_deeply $csv->get_data,
 
 756     [ { datatype => 'P', Afoo => 'Kaffee', Abar => 'lecker' }, { datatype => 'C', Bfoo => 'Meier', Bbar => 'froh' } ],
 
 757     'multiplex: empty path still gets parsed into data (strict profile)';
 
 758 ok $csv->get_objects->[0], 'multiplex: empty path gets ignored in object creation (strict profile)';
 
 762 $csv = SL::Helper::Csv->new(
 
 764 datatype;customernumber;name
 
 765 datatype;description;partnumber
 
 775   ignore_unknown_columns => 1,
 
 776   profile => [ { class => 'SL::DB::Customer', row_ident => 'C' },
 
 777                { class => 'SL::DB::Part',     row_ident => 'P' },
 
 781 is_deeply $csv->get_data, [
 
 782   {datatype => 'C', customernumber => 1000, name => 'Meier'},
 
 783   {datatype => 'P', partnumber => 1, description => 'Kaffee'},
 
 784   {datatype => 'C', customernumber => undef, name => undef},
 
 785   {datatype => 'P', partnumber => '', description => ' '},
 
 786   {datatype => 'C', customernumber => 2000, name => 'Meister'},
 
 787   {datatype => 'P', partnumber => '3', description => 'Tee'},
 
 788 ], 'ignoring empty lines works (multiplex data)';
 
 794 $csv = SL::Helper::Csv->new(
 
 796 description,sellprice,lastcost_as_number,purchaseprice,
 
 797 Kaffee,0.12,'12,2','1,5234'
 
 803       profile => { listprice => 'listprice_as_number' },
 
 804       mapping => { purchaseprice => 'listprice' },
 
 805       class   => 'SL::DB::Part',
 
 809 ok $csv->parse, 'simple mapping parses';
 
 810 is $csv->get_objects->[0]->listprice, 1.5234, 'simple mapping works';
 
 812 $csv = SL::Helper::Csv->new(
 
 814 description;partnumber;sellprice;purchaseprice;wiener;
 
 815 Kaffee;;0.12;1,221.52;ja wiener
 
 816 Beer;1123245;0.12;1.5234;nein kein wieder
 
 818   numberformat => '1,000.00',
 
 819   ignore_unknown_columns => 1,
 
 822     profile => { lastcost => 'lastcost_as_number' },
 
 823     mapping => { purchaseprice => 'lastcost' },
 
 824     class  => 'SL::DB::Part',
 
 827 ok $csv->parse, 'strict mapping parses';
 
 828 is $csv->get_objects->[0]->lastcost, 1221.52, 'strict mapping works';
 
 831 $csv = SL::Helper::Csv->new(
 
 833 description;partnumber;sellprice;lastcost;wiener;
 
 834 Kaffee;1;0.12;1,221.52;ja wiener
 
 835 Beer;1123245;0.12;1.5234;nein kein wieder
 
 837   numberformat => '1,000.00',
 
 838   ignore_unknown_columns => 1,
 
 841     mapping => { partnumber => 'description', description => 'partnumber' },
 
 842     class  => 'SL::DB::Part',
 
 845 ok $csv->parse, 'swapping parses';
 
 846 is $csv->get_objects->[0]->partnumber, 'Kaffee', 'strict mapping works 1';
 
 847 is $csv->get_objects->[0]->description, '1', 'strict mapping works 2';
 
 849 # case insensitive shit
 
 850 $csv = SL::Helper::Csv->new(
 
 851   file   => \"Description\nKaffee",        # " # make emacs happy
 
 852   case_insensitive_header => 1,
 
 854     mapping => { description => 'description' },
 
 855     class  => 'SL::DB::Part'
 
 859 is $csv->get_objects->[0]->description, 'Kaffee', 'case insensitive mapping without profile works';
 
 861 # case insensitive shit
 
 862 $csv = SL::Helper::Csv->new(
 
 863   file   => \"Price\n4,99",        # " # make emacs happy
 
 864   case_insensitive_header => 1,
 
 866     profile => { sellprice => 'sellprice_as_number' },
 
 867     mapping => { price => 'sellprice' },
 
 868     class  => 'SL::DB::Part',
 
 872 is $csv->get_objects->[0]->sellprice, 4.99, 'case insensitive mapping with profile works';
 
 875 # self-mapping with profile
 
 876 $csv = SL::Helper::Csv->new(
 
 877   file   => \"sellprice\n4,99",        # " # make emacs happy
 
 878   case_insensitive_header => 1,
 
 880     profile => { sellprice => 'sellprice_as_number' },
 
 881     mapping => { sellprice => 'sellprice' },
 
 882     class  => 'SL::DB::Part',
 
 886 is $csv->get_objects->[0]->sellprice, 4.99, 'self-mapping with profile works';
 
 888 # self-mapping without profile
 
 889 $csv = SL::Helper::Csv->new(
 
 890   file   => \"sellprice\n4.99",        # " # make emacs happy
 
 891   case_insensitive_header => 1,
 
 893     mapping => { sellprice => 'sellprice' },
 
 894     class  => 'SL::DB::Part',
 
 898 is $csv->get_objects->[0]->sellprice, 4.99, 'self-mapping without profile works';
 
 901 # set emacs to perl mode