1037b279b3d4e882aeafb8bda3309840232b12dd
[burette/cyclofficine_ivry.git] / data / members.import
1 #!/usr/bin/perl
2
3 our $VERSION = '0.0.1';
4 use strict;
5 use warnings FATAL => qw(all);
6 use utf8;
7 use open qw/:std :utf8/;
8 require Data::Dumper;
9 require Encode;
10 require IO::Wrap;
11 require Text::CSV;
12 #require Text::CSV::Encoded;
13 require XML::Generator;
14 require Text::Trim;
15
16 sub parse_date ($) {
17 my ($_) = @_;
18 if ($_) {
19 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*$});
20 return "20$yy-$mm-$jj";
21 }
22 else { return undef };
23 }
24 sub parse_euro ($) {
25 my ($_) = @_;
26 if ($_) {
27 my ($num) = ($_ =~ m{^\s*([0-9]+),00\s*€?.$});
28 return $num;
29 }
30 else { return undef };
31 }
32 sub parse_line (@) {
33 my ($pass, $xml, $number_next, $adh, $data, $data_noupdate, $data_rejected, $data_reparse) = @_;
34 my ($number, $date_cot1, $cot1, $moyen_cot1, $reduction, $genre, $prenom, $nom, $naissance
35 , $email, $tel_fixe, $tel_mobile, $addr_postale, $cp, $city, $comment) =
36 #map {Text::Trim::trim($_)}
37 @$adh;
38 my $partner = "cyclofficine_ivry";
39 $number = Text::Trim::trim($number);
40 if (not ($number =~ m/^[0-9]+$/)) {
41 if ($pass == 0) {
42 push @$data_reparse, $adh;
43 return ($number_next);
44 }
45 else {
46 $comment
47 =($comment?"$comment. ":"")
48 ."(n° malformé d'origine : $number)";
49 $number = "$number_next";
50 }
51 }
52 if ($number =~ m/^[0-9]+$/) {
53 if ($nom or $email) {
54 $number = $number + 0;
55 $number_next = $number + 1;
56 $date_cot1 = parse_date($date_cot1);
57 #$date_cot2 = parse_date($date_cot2);
58 $cot1 = parse_euro($cot1);
59 #$cot2 = parse_euro($cot2);
60 my $city = ($cp and ($cp =~ m/^750[0-2][0-9]$/) ? "Paris" : undef);
61 my $country = ($cp and ($cp =~ m/^UK$/) ? "Royaume-Uni" : "France");
62 my $phone = undef;
63 my $street = undef;
64 my %reductions =
65 ( "Chômeur" => "unemployed"
66 , "Chmeur" => "unemployed"
67 , "Atelier vélo IdF" => "velorution_idf"
68 , "Étudiant" => "student"
69 , "Etudiant" => "student"
70 , "etudiant" => "student"
71 , "Retraité" => "retired"
72 );
73 $reduction = Text::Trim::trim($reduction);
74 $reduction
75 = exists $reductions{$reduction}
76 ? $reductions{$reduction}
77 : "standard";
78 my %pay_accounts =
79 ( "Espèces" => "cash"
80 , "Chèque" => "bank"
81 );
82 my $pay_account_cot1 = Text::Trim::trim($moyen_cot1);
83 $pay_account_cot1
84 = exists $pay_accounts{$pay_account_cot1}
85 ? $pay_accounts{$pay_account_cot1}
86 : "cash";
87 push @$data, $xml->record
88 ( { id => "res_partner_${partner}_$number"
89 , model => "res.partner"
90 }
91 , $xml->field({name => "name"}, $nom . ($prenom ? " $prenom" : ""))
92 , $xml->field({name => "member_ident"}, $number)
93 , $xml->field({name => "type"}, "default")
94 , ($cp ? $xml->field({name => "zip"}, $cp) : ())
95 , ($city ? $xml->field({name => "city"}, $city) : ())
96 , ($country ? $xml->field({name => "country_id", model => "res.country", search => "[('name','=','$country')]"}) : ())
97 , ($email ? $xml->field({name => "email"}, $email) : ())
98 , ($phone ? $xml->field({name => "phone"}) : ())
99 , ($addr_postale? $xml->field({name => "street"}, $addr_postale) : ())
100 , ($comment ? $xml->field({name => "comment"}, $comment) : ())
101 );
102 my %cots =
103 ( ($cot1 ? ($cot1 => $date_cot1) : ())
104 #, ($cot2 ? ($cot2 => $date_cot2) : ())
105 ) ;
106 while ( my ($amount, $date_from) = each(%cots) ) {
107 push @$data_noupdate, $xml->function
108 ( { model => "account.invoice"
109 , name => "pay_and_reconcile"
110 }
111 , $xml->xmlcmnt('ids')
112 , $xml->function
113 ( { model => "account.invoice"
114 , name => "draft2open"
115 }
116 , $xml->function
117 ( { model => "res.partner"
118 , name => "create_membership_invoice"
119 }
120 , $xml->xmlcmnt('partner_id')
121 , $xml->value({eval => "ref('res_partner_${partner}_$number')"})
122 , $xml->xmlcmnt('product_id')
123 , $xml->value({eval => "ref('product_${reduction}_member')"})
124 , $xml->xmlcmnt('context')
125 , $xml->value({eval => "{'amount':$amount, 'date_from':'$date_from'}"})
126 )
127 )
128 , $xml->xmlcmnt('pay_amount')
129 , $xml->value ({eval => "$amount"})
130 , $xml->xmlcmnt('pay_account_id')
131 , $xml->value ({model => "account.account", search => "[('name', '=', 'Cash')]"})
132 , $xml->xmlcmnt("moyen_cot1: $moyen_cot1")
133 , $xml->xmlcmnt('period_id')
134 , $xml->value ({model => "account.period", search => "[('name', '=', time.strftime('%m/%Y'))]"})
135 , $xml->xmlcmnt('pay_journal_id')
136 , $xml->value ({model => "account.journal", search => "[('name', '=', 'Cash')]"})
137 , $xml->xmlcmnt('writeoff_acc_id')
138 , $xml->value ({model => "account.account", search => "[('name', '=', 'Cash')]"})
139 , $xml->xmlcmnt('writeoff_period_id')
140 , $xml->value ({model => "account.period", search => "[('name', '=', time.strftime('%m/%Y'))]"})
141 , $xml->xmlcmnt('writeoff_journal_id')
142 , $xml->value ({model => "account.journal", search => "[('name', '=', 'Cash')]"})
143 , $xml->xmlcmnt('context')
144 , $xml->value ({eval => "{}"})
145 , $xml->xmlcmnt('name')
146 , $xml->value ({eval => "str('Import de paiement automatique')"})
147 );
148 }
149 }
150 else {
151 push @$data_rejected, $adh;
152 }
153 }
154 return ($number_next);
155 }
156
157 sub main () {
158 my $csv = Text::CSV->new
159 ({ binary => 1, eol => $/
160 , sep_char => ';'
161 });
162 my $xml = XML::Generator->new
163 ( escape => 'always'
164 , conformance => 'strict'
165 , empty => 'self'
166 , pretty => 2
167 );
168 my $in = IO::Wrap::wraphandle(\*STDIN);
169 my $csv_head = $csv->getline($in);
170 #print STDERR ("head: ", join("|", @$csv_head), "\n");
171 $csv->column_names(@$csv_head);
172 my $data = [];
173 my $data_noupdate = [];
174 my $data_rejected = [];
175 my $data_reparse = [];
176 my $number_next = 1;
177 while (my $adh = $csv->getline($in)) {
178 #print STDERR ("line: ", join("|", @$adh), "\n");
179 ($number_next) = parse_line(0, $xml, $number_next, $adh, $data, $data_noupdate, $data_rejected, $data_reparse);
180 }
181 foreach (@$data_reparse) {
182 ($number_next) = parse_line(1, $xml, $number_next, $_, $data, $data_noupdate, $data_rejected, []);
183 }
184 push @$data_noupdate, $xml->record
185 ( { id => "remembership.member_ident_sequence"
186 , model => "ir.sequence"
187 }
188 , $xml->field({name => "number_next"}, $number_next)
189 );
190 binmode STDOUT, ':utf8';
191 print $xml->openerp
192 ( $xml->data(@$data)
193 , $xml->data
194 ( {noupdate=>"1"}
195 , @$data_noupdate )
196 );
197
198 my $out = IO::Wrap::wraphandle(\*STDERR);
199 foreach (@$data_rejected) {
200 $csv->print($out, $_);
201 }
202 }
203
204 main;