[ADD] Esterdad task and refund logic

This commit is contained in:
Ali Ammar 2025-12-04 14:28:08 +03:00
parent ecbf0de5ee
commit c95b988617
21 changed files with 719 additions and 31 deletions

View File

@ -56,12 +56,15 @@
'views/reports_templates.xml',
'views/reports_actions.xml',
'reports/month_payment_template.xml',
'reports/sponsorship_receipt_report.xml',
'wizards/takaful_reports_wizards.xml',
'wizards/refund_payment_wizard.xml',
'wizards/add_details_wizard.xml',
'wizards/donation_extension_wizard.xml',
'wizards/replace_sponsor_wizard.xml',
'wizards/add_benefit_wizard.xml',
'wizards/esterdad.xml',
'wizards/otp_confirm.xml',
'views/donations_details_lines.xml',
'views/donation_extension_history_views.xml',
'views/donation_replacement_log_views.xml',

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from . import _cart_change
from . import report_api

View File

@ -0,0 +1,53 @@
import json
import logging
import werkzeug
import werkzeug.exceptions
import werkzeug.utils
import werkzeug.wrappers
import werkzeug.wsgi
from odoo import http, tools
from odoo.http import content_disposition, dispatch_rpc, request, serialize_exception as _serialize_exception, Response
_logger = logging.getLogger(__name__)
class ReportController(http.Controller):
@http.route([
'/sponsorship/<converter>/<reportname>',
'/sponsorship/<converter>/<reportname>/<docids>',
], type='http', auth='public', website=True)
def report_routes(self, reportname, docids=None, converter=None, **data):
report = request.env['ir.actions.report']._get_report_from_name(reportname)
context = dict(request.env.context)
if docids:
docids = [int(i) for i in docids.split(',')]
if data.get('options'):
data.update(json.loads(data.pop('options')))
if data.get('context'):
# Ignore 'lang' here, because the context in data is the one from the webclient *but* if
# the user explicitely wants to change the lang, this mechanism overwrites it.
data['context'] = json.loads(data['context'])
if data['context'].get('lang') and not data.get('force_context_lang'):
del data['context']['lang']
context.update(data['context'])
if converter == 'html':
html = report.with_context(context)._render_qweb_html(docids, data=data)[0]
return request.make_response(html)
elif converter == 'pdf':
pdf = report.with_context(context)._render_qweb_pdf(docids, data=data)[0]
pdfhttpheaders = [('Content-Type', 'application/pdf'), ('Content-Length', len(pdf))]
return request.make_response(pdf, headers=pdfhttpheaders)
elif converter == 'text':
text = report.with_context(context)._render_qweb_text(docids, data=data)[0]
texthttpheaders = [('Content-Type', 'text/plain'), ('Content-Length', len(text))]
return request.make_response(text, headers=texthttpheaders)
else:
raise werkzeug.exceptions.HTTPException(description='Converter %s not implemented.' % converter)

View File

@ -1,6 +1,59 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="email_template_sponsorship_confirmation1" model="mail.template">
<field name="name">Sponsorship Confirmation Email</field>
<field name="email_from">${ctx.get('email_from')} or ''}</field>
<field name="email_to">${ctx.get('email_to')}</field>
<field name="subject">Sponsorship Confirmation - ${object.sponsor_id.name}</field>
<field name="partner_to">False</field>
<field name="model_id" ref="odex_takaful.model_takaful_sponsorship"/>
<field name="auto_delete" eval="True"></field>
<field name="lang">ar_001</field>
<field name="body_html"><![CDATA[
<p>Dear ${object.sponsor_id.name},</p>
<p>Your sponsorship request has been confirmed.</p>
<p><strong>Amount:</strong> ${object.total_sponsorship_amount} ${object.currency_id.name}</p>
<p>
<strong>Link:</strong>
<a t-att-href="${object.record_url}/sponsorship/pdf/odex_takaful.report_sponsorship_receipt_document/${object.id}">
Open Sponsorship Receipt
</a>
</p>
<p>Thank you for your support.</p>
<p>Best regards,<br/>
${user.company_id.name}</p>
]]>
</field>
</record>
<record id="email_template_esterdad_confirmation3" model="mail.template">
<field name="name">Esterdad Confirmation Email</field>
<field name="email_from">${ctx.get('email_from')} or ''}</field>
<field name="email_to">${ctx.get('email_to')}</field>
<field name="subject">Refund Confirmation - ${object.sponsor_id.name}</field>
<field name="partner_to">False</field>
<field name="model_id" ref="odex_takaful.model_takaful_sponsorship"/>
<field name="auto_delete" eval="True"></field>
<field name="lang">ar_001</field>
<field name="body_html"><![CDATA[
<p>Dear ${object.sponsor_id.name},</p>
<p>Your refund request has been confirmed.</p>
<p><strong>Amount:</strong> ${object.total_sponsorship_amount} ${object.currency_id.name}</p>
<p><strong>Reason:</strong> ${object.cancel_record_id.cancel_reason.name}</p>
<p>
<strong>Link:</strong>
<a t-att-href="${object.record_url}/sponsorship/pdf/odex_takaful.report_sponsorship_receipt_document/${object.id}">
Open Sponsorship Receipt
</a>
</p>
<p>Thank you for your support.</p>
<p>Best regards,<br/>
${user.company_id.name}</p>
]]>
</field>
</record>
<record id="push_notification_email_template" model="mail.template">
<field name="name">Notification Email</field>
@ -8,10 +61,10 @@
<field name="email_to">${ctx.get('email_to')}</field>
<field name="subject">${ctx.get('company_name')} - ${ctx.get('title')}</field>
<field name="partner_to">False</field>
<field name="model_id" ref="odex_takaful.model_takaful_push_notification"/>
<field name="auto_delete" eval="True"></field>
<!-- <field name="user_signature" eval="False"></field>-->
<!-- <field name="user_signature" eval="False"></field>-->
<field name="lang">ar_001</field>
<field name="body_html"><![CDATA[
<p>

View File

@ -103,6 +103,12 @@ msgstr "عدد الاجتماعات"
msgid "# Of Operations"
msgstr "العمليات"
#. module: odex_takaful
#: model:ir.model.fields,field_description:odex_takaful.field_takaful_sponsor__operation_count
msgid "# My Documents"
msgstr "سجلاتي"
#. module: odex_takaful
#: model:ir.model.fields,field_description:odex_takaful.field_takaful_sponsor__signature_count
msgid "# Signatures"
@ -7562,4 +7568,4 @@ msgstr "حساب الجمعية"
#. module: odex_takaful
#: model_terms:ir.ui.view,arch_db:odex_takaful.donation_extension_wizard_form
msgid "Sub Payments"
msgstr "دفع متعدد"
msgstr "دفع متعدد"

View File

@ -14,6 +14,17 @@ class AccountMove(models.Model):
sponsorship_id = fields.Many2one('takaful.sponsorship', string='Sponsorship', readonly=True, )
payment_id = fields.Many2one('account.payment', string='Payment', copy=False)
esterdad_id = fields.Many2one('esterdad.wizard')
def action_view_esterdad_id(self):
self.ensure_one() # Ensure the method is called on a single record
action = self.env.ref('odex_takaful.view_esterdad_wizard_tree').read()[0]
action['domain'] = [('id', '=', self.cancel_record_id.id)]
action['context'] = {
'create': False
}
return action
@api.depends('state')
def _compute_takaful_sponsorship_id(self):
for move in self:

View File

@ -4,4 +4,9 @@ from odoo import models, fields
class AccountPayment(models.Model):
_inherit = 'account.payment'
takaful_sponsorship_id = fields.Many2one(related="move_id.takaful_sponsorship_id")
takaful_sponsorship_id = fields.Many2one(related="move_id.takaful_sponsorship_id")
confirm_payment_refund = fields.Binary()
IBN_number = fields.Integer()
confirm_payment_refund_image = fields.Binary()
payment_method_line_id_type = fields.Selection(related = 'journal_id.type')

View File

@ -113,6 +113,21 @@ class DonationsDetailsLines(models.Model):
('all', 'جميع الأعمار'),
], string="الفئة العمرية", compute="_compute_age_category")
can_edit_benefit = fields.Boolean(
string="Can Edit Benefit",
compute="_compute_can_edit_benefit",
store=False
)
@api.depends()
def _compute_can_edit_benefit(self):
for rec in self:
user = self.env.user
is_manager = (
user.has_group('odex_takaful.sponsorship_system_manager_group') or
user.has_group('odex_takaful.branch_manager_group'))
rec.can_edit_benefit = (rec.create_uid == user and not is_manager)
@api.depends('sponsorship_duration', 'payment_month_count', 'direct_debit')
def _compute_age_category(self):
for rec in self:

View File

@ -84,7 +84,7 @@ class TakafulSponsorship(models.Model):
education_status = fields.Selection(string='Education Status',selection=[('educated', 'educated'), ('illiterate', 'illiterate'),('under_study_age','Under Study Age')])
education_level = fields.Many2one("education.level", string='Education Levels')
sponsorship_duration = fields.Selection([('temporary', 'Temporary'),('permanent', 'Permanent')],string='Sponsorship Duration',default='permanent',tracking=True)
total_sponsorship_amount = fields.Float(string='Total Sponsorship Amount',compute='_get_total_sponsorship_amount')
total_sponsorship_amount = fields.Float(string='Total Sponsorship Amount',compute='_get_total_sponsorship_amount' ,store=True)
#This field for total of donation and waqf without sponsorship
total_waqf_and_donation_amount = fields.Float(string='Total Sponsorship Amount',compute='_get_total_waqf_and_donation_amount')
supporter_status = fields.Selection([
@ -127,6 +127,103 @@ class TakafulSponsorship(models.Model):
replacement_id = fields.Many2one('replacement.process', string="Replacement")
create_uid = fields.Many2one('res.users', default=lambda self: self.env.user)
marketer_id = fields.Many2one('hr.employee')
pay_date = fields.Datetime()
cancel_record_id = fields.Many2one('esterdad.wizard', string="Cancel Record")
record_url = fields.Char(string="Record URL", readonly=True)
def action_quotation_send(self):
self.ensure_one()
print('self.state >>>> ' , self.state)
if self.state != 'canceled':
template = self.env.ref('odex_takaful.email_template_sponsorship_confirmation1')
else:
template = self.env.ref('odex_takaful.email_template_esterdad_confirmation3')
lang = self.env.context.get('lang')
print('cancel_record_id >>>> ' , self.cancel_record_id.cancel_reason.name)
if template.lang:
lang = template._render_lang(self.ids)[self.id]
ctx = {
'default_model': 'sale.order',
'default_res_id': self.id,
'default_use_template': True,
'default_template_id': template.id, # use the ID here
'default_composition_mode': 'comment',
'mark_so_as_sent': True,
'custom_layout': "mail.mail_notification_paynow",
'proforma': self.env.context.get('proforma', False),
'force_email': True,
'model_description': 'Test',
}
return {
'type': 'ir.actions.act_window',
'view_mode': 'form',
'res_model': 'mail.compose.message',
'views': [(False, 'form')],
'view_id': False,
'target': 'new',
'context': ctx,
}
def action_view_esterdad_id(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'res_model': 'esterdad.wizard',
'view_mode': 'form',
'view_id': False, # or specify a particular form view if you have one
'target': 'current', # or 'new' if you want a popup wizard
'res_id': self.cancel_record_id.id, # open this record directly
'context': {
'create': False
},
}
@api.constrains('state')
def set_pay_date(self):
for rec in self:
if rec.state == 'paid':
rec.pay_date = fields.Datetime.now()
def action_set_esterdad(self):
"""Make Cancellation For Sponsorship"""
duration_hours = int(self.env['ir.config_parameter'].sudo().get_param('cancel_refund', default=0))
for rec in self:
if not rec.pay_date:
return False
# pay_date is already a datetime object
pay_dt = rec.pay_date
# add the duration
calculated_dt = pay_dt + timedelta(hours=duration_hours)
# compare with now
now_dt = fields.Datetime.now()
if calculated_dt < now_dt:
context = dict(self.env.context or {})
context['default_sponsor_id'] = rec.id
context['default_pay_date'] = rec.pay_date
context['default_amount'] = rec.total_sponsorship_amount
context['default_sponsor_name'] = rec.sponsor_id.first_name
context['default_mobile'] = rec.sponsor_id.mobile
context['default_id_num'] = rec.sponsor_id.id_number
context['default_payment_ids'] = rec.payment_ids.ids
view = self.env.ref('odex_takaful.view_esterdad_wizard_form')
return {
'name': _('Sponsorship Cancellation'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'esterdad.wizard',
'view_id': view.id,
'target': 'new',
'context': context,
}
else:
raise UserError("لا يمكنك القيام بذلك لتجاوز المدة المحددة للاسترداد.")
@api.depends('sponsor_id','sponsor_id.mobile')
@ -827,7 +924,8 @@ class TakafulSponsorship(models.Model):
))
# If validation passed, create the record
return super(TakafulSponsorship, self).create(vals)
rec = super(TakafulSponsorship, self).create(vals)
return rec
def _get_default_record_type(self):
if self.env.user.has_group("odex_takaful.donation_officer_group"):
@ -870,6 +968,10 @@ class TakafulSponsorship(models.Model):
res.update({
'record_type': 'sponsorship',
})
url = self.env['ir.config_parameter'].sudo().get_param('web.base.url', '')
res.update({
'record_url': url,
})
return res
# payment_ids = fields.One2many('account.payment','sponsorship_id',string='Payments', copy=False)

View File

@ -0,0 +1,151 @@
<odoo>
<!-- Takaful Sponsorship Receipt - based on sale_order_report layout -->
<template id="report_sponsorship_receipt_document">
<!-- Standard report container to provide <main> for PDF engine -->
<t t-call="web.html_container">
<!-- Iterate over all sponsorship records passed by ir.actions.report -->
<t t-foreach="docs" t-as="doc">
<!-- Reuse sale order header layout -->
<t t-call="sale_order_report.sale_order_report_header">
<div class="page" style="position: relative;">
<!-- Watermark for canceled sponsorships -->
<t t-if="doc.state == 'canceled'">
<div style="position: absolute;
top: 0;
right: 0;
width: 100%;
height: 100%;
color: red;
font-size: 5rem;
opacity: 0.1;
transform: rotate(-45deg);
transform-origin: top right;
text-align: right;
z-index: 0;">
Canceled
</div>
</t>
<div style="position: relative; z-index: 1;">
<div class="oe_structure"/>
<!-- Greeting / intro -->
<div style="text-align: right; margin-bottom: 20px; padding-top: 300px;">
<div style="font-size: 1.5rem; color: #6B6B6A; font-weight: bold;">
مرحباً
<span style="color: #387F75;" t-esc="doc.sponsor_id.name or 'فاعل خير'"/>
</div>
<div style="font-size: 1.5rem; margin-top: 10px; color: #6B6B6A;">
بكل امتنان نشكر لك تبرعك الكريم، ونسأل الله أن يجعلك ممن يرافقون النبي ﷺ في الجنة.
</div>
<div style="font-size: 1.5rem; color: #6B6B6A;">
ونتشرف دائما باستقبال عطائك المستمر لدعم أبنائكم الأيتام.
</div>
</div>
<!-- Sponsorship info -->
<div style="text-align: right; margin-bottom: 20px;">
<span style="font-size: 1.5rem; color: #8F9090;">
[رقم الكفالة:
<t t-esc="doc.code"/>
]
</span>
<span style="font-size: 1.5rem; color: #8F9090;">
(
<t t-esc="doc.sponsorship_creation_date"
t-options='{"widget": "date", "format": "dd MMMM yyyy"}'/>
)
</span>
</div>
<!-- Lines table -->
<table class="table table-bordered" style="text-align: right;">
<thead>
<tr style="background-color: white;">
<th style="text-align: right; width: 50%; font-size: 1.5rem; padding: 8px; color: #6B6B6A; font-weight: bold;">
نوع التبرع
</th>
<th style="text-align: center; width: 25%; font-size: 1.5rem; padding: 8px; color: #6B6B6A; font-weight: bold;">
الكمية
</th>
<th style="text-align: center; width: 25%; font-size: 1.5rem; padding: 8px; color: #6B6B6A; font-weight: bold;">
المبلغ
</th>
</tr>
</thead>
<tbody>
<t t-set="lines_to_report" t-value="doc.donations_details_lines"/>
<t t-foreach="lines_to_report" t-as="line">
<t t-if="not line.display_type">
<tr>
<td style="text-align: right; padding: 8px; font-size: 1.5rem; color: #387F75; font-weight: bold;">
<span t-esc="line.product_template_id.name"/>
</td>
<td style="text-align: center; padding: 8px; font-size: 1.5rem; color: #387F75; font-weight: bold;">
<span t-esc="line.donation_qty"
t-options='{"widget": "integer"}'/>
</td>
<td style="text-align: center; padding: 8px; font-size: 1.5rem; color: #387F75; font-weight: bold;">
<span t-esc="line.donation_amount"/>
</td>
</tr>
</t>
</t>
<!-- Summary Row: المجموع -->
<tr>
<td style="text-align: right; padding: 8px; font-size: 1.5rem; color: #6B6B6A; font-weight: bold;">
<strong>المجموع:</strong>
</td>
<td style="text-align: center; padding: 8px;font-size: 1.5rem; color: #387F75; font-weight: bold;">
<strong>
<span t-esc="sum(line.donation_qty for line in lines_to_report if not line.display_type)"/>
</strong>
</td>
<td style="text-align: center; padding: 8px; font-size: 1.5rem; color: #387F75; font-weight: bold;">
<strong>
<span t-esc="doc.total_sponsorship_amount"/>
</strong>
</td>
</tr>
<!-- Payment Method Row: وسيلة الدفع -->
<tr>
<td style="text-align: right; padding: 8px; font-size: 1.5rem; color: #6B6B6A; font-weight: bold;"
colspan="2">
<strong>
<span style="margin-left: 10px;">وسيلة الدفع:</span>
</strong>
</td>
<td style="text-align: center; padding: 8px; font-size: 1.5rem; color: #387F75; font-weight: bold;">
<t t-if="doc.payment_details_lines">
<span t-esc="doc.payment_details_lines[0].payment_method_id.name or doc.payment_details_lines[0].payment_method"/>
</t>
<t t-else="">
<span>غير محدد</span>
</t>
</td>
</tr>
<!-- Total row (same as المجموع but using amount_total if needed in future) -->
<tr>
<td style="text-align: right; padding: 8px; font-size: 1.5rem; color: #6B6B6A; font-weight: bold;"
colspan="2">
<strong>
<span style="margin-left: 10px;">الإجمالي:</span>
</strong>
</td>
<td style="text-align: center; padding: 8px; font-size: 1.5rem; color: #387F75; font-weight: bold;">
<span t-esc="doc.total_sponsorship_amount"/>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</t>
</t>
</t>
</template>
</odoo>

View File

@ -0,0 +1,16 @@
<odoo>
<record id="action_report_transfer_deduction_pdf" model="ir.actions.report">
<field name="name">Transfer and Deduction Report (PDF)</field>
<field name="model">transfer.deduction.wizard</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">odex_takaful.report_transfer_deduction_document</field>
<field name="report_file">odex_takaful.report_transfer_deduction_document</field>
<field name="print_report_name">
(object.sponsorship_creation_date and ('Transfer Deduction Report - %s' %
(object.sponsorship_creation_date.strftime('%Y-%m-%d'))) or 'Transfer Deduction Report')
</field>
<field name="paperformat_id"
ref="odex_takaful.paperformat_transfer_deduction_landscape"/> <!-- Add this line -->
<field name="binding_model_id" eval="False"/>
</record>
</odoo>

View File

@ -55,3 +55,7 @@ access_group_kufula_user_account_move,access_group_kufula_user_account_move,acco
access_group_kufula_user_sale_order,access_group_kufula_user_sale_order,sale.model_sale_order,odex_takaful.group_kufula_user,1,1,1,0
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
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
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

1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
55
56
57
58
59
60
61

View File

@ -220,11 +220,13 @@
<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="domain_force">[(1,'=',1)]</field>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="1"/>
@ -299,7 +301,9 @@
<field name="model_id" ref="hr.model_hr_employee"/>
<field name="groups" eval="[(4, ref('donation_officer_group'))]"/>
<!-- <field name="domain_force">[(1, '=', 1)]</field>-->
<field name="domain_force">['|', '|', ('user_id','=',user.id), ('department_id.manager_id.user_id','=', user.id), ('parent_id.user_id','=', user.id)]</field>
<field name="domain_force">['|', '|', ('user_id','=',user.id), ('department_id.manager_id.user_id','=',
user.id), ('parent_id.user_id','=', user.id)]
</field>
<field name="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="0"/>

View File

@ -1,16 +1,27 @@
<odoo>
<!-- Inherit form account move view -->
<record id="takaful_account_move_inherit_form" model="ir.ui.view">
<field name="name">takaful.account.move.inherit.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_origin']" position="attributes">
<attribute name="attrs">{'invisible': False}</attribute>
<record id="takaful_account_move_inherit_form" model="ir.ui.view">
<field name="name">takaful.account.move.inherit.form</field>
<field name="model">account.move</field>
<field name="inherit_id" ref="account.view_move_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='invoice_origin']" position="attributes">
<attribute name="attrs">{'invisible': False}</attribute>
</xpath>
</xpath>
<xpath expr="//field[@name='invoice_origin']" position="after">
<field name="esterdad_id" invisible="1"/>
</xpath>
<xpath expr="//div[hasclass('oe_button_box')]" position="inside">
<button name="action_view_esterdad_id" type="object" class="oe_stat_button" icon="fa-money"
attrs="{'invisible': [('esterdad_id', '=', False)]}">
</button>
</xpath>
</field>
</field>
</record>
</odoo>
</odoo>

View File

@ -33,8 +33,10 @@
<filter string="With Conditions" name="filter_with_conditions" domain="[('donation_mechanism', '=', 'with_conditions')]"/>
<filter string="Without Conditions" name="filter_without_conditions" domain="[('donation_mechanism', '=', 'without_conditions')]"/>
<separator/>
<filter string="Without Beneficiary" name="filter_no_benefit" domain="[('benefit_id', '=', False), ('donation_type', '=', 'sponsorship')]"/>
<filter string="With Beneficiary" name="filter_with_benefit" domain="[('benefit_id', '!=', False), ('donation_type', '=', 'sponsorship')]"/>
<filter string="My Documents" name="filter_my_documents" domain="[('create_uid', '=', uid)]"/>
<separator/>
<group expand="0" string="Group By">
<filter string="State" name="group_state" context="{'group_by': 'state'}"/>
@ -147,7 +149,7 @@
type="object"
class="btn-primary"
icon="fa-plus-circle"
attrs="{'invisible': [('show_add_benefit_button', '=', False)]}"
attrs="{'invisible': ['|' , ('show_add_benefit_button', '=', False) , ('can_edit_benefit', '=', False)]}"
groups="odex_takaful.group_kufula_user" />
<field name="state" widget="statusbar"
@ -186,14 +188,14 @@
<field name="donation_type" invisible="1"/>
<field name="donation_types"
attrs="{'invisible': [('donation_type', '!=', 'donation')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="product_template_id"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}"
<field name="product_template_id"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
<field name="product_id" invisible="1" />
<field name="donation_mechanism" invisible="1" />
<field name="fixed_value" invisible="1" />
<field name="currency_id" invisible="1"/>
<field name="donation_amount" widget="monetary"
<field name="donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="total_donation_amount" widget="monetary"
@ -201,15 +203,16 @@
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
</group>
<group string="Sponsorship Information">
<field name="sponsorship_id" readonly="1"
<field name="can_edit_benefit" invisible="0"/>
<field name="sponsorship_id" readonly="1"
attrs="{'invisible': [('sponsorship_id', '=', False)]}" />
<field name="sponsorship_mechanism_id" readonly="1"
<field name="sponsorship_mechanism_id" readonly="1"
attrs="{'invisible': [('sponsorship_mechanism_id', '=', False)]}" />
<field name="sponsor_id"
<field name="sponsor_id"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="sponsor_phone" widget="phone"
<field name="sponsor_phone" widget="phone"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="branch_custom_id"
<field name="branch_custom_id"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="sponsorship_creation_date" invisible="1" />
<field name="parent_state" invisible="1" />
@ -455,7 +458,7 @@
<field name="res_model">donations.details.lines</field>
<field name="view_mode">tree,form</field>
<field name="search_view_id" ref="donations_details_lines_view_search"/>
<field name="context">{'create': False, 'delete': False}</field>
<field name="context">{'create': False ,'search_default_filter_my_documents': 1, 'delete': False}</field>
</record>
<record id="donations_details_lines_waiting_action" model="ir.actions.act_window">
@ -467,7 +470,7 @@
<field name="view_ids" eval="[(5, 0, 0),
(0, 0, {'view_mode': 'tree', 'view_id': ref('donations_details_lines_view_tree_waiting')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('donations_details_lines_view_form')})]"/>
<field name="context">{'create': False, 'delete': False}</field>
<field name="context">{'create': False,'search_default_filter_my_documents': 1, 'delete': False}</field>
</record>
<record id="donations_details_lines_replace_action" model="ir.actions.act_window">
@ -479,7 +482,7 @@
(0, 0, {'view_mode': 'tree', 'view_id': ref('donations_details_lines_view_tree_replace')}),
(0, 0, {'view_mode': 'form', 'view_id': ref('donations_details_lines_view_form')})]"/>
<field name="search_view_id" ref="donations_details_lines_view_search"/>
<field name="context">{'create': False, 'delete': False}</field>
<field name="context">{'create': False,'search_default_filter_my_documents': 1, 'delete': False}</field>
</record>
</odoo>

View File

@ -32,5 +32,16 @@
file ="odex_takaful.kafalat_cancel_report_pdf"
menu="False" />
<!-- Sponsorship receipt report directly on takaful.sponsorship -->
<report
id="takaful_sponsorship_receipt_report"
model="takaful.sponsorship"
string="Sponsorship Receipt"
report_type="qweb-pdf"
name="odex_takaful.report_sponsorship_receipt_document"
file="odex_takaful.report_sponsorship_receipt_document"
print_report_name="(object.code and ('Sponsorship Receipt - %s' % (object.code,))) or 'Sponsorship Receipt'"
/>
</data>
</odoo>

View File

@ -56,10 +56,17 @@
<button name="action_refund" type="object"
string="Refund All" class="oe_highlight"
attrs="{'invisible': ['|','|',('state','not in',['paid','partial_refund','under_replacement','replacement_done']),('record_type','!=','donation'), ('cancel_refund', '=', True)]}"/>
<button name="action_set_esterdad" type="object"
string="طلب الاسترداد" class="oe_highlight"
attrs="{'invisible': ['|','|',('state','not in',['paid','partial_refund','under_replacement','replacement_done']),('record_type','!=','donation'), ('cancel_refund', '=', True)]}"/>
<button string="Approve Refund" name="approve_refund" type="object"
class="oe_highlight"
attrs="{'invisible': [ '|', ('record_type', '!=', 'donation'), ('state', '!=', 'approve_refund')]}"
groups="odex_takaful.group_refund_approval"/>
<button string="Send By Email" name="action_quotation_send" type="object"
class="oe_highlight" attrs="{'invisible': [ ('state', '=', 'draft')]}"
groups="odex_takaful.group_refund_approval"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,confirmed,wait_pay,paid,canceled,closed"/>
</header>
@ -74,6 +81,10 @@
attrs="{'invisible': ['|', ('record_type','!=','donation'), ('donation_mechanism','!=','with_conditions')]}">
<field name="journal_entry_count_vendor" string="Vendor Invoices" widget="statinfo"/>
</button>
<button name="action_view_esterdad_id" type="object" class="oe_stat_button" icon="fa-money"
attrs="{'invisible': [('state', '!=', 'canceled')]}">
<span>Canceled</span>
</button>
<button name="action_view_refund_moves" type="object"
class="oe_stat_button" icon="fa-money">
<field name="refund_move_count" string="Refund Invoices"
@ -83,7 +94,7 @@
<!-- string="Replacement Processes" class="oe_stat_button" icon="fa-users">-->
<!-- </button>-->
</div>
<widget name="web_ribbon" title="Canceld" bg_color="bg-danger" attrs="{'invisible': [('state', '!=', 'canceled')]}"/>
<!-- Code badge hidden for now -->
<!-- <div style="position: absolute; top: 70px; right: 15px; z-index: 100;" attrs="{'invisible': [('code', '=', False)]}">
<span class="badge badge-info" style="font-size: 14px; padding: 6px 12px;">
@ -218,6 +229,7 @@
options="{'no_create': True, 'no_create_edit': True}"/>
</group>
<group name="group_right" string="Basic Information">
<field name="is_widow_orphan" invisible="1"/>
<field name="cancel_refund" invisible="1"/>

View File

@ -10,3 +10,4 @@ from . import donation_extension_wizard
from . import replace_sponsor_wizard
from . import add_benefit_wizard
from . import account_payment_register
from . import esterdad

View File

@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError, Warning
import logging
from odoo import SUPERUSER_ID
from datetime import datetime, date
_logger = logging.getLogger(__name__)
class EsterdadWizard(models.Model):
_name = "esterdad.wizard"
amount = fields.Monetary(currency_field='currency_id', compute='_get_total_sponsorship_amount')
currency_id = fields.Many2one(
'res.currency',
string="Currency",
required=True,
default=lambda self: self.env.company.currency_id
)
cancel_date = fields.Date()
pay_date = fields.Datetime(related='sponsor_id.pay_date')
cancel_reason = fields.Many2one('sponsorship.reason.stop' , required = True)
another_reason = fields.Boolean()
reason = fields.Text()
sponsor_id = fields.Many2one('takaful.sponsorship')
sponsor_name = fields.Char()
mobile = fields.Char()
id_num = fields.Char()
payment_ids = fields.Many2many('account.payment')
confirmed = fields.Boolean()
def action_confirm_refund(self):
for rec in self:
user = rec.sponsor_id.sponsor_id.kafel_id
if user:
user.generate_otp()
context = dict(self.env.context or {})
context['default_user_id'] = user.id
context['default_otp'] = user.otp_code
context['default_esterdad_id'] = rec.id
rec.sponsor_id.write({
'cancel_record_id': rec.id
})
view = self.env.ref('odex_takaful.view_otp_wizard_form')
return {
'name': _('OTP Confirmation'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'otp.confirmation.wizard',
'view_id': view.id,
'target': 'new',
'context': context,
}
else:
raise UserError("لا يوجد مستخدم مخصص لهذا الكفيل")
@api.depends('sponsor_id.donations_details_lines', 'sponsor_id.donations_details_lines_mechanism_ids')
def _get_total_sponsorship_amount(self):
for rec in self:
if rec.sponsor_id:
rec.amount = (
sum(line.total_donation_amount for line in rec.sponsor_id.donations_details_lines) +
sum(line.total_donation_amount for line in rec.sponsor_id.donations_details_lines_mechanism_ids)
)
class OTPWizard(models.TransientModel):
_name = "otp.confirmation.wizard"
otp = fields.Integer()
otp_code = fields.Integer()
esterdad_id = fields.Many2one('esterdad.wizard')
user_id = fields.Many2one('res.users')
def action_confirm_otp(self):
for rec in self:
if rec.otp == rec.otp_code:
sponsor_ship = rec.esterdad_id.sponsor_id
rec.esterdad_id.cancel_date = date.today()
if sponsor_ship:
credit = self.env['account.move.reversal'].with_company(self.env.user.company_id.id).create({
'refund_method': 'refund',
'date': date.today(),
'date_mode': 'custom',
'move_ids': sponsor_ship.journal_entry_ids.ids,
})
x = credit.reverse_moves()
sponsor_ship.state = 'canceled'
domain_ids = x.get('domain')[0][2]
last_id = domain_ids[-1]
sponsor_ship.write({
'journal_entry_ids': [(4, last_id)]
})
credit_note = self.env['account.move'].search([('id' , '=' , last_id)])
credit_note.action_post()
rec.esterdad_id.confirmed = True
else:
raise UserError("الرقم المدخل خاطئ")

View File

@ -0,0 +1,89 @@
<odoo>
<record id="view_esterdad_wizard_tree" model="ir.ui.view">
<field name="name">esterdad.wizard.tree</field>
<field name="model">esterdad.wizard</field>
<field name="arch" type="xml">
<tree string="Esterdad Wizard" create="0" edit="0">
<field name="amount"/>
<field name="cancel_date"/>
<field name="pay_date"/>
<field name="cancel_reason"/>
<field name="another_reason"/>
<field name="reason"/>
</tree>
</field>
</record>
<record id="view_esterdad_wizard_form" model="ir.ui.view">
<field name="name">esterdad.wizard.form</field>
<field name="model">esterdad.wizard</field>
<field name="arch" type="xml">
<form string="Esterdad Wizard" create="0" edit="0">
<group>
<field name="amount"/>
<field name="currency_id" invisible="1"/>
<field name="cancel_date" readonly="1"/>
<field name="pay_date" readonly="1"/>
<field name="cancel_reason"/>
<field name="another_reason"/>
<field name="reason" attrs="{'invisible': [('another_reason', '=', False)]}"/>
</group>
<notebook>
<page string="بيانات المتبرع">
<group>
<field name="sponsor_name"/>
<field name="mobile"/>
<field name="id_num"/>
</group>
</page>
<page string="Payment Details" groups="odex_takaful.group_refund_approval">
<field name="payment_ids">
<tree editable="1">
<field name="date" readonly="1"/>
<field name="name" readonly="1"/>
<field name="journal_id" readonly="1"/>
<field name="payment_method_line_id" readonly="1"/>
<field name="amount" sum="Amount"
readonly="1"/>
<field name="state" readonly="1"/>
<field name="currency_id" groups="base.group_multi_currency"/>
<field name="confirm_payment_refund"
attrs="{'readonly': [('payment_method_line_id_type', '=', 'cash')]}"/>
<field name="IBN_number"
attrs="{'readonly': [('payment_method_line_id_type', '=', 'cash')]}"/>
<field name="confirm_payment_refund_image"
attrs="{'readonly': [('payment_method_line_id_type', '=', 'cash')]}"/>
<field name="payment_method_line_id_type"/>
</tree>
</field>
</page>
</notebook>
</form>
<footer>
<button string="Cancel"
class="btn-secondary"
special="cancel"
attrs="{'invisible': [('confirmed', '=', True)]}"
/>
<button name="action_confirm_refund"
string="Confirm"
type="object"
attrs="{'invisible': [('confirmed', '=', True)]}"
class="btn-primary"/>
</footer>
</field>
</record>
<record id="action_esterdad_wizard" model="ir.actions.act_window">
<field name="name">Esterdad Wizard</field>
<field name="res_model">esterdad.wizard</field>
<field name="view_mode">tree,form</field>
<field name="context">{'create': False, 'edit': False}</field>
</record>
</odoo>

View File

@ -0,0 +1,34 @@
<odoo>
<!-- Form View -->
<record id="view_otp_wizard_form" model="ir.ui.view">
<field name="name">otp.confirmation.wizard.form</field>
<field name="model">otp.confirmation.wizard</field>
<field name="arch" type="xml">
<form string="OTP Confirmation Wizard">
<group>
<field name="otp_code"/>
<field name="otp" invisible="1"/>
<field name="esterdad_id" invisible="1"/>
</group>
<footer>
<button string="Cancel"
class="btn-secondary"
special="cancel"/>
<button name="action_confirm_otp"
string="Confirm"
type="object"
class="btn-primary"/>
</footer>
</form>
</field>
</record>
<!-- Action -->
<record id="action_otp_wizard" model="ir.actions.act_window">
<field name="name">OTP Confirmation Wizard</field>
<field name="res_model">otp.confirmation.wizard</field>
<field name="view_mode">tree,form</field>
<field name="target">new</field>
</record>
</odoo>