change on app icon journal and sequn

This commit is contained in:
Nossibaelhadi 2025-11-03 19:36:15 +03:00
commit cfc309f290
24 changed files with 456 additions and 406 deletions

View File

@ -2016,6 +2016,9 @@ msgstr "بيانات المستفيدين"
msgid "Beneficiaries Management"
msgstr "فئات المستفيدين"
#. module: odex_benefit
#: model:res.groups,name:odex_benefit.group_benefit_manager
msgid "Beneficiaries Manager"

View File

@ -777,7 +777,7 @@ class FamilyMemberProfile(models.Model):
rec.member_id_number
)
existing_member = rec.search([
('id', '!=', rec.id),
('id', '!=', rec._origin.id),
('member_id_number', '=', rec.member_id_number),
('relationn.relation_type', 'not in', ['mother', 'replacement_mother'])
], limit=1)
@ -785,7 +785,7 @@ class FamilyMemberProfile(models.Model):
raise ValidationError(_("This ID already exists."))
if rec.relationn.relation_type not in ['mother', 'replacement_mother']:
conflict_family = rec.env['grant.benefit'].search([
('id', '!=', family.id),
('id', '!=', family._origin.id),
'|', '|',
('father_id_number', '=', rec.member_id_number),
('mother_id_number', '=', rec.member_id_number),

View File

@ -33,6 +33,10 @@ class SeasonalService(models.Model):
], string='state', default='draft', tracking=True, copy=False)
is_payment_order_done = fields.Boolean(string='Is Payment Order Done?', copy=False)
account_id = fields.Many2one('account.account', string='Expenses Account', related="service_type_id.account_id")
service_requests_ids = fields.One2many('service.request', 'seasonal_service_id', string='Service Requests')
benefit_ids = fields.Many2many(comodel_name='grant.benefit', relation='benefit_grant_seasonal_service_rel',
column1='seasonal_service_id',
column2='benefit_id', string='Families',copy=False)
@api.depends('service_type_id','service_type_id.benefit_category_ids')
@ -128,12 +132,16 @@ class SeasonalService(models.Model):
def action_approval_of_beneficiary_services(self):
for rec in self:
if not rec.family_ids:
raise UserError(_("You Must Enter Families First"))
if not rec.service_requests_ids:
raise UserError(_("You must add at least one service request."))
rec.service_requests_ids.write({'state': 'accounting_approve'})
rec.state = 'approval_of_beneficiary_services'
def action_accounting_approve(self):
for rec in self:
rec.service_requests_ids.write({'state': 'send_request_to_supplier'})
rec.state = 'accounting_approve'

View File

@ -190,6 +190,8 @@ class ServiceRequest(models.Model):
string="Driving License")
owner_identity = fields.Many2many('ir.attachment', 'request_owner_identity_rel', 'request_id', 'attachment_id',
string="Owner Identity")
seasonal_service_id = fields.Many2one('seasonal.service', string='Seasonal Service', ondelete='cascade')
is_seasonal = fields.Boolean(string='Is Seasonal Service?',related='service_cat.is_seasonal_service')
@api.depends('requested_service_amount', 'service_max_amount')
def _get_money_for_payment_is_appearance(self):

View File

@ -1,18 +1,27 @@
<odoo>
<data noupdate="1">
<data noupdate="0">
<record model="ir.module.category" id="module_category_benefit">
<field name="name">Beneficiaries Management</field>
<field name="description">Helps you manage Beneficiaries Program</field>
<field name="sequence">1</field>
</record>
<!-- <record id="group_benefit_user" model="res.groups">-->
<!-- <field name="name">Beneficiaries User</field>-->
<!-- <field name="category_id" ref="module_category_benefit"/>-->
<!-- <field name="users" eval="[(4, ref('base.user_root'))]"/>-->
<!--&lt;!&ndash; <field name="implied_ids" eval="[(4, ref('base.group_erp_manager'))]"/>&ndash;&gt;-->
<!-- </record>-->
<record id="group_benefit_info" model="res.groups">
<record id="translation_benefit_ar" model="ir.translation">
<field name="name">ir.module.category,name</field>
<field name="lang">ar_001</field>
<field name="type">model</field>
<field name="res_id" eval="ref('module_category_benefit')"/>
<field name="src">Beneficiaries Management</field>
<field name="value">فئات المستفيدين</field>
</record>
<!-- <record id="group_benefit_user" model="res.groups">-->
<!-- <field name="name">Beneficiaries User</field>-->
<!-- <field name="category_id" ref="module_category_benefit"/>-->
<!-- <field name="users" eval="[(4, ref('base.user_root'))]"/>-->
<!--&lt;!&ndash; <field name="implied_ids" eval="[(4, ref('base.group_erp_manager'))]"/>&ndash;&gt;-->
<!-- </record>-->
<record id="group_benefit_info" model="res.groups">
<field name="name">Beneficiaries Inforamtion</field>
<field name="category_id" ref="module_category_benefit"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
@ -38,12 +47,12 @@
<field name="users" eval="[(4, ref('base.user_root'))]"/>
<field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>
</record>
<!-- <record id="group_benefit_officer" model="res.groups">-->
<!-- <field name="name">Beneficiaries Officer</field>-->
<!-- <field name="category_id" ref="module_category_benefit"/>-->
<!-- <field name="users" eval="[(4, ref('base.user_root'))]"/>-->
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_user')),(4, ref('group_benefit_edit'))]"/>-->
<!-- </record>-->
<!-- <record id="group_benefit_officer" model="res.groups">-->
<!-- <field name="name">Beneficiaries Officer</field>-->
<!-- <field name="category_id" ref="module_category_benefit"/>-->
<!-- <field name="users" eval="[(4, ref('base.user_root'))]"/>-->
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_user')),(4, ref('group_benefit_edit'))]"/>-->
<!-- </record>-->
<record id="group_benefit_manager" model="res.groups">
<field name="name">Beneficiaries Manager</field>
<field name="category_id" ref="module_category_benefit"/>
@ -89,25 +98,25 @@
<field name="category_id" ref="module_category_benefit"/>
<field name="implied_ids" eval="[(4, ref('group_benefit_branch_manager'))]"/>
</record>
<record id="group_benefit_accounting_accept" model="res.groups">
<record id="group_benefit_accounting_accept" model="res.groups">
<field name="name">Accounting Accept</field>
<field name="category_id" ref="module_category_benefit"/>
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
</record>
<record id="group_benefit_bank_info" model="res.groups">
<field name="name">Bank Account Information</field>
<field name="category_id" ref="module_category_benefit"/>
<field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>
<field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>
</record>
<record id="group_benefit_accountant_accept" model="res.groups">
<field name="name">Service Request Accountant Accept</field>
<field name="category_id" ref="odex25_account_payment_fix.module_category_payment_access"/>
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
</record>
<record id="group_benefit_payment_accountant_accept" model="res.groups">
<field name="name">Payment Orders Accountant Accept</field>
<field name="category_id" ref="odex25_account_payment_fix.module_category_payment_access"/>
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
</record>
<record id="group_accept_income_and_expenses" model="res.groups">
<field name="name">Accept income and expenses</field>
@ -130,7 +139,7 @@
<field name="name">Family Services Manager</field>
<field name="category_id" ref="module_category_benefit"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
<field name="implied_ids" eval="[(4, ref('group_benefit_manager'))]"/>
<field name="implied_ids" eval="[(4, ref('group_benefit_manager'))]"/>
</record>
<record id="group_service_legal_department" model="res.groups">
@ -178,7 +187,7 @@
<field name="active" eval="True" />
</record>
<!-- Add rules for visit.location -->
<!-- Add rules for visit.location -->
<record id="visit_location_show_all_rule" model="ir.rule">
<field name="name">Show All Visit Location</field>
<field name="model_id" ref="model_visit_location"/>
@ -208,9 +217,9 @@
<field name="model_id" ref="model_visit_location"/>
<field name="domain_force">[
'|',
('create_uid','=',user.id),
('researcher_team.employee_id', 'in', user.employee_id.ids)
]</field>
('create_uid','=',user.id),
('researcher_team.employee_id', 'in', user.employee_id.ids)
]</field>
<field name="groups" eval="[(4, ref('group_benefit_researcher'))]"/>
<field name="active" eval="True" />
</record>
@ -256,9 +265,9 @@
<field name="model_id" ref="model_family_complaints"/>
<field name="domain_force">[
'|',
('create_uid','=',user.id),
('researcher_id.employee_id', 'in', user.employee_id.ids)
]</field>
('create_uid','=',user.id),
('researcher_id.employee_id', 'in', user.employee_id.ids)
]</field>
<field name="groups" eval="[(4, ref('group_benefit_researcher'))]"/>
<field name="active" eval="True" />
</record>
@ -277,9 +286,9 @@
<field name="model_id" ref="model_service_request"/>
<field name="domain_force">[
'|',
('create_uid','=',user.id),
('researcher_id.employee_id', 'in', user.employee_id.ids)
]</field>
('create_uid','=',user.id),
('researcher_id.employee_id', 'in', user.employee_id.ids)
]</field>
<field name="groups" eval="[(4, ref('group_benefit_researcher'))]"/>
<field name="active" eval="True" />
</record>
@ -289,9 +298,9 @@
<field name="model_id" ref="model_service_request"/>
<field name="domain_force">[
'|',
('family_id.branch_custom_id.branch.manager_id', '=', user.employee_id.id),
('family_id.branch_custom_id.branch.operation_manager_id', '=', user.employee_id.id)
]</field>
('family_id.branch_custom_id.branch.manager_id', '=', user.employee_id.id),
('family_id.branch_custom_id.branch.operation_manager_id', '=', user.employee_id.id)
]</field>
<field name="groups" eval="[(4, ref('group_benefit_branch_manager')), (4, ref('group_benefit_woman_commitee'))]"/>
<field name="active" eval="True" />
</record>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -540,6 +540,7 @@
<field name="name">Services Requests</field>
<field name="res_model">service.request</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('is_seasonal','=',False)]</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the Service Request
</p>

View File

@ -9,77 +9,83 @@
<form string="Seasonal Service">
<header>
<button name="action_approval_of_beneficiary_services" type="object"
string="Approve Beneficiary Services" class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'draft')]}"
groups="odex_benefit.group_approval_of_beneficiary_services" />
string="Approve Beneficiary Services" class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'draft')]}"
groups="odex_benefit.group_approval_of_beneficiary_services"/>
<button name="get_families" type="object"
string="Get Families" class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'draft')]}" />
string="Get Families" class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'draft')]}"/>
<button name="action_accounting_approve" type="object"
string="Accounting Approve"
class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'approval_of_beneficiary_services')]}"
groups="odex_benefit.group_benefit_accounting_accept" />
string="Accounting Approve"
class="oe_highlight"
attrs="{'invisible': [('state', '!=', 'approval_of_beneficiary_services')]}"
groups="odex_benefit.group_benefit_accounting_accept"/>
<button name="action_open_exchange_order_wizard"
type="object"
string="امر الصرف"
class="oe_highlight"
attrs="{'invisible': ['|', ('state', '!=', 'accounting_approve'), ('payment_order_id', '!=', False)]}"
groups="odex_benefit.group_benefit_accounting_accept" />
type="object"
string="امر الصرف"
class="oe_highlight"
attrs="{'invisible': ['|', ('state', '!=', 'accounting_approve'), ('payment_order_id', '!=', False)]}"
groups="odex_benefit.group_benefit_accounting_accept"/>
<field name="state" widget="statusbar"
statusbar_visible="draft, approval_of_beneficiary_services,accounting_approve" />
statusbar_visible="draft, approval_of_beneficiary_services,accounting_approve"/>
</header>
<sheet>
<field name="is_payment_order_done" invisible="1" />
<field name="is_payment_order_done" invisible="1"/>
<widget name="web_ribbon" title="Payment Order Done" bg_color="bg-success"
attrs="{'invisible': [('is_payment_order_done', '=', False)]}" />
attrs="{'invisible': [('is_payment_order_done', '=', False)]}"/>
<group>
<group>
<field name="name" attrs="{'readonly': [('state', '!=', 'draft')]}" />
<field name="date" attrs="{'readonly': [('state', '!=', 'draft')]}" />
<field name="name" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="date" attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="service_type_id"
attrs="{'readonly': [('state', '!=', 'draft')]}" />
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="branch_ids" widget="many2many_tags"
attrs="{'readonly': [('state', '!=', 'draft')]}" />
<field name="family_category_ids" widget="many2many_tags" readonly="1" />
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="family_category_ids" widget="many2many_tags" readonly="1"/>
<field name="payment_order_id" readonly="1"
groups="odex_benefit.group_benefit_accounting_accept"
attrs="{
groups="odex_benefit.group_benefit_accounting_accept"
attrs="{
'invisible': [('payment_order_id', '=', False)],
'readonly': [('state', '!=', 'draft')]
}" />
}"/>
</group>
<group>
<field name="aid_amount" readonly="1" />
<field name="family_count" readonly="1" />
<field name="benefit_member_count" readonly="1" />
<field name="family_disbursement_total_amount" readonly="1" />
<field name="aid_amount" readonly="1"/>
<field name="family_count" readonly="1"/>
<field name="benefit_member_count" readonly="1"/>
<field name="family_disbursement_total_amount" readonly="1"/>
</group>
</group>
<notebook>
<page string="Families">
<field name="family_ids" widget="one2many_list"
attrs="{'readonly': [('state', '!=', 'draft')]}">
attrs="{'readonly': [('state', '!=', 'draft')]}">
<tree editable="bottom">
<field name="family_id" />
<field name="branch_custom_id" />
<field name="account_id" />
<field name="name" string="Service Number" />
<field name="aid_amount" string="Service Amount" />
<field name="family_id"/>
<field name="branch_custom_id"/>
<field name="account_id"/>
<field name="name" string="Service Number"/>
<field name="aid_amount" string="Service Amount"/>
</tree>
</field>
</page>
<page string="Services Requests">
<field name="service_requests_ids" widget="one2many_list" mode="tree,form"/>
</page>
<page string="Families">
<field name="benefit_ids"/>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"
groups="base.group_user" />
<field name="activity_ids" />
<field name="message_ids" widget="mail_thread" />
groups="base.group_user"/>
<field name="activity_ids"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
@ -91,14 +97,14 @@
<field name="model">seasonal.service</field>
<field name="arch" type="xml">
<tree string="Seasonal Services">
<field name="name" />
<field name="date" />
<field name="service_type_id" />
<field name="aid_amount" />
<field name="family_count" />
<field name="benefit_member_count" />
<field name="family_disbursement_total_amount" />
<field name="state" />
<field name="name"/>
<field name="date"/>
<field name="service_type_id"/>
<field name="aid_amount"/>
<field name="family_count"/>
<field name="benefit_member_count"/>
<field name="family_disbursement_total_amount"/>
<field name="state"/>
</tree>
</field>
</record>

View File

@ -256,6 +256,7 @@
<field name="refuse_reason" attrs="{'invisible': [('refuse_reason', '=', False)]}"
readonly="1"/>
<field name="required_attach" invisible="1"/>
<field name="is_seasonal" invisible="1"/>
</group>
</group>
<group>

View File

@ -10,5 +10,13 @@
action = records.action_unlink_sponsor_and_related()
</field>
</record>
<record id="action_extend_donation" model="ir.actions.server">
<field name="name">Extend Donation</field>
<field name="model_id" ref="odex_takaful.model_donations_details_lines"/>
<field name="binding_model_id" ref="odex_takaful.model_donations_details_lines"/>
<field name="state">code</field>
<field name="code">action = records.action_extend_sponsorship()</field>
</record>
</data>
</odoo>

View File

@ -3283,7 +3283,7 @@ msgstr "نظام الكفلاء ونقاط البيع"
#. module: odex_takaful
#: model:res.groups,name:odex_takaful.group_kufula_user
msgid "Kufula User"
msgstr ""
msgstr "مستخدم الكفالات"
#. module: odex_takaful
#: model:ir.model.fields,field_description:odex_takaful.field_takaful_sponsor__lang

View File

@ -7,13 +7,22 @@ from collections import defaultdict
class AccountMove(models.Model):
_inherit = 'account.move'
takaful_sponsorship_id = fields.Many2one('takaful.sponsorship')
takaful_sponsorship_id = fields.Many2one('takaful.sponsorship', compute='_compute_takaful_sponsorship_id', store=True)
is_refund_sponsorship = fields.Boolean(string='Is Refund Sponsorship', default=False)
sponsorship_scheduling_line = fields.Many2one('sponsorship.scheduling.line')
payment_details_line = fields.Many2one('payment.details.lines')
sponsorship_id = fields.Many2one('takaful.sponsorship', string='Sponsorship', readonly=True, )
payment_id = fields.Many2one('account.payment', string='Payment', copy=False)
@api.depends('state')
def _compute_takaful_sponsorship_id(self):
for move in self:
if not move.takaful_sponsorship_id:
partials = move.line_ids.matched_debit_ids | move.line_ids.matched_credit_ids
takaful_sponsorship_ids = (partials.debit_move_id.move_id.takaful_sponsorship_id | partials.credit_move_id.move_id.takaful_sponsorship_id)
move.takaful_sponsorship_id = takaful_sponsorship_ids[-1] if takaful_sponsorship_ids else False
else:
move.takaful_sponsorship_id = move.takaful_sponsorship_id
def action_move_line_create(self):
'''
Confirm the vouchers given in ids and create the journal entries for each of them
@ -239,5 +248,5 @@ class AccountMove(models.Model):
class AccountMoveLines(models.Model):
_inherit = 'account.move.line'
takaful_sponsorship_id = fields.Many2one('takaful.sponsorship')
takaful_sponsorship_id = fields.Many2one('takaful.sponsorship', related='move_id.takaful_sponsorship_id', store=True)

View File

@ -395,6 +395,7 @@ class DonationsDetailsLines(models.Model):
"donation_types": 'donation',
"name": product.name,
"donation_qty": _qty,
"donation_amount": product.lst_price
})
else:
if existing:
@ -942,7 +943,6 @@ class DonationsDetailsLines(models.Model):
"""
Open wizard to extend donation detail line
"""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
@ -951,9 +951,7 @@ class DonationsDetailsLines(models.Model):
'view_mode': 'form',
'target': 'new',
'context': {
'default_donation_detail_id': self.id,
'default_current_end_date': self.end_date,
'default_amount': self.product_template_id.list_price,
'donation_detail_ids': self.ids,
},
}

View File

@ -5,8 +5,7 @@ from odoo.exceptions import UserError, ValidationError, Warning
from dateutil.parser import parse
import re
from odoo.osv import expression
SAUDI_MOBILE_PATTERN = r"^(05|5)(5|0|3|6|4|9|1|8|7)([0-9]{7})$"
SAUDI_MOBILE_PATTERN = r"^(\+?966)?0?5[013456789][0-9]{7}$"
class IrActionsServer(models.Model):
_inherit = 'ir.actions.server'
@ -407,3 +406,15 @@ class ResPartner(models.Model):
else:
rec.name = " "
class ResPartnerBank(models.Model):
_inherit = 'res.partner.bank'
def name_get(self):
result = []
for bank in self:
if bank.bank_id:
name = f"{bank.acc_number} - {bank.bank_id.name}"
else:
name = f"{bank.acc_number}"
result.append((bank.id, name))
return result

View File

@ -15,7 +15,7 @@ import requests
from odoo.osv import expression
import logging
SAUDI_MOBILE_PATTERN = r"^(05|5)(5|0|3|6|4|9|1|8|7)([0-9]{7})$"
SAUDI_MOBILE_PATTERN = r"^(\+?966)?0?5[013456789][0-9]{7}$"
def trunc_datetime(someDate):
@ -328,6 +328,7 @@ class TakafulSponsorship(models.Model):
"donation_types": 'donation',
"name": product.name,
"donation_qty": _qty,
"donation_amount": product.lst_price
})
else:
# remove if qty <= 0
@ -754,6 +755,7 @@ class TakafulSponsorship(models.Model):
taxes = line.move_id.fiscal_position_id.map_tax(taxes, partner=line.partner_id)
line.tax_ids = taxes
line.product_uom_id = line._get_computed_uom()
bill_id.action_post()
else:
sponsorship.state = sponsorship.state
@ -1067,90 +1069,11 @@ class TakafulSponsorship(models.Model):
rec.expected_cancel_date = None
rec.due_days = 0
# On Change
# @api.onchange('sponsorship_class', 'sponsorship_type', 'benefit_id', 'benefit_ids')
# def sponsorship_fully_value(self):
# if self.sponsorship_class == 'fully' and self.benefit_ids and self.sponsorship_type == 'group':
# self.update({'contribution_value': sum(
# self.benefit_ids.mapped('benefit_needs_value'))})
# elif self.sponsorship_class == 'fully' and self.benefit_id and self.sponsorship_type == 'person':
# self.update(
# {'contribution_value': self.benefit_id.benefit_needs_value})
# else:
# self.update({'contribution_value': 0})
# @api.constrains('contribution_value')
# def check_contribution_value(self):
# if not self.sponsor_id:
# raise ValidationError(
# _(u'Please Select The Sponsor'))
# if not self.sponsorship_type:
# raise ValidationError(
# _(u'Please Select Sponsorship Type'))
#
# if not self.benefit_type:
# raise ValidationError(
# _(u'Please Select Sponsorship Beneficiary Type'))
#
# if not self.sponsorship_class:
# raise ValidationError(
# _(u'Please Select Sponsorship Class'))
#
# if not self.sponsorship_duration:
# raise ValidationError(
# _(u'Please Select Sponsorship Duration'))
#
# if not self.benefit_id and self.sponsorship_type == 'person':
# raise ValidationError(
# _(u'Please Select a Beneficiary For Sponsorship Person'))
#
# if len(self.benefit_ids) < 2 and self.sponsorship_type == 'group':
# raise ValidationError(
# _(u'Please Select At least Two Beneficiaries For Sponsorship Group'))
#
# if self.sponsorship_class == 'partial':
# default_sponsorship = int(
# self.env['ir.config_parameter'].sudo().get_param('odex_takaful_base.min_kafala', 0))
#
# if self.benefit_ids and self.sponsorship_type == 'group':
# benefit_count = len(self.benefit_ids)
# else:
# benefit_count = 1
#
# if default_sponsorship <= 0:
# raise ValidationError(
# _(u'Min kafala value should be defined by administration'))
#
# total_sponsorship = default_sponsorship * benefit_count
# if self.contribution_value < total_sponsorship:
# raise ValidationError(
# _(u'Kafala value should be equal or greater than') + ' ' + str(total_sponsorship))
# Model Operations
@api.model
def create(self, vals):
# if vals.get('code', 'New') == 'New':
# vals['code'] = self.env['ir.sequence'].sudo().next_by_code('sponsorship.sequence')
# if vals.get('benefit_type') == 'orphan':
# main_code = self.env['ir.sequence'].sudo(
# ).next_by_code('sponsorship.sequence')
# sub_code = self.env['ir.sequence'].sudo().next_by_code(
# 'sponsorship.orphan.sequence')
# if main_code and sub_code:
# defualt_code = 'OR/' + str(main_code) + '/' + sub_code
# vals.update({"code": defualt_code})
# elif vals.get('benefit_type') == 'widow':
# main_code = self.env['ir.sequence'].sudo(
# ).next_by_code('sponsorship.sequence')
# sub_code = self.env['ir.sequence'].sudo().next_by_code(
# 'sponsorship.widow.sequence')
# if main_code and sub_code:
# defualt_code = 'WI/' + str(main_code) + '/' + sub_code
# vals.update({"code": defualt_code})
# Valid Sponsor Mobile
sponsor_phone = vals.get('sponsor_phone', False)
if sponsor_phone:
self._check_phone_numbers(sponsor_phone)
@ -1269,9 +1192,10 @@ class TakafulSponsorship(models.Model):
for benefit in (line.benefit_id | line.benefit_ids):
if benefit.sponsor_related_id:
raise ValidationError(_("Cannot proceed with payment!\n\n"
"The following sponsorship lines contain beneficiaries that are already sponsored by other sponsors:\n"
"Lines: %s\n\n"
"Please choose different beneficiaries for these lines before proceeding with the payment." % line.sequence_no))
"The following sponsorship lines contain beneficiaries that are already sponsored by other sponsors:\n"
"Lines: %s\n\n"
"Please choose different beneficiaries for these lines before proceeding with the payment." % line.sequence_no))
if not all(all_donation_lines.mapped("sponsorships_computed")):
(self.donations_details_lines + self.donations_details_lines_mechanism_ids).compute_sponsorships_lines()
@ -1284,7 +1208,7 @@ class TakafulSponsorship(models.Model):
start_date = parse(str(self.start_date)).date()
start_by = _('Start Date')
start_text = start_by + ' ' + start_date.strftime('%d, %b %Y')
subject = msg_template.title
message = msg_template.body + '\n' + _('Sponsorship Number') + ' %s' % self.code + '\n' + _(
'Contribution Value') + ' %s' % str(self.contribution_value) + '\n' + start_text
@ -1294,7 +1218,7 @@ class TakafulSponsorship(models.Model):
'title': subject,
'body': message,
})
push.sudo().send_sms_notification()
self.state = "confirmed"
@ -1352,7 +1276,8 @@ class TakafulSponsorship(models.Model):
raise ValidationError(_("No Whatsapp notification of type 'Create Kafala' found."))
else:
pass
# self.action_send_whatsapp()
#self.action_send_whatsapp()
def action_send_whatsapp(self):
@ -1744,6 +1669,15 @@ class TakafulSponsorship(models.Model):
sponsorship_line_ids = (rec.donations_details_lines | rec.donations_details_lines_mechanism_ids).filtered(lambda l: not l.direct_debit)
rec.show_register_payment = rec.with_context(exclude_direct_debit=True).amount_paid < sum(sponsorship_line_ids.mapped('total_donation_amount'))
def action_reset_to_draft(self):
for rec in self:
if rec.state != 'confirmed':
raise ValidationError(_("You can only reset to draft a confirmed sponsorship."))
move_ids = rec.journal_entry_ids.filtered(lambda l: l.move_type == 'out_invoice')
move_ids.button_draft()
move_ids.button_cancel()
self.write({'state': 'draft'})
class AnotherSponsors(models.Model):
_name = "donate.for.another.person"

View File

@ -45,6 +45,7 @@ access_group_kufula_user_account_partial_reconcile,access_group_kufula_user_acco
access_group_kufula_user_account_full_reconcile,access_group_kufula_user_account_full_reconcile,account.model_account_full_reconcile,odex_takaful.group_kufula_user,1,1,1,0
access_donation_extension_wizard,donation.extension.wizard.access,model_donation_extension_wizard,base.group_user,1,1,1,1
access_donation_extension_history,donation.extension.history.access,model_donation_extension_history,odex_takaful.group_kufula_user,1,1,1,0
access_donation_extension_wizard_line,donation.extension.wizard.line.access,model_donation_extension_wizard_line,odex_takaful.group_kufula_user,1,1,1,0
access_replace_sponsor_wizard,replace.sponsor.wizard.access,model_replace_sponsor_wizard,odex_takaful.group_replace_sponsor,1,1,1,1

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
45 access_group_kufula_user_account_move access_group_kufula_user_product_template access_group_kufula_user_account_move access_group_kufula_user_product_template account.model_account_move product.model_product_template odex_takaful.group_kufula_user 1 1 1 0 0
46 access_group_kufula_user_sale_order access_group_kufula_user_account_move access_group_kufula_user_sale_order access_group_kufula_user_account_move sale.model_sale_order account.model_account_move odex_takaful.group_kufula_user 1 1 1 0
47 access_group_kufula_user_grant_benefit access_group_kufula_user_sale_order access_group_kufula_user_grant_benefit access_group_kufula_user_sale_order odex_benefit.model_grant_benefit sale.model_sale_order odex_takaful.group_kufula_user 1 1 1 0
48 access_group_kufula_user_grant_benefit access_group_kufula_user_grant_benefit odex_benefit.model_grant_benefit odex_takaful.group_kufula_user 1 1 1 0
49 access_group_kufula_user_res_partner access_group_kufula_user_res_partner base.model_res_partner odex_takaful.group_kufula_user 1 1 1 0
50
51

View File

@ -213,9 +213,18 @@
<field name="name">Responsible Users can access related Sponsorships</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('group_kufula_user'))]"/>
<field name="domain_force">
[('sponsor_id.responsible_user_ids', 'in', [user.id])]
</field>
<field name="domain_force">[('create_uid','=',user.id)]</field>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
<field name="perm_unlink" eval="1"/>
</record>
<record id="kufula_user_donations_details_lines_access" model="ir.rule">
<field name="name">Users can access related Donations Details Lines</field>
<field name="model_id" ref="model_donations_details_lines"/>
<field name="groups" eval="[(4, ref('group_kufula_user'))]"/>
<field name="domain_force">[('create_uid','=',user.id)]</field>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>

View File

@ -3,6 +3,13 @@
// Attach event handlers immediately using event delegation
// Odoo converts 'name' attribute to 'data-name' in rendered HTML
$(document).on('click', 'button[data-name="add_quantity_button_request"]', function(e) {
e.preventDefault();
e.stopPropagation();
handleQuantityChange($(this), 'first_add');
return false; // ensure Odoo's default kanban action handler does not run
});
$(document).on('click', 'button[data-name="add_quantity_button_so"]', function(e) {
e.preventDefault();
e.stopPropagation();
@ -24,6 +31,9 @@ window.__dc_add = function(btn) {
window.__dc_remove = function(btn) {
return __dc_handle(btn, 'remove');
};
window.__dc_first_add = function(btn) {
return __dc_handle(btn, 'first_add');
};
function __dc_handle(btn, operation) {
try {
@ -36,6 +46,7 @@ function __dc_handle(btn, operation) {
}
async function handleQuantityChange($button, operation) {
// Get the kanban record (product card) container
const $kanbanRecord = $button.closest('.o_kanban_record');
if (!$kanbanRecord.length) {
@ -43,24 +54,26 @@ async function handleQuantityChange($button, operation) {
}
// Get quantity display element from the button's parent container using stable custom classes
const $container = $button.closest('.dc-qty-controls');
const $quantityDisplay = $container.find('.dc-qty-badge');
if (!$quantityDisplay.length) {
return;
let $container = $button.closest('.dc-qty-controls');
if (operation === 'first_add'){
$container = $kanbanRecord.find('.dc-qty-controls')
}
let $quantityDisplay = $container.find('.dc-qty-badge');
// if (!$quantityDisplay.length) {
// return;
// }
// Extract product ID from the image URL
const $img = $kanbanRecord.find('.o_kanban_image img');
if (!$img.length) {
return;
}
// if (!$img.length) {
// return;
// }
const imgSrc = $img.attr('src');
const match = imgSrc.match(/[&?]id=(\d+)/);
if (!match || !match[1]) {
return;
}
// if (!match || !match[1]) {
// return;
// }
const productId = parseInt(match[1]);
let currentQuantity = parseFloat($quantityDisplay.text()) || 0;
@ -68,10 +81,6 @@ async function handleQuantityChange($button, operation) {
// Prevent going below zero for remove operation
if (operation === 'remove' && currentQuantity <= 0) {
$quantityDisplay.addClass('bg-warning').removeClass('bg-secondary');
setTimeout(() => {
$quantityDisplay.removeClass('bg-warning').addClass('bg-secondary');
}, 300);
return;
}
@ -108,16 +117,22 @@ async function handleQuantityChange($button, operation) {
// Calculate new quantity
let newQuantity = currentQuantity;
if (operation === 'add') {
newQuantity += 1;
} else if (operation === 'remove') {
newQuantity -= 1;
if (operation === 'first_add'){
$button.addClass('d-none');
$kanbanRecord.find('.dc-qty-controls').removeClass("d-none");
}
if (operation === 'add' || operation === 'first_add') {
newQuantity = newQuantity + 1;
}
if (operation === 'remove') {
newQuantity = newQuantity - 1;
}
// Update display optimistically
$quantityDisplay.text(newQuantity.toFixed(2));
try {
// Call server to update quantity
await $.ajax({
@ -139,22 +154,13 @@ async function handleQuantityChange($button, operation) {
throw info;
});
// Visual feedback - flash color based on operation
if (operation === 'add') {
$quantityDisplay.addClass('bg-success').removeClass('bg-secondary');
} else {
$quantityDisplay.addClass('bg-info').removeClass('bg-secondary');
}
setTimeout(() => {
$quantityDisplay.removeClass('bg-success bg-info').addClass('bg-secondary');
}, 300);
} catch (error) {
// Revert on error
$quantityDisplay.text(currentQuantity.toFixed(2));
$quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
// $quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
setTimeout(() => {
$quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
// $quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
}, 1000);
} finally {
// Re-enable buttons

View File

@ -4,34 +4,37 @@
<field name="model">product.template</field>
<field name="arch" type="xml">
<kanban edit="0" create="0" class="o_kanban_mobile o_cart_kanban">
<field name="id"/>
<field name="name"/>
<field name="_quantity"/>
<field name="id" />
<field name="name" />
<field name="_quantity" />
<templates>
<t t-name="kanban-box">
<div class="o_product_quantity d-flex flex-column justify-content-between"
style="min-height: 100px;width: 25%;">
<div class="o_kanban_image">
style="min-height: 100px;width: 25%;">
<div class="o_kanban_image" style="display: flex;width: 100%;justify-content: space-between;align-items: center;">
<img t-att-src="kanban_image('product.template', 'image_128', record.id.raw_value)"
alt="Product" class="o_image_64_contain"/>
alt="Product" class="o_image_64_contain" style="width: 100%;object-fit: cover;height: 100px;"/>
</div>
<h5 style="margin-top: 5px;text-align: center;">
<span>Amount:</span>
<field name="lst_price" widget="monetary" options="{'currency_field': 'currency_id'}" />
</h5>
<div class="oe_kanban_details p-2 d-flex">
<div class="o_kanban_record_top flex-column w-100 "
style="justify-content: space-between;">
<div class="o_kanban_record_title">
style="justify-content: space-between;">
<div class="o_kanban_record_title w-100" style="text-align: center;">
<strong>
<field name="name"/>
<field name="name" />
</strong>
</div>
<div class="d-flex w-100 justify-content-between">
<ul>
<!-- <ul>
<li>
<strong>
Price:
<field name="lst_price" widget="monetary"
options="{'currency_field': 'currency_id'}"/>
<strong> Amount: <field name="lst_price"
widget="monetary"
options="{'currency_field': 'currency_id'}" />
</strong>
</li>
</li> -->
<!-- <field name="currency_id" invisible="1"/> -->
<!-- <div> -->
@ -40,77 +43,51 @@
<!-- <field name="uom_id" class="ms-1" -->
<!-- groups="uom.group_uom"/> -->
<!-- </div> -->
</ul>
<!-- </ul> -->
</div>
<!-- <button t-if="record._quantity == 0"-->
<!-- <button
id="add_quantity"
class="btn btn-primary rounded-circle p-0 d-flex align-items-center justify-content-center"
style="width: 25px; height: 25px;" type="object"
name="add_quantity_button_so" string="ADD">
<i class="fa fa-plus fs-5" title="إضافة"/>
<div class="d-flex w-100 justify-content-center align-items-center mt-4">
</button> -->
<button class="btn btn-secondary" type="button"
name="add_quantity_button_so"
data-name="add_quantity_button_request"
title="إضافة منتج"
onclick="return window.__dc_first_add(this);">
<i class="fa fa-shopping-cart" />
<span>Add</span>
</button>
<!-- <button-->
<!-- id="add_quantity"-->
<!-- class="oe_kanban_button oe_dynamic_button btn btn-primary rounded-circle p-0 d-flex align-items-center justify-content-center"-->
<!-- style="width: 25px; height: 25px;" type="object"-->
<!-- name="add_quantity_button_so" string="ADD">-->
<!-- <i class="fa fa-plus fs-5" title="إضافة"/>-->
<!-- </button>-->
<!-- <t t-if="record._quantity == 1">
<span class="fa fa-plus fs-5">م الإضافة</span>
</t> -->
<!-- Quantity Controls: Minus, Display, Plus -->
<div class="d-flex align-items-center gap-2 dc-qty-controls">
<!-- Minus Button -->
<button
class="btn btn-light border rounded-circle p-0 d-flex align-items-center justify-content-center"
style="width: 28px; height: 28px;"
type="button"
name="remove_quantity_button_so"
title="تقليل الكمية"
onclick="return window.__dc_remove(this);">
<i class="fa fa-minus" style="font-size: 12px;"/>
</button>
<!-- Quantity Display -->
<span class="badge bg-secondary px-2 py-1 dc-qty-badge"
style="min-width: 35px; font-size: 14px; font-weight: bold;">
<field name="_quantity"/>
</span>
<!-- Plus Button -->
<button
class="btn btn-primary rounded-circle p-0 d-flex align-items-center justify-content-center"
style="width: 28px; height: 28px;"
type="button"
name="add_quantity_button_so"
title="إضافة"
onclick="return window.__dc_add(this);">
<i class="fa fa-plus" style="font-size: 12px;"/>
</button>
<div class="dc-qty-controls d-none">
<div class="input-group">
<div class="input-group-prepend">
<button
class="btn btn-primary"
type="button"
name="remove_quantity_button_so"
data-name="remove_quantity_button_so"
title="تقليل الكمية"
onclick="return window.__dc_remove(this);">
<i class="fa fa-minus" />
</button>
</div>
<div class="form-control dc-qty-badge">
<field name="_quantity" />
</div>
<div class="input-group-prepend">
<button
class="btn btn-primary"
type="button"
name="add_quantity_button_so"
data-name="add_quantity_button_so"
title="إضافة"
onclick="return window.__dc_add(this);">
<i class="fa fa-plus" />
</button>
</div>
</div>
</div>
</div>
<!-- <div name="_quantity" -->
<!-- class="h-100 ml-2 d-flex align-items-center o_product_quantity o_field_widget o_quick_editable" -->
<!-- style="z-index:1;align-items: center;"> -->
<!-- <button id="remove_quantity" -->
<!-- class="btn d-flex align-items-center justify-content-center o_qty_button btn-light text-muted" -->
<!-- type="object" name="remove_quantity_button_so"> -->
<!-- <i class="fa fa-minus center" title="Decrease" /> -->
<!-- </button> -->
<!-- <span style="font-size:1.5rem;" -->
<!-- t-attf-class="{{record.id.value}}" -->
<!-- onclick="change_input_so(this)"> -->
<!-- <field name="_quantity"></field> -->
<!-- </span> -->
<!-- <button id="add_quantity" -->
<!-- class="btn d-flex align-items-center justify-content-center o_qty_button btn-light text-muted" -->
<!-- type="object" name="add_quantity_button_so" string="ADD"> -->
<!-- &lt;!&ndash; <i class="fa fa-plus" title="Increase" />&ndash;&gt; -->
<!-- </button> -->
<!-- </div> -->
</div>
</div>
</div>
@ -119,6 +96,7 @@
</kanban>
</field>
</record>
<!-- Tree view for product.template with sponsorship button -->
<record id="view_product_template_tree_sponsorship" model="ir.ui.view">
<field name="name">product.template.tree.sponsorship</field>
@ -126,23 +104,24 @@
<field name="arch" type="xml">
<tree string="Products">
<header>
<button name="link_to_sponsorship" type="object" string="Link to Sponsorship" class="btn-primary"
icon="fa-link"/>
<button name="link_to_sponsorship" type="object" string="Link to Sponsorship"
class="btn-primary"
icon="fa-link" />
</header>
<field name="name"/>
<field name="donation_category"/>
<field name="list_price" string="Price"/>
<field name="name" />
<field name="donation_category" />
<field name="list_price" string="Price" />
</tree>
</field>
</record>
<record id="odex_takaful_product_template_form_view" model="ir.ui.view">
<field name="name">odex.takaful.product.template.form.view</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="product.product_template_form_view"/>
<field name="inherit_id" ref="product.product_template_form_view" />
<field name="arch" type="xml">
<field name="uom_id" position="before">
<field name="payment_method_id" options="{'no_create': True}"/>
<field name="payment_method_id" options="{'no_create': True}" />
</field>
</field>
</record>
</odoo>
</odoo>

View File

@ -1,6 +1,10 @@
<?xml version="1.0"?>
<odoo>
<<<<<<< HEAD
<menuitem id="takaful_kufula_app_top_menu" sequence="15" name="Kafalat System" web_icon="odex_takaful,static/description/icon5.png" groups="odex_takaful.group_kufula_user"/>
=======
<menuitem id="takaful_kufula_app_top_menu" sequence="15" name="Kafalat System" web_icon="odex_takaful,static/description/icon.png" groups="odex_takaful.donation_officer_group"/>
>>>>>>> bb335d757bca524e6bc8e1cc47f6327baa672c63
<!-- Main Kafalat-->
<menuitem id="kafalat_main_menu" parent="takaful_kufula_app_top_menu"

View File

@ -39,6 +39,9 @@
<button name="action_confirm_data" type="object"
string="Confirm Data" class="oe_highlight"
attrs="{'invisible': ['|','|', ('state','!=','draft'), ('id','=',False), '&amp;',('sponsor_or_donor_type','=','new_sponsor'),('sponsor_id','=',False)]}"/>
<button name="action_reset_to_draft" type="object"
string="Reset to Draft" class="oe_highlight"
attrs="{'invisible': [('state','!=','confirmed')]}"/>
<button string="Pay All Sponsorships" name="action_register_payment" type="object"
class="oe_highlight"
attrs="{'invisible': ['|', ('state', 'not in', ['confirmed', 'wait_pay','under_replacement','replacement_done']), ('show_register_payment', '=', False)]}"/>
@ -181,7 +184,7 @@
</page>
<page string="Donation Details">
<field name="donations_details_lines"
context="{'default_active_id': active_id,'default_donation_mechanism': donation_mechanism,'default_start_date': sponsorship_creation_date}"
context="{'default_active_id': active_id,'default_donation_mechanism': 'without_conditions','default_start_date': sponsorship_creation_date}"
widget="section_and_note_one2many"
attrs="{'invisible': ['|',('donation_mechanism', '=', 'with_conditions'),('record_type', '!=', 'donation')], 'readonly': [('state','!=','draft')]}">
<tree editable="bottom" class="fix_overflow">

View File

@ -43,7 +43,7 @@ class AccountRegisterPayment(models.TransientModel):
@api.depends('source_amount', 'source_amount_currency', 'source_currency_id', 'company_id', 'currency_id', 'payment_date')
def _compute_amount(self):
if self.env.context.get('sponsorship_payment'):
if self.env.context.get('sponsorship_payment_skip_compute_amount'):
self.amount = self.amount
else:
super(AccountRegisterPayment, self)._compute_amount()
@ -65,7 +65,6 @@ class AccountRegisterPayment(models.TransientModel):
payments = super(AccountRegisterPayment, self)._create_payments()
if sponsorship_lines:
sponsorship = sponsorship_lines.sponsorship_id or sponsorship_lines.sponsorship_mechanism_id
for line in sponsorship_lines:
state = ''
@ -119,6 +118,7 @@ class AccountRegisterPayment(models.TransientModel):
taxes = line.move_id.fiscal_position_id.map_tax(taxes, partner=line.partner_id)
line.tax_ids = taxes
line.product_uom_id = line._get_computed_uom()
bill_id.action_post()
for line in sponsorship_lines:
if line.record_type != 'sponsorship':
continue
@ -138,7 +138,6 @@ class AccountRegisterPayment(models.TransientModel):
if self.env.context.get('is_direct_debit'):
payments.write({'direct_debit': True})
payments.move_id.write({'takaful_sponsorship_id': sponsorship.id})
if self.transaction_file_attachment:
self.env['ir.attachment'].sudo().create({

View File

@ -10,29 +10,15 @@ class DonationExtensionWizard(models.TransientModel):
_name = 'donation.extension.wizard'
_description = "Donation Extension Wizard"
donation_detail_id = fields.Many2one(
'donations.details.lines',
string='Donation Detail',
line_ids = fields.One2many(
'donation.extension.wizard.line',
'wizard_id',
string='Lines',
required=True,
readonly=True
default=lambda self: self._compute_line_ids(),
)
amount = fields.Float(
string='Monthly Extension Amount',
required=True,
help='Amount per month for the extension period'
)
fixed_value = fields.Boolean(
string='Is Fixed Value?',
related='donation_detail_id.product_template_id.fixed_value'
)
total_months_amount = fields.Float(
string='Total Months Amount',
compute='_compute_total_months_amount',
store=True,
readonly=True,
help='Total amount for the extension period'
)
direct_debit = fields.Boolean(string='Direct Debit', required=True)
months = fields.Integer(
string='Extension Months',
@ -40,6 +26,97 @@ class DonationExtensionWizard(models.TransientModel):
default=1,
help='Number of months to extend'
)
def _compute_line_ids(self):
extension_line_ids = [(5,)]
donation_detail_ids = self.env['donations.details.lines'].browse(self.env.context.get('donation_detail_ids'))
for line in donation_detail_ids:
if not (line.record_type == 'donation' and line.direct_debit) and line.record_type != 'sponsorship':
raise ValidationError(_("Only donation with direct debit or sponsorship can be extended. Line: %s") % line.name)
if line.end_date and line.end_date < fields.Date.context_today(line):
raise ValidationError(_("Only active donations with end date in the future can be extended. Line: %s") % line.name)
if line.state != 'active':
raise ValidationError(_("Only active donations can be extended. Line: %s") % line.name)
extension_line_ids.append((0, 0, {
'donation_line_id': line.id,
'current_end_date': line.end_date,
}))
return extension_line_ids
@api.constrains('months')
def _check_months(self):
for rec in self:
if rec.months <= 0:
raise ValidationError(_("Extension months must be greater than 0."))
@api.onchange('direct_debit')
def _onchange_direct_debit(self):
self.line_ids.direct_debit = self.direct_debit
def action_extend(self):
"""
Extend the donation detail line with new amount and months
"""
invoice_ids = self.env['account.move']
donation_line_ids = self.env['donations.details.lines']
for line in self.line_ids:
result = line._extend()
if result:
invoice_ids += result[0]
donation_line_ids += result[1]
if invoice_ids:
return {
'name': _('Register Payment'),
'res_model': 'account.payment.register',
'view_mode': 'form',
'context': {
'active_model': 'account.move',
'active_ids': invoice_ids.ids,
'dont_redirect_to_payments': True,
'sponsorship_line_ids': donation_line_ids.ids,
'sponsorship_payment': True,
'default_sponsorship_payment': True,
},
'target': 'new',
'type': 'ir.actions.act_window',
}
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Donation has been extended for %s month(s).') % (
self.months,
),
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'}
}
}
def action_cancel(self):
"""
Cancel the wizard
"""
return {'type': 'ir.actions.act_window_close'}
class DonationExtensionWizardLine(models.TransientModel):
_name = 'donation.extension.wizard.line'
_description = "Donation Extension Wizard Line"
wizard_id = fields.Many2one('donation.extension.wizard', string='Wizard', required=True)
donation_line_id = fields.Many2one('donations.details.lines', string='Donation Detail', required=True, readonly=True)
donation_qty = fields.Float(compute='_compute_donation_qty', store=True)
direct_debit = fields.Boolean()
total_months_amount = fields.Float(
string='Total Months Amount',
compute='_compute_total_months_amount',
store=True,
readonly=True,
help='Total amount for the extension period'
)
total_donation_amount = fields.Float(
string='Total Extension Amount',
@ -60,20 +137,31 @@ class DonationExtensionWizard(models.TransientModel):
readonly=True
)
direct_debit = fields.Boolean(string='Direct Debit', required=True)
# related
record_type = fields.Selection(related='donation_line_id.record_type')
sponsorship_type = fields.Selection(related='donation_line_id.sponsorship_type')
donation_amount = fields.Float(related='donation_line_id.donation_amount', store=True)
benefits_count = fields.Integer(related='donation_line_id.benefits_count')
sponsorship_id = fields.Many2one(related='donation_line_id.sponsorship_id')
fixed_value = fields.Boolean(related='donation_line_id.fixed_value')
donation_mechanism = fields.Selection(related='donation_line_id.donation_mechanism')
months = fields.Integer(related='wizard_id.months')
@api.depends('amount', 'months')
@api.depends('benefits_count', 'donation_amount', 'months', 'donation_qty', 'record_type', 'sponsorship_type')
def _compute_total_donation_amount(self):
for rec in self:
if rec.donation_detail_id.sponsorship_type == 'group':
rec.total_donation_amount = rec.donation_detail_id.benefits_count * rec.total_months_amount
else :
rec.total_donation_amount = rec.total_months_amount
if rec.record_type == 'donation':
if rec.sponsorship_id.donation_mechanism == 'without_conditions':
rec.total_donation_amount = rec.donation_amount * rec.donation_qty
else:
rec.total_donation_amount = rec.total_months_amount
else:
rec.total_donation_amount = rec.total_months_amount * rec.benefits_count
@api.depends('amount', 'months')
@api.depends('donation_amount', 'months')
def _compute_total_months_amount(self):
for rec in self:
rec.total_months_amount = rec.amount * rec.months
rec.total_months_amount = rec.donation_amount * rec.months
@api.depends('current_end_date', 'months')
def _compute_new_end_date(self):
@ -83,25 +171,15 @@ class DonationExtensionWizard(models.TransientModel):
else:
rec.new_end_date = False
@api.constrains('months')
def _check_months(self):
@api.depends('donation_line_id')
def _compute_donation_qty(self):
for rec in self:
if rec.months <= 0:
raise ValidationError(_("Extension months must be greater than 0."))
@api.constrains('amount')
def _check_amount(self):
for rec in self:
if rec.amount <= 0:
raise ValidationError(_("Extension amount must be greater than 0."))
def action_extend(self):
"""
Extend the donation detail line with new amount and months
"""
rec.donation_qty = rec.donation_line_id.donation_qty
def _extend(self):
self.ensure_one()
if not self.donation_detail_id:
if not self.donation_line_id:
raise ValidationError(_("No donation detail line selected."))
# Update the donation detail line
@ -109,14 +187,14 @@ class DonationExtensionWizard(models.TransientModel):
old_end_date = self.current_end_date
# Update end date
self.donation_detail_id.write({
self.donation_line_id.write({
'end_date': new_end_date,
'donation_amount': self.total_months_amount,
'payment_month_count': self.donation_detail_id.payment_month_count + self.months,
'payment_month_count': self.donation_line_id.payment_month_count + self.months,
# 'state': 'extended',
})
benefit_ids = self.donation_detail_id.benefit_ids | self.donation_detail_id.benefit_id
benefit_ids = self.donation_line_id.benefit_ids | self.donation_line_id.benefit_id
benefit_ids.write({
'sponsorship_end_date': new_end_date,
})
@ -130,52 +208,23 @@ class DonationExtensionWizard(models.TransientModel):
# Create extension history record
self.env['donation.extension.history'].create({
'donation_detail_id': self.donation_detail_id.id,
'sponsorship_id': self.donation_detail_id.sponsorship_id.id or self.donation_detail_id.sponsorship_mechanism_id.id,
'donation_detail_id': self.donation_line_id.id,
'sponsorship_id': self.donation_line_id.sponsorship_id.id or self.donation_line_id.sponsorship_mechanism_id.id,
'extension_amount': self.total_donation_amount,
'extension_months': self.months,
'old_end_date': old_end_date,
'new_end_date': new_end_date,
'invoice_id': invoice_id.id if invoice_id else False,
'old_direct_debit': self.donation_detail_id.direct_debit,
'old_direct_debit': self.donation_line_id.direct_debit,
'new_direct_debit': self.direct_debit,
})
if not self.direct_debit:
result = {
'name': _('Register Payment'),
'res_model': 'account.payment.register',
'view_mode': 'form',
'context': {
'active_model': 'account.move',
'active_ids': invoice_id.ids,
'default_amount': self.total_donation_amount,
'dont_redirect_to_payments': True,
'sponsorship_line_ids': self.donation_detail_id.ids,
'sponsorship_payment': True,
'default_sponsorship_payment': True,
'force_sponsorship_line_partner_id': self.donation_detail_id.sponsor_id.id,
},
'target': 'new',
'type': 'ir.actions.act_window',
}
else:
result = {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Donation has been extended for %s month(s) until %s') % (
self.months,
new_end_date.strftime('%Y-%m-%d')
),
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'}
}
}
return invoice_id, self.donation_line_id
return result
return False
def _create_extension_scheduling_lines(self):
"""
@ -183,7 +232,7 @@ class DonationExtensionWizard(models.TransientModel):
"""
self.ensure_one()
donation_line = self.donation_detail_id
donation_line = self.donation_line_id
start_date = self.current_end_date + relativedelta(months=1)
# Distribute total amount across months
@ -214,7 +263,7 @@ class DonationExtensionWizard(models.TransientModel):
"""
self.ensure_one()
donation_line = self.donation_detail_id
donation_line = self.donation_line_id
sponsorship = donation_line.sponsorship_id or donation_line.sponsorship_mechanism_id
# Get journal from settings
@ -258,10 +307,4 @@ class DonationExtensionWizard(models.TransientModel):
invoice_id.action_post()
return invoice_id
def action_cancel(self):
"""
Cancel the wizard
"""
return {'type': 'ir.actions.act_window_close'}

View File

@ -7,21 +7,37 @@
<field name="arch" type="xml">
<form>
<sheet>
<field name="donation_detail_id" invisible="1"/>
<group>
<group string="Extension Details">
<field name="months"/>
<field name="direct_debit"/>
<field name="fixed_value" invisible="1"/>
<field name="amount"
attrs="{'readonly':[('fixed_value','=',True)]}"/>
<field name="total_donation_amount"/>
</group>
<group string="Date Information">
<field name="current_end_date" readonly="1"/>
<field name="new_end_date"/>
</group>
</group>
<notebook>
<page string="Lines">
<field name="line_ids" nolabel="1">
<tree create="0" editable="bottom">
<field name="wizard_id" invisible="1" force_save="1"/>
<field name="months" invisible="1" force_save="1"/>
<field name="record_type" invisible="1" force_save="1"/>
<field name="sponsorship_type" invisible="1" force_save="1"/>
<field name="benefits_count" invisible="1" force_save="1"/>
<field name="sponsorship_id" invisible="1" force_save="1"/>
<field name="donation_mechanism" invisible="1" force_save="1"/>
<field name="fixed_value" invisible="1" force_save="1"/>
<field name="donation_line_id" force_save="1"/>
<field name="current_end_date" force_save="1"/>
<field name="new_end_date" force_save="1"/>
<field name="direct_debit" force_save="1"/>
<field name="donation_amount" string="Amount" attrs="{'readonly':[('fixed_value','=',True)]}" />
<field name="donation_qty" string="Qty" attrs="{'invisible':[('donation_mechanism','!=','without_conditions')]}"/>
<field name="total_months_amount" string="Months Amount" force_save="1"/>
<field name="total_donation_amount" string="Total Amount" force_save="1"/>
</tree>
</field>
</page>
</notebook>
</sheet>
<footer>
<button name="action_extend" type="object" string="Extend" class="oe_highlight"/>