Merge pull request #5998 from expsa/14.0-i18n-odex_takaful-auto-20260106_022910
[FIX] odex_takaful: enhance data models and user interface
This commit is contained in:
commit
e129ab9fa7
|
|
@ -80,6 +80,7 @@
|
|||
'views/preferred_communication.xml',
|
||||
'views/takaful_payment_method.xml',
|
||||
'views/product_views.xml',
|
||||
'views/payment_machine_views.xml',
|
||||
'views/takaful_menus_actions.xml',
|
||||
'data/message_template_data.xml',
|
||||
'data/server_actions.xml',
|
||||
|
|
|
|||
|
|
@ -4642,7 +4642,7 @@ msgstr "فواتير المدفوعات"
|
|||
#: model_terms:ir.ui.view,arch_db:odex_takaful.view_account_payment_register_form
|
||||
#, python-format
|
||||
msgid "Payment Method"
|
||||
msgstr "طريقة الدفع"
|
||||
msgstr "طريقة السداد"
|
||||
|
||||
#. module: odex_takaful
|
||||
#: model:ir.model.fields,field_description:odex_takaful.field_donations_details_lines__payment_month_count
|
||||
|
|
|
|||
|
|
@ -28,3 +28,4 @@ from . import donation_extension_history
|
|||
from . import family_member
|
||||
from . import sponsorship_scheduling_line
|
||||
from . import donation_replacement_log
|
||||
from . import payment_machine
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from odoo import models, fields, api, _
|
||||
|
||||
|
||||
class PaymentMachine(models.Model):
|
||||
"""Payment Machine Model for POS Terminals like Gidea, Neoleap, etc."""
|
||||
_name = 'payment.machine'
|
||||
_description = 'Payment Machine'
|
||||
_order = 'name'
|
||||
_rec_name = 'name'
|
||||
|
||||
name = fields.Char(
|
||||
string='Machine Name',
|
||||
required=True,
|
||||
help='Name or identifier of the payment machine'
|
||||
)
|
||||
code = fields.Char(
|
||||
string='Machine Code',
|
||||
help='Serial number or code of the payment machine'
|
||||
)
|
||||
machine_type = fields.Selection([
|
||||
('neoleap', 'Neoleap'),
|
||||
('gidea', 'Gidea'),
|
||||
('other', 'Other'),
|
||||
], string='Machine Type', required=True, default='neoleap')
|
||||
machine_type_other = fields.Char(
|
||||
string='Other Machine Type',
|
||||
help='Specify the machine type if not listed above'
|
||||
)
|
||||
branch_custom_id = fields.Many2one(
|
||||
'branch.settings',
|
||||
string='Branch',
|
||||
required=True,
|
||||
help='Branch where this payment machine is located'
|
||||
)
|
||||
journal_id = fields.Many2one(
|
||||
'account.journal',
|
||||
string='Journal',
|
||||
required=True,
|
||||
domain="[('type', '=', 'bank')]",
|
||||
help='Bank journal associated with this payment machine'
|
||||
)
|
||||
active = fields.Boolean(
|
||||
string='Active',
|
||||
default=True,
|
||||
help='If unchecked, the machine will be archived and hidden'
|
||||
)
|
||||
notes = fields.Text(
|
||||
string='Notes',
|
||||
help='Additional notes or information about the machine'
|
||||
)
|
||||
|
||||
_sql_constraints = [
|
||||
('code_unique', 'UNIQUE(code)', 'Machine code must be unique!'),
|
||||
]
|
||||
|
||||
@api.depends('name', 'code')
|
||||
def name_get(self):
|
||||
"""Display name with code if available"""
|
||||
result = []
|
||||
for record in self:
|
||||
if record.code:
|
||||
name = f"{record.name} [{record.code}]"
|
||||
else:
|
||||
name = record.name
|
||||
result.append((record.id, name))
|
||||
return result
|
||||
|
|
@ -211,10 +211,15 @@ class ResPartner(models.Model):
|
|||
if not args:
|
||||
args = []
|
||||
|
||||
# If no name is provided, use standard Odoo search behavior
|
||||
# This fixes the issue where empty name causes invalid domain
|
||||
if not name:
|
||||
return super()._name_search(name, args=args, operator=operator, limit=limit, name_get_uid=name_get_uid)
|
||||
|
||||
# Build search domains for the raw name and (optionally) the name
|
||||
# without leading zero, to "ignore" a starting 0 in the search term.
|
||||
search_terms = [name] if name else []
|
||||
if name and name.startswith('0'):
|
||||
search_terms = [name]
|
||||
if name.startswith('0'):
|
||||
search_terms.append(name[1:])
|
||||
|
||||
domain = []
|
||||
|
|
@ -562,9 +567,10 @@ class ResPartner(models.Model):
|
|||
def name_get(self):
|
||||
result = []
|
||||
for sponsor in self:
|
||||
name = sponsor.name
|
||||
# Ensure name is always a string, never False or None
|
||||
name = sponsor.name or ''
|
||||
if sponsor.mobile:
|
||||
name = sponsor.name + " - " + str(sponsor.mobile)
|
||||
name = (sponsor.name or '') + " - " + str(sponsor.mobile)
|
||||
result.append((sponsor.id, name))
|
||||
return result
|
||||
|
||||
|
|
|
|||
|
|
@ -1892,6 +1892,7 @@ class TakafulSponsorship(models.Model):
|
|||
'sponsorship_payment_skip_compute_amount': True,
|
||||
'default_sponsorship_payment': True,
|
||||
'force_sponsorship_line_partner_id': self.sponsor_id.id,
|
||||
'default_takaful_sponsorship_id': self.id,
|
||||
},
|
||||
'target': 'new',
|
||||
'type': 'ir.actions.act_window',
|
||||
|
|
|
|||
|
|
@ -59,3 +59,5 @@ access_replace_benefit_wizard,replace.benefit.wizard.access,model_replace_benefi
|
|||
access_group_esterdad_wizard,access_group_esterdad_wizard,model_esterdad_wizard,,1,1,1,0
|
||||
|
||||
access_group_otp_confirmation_wizard,access_group_otp_confirmation_wizard,model_otp_confirmation_wizard,,1,1,1,0
|
||||
access_payment_machine,access_payment_machine,model_payment_machine,odex_takaful.group_kufula_user,1,1,1,1
|
||||
access_payment_machine_manager,access_payment_machine_manager,model_payment_machine,odex_takaful.sponsorship_system_manager_group,1,1,1,1
|
||||
|
|
|
|||
|
|
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<odoo>
|
||||
<!-- Payment Machine Tree View -->
|
||||
<record id="payment_machine_view_tree" model="ir.ui.view">
|
||||
<field name="name">payment.machine.view.tree</field>
|
||||
<field name="model">payment.machine</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Payment Machines">
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="machine_type"/>
|
||||
<field name="branch_custom_id"/>
|
||||
<field name="journal_id"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Payment Machine Form View -->
|
||||
<record id="payment_machine_view_form" model="ir.ui.view">
|
||||
<field name="name">payment.machine.view.form</field>
|
||||
<field name="model">payment.machine</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Payment Machine">
|
||||
<sheet>
|
||||
<div class="oe_button_box" name="button_box">
|
||||
</div>
|
||||
<div class="oe_title">
|
||||
<label for="name"/>
|
||||
<h1>
|
||||
<field name="name" placeholder="Machine Name"/>
|
||||
</h1>
|
||||
</div>
|
||||
<group>
|
||||
<group name="main_info" string="Machine Information">
|
||||
<field name="code"/>
|
||||
<field name="machine_type"/>
|
||||
<field name="machine_type_other"
|
||||
attrs="{'invisible': [('machine_type', '!=', 'other')],
|
||||
'required': [('machine_type', '=', 'other')]}"/>
|
||||
</group>
|
||||
<group name="branch_info" string="Branch & Journal">
|
||||
<field name="branch_custom_id" options="{'no_create': True}"/>
|
||||
<field name="journal_id" options="{'no_create': True}"/>
|
||||
<field name="active" widget="boolean_toggle"/>
|
||||
</group>
|
||||
</group>
|
||||
<group name="notes_group" string="Notes">
|
||||
<field name="notes" nolabel="1" placeholder="Additional notes..."/>
|
||||
</group>
|
||||
</sheet>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Payment Machine Search View -->
|
||||
<record id="payment_machine_view_search" model="ir.ui.view">
|
||||
<field name="name">payment.machine.view.search</field>
|
||||
<field name="model">payment.machine</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Search Payment Machines">
|
||||
<field name="name"/>
|
||||
<field name="code"/>
|
||||
<field name="branch_custom_id"/>
|
||||
<separator/>
|
||||
<filter string="Neoleap" name="filter_neoleap"
|
||||
domain="[('machine_type', '=', 'neoleap')]"/>
|
||||
<filter string="Gidea" name="filter_gidea"
|
||||
domain="[('machine_type', '=', 'gidea')]"/>
|
||||
<filter string="Other" name="filter_other"
|
||||
domain="[('machine_type', '=', 'other')]"/>
|
||||
<separator/>
|
||||
<filter string="Archived" name="filter_archived"
|
||||
domain="[('active', '=', False)]"/>
|
||||
<group expand="0" string="Group By">
|
||||
<filter string="Branch" name="group_branch"
|
||||
context="{'group_by': 'branch_custom_id'}"/>
|
||||
<filter string="Machine Type" name="group_type"
|
||||
context="{'group_by': 'machine_type'}"/>
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Payment Machine Action -->
|
||||
<record id="action_payment_machine" model="ir.actions.act_window">
|
||||
<field name="name">Payment Machines</field>
|
||||
<field name="res_model">payment.machine</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="search_view_id" ref="payment_machine_view_search"/>
|
||||
<field name="help" type="html">
|
||||
<p class="o_view_nocontent_smiling_face">
|
||||
Create your first payment machine
|
||||
</p>
|
||||
<p>
|
||||
Payment machines are used to track POS terminals like Gidea, Neoleap, etc.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Menu Item under Global Settings -->
|
||||
<menuitem id="menu_payment_machine"
|
||||
name="Payment Machines"
|
||||
parent="odex_takaful.sponsor_setting_menu"
|
||||
action="action_payment_machine"
|
||||
sequence="9"/>
|
||||
|
||||
</odoo>
|
||||
|
|
@ -8,6 +8,24 @@ _logger = logging.getLogger(__name__)
|
|||
class AccountRegisterPayment(models.TransientModel):
|
||||
_inherit = 'account.payment.register'
|
||||
|
||||
@api.model
|
||||
def default_get(self, fields_list):
|
||||
res = super(AccountRegisterPayment, self).default_get(fields_list)
|
||||
if 'machine_id' in res and res['machine_id']:
|
||||
machine = self.env['payment.machine'].browse(res['machine_id'])
|
||||
if machine.exists() and machine.journal_id:
|
||||
res['journal_id'] = machine.journal_id.id
|
||||
elif not res.get('machine_id'):
|
||||
# Fallback if default_get didn't catch the field default (though it usually does for computed defaults)
|
||||
# Let's explicitly check our custom default logic if not present
|
||||
machine_id = self._default_machine_id()
|
||||
if machine_id:
|
||||
res['machine_id'] = machine_id
|
||||
machine = self.env['payment.machine'].browse(machine_id)
|
||||
if machine.exists() and machine.journal_id:
|
||||
res['journal_id'] = machine.journal_id.id
|
||||
return res
|
||||
|
||||
@api.model
|
||||
def _default_payment_method_id(self):
|
||||
payment_method = self.env['takaful.payment.method'].sudo().search(
|
||||
|
|
@ -30,7 +48,29 @@ class AccountRegisterPayment(models.TransientModel):
|
|||
transaction_file_attachment = fields.Binary(string='Transaction Attachment', attachment=False)
|
||||
transaction_attachment_file_name = fields.Char('Transaction File Name', required=False)
|
||||
payment_method = fields.Selection(selection=[("cash", "Cash"), ("bank", "Bank Transfer"), ("check", "Check")], string="Payment Method", required=True, default="cash")
|
||||
machine_id = fields.Many2one('geidea.terminals', string=_('Machine'))
|
||||
@api.model
|
||||
def _default_machine_id(self):
|
||||
sponsorship_id = self.env.context.get('default_takaful_sponsorship_id') or self.env.context.get('active_id')
|
||||
if sponsorship_id:
|
||||
sponsorship = self.env['takaful.sponsorship'].browse(sponsorship_id)
|
||||
if sponsorship.exists() and sponsorship.branch_custom_id:
|
||||
return self.env['payment.machine'].search([
|
||||
('branch_custom_id', '=', sponsorship.branch_custom_id.id),
|
||||
('active', '=', True)
|
||||
], limit=1).id
|
||||
return False
|
||||
|
||||
machine_id = fields.Many2one(
|
||||
'payment.machine',
|
||||
string='Payment Machine',
|
||||
default=_default_machine_id
|
||||
)
|
||||
sponsorship_branch_id = fields.Many2one(
|
||||
'branch.settings',
|
||||
string='Sponsorship Branch',
|
||||
related='takaful_sponsorship_id.branch_custom_id',
|
||||
store=False,
|
||||
)
|
||||
check_number = fields.Char(string='Check Number')
|
||||
check_due_date = fields.Date(string='Check Due Date')
|
||||
sponsorship_payment = fields.Boolean(string='Sponsorship Payment', default=False)
|
||||
|
|
|
|||
|
|
@ -76,24 +76,35 @@
|
|||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='journal_id']" position="before">
|
||||
<field name="takaful_payment_method_id" string="Payment Method" attrs="{'invisible': [('sponsorship_payment', '=', False)]}" options="{'no_create': True, 'no_create_edit': True}"/>
|
||||
<field name="takaful_payment_method_id" string="Payment Method" attrs="{'invisible': [('sponsorship_payment', '=', False)]}" options="{'no_create': True, 'no_create_edit': True, 'no_open': True}"/>
|
||||
<field name="takaful_sponsorship_id" invisible="1"/>
|
||||
<field name="sponsorship_branch_id" invisible="1"/>
|
||||
<field name="machine_id"
|
||||
options="{'no_create': True, 'no_create_edit': True, 'no_open': True}"
|
||||
domain="[('branch_custom_id', '=', sponsorship_branch_id)]"
|
||||
attrs="{'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method', '!=', 'network')], 'required': [('sponsorship_payment', '=', True), ('takaful_payment_method', '=', 'network')]}"/>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='partner_bank_id']" position="after">
|
||||
<xpath expr="//field[@name='journal_id']" position="attributes">
|
||||
<attribute name="attrs">{'readonly':[('is_refund_sponsorship','=',True)], 'invisible': [('takaful_payment_method', '=', 'network')]}</attribute>
|
||||
<attribute name="string">Association Journal</attribute>
|
||||
</xpath>
|
||||
|
||||
<xpath expr="//field[@name='partner_bank_id']" position="after">
|
||||
<field name="sponsorship_payment" invisible="1"/>
|
||||
<field name="takaful_payment_method" invisible="1"/>
|
||||
<!-- <field name="payment_method" attrs="{'invisible': [('sponsorship_payment', '=', False)]}"/>-->
|
||||
<field name="payment_method" invisible="1"/>
|
||||
<field name="check_number" attrs="{'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method','!=','check')], 'required': [('sponsorship_payment', '=', True), ('takaful_payment_method','=','check')]}"/>
|
||||
<field name="check_due_date" attrs="{'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method','!=','check')], 'required': [('sponsorship_payment', '=', True), ('takaful_payment_method','=','check')]}"/>
|
||||
<field name="partner_bank_id" string="Donor Bank Account" options="{'skip_disable_quick_create': True}" context="{'form_view_ref': 'odex_takaful.res_partner_bank_view_form_quick_create', 'default_partner_id': context.get('force_sponsorship_line_partner_id')}" attrs="{'required': [('sponsorship_payment', '=', True), ('takaful_payment_method','not in',('bank','check'))], 'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method','not',('bank','check'))]}" create="1" edit="1"/>
|
||||
<field name="partner_bank_id" string="Donor Bank Account" options="{'skip_disable_quick_create': True}" context="{'form_view_ref': 'odex_takaful.res_partner_bank_view_form_quick_create', 'default_partner_id': context.get('force_sponsorship_line_partner_id')}" attrs="{'required': [('sponsorship_payment', '=', True), ('takaful_payment_method','in',['bank','check'])], 'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method','not in',['bank','check'])]}" create="1" edit="1"/>
|
||||
<field name="transaction_file_attachment" widget="binary"
|
||||
filename="transaction_attachment_file_name"
|
||||
attrs="{'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method','not in',['bank', 'check'])], 'required': [('sponsorship_payment', '=', True), ('takaful_payment_method','=','bank')]}"/>
|
||||
<field name="transaction_attachment_file_name" invisible="1"/>
|
||||
<field name="payment_date" attrs="{'readonly': [('sponsorship_payment', '=', True)]}"/>
|
||||
<field name="communication"/>
|
||||
</xpath>
|
||||
</xpath>
|
||||
<xpath expr="//footer/button[2]" position="replace">
|
||||
<!-- <field name="show_cancel_button" invisible="1"/>-->
|
||||
<button string="Cancel"
|
||||
|
|
|
|||
Loading…
Reference in New Issue