#!/usr/bin/perl our $VERSION = '0.0.1'; use strict; use warnings FATAL => qw(all); use utf8; use open qw/:std :utf8/; require Data::Dumper; require Encode; require IO::Wrap; require Text::CSV; #require Text::CSV::Encoded; require XML::Generator; require Text::Trim; sub parse_date ($) { my ($_) = @_; if ($_) { my ($jj,$mm,undef,$yy) = ($_ =~ m{^\s*([0-3]?[0-9])\s*/\s*([0-1]?[0-9])\s*/\s*(20)?([0-9][0-9])\s*$}); return "20$yy-$mm-$jj"; } else { return undef }; } sub parse_euro ($) { my ($_) = @_; if ($_) { my ($num) = ($_ =~ m{^\s*([0-9]+),00\s*€?.$}); return $num; } else { return undef }; } sub parse_line (@) { my ($pass, $xml, $number_next, $adh, $data, $data_noupdate, $data_rejected, $data_reparse) = @_; my ($number, $date_cot1, $cot1, $moyen_cot1, $reduction, $genre, $prenom, $nom, $naissance , $email, $tel_fixe, $tel_mobile, $addr_postale, $cp, $city, $comment) = #map {Text::Trim::trim($_)} @$adh; my $partner = "cyclofficine_ivry"; $number = Text::Trim::trim($number); if (not ($number =~ m/^[0-9]+$/)) { if ($pass == 0) { push @$data_reparse, $adh; return ($number_next); } else { $comment =($comment?"$comment. ":"") ."(n° malformé d'origine : $number)"; $number = "$number_next"; } } if ($number =~ m/^[0-9]+$/) { if ($nom or $email) { $number = $number + 0; $number_next = $number + 1; $date_cot1 = parse_date($date_cot1); #$date_cot2 = parse_date($date_cot2); $cot1 = parse_euro($cot1); #$cot2 = parse_euro($cot2); my $city = ($cp and ($cp =~ m/^750[0-2][0-9]$/) ? "Paris" : undef); my $country = ($cp and ($cp =~ m/^UK$/) ? "Royaume-Uni" : "France"); my $phone = undef; my $street = undef; my %reductions = ( "Chômeur" => "unemployed" , "Chmeur" => "unemployed" , "Atelier vélo IdF" => "velorution_idf" , "Étudiant" => "student" , "Etudiant" => "student" , "etudiant" => "student" , "Retraité" => "retired" ); $reduction = Text::Trim::trim($reduction); $reduction = exists $reductions{$reduction} ? $reductions{$reduction} : "standard"; my %pay_accounts = ( "Espèces" => "cash" , "Chèque" => "bank" ); my $pay_account_cot1 = Text::Trim::trim($moyen_cot1); $pay_account_cot1 = exists $pay_accounts{$pay_account_cot1} ? $pay_accounts{$pay_account_cot1} : "cash"; push @$data, $xml->record ( { id => "res_partner_${partner}_$number" , model => "res.partner" } , $xml->field({name => "name"}, $nom . ($prenom ? " $prenom" : "")) , $xml->field({name => "member_ident"}, $number) , $xml->field({name => "type"}, "default") , ($cp ? $xml->field({name => "zip"}, $cp) : ()) , ($city ? $xml->field({name => "city"}, $city) : ()) , ($country ? $xml->field({name => "country_id", model => "res.country", search => "[('name','=','$country')]"}) : ()) , ($email ? $xml->field({name => "email"}, $email) : ()) , ($phone ? $xml->field({name => "phone"}) : ()) , ($addr_postale? $xml->field({name => "street"}, $addr_postale) : ()) , ($comment ? $xml->field({name => "comment"}, $comment) : ()) ); my %cots = ( ($cot1 ? ($cot1 => $date_cot1) : ()) #, ($cot2 ? ($cot2 => $date_cot2) : ()) ) ; while ( my ($amount, $date_from) = each(%cots) ) { push @$data_noupdate, $xml->function ( { model => "account.invoice" , name => "pay_and_reconcile" } , $xml->xmlcmnt('ids') , $xml->function ( { model => "account.invoice" , name => "draft2open" } , $xml->function ( { model => "res.partner" , name => "create_membership_invoice" } , $xml->xmlcmnt('partner_id') , $xml->value({eval => "ref('res_partner_${partner}_$number')"}) , $xml->xmlcmnt('product_id') , $xml->value({eval => "ref('product_${reduction}_member')"}) , $xml->xmlcmnt('context') , $xml->value({eval => "{'amount':$amount, 'date_from':'$date_from'}"}) ) ) , $xml->xmlcmnt('pay_amount') , $xml->value ({eval => "$amount"}) , $xml->xmlcmnt('pay_account_id') , $xml->value ({model => "account.account", search => "[('name', '=', 'Cash')]"}) , $xml->xmlcmnt("moyen_cot1: $moyen_cot1") , $xml->xmlcmnt('period_id') , $xml->value ({model => "account.period", search => "[('name', '=', time.strftime('%m/%Y'))]"}) , $xml->xmlcmnt('pay_journal_id') , $xml->value ({model => "account.journal", search => "[('name', '=', 'Cash')]"}) , $xml->xmlcmnt('writeoff_acc_id') , $xml->value ({model => "account.account", search => "[('name', '=', 'Cash')]"}) , $xml->xmlcmnt('writeoff_period_id') , $xml->value ({model => "account.period", search => "[('name', '=', time.strftime('%m/%Y'))]"}) , $xml->xmlcmnt('writeoff_journal_id') , $xml->value ({model => "account.journal", search => "[('name', '=', 'Cash')]"}) , $xml->xmlcmnt('context') , $xml->value ({eval => "{}"}) , $xml->xmlcmnt('name') , $xml->value ({eval => "str('Import de paiement automatique')"}) ); } } else { push @$data_rejected, $adh; } } return ($number_next); } sub main () { my $csv = Text::CSV->new ({ binary => 1, eol => $/ , sep_char => ';' }); my $xml = XML::Generator->new ( escape => 'always' , conformance => 'strict' , empty => 'self' , pretty => 2 ); my $in = IO::Wrap::wraphandle(\*STDIN); my $csv_head = $csv->getline($in); #print STDERR ("head: ", join("|", @$csv_head), "\n"); $csv->column_names(@$csv_head); my $data = []; my $data_noupdate = []; my $data_rejected = []; my $data_reparse = []; my $number_next = 1; while (my $adh = $csv->getline($in)) { #print STDERR ("line: ", join("|", @$adh), "\n"); ($number_next) = parse_line(0, $xml, $number_next, $adh, $data, $data_noupdate, $data_rejected, $data_reparse); } foreach (@$data_reparse) { ($number_next) = parse_line(1, $xml, $number_next, $_, $data, $data_noupdate, $data_rejected, []); } push @$data_noupdate, $xml->record ( { id => "remembership.member_ident_sequence" , model => "ir.sequence" } , $xml->field({name => "number_next"}, $number_next) ); binmode STDOUT, ':utf8'; print $xml->openerp ( $xml->data(@$data) , $xml->data ( {noupdate=>"1"} , @$data_noupdate ) ); my $out = IO::Wrap::wraphandle(\*STDERR); foreach (@$data_rejected) { $csv->print($out, $_); } } main;