Merge lp:~camptocamp/openobject-addons/6.0-fix-l10n_ch-20110914 into lp:openobject-addons/6.0

Proposed by Yannick Vaucher @ Camptocamp
Status: Needs review
Proposed branch: lp:~camptocamp/openobject-addons/6.0-fix-l10n_ch-20110914
Merge into: lp:openobject-addons/6.0
Diff against target: 2892 lines (+1825/-504)
30 files modified
l10n_ch/__openerp__.py (+6/-3)
l10n_ch/account_move_line.py (+0/-87)
l10n_ch/bank.py (+31/-10)
l10n_ch/bank_view.xml (+190/-27)
l10n_ch/company.py (+17/-0)
l10n_ch/company_view.xml (+14/-6)
l10n_ch/demo/demo.xml (+0/-2)
l10n_ch/dta.py (+0/-85)
l10n_ch/dta_data.xml (+11/-26)
l10n_ch/dta_view.xml (+0/-37)
l10n_ch/invoice.py (+4/-4)
l10n_ch/journal_data.xml (+2/-2)
l10n_ch/partner.py (+0/-31)
l10n_ch/report/bvr.mako (+45/-2)
l10n_ch/report/report_webkit_html.mako (+1/-1)
l10n_ch/report/report_webkit_html.py (+132/-78)
l10n_ch/report/report_webkit_html_view.xml (+51/-49)
l10n_ch/sterchi_chart/account.xml (+2/-2)
l10n_ch/sterchi_chart/fiscal_position.xml (+1/-1)
l10n_ch/test/l10n_ch_dta.yml (+221/-0)
l10n_ch/test/l10n_ch_v11.yml (+161/-0)
l10n_ch/test/l10n_ch_v11_part.yml (+292/-0)
l10n_ch/test/test.v11 (+2/-0)
l10n_ch/test/test_part_1.v11 (+2/-0)
l10n_ch/test/test_part_2.v11 (+2/-0)
l10n_ch/wizard/__init__.py (+3/-2)
l10n_ch/wizard/bvr_import.py (+7/-6)
l10n_ch/wizard/create_dta.py (+35/-27)
l10n_ch/wizard/create_dta_view.xml (+1/-16)
l10n_ch/wizard/unicode2ascii.py (+592/-0)
To merge this branch: bzr merge lp:~camptocamp/openobject-addons/6.0-fix-l10n_ch-20110914
Reviewer Review Type Date Requested Status
OpenERP Core Team Pending
Review via email: mp+75354@code.launchpad.net

This proposal supersedes a proposal from 2011-09-14.

Description of the change

Multiple fix, improvments and adds to l10n_ch from Camptocamp swiss localization

To post a comment you must log in.
Revision history for this message
xrg (xrg) wrote : Posted in a previous version of this proposal

From the very first quick look I had at the diff:

=== ....
=== modified file 'l10n_ch/sample/README' (properties changed: -x to +x)
=== modified file 'l10n_ch/sample/sample.dta' (properties changed: -x to +x)
=== modified file 'l10n_ch/sample/sample.v11' (properties changed: -x to +x)
=== modified file 'l10n_ch/sample/zvr_besrtechdok_fr.pdf' (properties changed: -
x to +x)
.... etc.

Please, do not turn on the executable bit on data files. It produces errors
when trying to package OpenERP.

Also, if you are including files from other python projects, please be prepared
to answer:
 - are these files just standalone, or part of any other python "library"? In
the second case, why not call this library instead of copying (bundling) the
file?
 - what is the copyright of the files? License, distribution policy?

--
Say NO to spam and viruses. Stop using Microsoft Windows!

Revision history for this message
Yannick Vaucher @ Camptocamp (yvaucher-c2c) wrote : Posted in a previous version of this proposal

Thanks for the warning, I updated the branch by reverting those unwanted chmod changes.

Unmerged revisions

4823. By Yannick Vaucher @ Camptocamp

[FIX] revert chmod -x

4822. By Yannick Vaucher @ Camptocamp

[MRG] from c2c l10n_ch

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'l10n_ch/__openerp__.py'
--- l10n_ch/__openerp__.py 2011-02-09 08:59:05 +0000
+++ l10n_ch/__openerp__.py 2011-09-14 14:11:28 +0000
@@ -61,8 +61,8 @@
6161
6262
63""",63""",
64 "version" : "6.0",64 "version" : "6.1",
65 "author" : "Camptocamp SA",65 "author" : "Camptocamp",
66 "category" : "Localization/Account Charts",66 "category" : "Localization/Account Charts",
67 "website": "http://www.camptocamp.com",67 "website": "http://www.camptocamp.com",
6868
@@ -84,10 +84,10 @@
84 ],84 ],
85 "demo_xml" : [85 "demo_xml" : [
86 "demo/demo.xml",86 "demo/demo.xml",
87 "demo/dta_demo.xml",
87 ],88 ],
88 "update_xml" : [89 "update_xml" : [
89 "wizard.xml",90 "wizard.xml",
90 "dta_view.xml",
91 "wizard/bvr_import_view.xml",91 "wizard/bvr_import_view.xml",
92 "wizard/create_dta_view.xml",92 "wizard/create_dta_view.xml",
93 "company_view.xml",93 "company_view.xml",
@@ -98,6 +98,9 @@
98 ],98 ],
99 'test' : [99 'test' : [
100 'test/l10n_ch_report.yml',100 'test/l10n_ch_report.yml',
101 'test/l10n_ch_dta.yml',
102 'test/l10n_ch_v11.yml',
103 'test/l10n_ch_v11_part.yml',
101 ],104 ],
102 "active": False,105 "active": False,
103 "installable": True,106 "installable": True,
104107
=== removed file 'l10n_ch/account_move_line.py'
--- l10n_ch/account_move_line.py 2011-01-14 12:41:54 +0000
+++ l10n_ch/account_move_line.py 1970-01-01 00:00:00 +0000
@@ -1,87 +0,0 @@
1# -*- coding: utf-8 -*-
2#
3# account_move_line.py
4# l10n_ch
5#
6# Created by Nicolas Bessi based on Credric Krier contribution
7#
8# Copyright (c) 2009 CamptoCamp. All rights reserved.
9##############################################################################
10#
11# WARNING: This program as such is intended to be used by professional
12# programmers who take the whole responsability of assessing all potential
13# consequences resulting from its eventual inadequacies and bugs
14# End users who are looking for a ready-to-use solution with commercial
15# garantees and support are strongly adviced to contract a Free Software
16# Service Company
17#
18# This program is Free Software; you can redistribute it and/or
19# modify it under the terms of the GNU General Public License
20# as published by the Free Software Foundation; either version 2
21# of the License, or (at your option) any later version.
22#
23# This program is distributed in the hope that it will be useful,
24# but WITHOUT ANY WARRANTY; without even the implied warranty of
25# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26# GNU General Public License for more details.
27#
28# You should have received a copy of the GNU General Public License
29# along with this program; if not, write to the Free Software
30# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
31#
32##############################################################################
33
34from osv import fields, osv
35# -*- encoding: utf-8 -*-
36##############################################################################
37#
38# Author: Nicolas Bessi. Copyright Camptocamp SA
39# Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
40#
41# This program is free software: you can redistribute it and/or modify
42# it under the terms of the GNU Affero General Public License as
43# published by the Free Software Foundation, either version 3 of the
44# License, or (at your option) any later version.
45#
46# This program is distributed in the hope that it will be useful,
47# but WITHOUT ANY WARRANTY; without even the implied warranty of
48# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
49# GNU Affero General Public License for more details.
50#
51# You should have received a copy of the GNU Affero General Public License
52# along with this program. If not, see <http://www.gnu.org/licenses/>.
53#
54##############################################################################
55
56class AccountMoveLine(osv.osv):
57 """ Inherit account.move.line in order to add a custom link
58 between supplier invoice line and bank. The original link
59 was defined in account_payment between line """
60
61 _inherit = 'account.move.line'
62
63 def line2bank(self, cr, uid, ids, payment_type='manual', context=None):
64 """add a link to account.move.line in order to link
65 supplier invoice line and bank. The original link
66 was defined in account_payment"""
67 payment_mode_obj = self.pool.get('payment.mode')
68 line2bank = {}
69 if not ids:
70 return {}
71 bank_type = payment_mode_obj.suitable_bank_types(cr, uid, payment_type,
72 context=context)
73 for line in self.browse(cr, uid, ids, context=context):
74 if line.invoice and line.invoice.partner_bank_id:
75 line2bank[line.id] = line.invoice.partner_bank_id.id
76 elif line.partner_id:
77 for bank in line.partner_id.bank_ids:
78 if bank.state in bank_type:
79 line2bank[line.id] = bank.id
80 break
81 if line.id not in line2bank and line.partner_id.bank_ids:
82 line2bank[line.id] = line.partner_id.bank_ids[0].id
83 return line2bank
84
85AccountMoveLine()
86
87# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
880
=== modified file 'l10n_ch/bank.py'
--- l10n_ch/bank.py 2011-01-14 12:41:54 +0000
+++ l10n_ch/bank.py 2011-09-14 14:11:28 +0000
@@ -33,15 +33,36 @@
3333
34Bank()34Bank()
3535
36class bvr_checkbox(osv.osv):36
37 """ Add function to generate function """37class ResPartnerBank(osv.osv):
38 _inherit = "res.partner.bank"38 _inherit = "res.partner.bank"
3939
40 _columns = {40 _columns = {
41 'print_bank' : fields.boolean('Print Bank on BVR'),41 'name': fields.char('Description', size=128, required=True),
42 'print_account' : fields.boolean('Print Account Number on BVR'),42 'post_number': fields.char('Post number', size=64),
43 }43 'bvr_adherent_num': fields.char('BVR adherent number', size=11),
4444 'dta_code': fields.char('DTA code', size=5),
45bvr_checkbox()45 'print_bank': fields.boolean('Print Bank on BVR'),
4646 'print_account': fields.boolean('Print Account Number on BVR'),
47# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:47 'my_bank': fields.boolean('Print BVR ?', help="Check to print BVR invoices"),
48 }
49
50 def name_get(self, cursor, uid, ids, context=None):
51 if not len(ids):
52 return []
53 bank_type_obj = self.pool.get('res.partner.bank.type')
54
55 type_ids = bank_type_obj.search(cursor, uid, [])
56 bank_type_names = {}
57 for bank_type in bank_type_obj.browse(cursor, uid, type_ids,
58 context=context):
59 bank_type_names[bank_type.code] = bank_type.name
60 res = []
61 for r in self.read(cursor, uid, ids, ['name','state'], context):
62 res.append((r['id'], r['name']+' : '+bank_type_names.get(r['state'], '')))
63 return res
64
65 _sql_constraints = [('bvr_adherent_uniq', 'unique (bvr_adherent_num)',
66 'The BVR adherent number must be unique !')]
67
68ResPartnerBank()
4869
=== modified file 'l10n_ch/bank_view.xml'
--- l10n_ch/bank_view.xml 2011-01-14 00:11:01 +0000
+++ l10n_ch/bank_view.xml 2011-09-14 14:11:28 +0000
@@ -24,31 +24,194 @@
24 </field>24 </field>
25 </field>25 </field>
26 </record>26 </record>
2727 <!-- res.partner.bank in res partner form-->
28 <record model="ir.ui.view" id="l10nch_view_res_partner_bank">28
29 <field name="name">res.partner_bank.form</field>29 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_hide_f1">
30 <field name="model">res.partner.bank</field>30 <field name="name">res.partner_bank.form.hide.f1</field>
31 <field name="type">form</field>31 <field name="model">res.partner</field>
32 <field name="inherit_id" ref="base.view_partner_bank_form"/>32 <field name="type">form</field>
33 <field name="arch" type="xml">33 <field name="sequence" eval="9" /> <!-- we do this to be called before base iban view -->
34 <field name="country_id" position="after">34 <field name="inherit_id" ref="account.view_partner_property_form"/>
35 <field name="print_bank"/>35 <field name="arch" type="xml">
36 <field name="print_account"/>36 <field name="acc_number" position="replace">
37 </field>37 </field>
38 </field>38 </field>
39 </record>39 </record>
40 <record model="ir.ui.view" id="l10nch_view_res_partner_bank">40 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_hide_f2">
41 <field name="name">res.partner_partner_bank.form</field>41 <field name="name">res.partner_bank.form.hide.f2</field>
42 <field name="model">res.partner</field>42 <field name="model">res.partner</field>
43 <field name="type">form</field>43 <field name="type">form</field>
44 <field name="inherit_id" ref="account.view_partner_property_form"/>44 <field name="inherit_id" ref="account.view_partner_property_form"/>
45 <field name="arch" type="xml">45 <field name="arch" type="xml">
46 <field name="bank" position="after">46 <field name="bank" position="replace">
47 <newline />47 </field>
48 <field name="print_bank"/>48 </field>
49 <field name="print_account"/>49 </record>
50 </field>50
51 </field>51 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_add_groups">
52 </record>52 <field name="name">res.partner_bank.form.hide.f2</field>
53 <field name="model">res.partner</field>
54 <field name="type">form</field>
55 <field name="sequence" eval="10" /> <!-- we do this to be called before base iban view -->
56 <field name="inherit_id" ref="account.view_partner_property_form"/>
57 <field name="arch" type="xml">
58 <field name="state" position="after">
59 <newline/>
60 <separator colspan="4" string="Account infos"/>
61 <group string="Bank account info" colspan="4" attrs="{'invisible': [('state','in', ['bvpost','bvrpost'])]}" >
62 <field name="acc_number"/>
63 <field name="dta_code"/>
64 <newline/>
65 </group>
66 <newline/>
67 <group string="Postal account info" colspan="4" attrs="{'invisible': [('state','not in', ['bvpost','bvrpost','bvbank','bvrbank'])]}" >
68 <field name="post_number"/>
69 <newline/>
70 </group>
71 <separator colspan="4" string="financial institute infos"/>
72 <field name="my_bank"/>
73 <group string="BVR print options" colspan="4" attrs="{'invisible': [('my_bank','!=', True)]}" >
74 <field name="bvr_adherent_num"/>
75 <field name="print_bank"/>
76 <field name="print_account"/>
77 <newline/>
78 </group>
79 <field name="bank" />
80 </field>
81 </field>
82 </record>
83
84
85 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_hide_f4">
86 <field name="name">res.partner_bank.form.hide.f1</field>
87 <field name="model">res.partner</field>
88 <field name="type">form</field>
89 <field name="sequence" eval="9" /> <!-- we do this to be called before base iban view -->
90 <field name="inherit_id" ref="base.view_partner_bank_form"/>
91 <field name="arch" type="xml">
92 <field name="acc_number" position="replace">
93 </field>
94 </field>
95 </record>
96 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_hide_f5">
97 <field name="name">res.partner_bank.form.hide.f2</field>
98 <field name="model">res.partner</field>
99 <field name="type">form</field>
100 <field name="inherit_id" ref="base.view_partner_bank_form"/>
101 <field name="arch" type="xml">
102 <field name="bank" position="replace">
103 </field>
104 </field>
105 </record>
106
107 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_add_groups2">
108 <field name="name">res.partner_bank.form.hide.f2</field>
109 <field name="model">res.partner</field>
110 <field name="type">form</field>
111 <field name="sequence" eval="10" /> <!-- we do this to be called before base iban view -->
112 <field name="inherit_id" ref="base.view_partner_bank_form"/>
113 <field name="arch" type="xml">
114 <field name="state" position="after">
115 <newline/>
116 <separator colspan="4" string="Account infos"/>
117 <group string="Bank account info" colspan="4" attrs="{'invisible': [('state','in', ['bvpost','bvrpost'])]}" >
118 <field name="acc_number"/>
119 <field name="dta_code"/>
120 <newline/>
121 </group>
122 <newline/>
123 <group string="Postal account info" colspan="4" attrs="{'invisible': [('state','not in', ['bvpost','bvrpost','bvbank','bvrbank'])]}" >
124 <field name="post_number"/>
125 <newline/>
126 <field name="my_bank"/>
127 <group string="BVR print options" colspan="4" attrs="{'invisible': [('my_bank','!=', True)]}" >
128 <field name="bvr_adherent_num"/>
129 <field name="print_bank"/>
130 <field name="print_account"/>
131 <newline/>
132 </group>
133 </group>
134 <separator colspan="4" string="Financial institute infos"/>
135 </field>
136 </field>
137 </record>
138
139 <!-- res.partner.bank base form-->
140
141 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_acc_number_hide_frominvoice">
142 <field name="name">res.partner_bank.form.hide.acc_number.frominvoice</field>
143 <field name="model">res.partner.bank</field>
144 <field name="type">form</field>
145 <field name="sequence" eval="9" /> <!-- we do this to be called before base iban view -->
146 <field name="inherit_id" ref="base_iban.view_partner_bank_iban_form"/>
147 <field name="arch" type="xml">
148 <field name="acc_number" position="replace">
149 </field>
150 </field>
151 </record>
152 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_hide_bank_frominvoice2">
153 <field name="name">res.partner_bank.form.hide.bank.frominvoice</field>
154 <field name="model">res.partner.bank</field>
155 <field name="type">form</field>
156 <field name="sequence" eval="9" /> <!-- we do this to be called before base iban view -->
157 <field name="inherit_id" ref="base_iban.view_partner_bank_iban_form"/>
158 <field name="arch" type="xml">
159 <field name="bank" position="replace">
160 </field>
161 </field>
162 </record>
163
164 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_hide_bank_frominvoice3">
165 <field name="name">res.partner_bank.form.hide.bank.frominvoice</field>
166 <field name="model">res.partner.bank</field>
167 <field name="type">form</field>
168 <field name="sequence" eval="16" /> <!-- we do this to be called before base iban view -->
169 <field name="inherit_id" ref="base_iban.view_partner_bank_iban_form"/>
170 <field name="arch" type="xml">
171 <field name="iban" position="replace">
172 </field>
173 </field>
174 </record>
175
176
177 <record model="ir.ui.view" id="l10nch_view_res_partner_bank_from_invoice">
178 <field name="name">res.partner_bank.form.hide.frominvoice</field>
179 <field name="model">res.partner.bank</field>
180 <field name="type">form</field>
181 <field name="sequence" eval="10" /> <!-- we do this to be called before base iban view -->
182 <field name="inherit_id" ref="base_iban.view_partner_bank_iban_form"/>
183 <field name="arch" type="xml">
184 <field name="state" position="after">
185 <newline/>
186 <separator colspan="4" string="Account infos"/>
187 <group string="IBAN account info" colspan="4" attrs="{'invisible': [('state','not in', ['iban'])]}" >
188 <field name="iban"/>
189 <newline/>
190 </group>
191
192 <group string="Bank account info" colspan="4" attrs="{'invisible': [('state','in', ['bvpost','bvrpost'])]}" >
193 <field name="acc_number"/>
194 <field name="dta_code"/>
195 <newline/>
196 </group>
197 <newline/>
198 <group string="Postal account info" colspan="4" attrs="{'invisible': [('state','not in', ['bvpost','bvrpost','bvbank','bvrbank'])]}" >
199 <field name="post_number"/>
200 <newline/>
201 <field name="my_bank"/>
202 <group string="BVR print options" colspan="4" attrs="{'invisible': [('my_bank','!=', True)]}" >
203 <field name="bvr_adherent_num"/>
204 <field name="print_bank"/>
205 <field name="print_account"/>
206 <newline/>
207 </group>
208 </group>
209 <field name="bank" />
210 </field>
211 </field>
212 </record>
213
214
215
53 </data>216 </data>
54</openerp>217</openerp>
55\ No newline at end of file218\ No newline at end of file
56219
=== modified file 'l10n_ch/company.py'
--- l10n_ch/company.py 2011-02-09 08:59:05 +0000
+++ l10n_ch/company.py 2011-09-14 14:11:28 +0000
@@ -33,6 +33,16 @@
33 'bvr_delta_vert': fields.float('BVR Vert. Delta (mm)',33 'bvr_delta_vert': fields.float('BVR Vert. Delta (mm)',
34 help='vert. delta in mm 1.2 will print the bvr 1.2mm lower, negative value is possible'),34 help='vert. delta in mm 1.2 will print the bvr 1.2mm lower, negative value is possible'),
35 35
36 'bvr_scan_line_vert': fields.float('BVR vert. position for scan line (mm)',
37 help='Vert. position in mm for scan line'),
38
39 'bvr_scan_line_horz': fields.float('BVR horiz. position for scan line(mm)',
40 help='Horiz. position in mm for scan line'),
41
42 'bvr_scan_line_font_size': fields.float('BVR scan line font size (pt)'),
43
44 'bvr_scan_line_letter_spacing':fields.float('BVR scan line letter spacing'),
45
36 'bvr_background': fields.boolean('Insert BVR background ?'),46 'bvr_background': fields.boolean('Insert BVR background ?'),
37 47
38 'bvr_only': fields.boolean('Separated BVR only ?',48 'bvr_only': fields.boolean('Separated BVR only ?',
@@ -41,6 +51,13 @@
41 'invoice_only': fields.boolean('Invoice only (Do not use with bvr only)?',51 'invoice_only': fields.boolean('Invoice only (Do not use with bvr only)?',
42 help='Print only the invoice without BVR'),52 help='Print only the invoice without BVR'),
43 }53 }
54
55 _defaults = {
56 'bvr_scan_line_vert': lambda *a: 232,
57 'bvr_scan_line_horz': lambda *a: 72,
58 'bvr_scan_line_font_size': lambda *a: 12,
59 'bvr_scan_line_letter_spacing': lambda *a: 0,
60 }
4461
45res_company()62res_company()
4663
4764
=== modified file 'l10n_ch/company_view.xml'
--- l10n_ch/company_view.xml 2011-01-14 12:41:54 +0000
+++ l10n_ch/company_view.xml 2011-09-14 14:11:28 +0000
@@ -8,13 +8,21 @@
8 <field name="inherit_id" ref="base.view_company_form"/>8 <field name="inherit_id" ref="base.view_company_form"/>
9 <field name="arch" type="xml">9 <field name="arch" type="xml">
10 <field name="rml_footer2" position="after">10 <field name="rml_footer2" position="after">
11 <field name="bvr_delta_horz"/>11 <newline/>
12 <field name="bvr_delta_vert"/>12 <group string="BVR data" colspan="4">
13 <field name="bvr_background"/>13 <field name="bvr_delta_horz"/>
14 <field name="bvr_only"/>14 <field name="bvr_delta_vert"/>
15 <field name="invoice_only"/>15 <field name="bvr_scan_line_vert"/>
16 <field name="bvr_scan_line_horz"/>
17 <field name="bvr_scan_line_font_size"/>
18 <field name="bvr_scan_line_letter_spacing"/>
19 <field name="bvr_background"/>
20 <field name="bvr_only"/>
21 <field name="invoice_only"/>
22 </group>
23 <newline/>
16 </field>24 </field>
17 </field>25 </field>
18 </record>26 </record>
19 </data>27 </data>
20</openerp>28</openerp>
21\ No newline at end of file29\ No newline at end of file
2230
=== modified file 'l10n_ch/demo/demo.xml'
--- l10n_ch/demo/demo.xml 2011-02-09 08:59:05 +0000
+++ l10n_ch/demo/demo.xml 2011-09-14 14:11:28 +0000
@@ -15,8 +15,6 @@
15 <field name="bank" ref="main_bank"/>15 <field name="bank" ref="main_bank"/>
16 <field name="iban">CH9100767000S00023455</field>16 <field name="iban">CH9100767000S00023455</field>
17 <field name="bvr_adherent_num">0000000</field>17 <field name="bvr_adherent_num">0000000</field>
18
19
20 </record>18 </record>
2119
22 <record id="bank" model="res.partner">20 <record id="bank" model="res.partner">
2321
=== removed file 'l10n_ch/dta.py'
--- l10n_ch/dta.py 2011-01-14 12:41:54 +0000
+++ l10n_ch/dta.py 1970-01-01 00:00:00 +0000
@@ -1,85 +0,0 @@
1# -*- encoding: utf-8 -*-
2##############################################################################
3#
4# Author: Nicolas Bessi. Copyright Camptocamp SA
5# Donors: Hasa Sàrl, Open Net Sàrl and Prisme Solutions Informatique SA
6#
7# This program is free software: you can redistribute it and/or modify
8# it under the terms of the GNU Affero General Public License as
9# published by the Free Software Foundation, either version 3 of the
10# License, or (at your option) any later version.
11#
12# This program is distributed in the hope that it will be useful,
13# but WITHOUT ANY WARRANTY; without even the implied warranty of
14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15# GNU Affero General Public License for more details.
16#
17# You should have received a copy of the GNU Affero General Public License
18# along with this program. If not, see <http://www.gnu.org/licenses/>.
19#
20##############################################################################
21
22import time
23from osv import osv, fields
24
25class account_dta(osv.osv):
26 """class that implements bank DTA File format,
27 used to transfert bulk batch payment instruction to a bank"""
28 _name = "account.dta"
29 _description = "DTA History"
30 _columns = {
31 ### name of the file
32 'name': fields.binary('DTA file', readonly=True),
33 ### list of dta line linked to the dta order
34 'dta_line_ids': fields.one2many('account.dta.line','dta_id','DTA lines', readonly=True),
35 ## textual notes
36 'note': fields.text('Creation log', readonly=True,
37 help="Displays the problem during dta generation"),
38 ### bank how will execute DTA order
39 'bank': fields.many2one('res.partner.bank','Bank', readonly=True,select=True,
40 help="Bank how will execute DTA order"),
41 ### date of DTA order generation
42 'date': fields.date('Creation Date', readonly=True,select=True,
43 help="Date of DTA order generation"),
44 ### user how generate the DTA order
45 'user_id': fields.many2one('res.users','User', readonly=True, select=True),
46 }
47account_dta()
48
49class account_dta_line(osv.osv):
50 """Class that represent a DTA order line,
51 each line corressponds to a payment instruction"""
52 _name = "account.dta.line"
53 _description = "DTA line"
54 _columns = {
55 ### name of the line
56 'name' : fields.many2one('account.invoice','Invoice', required=True, size=256),
57 ### partner how will receive payments
58 'partner_id' : fields.many2one('res.partner','Partner',
59 help="Partenr to pay"),
60 ### due date of the payment
61 'due_date' : fields.date('Due date'),
62 ### date of the supplier invoice to pay
63 'invoice_date' : fields.date('Invoice date'),
64 ### cash discount date
65 'cashdisc_date' : fields.date('Cash Discount date'),
66 ### amount effectively paied on this line
67 'amount_to_pay' : fields.float('Amount to pay',
68 help="Amount effectively paid"),
69 ### amount that was on the supplier invoice
70 'amount_invoice': fields.float('Invoiced Amount',
71 help="Amount to pay base on the supplier invoice"),
72 ### Cash discount amount
73 'amount_cashdisc': fields.float('Cash Discount Amount'),
74 ### Linke to the main dta order
75 'dta_id': fields.many2one('account.dta','Associated DTA', required=True, ondelete='cascade'),
76 ### state of the invoice Drat, Cancel, Done
77 'state' : fields.selection([('draft','Draft'),('cancel','Error'),('done','Paid')],'State')
78 }
79 _defaults = {
80 'state' : lambda *a :'draft',
81 }
82
83account_dta_line()
84
85# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
86\ No newline at end of file0\ No newline at end of file
871
=== modified file 'l10n_ch/dta_data.xml'
--- l10n_ch/dta_data.xml 2011-05-25 11:51:33 +0000
+++ l10n_ch/dta_data.xml 2011-09-14 14:11:28 +0000
@@ -30,33 +30,27 @@
30 <field name="code">dta_company</field>30 <field name="code">dta_company</field>
31 </record>31 </record>
3232
33 <record model="res.partner.bank.type" id="dta_iban">
34 <field name="name">DTA-IBAN</field>
35 <field name="code">dta_iban</field>
36 </record>
37
38 <record model="res.partner.bank.type" id="bvrbank">33 <record model="res.partner.bank.type" id="bvrbank">
39 <field name="name">DTA-BVRBANK</field>34 <field name="name">BVR Bank</field>
40 <field name="code">bvrbank</field>35 <field name="code">bvrbank</field>
41 </record>36 </record>
4237
43 <record model="res.partner.bank.type" id="bvrpost">38 <record model="res.partner.bank.type" id="bvrpost">
44 <field name="name">DTA-BVRPOST</field>39 <field name="name">BVR Post</field>
45 <field name="code">bvrpost</field>40 <field name="code">bvrpost</field>
46 </record>41 </record>
4742
48 <record model="res.partner.bank.type" id="bvpost">43 <record model="res.partner.bank.type" id="bvpost">
49 <field name="name">DTA-BVPOST</field>44 <field name="name">BV Post</field>
50 <field name="code">bvpost</field>45 <field name="code">bvpost</field>
51 </record>46 </record>
5247
53 <record model="res.partner.bank.type" id="bvbank">48 <record model="res.partner.bank.type" id="bvbank">
54 <field name="name">DTA-BVBANK</field>49 <field name="name">BV Bank</field>
55 <field name="code">bvbank</field>50 <field name="code">bvbank</field>
56 </record>51 </record>
5752
5853
59
60 <!-- Adjust the fields attributes for dta_company-->54 <!-- Adjust the fields attributes for dta_company-->
61 <record model="res.partner.bank.type.field" id="iban_field">55 <record model="res.partner.bank.type.field" id="iban_field">
62 <field name="name">iban</field>56 <field name="name">iban</field>
@@ -64,22 +58,13 @@
64 <field name="required" eval="True"/>58 <field name="required" eval="True"/>
65 <field name="readonly" eval="False"/>59 <field name="readonly" eval="False"/>
66 </record>60 </record>
6761
6862 <record model="res.partner.bank.type.field" id="iban_field_bvr_bank">
69 <!-- Adjust the fields attributes for dta_iban-->
70 <record model="res.partner.bank.type.field" id="iban_field_iban">
71 <field name="name">iban</field>63 <field name="name">iban</field>
72 <field name="bank_type_id" ref="dta_iban"/>64 <field name="bank_type_id" ref="bvrbank"/>
73 <field name="required" eval="True"/>65 <field name="required" eval="False"/>
74 <field name="readonly" eval="False"/>66 <field name="readonly" eval="False"/>
75 </record>67 </record>
76 <record model="res.partner.bank.type.field" id="bank_field_iban">
77 <field name="name">bank</field>
78 <field name="bank_type_id" ref="dta_iban"/>
79 <field name="required" eval="True"/>
80 <field name="readonly" eval="False"/>
81 </record>
82
8368
84 <!-- Adjust the fields attributes for bvrbank-->69 <!-- Adjust the fields attributes for bvrbank-->
85 <record model="res.partner.bank.type.field" id="bank_field_bvrbank">70 <record model="res.partner.bank.type.field" id="bank_field_bvrbank">
@@ -139,4 +124,4 @@
139 </record>124 </record>
140125
141</data>126</data>
142</openerp>
143\ No newline at end of file127\ No newline at end of file
128</openerp>
144129
=== removed file 'l10n_ch/dta_view.xml'
--- l10n_ch/dta_view.xml 2011-02-09 08:59:05 +0000
+++ l10n_ch/dta_view.xml 1970-01-01 00:00:00 +0000
@@ -1,37 +0,0 @@
1<?xml version="1.0"?>
2<openerp>
3 <data>
4
5 <!-- Inherit both bank view -->
6 <record model="ir.ui.view" id="view_partner_bank_form">
7 <field name="name">partner - bank inherit</field>
8 <field name="model">res.partner</field>
9 <field name="type">form</field>
10 <field name="inherit_id" ref="base.view_partner_form"/>
11 <field name="arch" type="xml">
12 <field name="acc_number" position="after">
13 <newline/>
14 <field name="bvr_adherent_num"/>
15 <field name="post_number"/>
16 <field name="dta_code"/>
17 </field>
18 </field>
19 </record>
20
21 <record model="ir.ui.view" id="view_partner_bank_form2">
22 <field name="name">partner - bank inherit</field>
23 <field name="model">res.partner.bank</field>
24 <field name="type">form</field>
25 <field name="inherit_id" ref="base.view_partner_bank_form"/>
26 <field name="arch" type="xml">
27 <field name="acc_number" position="after">
28 <newline/>
29 <field name="bvr_adherent_num"/>
30 <field name="post_number"/>
31 <field name="dta_code"/>
32 </field>
33 </field>
34 </record>
35
36 </data>
37</openerp>
380
=== modified file 'l10n_ch/invoice.py'
--- l10n_ch/invoice.py 2011-02-09 08:59:05 +0000
+++ l10n_ch/invoice.py 2011-09-14 14:11:28 +0000
@@ -84,7 +84,7 @@
84 ## @param user res.user.id that is currently loged84 ## @param user res.user.id that is currently loged
85 ## @parma ids invoices id85 ## @parma ids invoices id
86 ## @return a boolean True if valid False if invalid86 ## @return a boolean True if valid False if invalid
87 def _check_bvr(self, cr, uid, ids):87 def _check_bvr(self, cr, uid, ids, context=None):
88 """88 """
89 Function to validate a bvr reference like :89 Function to validate a bvr reference like :
90 0100054150009>132000000000000000000000014+ 1300132412>90 0100054150009>132000000000000000000000014+ 1300132412>
@@ -111,7 +111,7 @@
111 ## @param user res.user.id that is currently loged111 ## @param user res.user.id that is currently loged
112 ## @parma ids invoices id112 ## @parma ids invoices id
113 ## @return a boolean True if valid False if invalid113 ## @return a boolean True if valid False if invalid
114 def _check_reference_type(self, cursor, user, ids):114 def _check_reference_type(self, cursor, user, ids, context=None):
115 """Check the customer invoice reference type depending115 """Check the customer invoice reference type depending
116 on the BVR reference type and the invoice partner bank type"""116 on the BVR reference type and the invoice partner bank type"""
117 for invoice in self.browse(cursor, user, ids):117 for invoice in self.browse(cursor, user, ids):
@@ -120,7 +120,7 @@
120 invoice.partner_bank_id.state in \120 invoice.partner_bank_id.state in \
121 ('bvrbank', 'bvrpost') and \121 ('bvrbank', 'bvrpost') and \
122 invoice.reference_type != 'bvr':122 invoice.reference_type != 'bvr':
123 return False123 return False
124 return True124 return True
125125
126 _constraints = [126 _constraints = [
@@ -143,7 +143,7 @@
143 def onchange_partner_id(self, cr, uid, ids, type, partner_id,143 def onchange_partner_id(self, cr, uid, ids, type, partner_id,
144 date_invoice=False, payment_term=False, partner_bank_id=False, company_id=False):144 date_invoice=False, payment_term=False, partner_bank_id=False, company_id=False):
145 """ Function that is call when the partner of the invoice is changed145 """ Function that is call when the partner of the invoice is changed
146 it will retriev and set the good bank partner bank"""146 it will retrieve and set the good bank partner bank"""
147 res = super(account_invoice, self).onchange_partner_id(147 res = super(account_invoice, self).onchange_partner_id(
148 cr,148 cr,
149 uid,149 uid,
150150
=== modified file 'l10n_ch/journal_data.xml'
--- l10n_ch/journal_data.xml 2011-05-25 11:51:33 +0000
+++ l10n_ch/journal_data.xml 2011-09-14 14:11:28 +0000
@@ -15,7 +15,7 @@
15 <record id="bank_journal" model="account.journal">15 <record id="bank_journal" model="account.journal">
16 <field name="name">Banque CHF</field>16 <field name="name">Banque CHF</field>
17 <field name="code">BCHF</field>17 <field name="code">BCHF</field>
18 <field name="type">cash</field>18 <field name="type">bank</field>
19 <field name="view_id" ref="account.account_journal_bank_view"/>19 <field name="view_id" ref="account.account_journal_bank_view"/>
20 <field name="sequence_id" ref="account.sequence_journal"/>20 <field name="sequence_id" ref="account.sequence_journal"/>
21 <field name="user_id" ref="base.user_root"/>21 <field name="user_id" ref="base.user_root"/>
@@ -26,7 +26,7 @@
26 <record id="bank_euro_journal" model="account.journal">26 <record id="bank_euro_journal" model="account.journal">
27 <field name="name">Banque EUR</field>27 <field name="name">Banque EUR</field>
28 <field name="code">BEUR</field>28 <field name="code">BEUR</field>
29 <field name="type">cash</field>29 <field name="type">bank</field>
30 <field name="view_id" ref="account.account_journal_bank_view"/>30 <field name="view_id" ref="account.account_journal_bank_view"/>
31 <field name="sequence_id" ref="account.sequence_journal"/>31 <field name="sequence_id" ref="account.sequence_journal"/>
32 <field name="user_id" ref="base.user_root"/>32 <field name="user_id" ref="base.user_root"/>
3333
=== modified file 'l10n_ch/partner.py'
--- l10n_ch/partner.py 2011-02-09 08:59:05 +0000
+++ l10n_ch/partner.py 2011-09-14 14:11:28 +0000
@@ -30,35 +30,4 @@
30 }30 }
3131
32res_partner()32res_partner()
33
34class res_partner_bank(osv.osv):
35 _inherit = "res.partner.bank"
36 _columns = {
37 'name': fields.char('Description', size=128, required=True),
38 'post_number': fields.char('Post number', size=64),
39 'bvr_adherent_num': fields.char('BVR adherent number', size=11),
40 'dta_code': fields.char('DTA code', size=5),
41 }
42
43 def name_get(self, cr, uid, ids, context=None):
44 if not len(ids):
45 return []
46 bank_type_obj = self.pool.get('res.partner.bank.type')
47
48 type_ids = bank_type_obj.search(cr, uid, [])
49 bank_type_names = {}
50 for bank_type in bank_type_obj.browse(cr, uid, type_ids,
51 context=context):
52 bank_type_names[bank_type.code] = bank_type.name
53 res = []
54 for r in self.read(cr, uid, ids, ['name','state'], context):
55 res.append((r['id'], r['name']+' : '+bank_type_names[r['state']]))
56 return res
57
58 _sql_constraints = [
59 ('bvr_adherent_uniq', 'unique (bvr_adherent_num)', 'The BVR adherent number must be unique !')
60 ]
61
62res_partner_bank()
63
64# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:33# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
65\ No newline at end of file34\ No newline at end of file
6635
=== modified file 'l10n_ch/report/bvr.mako'
--- l10n_ch/report/bvr.mako 2011-02-09 08:59:05 +0000
+++ l10n_ch/report/bvr.mako 2011-09-14 14:11:28 +0000
@@ -7,6 +7,17 @@
7 font-weight: normal;7 font-weight: normal;
8 src: url(${police_absolute_path('ocrbb.ttf')}) format("truetype");8 src: url(${police_absolute_path('ocrbb.ttf')}) format("truetype");
9 }9 }
10 .ocrbb{
11 text-align:right;
12 font-family:bvrocrb;
13 font-size:${str(company.bvr_scan_line_font_size or '0.0').replace(',','.')}pt;
14 position:absolute;top:${str(company.bvr_scan_line_vert or '0.0').replace(',','.')}mm;
15 left:${str(company.bvr_scan_line_horz or '0.0').replace(',','.')}mm;
16 z-index:4;
17 letter-spacing:str(company.bvr_scan_line_letter_spacing or '0.0').replace(',','.')
18 }
19 ${css}
20 </style>
10 </style>21 </style>
1122
12 </head>23 </head>
@@ -87,9 +98,41 @@
87 98
88 }99 }
89 </script>100 </script>
90 ${_check(objects)}
91 %for inv in objects :101 %for inv in objects :
92 <% setLang(inv.partner_id.lang) %>102 <% setLang(inv.partner_id.lang) %>
103 <!--adresses + info block -->
104 <table class="dest_address" style="position:absolute;top:6mm;left:15mm">
105 <tr><td ><b>${inv.partner_id.title.name or ''|entity} ${inv.partner_id.name |entity}</b></td></tr>
106 <tr><td>${inv.address_invoice_id.street or ''|entity}</td></tr>
107 <tr><td>${inv.address_invoice_id.street2 or ''|entity}</td></tr>
108 <tr><td>${inv.address_invoice_id.zip or ''|entity} ${inv.address_invoice_id.city or ''|entity}</td></tr>
109 %if inv.address_invoice_id.country_id :
110 <tr><td>${inv.address_invoice_id.country_id.name or ''|entity} </td></tr>
111 %endif
112 %if inv.address_invoice_id.phone :
113 <tr><td>${_("Tel") |entity}: ${inv.address_invoice_id.phone|entity}</td></tr>
114 %endif
115 %if inv.address_invoice_id.fax :
116 <tr><td>${_("Fax") |entity}: ${inv.address_invoice_id.fax|entity}</td></tr>
117 %endif
118 %if inv.address_invoice_id.email :
119 <tr><td>${_("E-mail") |entity}: ${inv.address_invoice_id.email|entity}</td></tr>
120 %endif
121 %if inv.partner_id.vat :
122 <tr><td>${_("VAT") |entity}: ${inv.partner_id.vat|entity}</td></tr>
123 %endif
124 </table>
125
126 <div style="position:absolute;top:60mm; left:20mm">
127 ${_('Invoice')} - ${inv.number or ''|entity}
128 <br/>
129 <br/>
130 ${_('Here is the BVR to allow you to pay the invoice %s - %s') % (inv.name or '', inv.number or '',)}
131 <br/>
132 ${_('Regards')}
133 </div>
134
135 <div colspan="2" class="ocrbb">${mod10r('01'+str('%.2f' % inv.amount_total).replace('.','').rjust(10,'0'))}&gt;${_get_ref(inv)}+${inv.partner_bank_id.post_number.split('-')[0]+(str(inv.partner_bank_id.post_number.split('-')[1])).rjust(6,'0')+inv.partner_bank_id.post_number.split('-')[2]}&gt;</div>
93 <div id="cont_${inv.id}" style="padding-left:20mm;padding-top:0;padding-bottom:10;height:180mm">136 <div id="cont_${inv.id}" style="padding-left:20mm;padding-top:0;padding-bottom:10;height:180mm">
94 <!-- Your communication message here -->137 <!-- Your communication message here -->
95 </div>138 </div>
@@ -103,7 +146,7 @@
103 <tr style="height:8.4666667mm;vertical-align:bottom;padding-bottom:0"> <td><table style="width:100%" CELLPADDING="0" CELLSPACING="0"><td style="width:4mm"></td><td style="width:40mm;text-align: right" >${_space(('%.2f' % inv.amount_total)[:-3], 1)}</td><td style="width:6mm"></td><td style="width:10mm;text-align: right">${ _space(('%.2f' % inv.amount_total)[-2:], 1)}</td><td style="width:3mm;text-align: right"></td></table></td><td><table style="width:100%" CELLPADDING="0" CELLSPACING="0"><td style="width:4mm"></td><td style="width:40mm;text-align: right" >${_space(('%.2f' % inv.amount_total)[:-3], 1)}</td><td style="width:6mm"></td><td style="width:10mm;text-align: right">${ _space(('%.2f' % inv.amount_total)[-2:], 1)}</td><td style="width:3mm;text-align: right"></td></table></td><td></td></tr>146 <tr style="height:8.4666667mm;vertical-align:bottom;padding-bottom:0"> <td><table style="width:100%" CELLPADDING="0" CELLSPACING="0"><td style="width:4mm"></td><td style="width:40mm;text-align: right" >${_space(('%.2f' % inv.amount_total)[:-3], 1)}</td><td style="width:6mm"></td><td style="width:10mm;text-align: right">${ _space(('%.2f' % inv.amount_total)[-2:], 1)}</td><td style="width:3mm;text-align: right"></td></table></td><td><table style="width:100%" CELLPADDING="0" CELLSPACING="0"><td style="width:4mm"></td><td style="width:40mm;text-align: right" >${_space(('%.2f' % inv.amount_total)[:-3], 1)}</td><td style="width:6mm"></td><td style="width:10mm;text-align: right">${ _space(('%.2f' % inv.amount_total)[-2:], 1)}</td><td style="width:3mm;text-align: right"></td></table></td><td></td></tr>
104 <tr style="height:21.166667mm"><td></td><td></td><td></td></tr>147 <tr style="height:21.166667mm"><td></td><td></td><td></td></tr>
105 <tr style="height:8.4666667mm"> <td></td><td></td><td></td></tr>148 <tr style="height:8.4666667mm"> <td></td><td></td><td></td></tr>
106 <tr style="height:21.166667mm;vertical-align:top"><td></td><td colspan="2" style="text-align:right;padding-right:0.3in;font-family:bvrocrb;font-size:12pt">${mod10r('01'+str('%.2f' % inv.amount_total).replace('.','').rjust(10,'0'))}&gt;${_get_ref(inv)}+${inv.partner_bank_id.post_number.split('-')[0]+(str(inv.partner_bank_id.post_number.split('-')[1])).rjust(6,'0')+inv.partner_bank_id.post_number.split('-')[2]}&gt;</td></tr>149 <tr style="height:21.166667mm;vertical-align:top"><td></td><td></td></tr>
107 </table>150 </table>
108 %endfor151 %endfor
109</body>152</body>
110153
=== modified file 'l10n_ch/report/report_webkit_html.mako'
--- l10n_ch/report/report_webkit_html.mako 2011-02-09 08:59:05 +0000
+++ l10n_ch/report/report_webkit_html.mako 2011-09-14 14:11:28 +0000
@@ -9,7 +9,7 @@
9 <% setLang(inv.partner_id.lang) %>9 <% setLang(inv.partner_id.lang) %>
10 <div id="inv_cont_${inv.id}" style="padding-left:20mm;padding-top:0;padding-bottom:10;border-width:0px;border-style:solid">10 <div id="inv_cont_${inv.id}" style="padding-left:20mm;padding-top:0;padding-bottom:10;border-width:0px;border-style:solid">
11 <table class="dest_address">11 <table class="dest_address">
12 <tr><td ><b>${inv.partner_id.title or ''|entity} ${inv.partner_id.name |entity}</b></td></tr>12 <tr><td ><b>${inv.partner_id.title.name or ''|entity} ${inv.partner_id.name |entity}</b></td></tr>
13 <tr><td>${inv.address_invoice_id.street or ''|entity}</td></tr>13 <tr><td>${inv.address_invoice_id.street or ''|entity}</td></tr>
14 <tr><td>${inv.address_invoice_id.street2 or ''|entity}</td></tr>14 <tr><td>${inv.address_invoice_id.street2 or ''|entity}</td></tr>
15 <tr><td>${inv.address_invoice_id.zip or ''|entity} ${inv.address_invoice_id.city or ''|entity}</td></tr>15 <tr><td>${inv.address_invoice_id.zip or ''|entity} ${inv.address_invoice_id.city or ''|entity}</td></tr>
1616
=== modified file 'l10n_ch/report/report_webkit_html.py'
--- l10n_ch/report/report_webkit_html.py 2011-02-09 08:59:05 +0000
+++ l10n_ch/report/report_webkit_html.py 2011-09-14 14:11:28 +0000
@@ -33,7 +33,9 @@
33import pooler33import pooler
34from tools.config import config34from tools.config import config
35from mako.template import Template35from mako.template import Template
36from mako import exceptions
36from tools.translate import _37from tools.translate import _
38from osv.osv import except_osv
3739
3840
39class l10n_ch_report_webkit_html(report_sxw.rml_parse):41class l10n_ch_report_webkit_html(report_sxw.rml_parse):
@@ -41,16 +43,15 @@
41 super(l10n_ch_report_webkit_html, self).__init__(cr, uid, name, context=context)43 super(l10n_ch_report_webkit_html, self).__init__(cr, uid, name, context=context)
42 self.localcontext.update({44 self.localcontext.update({
43 'time': time,45 'time': time,
44 'cr':cr,46 'cr': cr,
45 'uid': uid,47 'uid': uid,
46 'user':self.pool.get("res.users").browse(cr, uid, uid),48 'user':self.pool.get("res.users").browse(cr, uid, uid),
47 'mod10r': mod10r,49 'mod10r': mod10r,
48 '_space': self._space,50 '_space': self._space,
49 '_get_ref': self._get_ref,51 '_get_ref': self._get_ref,
50 'comma_me': self.comma_me,52 'comma_me': self.comma_me,
51 'police_absolute_path' : self.police_absolute_path,53 'police_absolute_path': self.police_absolute_path,
52 'bvr_absolute_path':self.bvr_absolute_path,54 'bvr_absolute_path': self.bvr_absolute_path,
53 '_check' : self._check,
54 'headheight': self.headheight55 'headheight': self.headheight
55 })56 })
5657
@@ -58,15 +59,22 @@
58 _compile_comma_me = re.compile("^(-?\d+)(\d{3})")59 _compile_comma_me = re.compile("^(-?\d+)(\d{3})")
59 _compile_check_bvr = re.compile('[0-9][0-9]-[0-9]{3,6}-[0-9]')60 _compile_check_bvr = re.compile('[0-9][0-9]-[0-9]{3,6}-[0-9]')
60 _compile_check_bvr_add_num = re.compile('[0-9]*$')61 _compile_check_bvr_add_num = re.compile('[0-9]*$')
6162
63 def set_context(self, objects, data, ids, report_type=None):
64 user = self.pool.get('res.users').browse(self.cr, self.uid, self.uid)
65 company = user.company_id
66 if not company.invoice_only:
67 self._check(ids)
68 return super(l10n_ch_report_webkit_html, self).set_context(objects, data, ids, report_type=report_type)
69
62 def police_absolute_path(self, inner_path) :70 def police_absolute_path(self, inner_path) :
63 """Will get the ocrb police absolute path"""71 """Will get the ocrb police absolute path"""
64 path = addons.get_module_resource(os.path.join('l10n_ch','report',inner_path))72 path = addons.get_module_resource(os.path.join('l10n_ch', 'report', inner_path))
65 return path73 return path
66 74
67 def bvr_absolute_path(self) :75 def bvr_absolute_path(self) :
68 """Will get the ocrb police absolute path"""76 """Will get the ocrb police absolute path"""
69 path = addons.get_module_resource(os.path.join('l10n_ch','report','bvr1.jpg'))77 path = addons.get_module_resource(os.path.join('l10n_ch', 'report', 'bvr1.jpg'))
70 return path78 return path
71 79
72 def headheight(self):80 def headheight(self):
@@ -76,7 +84,7 @@
7684
77 def comma_me(self, amount):85 def comma_me(self, amount):
78 """Fast swiss number formatting"""86 """Fast swiss number formatting"""
79 if type(amount) is float :87 if isinstance(amount, float):
80 amount = str('%.2f'%amount)88 amount = str('%.2f'%amount)
81 else :89 else :
82 amount = str(amount)90 amount = str(amount)
@@ -88,14 +96,15 @@
88 return self.comma_me(new)96 return self.comma_me(new)
8997
90 def _space(self, nbr, nbrspc=5):98 def _space(self, nbr, nbrspc=5):
91 """Spaces * 5"""99 """Spaces * 5.
92 res = ''
93 for i in range(len(nbr)):
94 res = res + nbr[i]
95 if not (i-1) % nbrspc:
96 res = res + ' '
97 return res
98100
101 Example:
102 >>> self._space('123456789012345')
103 '12 34567 89012 345'
104 """
105 return ''.join([' '[(i - 2) % nbrspc:] + c for i, c in enumerate(nbr)])
106
107
99 def _get_ref(self, inv):108 def _get_ref(self, inv):
100 """Retrieve ESR/BVR reference form invoice in order to print it"""109 """Retrieve ESR/BVR reference form invoice in order to print it"""
101 res = ''110 res = ''
@@ -106,39 +115,77 @@
106 invoice_number = self._compile_get_ref.sub('', inv.number)115 invoice_number = self._compile_get_ref.sub('', inv.number)
107 return mod10r(res + invoice_number.rjust(26-len(res), '0'))116 return mod10r(res + invoice_number.rjust(26-len(res), '0'))
108 117
109 def _check(self, invoices):118 def _check(self, invoice_ids):
110 """Check if the invoice is ready to be printed"""119 """Check if the invoice is ready to be printed"""
120 if not invoice_ids:
121 invoice_ids = []
111 cursor = self.cr122 cursor = self.cr
112 pool = self.pool123 pool = self.pool
113 invoice_obj = pool.get('account.invoice')124 invoice_obj = pool.get('account.invoice')
114 ids = [x.id for x in invoices]125 ids = invoice_ids
115 for invoice in invoice_obj.browse(cursor, self.uid, ids):126 for invoice in invoice_obj.browse(cursor, self.uid, ids):
116 if not invoice.partner_bank_id:127 if not invoice.partner_bank_id:
117 raise wizard.except_wizard(_('UserError'),128 raise except_osv(_('UserError'),
118 _('No bank specified on invoice:\n' + \129 _('No bank specified on invoice:\n' + \
119 invoice_obj.name_get(cursor, self.uid, [invoice.id],130 invoice_obj.name_get(cursor, self.uid, [invoice.id],
120 context={})[0][1]))131 context={})[0][1]))
121 if not self._compile_check_bvr.match(132 if not self._compile_check_bvr.match(
122 invoice.partner_bank_id.post_number or ''):133 invoice.partner_bank_id.post_number or ''):
123 raise wizard.except_wizard(_('UserError'),134 raise except_osv(_('UserError'),
124 _("Your bank BVR number should be of the form 0X-XXX-X! " +135 _('Your bank BVR number should be of the form 0X-XXX-X! ' +
125 'Please check your company ' +136 'Please check your company ' +
126 'information for the invoice:\n' + 137 'information for the invoice:\n' +
127 invoice_obj.name_get(cursor, self.uid, [invoice.id],138 invoice_obj.name_get(cursor, self.uid, [invoice.id],
128 context={})[0][1]))139 context={})[0][1]))
129 if invoice.partner_bank_id.bvr_adherent_num \140 if invoice.partner_bank_id.bvr_adherent_num \
130 and not self._compile_check_bvr_add_num.match(141 and not self._compile_check_bvr_add_num.match(
131 invoice.partner_bank_id.bvr_adherent_num):142 invoice.partner_bank_id.bvr_adherent_num):
132 raise wizard.except_wizard('UserError',143 raise except_osv(_('UserError'),
133 'Your bank BVR adherent number must contain exactly seven' +144 _('Your bank BVR adherent number must contain exactly seven' +
134 'digits!\nPlease check your company ' +145 'digits!\nPlease check your company ' +
135 'information for the invoice:\n' +146 'information for the invoice:\n' +
136 invoice_obj.name_get(cursor, self.uid, [invoice.id],147 invoice_obj.name_get(cursor, self.uid, [invoice.id],
137 context={})[0][1])148 context={})[0][1]))
138 return ""149 return ''
139150
140class BVRWebKitParser(webkit_report.WebKitParser):151class BVRWebKitParser(webkit_report.WebKitParser):
141 152
153 def setLang(self, lang):
154 if not lang:
155 lang = 'en_US'
156 self.localcontext['lang'] = lang
157
158 def formatLang(self, value, digits=None, date=False, date_time=False, grouping=True, monetary=False):
159 """format using the know cursor, language from localcontext"""
160 if digits is None:
161 digits = self.parser_instance.get_digits(value)
162 if isinstance(value, (str, unicode)) and not value:
163 return ''
164 pool_lang = self.pool.get('res.lang')
165 lang = self.localcontext['lang']
166
167 lang_ids = pool_lang.search(self.parser_instance.cr, self.parser_instance.uid, [('code','=',lang)])[0]
168 lang_obj = pool_lang.browse(self.parser_instance.cr, self.parser_instance.uid, lang_ids)
169
170 if date or date_time:
171 if not str(value):
172 return ''
173
174 date_format = lang_obj.date_format
175 parse_format = '%Y-%m-%d'
176 if date_time:
177 value=value.split('.')[0]
178 date_format = date_format + " " + lang_obj.time_format
179 parse_format = '%Y-%m-%d %H:%M:%S'
180 if not isinstance(value, time.struct_time):
181 return time.strftime(date_format, time.strptime(value, parse_format))
182
183 else:
184 date = datetime(*value.timetuple()[:6])
185 return date.strftime(date_format)
186
187 return lang_obj.format('%.' + str(digits) + 'f', value, grouping=grouping, monetary=monetary)
188
142 def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):189 def create_single_pdf(self, cursor, uid, ids, data, report_xml, context=None):
143 """generate the PDF"""190 """generate the PDF"""
144 self.parser_instance = self.parser(191 self.parser_instance = self.parser(
@@ -190,74 +237,81 @@
190<body style="border:0; margin: 0;" onload="subst()">237<body style="border:0; margin: 0;" onload="subst()">
191</body>238</body>
192</html>"""239</html>"""
240 self.parser_instance.localcontext.update({'setLang':self.setLang})
241 self.parser_instance.localcontext.update({'formatLang':self.formatLang})
193 css = report_xml.webkit_header.css242 css = report_xml.webkit_header.css
194 if not css :243 if not css :
195 css = ''244 css = ''
196 user = self.pool.get('res.users').browse(cursor, uid, uid)245 user = self.pool.get('res.users').browse(cursor, uid, uid)
197 company= user.company_id246 company = user.company_id
198 parse_template = template247 parse_template = template
199 #default_filters=['unicode', 'entity'] can be used to set global filter248 #default_filters=['unicode', 'entity'] can be used to set global filter
200 body_mako_tpl = Template(parse_template ,input_encoding='utf-8')249 body_mako_tpl = Template(parse_template ,input_encoding='utf-8', output_encoding='utf-8')
201 #BVR specific250 #BVR specific
202 bvr_path = addons.get_module_resource(os.path.join('l10n_ch','report','bvr.mako'))251 bvr_path = addons.get_module_resource(os.path.join('l10n_ch','report','bvr.mako'))
203 body_bvr_tpl = Template(file(bvr_path).read(), input_encoding='utf-8')252 body_bvr_tpl = Template(file(bvr_path).read(), input_encoding='utf-8', output_encoding='utf-8')
204253
205 helper = report_helper.WebKitHelper(cursor, uid, report_xml.id, context)254 helper = report_helper.WebKitHelper(cursor, uid, report_xml.id, context)
206 ##BVR Specific255 ##BVR Specific
207 htmls = []256 htmls = []
208 for obj in objs :257 for obj in objs :
209
210 self.parser_instance.localcontext['objects'] = [obj]258 self.parser_instance.localcontext['objects'] = [obj]
211 if not company.bvr_only:259 if not company.bvr_only:
212 html = body_mako_tpl.render(260 try:
213 helper=helper, 261 html = body_mako_tpl.render(
214 css=css,262 helper=helper,
215 _=self.translate_call,263 css=css,
216 **self.parser_instance.localcontext264 _=self.translate_call,
217 )265 **self.parser_instance.localcontext
266 )
267 except Exception, e:
268 raise Exception(exceptions.text_error_template().render())
218 htmls.append(html)269 htmls.append(html)
219 if not company.invoice_only:270 if not company.invoice_only:
220 bvr = body_bvr_tpl.render(271 try:
221 helper=helper, 272 bvr = body_bvr_tpl.render(
222 css=css,273 helper=helper,
223 _=self.translate_call,274 css=css,
224 **self.parser_instance.localcontext275 _=self.translate_call,
276 **self.parser_instance.localcontext
277 )
278 except Exception, e:
279 raise Exception(exceptions.text_error_template().render())
280 htmls.append(bvr)
281 head_mako_tpl = Template(header, input_encoding='utf-8', output_encoding='utf-8')
282 try:
283 head = head_mako_tpl.render(
284 helper=helper,
285 css=css,
286 _debug=False,
287 _=self.translate_call,
288 **self.parser_instance.localcontext
225 )289 )
226 htmls.append(bvr) 290 except Exception, e:
227 head_mako_tpl = Template(header, input_encoding='utf-8')291 raise Exception(exceptions.text_error_template().render())
228 head = head_mako_tpl.render(
229 company=company,
230 time=time,
231 helper=helper,
232 css=css,
233 formatLang=self.parser_instance.formatLang,
234 setLang=self.parser_instance.setLang,
235 _debug=False
236 )
237 foot = False292 foot = False
238 if footer and company.invoice_only :293 if footer and company.invoice_only :
239 foot_mako_tpl = Template(footer ,input_encoding='utf-8')294 foot_mako_tpl = Template(footer, input_encoding='utf-8', output_encoding='utf-8')
240 foot = foot_mako_tpl.render(295 try:
241 company=company, 296 foot = foot_mako_tpl.render(
242 time=time, 297 helper=helper,
243 helper=helper, 298 css=css,
244 css=css, 299 _=self.translate_call,
245 formatLang=self.parser_instance.formatLang,300 **self.parser_instance.localcontext
246 setLang=self.parser_instance.setLang,301 )
247 _=self.translate_call,302 except Exception, e:
248303 raise Exception(exceptions.text_error_template().render())
249 )
250 if report_xml.webkit_debug :304 if report_xml.webkit_debug :
251 deb = head_mako_tpl.render(305 try:
252 company=company, 306 deb = head_mako_tpl.render(
253 time=time, 307 helper=helper,
254 helper=helper, 308 css=css,
255 css=css, 309 _debug=html,
256 _debug=html,310 _=self.translate_call,
257 formatLang=self.parser_instance.formatLang,311 **self.parser_instance.localcontext
258 setLang=self.parser_instance.setLang,312 )
259 _=self.translate_call,313 except Exception, e:
260 )314 raise Exception(exceptions.text_error_template().render())
261 return (deb, 'html')315 return (deb, 'html')
262 bin = self.get_lib(cursor, uid, company.id)316 bin = self.get_lib(cursor, uid, company.id)
263 pdf = self.generate_pdf(bin, report_xml, head, foot, htmls)317 pdf = self.generate_pdf(bin, report_xml, head, foot, htmls)
264318
=== modified file 'l10n_ch/report/report_webkit_html_view.xml'
--- l10n_ch/report/report_webkit_html_view.xml 2011-02-09 08:59:05 +0000
+++ l10n_ch/report/report_webkit_html_view.xml 2011-09-14 14:11:28 +0000
@@ -5,55 +5,57 @@
5 <field name="orientation">Portrait</field>5 <field name="orientation">Portrait</field>
6 <field name="format">A4</field>6 <field name="format">A4</field>
7 <field name="html"><![CDATA[<html>7 <field name="html"><![CDATA[<html>
8 <head>8 <head>
9 <script>9 <script>
10 function subst() {10 function subst() {
11 var vars={};11 var vars={};
12 var x=document.location.search.substring(1).split('&');12 var x=document.location.search.substring(1).split('&');
13 for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}13 for(var i in x) {var z=x[i].split('=',2);vars[z[0]] = unescape(z[1]);}
14 var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];14 var x=['frompage','topage','page','webpage','section','subsection','subsubsection'];
15 for(var i in x) {15 for(var i in x) {
16 var y = document.getElementsByClassName(x[i]);16 var y = document.getElementsByClassName(x[i]);
17 for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];17 for(var j=0; j<y.length; ++j) y[j].textContent = vars[x[i]];
18 }18 }
19 }19 }
20 </script>20 </script>
21 <style type="text/css">21 <style type="text/css">
22 ${css}22 ${css}
23 </style>23 </style>
24 </head>24 </head>
25 <body style="border:0; margin: 0;" onload="subst()">25 <!-- <tr style="vertical-align:top">
26 <table class="header" style="border-bottom: 0px solid black; width: 100%;padding-left:20mm">26 <td style="text-align:right;font-size:12" ><span class="page"/></td><td style="text-align:left;font-size:12;"> / <span class="topage"/></td>
27 <tr style="vertical-align:top" >27 </tr> style="text-align:right"-->
28 <td>${helper.embed_logo_by_name('camptocamp_logo', width=64)}</td>28 <body style="border:0; margin: 0;" onload="subst()">
29 <td style="text-align:right">29 <table style="border-bottom: 1px solid black; width: 90%;padding-left:0mm;margin-left:5%">
30 <table style="border-top: 0px solid black; width: 100%;height:100%">30 <tr style="vertical-align:top" >
31 <tr style="vertical-align:top">31 <td>${helper.embed_logo_by_name('camptocamp_logo', width=128)}</td>
32 <td style="text-align:right;font-size:12" width="80%"><span class="page"/></td><td style="text-align:left;font-size:12;"> / <span class="topage"/></td>32 <td >
33 </tr>33
34 </table> </td>34 <table style="border-top: 0px solid black; width: 100%;height:100%;;padding-left:4mm; margin-left:2%" class="dest_address">
35 </tr>35 <tr>
36 <tr>36 <td><b>${company.partner_id.name |entity}</b></td><td></td><td></td>
37 <td><br/></td>37 </tr>
38 <td style="text-align:right"> </td>38 <tr>
39 </tr>39 <td>${company.partner_id.address and company.partner_id.address[0].street or ''|entity}</td><td>${_("phone")}:</td><td>${company.partner_id.address and company.partner_id.address[0].phone or ''|entity} </td><td></td>
40 <tr>40 </tr>
41 <td>${company.partner_id.name |entity}</td>41 <tr>
42 <td/>42 <td>${company.partner_id.address and company.partner_id.address[0].street2 or ''|entity}</td><td>${_('Fax')}:</td><td>${company.partner_id.address and company.partner_id.address[0].fax or ''|entity} </td><td></td>
43 </tr>43 </tr>
44 <tr>44 <tr>
45 <td >${company.partner_id.address and company.partner_id.address[0].street or ''|entity}</td>45 <td>${company.partner_id.address and company.partner_id.address[0].zip or ''|entity} ${company.partner_id.address and company.partner_id.address[0].city or ''|entity}</td><td>${_('e-mail')}:</td><td><a href="mailto:${company.partner_id.address and company.partner_id.address[0].email or ''|entity}">${company.partner_id.address and company.partner_id.address[0].email or ''|entity}</a></td><td></td>
46 <td/>46 </tr>
47 </tr>47 <tr>
48 <tr>48 <td>${company.partner_id.address and company.partner_id.address[0].country_id.name or ''|entity}</td><td></td><td style="text-align:right;font-size:12" ><span class="page"/></td><td style="text-align:left;font-size:12;"> / <span class="topage"/></td>
49 <td>Phone: ${company.partner_id.address and company.partner_id.address[0].phone or ''|entity} </td>49 </tr>
50 <td/>50 </table>
51 </tr>51 </td>
52 <tr>52 </tr>
53 <td>Mail: <a href="mailto:${company.partner_id.address and company.partner_id.address[0].email or ''|entity}">${company.partner_id.address and company.partner_id.address[0].email or ''|entity}</a><br/></td>53 </table>
54 </tr>54 <br/>
55 </table> ${_debug or ''} <br/></body>55 ${_debug or ''}
56 </html>]]>56 <br/>
57 </body>
58</html>]]>
57 </field>59 </field>
58 <field eval="45" name="margin_top"/>60 <field eval="45" name="margin_top"/>
59 <field eval="0.01" name="margin_bottom"/>61 <field eval="0.01" name="margin_bottom"/>
6062
=== modified file 'l10n_ch/sterchi_chart/account.xml'
--- l10n_ch/sterchi_chart/account.xml 2011-02-09 08:59:05 +0000
+++ l10n_ch/sterchi_chart/account.xml 2011-09-14 14:11:28 +0000
@@ -11773,10 +11773,10 @@
11773 <field name="parent_id" eval="False"/>11773 <field name="parent_id" eval="False"/>
11774 </record>11774 </record>
11775 <record id="l10nch_chart_template" model="account.chart.template">11775 <record id="l10nch_chart_template" model="account.chart.template">
11776 <field name="name">Swiss PCG</field>11776 <field name="name">Plan comptable STERCHI</field>
11777 <field name="account_root_id" ref="ch_minimal_0"/>11777 <field name="account_root_id" ref="ch_minimal_0"/>
11778 <field name="tax_code_root_id" ref="vat_code_chart_root"/>11778 <field name="tax_code_root_id" ref="vat_code_chart_root"/>
11779 <field name="bank_account_view_id" ref="ch_3400"/>11779 <field name="bank_account_view_id" ref="ch_102_0"/>
11780 <field name="property_account_receivable" ref="ch_1100"/>11780 <field name="property_account_receivable" ref="ch_1100"/>
11781 <field name="property_account_payable" ref="ch_2000"/>11781 <field name="property_account_payable" ref="ch_2000"/>
11782 <field name="property_account_expense_categ" ref="ch_4200"/>11782 <field name="property_account_expense_categ" ref="ch_4200"/>
1178311783
=== modified file 'l10n_ch/sterchi_chart/fiscal_position.xml'
--- l10n_ch/sterchi_chart/fiscal_position.xml 2011-05-25 11:51:33 +0000
+++ l10n_ch/sterchi_chart/fiscal_position.xml 2011-09-14 14:11:28 +0000
@@ -115,4 +115,4 @@
115 <field name="tax_dest_id" ref="vat_XO" />115 <field name="tax_dest_id" ref="vat_XO" />
116 </record>116 </record>
117 </data>117 </data>
118</openerp>
119\ No newline at end of file118\ No newline at end of file
119</openerp>
120120
=== added file 'l10n_ch/test/l10n_ch_dta.yml'
--- l10n_ch/test/l10n_ch_dta.yml 1970-01-01 00:00:00 +0000
+++ l10n_ch/test/l10n_ch_dta.yml 2011-09-14 14:11:28 +0000
@@ -0,0 +1,221 @@
1-
2 In order to test DTA generation I make an invoice and create the DTA from it.
3-
4 I create an invoice on 1st January for 7000 EUR
5 ###########################
6 # Creating 1 invoice #
7###########################
8-
9 !record {model: account.invoice, id: dta_account_invoice}:
10 company_id: base.main_company
11 journal_id: account.bank_journal
12 currency_id: base.EUR
13 account_id: account.a_pay
14 type : in_invoice
15 partner_id: base.res_partner_agrolait
16 address_contact_id: base.res_partner_address_8
17 address_invoice_id: base.res_partner_address_8
18 reference_type: bvr
19 reference: 111111111111111111111111111111
20 date_invoice: !eval "'%s-01-01' %(datetime.now().year)"
21 period_id: account.period_1
22 #invoice_line:
23 partner_bank_id: main_partner_bank
24 check_total : 7000
25-
26 I add an invoice line
27-
28 !record {model: account.invoice.line, id: dta_invoice_line}:
29 account_id: account.a_expense
30 name: '[PC1] Basic PC'
31 price_unit: 700.0
32 quantity: 10.0
33 product_id: product.product_product_pc1
34 uos_id: product.product_uom_unit
35 invoice_id: dta_account_invoice
36
37
38-
39 I Validate invoice by clicking on Validate button
40-
41 !workflow {model: account.invoice, action: invoice_open, ref: dta_account_invoice}
42
43-
44 I create my payment order to pay my invoice
45 ###########################
46 # Doing payment order #
47###########################
48-
49 !record {model: payment.order, id: dta_payment_order}:
50 #date_created
51 #date_done
52 date_prefered: due
53 #date_scheduled
54 #line_ids:
55 mode: l10n_ch.payment_mode_dta
56 #reference
57 state: draft
58 total: 7000
59 #user_id
60-
61 I add a payment line to my payment order
62-
63 !record {model: payment.line, id: dta_pay_line}:
64 amount: 7000
65 amount_currency: 7000
66 bank_id: l10n_ch.agro_bank
67 #bank_statement_line_id
68 communication: "111111111111111111111111111111"
69 #communication2
70 company_currency: base.EUR
71 #create_date
72 currency: base.EUR
73 #date
74 #info_owner
75 #info_partner
76 #ml_date_created
77 #ml_inv_ref
78 #ml_maturity_date
79 move_line_id: !ref {model: account.move.line, search: "[('ref','=','111111111111111111111111111111')]"}
80 #name (reference)
81 order_id: dta_payment_order
82 partner_id: base.res_partner_agrolait
83 state: normal
84
85-
86 I generate a DTA file by using the wizard "Create DTA" for my payment order
87-
88 !python {model: create.dta.wizard}: |
89 import base64
90 wiz_id = self.create(cr,uid,[])
91 wiz = self.browse(cr, uid, wiz_id)
92 pay_order_id = ref("dta_payment_order")
93 #set the payment order as the active id
94 context['active_ids'] = [pay_order_id]
95 context['active_id'] = pay_order_id
96 result = wiz.create_dta(context=context)
97 assert result, "No result returned"
98
99 data = wiz.read(['dta_file'])
100 dta_file = base64.decodestring(data[0]['dta_file'] or '')
101 assert dta_file, "File is empty"
102
103 #check that file starts with 1st segment characters "01"
104 assert dta_file[:2] == "01", "File is not a DTA file"
105
106 payment_obj = self.pool.get('payment.order')
107 payment_obj.set_done(cr, uid, [ref('dta_payment_order')], context)
108 #force state in open state (confirmed)
109 payment_obj.write(cr, uid, [ref('dta_payment_order')], {'state': 'open'})
110
111-
112 I check the execution date is today
113-
114 !assert {model: payment.order, id: dta_payment_order}:
115 - date_done == datetime.now().date().strftime('%Y-%m-%d')
116
117-
118 I check my payment order state is Confirmed
119-
120 !assert {model: payment.order, id: dta_payment_order, string: state is done}:
121 - state == 'open'
122
123-
124 I create a Bank Statment in order to confirm the payment line
125-
126 !record {model: account.bank.statement, id: dta_bank_statement}:
127 #account_id:
128 #balance_end:
129 #balance_end_cash:
130 #balance_end_real:
131 #balance_start:
132 #closing_date:
133 #company_id:
134 #currency:
135 date: !eval "'%s-01-01' %(datetime.now().year)"
136 #ending_details_ids:
137 journal_id: account.bank_journal
138 #line_ids:
139 #move_line_ids
140 name: "/"
141 period_id: account.period_1
142 #starting_details_ids
143 state: draft
144 #total_entry_encoding
145 #user_id
146
147-
148 I import the payment line
149-
150 !python {model: account.payment.populate.statement}: |
151 wiz_id = self.create(cr,uid,[])
152 wiz = self.browse(cr, uid, wiz_id)
153
154 line_obj = self.pool.get('payment.line')
155 pay_line_ids = line_obj.search(cr, uid, [('communication','=','111111111111111111111111111111'),('amount','=','7000')])
156
157 data = { 'lines': [(6, 0, [pay_line_ids[0]])],}
158 wiz.write(data)
159
160 context['active_id'] = ref('dta_bank_statement')
161 context['active_ids'] = [ref('dta_bank_statement')]
162
163 self.populate_statement(cr, uid, [wiz_id], context=context)
164
165
166-
167 I check the statement line is created
168-
169 !assert {model: account.bank.statement, id: dta_bank_statement, string: statement_line_ids is not empty}:
170 - line_ids
171
172-
173 I check the voucher line is created
174-
175 !python {model: account.bank.statement}: |
176 statement = self.browse(cr, uid, ref('dta_bank_statement'))
177
178 assert statement.line_ids[0].voucher_id.line_ids, "Voucher line is missing"
179 assert len(statement.line_ids[0].voucher_id.line_ids) == 1, "There are too many voucher lines"
180
181-
182 In order to confirm my bank statement, I enter the closing balance and press on compute button
183-
184 !python {model: account.bank.statement}: |
185 statement = self.browse(cr, uid, ref('dta_bank_statement'))
186 statement.write({'balance_end_real': -7000.0})
187 self.button_dummy(cr, uid, [ref('dta_bank_statement')], context=context)
188 statement = self.browse(cr, uid, ref('dta_bank_statement'))
189
190-
191 I confirm my bank statement
192-
193 !python {model: account.bank.statement}: |
194 self.button_confirm_bank(cr, uid, [ref('dta_bank_statement')], context=context)
195
196
197-
198 I check the move lines have been defined
199-
200 !assert {model: account.bank.statement, id: dta_bank_statement, string: move_line_ids is not empty}:
201 - move_line_ids
202
203
204-
205 I check bank statement is Closed and balance is -7000
206-
207 !assert {model: account.bank.statement, id: dta_bank_statement, string: state is Closed and balance is -7000}:
208 - state == 'confirm'
209 - balance_end == -7000.0
210
211-
212 I check the residual amount of invoice, should be 0 in residual currency and 0 in amount_residual and paid
213-
214 !python {model: account.invoice}: |
215 invoice_id = self.browse(cr, uid, ref("dta_account_invoice"))
216 move_line_obj = self.pool.get('account.move.line')
217 move_lines = move_line_obj.search(cr, uid, [('move_id', '=', invoice_id.move_id.id), ('invoice', '=', invoice_id.id), ('account_id', '=', invoice_id.account_id.id)])
218 move_line = move_line_obj.browse(cr, uid, move_lines[0])
219 assert move_line.amount_residual_currency == 0.0, "Residual amount currency is not correct : %.2f" % move_line.amount_residual_currency
220 assert move_line.amount_residual == 0.0 , "Residual amount of invoice is not correct : %.2f" % move_line.amount_residual
221 assert invoice_id.state == 'paid', "Invoice state is not Paid"
0\ No newline at end of file222\ No newline at end of file
1223
=== added file 'l10n_ch/test/l10n_ch_v11.yml'
--- l10n_ch/test/l10n_ch_v11.yml 1970-01-01 00:00:00 +0000
+++ l10n_ch/test/l10n_ch_v11.yml 2011-09-14 14:11:28 +0000
@@ -0,0 +1,161 @@
1-
2 In order to test the V11 import,
3 I will create an invoice with a specified reference that I will reconcile with the moves imported from a V11
4-
5 I create an invoice ref 1234567
6-
7 !record {model: account.invoice, id: v11_test_invoice}:
8 name: V11 YAML invoice
9 number: 1234567
10 company_id: base.main_company
11 journal_id: account.bank_journal
12 currency_id: base.EUR
13 account_id: account.a_recv
14 type : out_invoice
15 partner_id: base.res_partner_agrolait
16 address_contact_id: base.res_partner_address_8
17 address_invoice_id: base.res_partner_address_8
18 reference_type: bvr
19 reference: 12345676
20 date_invoice: !eval "'%s-01-01' %(datetime.now().year)"
21 period_id: account.period_1
22 #invoice_line:
23 partner_bank_id: main_partner_bank
24 check_total : 888.00
25
26-
27 I create an invoice line
28-
29 !record {model: account.invoice.line, id: v11_test_invoice_line}:
30 account_id: account.a_expense
31 name: '[PC1] Basic PC'
32 price_unit: 888.00
33 quantity: 1.0
34 product_id: product.product_product_pc1
35 uos_id: product.product_uom_unit
36 invoice_id: v11_test_invoice
37
38-
39 I Validate invoice by clicking on Validate button
40-
41 !workflow {model: account.invoice, action: invoice_open, ref: v11_test_invoice}
42
43-
44 I specify the invoice number to fit with my v11
45-
46 !python {model: account.invoice}: |
47 invoice = self.browse(cr, uid, ref('v11_test_invoice'))
48 invoice.write({'number': 1234567})
49
50
51-
52 I create a bank statement
53-
54 !record {model: account.bank.statement, id: v11_test_bank_statement}:
55 #account_id:
56 #balance_end:
57 #balance_end_cash:
58 #balance_end_real:
59 #balance_start:
60 #closing_date:
61 #company_id:
62 #currency:
63 date: !eval "'%s-01-01' %(datetime.now().year)"
64 #ending_details_ids:
65 journal_id: account.bank_journal
66 #line_ids:
67 #move_line_ids
68 name: "/"
69 period_id: account.period_1
70 #starting_details_ids
71 state: draft
72 #total_entry_encoding
73 #user_id
74
75-
76 I import the V11
77-
78 !python {model: bvr.import.wizard}: |
79 import base64
80 import addons
81 import os
82
83 # create our wizard
84 wiz_id = self.create(cr,uid,[])
85 wiz = self.browse(cr, uid, wiz_id)
86
87 test_file_path = addons.get_module_resource(os.path.join('l10n_ch', 'test', 'test.v11'))
88
89 # get our test file to test it
90 f_v11 = open(test_file_path)
91
92 str64_v11 = base64.encodestring(f_v11.read())
93
94 wiz.write({'file': str64_v11})
95
96 # set the file in the wizard field
97 bank_statement_id = ref('v11_test_bank_statement')
98
99 context['active_id'] = bank_statement_id
100 context['active_ids'] = [bank_statement_id]
101 # launch the import
102 self.import_bvr(cr, uid, [wiz_id], context=context)
103
104
105-
106 I check my bank statement got a statement line
107-
108 !assert {model: account.bank.statement, id: v11_test_bank_statement, string: statement has 1 and only 1 statement line id}:
109 - len(line_ids) == 1
110
111-
112 I check the voucher linked to the statement line contains a line with an amount of 888.00
113-
114 !python {model: account.bank.statement}: |
115 statement = self.browse(cr, uid, ref('v11_test_bank_statement'))
116
117 voucher_line_ids = statement.line_ids[0].voucher_id.line_ids
118
119 assert voucher_line_ids, "No voucher line found"
120
121 voucher_line_amount = voucher_line_ids[0].amount
122 assert voucher_line_amount == 888.00, "Amount isn't correct : %d" %(voucher_line_amount)
123
124-
125 I check amount of account voucher is equal to the bank statement line amount
126-
127 !python {model: account.bank.statement}: |
128 statement = self.browse(cr, uid, ref('v11_test_bank_statement'))
129
130 statement_line_amount = statement.line_ids[0].amount
131 voucher_amount = statement.line_ids[0].voucher_id.amount
132
133 assert statement_line_amount == voucher_amount, "Mismatch of amounts"
134
135-
136 I enter the closing balance and press on compute button
137-
138 !python {model: account.bank.statement}: |
139 statement = self.browse(cr, uid, ref('v11_test_bank_statement'))
140 statement.write({'balance_end_real': 888.00})
141 self.button_dummy(cr, uid, [ref('v11_test_bank_statement')], context=context)
142
143-
144 I check that the statement Balance is 888.00
145-
146 !assert {model: account.bank.statement, id: v11_test_bank_statement, string: balance is 888.0}:
147 - balance_end == 888.0
148
149-
150 I confirm my bank statement
151-
152 !python {model: account.bank.statement}: |
153 self.button_confirm_bank(cr, uid, [ref('v11_test_bank_statement')], context=context)
154
155-
156 I check my invoice is paid, reconciled and has no residual
157-
158 !assert {model: account.invoice, id: v11_test_invoice, string: 'invoice is paid, reconciled and has no residual'}:
159 - state == "paid"
160 - reconciled
161 - residual == 0.0
0\ No newline at end of file162\ No newline at end of file
1163
=== added file 'l10n_ch/test/l10n_ch_v11_part.yml'
--- l10n_ch/test/l10n_ch_v11_part.yml 1970-01-01 00:00:00 +0000
+++ l10n_ch/test/l10n_ch_v11_part.yml 2011-09-14 14:11:28 +0000
@@ -0,0 +1,292 @@
1-
2 In order to test the V11 import,
3 I will create an invoice with a specified reference that I will partialy reconcile with a 1st V11
4 And then I will complete the reconcile with a second V11
5-
6 I create an invoice ref 2000999 of EUR 250.00
7-
8 !record {model: account.invoice, id: v11_part_test_invoice}:
9 name: V11 YAML invoice
10 number: 2000999
11 company_id: base.main_company
12 journal_id: account.bank_journal
13 currency_id: base.EUR
14 account_id: account.a_recv
15 type : out_invoice
16 partner_id: base.res_partner_agrolait
17 address_contact_id: base.res_partner_address_8
18 address_invoice_id: base.res_partner_address_8
19 reference_type: bvr
20 reference: 20009997
21 date_invoice: !eval "'%s-01-01' %(datetime.now().year)"
22 period_id: account.period_1
23 #invoice_line:
24 partner_bank_id: main_partner_bank
25 check_total : 250.00
26
27-
28 I create an invoice line
29-
30 !record {model: account.invoice.line, id: v11_part_test_invoice_line}:
31 account_id: account.a_expense
32 name: '[PC1] Basic PC'
33 price_unit: 250.00
34 quantity: 1.0
35 product_id: product.product_product_pc1
36 uos_id: product.product_uom_unit
37 invoice_id: v11_part_test_invoice
38
39-
40 I Validate invoice by clicking on Validate button
41-
42 !workflow {model: account.invoice, action: invoice_open, ref: v11_part_test_invoice}
43
44-
45 I specify the invoice number to fit with my v11
46-
47 !python {model: account.invoice}: |
48 invoice = self.browse(cr, uid, ref('v11_part_test_invoice'))
49 invoice.write({'number': 2000999})
50
51
52-
53 I create a 1st bank statement
54 #########################################
55 # Creating 1st bank statement #
56#########################################
57-
58 !record {model: account.bank.statement, id: v11_part_test_bank_statement_1}:
59 #account_id:
60 #balance_end:
61 #balance_end_cash:
62 #balance_end_real:
63 #balance_start:
64 #closing_date:
65 #company_id:
66 #currency:
67 date: !eval "'%s-01-01' %(datetime.now().year)"
68 #ending_details_ids:
69 journal_id: account.bank_journal
70 #line_ids:
71 #move_line_ids
72 name: "/"
73 period_id: account.period_1
74 #starting_details_ids
75 state: draft
76 #total_entry_encoding
77 #user_id
78
79-
80 I import the 1st V11
81-
82 !python {model: bvr.import.wizard}: |
83 import base64
84 import addons
85 import os
86
87 # create our wizard
88 wiz_id = self.create(cr,uid,[])
89 wiz = self.browse(cr, uid, wiz_id)
90
91 test_file_path = addons.get_module_resource(os.path.join('l10n_ch', 'test', 'test_part_1.v11'))
92
93 # get our test file to test it
94 f_v11 = open(test_file_path)
95
96 str64_v11 = base64.encodestring(f_v11.read())
97
98 wiz.write({'file': str64_v11})
99
100 # set the file in the wizard field
101 bank_statement_id = ref('v11_part_test_bank_statement_1')
102
103 context['active_id'] = bank_statement_id
104 context['active_ids'] = [bank_statement_id]
105 # launch the import
106 self.import_bvr(cr, uid, [wiz_id], context=context)
107
108
109-
110 I check my bank statement got a statement line
111-
112 !assert {model: account.bank.statement, id: v11_part_test_bank_statement_1, string: statement has 1 and only 1 statement line id}:
113 - len(line_ids) == 1
114
115-
116 I check the voucher linked to the statement line contains a line with an amount of EUR 150.00
117-
118 !python {model: account.bank.statement}: |
119 statement = self.browse(cr, uid, ref('v11_part_test_bank_statement_1'))
120
121 voucher_line_ids = statement.line_ids[0].voucher_id.line_ids
122
123 assert voucher_line_ids, "No voucher line found"
124
125 voucher_line_amount = voucher_line_ids[0].amount
126 assert voucher_line_amount == 150.00, "Amount isn't correct : %d" %(voucher_line_amount)
127
128-
129 I check amount of account voucher is equal to the bank statement line amount
130-
131 !python {model: account.bank.statement}: |
132 statement = self.browse(cr, uid, ref('v11_part_test_bank_statement_1'))
133
134 statement_line_amount = statement.line_ids[0].amount
135 voucher_amount = statement.line_ids[0].voucher_id.amount
136
137 assert statement_line_amount == voucher_amount, "Mismatch of amounts"
138
139-
140 I enter the closing balance and press on compute button
141-
142 !python {model: account.bank.statement}: |
143 statement = self.browse(cr, uid, ref('v11_part_test_bank_statement_1'))
144 statement.write({'balance_end_real': 150.00})
145 self.button_dummy(cr, uid, [ref('v11_part_test_bank_statement_1')], context=context)
146
147-
148 I check that the statement Balance is EUR 150.00
149-
150 !assert {model: account.bank.statement, id: v11_part_test_bank_statement_1, string: balance is 150.0}:
151 - balance_end == 150.0
152
153-
154 I confirm my 1st bank statement
155-
156 !python {model: account.bank.statement}: |
157 self.button_confirm_bank(cr, uid, [ref('v11_part_test_bank_statement_1')], context=context)
158
159
160-
161 I check that my invoice is partially paid in open state, not reconciled, with a residual amount of EUR 100.0
162 #########################################
163 # Checking partial result #
164#########################################
165-
166 !assert {model: account.invoice, id: v11_part_test_invoice, string: 'invoice is open, reconciled and has no residual'}:
167 - state == "open"
168 - not reconciled
169 - residual == 100.0
170
171
172
173-
174 I create a 2nd bank statement
175 #########################################
176 # Creating 2nd bank statement #
177#########################################
178-
179 !record {model: account.bank.statement, id: v11_part_test_bank_statement_2}:
180 #account_id:
181 #balance_end:
182 #balance_end_cash:
183 #balance_end_real:
184 #balance_start:
185 #closing_date:
186 #company_id:
187 #currency:
188 date: !eval "'%s-01-01' %(datetime.now().year)"
189 #ending_details_ids:
190 journal_id: account.bank_journal
191 #line_ids:
192 #move_line_ids
193 name: "/"
194 period_id: account.period_1
195 #starting_details_ids
196 state: draft
197 #total_entry_encoding
198 #user_id
199
200-
201 I import the 2nd V11
202-
203 !python {model: bvr.import.wizard}: |
204 import base64
205 import addons
206 import os
207
208 # create our wizard
209 wiz_id = self.create(cr,uid,[])
210 wiz = self.browse(cr, uid, wiz_id)
211
212 test_file_path = addons.get_module_resource(os.path.join('l10n_ch', 'test', 'test_part_2.v11'))
213
214 # get our test file to test it
215 f_v11 = open(test_file_path)
216
217 str64_v11 = base64.encodestring(f_v11.read())
218
219 wiz.write({'file': str64_v11})
220
221 # set the file in the wizard field
222 bank_statement_id = ref('v11_part_test_bank_statement_2')
223
224 context['active_id'] = bank_statement_id
225 context['active_ids'] = [bank_statement_id]
226 # launch the import
227 self.import_bvr(cr, uid, [wiz_id], context=context)
228
229
230-
231 I check my bank statement got a statement line
232-
233 !assert {model: account.bank.statement, id: v11_part_test_bank_statement_2, string: statement has 1 and only 1 statement line id}:
234 - len(line_ids) == 1
235
236-
237 I check the voucher linked to the statement line contains a line with an amount of EUR 100.00
238-
239 !python {model: account.bank.statement}: |
240 statement = self.browse(cr, uid, ref('v11_part_test_bank_statement_2'))
241
242 voucher_line_ids = statement.line_ids[0].voucher_id.line_ids
243
244 assert voucher_line_ids, "No voucher line found"
245
246 voucher_line_amount = voucher_line_ids[0].amount
247 assert voucher_line_amount == 100.00, "Amount isn't correct : %d" %(voucher_line_amount)
248
249-
250 I check amount of account voucher is equal to the bank statement line amount
251-
252 !python {model: account.bank.statement}: |
253 statement = self.browse(cr, uid, ref('v11_part_test_bank_statement_2'))
254
255 statement_line_amount = statement.line_ids[0].amount
256 voucher_amount = statement.line_ids[0].voucher_id.amount
257
258 assert statement_line_amount == voucher_amount, "Mismatch of amounts"
259
260
261-
262 I enter the closing balance and press on compute button
263-
264 !python {model: account.bank.statement}: |
265 statement = self.browse(cr, uid, ref('v11_part_test_bank_statement_2'))
266 statement.write({'balance_end_real': 100.00})
267 self.button_dummy(cr, uid, [ref('v11_part_test_bank_statement_2')], context=context)
268
269-
270 I check that the statement Balance is EUR 100.00
271-
272 !assert {model: account.bank.statement, id: v11_part_test_bank_statement_2, string: balance is 100.0}:
273 - balance_end == 100.0
274
275-
276 I confirm my 2nd bank statement
277-
278 !python {model: account.bank.statement}: |
279 self.button_confirm_bank(cr, uid, [ref('v11_part_test_bank_statement_2')], context=context)
280
281
282
283-
284 I check my invoice is paid, reconciled and has no residual
285 #########################################
286 # Checking finale state #
287#########################################
288-
289 !assert {model: account.invoice, id: v11_part_test_invoice, string: 'invoice is paid, reconciled and has no residual'}:
290 - state == "paid"
291 - reconciled
292 - residual == 0.0
0\ No newline at end of file293\ No newline at end of file
1294
=== added file 'l10n_ch/test/test.v11'
--- l10n_ch/test/test.v11 1970-01-01 00:00:00 +0000
+++ l10n_ch/test/test.v11 2011-09-14 14:11:28 +0000
@@ -0,0 +1,2 @@
100201012162700000000000000000001234567600000888000001 000111010111010111010100000000010000000000000
2999010121627999999999999999999999999999000000088800000000000001110102000000000000000000
03
=== added file 'l10n_ch/test/test_part_1.v11'
--- l10n_ch/test/test_part_1.v11 1970-01-01 00:00:00 +0000
+++ l10n_ch/test/test_part_1.v11 2011-09-14 14:11:28 +0000
@@ -0,0 +1,2 @@
100201012162700000000000000000002000999700000150000001 000111010111010111010100000000010000000000000
2999010121627999999999999999999999999999000000015000000000000001110102000000000000000000
03
=== added file 'l10n_ch/test/test_part_2.v11'
--- l10n_ch/test/test_part_2.v11 1970-01-01 00:00:00 +0000
+++ l10n_ch/test/test_part_2.v11 2011-09-14 14:11:28 +0000
@@ -0,0 +1,2 @@
100201012162700000000000000000002000999700000100000001 000111010511010511010500000000010000000000000
2999010121627999999999999999999999999999000000010000000000000001110106000000000000000000
03
=== modified file 'l10n_ch/wizard/__init__.py'
--- l10n_ch/wizard/__init__.py 2011-01-14 12:41:54 +0000
+++ l10n_ch/wizard/__init__.py 2011-09-14 14:11:28 +0000
@@ -19,7 +19,8 @@
19#19#
20##############################################################################20##############################################################################
2121
22import create_dta22from . import create_dta
23import bvr_import23from . import bvr_import
24from . import unicode2ascii
2425
25# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:26# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
2627
=== modified file 'l10n_ch/wizard/bvr_import.py'
--- l10n_ch/wizard/bvr_import.py 2011-07-04 12:46:51 +0000
+++ l10n_ch/wizard/bvr_import.py 2011-09-14 14:11:28 +0000
@@ -36,7 +36,9 @@
36 user_current=user_obj.browse(cursor, user, user)36 user_current=user_obj.browse(cursor, user, user)
3737
38 ##38 ##
39 cursor.execute("SELECT inv.id,inv.number from account_invoice AS inv where inv.company_id = %s" ,(user_current.company_id.id,))39 cursor.execute("SELECT inv.id,inv.number from account_invoice "
40 "AS inv where inv.company_id = %s and type='out_invoice'",
41 (user_current.company_id.id,))
40 result_invoice = cursor.fetchall()42 result_invoice = cursor.fetchall()
41 REF = re.compile('[^0-9]')43 REF = re.compile('[^0-9]')
42 for inv_id,inv_name in result_invoice:44 for inv_id,inv_name in result_invoice:
@@ -60,7 +62,6 @@
60def _import(self, cursor, user, data, context=None):62def _import(self, cursor, user, data, context=None):
6163
62 statement_line_obj = self.pool.get('account.bank.statement.line')64 statement_line_obj = self.pool.get('account.bank.statement.line')
63# statement_reconcile_obj = pool.get('account.bank.statement.reconcile')
64 voucher_obj = self.pool.get('account.voucher')65 voucher_obj = self.pool.get('account.voucher')
65 voucher_line_obj = self.pool.get('account.voucher.line')66 voucher_line_obj = self.pool.get('account.voucher.line')
66 move_line_obj = self.pool.get('account.move.line')67 move_line_obj = self.pool.get('account.move.line')
@@ -167,7 +168,6 @@
167# line2reconcile = line.id168# line2reconcile = line.id
168 account_id = line.account_id.id169 account_id = line.account_id.id
169 break170 break
170 context.update({'move_line_ids': line_ids})
171 result = voucher_obj.onchange_partner_id(cursor, user, [], partner_id, journal_id=statement.journal_id.id, price=abs(record['amount']), currency_id= statement.currency.id, ttype='receipt', date=statement.date ,context=context)171 result = voucher_obj.onchange_partner_id(cursor, user, [], partner_id, journal_id=statement.journal_id.id, price=abs(record['amount']), currency_id= statement.currency.id, ttype='receipt', date=statement.date ,context=context)
172 voucher_res = { 'type': 'receipt' ,172 voucher_res = { 'type': 'receipt' ,
173173
@@ -182,6 +182,7 @@
182 'period_id': statement.period_id.id182 'period_id': statement.period_id.id
183 }183 }
184 voucher_id = voucher_obj.create(cursor, user, voucher_res, context=context)184 voucher_id = voucher_obj.create(cursor, user, voucher_res, context=context)
185 context.update({'move_line_ids': line_ids})
185 values['voucher_id'] = voucher_id186 values['voucher_id'] = voucher_id
186 voucher_line_dict = False187 voucher_line_dict = False
187 if result['value']['line_ids']:188 if result['value']['line_ids']:
@@ -207,7 +208,7 @@
207 cursor, 208 cursor,
208 user,209 user,
209 [210 [
210 ('name','=','property_account_receivable'),211 ('name','=',name),
211 ('company_id','=',statement.company_id.id),212 ('company_id','=',statement.company_id.id),
212 ('res_id', '=', False)213 ('res_id', '=', False)
213 ]214 ]
@@ -226,9 +227,9 @@
226 values['partner_id'] = partner_id227 values['partner_id'] = partner_id
227 statement_line_obj.create(cursor, user, values, context=context)228 statement_line_obj.create(cursor, user, values, context=context)
228 attachment_obj.create(cursor, user, {229 attachment_obj.create(cursor, user, {
229 'name': 'BVR',230 'name': 'BVR %s'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
230 'datas': file,231 'datas': file,
231 'datas_fname': 'BVR.txt',232 'datas_fname': 'BVR %s.txt'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
232 'res_model': 'account.bank.statement',233 'res_model': 'account.bank.statement',
233 'res_id': statement_id,234 'res_id': statement_id,
234 }, context=context)235 }, context=context)
235236
=== modified file 'l10n_ch/wizard/create_dta.py'
--- l10n_ch/wizard/create_dta.py 2011-02-09 08:59:05 +0000
+++ l10n_ch/wizard/create_dta.py 2011-09-14 14:11:28 +0000
@@ -26,6 +26,7 @@
26from osv import osv, fields26from osv import osv, fields
27import pooler27import pooler
28from tools.translate import _28from tools.translate import _
29import unicode2ascii
2930
30TRANS=[31TRANS=[
31 (u'é','e'),32 (u'é','e'),
@@ -38,6 +39,24 @@
38 (u'ä','a'),39 (u'ä','a'),
39]40]
4041
42def _u2a(text) :
43 """Tries to convert unicode charactere to asci equivalence"""
44 if not text : return ""
45 txt = ""
46 for c in text:
47 if ord(c) < 128 :
48 txt += c
49 elif c in unicode2ascii.EXTRA_LATIN_NAMES :
50 txt += unicode2ascii.EXTRA_LATIN_NAMES[c]
51 elif c in unicode2ascii.UNI2ASCII_CONVERSIONS :
52 txt += unicode2ascii.UNI2ASCII_CONVERSIONS[c]
53 elif c in unicode2ascii.EXTRA_CHARACTERS :
54 txt += unicode2ascii.EXTRA_CHARACTERS[c]
55 elif c in unicode2ascii.FG_HACKS :
56 txt += unicode2ascii.FG_HACKS[c]
57 else : txt+= "_"
58 return txt
59
41def tr(string_in):60def tr(string_in):
42 try:61 try:
43 string_in= string_in.decode('utf-8')62 string_in= string_in.decode('utf-8')
@@ -339,7 +358,9 @@
339 if context is None:358 if context is None:
340 context = {}359 context = {}
341 payment = payment_obj.browse(cr, uid, data['id'], context=context)360 payment = payment_obj.browse(cr, uid, data['id'], context=context)
342361 # if payment.state != 'done':
362 # raise osv.except_osv(_('Order not confirmed'),
363 # _('Please confirm it'))
343 if not payment.mode:364 if not payment.mode:
344 raise osv.except_osv(_('Error'),365 raise osv.except_osv(_('Error'),
345 _('No payment mode'))366 _('No payment mode'))
@@ -374,7 +395,6 @@
374 raise osv.except_osv(_('Error'),395 raise osv.except_osv(_('Error'),
375 _('No IBAN for the company bank account.'))396 _('No IBAN for the company bank account.'))
376397
377 dta_line_obj = pool.get('account.dta.line')
378 res_partner_bank_obj = pool.get('res.partner.bank')398 res_partner_bank_obj = pool.get('res.partner.bank')
379399
380 seq = 1400 seq = 1
@@ -469,7 +489,7 @@
469 # si payment structure -> bvr (826)489 # si payment structure -> bvr (826)
470 # si non -> (827)490 # si non -> (827)
471491
472 if elec_pay == 'dta_iban':492 if elec_pay == 'iban':
473 # If iban => country=country code for space reason493 # If iban => country=country code for space reason
474 v['comp_country'] = co_addr.country_id and co_addr.country_id.code+'-' or ''494 v['comp_country'] = co_addr.country_id and co_addr.country_id.code+'-' or ''
475 record_type = record_gt836495 record_type = record_gt836
@@ -552,17 +572,17 @@
552 v['sequence'] = str(seq).rjust(5).replace(' ','0')572 v['sequence'] = str(seq).rjust(5).replace(' ','0')
553 if dta :573 if dta :
554 dta = dta + record_gt890(v).generate()574 dta = dta + record_gt890(v).generate()
555575 dta_data = _u2a(dta)
556 dta_data = base64.encodestring(dta)576 dta_data = base64.encodestring(dta)
557 payment_obj.set_done(cr, uid, [data['id']], context)577 payment_obj.set_done(cr, uid, [data['id']], context)
558 attachment_obj.create(cr, uid, {578 attachment_obj.create(cr, uid, {
559 'name': 'DTA',579 'name': 'DTA%s'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
560 'datas': dta_data,580 'datas': dta_data,
561 'datas_fname': 'DTA.txt',581 'datas_fname': 'DTA%s.txt'%time.strftime("%Y-%m-%d_%H:%M:%S", time.gmtime()),
562 'res_model': 'payment.order',582 'res_model': 'payment.order',
563 'res_id': data['id'],583 'res_id': data['id'],
564 }, context=context)584 }, context=context)
565 return {'dta': dta_data}585 return dta_data
566586
567class create_dta_wizard(osv.osv_memory):587class create_dta_wizard(osv.osv_memory):
568 _name="create.dta.wizard"588 _name="create.dta.wizard"
@@ -573,6 +593,11 @@
573 def create_dta(self, cr, uid, ids, context=None):593 def create_dta(self, cr, uid, ids, context=None):
574 if not context:594 if not context:
575 context = {}595 context = {}
596 if isinstance(ids, list):
597 req_id = ids[0]
598 else:
599 req_id = ids
600 current = self.browse(cr, uid, req_id, context)
576 data = {}601 data = {}
577 active_ids = context.get('active_ids', [])602 active_ids = context.get('active_ids', [])
578 active_id = context.get('active_id', [])603 active_id = context.get('active_id', [])
@@ -580,26 +605,9 @@
580 data['ids'] = active_ids605 data['ids'] = active_ids
581 data['id'] = active_id606 data['id'] = active_id
582 dta_file = _create_dta(self, cr, uid, data, context)607 dta_file = _create_dta(self, cr, uid, data, context)
583 context.update({'dta_file':dta_file})608 current.write({'dta_file': dta_file})
584 return self.save_dta(cr, uid, ids, context)609 return True
585
586 def save_dta(self, cr, uid, ids, context=None):
587 obj_model = self.pool.get('ir.model.data')
588 if context is None:
589 context = {}
590 model_data_ids = obj_model.search(cr,uid,[('model','=','ir.ui.view'), ('name','=','dta_save_view')])
591 resource_id = obj_model.read(cr, uid, model_data_ids, fields=['res_id'])[0]['res_id']
592 return {
593 'view_type': 'form',
594 'view_mode': 'form',
595 'res_model': 'create.dta.wizard',
596 'views': [(resource_id, 'form')],
597 'type': 'ir.actions.act_window',
598 'target': 'new',
599 'context': context,
600 }
601
602610
603create_dta_wizard()611create_dta_wizard()
604612
605# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
606\ No newline at end of file613\ No newline at end of file
614# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
607615
=== modified file 'l10n_ch/wizard/create_dta_view.xml'
--- l10n_ch/wizard/create_dta_view.xml 2011-01-14 12:41:54 +0000
+++ l10n_ch/wizard/create_dta_view.xml 2011-09-14 14:11:28 +0000
@@ -10,6 +10,7 @@
10 <form string="DTA file creation - Results">10 <form string="DTA file creation - Results">
11 <group width="300" colspan="4">11 <group width="300" colspan="4">
12 <separator string="Create DTA" colspan="4"/>12 <separator string="Create DTA" colspan="4"/>
13 <field name="dta_file"/>
13 <group colspan="4">14 <group colspan="4">
14 <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2"/>15 <button special="cancel" string="Cancel" icon="gtk-cancel" colspan="2"/>
15 <button name="create_dta" string="Create DTA" type="object" icon="gtk-ok" colspan="2"/>16 <button name="create_dta" string="Create DTA" type="object" icon="gtk-ok" colspan="2"/>
@@ -38,21 +39,5 @@
38 <field name="key">action</field>39 <field name="key">action</field>
39 <field name="model">payment.order</field>40 <field name="model">payment.order</field>
40 </record>41 </record>
41
42 <!-- Save DTA -->
43 <record id="dta_save_view" model="ir.ui.view">
44 <field name="name">Save DTA</field>
45 <field name="model">create.dta.wizard</field>
46 <field name="type">form</field>
47 <field name="arch" type="xml">
48 <form string="DTA file creation - Results">
49 <group width="500" colspan="4">
50 <separator colspan="4" string="Click on 'Save as' to save the DTA file :" />
51 <field name="dta_file"/>
52 </group>
53 </form>
54 </field>
55 </record>
56
57 </data>42 </data>
58</openerp>43</openerp>
59\ No newline at end of file44\ No newline at end of file
6045
=== added file 'l10n_ch/wizard/unicode2ascii.py'
--- l10n_ch/wizard/unicode2ascii.py 1970-01-01 00:00:00 +0000
+++ l10n_ch/wizard/unicode2ascii.py 2011-09-14 14:11:28 +0000
@@ -0,0 +1,592 @@
1# -*- encoding: utf-8 -*-
2
3"""Convert many unicode characters to ascii characters that are like them.
4
5I want to collate names, with the property that a last name starting with
6O-umlaut will be in with the last name's starting with O. Horrors!
7
8So I want that many Latin-1 characters have their umlaute's, etc., stripped.
9Some of it can be done automatically but some needs to be done by hand, that
10I can tell.
11"""
12__version__='1.0.1'
13__author__='Jim Hefferon: ftpmaint at tug.ctan.org'
14__date__='2008-July-15'
15__notes__="""As sources, used effbot's web site, and
16 http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/251871
17and
18 man uni2ascii
19"""
20
21import os, os.path, sys, re
22import unicodedata
23
24# These characters that are not done automatically by NFKD, and
25# have a name starting with "LATIN". Some of these I found on the interwebs,
26# but some I did by eye. Corrections or additions appreciated.
27EXTRA_LATIN_NAMES={
28 # First are ones I got off the interweb
29 u"\N{LATIN CAPITAL LETTER O WITH STROKE}": u"O",
30 u"\N{LATIN SMALL LETTER A WITH GRAVE}": u"a",
31 u"\N{LATIN SMALL LETTER A WITH ACUTE}": u"a",
32 u"\N{LATIN SMALL LETTER A WITH CIRCUMFLEX}": u"a",
33 u"\N{LATIN SMALL LETTER A WITH TILDE}": u"a",
34 u"\N{LATIN SMALL LETTER A WITH DIAERESIS}": u"ae",
35 u"\N{LATIN SMALL LETTER A WITH RING ABOVE}": u"a",
36 u"\N{LATIN SMALL LETTER C WITH CEDILLA}": u"c",
37 u"\N{LATIN SMALL LETTER E WITH GRAVE}": u"e",
38 u"\N{LATIN SMALL LETTER E WITH ACUTE}": u"e",
39 u"\N{LATIN SMALL LETTER E WITH CIRCUMFLEX}": u"e",
40 u"\N{LATIN SMALL LETTER E WITH DIAERESIS}": u"e",
41 u"\N{LATIN SMALL LETTER I WITH GRAVE}": u"i",
42 u"\N{LATIN SMALL LETTER I WITH ACUTE}": u"i",
43 u"\N{LATIN SMALL LETTER I WITH CIRCUMFLEX}": u"i",
44 u"\N{LATIN SMALL LETTER I WITH DIAERESIS}": u"i",
45 u"\N{LATIN SMALL LETTER N WITH TILDE}": u"n",
46 u"\N{LATIN SMALL LETTER O WITH GRAVE}": u"o",
47 u"\N{LATIN SMALL LETTER O WITH ACUTE}": u"o",
48 u"\N{LATIN SMALL LETTER O WITH CIRCUMFLEX}": u"o",
49 u"\N{LATIN SMALL LETTER O WITH TILDE}": u"o",
50 u"\N{LATIN SMALL LETTER O WITH DIAERESIS}": u"oe",
51 u"\N{LATIN SMALL LETTER O WITH STROKE}": u"o",
52 u"\N{LATIN SMALL LETTER U WITH GRAVE}": u"u",
53 u"\N{LATIN SMALL LETTER U WITH ACUTE}": u"u",
54 u"\N{LATIN SMALL LETTER U WITH CIRCUMFLEX}": u"u",
55 u"\N{LATIN SMALL LETTER U WITH DIAERESIS}": u"ue",
56 u"\N{LATIN SMALL LETTER Y WITH ACUTE}": u"y",
57 u"\N{LATIN SMALL LETTER Y WITH DIAERESIS}": u"y",
58 u"\N{LATIN SMALL LETTER A WITH MACRON}": u"a",
59 u"\N{LATIN SMALL LETTER A WITH BREVE}": u"a",
60 u"\N{LATIN SMALL LETTER C WITH ACUTE}": u"c",
61 u"\N{LATIN SMALL LETTER C WITH CIRCUMFLEX}": u"c",
62 u"\N{LATIN SMALL LETTER E WITH MACRON}": u"e",
63 u"\N{LATIN SMALL LETTER E WITH BREVE}": u"e",
64 u"\N{LATIN SMALL LETTER G WITH CIRCUMFLEX}": u"g",
65 u"\N{LATIN SMALL LETTER G WITH BREVE}": u"g",
66 u"\N{LATIN SMALL LETTER G WITH CEDILLA}": u"g",
67 u"\N{LATIN SMALL LETTER H WITH CIRCUMFLEX}": u"h",
68 u"\N{LATIN SMALL LETTER I WITH TILDE}": u"i",
69 u"\N{LATIN SMALL LETTER I WITH MACRON}": u"i",
70 u"\N{LATIN SMALL LETTER I WITH BREVE}": u"i",
71 u"\N{LATIN SMALL LETTER J WITH CIRCUMFLEX}": u"j",
72 u"\N{LATIN SMALL LETTER K WITH CEDILLA}": u"k",
73 u"\N{LATIN SMALL LETTER L WITH ACUTE}": u"l",
74 u"\N{LATIN SMALL LETTER L WITH CEDILLA}": u"l",
75 u"\N{LATIN CAPITAL LETTER L WITH STROKE}": u"L",
76 u"\N{LATIN SMALL LETTER L WITH STROKE}": u"l",
77 u"\N{LATIN SMALL LETTER N WITH ACUTE}": u"n",
78 u"\N{LATIN SMALL LETTER N WITH CEDILLA}": u"n",
79 u"\N{LATIN SMALL LETTER O WITH MACRON}": u"o",
80 u"\N{LATIN SMALL LETTER O WITH BREVE}": u"o",
81 u"\N{LATIN SMALL LETTER R WITH ACUTE}": u"r",
82 u"\N{LATIN SMALL LETTER R WITH CEDILLA}": u"r",
83 u"\N{LATIN SMALL LETTER S WITH ACUTE}": u"s",
84 u"\N{LATIN SMALL LETTER S WITH CIRCUMFLEX}": u"s",
85 u"\N{LATIN SMALL LETTER S WITH CEDILLA}": u"s",
86 u"\N{LATIN SMALL LETTER T WITH CEDILLA}": u"t",
87 u"\N{LATIN SMALL LETTER U WITH TILDE}": u"u",
88 u"\N{LATIN SMALL LETTER U WITH MACRON}": u"u",
89 u"\N{LATIN SMALL LETTER U WITH BREVE}": u"u",
90 u"\N{LATIN SMALL LETTER U WITH RING ABOVE}": u"u",
91 u"\N{LATIN SMALL LETTER W WITH CIRCUMFLEX}": u"w",
92 u"\N{LATIN SMALL LETTER Y WITH CIRCUMFLEX}": u"y",
93 u"\N{LATIN SMALL LETTER Z WITH ACUTE}": u"z",
94 u"\N{LATIN SMALL LETTER W WITH GRAVE}": u"w",
95 u"\N{LATIN SMALL LETTER W WITH ACUTE}": u"w",
96 u"\N{LATIN SMALL LETTER W WITH DIAERESIS}": u"w",
97 u"\N{LATIN SMALL LETTER Y WITH GRAVE}": u"y",
98 # Below are the ones that failed automated conversion
99 u'\N{LATIN CAPITAL LETTER AE}': u'AE',
100 u'\N{LATIN CAPITAL LETTER ETH}': u'D',
101 u"\N{LATIN CAPITAL LETTER A WITH DIAERESIS}": u"Ae",
102 u"\N{LATIN CAPITAL LETTER O WITH DIAERESIS}": u"Oe",
103 u"\N{LATIN CAPITAL LETTER U WITH DIAERESIS}": u"Ue",
104 u'\N{LATIN CAPITAL LETTER O WITH STROKE}': u'O',
105 u'\N{LATIN CAPITAL LETTER THORN}': u'TH',
106 u'\N{LATIN SMALL LETTER SHARP S}': u'ss',
107 u'\N{LATIN SMALL LETTER AE}': u'ae',
108 u'\N{LATIN SMALL LETTER ETH}': u'd',
109 u'\N{LATIN SMALL LETTER O WITH STROKE}': u'o',
110 u'\N{LATIN SMALL LETTER THORN}': 'th',
111 u'\N{LATIN CAPITAL LETTER D WITH STROKE}': u'D',
112 u'\N{LATIN SMALL LETTER D WITH STROKE}': u'd',
113 u'\N{LATIN CAPITAL LETTER H WITH STROKE}': u'H',
114 u'\N{LATIN SMALL LETTER H WITH STROKE}': u'h',
115 u'\N{LATIN SMALL LETTER DOTLESS I}': u'i',
116 u'\N{LATIN SMALL LETTER KRA}': u'q',
117 u'\N{LATIN CAPITAL LETTER L WITH STROKE}': u'L',
118 u'\N{LATIN SMALL LETTER L WITH STROKE}': u'l',
119 u'\N{LATIN CAPITAL LETTER ENG}': u'N',
120 u'\N{LATIN SMALL LETTER ENG}': u'n',
121 u'\N{LATIN CAPITAL LIGATURE OE}': u'OE',
122 u'\N{LATIN SMALL LIGATURE OE}': u'oe',
123 u'\N{LATIN CAPITAL LETTER T WITH STROKE}': u'T',
124 u'\N{LATIN SMALL LETTER T WITH STROKE}': u't',
125 u'\N{LATIN SMALL LETTER B WITH STROKE}': u'b',
126 u'\N{LATIN CAPITAL LETTER B WITH HOOK}': u'B',
127 u'\N{LATIN CAPITAL LETTER B WITH TOPBAR}': u'B',
128 u'\N{LATIN SMALL LETTER B WITH TOPBAR}': u'b',
129 # u'\N{LATIN CAPITAL LETTER TONE SIX}': u'', # ?B
130 # u'\N{LATIN SMALL LETTER TONE SIX}': u'', # ?b
131 u'\N{LATIN CAPITAL LETTER OPEN O}': u'O',
132 u'\N{LATIN CAPITAL LETTER C WITH HOOK}': u'C',
133 u'\N{LATIN SMALL LETTER C WITH HOOK}': u'c',
134 u'\N{LATIN CAPITAL LETTER AFRICAN D}': u'D',
135 u'\N{LATIN CAPITAL LETTER D WITH HOOK}': u'D',
136 u'\N{LATIN CAPITAL LETTER D WITH TOPBAR}': u'D',
137 u'\N{LATIN SMALL LETTER D WITH TOPBAR}': u'd',
138 # u'\N{LATIN SMALL LETTER TURNED DELTA}': u'',
139 u'\N{LATIN CAPITAL LETTER REVERSED E}': u'E',
140 # u'\N{LATIN CAPITAL LETTER SCHWA}': u'',
141 u'\N{LATIN CAPITAL LETTER OPEN E}': u'E',
142 u'\N{LATIN CAPITAL LETTER F WITH HOOK}': u'F',
143 u'\N{LATIN SMALL LETTER F WITH HOOK}': u'f',
144 u'\N{LATIN CAPITAL LETTER G WITH HOOK}': u'G',
145 # u'\N{LATIN CAPITAL LETTER GAMMA}': u'',
146 u'\N{LATIN SMALL LETTER HV}': u'hv',
147 u'\N{LATIN CAPITAL LETTER IOTA}': u'i',
148 u'\N{LATIN CAPITAL LETTER I WITH STROKE}': u'I',
149 u'\N{LATIN CAPITAL LETTER K WITH HOOK}': u'K',
150 u'\N{LATIN SMALL LETTER K WITH HOOK}': u'k',
151 u'\N{LATIN SMALL LETTER L WITH BAR}': u'l',
152 # u'\N{LATIN SMALL LETTER LAMBDA WITH STROKE}': u'',
153 # u'\N{LATIN CAPITAL LETTER TURNED M}': u'',
154 u'\N{LATIN CAPITAL LETTER N WITH LEFT HOOK}': u'N',
155 u'\N{LATIN SMALL LETTER N WITH LONG RIGHT LEG}': u'N',
156 u'\N{LATIN CAPITAL LETTER O WITH MIDDLE TILDE}': u'O',
157 u'\N{LATIN CAPITAL LETTER OI}': u'OI',
158 u'\N{LATIN SMALL LETTER OI}': u'oi',
159 u'\N{LATIN CAPITAL LETTER P WITH HOOK}': u'P',
160 u'\N{LATIN SMALL LETTER P WITH HOOK}': u'p',
161 # u'\N{LATIN LETTER YR}': u'',
162 # u'\N{LATIN CAPITAL LETTER TONE TWO}': u'',
163 # u'\N{LATIN SMALL LETTER TONE TWO}': u'',
164 u'\N{LATIN CAPITAL LETTER ESH}': u'SH',
165 # u'\N{LATIN LETTER REVERSED ESH LOOP}': u'',
166 u'\N{LATIN SMALL LETTER T WITH PALATAL HOOK}': u't',
167 u'\N{LATIN CAPITAL LETTER T WITH HOOK}': u'T',
168 u'\N{LATIN SMALL LETTER T WITH HOOK}': u't',
169 u'\N{LATIN CAPITAL LETTER T WITH RETROFLEX HOOK}': u'T',
170 # u'\N{LATIN CAPITAL LETTER UPSILON}': u'',
171 u'\N{LATIN CAPITAL LETTER V WITH HOOK}': u'V',
172 u'\N{LATIN CAPITAL LETTER Y WITH HOOK}': u'Y',
173 u'\N{LATIN SMALL LETTER Y WITH HOOK}': u'y',
174 u'\N{LATIN CAPITAL LETTER Z WITH STROKE}': u'Z',
175 u'\N{LATIN SMALL LETTER Z WITH STROKE}': u'z',
176 u'\N{LATIN CAPITAL LETTER EZH}': u'S',
177 # u'\N{LATIN CAPITAL LETTER EZH REVERSED}': u'',
178 # u'\N{LATIN SMALL LETTER EZH REVERSED}': u'',
179 u'\N{LATIN SMALL LETTER EZH WITH TAIL}': u's',
180 # u'\N{LATIN LETTER TWO WITH STROKE}': u'',
181 # u'\N{LATIN CAPITAL LETTER TONE FIVE}': u'',
182 # u'\N{LATIN SMALL LETTER TONE FIVE}': u'',
183 # u'\N{LATIN LETTER INVERTED GLOTTAL STOP WITH STROKE}': u'',
184 u'\N{LATIN LETTER WYNN}': u'w',
185 # u'\N{LATIN LETTER DENTAL CLICK}': u'',
186 # u'\N{LATIN LETTER LATERAL CLICK}': u'',
187 # u'\N{LATIN LETTER ALVEOLAR CLICK}': u'',
188 # u'\N{LATIN LETTER RETROFLEX CLICK}': u'',
189 # u'\N{LATIN SMALL LETTER TURNED E}': u'',
190 u'\N{LATIN CAPITAL LETTER AE WITH MACRON}': u'AE',
191 u'\N{LATIN SMALL LETTER AE WITH MACRON}': u'ae',
192 u'\N{LATIN CAPITAL LETTER G WITH STROKE}': u'G',
193 u'\N{LATIN SMALL LETTER G WITH STROKE}': u'g',
194 u'\N{LATIN CAPITAL LETTER EZH WITH CARON}': u'S',
195 u'\N{LATIN SMALL LETTER EZH WITH CARON}': u's',
196 u'\N{LATIN CAPITAL LETTER HWAIR}': u'HW',
197 u'\N{LATIN CAPITAL LETTER WYNN}': u'W',
198 u'\N{LATIN CAPITAL LETTER AE WITH ACUTE}': u'AE',
199 u'\N{LATIN SMALL LETTER AE WITH ACUTE}': u'AE',
200 u'\N{LATIN CAPITAL LETTER O WITH STROKE AND ACUTE}': u'O',
201 u'\N{LATIN SMALL LETTER O WITH STROKE AND ACUTE}': u'o',
202 u'\N{LATIN CAPITAL LETTER YOGH}': u'J',
203 u'\N{LATIN SMALL LETTER YOGH}': u'j',
204 u'\N{LATIN CAPITAL LETTER N WITH LONG RIGHT LEG}': u'N',
205 u'\N{LATIN SMALL LETTER D WITH CURL}': u'd',
206 u'\N{LATIN CAPITAL LETTER OU}': u'OU',
207 u'\N{LATIN SMALL LETTER OU}': u'ou',
208 u'\N{LATIN CAPITAL LETTER Z WITH HOOK}': u'Z',
209 u'\N{LATIN SMALL LETTER Z WITH HOOK}': u'z',
210 u'\N{LATIN SMALL LETTER L WITH CURL}': u'l',
211 u'\N{LATIN SMALL LETTER N WITH CURL}': u'n',
212 u'\N{LATIN SMALL LETTER T WITH CURL}': u't',
213 u'\N{LATIN SMALL LETTER DOTLESS J}': u'j',
214 u'\N{LATIN SMALL LETTER DB DIGRAPH}': u'db',
215 u'\N{LATIN SMALL LETTER QP DIGRAPH}': u'qp',
216 u'\N{LATIN CAPITAL LETTER A WITH STROKE}': u'A',
217 u'\N{LATIN CAPITAL LETTER C WITH STROKE}': u'C',
218 u'\N{LATIN SMALL LETTER C WITH STROKE}': u'C',
219 u'\N{LATIN CAPITAL LETTER L WITH BAR}': u'L',
220 u'\N{LATIN CAPITAL LETTER T WITH DIAGONAL STROKE}': u'T',
221 u'\N{LATIN SMALL LETTER S WITH SWASH TAIL}': u'S',
222 u'\N{LATIN SMALL LETTER Z WITH SWASH TAIL}': u'Z',
223 # u'\N{LATIN CAPITAL LETTER GLOTTAL STOP}': u'',
224 # u'\N{LATIN SMALL LETTER TURNED A}': u'',
225 # u'\N{LATIN SMALL LETTER ALPHA}': u'',
226 # u'\N{LATIN SMALL LETTER TURNED ALPHA}': u'',
227 u'\N{LATIN SMALL LETTER B WITH HOOK}': u'b',
228 u'\N{LATIN SMALL LETTER OPEN O}': u'o',
229 u'\N{LATIN SMALL LETTER C WITH CURL}': u'c',
230 u'\N{LATIN SMALL LETTER D WITH TAIL}': u'd',
231 u'\N{LATIN SMALL LETTER D WITH HOOK}': u'd',
232 # u'\N{LATIN SMALL LETTER REVERSED E}': u'',
233 # u'\N{LATIN SMALL LETTER SCHWA}': u'',
234 # u'\N{LATIN SMALL LETTER SCHWA WITH HOOK}': u'',
235 u'\N{LATIN SMALL LETTER OPEN E}': u'e',
236 # u'\N{LATIN SMALL LETTER REVERSED OPEN E}': u'',
237 # u'\N{LATIN SMALL LETTER REVERSED OPEN E WITH HOOK}': u'',
238 # u'\N{LATIN SMALL LETTER CLOSED REVERSED OPEN E}': u'',
239 u'\N{LATIN SMALL LETTER DOTLESS J WITH STROKE}': u'j',
240 u'\N{LATIN SMALL LETTER G WITH HOOK}': u'g',
241 u'\N{LATIN SMALL LETTER SCRIPT G}': u'g',
242 u'\N{LATIN LETTER SMALL CAPITAL G}': u'G',
243 # u'\N{LATIN SMALL LETTER GAMMA}': u'',
244 # u'\N{LATIN SMALL LETTER RAMS HORN}': u'',
245 # u'\N{LATIN SMALL LETTER TURNED H}': u'',
246 u'\N{LATIN SMALL LETTER H WITH HOOK}': u'h',
247 u'\N{LATIN SMALL LETTER HENG WITH HOOK}': u'h',
248 u'\N{LATIN SMALL LETTER I WITH STROKE}': u'i',
249 # u'\N{LATIN SMALL LETTER IOTA}': u'',
250 u'\N{LATIN LETTER SMALL CAPITAL I}': u'I',
251 u'\N{LATIN SMALL LETTER L WITH MIDDLE TILDE}': u'L',
252 u'\N{LATIN SMALL LETTER L WITH BELT}': u'L',
253 u'\N{LATIN SMALL LETTER L WITH RETROFLEX HOOK}': u'L',
254 # u'\N{LATIN SMALL LETTER LEZH}': u'',
255 # u'\N{LATIN SMALL LETTER TURNED M}': u'',
256 # u'\N{LATIN SMALL LETTER TURNED M WITH LONG LEG}': u'',
257 u'\N{LATIN SMALL LETTER M WITH HOOK}': u'm',
258 u'\N{LATIN SMALL LETTER N WITH LEFT HOOK}': u'n',
259 u'\N{LATIN SMALL LETTER N WITH RETROFLEX HOOK}': u'n',
260 u'\N{LATIN LETTER SMALL CAPITAL N}': u'N',
261 u'\N{LATIN SMALL LETTER BARRED O}': u'o',
262 u'\N{LATIN LETTER SMALL CAPITAL OE}': u'OE',
263 # u'\N{LATIN SMALL LETTER CLOSED OMEGA}': u'',
264 # u'\N{LATIN SMALL LETTER PHI}': u'',
265 # u'\N{LATIN SMALL LETTER TURNED R}': u'',
266 # u'\N{LATIN SMALL LETTER TURNED R WITH LONG LEG}': u'',
267 # u'\N{LATIN SMALL LETTER TURNED R WITH HOOK}': u'',
268 u'\N{LATIN SMALL LETTER R WITH LONG LEG}': u'r',
269 u'\N{LATIN SMALL LETTER R WITH TAIL}': u'r',
270 u'\N{LATIN SMALL LETTER R WITH FISHHOOK}': u'r',
271 # u'\N{LATIN SMALL LETTER REVERSED R WITH FISHHOOK}': u'',
272 u'\N{LATIN LETTER SMALL CAPITAL R}': u'R',
273 # u'\N{LATIN LETTER SMALL CAPITAL INVERTED R}': u'',
274 u'\N{LATIN SMALL LETTER S WITH HOOK}': u's',
275 u'\N{LATIN SMALL LETTER ESH}': u'sh',
276 u'\N{LATIN SMALL LETTER DOTLESS J WITH STROKE AND HOOK}': u'j',
277 # u'\N{LATIN SMALL LETTER SQUAT REVERSED ESH}': u'',
278 u'\N{LATIN SMALL LETTER ESH WITH CURL}': u'sh',
279 # u'\N{LATIN SMALL LETTER TURNED T}': u'',
280 u'\N{LATIN SMALL LETTER T WITH RETROFLEX HOOK}': u't',
281 u'\N{LATIN SMALL LETTER U BAR}': u'u',
282 # u'\N{LATIN SMALL LETTER UPSILON}': u'',
283 u'\N{LATIN SMALL LETTER V WITH HOOK}': u'v',
284 # u'\N{LATIN SMALL LETTER TURNED V}': u'',
285 # u'\N{LATIN SMALL LETTER TURNED W}': u'',
286 # u'\N{LATIN SMALL LETTER TURNED Y}': u'',
287 u'\N{LATIN LETTER SMALL CAPITAL Y}': u'Y',
288 u'\N{LATIN SMALL LETTER Z WITH RETROFLEX HOOK}': u'z',
289 u'\N{LATIN SMALL LETTER Z WITH CURL}': u'z',
290 u'\N{LATIN SMALL LETTER EZH}': u's',
291 u'\N{LATIN SMALL LETTER EZH WITH CURL}': u's',
292 # u'\N{LATIN LETTER GLOTTAL STOP}': u'',
293 # u'\N{LATIN LETTER PHARYNGEAL VOICED FRICATIVE}': u'',
294 # u'\N{LATIN LETTER INVERTED GLOTTAL STOP}': u'',
295 u'\N{LATIN LETTER STRETCHED C}': u'c',
296 # u'\N{LATIN LETTER BILABIAL CLICK}': u'',
297 u'\N{LATIN LETTER SMALL CAPITAL B}': u'B',
298 u'\N{LATIN SMALL LETTER CLOSED OPEN E}': u'e',
299 u'\N{LATIN LETTER SMALL CAPITAL G WITH HOOK}': u'G',
300 u'\N{LATIN LETTER SMALL CAPITAL H}': u'H',
301 u'\N{LATIN SMALL LETTER J WITH CROSSED-TAIL}': u'j',
302 # u'\N{LATIN SMALL LETTER TURNED K}': u'',
303 u'\N{LATIN LETTER SMALL CAPITAL L}': u'L',
304 u'\N{LATIN SMALL LETTER Q WITH HOOK}': u'q',
305 # u'\N{LATIN LETTER GLOTTAL STOP WITH STROKE}': u'',
306 # u'\N{LATIN LETTER REVERSED GLOTTAL STOP WITH STROKE}': u'',
307 # u'\N{LATIN SMALL LETTER DZ DIGRAPH}': u'',
308 # u'\N{LATIN SMALL LETTER DEZH DIGRAPH}': u'',
309 # u'\N{LATIN SMALL LETTER DZ DIGRAPH WITH CURL}': u'',
310 # u'\N{LATIN SMALL LETTER TS DIGRAPH}': u'',
311 # u'\N{LATIN SMALL LETTER TESH DIGRAPH}': u'',
312 # u'\N{LATIN SMALL LETTER TC DIGRAPH WITH CURL}': u'',
313 # u'\N{LATIN SMALL LETTER FENG DIGRAPH}': u'',
314 # u'\N{LATIN SMALL LETTER LS DIGRAPH}': u'',
315 # u'\N{LATIN SMALL LETTER LZ DIGRAPH}': u'',
316 # u'\N{LATIN LETTER BILABIAL PERCUSSIVE}': u'',
317 # u'\N{LATIN LETTER BIDENTAL PERCUSSIVE}': u'',
318 # u'\N{LATIN SMALL LETTER TURNED H WITH FISHHOOK}': u'',
319 # u'\N{LATIN SMALL LETTER TURNED H WITH FISHHOOK AND TAIL}': u'',
320 u'\N{LATIN LETTER SMALL CAPITAL A}': u'A',
321 u'\N{LATIN LETTER SMALL CAPITAL AE}': u'AE',
322 # u'\N{LATIN SMALL LETTER TURNED AE}': u'',
323 u'\N{LATIN LETTER SMALL CAPITAL BARRED B}': u'B',
324 u'\N{LATIN LETTER SMALL CAPITAL C}': u'C',
325 u'\N{LATIN LETTER SMALL CAPITAL D}': u'D',
326 u'\N{LATIN LETTER SMALL CAPITAL ETH}': u'D',
327 u'\N{LATIN LETTER SMALL CAPITAL E}': u'E',
328 # u'\N{LATIN SMALL LETTER TURNED OPEN E}': u'',
329 # u'\N{LATIN SMALL LETTER TURNED I}': u'',
330 u'\N{LATIN LETTER SMALL CAPITAL J}': u'J',
331 u'\N{LATIN LETTER SMALL CAPITAL K}': u'K',
332 u'\N{LATIN LETTER SMALL CAPITAL L WITH STROKE}': u'L',
333 u'\N{LATIN LETTER SMALL CAPITAL M}': u'M',
334 # u'\N{LATIN LETTER SMALL CAPITAL REVERSED N}': u'',
335 u'\N{LATIN LETTER SMALL CAPITAL O}': u'O',
336 u'\N{LATIN LETTER SMALL CAPITAL OPEN O}': u'O',
337 # u'\N{LATIN SMALL LETTER SIDEWAYS O}': u'',
338 # u'\N{LATIN SMALL LETTER SIDEWAYS OPEN O}': u'',
339 # u'\N{LATIN SMALL LETTER SIDEWAYS O WITH STROKE}': u'',
340 # u'\N{LATIN SMALL LETTER TURNED OE}': u'',
341 u'\N{LATIN LETTER SMALL CAPITAL OU}': u'OU',
342 # u'\N{LATIN SMALL LETTER TOP HALF O}': u'',
343 # u'\N{LATIN SMALL LETTER BOTTOM HALF O}': u'',
344 u'\N{LATIN LETTER SMALL CAPITAL P}': u'P',
345 # u'\N{LATIN LETTER SMALL CAPITAL REVERSED R}': u'',
346 # u'\N{LATIN LETTER SMALL CAPITAL TURNED R}': u'',
347 u'\N{LATIN LETTER SMALL CAPITAL T}': u'T',
348 u'\N{LATIN LETTER SMALL CAPITAL U}': u'U',
349 # u'\N{LATIN SMALL LETTER SIDEWAYS U}': u'',
350 # u'\N{LATIN SMALL LETTER SIDEWAYS DIAERESIZED U}': u'',
351 # u'\N{LATIN SMALL LETTER SIDEWAYS TURNED M}': u'',
352 u'\N{LATIN LETTER SMALL CAPITAL V}': u'V',
353 u'\N{LATIN LETTER SMALL CAPITAL W}': u'W',
354 u'\N{LATIN LETTER SMALL CAPITAL Z}': u'',
355 u'\N{LATIN LETTER SMALL CAPITAL EZH}': u'S',
356 # u'\N{LATIN LETTER VOICED LARYNGEAL SPIRANT}': u'',
357 # u'\N{LATIN LETTER AIN}': u'',
358 u'\N{LATIN SMALL LETTER UE}': u'ue',
359 u'\N{LATIN SMALL LETTER B WITH MIDDLE TILDE}': u'b',
360 u'\N{LATIN SMALL LETTER D WITH MIDDLE TILDE}': u'd',
361 u'\N{LATIN SMALL LETTER F WITH MIDDLE TILDE}': u'f',
362 u'\N{LATIN SMALL LETTER M WITH MIDDLE TILDE}': u'm',
363 u'\N{LATIN SMALL LETTER N WITH MIDDLE TILDE}': u'n',
364 u'\N{LATIN SMALL LETTER P WITH MIDDLE TILDE}': u'p',
365 u'\N{LATIN SMALL LETTER R WITH MIDDLE TILDE}': u'r',
366 u'\N{LATIN SMALL LETTER R WITH FISHHOOK AND MIDDLE TILDE}': u'r',
367 u'\N{LATIN SMALL LETTER S WITH MIDDLE TILDE}': u's',
368 u'\N{LATIN SMALL LETTER T WITH MIDDLE TILDE}': u't',
369 u'\N{LATIN SMALL LETTER Z WITH MIDDLE TILDE}': u'z',
370 # u'\N{LATIN SMALL LETTER TURNED G}': u'',
371 # u'\N{LATIN SMALL LETTER INSULAR G}': u'',
372 u'\N{LATIN SMALL LETTER TH WITH STRIKETHROUGH}': u'th',
373 u'\N{LATIN SMALL CAPITAL LETTER I WITH STROKE}': u'I',
374 # u'\N{LATIN SMALL LETTER IOTA WITH STROKE}': u'',
375 u'\N{LATIN SMALL LETTER P WITH STROKE}': u'p',
376 u'\N{LATIN SMALL CAPITAL LETTER U WITH STROKE}': u'U',
377 # u'\N{LATIN SMALL LETTER UPSILON WITH STROKE}': u'',
378 u'\N{LATIN SMALL LETTER B WITH PALATAL HOOK}': u'b',
379 u'\N{LATIN SMALL LETTER D WITH PALATAL HOOK}': u'd',
380 u'\N{LATIN SMALL LETTER F WITH PALATAL HOOK}': u'f',
381 u'\N{LATIN SMALL LETTER G WITH PALATAL HOOK}': u'g',
382 u'\N{LATIN SMALL LETTER K WITH PALATAL HOOK}': u'k',
383 u'\N{LATIN SMALL LETTER L WITH PALATAL HOOK}': u'l',
384 u'\N{LATIN SMALL LETTER M WITH PALATAL HOOK}': u'm',
385 u'\N{LATIN SMALL LETTER N WITH PALATAL HOOK}': u'n',
386 u'\N{LATIN SMALL LETTER P WITH PALATAL HOOK}': u'p',
387 u'\N{LATIN SMALL LETTER R WITH PALATAL HOOK}': u'r',
388 u'\N{LATIN SMALL LETTER S WITH PALATAL HOOK}': u's',
389 u'\N{LATIN SMALL LETTER ESH WITH PALATAL HOOK}': u'sh',
390 u'\N{LATIN SMALL LETTER V WITH PALATAL HOOK}': u'v',
391 u'\N{LATIN SMALL LETTER X WITH PALATAL HOOK}': u'x',
392 u'\N{LATIN SMALL LETTER Z WITH PALATAL HOOK}': u'z',
393 u'\N{LATIN SMALL LETTER A WITH RETROFLEX HOOK}': u'a',
394 # u'\N{LATIN SMALL LETTER ALPHA WITH RETROFLEX HOOK}': u'',
395 u'\N{LATIN SMALL LETTER D WITH HOOK AND TAIL}': u'd',
396 u'\N{LATIN SMALL LETTER E WITH RETROFLEX HOOK}': u'e',
397 u'\N{LATIN SMALL LETTER OPEN E WITH RETROFLEX HOOK}': u'e',
398 u'\N{LATIN SMALL LETTER REVERSED OPEN E WITH RETROFLEX HOOK}': u'e',
399 # u'\N{LATIN SMALL LETTER SCHWA WITH RETROFLEX HOOK}': u'',
400 u'\N{LATIN SMALL LETTER I WITH RETROFLEX HOOK}': u'i',
401 u'\N{LATIN SMALL LETTER OPEN O WITH RETROFLEX HOOK}': u'o',
402 u'\N{LATIN SMALL LETTER ESH WITH RETROFLEX HOOK}': u'sh',
403 u'\N{LATIN SMALL LETTER U WITH RETROFLEX HOOK}': u'u',
404 u'\N{LATIN SMALL LETTER EZH WITH RETROFLEX HOOK}': u's',
405 # u'\N{LATIN SUBSCRIPT SMALL LETTER SCHWA}': u'',
406 # u'\N{LATIN CROSS}': u''
407 }
408
409# Additional ones; see "man uni2ascii"
410UNI2ASCII_CONVERSIONS={
411 u'\N{NO-BREAK SPACE}': u' ',
412 u'\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}': u'"',
413 u'\N{SOFT HYPHEN}': u'', # Controversial: see http://www.cs.tut.fi/~jkorpela/shy.html
414 u'\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}': u'"',
415 u'\N{ETHIOPIC WORDSPACE}': u' ',
416 u'\N{OGHAM SPACE MARK}': u' ',
417 u'\N{EN QUAD}': u' ',
418 u'\N{EM QUAD}': u' ',
419 u'\N{EN SPACE}': u' ',
420 u'\N{EM SPACE}': u' ',
421 u'\N{THREE-PER-EM SPACE}': u' ',
422 u'\N{FOUR-PER-EM SPACE}': u' ',
423 u'\N{SIX-PER-EM SPACE}': u' ',
424 u'\N{FIGURE SPACE}': u' ',
425 u'\N{PUNCTUATION SPACE}': u' ',
426 u'\N{THIN SPACE}': u' ',
427 u'\N{HAIR SPACE}': u' ',
428 u'\N{ZERO WIDTH SPACE}': u' ',
429 u'\N{ZERO WIDTH NO-BREAK SPACE}': u' ',
430 u'\N{HYPHEN}': u'-',
431 u'\N{NON-BREAKING HYPHEN}': u'-',
432 u'\N{FIGURE DASH}': u'-',
433 u'\N{EN DASH}': u'-',
434 u'\N{EM DASH}': u'-',
435 u'\N{LEFT SINGLE QUOTATION MARK}': u'`',
436 u'\N{RIGHT SINGLE QUOTATION MARK}': u"'",
437 u'\N{SINGLE LOW-9 QUOTATION MARK}': u'`',
438 u'\N{SINGLE HIGH-REVERSED-9 QUOTATION MARK}': u'`',
439 u'\N{LEFT DOUBLE QUOTATION MARK}': u'"',
440 u'\N{RIGHT DOUBLE QUOTATION MARK}': u'"',
441 u'\N{DOUBLE LOW-9 QUOTATION MARK}': u'"',
442 u'\N{DOUBLE HIGH-REVERSED-9 QUOTATION MARK}': u'"',
443 u'\N{SINGLE LEFT-POINTING ANGLE QUOTATION MARK}': u'`',
444 u'\N{SINGLE RIGHT-POINTING ANGLE QUOTATION MARK}': u"'",
445 u'\N{LOW ASTERISK}': u'*',
446 u'\N{MINUS SIGN}': u'-',
447 u'\N{ASTERISK OPERATOR}': u'*',
448 u'\N{BOX DRAWINGS LIGHT HORIZONTAL}': u'-',
449 u'\N{BOX DRAWINGS HEAVY HORIZONTAL}': u'-',
450 u'\N{BOX DRAWINGS LIGHT VERTICAL}': u'|',
451 u'\N{BOX DRAWINGS HEAVY VERTICAL}': u'|',
452 u'\N{HEAVY ASTERISK}': u'*',
453 u'\N{HEAVY DOUBLE TURNED COMMA QUOTATION MARK ORNAMENT}': u'"',
454 u'\N{HEAVY DOUBLE COMMA QUOTATION MARK ORNAMENT}': u'"',
455 u'\N{IDEOGRAPHIC SPACE}': u' ',
456 u'\N{SMALL AMPERSAND}': u'&',
457 u'\N{SMALL ASTERISK}': u'*',
458 u'\N{SMALL PLUS SIGN}': u'+',
459 u'\N{CENT SIGN}': u'cent',
460 u'\N{POUND SIGN}': u'pound',
461 u'\N{YEN SIGN}': u'yen',
462 u'\N{COPYRIGHT SIGN}': u'(c)',
463 u'\N{REGISTERED SIGN}': u'(R)',
464 u'\N{VULGAR FRACTION ONE QUARTER}': u'1/4',
465 u'\N{VULGAR FRACTION ONE HALF}': u'1/2',
466 u'\N{VULGAR FRACTION THREE QUARTERS}': u'3/4',
467 # u'\N{CAPITAL LETTER ASH}': u'AE',
468 u'\N{LATIN SMALL LETTER SHARP S}': u'ss',
469 # u'\N{SMALL LETTER ASH}': u'ae',
470 u'\N{LATIN CAPITAL LIGATURE IJ}': u'IJ',
471 u'\N{LATIN SMALL LIGATURE IJ}': u'ij',
472 u'\N{LATIN CAPITAL LIGATURE OE}': u'OE',
473 u'\N{LATIN SMALL LIGATURE oe}': u'oe',
474 u'\N{LATIN CAPITAL LETTER DZ}': u'DZ',
475 u'\N{LATIN CAPITAL LETTER DZ WITH CARON}': u'DZ',
476 u'\N{LATIN CAPITAL LETTER D WITH SMALL LETTER Z}': u'Dz',
477 u'\N{LATIN CAPITAL LETTER D WITH SMALL LETTER Z WITH CARON}': u'Dz',
478 u'\N{LATIN SMALL LETTER DZ}': u'dz',
479 u'\N{LATIN SMALL LETTER TS DIGRAPH}': u'ts',
480 u'\N{HORIZONTAL ELLIPSIS}': u'...',
481 u'\N{MIDLINE HORIZONTAL ELLIPSIS}': u'...',
482 u'\N{LEFTWARDS ARROW}': u'<-',
483 u'\N{RIGHTWARDS ARROW}': u'->',
484 u'\N{LEFTWARDS DOUBLE ARROW}': u'<=',
485 u'\N{RIGHTWARDS DOUBLE ARROW}': u'=>',
486 }
487
488# More from "man uni2ascii", in a different category.
489EXTRA_CHARACTERS={
490 u'\N{ACUTE ACCENT}': u"'",
491 u'\N{BROKEN BAR}': u'|',
492 # u'\N{CEDILLA}': u'{cedilla}',
493 u'\N{CENT SIGN}': u' cents ',
494 u'\N{COPYRIGHT SIGN}': u'(C)',
495 u'\N{CURRENCY SIGN}': u' currency ',
496 u'\N{DEGREE SIGN}': u' degrees ',
497 # u'\N{DIAERESIS}': u'{umlaut}',
498 u'\N{DIVISION SIGN}': u'/',
499 # u'\N{FEMININE ORDINAL INDICATOR}': u'{^a}',
500 u'\N{INVERTED EXCLAMATION MARK}': u'!',
501 u'\N{INVERTED QUESTION MARK}': u'?',
502 # wrong? u'\N{LEFT-POINTING DOUBLE ANGLE QUOTATION MARK}': u'<<',
503 u'\N{MACRON}': u'_',
504 # u'\N{MASCULINE ORDINAL INDICATOR}': u'{^o}',
505 u'\N{MICRO SIGN}': u'micro',
506 u'\N{MIDDLE DOT}': u'*',
507 u'\N{MULTIPLICATION SIGN}': u'*',
508 u'\N{NOT SIGN}': u'not',
509 u'\N{PILCROW SIGN}': u'paragraph',
510 u'\N{PLUS-MINUS SIGN}': u'+/-',
511 u'\N{POUND SIGN}': u'pound',
512 u'\N{REGISTERED SIGN}': u'(R)',
513 # wrong? u'\N{RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK}': u'>>',
514 u'\N{SECTION SIGN}': u'section',
515 u'\N{SOFT HYPHEN}': u'',
516 u'\N{SUPERSCRIPT ONE}': u'^1',
517 u'\N{SUPERSCRIPT THREE}': u'^3',
518 u'\N{SUPERSCRIPT TWO}': u'^2',
519 u'\N{VULGAR FRACTION ONE HALF}': u'1/2',
520 u'\N{VULGAR FRACTION ONE QUARTER}': u'1/4',
521 u'\N{VULGAR FRACTION THREE QUARTERS}': u'3/4',
522 u'\N{YEN SIGN}': u'yen'
523}
524FG_HACKS={
525 u'\u0082': u'', # "break permitted here" symbol
526 u'\u2022': u'*', # Bullet
527}
528
529
530def build_dictionary():
531 'Return the translation dictionary.'
532 d = dict()
533 # First do what can be done automatically
534 for i in range(0xffff):
535 u=unichr(i)
536 try:
537 n=unicodedata.name(u)
538 if n.startswith('LATIN '):
539 k=unicodedata.normalize('NFKD', u).encode('ASCII', 'ignore')
540 if k: d[i]=unicode(k) # i=ord(u)
541 except ValueError: pass
542 # Next, add some by-hand ones (overlap possible, so order matters)
543 for m in [EXTRA_LATIN_NAMES,EXTRA_CHARACTERS,UNI2ASCII_CONVERSIONS,FG_HACKS]:
544 for i in m:
545 try: d[ord(i)]=unicode(m[i])
546 except Exception, err: pass
547 return d
548
549
550
551udict = build_dictionary()
552convert = lambda s: s.translate(udict)
553
554def coroutine(func):
555 def start(*argz, **kwz):
556 cr = func(*argz, **kwz)
557 cr.next()
558 return cr
559 return start
560
561@coroutine
562def co_filter(drain, in_enc='utf-8', out_enc='ascii'):
563 bs = None
564 while True:
565 chunk = (yield bs)
566 bs = drain(convert(unicode(chunk)).encode('utf-8'))
567
568def uc_filter(sin, sout, bs=8192, in_enc='utf-8', out_enc='ascii'):
569 sout = co_filter(sout.write, in_enc, out_enc)
570 while True:
571 dta = sin.read(bs)
572 if not dta: break
573 else: sout.send(dta)
574
575
576if __name__ == '__main__':
577 from optparse import OptionParser
578 parser = OptionParser(usage='%prog [options]',
579 description='utf8 stdin -> ascii stdout')
580 parser.add_option('-s', '--src-enc',
581 action='store', type='str', dest='src_enc', metavar='ENC', default='utf-8',
582 help='source encoding (utf-8)')
583 parser.add_option('-d', '--dst-enc',
584 action='store', type='str', dest='dst_enc', metavar='ENC', default='ascii',
585 help='destination encoding (ascii)')
586 parser.add_option('-c', '--chunk',
587 action='store', type='int', dest='bs', metavar='BYTES', default=8192,
588 help='read/write in chunks of a given size (8192)')
589 optz, argz = parser.parse_args()
590 if argz: parser.error('Only stdin -> stdout conversion suported')
591
592 uc_filter(sys.stdin, sys.stdout, bs=optz.bs, in_enc=optz.src_enc, out_enc=optz.dst_enc)