27.02.26
This commit is contained in:
77
modules/purchase_trade/numbers_to_words.py
Normal file
77
modules/purchase_trade/numbers_to_words.py
Normal file
@@ -0,0 +1,77 @@
|
||||
from decimal import Decimal, ROUND_HALF_UP
|
||||
|
||||
|
||||
UNITS = (
|
||||
"ZERO ONE TWO THREE FOUR FIVE SIX SEVEN EIGHT NINE TEN ELEVEN TWELVE "
|
||||
"THIRTEEN FOURTEEN FIFTEEN SIXTEEN SEVENTEEN EIGHTEEN NINETEEN"
|
||||
).split()
|
||||
|
||||
TENS = "ZERO TEN TWENTY THIRTY FORTY FIFTY SIXTY SEVENTY EIGHTY NINETY".split()
|
||||
|
||||
|
||||
def _under_thousand(n, use_and=True):
|
||||
words = []
|
||||
|
||||
hundreds = n // 100
|
||||
remainder = n % 100
|
||||
|
||||
if hundreds:
|
||||
words.append(UNITS[hundreds])
|
||||
words.append("HUNDRED")
|
||||
if remainder and use_and:
|
||||
words.append("AND")
|
||||
|
||||
if remainder:
|
||||
if remainder < 20:
|
||||
words.append(UNITS[remainder])
|
||||
else:
|
||||
words.append(TENS[remainder // 10])
|
||||
if remainder % 10:
|
||||
words.append(UNITS[remainder % 10])
|
||||
|
||||
return " ".join(words)
|
||||
|
||||
|
||||
def number_to_words(n, decimals_mode="digit", use_and=True):
|
||||
"""
|
||||
decimals_mode:
|
||||
- "digit" → ONE HUNDRED POINT TWO FIVE
|
||||
- "fraction" → ONE HUNDRED AND 25/100
|
||||
"""
|
||||
|
||||
n = Decimal(str(n)).quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
|
||||
|
||||
integer_part = int(n)
|
||||
decimal_part = int((n - integer_part) * 100)
|
||||
|
||||
if integer_part == 0:
|
||||
words = "ZERO"
|
||||
else:
|
||||
parts = []
|
||||
|
||||
millions = integer_part // 1_000_000
|
||||
thousands = (integer_part // 1_000) % 1_000
|
||||
remainder = integer_part % 1_000
|
||||
|
||||
if millions:
|
||||
parts.append(_under_thousand(millions, use_and))
|
||||
parts.append("MILLION")
|
||||
|
||||
if thousands:
|
||||
parts.append(_under_thousand(thousands, use_and))
|
||||
parts.append("THOUSAND")
|
||||
|
||||
if remainder:
|
||||
parts.append(_under_thousand(remainder, use_and))
|
||||
|
||||
words = " ".join(parts)
|
||||
|
||||
# Gestion décimales
|
||||
if decimal_part:
|
||||
if decimals_mode == "digit":
|
||||
digits = " ".join(UNITS[int(d)] for d in f"{decimal_part:02d}")
|
||||
words = f"{words} POINT {digits}"
|
||||
elif decimals_mode == "fraction":
|
||||
words = f"{words} AND {decimal_part:02d}/100"
|
||||
|
||||
return words.upper()
|
||||
@@ -15,6 +15,7 @@ import datetime
|
||||
import logging
|
||||
import json
|
||||
from trytond.exceptions import UserWarning, UserError
|
||||
from trytond.modules.purchase_trade.numbers_to_words import number_to_words
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@@ -264,13 +265,31 @@ class Sale(metaclass=PoolMeta):
|
||||
else:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def report_qt(self):
|
||||
if self.lines:
|
||||
return number_to_words(self.lines[0].quantity)
|
||||
else:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def report_price(self):
|
||||
if self.lines:
|
||||
return number_to_words(self.lines[0].unit_price)
|
||||
else:
|
||||
return ''
|
||||
|
||||
@property
|
||||
def report_shipment(self):
|
||||
if self.lines:
|
||||
if len(self.lines[0].lots)>1:
|
||||
shipment = self.lines[0].lots[1].lot_shipment_in
|
||||
if shipment:
|
||||
info = 'B/L ' + shipment.bl_number + ' ' + shipment.note
|
||||
info = 'B/L ' + shipment.bl_number
|
||||
if shipment.container and shipment.container[0].container_no:
|
||||
info += ' ' + shipment.container[0].container_no
|
||||
if shipment.note:
|
||||
info += ' ' + shipment.note
|
||||
return info
|
||||
else:
|
||||
return ''
|
||||
|
||||
Reference in New Issue
Block a user