Merge lp:~openbmsjsc/openobject-server/amount-to-text-refactor into lp:openobject-server

Proposed by OpenBMS JSC
Status: Work in progress
Proposed branch: lp:~openbmsjsc/openobject-server/amount-to-text-refactor
Merge into: lp:openobject-server
Diff against target: 535 lines (+352/-133)
6 files modified
openerp/tools/__init__.py (+5/-2)
openerp/tools/amount_to_text.py (+1/-130)
openerp/tools/amount_to_text_en.py (+1/-1)
openerp/tools/amount_to_text_fr.py (+105/-0)
openerp/tools/amount_to_text_nl.py (+105/-0)
openerp/tools/amount_to_text_vi.py (+135/-0)
To merge this branch: bzr merge lp:~openbmsjsc/openobject-server/amount-to-text-refactor
Reviewer Review Type Date Requested Status
Vo Minh Thu (community) Needs Fixing
Review via email: mp+61291@code.launchpad.net

Description of the change

Credit to Ivan Gudym (https://code.launchpad.net/~igudym) for the re-factoring

This branch is proposed refactoring of amount_to_text* functions.
Current implementation of amount_to_text_en.py incorrect in structure. It shouldn't redefine so called "generic" functions and variables from amount_to_text.py, but should extend it in a proper way - by using add_amount_to_text_function function.
To avoid confusion i propose to leave in amount_to_text.py "generic" functions only, and all localization staff turn into amount_to_text_fr.py and a such.
Modules shouldn't direct use any "amount_to_text_XX" function, instead it should call generic amount_to_text.

In localization module, say, Ukraine, we implement some amount_to_text_ua function. Then in init section of module do:

from amount_to_text_ua import amount_to_text_ua
from tools.amount_to_text import add_amount_to_text_function

add_amount_to_text_function('uk', amount_to_text_ua)

Then we can use amount_to_text in localized report:

from tools.amount_to_text import amount_to_text

class account_invoice(report_sxw.rml_parse):
    def __init__(self, cr, uid, name, context):
        super(account_invoice, self).__init__(cr, uid, name, context=context)
        self.localcontext.update({
            'time': time,
            'convert': self.convert,
        })

    def convert(self,amount):
        return amount_to_text(amount, 'uk')

Main advantage of this is to ability to implement generalized modules, which will just sent lang from context into amount_to_text and get write result.

To post a comment you must log in.
3419. By OpenBMS JSC

Forgot to add amount_to_text_vi to module initialization

Revision history for this message
Vo Minh Thu (thu) wrote :

Thanks a lot! This is a really good thing to change.

Am I right you left the 'generic code' in amount_to_text_en? In that case, it should be removed as it would be unused.

I would also like that you don't add new the vietnamese code. It would be better in a localization module. The other languages should also be in their respective addons but since they were in the server, you can leave them there for now.

review: Needs Fixing
Revision history for this message
Antony Lesuisse (OpenERP) (al-openerp) wrote :

Could you add test ?

Unmerged revisions

3419. By OpenBMS JSC

Forgot to add amount_to_text_vi to module initialization

3418. By OpenBMS JSC

Refactor amount_to_text functions, credit for Ivan Gudym (https://launchpad.net/~igudym)
Add Vietnamese localization for amount_to_text

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openerp/tools/__init__.py'
2--- openerp/tools/__init__.py 2011-02-07 12:57:23 +0000
3+++ openerp/tools/__init__.py 2011-05-17 18:26:39 +0000
4@@ -26,8 +26,11 @@
5 from convert import *
6 from translate import *
7 from graph import graph
8-from amount_to_text import *
9-from amount_to_text_en import *
10+import amount_to_text
11+import amount_to_text_en
12+import amount_to_text_fr
13+import amount_to_text_nl
14+import amount_to_text_vi
15 from pdf_utils import *
16 from yaml_import import *
17 from sql import *
18
19=== modified file 'openerp/tools/amount_to_text.py'
20--- openerp/tools/amount_to_text.py 2010-02-16 06:31:14 +0000
21+++ openerp/tools/amount_to_text.py 2011-05-17 18:26:39 +0000
22@@ -20,139 +20,10 @@
23 ##############################################################################
24
25 #-------------------------------------------------------------
26-# French
27-#-------------------------------------------------------------
28-
29-
30-to_19_fr = ( 'zéro', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six',
31- 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize',
32- 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf' )
33-tens_fr = ( 'vingt', 'trente', 'quarante', 'Cinquante', 'Soixante', 'Soixante-dix', 'Quatre-vingts', 'Quatre-vingt Dix')
34-denom_fr = ( '',
35- 'Mille', 'Millions', 'Milliards', 'Billions', 'Quadrillions',
36- 'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
37- 'Décillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
38- 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion' )
39-
40-# convert a value < 100 to French.
41-def _convert_nn_fr(val):
42- if val < 20:
43- return to_19_fr[val]
44- for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_fr)):
45- if dval + 10 > val:
46- if val % 10:
47- return dcap + '-' + to_19_fr[val % 10]
48- return dcap
49-
50-# convert a value < 1000 to french, special cased because it is the level that kicks
51-# off the < 100 special case. The rest are more general. This also allows you to
52-# get strings in the form of 'forty-five hundred' if called directly.
53-def _convert_nnn_fr(val):
54- word = ''
55- (mod, rem) = (val % 100, val // 100)
56- if rem > 0:
57- word = to_19_fr[rem] + ' Cent'
58- if mod > 0:
59- word = word + ' '
60- if mod > 0:
61- word = word + _convert_nn_fr(mod)
62- return word
63-
64-def french_number(val):
65- if val < 100:
66- return _convert_nn_fr(val)
67- if val < 1000:
68- return _convert_nnn_fr(val)
69- for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_fr))):
70- if dval > val:
71- mod = 1000 ** didx
72- l = val // mod
73- r = val - (l * mod)
74- ret = _convert_nnn_fr(l) + ' ' + denom_fr[didx]
75- if r > 0:
76- ret = ret + ', ' + french_number(r)
77- return ret
78-
79-def amount_to_text_fr(number, currency):
80- number = '%.2f' % number
81- units_name = currency
82- list = str(number).split('.')
83- start_word = french_number(abs(int(list[0])))
84- end_word = french_number(int(list[1]))
85- cents_number = int(list[1])
86- cents_name = (cents_number > 1) and ' Cents' or ' Cent'
87- final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
88- return final_result
89-
90-#-------------------------------------------------------------
91-# Dutch
92-#-------------------------------------------------------------
93-
94-to_19_nl = ( 'Nul', 'Een', 'Twee', 'Drie', 'Vier', 'Vijf', 'Zes',
95- 'Zeven', 'Acht', 'Negen', 'Tien', 'Elf', 'Twaalf', 'Dertien',
96- 'Veertien', 'Vijftien', 'Zestien', 'Zeventien', 'Achttien', 'Negentien' )
97-tens_nl = ( 'Twintig', 'Dertig', 'Veertig', 'Vijftig', 'Zestig', 'Zeventig', 'Tachtig', 'Negentig')
98-denom_nl = ( '',
99- 'Duizend', 'Miljoen', 'Miljard', 'Triljoen', 'Quadriljoen',
100- 'Quintillion', 'Sextiljoen', 'Septillion', 'Octillion', 'Nonillion',
101- 'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
102- 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' )
103-
104-# convert a value < 100 to Dutch.
105-def _convert_nn_nl(val):
106- if val < 20:
107- return to_19_nl[val]
108- for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_nl)):
109- if dval + 10 > val:
110- if val % 10:
111- return dcap + '-' + to_19_nl[val % 10]
112- return dcap
113-
114-# convert a value < 1000 to Dutch, special cased because it is the level that kicks
115-# off the < 100 special case. The rest are more general. This also allows you to
116-# get strings in the form of 'forty-five hundred' if called directly.
117-def _convert_nnn_nl(val):
118- word = ''
119- (mod, rem) = (val % 100, val // 100)
120- if rem > 0:
121- word = to_19_nl[rem] + ' Honderd'
122- if mod > 0:
123- word = word + ' '
124- if mod > 0:
125- word = word + _convert_nn_nl(mod)
126- return word
127-
128-def dutch_number(val):
129- if val < 100:
130- return _convert_nn_nl(val)
131- if val < 1000:
132- return _convert_nnn_nl(val)
133- for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_nl))):
134- if dval > val:
135- mod = 1000 ** didx
136- l = val // mod
137- r = val - (l * mod)
138- ret = _convert_nnn_nl(l) + ' ' + denom_nl[didx]
139- if r > 0:
140- ret = ret + ', ' + dutch_number(r)
141- return ret
142-
143-def amount_to_text_nl(number, currency):
144- number = '%.2f' % number
145- units_name = currency
146- list = str(number).split('.')
147- start_word = dutch_number(int(list[0]))
148- end_word = dutch_number(int(list[1]))
149- cents_number = int(list[1])
150- cents_name = (cents_number > 1) and 'cent' or 'cent'
151- final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
152- return final_result
153-
154-#-------------------------------------------------------------
155 # Generic functions
156 #-------------------------------------------------------------
157
158-_translate_funcs = {'fr' : amount_to_text_fr, 'nl' : amount_to_text_nl}
159+_translate_funcs = {}
160
161 def add_amount_to_text_function(lang, func):
162 _translate_funcs[lang] = func
163
164=== modified file 'openerp/tools/amount_to_text_en.py'
165--- openerp/tools/amount_to_text_en.py 2011-02-07 12:57:23 +0000
166+++ openerp/tools/amount_to_text_en.py 2011-05-17 18:26:39 +0000
167@@ -73,7 +73,7 @@
168 ret = ret + ', ' + english_number(r)
169 return ret
170
171-def amount_to_text(number, currency):
172+def amount_to_text_en(number, currency):
173 number = '%.2f' % number
174 units_name = currency
175 list = str(number).split('.')
176
177=== added file 'openerp/tools/amount_to_text_fr.py'
178--- openerp/tools/amount_to_text_fr.py 1970-01-01 00:00:00 +0000
179+++ openerp/tools/amount_to_text_fr.py 2011-05-17 18:26:39 +0000
180@@ -0,0 +1,105 @@
181+# -*- encoding: utf-8 -*-
182+##############################################################################
183+#
184+# OpenERP, Open Source Management Solution
185+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
186+# $Id$
187+#
188+# This program is free software: you can redistribute it and/or modify
189+# it under the terms of the GNU General Public License as published by
190+# the Free Software Foundation, either version 3 of the License, or
191+# (at your option) any later version.
192+#
193+# This program is distributed in the hope that it will be useful,
194+# but WITHOUT ANY WARRANTY; without even the implied warranty of
195+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
196+# GNU General Public License for more details.
197+#
198+# You should have received a copy of the GNU General Public License
199+# along with this program. If not, see <http://www.gnu.org/licenses/>.
200+#
201+##############################################################################
202+
203+#-------------------------------------------------------------
204+# French
205+#-------------------------------------------------------------
206+import amount_to_text
207+
208+
209+to_19_fr = ( 'zéro', 'un', 'deux', 'trois', 'quatre', 'cinq', 'six',
210+ 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze', 'treize',
211+ 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit', 'dix-neuf' )
212+tens_fr = ( 'vingt', 'trente', 'quarante', 'Cinquante', 'Soixante', 'Soixante-dix', 'Quatre-vingts', 'Quatre-vingt Dix')
213+denom_fr = ( '',
214+ 'Mille', 'Millions', 'Milliards', 'Billions', 'Quadrillions',
215+ 'Quintillion', 'Sextillion', 'Septillion', 'Octillion', 'Nonillion',
216+ 'Décillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
217+ 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion' )
218+
219+# convert a value < 100 to French.
220+def _convert_nn_fr(val):
221+ if val < 20:
222+ return to_19_fr[val]
223+ for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_fr)):
224+ if dval + 10 > val:
225+ if val % 10:
226+ return dcap + '-' + to_19_fr[val % 10]
227+ return dcap
228+
229+# convert a value < 1000 to french, special cased because it is the level that kicks
230+# off the < 100 special case. The rest are more general. This also allows you to
231+# get strings in the form of 'forty-five hundred' if called directly.
232+def _convert_nnn_fr(val):
233+ word = ''
234+ (mod, rem) = (val % 100, val // 100)
235+ if rem > 0:
236+ word = to_19_fr[rem] + ' Cent'
237+ if mod > 0:
238+ word = word + ' '
239+ if mod > 0:
240+ word = word + _convert_nn_fr(mod)
241+ return word
242+
243+def french_number(val):
244+ if val < 100:
245+ return _convert_nn_fr(val)
246+ if val < 1000:
247+ return _convert_nnn_fr(val)
248+ for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_fr))):
249+ if dval > val:
250+ mod = 1000 ** didx
251+ l = val // mod
252+ r = val - (l * mod)
253+ ret = _convert_nnn_fr(l) + ' ' + denom_fr[didx]
254+ if r > 0:
255+ ret = ret + ', ' + french_number(r)
256+ return ret
257+
258+def amount_to_text_fr(number, currency):
259+ number = '%.2f' % number
260+ units_name = currency
261+ list = str(number).split('.')
262+ start_word = french_number(abs(int(list[0])))
263+ end_word = french_number(int(list[1]))
264+ cents_number = int(list[1])
265+ cents_name = (cents_number > 1) and ' Cents' or ' Cent'
266+ final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
267+ return final_result
268+
269+amount_to_text.add_amount_to_text_function('fr', amount_to_text_fr)
270+
271+if __name__=='__main__':
272+ from sys import argv
273+
274+ lang = 'fr'
275+ if len(argv) < 2:
276+ for i in range(1,200):
277+ print i, ">>", amount_to_text(i, lang)
278+ for i in range(200,999999,139):
279+ print i, ">>", amount_to_text(i, lang)
280+ else:
281+ print amount_to_text(int(argv[1]), lang)
282+
283+
284+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
285+
286
287=== added file 'openerp/tools/amount_to_text_nl.py'
288--- openerp/tools/amount_to_text_nl.py 1970-01-01 00:00:00 +0000
289+++ openerp/tools/amount_to_text_nl.py 2011-05-17 18:26:39 +0000
290@@ -0,0 +1,105 @@
291+# -*- encoding: utf-8 -*-
292+##############################################################################
293+#
294+# OpenERP, Open Source Management Solution
295+# Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
296+# $Id$
297+#
298+# This program is free software: you can redistribute it and/or modify
299+# it under the terms of the GNU General Public License as published by
300+# the Free Software Foundation, either version 3 of the License, or
301+# (at your option) any later version.
302+#
303+# This program is distributed in the hope that it will be useful,
304+# but WITHOUT ANY WARRANTY; without even the implied warranty of
305+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
306+# GNU General Public License for more details.
307+#
308+# You should have received a copy of the GNU General Public License
309+# along with this program. If not, see <http://www.gnu.org/licenses/>.
310+#
311+##############################################################################
312+
313+#-------------------------------------------------------------
314+# Dutch
315+#-------------------------------------------------------------
316+import amount_to_text
317+
318+to_19_nl = ( 'Nul', 'Een', 'Twee', 'Drie', 'Vier', 'Vijf', 'Zes',
319+ 'Zeven', 'Acht', 'Negen', 'Tien', 'Elf', 'Twaalf', 'Dertien',
320+ 'Veertien', 'Vijftien', 'Zestien', 'Zeventien', 'Achttien', 'Negentien' )
321+tens_nl = ( 'Twintig', 'Dertig', 'Veertig', 'Vijftig', 'Zestig', 'Zeventig', 'Tachtig', 'Negentig')
322+denom_nl = ( '',
323+ 'Duizend', 'Miljoen', 'Miljard', 'Triljoen', 'Quadriljoen',
324+ 'Quintillion', 'Sextiljoen', 'Septillion', 'Octillion', 'Nonillion',
325+ 'Decillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
326+ 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Novemdecillion', 'Vigintillion' )
327+
328+# convert a value < 100 to Dutch.
329+def _convert_nn_nl(val):
330+ if val < 20:
331+ return to_19_nl[val]
332+ for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_nl)):
333+ if dval + 10 > val:
334+ if val % 10:
335+ return dcap + '-' + to_19_nl[val % 10]
336+ return dcap
337+
338+# convert a value < 1000 to Dutch, special cased because it is the level that kicks
339+# off the < 100 special case. The rest are more general. This also allows you to
340+# get strings in the form of 'forty-five hundred' if called directly.
341+def _convert_nnn_nl(val):
342+ word = ''
343+ (mod, rem) = (val % 100, val // 100)
344+ if rem > 0:
345+ word = to_19_nl[rem] + ' Honderd'
346+ if mod > 0:
347+ word = word + ' '
348+ if mod > 0:
349+ word = word + _convert_nn_nl(mod)
350+ return word
351+
352+def dutch_number(val):
353+ if val < 100:
354+ return _convert_nn_nl(val)
355+ if val < 1000:
356+ return _convert_nnn_nl(val)
357+ for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_nl))):
358+ if dval > val:
359+ mod = 1000 ** didx
360+ l = val // mod
361+ r = val - (l * mod)
362+ ret = _convert_nnn_nl(l) + ' ' + denom_nl[didx]
363+ if r > 0:
364+ ret = ret + ', ' + dutch_number(r)
365+ return ret
366+
367+def amount_to_text_nl(number, currency):
368+ number = '%.2f' % number
369+ units_name = currency
370+ list = str(number).split('.')
371+ start_word = dutch_number(int(list[0]))
372+ end_word = dutch_number(int(list[1]))
373+ cents_number = int(list[1])
374+ cents_name = (cents_number > 1) and 'cent' or 'cent'
375+ final_result = start_word +' '+units_name+' '+ end_word +' '+cents_name
376+ return final_result
377+
378+amount_to_text.add_amount_to_text_function('nl', amount_to_text_nl)
379+
380+
381+if __name__=='__main__':
382+ from sys import argv
383+
384+ lang = 'nl'
385+ if len(argv) < 2:
386+ for i in range(1,200):
387+ print i, ">>", amount_to_text(i, lang)
388+ for i in range(200,999999,139):
389+ print i, ">>", amount_to_text(i, lang)
390+ else:
391+ print amount_to_text(int(argv[1]), lang)
392+
393+
394+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
395+
396
397=== added file 'openerp/tools/amount_to_text_vi.py'
398--- openerp/tools/amount_to_text_vi.py 1970-01-01 00:00:00 +0000
399+++ openerp/tools/amount_to_text_vi.py 2011-05-17 18:26:39 +0000
400@@ -0,0 +1,135 @@
401+# -*- encoding: utf-8 -*-
402+##############################################################################
403+#
404+# OpenERP, Open Source Management Solution
405+# Copyright (C) 2010-TODAY OpenERP SA (<http://openerp.com>).
406+# Copyright (c) 2010-TODAY Phong Nguyen-Thanh (phong.nguyen_thanh@yahoo.com)
407+#
408+# This program is free software: you can redistribute it and/or modify
409+# it under the terms of the GNU Affero General Public License as
410+# published by the Free Software Foundation, either version 3 of the
411+# License, or (at your option) any later version.
412+#
413+# This program is distributed in the hope that it will be useful,
414+# but WITHOUT ANY WARRANTY; without even the implied warranty of
415+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
416+# GNU Affero General Public License for more details.
417+#
418+# You should have received a copy of the GNU Affero General Public License
419+# along with this program. If not, see <http://www.gnu.org/licenses/>, or
420+# write to the Free Software Foundation, Inc.,
421+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
422+#
423+# WARNING: This program as such is intended to be used by professional
424+# programmers who take the whole responsability of assessing all potential
425+# consequences resulting from its eventual inadequacies and bugs
426+# End users who are looking for a ready-to-use solution with commercial
427+# garantees and support are strongly adviced to contract a Free Software
428+# Service Company
429+#
430+##############################################################################
431+
432+#-------------------------------------------------------------
433+# Vietnamese
434+#-------------------------------------------------------------
435+import amount_to_text
436+
437+
438+to_19_vi = ('không', 'một', 'hai', 'ba', 'bốn', 'năm', 'sáu',
439+ 'bảy', 'tám', 'chín', 'mười', 'mười một', 'mười hai', 'mười ba',
440+ 'mười bốn', 'mười lăm', 'mười sáu', 'mười bảy', 'mười tám', 'mười chín')
441+tens_vi = ('hai mươi', 'ba mươi', 'bốn mươi', 'năm mươi', 'sáu mươi', 'bảy mươi', 'tám mươi', 'chín mươi')
442+denom_vi = ('',
443+ 'ngàn', 'triệu', 'tỉ', 'ngàn tỉ', 'triệu tỉ',
444+ 'tỉ tỉ', 'ngàn tỉ tỉ', 'triệu tỉ tỉ', 'tỉ tỉ tỉ', 'Nonillion',
445+ 'Décillion', 'Undecillion', 'Duodecillion', 'Tredecillion', 'Quattuordecillion',
446+ 'Sexdecillion', 'Septendecillion', 'Octodecillion', 'Icosillion', 'Vigintillion')
447+
448+# convert a value < 100 to Vietnamese.
449+def _convert_nn_vi(val):
450+ if val < 20:
451+ return to_19_vi[val]
452+ for (dcap, dval) in ((k, 20 + (10 * v)) for (v, k) in enumerate(tens_vi)):
453+ if dval + 10 > val:
454+ if (val % 10) == 1:
455+ return dcap + ' mốt'
456+ elif (val % 10) == 5:
457+ return dcap + ' lăm'
458+ elif val % 10:
459+ return dcap + ' ' + to_19_vi[val % 10]
460+ return dcap
461+
462+# convert a value < 1000 to Vietnamese, special cased because it is the level that kicks
463+# off the < 100 special case. The rest are more general. This also allows you to
464+# get strings in the form of 'forty-five hundred' if called directly.
465+def _convert_nnn_vi(val):
466+ word = ''
467+ (mod, rem) = (val % 100, val // 100)
468+ if rem > 0:
469+ word = to_19_vi[rem] + ' trăm'
470+ if mod > 0:
471+ word = word + ' '
472+ if mod > 0:
473+ if mod < 10:
474+ word = word + 'lẻ '
475+ word = word + _convert_nn_vi(mod)
476+ return word
477+
478+def vi_number(val):
479+ if val < 100:
480+ return _convert_nn_vi(val)
481+ if val < 1000:
482+ return _convert_nnn_vi(val)
483+ for (didx, dval) in ((v - 1, 1000 ** v) for v in range(len(denom_vi))):
484+ if dval > val:
485+ mod = 1000 ** didx
486+ l = val // mod
487+ r = val - (l * mod)
488+ if l < 10:
489+ ret = _convert_nn_vi(l) + ' ' + denom_vi[didx]
490+ else:
491+ ret = _convert_nnn_vi(l) + ' ' + denom_vi[didx]
492+ if r > 0:
493+ ret = ret + ', ' + vi_number(r)
494+ return ret
495+
496+def amount_to_text_vi(number, currency):
497+ if currency == 'VND':
498+ currency = 'đồng'
499+ number = '%.2f' % number
500+ units_name = currency
501+ list = str(number).split('.')
502+ start_word = vi_number(abs(int(list[0])))
503+ cents_number = int(list[1])
504+ end_word = ''
505+ if cents_number > 0:
506+ end_word = ' ' + vi_number(int(list[1]))
507+
508+ cents_name = (cents_number > 1) and ' xu' or ' chẵn'
509+ final_result = start_word + ' ' + units_name + end_word + cents_name
510+ return final_result
511+
512+amount_to_text.add_amount_to_text_function('vi', amount_to_text_vi)
513+
514+
515+import random
516+if __name__ == '__main__':
517+ from sys import argv
518+
519+ lang = 'đồng'
520+ if len(argv) < 2:
521+ for i in range(1, 200):
522+ print i, ">>", amount_to_text_vi(i, lang)
523+ j = random.random()
524+ print i + j, ">>", amount_to_text_vi(i + j, lang)
525+# amount_to_text.amount_to_text(i+j, 'vi', currency='đồng')
526+# amount_to_text.amount_to_text(i+j, 'vi', currency='euro')
527+# amount_to_text.amount_to_text(i+j, 'vi', currency='đô-la')
528+ for i in range(200, 999999, 139):
529+ print i, ">>", amount_to_text_vi(i, lang)
530+ else:
531+ print amount_to_text_vi(int(argv[1]), lang)
532+
533+
534+# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
535+