2
0
account-financial-tools/account_cash_deposit/models/cash_unit.py
2022-12-12 21:12:46 +01:00

153 lines
5.6 KiB
Python

# Copyright 2022 Akretion France (http://www.akretion.com/)
# @author: Alexis de Lattre <alexis.delattre@akretion.com>
# License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl).
import logging
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError
from odoo.tools.misc import format_amount
logger = logging.getLogger(__name__)
class CashUnit(models.Model):
_name = "cash.unit"
_description = "Cash Unit"
_order = "currency_id, tree_order desc"
_rec_name = "value"
currency_id = fields.Many2one("res.currency", ondelete="cascade")
active = fields.Boolean(default=True)
tree_order = fields.Float(compute="_compute_all", store=True)
cash_type = fields.Selection(
[
("note", "Note"),
("coin", "Coin"),
("coinroll", "Coin Roll"),
],
string="Type",
required=True,
help="This field should never be modified.",
)
coinroll_qty = fields.Integer(
string="Coin Quantity", help="This field should never be modified."
)
value = fields.Monetary(
required=True,
help="This field should never be modified. For a coin roll, "
"you must enter the value of the coin.",
)
total_value = fields.Monetary(compute="_compute_all", store=True)
auto_create = fields.Selection(
[
("deposit", "Deposit"),
("order", "Order"),
("both", "Both"),
],
help="If set, a line for this cash unit will be created by default "
"on a new cash deposit or a new cash order or both.",
)
_sql_constraints = [
(
"coinroll_qty_positive",
"CHECK(coinroll_qty >= 0)",
"The coin quantity must be positive.",
),
("value_positive", "CHECK(value > 0)", "The value must be strictly positive."),
]
@api.constrains("cash_type", "coinroll_qty")
def _check_cash_unit(self):
for rec in self:
if rec.cash_type == "coinroll" and rec.coinroll_qty <= 0:
raise ValidationError(
_("For a coin roll, the coin quantity must be strictly positive.")
)
@api.depends("coinroll_qty", "cash_type", "value")
def _compute_all(self):
# I want bank notes first, then coinrolls, then coins
# This is a hack, but it is designed to work fine with
# all currencies of the planet !
type2multiplier = {
"note": 1000000,
"coinroll": 1000,
"coin": 1,
}
for rec in self:
qty = rec.cash_type == "coinroll" and rec.coinroll_qty or 1
total_value = rec.value * qty
rec.tree_order = type2multiplier.get(rec.cash_type, 0) * total_value
rec.total_value = total_value
def _get_value_label(self, value):
self.ensure_one()
symbol_position = self.currency_id.position
symbol = self.currency_id.symbol
int_value = int(round(value))
# if value is an integer
if self.currency_id.compare_amounts(value, int_value) == 0:
amount_label = str(int_value)
if symbol_position == "before":
value_label = "%s %s" % (symbol, amount_label)
else:
value_label = "%s %s" % (amount_label, symbol)
else:
value_label = format_amount(self.env, value, self.currency_id)
return value_label
def name_get(self):
res = []
type2label = dict(
self.fields_get("cash_type", "selection")["cash_type"]["selection"]
)
for rec in self:
cash_type_label = type2label.get(rec.cash_type)
value_label = rec._get_value_label(rec.value)
if rec.cash_type == "coinroll":
total_value_label = rec._get_value_label(rec.total_value)
label = "%s %s x %d (%s)" % (
cash_type_label,
value_label,
rec.coinroll_qty,
total_value_label,
)
else:
label = "%s %s" % (cash_type_label, value_label)
res.append((rec.id, label))
return res
@api.model
def name_search(self, name="", args=None, operator="ilike", limit=100):
if args is None:
args = []
if name and operator == "ilike":
if name.isdigit():
recs = self.search([("value", "=", name)] + args, limit=limit)
if recs:
return recs.name_get()
value = False
try:
value = float(name)
except ValueError:
logger.debug("name %s is not a float. Make pylint happy.", name)
if value:
recs = self.search([("value", "=", value)] + args, limit=limit)
if recs:
return recs.name_get()
lang = self.env["res.lang"]._lang_get(self.env.user.lang)
if lang:
decimal_sep = lang.decimal_point
if decimal_sep and decimal_sep != ".":
try:
value = float(name.replace(decimal_sep, ".", 1))
except ValueError:
logger.debug("name %s is not a float. Make pylint happy.", name)
if value:
recs = self.search([("value", "=", value)] + args, limit=limit)
if recs:
return recs.name_get()
return super().name_search(name=name, args=args, operator=operator, limit=limit)