Tower: upload laundry_management 19.0.19.0.4 (via marketplace)

This commit is contained in:
2026-05-01 15:01:20 +00:00
parent cead209507
commit eb27193b6e

View File

@@ -0,0 +1,101 @@
from odoo import models, fields, api
from odoo.exceptions import UserError
class LaundryPaymentMethod(models.Model):
"""Configurable payment method linked to an accounting journal.
One record per payment option (e.g. Cash, Visa, Bank Transfer, Credit).
Each method is typed as cash / bank / credit so that session cash-control
and accounting routing work exactly like Odoo POS payment methods.
cash → counted in the session cash drawer
bank → posted to a bank/card journal, not counted in cash
credit → deferred / no-posting (customer owes)
"""
_name = 'laundry.payment.method'
_description = 'Laundry Payment Method'
_order = 'sequence, id'
# ── Identity ──────────────────────────────────────────────────────
name = fields.Char(
string='Method Name',
required=True,
translate=True,
)
sequence = fields.Integer(default=10)
active = fields.Boolean(default=True)
company_id = fields.Many2one(
'res.company',
default=lambda self: self.env.company,
)
# ── Type ──────────────────────────────────────────────────────────
payment_type = fields.Selection([
('cash', 'Cash / نقد'),
('bank', 'Bank / Card / بنك'),
('credit', 'Credit / Deferred / آجل'),
], string='Type', required=True, default='cash',
help=(
'cash → counts in session cash drawer\n'
'bank → posted to bank/card journal\n'
'credit → deferred, no immediate accounting entry'
),
)
# ── Journal ───────────────────────────────────────────────────────
journal_id = fields.Many2one(
'account.journal', string='Accounting Journal',
domain="[('type', 'in', ['cash', 'bank']), ('company_id', '=', company_id)]",
help='Leave blank only for Credit/Deferred methods.',
)
# ── UI ────────────────────────────────────────────────────────────
is_default = fields.Boolean(
string='Default',
help='Pre-selected when staff opens the Register Payment wizard.',
)
# ── Constraints ───────────────────────────────────────────────────
@api.constrains('is_default', 'company_id')
def _check_single_default(self):
for rec in self.filtered('is_default'):
duplicate = self.search([
('is_default', '=', True),
('company_id', '=', rec.company_id.id),
('id', '!=', rec.id),
], limit=1)
if duplicate:
raise UserError(
f'Only one default payment method is allowed per company.\n'
f'"{duplicate.name}" is already the default.\n'
'Unset it first before marking this one as default.'
)
@api.constrains('payment_type', 'journal_id')
def _check_journal_required(self):
for rec in self:
if rec.payment_type in ('cash', 'bank') and not rec.journal_id:
raise UserError(
f'Payment method "{rec.name}" is of type "{rec.payment_type}" '
'and requires an accounting journal. '
'Please select a journal or change the type to Credit/Deferred.'
)
# ── Helpers ───────────────────────────────────────────────────────
@api.model
def get_default_method(self):
"""Return the default payment method for the current company."""
company = self.env.company
return (
self.search([
('is_default', '=', True),
('company_id', '=', company.id),
('active', '=', True),
], limit=1)
or self.search([
('payment_type', '=', 'cash'),
('company_id', '=', company.id),
('active', '=', True),
], limit=1)
)