Merge pull request #5507 from expsa/you_dev_odex25_takaful

[ADD] odex25_takaful: Add new branch
This commit is contained in:
kchyounes19 2025-11-25 08:39:42 +01:00 committed by GitHub
commit e719062e8e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
903 changed files with 290951 additions and 0 deletions

View File

@ -0,0 +1 @@
from . import models

View File

@ -0,0 +1,18 @@
{
'name': 'Ensan Sale Management Takaful',
'version': '1.0',
'description': 'Bridging Takaful and Sale Management',
'summary': 'Bridging Takaful and Sale Management',
'author': 'Expert Co. Ltd.',
'website': 'http://www.exp-sa.com',
'license': 'LGPL-3',
'category': 'Odex25-Ens',
'depends': [
'ensan_sale_management',
'odex_takaful',
],
'data': [
'views/product_template_views.xml',
],
'auto_install': True,
}

View File

@ -0,0 +1 @@
from . import product

View File

@ -0,0 +1,8 @@
from odoo import models
class ProductTemplate(models.Model):
_inherit = 'product.template'
def _compute_fixed_value(self):
for rec in self:
rec.fixed_value = rec.donation_type == 'Fixed Amount'

View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="product_template_inherit_form">
<field name="name">product.template.form.inherit</field>
<field name="model">product.template</field>
<field name="inherit_id" ref="ensan_sale_management.product_template_inherit_form"/>
<field name="arch" type="xml">
<field name="donation_type" position="after">
<field name="donation_category" />
<field name="sponsorship_duration" attrs="{'invisible': [('donation_category','!=','sponsorship')], 'required': [('donation_category','=','sponsorship')]}" />
</field>
</field>
</record>
</odoo>

View File

@ -0,0 +1,354 @@
# مراجعة شاملة لموديول Odex Takaful System
## نظرة عامة
**اسم الموديول:** Odex Takaful System
**الإصدار:** 11.0
**الفئة:** Odex25-Takaful/Odex25-Takaful
**المؤلف:** Expert Co. Ltd.
**الموقع:** http://www.exp-sa.com
**الملخص:** موديول لإدارة نظام التكافل (الكفالة والمساهمات والتبرعات)
## الاعتماديات (Dependencies)
- `base`
- `takaful_core`
- `odex_takaful_base`
- `odex_benefit`
- `account`
- `phone_validation`
## الهيكل العام للموديول
### 1. النماذج (Models) - 26 ملف
#### النماذج الرئيسية:
1. **`takaful.sponsorship`** - نموذج الكفالة الرئيسي
- إدارة الكفالات (أيتام/أرامل)
- أنواع الكفالة: فردية/جماعية، مؤقتة/دائمة
- حالات الكفالة: draft, confirmed, wait_pay, paid, canceled, closed, etc.
- إدارة المدفوعات والاسترداد
- ربط مع الحسابات المالية
2. **`donations.details.lines`** - تفاصيل التبرعات والكفالات
- إدارة بنود التبرعات والكفالات
- دعم التبرعات المباشرة (Direct Debit)
- جدولة المدفوعات الشهرية
- إدارة الاستبدال والتمديد
3. **`payment.details.lines`** - تفاصيل المدفوعات
- تسجيل المدفوعات
- ربط مع الحسابات المالية
- دعم طرق الدفع المختلفة (نقد، تحويل بنكي، سحب مباشر)
4. **`sponsorship.scheduling.line`** - جدولة المدفوعات
- جدولة المدفوعات الشهرية
- معالجة المدفوعات التلقائية
- تتبع حالة كل دفعة
5. **`month.payment`** - المدفوعات الشهرية للمستفيدين
- تجميع المدفوعات الشهرية
- إنشاء قيود مالية للمستفيدين
6. **`takaful.sponsor.operation`** - عمليات الكافل
- تتبع عمليات الكافل (كفالة، مساهمة، هدية)
7. **`sponsorship.payment`** - مدفوعات الكفالة
- إدارة مدفوعات الكفالة
- ربط مع الفواتير
8. **`sponsorship.cancellation`** - إلغاء الكفالة
- إدارة عمليات الإلغاء
- حساب المتأخرات
9. **`replacement.process`** - عملية الاستبدال
- استبدال المستفيدين
- تتبع عمليات الاستبدال
10. **`takaful.contribution`** - المساهمات المالية
- إدارة المساهمات المالية
- ربط مع الحاجات
11. **`takaful.grant.benefit`** - تمديد نموذج المستفيدين
- حساب قيمة الكفالة
- تتبع الكفالات النشطة
12. **`takaful.push.notification`** - الإشعارات
- إرسال الإشعارات (SMS, Email, WhatsApp)
13. **`takaful.notification`** - إعدادات الإشعارات
- أنواع الإشعارات المختلفة
- ربط مع حالات الكفالة
14. **`takaful.payment.method`** - طرق الدفع
- إدارة طرق الدفع المختلفة
15. **`donation.extension.history`** - سجل التمديدات
- تتبع تمديدات التبرعات
16. **`donation.replacement.log`** - سجل الاستبدالات
- تتبع استبدالات المستفيدين
17. **`refund.details.lines`** - تفاصيل الاسترداد
- إدارة عمليات الاسترداد
18. **`sponsorship.benefit.arrears`** - المتأخرات
- حساب المتأخرات للمستفيدين
#### النماذج المساعدة:
- `replacement.reasons` - أسباب الاستبدال
- `sponsorship.reason.stop` - أسباب إيقاف الكفالة
- `refund.reasons` - أسباب الاسترداد
- `sponsorship.states` - حالات الكفالة
- `preferred.communication` - طرق التواصل المفضلة
- `takaful.conf` - إعدادات التكافل
- `donations.items` - عناصر التبرعات
- `points.of.sale.custom` - نقاط البيع
### 2. الويزاردات (Wizards) - 10 ملفات
1. **`account.payment.register`** - تسجيل المدفوعات
2. **`add.details.wiz`** - إضافة التفاصيل
3. **`benefit.month.payment.wiz`** - مدفوعات المستفيدين الشهرية
4. **`donation.extension.wizard`** - تمديد التبرعات
5. **`orphan.replacement.wizard`** - استبدال الأيتام
6. **`refund.wiz`** - استرداد المدفوعات
7. **`replace.sponsor.wizard`** - استبدال الكافل
8. **`takaful.reports.wizards`** - تقارير التكافل
9. **`transfer.deduction.wizard`** - تحويل الخصومات
### 3. التقارير (Reports) - 7 ملفات
1. **`month_payment_report.py`** - تقرير المدفوعات الشهرية
2. **`payment_details_lines_reports.xml`** - تقارير تفاصيل المدفوعات
3. **`takaful_reports.py`** - تقارير التكافل العامة
4. **`transfer_deduction_report.xml`** - تقرير تحويل الخصومات
### 4. البيانات (Data) - 7 ملفات
1. **`sequence_data.xml`** - التسلسلات
2. **`scheduled_actions.xml`** - الإجراءات المجدولة
3. **`takaful_notification_mail_template.xml`** - قوالب البريد الإلكتروني
4. **`sponsorship_states_data.xml`** - حالات الكفالة
5. **`sponsorship_notification_data.xml`** - إعدادات الإشعارات
6. **`message_template_data.xml`** - قوالب الرسائل
7. **`server_actions.xml`** - إجراءات الخادم
### 5. الأمان (Security)
- **`security_data.xml`** - مجموعات الأمان
- **`ir.model.access.csv`** - صلاحيات الوصول
### 6. الواجهات (Views) - 33 ملف
- واجهات الكفالات
- واجهات المدفوعات
- واجهات التبرعات
- واجهات التقارير
- واجهات الإشعارات
### 7. الإجراءات المجدولة (Scheduled Actions)
1. **فحص تاريخ انتهاء الكفالة وإرسال رسائل WhatsApp**
- التكرار: يومي
- الوقت: 04:00
2. **إدارة سير عمل الكفالة يومياً**
- التكرار: يومي
- الوقت: 04:00
3. **إنشاء فواتير الكفالات شهرياً**
- التكرار: شهري
- الوقت: 02:00 في اليوم الأول من الشهر
4. **معالجة المدفوعات المجدولة يومياً**
- التكرار: يومي
- الوقت: 03:00
5. **إرسال تذكيرات SMS لانتهاء السحب المباشر**
- التكرار: يومي
- الوقت: 05:00
## الوظائف الرئيسية
### 1. إدارة الكفالات
#### إنشاء كفالة جديدة:
- اختيار الكافل (مسجل، جديد، غير معروف)
- اختيار المستفيد (فردي/جماعي)
- اختيار نوع المستفيد (أيتام/أرامل)
- تحديد مدة الكفالة (مؤقتة/دائمة)
- إضافة بنود التبرعات/الكفالات
- تحديد طريقة الدفع
#### حالات الكفالة:
- **draft**: مسودة
- **confirmed**: مؤكدة
- **wait_pay**: انتظار الدفع
- **paid**: مدفوعة
- **partial_refund**: استرداد جزئي
- **fully_refund**: استرداد كامل
- **approve_refund**: موافقة على الاسترداد
- **under_refund**: تحت إجراءات الاسترداد
- **under_replacement**: تحت الاستبدال
- **replacement_done**: تم الاستبدال
- **canceled**: ملغاة
- **closed**: مغلقة
### 2. إدارة المدفوعات
#### أنواع المدفوعات:
- نقد (Cash)
- بطاقة (Card)
- شيك (Check)
- تحويل بنكي (Bank Transfer)
- سحب مباشر (Direct Debit)
#### تسجيل المدفوعات:
- ربط مع الفواتير
- إنشاء قيود مالية تلقائياً
- تتبع حالة الدفع
### 3. جدولة المدفوعات
- جدولة المدفوعات الشهرية للكفالات المؤقتة
- معالجة تلقائية للمدفوعات المجدولة
- تتبع حالة كل دفعة
### 4. الاستبدال
- استبدال المستفيدين
- تتبع عمليات الاستبدال
- إرسال إشعارات للكافل
### 5. التمديد
- تمديد التبرعات/الكفالات
- تتبع تاريخ التمديدات
- إرسال تذكيرات قبل الانتهاء
### 6. الاسترداد
- استرداد كامل أو جزئي
- إنشاء فواتير استرداد
- تتبع عمليات الاسترداد
### 7. الإشعارات
#### أنواع الإشعارات:
- إنشاء كفالة
- قبل انتهاء الكفالة
- بعد انتهاء الكفالة
- إلغاء الكفالة
- استرداد كامل/جزئي
- استبدال يتيم/أرملة
- دفع كامل/جزئي
- قبل الإلغاء
#### قنوات الإشعارات:
- SMS
- Email
- WhatsApp (عبر Twilio)
- Push Notifications
### 8. التقارير
- تقارير المدفوعات الشهرية
- تقارير تفاصيل المدفوعات
- تقارير التكافل العامة
- تقارير تحويل الخصومات
## التكامل مع الموديولات الأخرى
### 1. odex_benefit
- ربط مع المستفيدين (family.member)
- ربط مع العائلات (grant.benefit)
- استخدام حالات المستفيدين
### 2. account
- إنشاء الفواتير تلقائياً
- إنشاء قيود المدفوعات
- ربط مع الحسابات المالية
### 3. takaful_core
- استخدام الإعدادات الأساسية
- استخدام الحسابات المالية
### 4. odex_takaful_base
- استخدام الإعدادات الأساسية
- استخدام الإشعارات
## البيانات في النظام
بناءً على فحص البيانات في Odoo:
- **الكفالات (takaful.sponsorship):** 0 سجل
- **تفاصيل التبرعات (donations.details.lines):** 0 سجل
- **تفاصيل المدفوعات (payment.details.lines):** 197 سجل
- **المدفوعات الشهرية (month.payment):** 0 سجل
- **جدولة المدفوعات (sponsorship.scheduling.line):** 0 سجل
## الميزات المتقدمة
### 1. السحب المباشر (Direct Debit)
- جدولة المدفوعات الشهرية تلقائياً
- معالجة المدفوعات في التاريخ المحدد
- إرسال تذكيرات قبل الانتهاء
### 2. آلية التبرع
- **مع شروط (With Conditions):** ربط مع مستفيدين محددين
- **بدون شروط (Without Conditions):** تبرع عام
### 3. حساب المتأخرات
- حساب المتأخرات تلقائياً
- إرسال إشعارات للمتأخرات
- إلغاء تلقائي بعد فترة محددة
### 4. الاستبدال التلقائي
- استبدال تلقائي عند تغيير حالة المستفيد
- إرسال إشعارات للكافل
### 5. التكامل مع Twilio
- إرسال رسائل WhatsApp
- إرسال SMS
- استخدام قوالب الرسائل
## الأمان والصلاحيات
### مجموعات الأمان:
- `group_kufula_user` - مستخدم التكافل
- `group_donations_coordinator` - منسق التبرعات
- `group_sponsorship_coordinator` - منسق الكفالات
- `group_orphan_replacement` - استبدال الأيتام
- `group_replace_sponsor` - استبدال الكافل
- `donation_officer_group` - موظف التبرعات
- `sponsorship_officer_group` - موظف الكفالات
## نقاط القوة
1. **شمولية النظام:** يغطي جميع جوانب إدارة الكفالات والتبرعات
2. **التكامل الجيد:** تكامل ممتاز مع الموديولات الأخرى
3. **الإشعارات المتقدمة:** دعم قنوات إشعارات متعددة
4. **الأتمتة:** معالجة تلقائية للعديد من العمليات
5. **المرونة:** دعم أنواع مختلفة من الكفالات والتبرعات
6. **التقارير:** تقارير شاملة للعمليات
## نقاط التحسين المحتملة
1. **الأداء:** قد يحتاج تحسين للأداء مع كمية كبيرة من البيانات
2. **التوثيق:** يمكن تحسين التوثيق الداخلي للكود
3. **الاختبارات:** إضافة المزيد من الاختبارات الآلية
4. **التعليقات:** بعض الأكواد تحتاج تعليقات أوضح
5. **معالجة الأخطاء:** تحسين معالجة الأخطاء في بعض الأماكن
## الخلاصة
موديول **Odex Takaful System** هو نظام شامل ومتكامل لإدارة الكفالات والتبرعات. يوفر ميزات متقدمة مثل السحب المباشر، الاستبدال التلقائي، والإشعارات المتعددة القنوات. النظام متكامل جيداً مع الموديولات الأخرى ويوفر واجهات سهلة الاستخدام.
النظام جاهز للاستخدام في بيئة الإنتاج مع بعض التحسينات المحتملة للأداء والتوثيق.
---
**تاريخ المراجعة:** 2025-01-27
**المراجع:** AI Assistant

View File

@ -0,0 +1,6 @@
from . import models
from . import controllers
from . import reports
from . import wizards

View File

@ -0,0 +1,84 @@
{
'name': 'Odex Takaful System',
'version': '11.0',
'category': 'Odex25-Takaful/Odex25-Takaful',
'author': "Expert Co. Ltd.",
'website': "http://www.exp-sa.com",
'summary': 'This module for Takaful project',
'depends': [
'base',
'takaful_core',
'odex_takaful_base',
'odex_benefit',
'account',
'phone_validation',
# 'analytic_account',
],
'data': [
'security/security_data.xml',
'security/ir.model.access.csv',
'data/sequence_data.xml',
'data/scheduled_actions.xml',
'data/takaful_notification_mail_template.xml',
'data/sponsorship_states_data.xml',
'data/sponsorship_notification_data.xml',
'views/takaful_sponsor_view.xml',
'views/takaful_sponsor_operation_views.xml',
'reports/payment_details_lines_reports.xml',
'views/assets.xml',
'views/res_config_settings.xml',
'wizards/orphan_replacement_wizard.xml',
'views/takaful_sponorship_view.xml',
'views/donation_item_views.xml',
'views/replacement_reasons_views.xml',
'views/replacement_process_views.xml',
'views/benefit_views.xml',
'views/family_member.xml',
'views/takaful_contribution_view.xml',
'views/sponsorship_payment_view.xml',
'views/sponsorship_cancellation_view.xml',
'views/payment_details_lines_views.xml',
'wizards/account_payment_register.xml',
'views/res_partner_bank.xml',
'views/res_users_inherit.xml',
'views/takaful_push_notification_view.xml',
'views/takaful_grant_benefit_view.xml',
'views/takaful_month_payment_view.xml',
'wizards/benefit_month_payment_wiz_view.xml',
'views/takaful_conf.xml',
'views/sponsorship_states.xml',
'views/takaful_notification.xml',
'views/reports_paperformats.xml',
'views/reports_templates.xml',
'views/reports_actions.xml',
'reports/month_payment_template.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',
'views/donations_details_lines.xml',
'views/donation_extension_history_views.xml',
'views/donation_replacement_log_views.xml',
'views/sponsorship_scheduling_line.xml',
'views/takaful_menus_actions.xml',
'views/preferred_communication.xml',
'views/takaful_payment_method.xml',
'views/product_views.xml',
'data/message_template_data.xml',
'data/server_actions.xml',
'wizards/transfer_deduction_wizard_views.xml',
'reports/transfer_deduction_report.xml',
'reports/transfer_deduction_report_templates.xml',
],
'icon': 'static/description/icon.png',
# 'installable': True,
# 'application': True,
# 'auto_install': False,
}

View File

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

View File

@ -0,0 +1,34 @@
from odoo import http
import json
class QtyChangeSO(http.Controller):
@http.route(['/qtyupdatecart_so'], type='http', auth='user', website=True)
def QtyUpdateSO(self, **post):
# _sol_obj = http.request.env["takaful.sponsorship"]
# _sol_obj.user_input_qty_sol(
# float(post.get("quantity")), int(post.get("donation_name")), int(post.get("sponsorship_id")))
# return json.dumps({"message": True})
try:
env = http.request.env
sponsorship_model = env["takaful.sponsorship"].sudo()
# Support both 'donation_name' and 'product_id' parameters for backwards compatibility
product_id = int(post.get("donation_name") or post.get("product_id"))
quantity = float(post.get("quantity"))
sponsorship_id = int(post.get("sponsorship_id"))
sponsorship_model.user_input_qty_sol(quantity, product_id, sponsorship_id)
return json.dumps({"message": True})
except Exception as e:
# Return a structured error so the frontend can display/log details
return http.Response(
json.dumps({"message": False, "error": str(e)}),
status=500,
mimetype='application/json'
)
# @http.route(['/getuom_so'], type='http', auth='user', website=True)
# def UOMGetSO(self, **post):
# product = http.request.env['product.product'].search([('id', '=', post["product_id"])])
# uom_category = product.product_tmpl_id.uom_id.category_id.name
# return json.dumps({"uom_category": uom_category.lower()})

View File

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<!-- On Sponsorship Creation -->
<record model="takaful.message.template" id="sponsorship_creation_template">
<field name="title">إنشاء كفالة</field>
<field name="body">تم إنشاء كفالة</field>
<field name="template_name">sponsorship_creation</field>
</record>
<!-- On paid sponsorship -->
<record model="takaful.message.template" id="sponsorship_paid_template">
<field name="title">إشعار سداد</field>
<field name="body">تم سداد كفالة</field>
<field name="template_name">sponsorship_paid</field>
</record>
<!-- On canceled sponsorship -->
<record model="takaful.message.template" id="sponsorship_canceled_template">
<field name="title">إلغاء كفالة</field>
<field name="body">لقد تم إلغاء الكفالة</field>
<field name="template_name">sponsorship_canceled</field>
</record>
</data>
<data noupdate="1">
<!-- On Sponsorship About to cancel -->
<record model="takaful.message.template" id="sponsorship_to_cancel_template">
<field name="title">علي وشك الإلغاء</field>
<field name="body">الكفالة علي وشك الإلغاء</field>
<field name="template_name">sponsorship_to_cancel</field>
</record>
<!-- On Sponsorship Close -->
<record model="takaful.message.template" id="sponsorship_close_template">
<field name="title">إنهاء كفالة</field>
<field name="body">تم إنهاء الكفالة</field>
<field name="template_name">sponsorship_close</field>
</record>
<!-- On Sponsorship to Close -->
<record model="takaful.message.template" id="sponsorship_to_close_template">
<field name="title">علي وشك الإنتهاء</field>
<field name="body">الكفالة علي وشك النهاية</field>
<field name="template_name">sponsorship_to_close</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,95 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="0">
<!-- Scheduler for Check sponsorship End Date daily and Sending Whatsapp message before specific duration -->
<record id="scheduler_check_sponsorship_end_date_send_whatsapp_action" forcecreate='True' model="ir.cron">
<field name="name">Check Sponsorship End Date To Send Wahtsapp Message to Sponsor</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 04:00:00')"/>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model_id" ref="model_donations_details_lines"/>
<field name="code">model.run_check_all_end_dates()</field>
<field name="state">code</field>
<field name="priority" eval="2"/>
<field name="active" eval="True"/>
</record>
<!-- Scheduler for Managing Sponsorship Workflow Every Day -->
<record id="scheduler_sponsorship_workflow_action" forcecreate='True' model="ir.cron">
<field name="name">Daily Manage Sponsorship Workflow Scheduler</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 04:00:00')"/>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="code">model.process_sponsorship_workflow_scheduler()</field>
<field name="state">code</field>
<field name="priority" eval="5"/>
<field name="active" eval="True"/>
</record>
<!-- Scheduler for Creating Sponsorships Invoices once a month -->
<record id="scheduler_monthly_create_sponsorship_invoice_action" forcecreate='True' model="ir.cron">
<field name="name">Create Sponsorships Invoices Scheduler</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">months</field>
<field name="nextcall" eval="(DateTime.now() + timedelta(days=28)).strftime('%Y-%m-01 02:00:00')"/>
<field name="numbercall">-1</field>
<field name="doall" eval="True"/>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="state">code</field>
<field name="code">model.monthly_create_sponsorship_invoice_scheduler()</field>
<field name="priority" eval="1"/>
<field name="active" eval="True"/>
</record>
<!-- Scheduler for Processing Scheduled Payments Daily -->
<record id="scheduler_process_scheduled_payments_action" forcecreate='True' model="ir.cron">
<field name="name">Process Scheduled Payments Daily</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 03:00:00')"/>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model_id" ref="model_sponsorship_scheduling_line"/>
<field name="state">code</field>
<field name="code">model.with_context(from_cron=True).cron_process_scheduled_payments()</field>
<field name="priority" eval="3"/>
<field name="active" eval="True"/>
</record>
<!-- Scheduler for Sending SMS Reminders for Direct Debit End Dates -->
<record id="scheduler_direct_debit_end_date_reminders" forcecreate='True' model="ir.cron">
<field name="name">Send Direct Debit End Date Reminders</field>
<field name="user_id" ref="base.user_root"/>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="nextcall" eval="(DateTime.now() + timedelta(days=1)).strftime('%Y-%m-%d 05:00:00')"/>
<field name="numbercall">-1</field>
<field name="doall" eval="False"/>
<field name="model_id" ref="model_donations_details_lines"/>
<field name="state">code</field>
<field name="code">model.cron_send_direct_debit_end_date_reminders()</field>
<field name="priority" eval="4"/>
<field name="active" eval="True"/>
</record>
<record id="ir_cron_family_member_restriction" model="ir.cron">
<field name="name">Family Member Restriction</field>
<field name="model_id" ref="odex_benefit.model_family_member"/>
<field name="state">code</field>
<field name="code">model._cron_family_member_restriction()</field>
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field name="active">False</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,119 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record id="sequence_sponsorship" model="ir.sequence">
<field name="name">Sponsorship Sequence</field>
<field name="code">sponsorship.sequence</field>
<field name="prefix">SPSHIP/</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">4</field>
</record>
<record id="sequence_replacement_process" model="ir.sequence">
<field name="name">Replacement Process Sequence</field>
<field name="code">replacement.process.sequence</field>
<field name="prefix">OR-RE/</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">4</field>
</record>
<record id="sequence_sponsorship_orphan" model="ir.sequence">
<field name="name">Sponsorship Orphan Sequence</field>
<field name="code">sponsorship.orphan.sequence</field>
<!-- <field name="prefix">OR/</field> -->
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">1</field>
</record>
<record id="sequence_sponsorship_widow" model="ir.sequence">
<field name="name">Sponsorship Widow Sequence</field>
<field name="code">sponsorship.widow.sequence</field>
<!-- <field name="prefix">WI/</field> -->
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">1</field>
</record>
<record id="sequence_benefit_month_payment" model="ir.sequence">
<field name="name">Month Payment Sequence</field>
<field name="code">month.payment.sequence</field>
<field name="prefix">PAY/</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">4</field>
</record>
<record id="sequence_point_of_sales_custom" model="ir.sequence">
<field name="name">Point Of Sale Sequence</field>
<field name="code">point.of.sale.sequence</field>
<field name="prefix">PO/</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">4</field>
</record>
<record id="payment_details" model="ir.sequence">
<field name="name">Payment Details Sequence</field>
<field name="code">payment.details.sequence</field>
<field name="prefix">Payment/</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field eval="False" name="company_id"/>
<field name="padding">4</field>
</record>
<record id="donation_details_sequence" model="ir.sequence">
<field name="name">Donations Details Sequence</field>
<field name="code">donations.details.lines.sequence</field>
<field name="prefix">SPSH/</field>
<field name="padding">4</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
<field eval="False" name="company_id"/>
</record>
<record id="sponsorship_scheduling_line_sequence" model="ir.sequence">
<field name="name">Sponsorship Scheduling Line Sequence</field>
<field name="code">sponsorship.scheduling.line.sequence</field>
<field name="prefix">SSL/</field>
<field name="padding">5</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
<field eval="False" name="company_id"/>
</record>
<record id="account_move_accrsp_sequence" model="ir.sequence">
<field name="name">ACCRSP Journal Entries Sequence</field>
<field name="code">account.move.accrsp</field>
<field name="prefix">ACCRSP/%(year)s/%(month)s/</field>
<field name="padding">4</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
<field eval="False" name="company_id"/>
<field name="use_date_range">True</field>
</record>
<record id="account_move_payment_details_sequence" model="ir.sequence">
<field name="name">SP Journal Entries Sequence</field>
<field name="code">account.move.payment.details.sequence</field>
<field name="prefix">SP/%(year)s/%(month)s/</field>
<field name="padding">4</field>
<field name="number_next">1</field>
<field name="number_increment">1</field>
<field eval="False" name="company_id"/>
<field name="use_date_range">True</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<!-- <record id="server_action_unlink_sponsor_and_related" model="ir.actions.server">
<field name="name">Sponsor Unlink And Its Relations</field>
<field name="model_id" ref="odex_takaful.model_takaful_sponsor"/>
<field name="binding_model_id" ref="odex_takaful.model_takaful_sponsor"/>
<field name="state">code</field>
<field name="code">
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

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record model="takaful.notification" id="sponsorship_confirm_whatsapp_message">
<field name="name">ارسال رسالة واتساب مباشرة بعد اجراء الconfirm على الكفالة </field>
<field name="duration">0</field>
<field name="notification_type">create_kafala</field>
<field name="message_type_ids" eval="[(4, ref('odex_takaful.whatsapp_message_type'))]"/>
<field name="notification_state_ids"
eval="[(4, ref('odex_takaful.sponsorship_state_draft')), (4, ref('odex_takaful.sponsorship_state_confirmed'))]"/>
<field name="message">هنيئًا لك .. يا من اعطيت وبادرت لتُسعد يتيمًا، نشكركم على كفالتكم بمبلغ ( [Amount] ) ر.س بلغكم الله مرافقة النبي ﷺ في الجنة رابط التقييم : https://forms.gle/pRrNWohAnLPoFwb38
</field>
</record>
<record model="takaful.notification" id="sponsorship_before_finish_30_whatsapp_message">
<field name="name"> تذكير اول بأنتهاء الكفالة: يتم ارسال رسالة واتساب قبل تاريخ انتهاء الكفالة المخطط له اخر بند مجدول بشهر</field>
<field name="duration">30</field>
<field name="notification_type">before_finish</field>
<field name="message_type_ids" eval="[(4, ref('odex_takaful.whatsapp_message_type'))]"/>
<field name="notification_state_ids"
eval="[(4, ref('odex_takaful.sponsorship_state_confirmed')), (4, ref('odex_takaful.sponsorship_state_wait_pay'))]"/>
<field name="message"> عزيزي الكافل / ـة : كفالتك السنوية عطاء يتجدد في كل عام، وثواب يُخلد لمرافقة خير الأنام ﷺ نود تذكيركم بموعد تجديد كفالتكم قبل تاريخ [ExpiryDate]
</field>
</record>
<record model="takaful.notification" id="sponsorship_before_finish_16_whatsapp_message">
<field name="name">تذكير ثاني بأنتهاء الكفالة: = يتم ارسال رسالة واتساب قبل تاريخ انتهاء الكفالة المخطط له اخر بند مجدول ب16 يوم</field>
<field name="duration">16</field>
<field name="notification_type">before_finish</field>
<field name="message_type_ids" eval="[(4, ref('odex_takaful.whatsapp_message_type'))]"/>
<field name="notification_state_ids"
eval="[(4, ref('odex_takaful.sponsorship_state_confirmed'), 4, ref('odex_takaful.sponsorship_state_wait_pay'))]"/>
<field name="message">عزيزي الكافل / ـة : كفالتك السنوية عطاء يتجدد في كل عام، وثواب يُخلد لمرافقة خير الأنام ﷺ نود تذكيركم بموعد تجديد كفالتكم المتبقي عليها 15 يوماَ
</field>
</record>
<record model="takaful.notification" id="sponsorship_before_finish_4_whatsapp_message">
<field name="name"> تذكير ثالث بأنتهاء الكفالة: يتم ارسال رسالة واتساب قبل تاريخ انتهاء الكفالة المخطط له اخر بند مجدول ب4 يوم</field>
<field name="duration">4</field>
<field name="notification_type">before_finish</field>
<field name="message_type_ids" eval="[(4, ref('odex_takaful.whatsapp_message_type'))]"/>
<field name="notification_state_ids"
eval="[(4, ref('odex_takaful.sponsorship_state_confirmed')), (4, ref('odex_takaful.sponsorship_state_wait_pay'))]"/>
<field name="message">عزيزي الكافل / ـة : ثلاثة أيام فقط على إنتهاء كفالتكم السنوية. كنتم سندًا لليتيم، ويسعدنا استمرار كفالتكم التي تنتهي تلقائياَ بتاريخ [ExpiryDate]</field>
</record>
<record model="takaful.notification" id="sponsorship_before_finish_payment_whatsapp_message">
<field name="name"> ارسال رسالة واتساب بعد كل اجراء دفع يتم على بنود جدولة الكفالات </field>
<field name="duration">0</field>
<field name="notification_type">partial_payment</field>
<field name="notification_state_ids"
eval="[(4, ref('odex_takaful.sponsorship_state_paid')), (4, ref('odex_takaful.sponsorship_state_wait_pay'))]"/>
<field name="message_type_ids" eval="[(4, ref('odex_takaful.whatsapp_message_type'))]"/>
<field name="message">هنيئًا لك .. يا من اعطيت وبادرت لتُسعد يتيمًا وأسرته، تم استلام تبرعكم بمبلغ ( [Amount] ) ر س بلغكم الله مرافقة النبي ﷺ في الجنة. رابط التقييم: https://forms.gle/pRrNWohAnLPoFwb38</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record model="sponsorship.states" id="sponsorship_state_draft">
<field name="name">draft</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_confirmed">
<field name="name">confirmed</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_wait_pay">
<field name="name">wait_pay</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_paid">
<field name="name">paid</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_partial_refund">
<field name="name">partial_refund</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_fully_refund">
<field name="name">fully_refund</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_approve_refund">
<field name="name">approve_refund</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_under_refund">
<field name="name">under_refund</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_under_replacement">
<field name="name">under_replacement</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_replacement_done">
<field name="name">replacement_done</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_canceled">
<field name="name">canceled</field>
</record>
<record model="sponsorship.states" id="sponsorship_state_closed">
<field name="name">closed</field>
</record>
<record model="takaful.message.type" id="whatsapp_message_type">
<field name="name">Whatsapp</field>
<field name="tool_type">app</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record id="push_notification_email_template" model="mail.template">
<field name="name">Notification Email</field>
<field name="email_from">${ctx.get('email_from')} or ''}</field>
<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="lang">ar_001</field>
<field name="body_html"><![CDATA[
<p>
Dear ${ctx.get('partner_name')},
</p>
<p>
<strong>${ctx.get('body')}</strong>
</p>
<p>
Thank you,
</p>
<p>
From ${ctx.get('company_name')}.
</p>
]]></field>
</record>
</odoo>

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,30 @@
# -*- coding: utf-8 -*-
from . import takaful_grant_benefit_model
from . import takaful_sponorship_model
from . import takaful_sponsorship_cancellation_model
from . import takaful_sponsorship_payment_model
from . import takaful_sponsor_operation
from . import takaful_push_notification
from . import takaful_contribution_model
from . import takaful_month_payment
from . import takaful_conf
from . import sponsorship_states
from . import replacement_reasons
from . import replacement_process
from . import takaful_notification
from . import account_move
from . import account_payment
from . import res_partner
from . import preferred_communication
from . import takaful_payment_method
from . import res_config_settings
from . import product
from . import donation_details_lines
from . import donation_extension_history
from . import family_member
from . import sponsorship_scheduling_line
from . import donation_replacement_log

View File

@ -0,0 +1,253 @@
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools import float_compare
from odoo.tools.misc import format_date, get_lang
from collections import defaultdict
class AccountMove(models.Model):
_inherit = 'account.move'
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 and move.move_type == 'entry':
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
'''
res = super(AccountMove, self).action_move_line_create()
if res:
self.write({'payment_id': self.move_id.line_ids.mapped('payment_id').id})
@api.onchange('payment_journal_id')
def on_change_payment_journal_id(self):
for rec in self:
rec.account_id = rec.payment_journal_id.default_debit_account_id
def action_register_payment(self):
''' Override the payment registration behavior. '''
# Perform any custom logic before calling the original method
# Call the original method to preserve the default behavior
action = super(AccountMove, self).action_register_payment()
for move in self:
if move.is_refund_sponsorship: # Check if it's a refund
# Add any additional custom logic after calling the original method
action['context'].update({
'default_takaful_sponsorship_id': move.takaful_sponsorship_id.id,
'default_journal_id': move.payment_details_line.journal_id.id,
'default_is_refund_sponsorship': True,
})
return action
@api.depends(
'line_ids.matched_debit_ids.debit_move_id.move_id.payment_id.is_matched',
'line_ids.matched_debit_ids.debit_move_id.move_id.line_ids.amount_residual',
'line_ids.matched_debit_ids.debit_move_id.move_id.line_ids.amount_residual_currency',
'line_ids.matched_credit_ids.credit_move_id.move_id.payment_id.is_matched',
'line_ids.matched_credit_ids.credit_move_id.move_id.line_ids.amount_residual',
'line_ids.matched_credit_ids.credit_move_id.move_id.line_ids.amount_residual_currency',
'line_ids.debit',
'line_ids.credit',
'line_ids.currency_id',
'line_ids.amount_currency',
'line_ids.amount_residual',
'line_ids.amount_residual_currency',
'line_ids.payment_id.state',
'line_ids.full_reconcile_id',
'sponsorship_scheduling_line.status'
)
def _compute_amount(self):
# Call the original method to preserve Odoo's logic
super(AccountMove, self)._compute_amount()
for move in self.filtered("takaful_sponsorship_id"):
scheduling_amount = move.sponsorship_scheduling_line.amount
if move.payment_state == 'paid':
# refund_amount = move.invoice_line_ids.price_unit
refund_amount = sum(move.invoice_line_ids.mapped("price_unit"))
refunded_scheduling_amount = move.sponsorship_scheduling_line.refunded_amount
total_refunded_amount = refund_amount + refunded_scheduling_amount
if refunded_scheduling_amount == scheduling_amount:
move.sponsorship_scheduling_line.status = 'fully_refund'
move.sponsorship_scheduling_line.refunded_amount = scheduling_amount
move.payment_details_line.is_fully_refund = True
elif refunded_scheduling_amount < scheduling_amount:
move.sponsorship_scheduling_line.status = 'partial_refund'
move.sponsorship_scheduling_line.refunded_amount += refund_amount
move.payment_details_line.is_partial_refund = True
else:
if not isinstance(scheduling_amount, (int, float)):
raise UserError(
_("Total amount should be less or equal %s") % scheduling_amount
)
has_partial_refund = False
has_fully_refund = False
has_paid = False
has_unpaid = False
for line in move.takaful_sponsorship_id.sponsorship_scheduling_line_ids:
if line.status == "partial_refund":
has_partial_refund = True
elif line.status == "fully_refund":
has_fully_refund = True
elif line.status == "paid":
has_paid = True
elif line.status == "unpaid":
has_unpaid = True
if has_partial_refund:
move.takaful_sponsorship_id.state = 'partial_refund'
elif has_fully_refund and not (has_partial_refund and has_paid and has_unpaid):
move.takaful_sponsorship_id.state = 'fully_refund'
elif has_fully_refund and (has_partial_refund or has_paid or has_unpaid):
move.takaful_sponsorship_id.state = 'partial_refund'
def _post(self, soft=True):
"""Post/Validate the documents.
Posting the documents will give it a number, and check that the document is
complete (some fields might not be required if not posted but are required
otherwise).
If the journal is locked with a hash table, it will be impossible to change
some fields afterwards.
:param soft (bool): if True, future documents are not immediately posted,
but are set to be auto posted automatically at the set accounting date.
Nothing will be performed on those documents before the accounting date.
:return Model<account.move>: the documents that have been posted
"""
if soft:
future_moves = self.filtered(lambda move: move.date > fields.Date.context_today(self))
future_moves.auto_post = True
for move in future_moves:
msg = _('This move will be posted at the accounting date: %(date)s',
date=format_date(self.env, move.date))
move.message_post(body=msg)
to_post = self - future_moves
else:
to_post = self
# `user_has_group` won't be bypassed by `sudo()` since it doesn't change the user anymore.
# if not self.env.su and not self.env.user.has_group('account.group_account_invoice'):
# raise AccessError(_("You don't have the access rights to post an invoice."))
for move in to_post:
if move.partner_bank_id and not move.partner_bank_id.active:
raise UserError(
_("The recipient bank account link to this invoice is archived.\nSo you cannot confirm the invoice."))
if move.state == 'posted':
raise UserError(_('The entry %s (id %s) is already posted.') % (move.name, move.id))
if not move.line_ids.filtered(lambda line: not line.display_type):
raise UserError(_('You need to add a line before posting.'))
if move.auto_post and move.date > fields.Date.context_today(self):
date_msg = move.date.strftime(get_lang(self.env).date_format)
raise UserError(_("This move is configured to be auto-posted on %s", date_msg))
if not move.partner_id:
if move.is_sale_document():
raise UserError(
_("The field 'Customer' is required, please complete it to validate the Customer Invoice."))
elif move.is_purchase_document():
raise UserError(
_("The field 'Vendor' is required, please complete it to validate the Vendor Bill."))
if move.is_invoice(include_receipts=True) and float_compare(move.amount_total, 0.0,
precision_rounding=move.currency_id.rounding) < 0:
raise UserError(
_("You cannot validate an invoice with a negative total amount. You should create a credit note instead. Use the action menu to transform it into a credit note or refund."))
if move.line_ids.account_id.filtered(lambda account: account.deprecated):
raise UserError(_("A line of this move is using a deprecated account, you cannot post it."))
# Handle case when the invoice_date is not set. In that case, the invoice_date is set at today and then,
# lines are recomputed accordingly.
# /!\ 'check_move_validity' must be there since the dynamic lines will be recomputed outside the 'onchange'
# environment.
if not move.invoice_date:
if move.is_sale_document(include_receipts=True):
move.invoice_date = fields.Date.context_today(self)
move.with_context(check_move_validity=False)._onchange_invoice_date()
elif move.is_purchase_document(include_receipts=True):
raise UserError(_("The Bill/Refund date is required to validate this document."))
# When the accounting date is prior to the tax lock date, move it automatically to the next available date.
# /!\ 'check_move_validity' must be there since the dynamic lines will be recomputed outside the 'onchange'
# environment.
if (move.company_id.tax_lock_date and move.date <= move.company_id.tax_lock_date) and (
move.line_ids.tax_ids or move.line_ids.tax_tag_ids):
move.date = move._get_accounting_date(move.invoice_date or move.date, True)
move.with_context(check_move_validity=False)._onchange_currency()
for move in to_post:
# Fix inconsistencies that may occure if the OCR has been editing the invoice at the same time of a user. We force the
# partner on the lines to be the same as the one on the move, because that's the only one the user can see/edit.
wrong_lines = move.is_invoice() and move.line_ids.filtered(
lambda aml: aml.partner_id != move.commercial_partner_id and not aml.display_type)
if wrong_lines:
wrong_lines.partner_id = move.commercial_partner_id.id
# Create the analytic lines in batch is faster as it leads to less cache invalidation.
to_post.mapped('line_ids').create_analytic_lines()
to_post.write({
'state': 'posted',
'posted_before': True,
})
for move in to_post:
move.message_subscribe([p.id for p in [move.partner_id] if p not in move.sudo().message_partner_ids])
for move in to_post:
if move.is_sale_document() \
and move.journal_id.sale_activity_type_id \
and (move.journal_id.sale_activity_user_id or move.invoice_user_id).id not in (
self.env.ref('base.user_root').id, False):
move.activity_schedule(
date_deadline=min((date for date in move.line_ids.mapped('date_maturity') if date),
default=move.date),
activity_type_id=move.journal_id.sale_activity_type_id.id,
summary=move.journal_id.sale_activity_note,
user_id=move.journal_id.sale_activity_user_id.id or move.invoice_user_id.id,
)
customer_count, supplier_count = defaultdict(int), defaultdict(int)
for move in to_post:
if move.is_sale_document():
customer_count[move.partner_id] += 1
elif move.is_purchase_document():
supplier_count[move.partner_id] += 1
for partner, count in customer_count.items():
(partner | partner.commercial_partner_id)._increase_rank('customer_rank', count)
for partner, count in supplier_count.items():
(partner | partner.commercial_partner_id)._increase_rank('supplier_rank', count)
# Trigger action for paid invoices in amount is zero
to_post.filtered(
lambda m: m.is_invoice(include_receipts=True) and m.currency_id.is_zero(m.amount_total)
).action_invoice_paid()
# Force balance check since nothing prevents another module to create an incorrect entry.
# This is performed at the very end to avoid flushing fields before the whole processing.
to_post._check_balanced()
return to_post
class AccountMoveLines(models.Model):
_inherit = 'account.move.line'
takaful_sponsorship_id = fields.Many2one('takaful.sponsorship', related='move_id.takaful_sponsorship_id', store=True)

View File

@ -0,0 +1,7 @@
from odoo import models, fields
class AccountPayment(models.Model):
_inherit = 'account.payment'
takaful_sponsorship_id = fields.Many2one(related="move_id.takaful_sponsorship_id")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,118 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class DonationExtensionHistory(models.Model):
_name = 'donation.extension.history'
_description = 'Donation Extension History'
_order = 'extension_date desc'
_rec_name = 'extension_ref'
extension_ref = fields.Char(
string='Extension Reference',
readonly=True,
compute='_compute_extension_ref',
store=True
)
donation_detail_id = fields.Many2one(
'donations.details.lines',
string='Donation Detail',
required=True,
ondelete='cascade',
index=True
)
sponsor_id = fields.Many2one(
'res.partner',
string='Sponsor',
related='donation_detail_id.sponsor_id',
store=True,
readonly=True
)
sponsorship_id = fields.Many2one(
'takaful.sponsorship',
string='Sponsorship',
related='donation_detail_id.sponsorship_id',
store=True,
readonly=True
)
product_template_id = fields.Many2one(
'product.template',
string='Donation Item',
related='donation_detail_id.product_template_id',
store=True,
readonly=True
)
extension_amount = fields.Float(
string='Extension Amount',
required=True,
readonly=True
)
extension_months = fields.Integer(
string='Extension Months',
required=True,
readonly=True
)
old_end_date = fields.Date(
string='Old End Date',
required=True,
readonly=True
)
new_end_date = fields.Date(
string='New End Date',
required=True,
readonly=True
)
extension_date = fields.Datetime(
string='Extension Date',
default=fields.Datetime.now,
readonly=True
)
user_id = fields.Many2one(
'res.users',
string='Extended By',
default=lambda self: self.env.user,
readonly=True
)
invoice_id = fields.Many2one(
'account.move',
string='Extension Invoice',
readonly=True,
help='Invoice created for this extension'
)
notes = fields.Text(
string='Notes'
)
old_direct_debit = fields.Boolean(
string='Old Direct Debit',
readonly=True
)
new_direct_debit = fields.Boolean(
string='New Direct Debit',
readonly=True
)
@api.depends('donation_detail_id', 'extension_date')
def _compute_extension_ref(self):
for rec in self:
if rec.donation_detail_id and rec.extension_date:
rec.extension_ref = _('Extension - %s - %s') % (
rec.donation_detail_id.sequence_no or 'N/A',
rec.extension_date.strftime('%Y-%m-%d %H:%M')
)
else:
rec.extension_ref = _('Extension')

View File

@ -0,0 +1,70 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class DonationReplacementLog(models.Model):
_name = 'donation.replacement.log'
_description = 'Donation Replacement Log'
_order = 'replacement_date desc'
_rec_name = 'replacement_ref'
replacement_ref = fields.Char(
string='replacement Reference',
readonly=True,
compute='_compute_replacement_ref',
store=True
)
donation_detail_id = fields.Many2one(
'donations.details.lines',
string='Donation Detail',
required=True,
ondelete='cascade',
index=True
)
sponsor_id = fields.Many2one(
'res.partner',
string='Sponsor',
related='donation_detail_id.sponsor_id',
store=True,
readonly=True
)
sponsorship_id = fields.Many2one(
'takaful.sponsorship',
string='Sponsorship',
related='donation_detail_id.sponsorship_id',
store=True,
readonly=True
)
replacement_date = fields.Datetime(
string='Replacement Date',
default=fields.Datetime.now,
readonly=True
)
user_id = fields.Many2one(
'res.users',
string='Replaced By',
default=lambda self: self.env.user,
readonly=True
)
new_benefit = fields.Char(string="New Benefit", copy=False, readonly=True)
old_benefit = fields.Char(string="old Benefit", copy=False, readonly=True)
record_type = fields.Selection([('sponsorship', 'Sponsorship'),('donation', 'Donation')], string="Record Type", readonly=True)
replacement_reason_id = fields.Many2one('replacement.reasons', string="Replacement Reason", readonly=True)
@api.depends('donation_detail_id', 'replacement_date')
def _compute_replacement_ref(self):
for rec in self:
if rec.donation_detail_id and rec.replacement_date:
rec.replacement_ref = _('Replacement - %s - %s') % (
rec.donation_detail_id.sequence_no or 'N/A',
rec.replacement_date.strftime('%Y-%m-%d %H:%M')
)
else:
rec.replacement_ref = _('Replacement')

View File

@ -0,0 +1,108 @@
from odoo import models, fields, api, _
from dateutil.relativedelta import relativedelta
from datetime import datetime, timedelta
class GrantBenefit(models.Model):
_inherit = 'grant.benefit'
def action_second_accepted(self):
super(GrantBenefit, self).action_second_accepted()
for member in self.member_ids:
sponsorships_main = self.env['donations.details.lines'].search([
('benefit_id', '=', member.id,),('state', '=', 'active')
])
sponsorships_multi = self.env['donations.details.lines'].search([
('benefit_ids', 'in', member.id),('state', '=', 'active')
])
sponsorships = sponsorships_main | sponsorships_multi
if sponsorships:
for sponsorship in sponsorships:
if member.member_status and member.member_status == 'non_benefit' and sponsorship.record_type == 'sponsorship':
sponsorship.sudo().write({'state': 'replace'})
class FamilyMember(models.Model):
_inherit = 'family.member'
donation_details_count = fields.Integer(
string='Donation Details',
compute='_compute_donation_details_count'
)
sponsor_id = fields.Many2one('res.partner', string='Sponsor Partner', domain="[('is_sponsor_portal', '=', True)]")
sponsor_related_id = fields.Many2one('res.partner', string='Sponsor')
sponsorship_id = fields.Many2one('takaful.sponsorship', string='Sponsorship')
sponsorship_end_date = fields.Date(string='Sponsorship End Date')
is_restricted = fields.Boolean(string="Is Restricted ?", default=False, readonly=True)
general_restriction = fields.Boolean(string="General Restriction", default=False, readonly=True)
kafala_status = fields.Selection(
[('have_kafala', 'Have Kafala'), ('have_not_kafala', 'Have not Kafala')],
string='Kafala Status', compute='_compute_kafala_status', store=True, readonly=True)
@api.depends('sponsor_related_id')
def _compute_kafala_status(self):
for rec in self:
rec.kafala_status = 'have_kafala' if rec.sponsor_related_id else 'have_not_kafala'
def _compute_donation_details_count(self):
for rec in self:
rec.donation_details_count = self.env['donations.details.lines'].search_count([
'|',
('benefit_id', '=', rec.id),
('benefit_ids', 'in', rec.ids)
])
def action_open_donation_detail(self):
self.ensure_one()
return {
'name': _('Donation Details Lines'),
'type': 'ir.actions.act_window',
'res_model': 'donations.details.lines',
'view_mode': 'tree,form',
'domain': ['|', ('benefit_id', '=', self.id), ('benefit_ids', 'in', self.ids)],
'context': {'create': False, 'delete': False},
}
def action_not_available_for_sponsorship(self):
for rec in self:
rec.general_restriction = True
def action_available_for_sponsorship(self):
for rec in self:
rec.general_restriction = False
@api.model
def _cron_family_member_restriction(self):
benefit_ids = self.env["family.member"].sudo().search([("is_restricted", "=", True)])
today = fields.Date.today()
restriction_period = self.env['ir.config_parameter'].sudo().get_param('odex_takaful.restriction_period')
for benefit in benefit_ids:
create_date = benefit.create_date.date()
benefit_date = create_date + timedelta(days=int(restriction_period) or 0)
if benefit_date >= today:
benefit.is_restricted = False
def create(self, vals):
res = super(FamilyMember, self).create(vals)
self.is_restricted = True
return res
# @api.model
# def write(self, vals):
# res = super(FamilyMember, self).write(vals)
# if 'member_status' in vals:
# for member in self:
# sponsorships_main = self.env['donations.details.lines'].search([
# ('benefit_id', '=', member.id)
# ])
# sponsorships_multi = self.env['donations.details.lines'].search([
# ('benefit_ids', 'in', member.id)
# ])
# sponsorships = sponsorships_main | sponsorships_multi
#
# if sponsorships:
# if member.member_status and member.member_status == 'non_benefit' and sponsorships.sponsorship_id.record_type == 'sponsorship':
# sponsorships.write({'state': 'replace'})
# return res

View File

@ -0,0 +1,9 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class PreferredCommunication(models.Model):
_name = 'preferred.communication'
name = fields.Char(required=True)

View File

@ -0,0 +1,99 @@
from odoo import models, fields, api, _
class ProductTemplate(models.Model):
_inherit = 'product.template'
donation_category = fields.Selection(
[('donation', 'Donation'), ('sponsorship', 'Sponsorship'), ('endowment', 'Endowment')],
string='Donation Category')
fixed_value = fields.Boolean(string='Is Fixed Value?', compute='_compute_fixed_value')
sponsorship_duration = fields.Selection([('temporary', 'Temporary'), ('permanent', 'Permanent')],
string='Sponsorship Duration Type')
_quantity = fields.Float(default=0, store=True)
payment_method_id = fields.Many2one('takaful.payment.method', string="Payment Method")
def _compute_fixed_value(self):
for rec in self:
rec.fixed_value = False
def link_to_sponsorship(self):
sponsorship_id = self.env.context.get('sponsorship_id')
if not sponsorship_id:
return
sponsorship = self.env['takaful.sponsorship'].browse(sponsorship_id)
vals = []
for rec in self:
vals.append((0, 0, {
'product_template_id': rec.id,
'sponsorship_id': sponsorship_id,
'donation_types': 'donation',
'donation_mechanism': 'without_conditions',
}))
# Append to existing lines instead of replacing them
sponsorship.write({
'donations_details_lines': vals
})
def utilizable_cart_details(self):
"""
Utilizable Cart Details For Remove , Add And Update Operations
For Cart To Product Catelog Module To Object addcart.sales.products
"""
context = self._context.copy() or {}
cart_object = self.env["donations.details.lines"]
cart_details = dict()
total_count = cart_object.search_count(
[('product_template_id', '=', self.id),
('sponsorship_id', '=', context.get('sponsorship_id'))]) # , ("cart_flag", "=", True)
cart_details["total_count"] = total_count
cart_data = cart_object.search(
[('product_template_id', '=', self.id),
('sponsorship_id', '=', context.get('sponsorship_id'))]) # , ("cart_flag", "=", True)
cart_details["cart_data"] = cart_data
return cart_details
def initiate_sol(self, operation, sponsorship_id):
"""
Initiate Sale Order Line By Cart Functionality.
"""
ts_object = self.env["takaful.sponsorship"]
sponsorship_object = ts_object.search([("id", "=", sponsorship_id)])
if operation == "add":
ts_object.sol_by_cart(operation, self, sponsorship_object)
elif operation == "remove":
ts_object.sol_by_cart(operation, self, sponsorship_object)
elif operation == "update":
ts_object.sol_by_cart(operation, self, sponsorship_object)
def set_quantity_so(self, quantity, operation=None):
context = self._context.copy() or {}
cart_details = self.utilizable_cart_details()
if operation == "remove":
self._quantity -= quantity
if cart_details.get("total_count") != 0:
self.initiate_sol("remove", context.get("sponsorship_id"))
else:
self._quantity += quantity
if cart_details.get("total_count") != 0:
self.initiate_sol("update", context.get("sponsorship_id"))
else:
self.initiate_sol("add", context.get("sponsorship_id"))
def remove_quantity_button_so(self):
if self._quantity == 0:
self._quantity = 0
return
return self.set_quantity_so(1, operation="remove")
def add_quantity_button_so(self):
# return self.set_quantity_so(1, operation="add")
self.set_quantity_so(1, operation="add")
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
}

View File

@ -0,0 +1,230 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _, exceptions
from odoo.exceptions import ValidationError, UserError, Warning
import requests
import re
class ReplacementProcess(models.Model):
_name = 'replacement.process'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "Replacement Process"
_rec_name = 'code'
code = fields.Char(string="Replacement Reference",copy=False,readonly=True)
user_id = fields.Many2one('res.users', string="Create User")
sponsorship_id = fields.Many2one('takaful.sponsorship',string='Sponsorship')
branch_id = fields.Many2one('branch.settings', string="Branch")
branch_ids = fields.Many2many('branch.settings', string="Branch")
sponsor_donor_type = fields.Selection(string='Sponsor / Donor Type',selection=[('registered', 'Registered'), ('new_sponsor', 'New Sponsor')])
record_type = fields.Selection([('sponsorship', 'Sponsorship'),('donation', 'Donation')], string="Record Type")
sponsor_id = fields.Many2one('res.partner',string='Sponsor Name')
replacement_reason_id = fields.Many2one('replacement.reasons', string="Replacement Reason")
benefit_ids = fields.Many2many('family.member',string='Benefits')
replaced = fields.Boolean('Replaced')
family_ids = fields.Many2many('grant.benefit',string='Family')
registered_type = fields.Selection(string='Registered Type',selection=[('sponsor', 'Sponsor'),('member', 'Member')])
replacement_line_ids = fields.One2many('replacement.process.line', 'process_id', string="Replacement Lines", tracking=True)
state = fields.Selection([('draft', 'Draft'),('replaced', 'Replaced')],string='State', default='draft', tracking=True)
# Model Operations
@api.model
def create(self, vals):
if vals.get('code', 'New') == 'New':
vals['code'] = self.env['ir.sequence'].sudo().next_by_code('replacement.process.sequence')
res = super(ReplacementProcess, self).create(vals)
return res
def unlink(self):
raise UserError(_('You cannot delete this record'))
return super(ReplacementProcess, self).unlink()
def confirm_replacement(self):
for rec in self:
rec.benefit_ids.sudo().write({'replaced': True})
rec.sponsorship_id.sudo().write({'state': 'replacement_done'})
rec.sponsorship_id.sudo().write({'branch_custom_id': self.branch_id.id})
if rec.replacement_line_ids:
for benefit in rec.replacement_line_ids:
all_donation_lines = (
(rec.sponsorship_id.donations_details_lines if rec.sponsorship_id.donations_details_lines else self.env[
'donations.details.lines']) |
(
rec.sponsorship_id.donations_details_lines_mechanism_ids if rec.sponsorship_id.donations_details_lines_mechanism_ids else
self.env['donations.details.lines'])
)
for donation_line in all_donation_lines:
if donation_line.sponsorship_type in ['person',benefit.sponsorship_type] and donation_line.benefit_id and benefit.to_benefit_id and donation_line.benefit_id == benefit.from_benefit_id:
donation_line.benefit_id.sudo().write({'replaced': True})
rec.family_ids = [(6, 0, [donation_line.benefit_id.benefit_id.id])]
donation_line.sudo().write({'benefit_id': benefit.to_benefit_id.id})
elif donation_line.sponsorship_type in ['group',benefit.sponsorship_type] and donation_line.benefit_ids and benefit.to_benefit_ids and donation_line.benefit_ids == benefit.from_benefit_ids:
rec.family_ids = [(6, 0, [donation_line.benefit_ids.mapped('benefit_id.id')[0]])]
donation_line.sudo().write({'benefit_ids': benefit.to_benefit_ids.ids})
donation_line.sudo().write({'benefit_id': benefit.to_benefit_ids.ids[0]})
donation_line.benefit_ids.sudo().write({'replaced': True})
rec.state = 'replaced'
rec.replaced = True
rec.action_send_whatsapp()
def action_send_whatsapp(self):
config = self.env['ir.config_parameter'].sudo()
account_sid = config.get_param('odex_takaful.twilio_account_sid')
auth_token = config.get_param('odex_takaful.twilio_auth_token')
from_whatsapp = config.get_param('odex_takaful.twilio_from_whatsapp')
if not account_sid or not auth_token or not from_whatsapp:
raise ValidationError(_("Twilio configuration is missing. Please configure Twilio SID, Auth Token, and WhatsApp number in General Configurations."))
from_cleaned_mobile = re.sub(r'[^\d+]', '', from_whatsapp)
from_whatsapp_number = f'whatsapp:{from_cleaned_mobile}'
message = "نشعركم بإستبدال أبنائكم المكفول/ة بآخر مستحق وذلك لإستبعاده من الجمعية نظامياً، للحصول على تقرير اليتيم الجديد يسعدنا تواصلكم مع الفرع، بلغكم الله مرافقة النبى صلى الله عليه وسلم فى الجنة"
for partner in self:
mobile = partner.sponsor_id.mobile if partner.sponsor_id else partner.sponsorship_id.member_id.mobile
if mobile:
# Clean the number (keep + and digits only)
cleaned_mobile = re.sub(r'[^\d+]', '', mobile)
to_whatsapp_number = f'whatsapp:{cleaned_mobile}'
url = f"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Messages.json"
payload = {
'From': from_whatsapp_number,
'To': to_whatsapp_number,
'Body': message,
}
response = requests.post(
url,
data=payload,
auth=(account_sid, auth_token)
)
if response.status_code != 201:
raise ValidationError(_("Failed to send WhatsApp message: %s") % response.text)
class FamilyMember(models.Model):
_inherit = 'family.member'
replaced = fields.Boolean('Replaced')
def write(self, vals):
res = super(FamilyMember, self).write(vals)
sponsorship_states = ['confirmed', 'wait_pay', 'under_refund', 'under_replacement', 'replacement_done']
for record in self:
if any(key in vals for key in ['is_work', 'is_married', 'member_location_conf']):
if vals.get('is_work') or vals.get('is_married') or vals.get('member_location_conf') is False:
# Search in donations.details.lines where this member is either benefit_id or in benefit_ids
lines = self.env['donations.details.lines'].sudo().search([
'|',
('benefit_id', '=', record.id),
('benefit_ids', 'in', [record.id])
])
for line in lines:
# Get related sponsorship
sponsorship = line.sponsorship_mechanism_id or line.sponsorship_id
if sponsorship and sponsorship.state in sponsorship_states:
sponsor = sponsorship.sponsor_id or sponsorship.member_id
mobile = sponsor.mobile if sponsor else None
if mobile:
self.send_whatsapp_message(mobile, record.name)
break
return res
def send_whatsapp_message(self, mobile, member_name):
config = self.env['ir.config_parameter'].sudo()
account_sid = config.get_param('odex_takaful.twilio_account_sid')
auth_token = config.get_param('odex_takaful.twilio_auth_token')
from_whatsapp = config.get_param('odex_takaful.twilio_from_whatsapp')
if not account_sid or not auth_token or not from_whatsapp:
raise ValidationError(_("Twilio configuration is missing. Please configure Twilio SID, Auth Token, and WhatsApp number in General Configurations."))
from_cleaned_mobile = re.sub(r'[^\d+]', '', from_whatsapp)
from_whatsapp_number = f'whatsapp:{from_cleaned_mobile}'
message = "تنبيه: اليتيم الحالي [NAME] أصبح غير مستحق لأسباب محددة ويجب الاستبدال بيتيم اخر."
message = message.replace("[NAME]", member_name) # Clean the number (keep + and digits only)
cleaned_mobile = re.sub(r'[^\d+]', '', mobile)
to_whatsapp_number = f'whatsapp:{cleaned_mobile}'
url = f"https://api.twilio.com/2010-04-01/Accounts/{account_sid}/Messages.json"
payload = {
'From': from_whatsapp_number,
'To': to_whatsapp_number,
'Body': message,
}
response = requests.post(url, data=payload, auth=(account_sid, auth_token))
if response.status_code != 201:
raise ValidationError(_("Failed to send WhatsApp message: %s") % response.text)
class ReplacementProcessLine(models.Model):
_name = 'replacement.process.line'
_description = 'Replacement ProcessLine'
members_domain_ids = fields.Many2many(comodel_name='family.member')
from_benefit_id = fields.Many2one('family.member', string="From Benefit")
to_benefit_id = fields.Many2one('family.member', string="To Benefit", domain = "[('id', 'in',members_domain_ids)]")
from_benefit_ids = fields.Many2many('family.member', 'replacement_process_from_benefit_wiz_rel', 'line_id', 'benefit_id', string="From Benefits (Group)")
to_benefit_ids = fields.Many2many('family.member', 'replacement_process_to_benefitwiz__rel', 'line_id', 'benefit_id', string="To Benefits (Group)", domain = "[('id', 'in',members_domain_ids)]")
sponsorship_type = fields.Selection([('person', 'Individual'),('group', 'Group')],string='Sponsorship Type')
process_id = fields.Many2one('replacement.process', string="Wizard")
@api.constrains('from_benefit_ids', 'to_benefit_ids')
def onchange_from_to_constrain(self):
for rec in self:
if len(self.from_benefit_ids) != len(self.to_benefit_ids):
raise ValidationError(
_("You must select the same number of beneficiaries in the from benefits group (%s) to the to benefits group (%s)" % (
", ".join(self.from_benefit_ids.mapped('name')),
", ".join(self.to_benefit_ids.mapped('name')))))
class GrantBenefit(models.Model):
_inherit = 'grant.benefit'
replaced = fields.Boolean('Replaced')
def action_open_replacements(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': 'Replacement Process',
'view_mode': 'tree,form',
'res_model': 'replacement.process',
'domain': [('family_ids', 'in', [self.id])],
}

View File

@ -0,0 +1,7 @@
from odoo import api, fields, models, _
class ReplacementReasons(models.Model):
_name = "replacement.reasons"
_description = "Replacement Reasons"
name = fields.Char(string="Name")

View File

@ -0,0 +1,47 @@
from odoo import models, fields, api, _
class TakafulConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
cancel_refund = fields.Integer(string='Cancel Refund Time')
twilio_account_sid = fields.Char(string="Twilio Account SID", config_parameter="odex_takaful.twilio_account_sid")
twilio_auth_token = fields.Char(string="Twilio Auth Token", config_parameter="odex_takaful.twilio_auth_token")
twilio_from_whatsapp = fields.Char(string="From WhatsApp Number",help="Enter a valid phone number including country code. Example: +14155238886",
config_parameter="odex_takaful.twilio_from_whatsapp")
donation_extension_reminder_sms_template_id = fields.Many2one('sms.template', string="Donation Extension Reminder SMS Template", related='company_id.donation_extension_reminder_sms_template_id', readonly=False)
donation_ended_sms_template_id = fields.Many2one('sms.template', string="Donation Ended SMS Template", related='company_id.donation_ended_sms_template_id', readonly=False)
restriction_period = fields.Integer(string='Restriction Period')
faal_kheer_partner_id = fields.Many2one("res.partner", string="Faal Kheer Partner", related='company_id.faal_kheer_partner_id', readonly=False)
def set_values(self):
super(TakafulConfigSettings, self).set_values()
sudoConf = self.env['ir.config_parameter'].sudo()
sudoConf.set_param('odex_takaful.cancel_refund', self.cancel_refund)
sudoConf.set_param('odex_takaful.restriction_period', self.restriction_period)
@api.model
def get_values(self):
res = super(TakafulConfigSettings, self).get_values()
sudoConf = self.env['ir.config_parameter'].sudo()
cancel_refund = sudoConf.get_param('odex_takaful.cancel_refund')
restriction_period = sudoConf.get_param('odex_takaful.restriction_period')
res.update(
{
'cancel_refund': int(cancel_refund),
'restriction_period': int(restriction_period),
}
)
return res
class ResCompany(models.Model):
_inherit = 'res.company'
donation_extension_reminder_sms_template_id = fields.Many2one('sms.template', string="Donation Extension Reminder SMS Template")
donation_ended_sms_template_id = fields.Many2one('sms.template', string="Donation Ended SMS Template")
faal_kheer_partner_id = fields.Many2one("res.partner", string="Faal Kheer Partner")

View File

@ -0,0 +1,455 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError, Warning
from dateutil.parser import parse
import re
from odoo.osv import expression
SAUDI_MOBILE_PATTERN = r"^(\+?966)?0?5[013456789][0-9]{7}$"
class IrActionsServer(models.Model):
_inherit = 'ir.actions.server'
groups_id = fields.Many2many('res.groups', 'res_groups_server_rel', 'uid', 'gid', string='Groups')
class sponsor(models.Model):
_name = 'takaful.sponsor'
class ResPartner(models.Model):
_name = 'res.partner'
_inherit = ['res.partner', 'mail.thread']
account_number = fields.Char(string="Account Number")
bank_entity_name = fields.Char(string="Bank Entity Name")
name = fields.Char(string="Name", compute='get_partner_name', store=True, readonly=False)
#Location
branch_custom_id = fields.Many2one('branch.settings', string="Branch")
district_id = fields.Many2one('res.districts', string="District", domain="[('branch_custom_id','=',branch_custom_id)]")
# New Added
notify_by_app = fields.Boolean(string='Notify By App', default=True)
notify_by_sms = fields.Boolean(string='Notify By SMS', default=True)
notify_for_pay = fields.Boolean(string='Paying Notify By App', default=True)
notify_pay_by_app = fields.Boolean(string='Paying Notify By App', default=True)
notify_pay_by_sms = fields.Boolean(string='Paying Notify By SMS', default=True)
name_in_certificate = fields.Boolean(string='Beneficiaries Names In Certificate', default=True)
type_in_certificate = fields.Boolean(string='Beneficiaries Type In Certificate', default=True)
duration_in_certificate = fields.Boolean(string='Sponsorship Duration In Certificate', default=True)
notify_month_day = fields.Integer(string="Notify Month Day", default=1)
wait_cancel_day = fields.Integer(string="Waiting For Cancellation", default=2)
# operation_ids = fields.One2many('takaful.sponsor.operation', 'sponsor_id', string="Operations Records")
benefit_ids = fields.One2many('family.member', 'sponsor_related_id', string="Benefits Records")
related_benefits_count = fields.Integer(compute="_compute_related_benefits_count")
kafel_id = fields.Many2one('res.users')
state = fields.Selection([
('draft', 'Draft'),
('verified', 'Verified')
], string='State',default='draft', tracking=True)
def _get_default_preferred_communication(self):
"""Get first preferred communication method as default"""
first_comm = self.env['preferred.communication'].search([], limit=1, order='id asc')
return first_comm if first_comm else False
preferred_communication = fields.Many2one('preferred.communication', string="Preferred Communication", default=_get_default_preferred_communication)
serial_code = fields.Char(string="Serial Code", readonly=True, copy=False)
responsible_user_ids = fields.Many2many(
'res.users',
'takaful_sponsor_user_rel',
'sponsor_id',
'user_id',
string='Responsible Employees'
)
operation_count = fields.Integer(
compute='_compute_operation_count',
string="# Of Operations",
readonly=True
)
kafalat_count = fields.Integer(
compute='_compute_kafalat_count',
string="# of Kafalat",
readonly=True
)
contribution_count = fields.Integer(
compute='_compute_contribution_count',
string="# of Contributions",
readonly=True
)
active_counts = fields.Integer(
string="Active Sponsors Count",
)
active = fields.Boolean(default=True)
gift_count = fields.Integer(
compute='_compute_gift_count',
string="# of Gifts",
readonly=True
)
_sql_constraints = [
('id_number_uniq', 'unique (id_number)', 'The ID Number Already Exist!'),
]
def view_sponsorship_payment_action(self):
"""Enable The Sponsor To Pay Sponsorships Entries"""
sponsorship_id = self.env['takaful.sponsorship'].sudo().search([('sponsor_id', '=', self.id), ('has_delay', '=', True)], limit=1)
context = dict(self.env.context or {})
context['default_sponsor_id'] = self.id or False
context['default_sponsorship_id'] = sponsorship_id.id or False
return {
'name': _('Sponsorship Payment'),
'view_type': 'form',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_takaful.takaful_sponsorship_payment_tree').id, 'tree'),
(self.env.ref('odex_takaful.takaful_sponsorship_payment_form').id, 'form')],
'type': 'ir.actions.act_window',
'res_model': 'sponsorship.payment',
'domain': "[('sponsor_id','=',%s)]" % (self.id or False),
'target': 'current',
'context': context,
}
@api.constrains('is_family', 'is_benefit', 'is_donor', 'is_sponsor_portal')
def _check_family_beneficiary_exclusivity(self):
for rec in self:
is_family_or_beneficiary = rec.is_family or rec.is_benefit
is_donor_vendor_sponsor = rec.is_donor or rec.is_sponsor_portal or rec.is_vendor
if is_family_or_beneficiary and is_donor_vendor_sponsor:
raise ValidationError(_("A contact cannot be both Family/Beneficiary and Donor/Member/Sponsor at the same time!"))
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
if not args:
args = []
domain = ['|', '|', ('name', operator, name),('id_number', operator, name),('mobile', operator, name)]
domain = expression.AND([domain, args])
parent_record_ids = self.search(domain).ids
domain = expression.OR([domain, [('parent_id', 'in', parent_record_ids)]])
return self._search(domain, limit=limit, access_rights_uid=name_get_uid)
def _compute_related_benefits_count(self):
for record in self:
record.related_benefits_count = self.env['family.member'].search_count([
('sponsor_related_id', '=', record.id)
])
def action_open_benefit_records(self):
"""Open related account.move records."""
return {
'type': 'ir.actions.act_window',
'name': 'Related Benefits',
'view_mode': 'tree,form',
'res_model': 'family.member',
'domain': [('id', 'in', self.benefit_ids.ids)],
'context': {'create': False},
}
def _compute_operation_count(self):
# Get operation_count
operation_count = self.env['takaful.sponsor.operation'].sudo().search_count([('sponsor_id', '=', self.id)])
if operation_count >0:
self.operation_count = operation_count
else:
self.operation_count = 0
def _compute_kafalat_count(self):
# Get kafalat
kafalat_count = self.env['takaful.sponsorship'].sudo().search_count([('sponsor_id', '=', self.id)])
if kafalat_count >0:
self.kafalat_count = kafalat_count
else:
self.kafalat_count = 0
def _compute_contribution_count(self):
# The current user may not have access rights for contributions.
for partner in self:
try:
partner.contribution_count = len(partner.id) * 2
except Exception:
partner.contribution_count = 50
def _compute_gift_count(self):
# The current user may not have access rights for gifts.
for partner in self:
try:
partner.gift_count = len(partner.id) * 3
except Exception:
partner.gift_count = 75
#Validition here
def check_bank_info_value(self):
# all values true
bank_info = [self.account_number,
self.iban,
self.bank_id,
self.bank_entity_name,
]
res = all(bank_info)
return res
def unlink(self):
related_contact = self.env['res.partner'].search([('parent_id', 'in', self.ids)])
sponsorships = self.env['takaful.sponsorship'].search([('sponsor_id', 'in', self.ids)])
if sponsorships or related_contact:
raise UserError(_('Contacts are associated with sponsorships') )
self.user_id.sudo().write({
"active": False
})
return super(ResPartner, self).unlink()
def on_activate_sponsor_multi(self):
for record in self:
if not record.active:
if record.user_id:
record.user_id.sudo().write({
"active": True
})
record.active = True
else:
raise UserError(_('Sponsor is already active'))
def action_save_and_close(self):
"""Save and close the form wizard - used when creating new sponsor from sponsorship form"""
self.ensure_one()
# The form will close automatically and return to parent form
return {'type': 'ir.actions.act_window_close'}
@api.model
def create(self, values):
mobile_number = values.get('mobile', False)
context = self.env.context
if mobile_number:
self._check_phone_numbers(values['mobile'])
validated_mobile_number = self.phone_format(mobile_number)
values.update({'mobile': validated_mobile_number})
if context.get('sponsor_contact'):
values.update({'lang': 'ar_001'})
values.update({'tz': 'Asia/Riyadh'})
# values.update({'account_type':'sponsor'})
values.update({'is_sponsor_portal': True})
if not values.get('serial_code'):
values['serial_code'] = self.env['ir.sequence'].next_by_code('takaful.sponsor.sequence') or 'S/0000'
res = super(ResPartner, self).create(values)
if context.get('sponsor_contact'):
if context.get('parent_model') == 'takaful.sponsorship' and context.get('parent_id'):
parent_record = self.env[context['parent_model']].browse(context['parent_id'])
parent_record.sponsor_id = res.id
if 'is_sponsor_portal' in values or 'is_donor' in values:
if values['is_sponsor_portal'] == True or values['is_donor'] == True :
if res.mobile != False:
kafeel = self.env['res.users'].with_user(2).create({
'name' : values['name'],
'branch_custom_id':values['branch_custom_id'],
'sel_groups_1_9_10' : 9,
'partner_id' : res.id,
'login' : values['mobile'],
'otp_mobile_phone' : values['mobile'],
'otp_enabled' : True,
})
res.kafel_id = kafeel
return res
def write(self, vals):
if 'mobile' in vals:
self._check_phone_numbers(vals['mobile'])
vals['mobile'] = self.phone_format(vals['mobile'])
if 'name' in vals :
if self.kafel_id:
self.kafel_id.name = vals['name']
if 'mobile' in vals :
if self.kafel_id:
self.kafel_id.login = vals['mobile']
res = super(ResPartner, self).write(vals)
return res
def create_user(self):
for follower in self.message_follower_ids:
follower.sudo().unlink()
# If you add 'no_reset_password' to the context to True, it won't send an email.
# You can then set the password manually (and find a way to let the user know it).
user = self.env['res.users'].sudo().with_context(no_reset_password=False).create({
'name': self.name,
'login': self.mobile,
'phone': self.mobile,
'mobile': self.mobile,
'partner_id': self.id,
'active': True,
'city': self.city_id.name if self.city_id else False,
'lang':'ar_001',
'tz': 'Asia/Riyadh',
})
# Add groups to the user as sponsor
user.sudo().write({'groups_id': [
# in odoo relation field accept a list of commands
# command 4 means add the id in the second position must be an integer
# ref return an object so we return the id
(4, self.env.ref('odex_takaful.takaful_group_user_sponsor').id),
(3, self.env.ref('base.group_user', False).id),
(4, self.env.ref('base.group_portal', False).id)]
})
self.user_id = user.id
return self
def action_open_sponsor_operation(self):
"""Open Operations History for a Sponsor"""
domain = [('sponsor_id', '=', self.id or False)]
context = dict(self.env.context or {})
context['default_sponsor_id'] = self.id or False
return {
'name': _('Sponsor Operations'),
'view_type': 'form',
'view_mode': 'tree,form',
'view_id': False,
'res_model': 'takaful.sponsor.operation',
'type': 'ir.actions.act_window',
'target': 'current',
'domain': domain,
'context': context,
}
def view_sponsorship_action(self):
"""List Sponsorships For The Sponsor"""
domain = [('sponsor_id', '=', self.id or False)]
context = dict(self.env.context or {})
context['default_sponsor_id'] = self.id or False
# view = self.env.ref('odex_takaful.takaful_sponsorship_tree')
return {
'name': _('Sponsorships'),
'view_type': 'form',
'view_mode': 'tree,form',
'view_id': False,
'res_model': 'takaful.sponsorship',
'type': 'ir.actions.act_window',
'target': 'current',
'domain': domain,
'context': context,
}
@api.model
def get_active_sponsors_users(self):
sponsors_users = self.env['res.users'].sudo().search([
("active", "=", True),
("groups_id", "=", self.env.ref("odex_takaful.takaful_group_user_sponsor").id)])#self.env['res.users'].sudo().search([])
count = len(sponsors_users) or 0
sponsors = self.env['res.partner'].sudo().search([])
for rec in sponsors:
rec.update({
"active_counts": count,
})
def show_active_sponsor_report_report(self):
self.sudo().get_active_sponsors_users()
ctx = self.env.context.copy()
return {
'name': _('Active Sponsors Count Report'),
'type': 'ir.actions.act_window',
'res_model': 'res.partner',
'view_type': 'form',
'view_mode': 'pivot',
'view_id': self.env.ref('odex_takaful.active_sponsor_report_pivot_view').id,
'target': 'main',
'context': ctx,
}
def _check_phone_numbers(self, mobile_number):
for rec in self:
mobile = str(mobile_number).strip().replace(" ", "").replace("-", "")
if not re.fullmatch(SAUDI_MOBILE_PATTERN, mobile):
raise ValidationError(_('Enter a valid Saudi mobile number'))
def action_unlink_sponsor_and_related(self):
member_ids = self.env["family.member"].sudo().search([("sponsor_related_id", "in", self.ids)])
if member_ids:
member_ids.sudo().write({"sponsor_related_id": False})
grant_partner_ids = self.env['grant.benefit'].sudo().search([
('partner_id', 'in', self.ids),
('state', 'not in', ['draft', 'new'])
]).partner_id
if grant_partner_ids:
partner_ids = self.filtered(lambda p: p.id not in grant_partner_ids)
partner_ids.sudo().write({'active': False})
def name_get(self):
result = []
for sponsor in self:
name = sponsor.name
if sponsor.mobile:
name = sponsor.name + " - " + str(sponsor.mobile)
result.append((sponsor.id, name))
return result
@api.depends('company_type',
'first_name',
'second_name',
'middle_name',
'family_name',
'sponsor_title',
'suffix_title_id')
def get_partner_name(self):
for rec in self:
names = []
if rec.sponsor_title:
names.append(f"{rec.sponsor_title.shortcut if rec.sponsor_title.shortcut else rec.sponsor_title.name}/")
if rec.first_name:
names.append(rec.first_name)
if rec.second_name:
names.append(rec.second_name)
if rec.middle_name:
names.append(rec.middle_name)
if rec.family_name:
names.append(rec.family_name)
if rec.suffix_title_id:
names.append(f"({rec.suffix_title_id.shortcut if rec.suffix_title_id.shortcut else rec.suffix_title_id.name})")
if names:
rec.name = " ".join(names)
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

@ -0,0 +1,245 @@
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class SchedulingLine(models.Model):
_name = 'sponsorship.scheduling.line'
sponsorship_id = fields.Many2one('takaful.sponsorship')
sponsorship_state = fields.Selection(related='sponsorship_id.state')
donation_detail_linked_id = fields.Many2one('donations.details.lines')
sequence_no = fields.Char(default='/', readonly=True, copy=False)
beneficiary_id = fields.Many2one('family.member')
month_year = fields.Char()
scheduled_date = fields.Date(string='Scheduled Date', help='Date when the payment should be automatically processed')
amount = fields.Float()
refunded_amount = fields.Float(string='Refunded Amount')
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
status = fields.Selection([
('unpaid', 'Unpaid'),
('paid', 'Paid'),
('approve_refund', 'Approve Refund'),
('under_refund', 'Under Refund'),
('partial_refund', 'Partial Refund'),
('fully_refund', 'Fully Refund'),
], copy=False, default='unpaid')
sponsor_id = fields.Many2one('res.partner')
direct_debit = fields.Boolean(string='Direct Debit', related='donation_detail_linked_id.direct_debit')
cancel_refund = fields.Boolean(string='Cancel Refund Time', compute="compute_days_after_payment")
def compute_days_after_payment(self):
"""Check if the number of hours passed after payment is within the configured limit"""
for record in self:
days_passed = 0
config_param = record.env['ir.config_parameter'].sudo()
max_hours = int(config_param.get_param('odex_takaful.cancel_refund', default=0))
payment_record = record.env['payment.details.lines'].search([
'|',
('sponsorship_scheduling_line_id', '=', record.id),
('sponsorship_scheduling_line_ids', 'in', record.id),
('sponsorship_id', '=', record.sponsorship_id.id)
], order="payment_date desc", limit=1)
if payment_record and payment_record.payment_date:
now = fields.Datetime.now()
payment_datetime = fields.Datetime.to_datetime(payment_record.payment_date)
hours_passed = (now - payment_datetime).total_seconds() / 3600 # Convert seconds to hours
record.cancel_refund = hours_passed >= max_hours
else:
record.cancel_refund = False
def action_register_payment(self):
invoice_id = self.env['account.move'].sudo().search([
('takaful_sponsorship_id', '=', self.sponsorship_id.id),
('move_type', '=', 'out_invoice'),
('state', '=', 'posted'),
('payment_state', 'in', ['not_paid', 'partial'])], limit=1, order='id')
if not invoice_id:
raise ValidationError(_("No invoice found for this sponsorship."))
return {
'name': _('Register Payment'),
'res_model': 'account.payment.register',
'view_mode': 'form',
'context': {
'active_model': 'account.move',
'active_ids': invoice_id.ids,
'dont_redirect_to_payments': True,
'sponsorship_line_ids': self.donation_detail_linked_id.ids,
'default_amount': self.amount,
'default_journal_id': self.env.company.sponsorship_direct_debit_journal_id.id,
'schedule_line_payment': True,
'schedule_line_id': self.id,
'force_sponsorship_line_partner_id': self.donation_detail_linked_id.sponsor_id.id,
},
'target': 'new',
'type': 'ir.actions.act_window',
}
@api.model
def create(self, vals):
# Check if sequence_no is not already set
if vals.get('sequence_no', '/') == '/':
# Assign the next sequence number
vals['sequence_no'] = self.env['ir.sequence'].next_by_code('sponsorship.scheduling.line.sequence') or '/'
return super(SchedulingLine, self).create(vals)
@api.model
def cron_process_scheduled_payments(self):
today = fields.Date.today()
scheduled_lines = self.search([
('scheduled_date', '<=', today),
('status', '=', 'unpaid'),
])
_logger.info(f"Found {len(scheduled_lines)} scheduling lines scheduled for {today}")
for line in scheduled_lines:
donation_line = line.donation_detail_linked_id
sponsorship = donation_line.sponsorship_id or donation_line.sponsorship_mechanism_id
try:
if line.donation_detail_linked_id.direct_debit:
invoice_id = self.env['account.move'].sudo().search([
('takaful_sponsorship_id', '=', sponsorship.id),
('move_type', '=', 'out_invoice'),
('state', '=', 'posted'),
('payment_state', 'in', ['not_paid', 'partial'])
], limit=1)
if not invoice_id:
_logger.warning(f"No unpaid invoice found for sponsorship {line.sponsorship_id.code}, skipping line {line.sequence_no}")
continue
journal_id = self.env.company.sponsorship_direct_debit_journal_id
if not journal_id:
_logger.warning(f"No journal found for payment method of line {line.sequence_no}")
continue
payment_register_vals = {
'payment_date': fields.Date.today(),
'amount': line.amount,
'journal_id': journal_id.id,
'partner_bank_id': donation_line.direct_debit_partner_bank_id.id,
'communication': f"{line.sponsorship_id.code} - {line.sequence_no}",
'transaction_file_attachment': donation_line.debit_payment_file_attachment,
}
payment_register = self.env['account.payment.register'].sudo().with_context(
active_model='account.move',
active_ids=invoice_id.ids,
schedule_line_payment=True,
dont_redirect_to_payments=True,
schedule_line_id=line.id,
is_direct_debit=True,
sponsorship_id=sponsorship.id,
sponsorship_line_ids=line.donation_detail_linked_id.ids,
from_cron=True,
force_sponsorship_line_partner_id=line.donation_detail_linked_id.sponsor_id.id,
).create(payment_register_vals)
payment_register.action_create_payments()
line.sudo().write({'status': 'paid'})
if line.donation_detail_linked_id.state == 'waiting' or (not line.donation_detail_linked_id.benefit_id and line.donation_detail_linked_id.record_type == 'sponsorship'):
line.donation_detail_linked_id.sudo().write({'state': 'waiting'})
elif line.donation_detail_linked_id.record_type == 'donation':
line.donation_detail_linked_id.sudo().write({'state': 'paid'})
elif line.donation_detail_linked_id.state != 'waiting' and line.donation_detail_linked_id.record_type != 'donation' and line.donation_detail_linked_id.record_type == 'sponsorship':
line.donation_detail_linked_id.sudo().write({'state': 'active'})
line.donation_detail_linked_id.sponsorship_id.sudo().write({'state': 'wait_pay'})
_logger.info(f"Successfully processed scheduled payment for line {line.sequence_no}")
else:
_logger.warning(f"Scheduling line {line.sequence_no} payment method is not direct debit, skipping auto-payment")
except Exception as e:
_logger.error(f"Error processing scheduled payment for line {line.sequence_no}: {str(e)}")
continue
return True
def action_refund(self):
refund_amount = self.amount - self.refunded_amount
return {
'type': 'ir.actions.act_window',
'name': 'Refund Wizard',
'res_model': 'refund.wiz',
'view_mode': 'form',
'target': 'new',
'context': {'default_refund_amount': refund_amount}
}
def approve_refund(self):
self.final_refund()
self.sponsorship_id.state = 'under_refund'
def final_refund(self):
invoice_lines = []
unpaid_invoice_exists = self.env['account.move'].search(
[('takaful_sponsorship_id', '=', self.sponsorship_id.id), ('move_type', '=', 'out_refund'),
('payment_state', '!=', 'paid')])
refund_amount = self.sponsorship_id.refund_details_lines_ids.filtered(
lambda r: r.sponsorship_scheduling_line.id == self.id or self.id in r.sponsorship_scheduling_line_ids.ids and r.invoiced == False).mapped('refund_amount')[0] if self.sponsorship_id.refund_details_lines_ids else 0.0
sponsor_id = self.sponsorship_id.sponsor_id
payment_details_line = self.sponsorship_id.refund_details_lines_ids.filtered(
lambda r: r.sponsorship_scheduling_line.id == self.id or self.id in r.sponsorship_scheduling_line_ids.ids).mapped('payment_details_line')
if unpaid_invoice_exists:
raise ValidationError(_("You have Refund invoice not paid"))
# Check if product exists from donation item
product_template = self.donation_detail_linked_id.product_template_id
product = self.donation_detail_linked_id.product_id # Directly linked product
if not product:
# If no product_id exists in product_template, check if a product with the same name exists
product = self.env['product.product'].search([('name', '=', product_template.name)], limit=1)
if not product:
# Create new product if it doesn't exist
product = self.env['product.product'].create({
'name': product_template.name,
'type': 'service' # Setting type to service
})
invoice_lines.append((0, 0, {
'product_id': product.id,
'account_id': self.donation_detail_linked_id.product_template_id.property_account_income_id.id,
# The same account for all lines
'quantity': 1, # Qty is 1
# The same analytic account
'takaful_sponsorship_id': self.sponsorship_id.id,
'price_unit': refund_amount,
'analytic_account_id': self.sponsorship_id.branch_custom_id.branch.analytic_account_id.id
}))
Partner = self.env['res.partner'].sudo()
partner_id = sponsor_id or Partner.search([('name', '=', 'Cash Customer')], limit=1)
if not partner_id:
partner_id = Partner.create({
'company_type': 'person',
'name': 'Cash Customer'
})
invoice = self.env['account.move'].create({
'move_type': 'out_refund', # Refund Invoice
'partner_id': partner_id.id,
'invoice_date': fields.Date.today(),
'invoice_line_ids': invoice_lines,
'takaful_sponsorship_id': self.sponsorship_id.id,
'is_refund_sponsorship': True,
'sponsorship_scheduling_line': self.id,
'payment_details_line': payment_details_line,
})
invoice.action_post()
self.sponsorship_id.refund_details_lines_ids.write({'invoiced': True})
return invoice

View File

@ -0,0 +1,33 @@
from odoo.exceptions import UserError , ValidationError
from odoo import api, fields, models, _
class SponsorshipStates(models.Model):
_name = "sponsorship.states"
_description = "SponsorshipS States"
_rec_name = 'display_name'
name = fields.Selection([
('draft', 'Draft'),
('confirmed', 'Confirmed'),
('wait_pay', 'Enter Payment Details'),
('paid', 'Paid'),
('partial_refund', 'Partial Refund'),
('fully_refund', 'Fully Refund'),
('approve_refund', 'Approve Refund'),
('under_refund', 'Under Refund Procedure'),
('under_replacement', 'Under Replacement'),
('replacement_done', 'Replacement Done'),
('canceled', 'Canceled'),
('closed', 'Closed'),
], string='State', default='draft', required=True)
display_name = fields.Char(string="Display Name", compute='_compute_display_name')
@api.depends('name')
def _compute_display_name(self):
selection_dict = dict(self._fields['name'].selection)
for rec in self:
rec.display_name = _(selection_dict.get(rec.name, rec.name))

View File

@ -0,0 +1,133 @@
from odoo.exceptions import UserError , ValidationError
from odoo import api, fields, models, _
class DonationsItems(models.Model):
_name = "donations.items"
_description = "Donation Items"
name = fields.Char(string="Donation Name")
donation_type = fields.Selection([('donation', 'Donation'),('waqf', 'Waqf'),('sponsorship', 'Sponsorship'),], string='Donation Type')
branch_custom_id = fields.Many2one('branch.settings', string="Branch")
show_donation_item = fields.Boolean(string='Show Donation Item')
fixed_value = fields.Boolean(string='Is Fixed Value?')
fixed_donation_amount = fields.Float(string='Donation Amount')
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
account_id = fields.Many2one('account.account', string="Account",domain="[('user_type_id.id','=',13)]")
product_id = fields.Many2one('product.product', string="Product", domain="[('type', '=', 'service')]")
_quantity = fields.Float(default=0, store=True)
donation_types = fields.Selection([('donation', 'Donation'), ('waqf', 'Waqf')],string='Donation Type')
payment_method_id = fields.Many2one('takaful.payment.method', string="Payment Method")
@api.model
def create(self, vals):
"""Automatically create a product when a donation item is created"""
donation_item = super(DonationsItems, self).create(vals)
# Create a related product
product = self.env['product.product'].create({
'name': donation_item.name,
'type': 'service',
})
# Link the created product to the donation item
donation_item.product_id = product.id
return donation_item
@api.onchange('name')
def _onchange_name(self):
"""Update the related product name when the donation item name changes"""
if self.product_id:
self.product_id.name = self.name
def add_payment_method(self):
return {
'type': 'ir.actions.act_window',
'name': _('Add Details Wizard'),
'res_model': 'add.details.wiz',
'view_mode': 'form',
'target': 'new',
}
def utilizable_cart_details(self):
"""
Utilizable Cart Details For Remove , Add And Update Operations
For Cart To Product Catelog Module To Object addcart.sales.products
"""
context = self._context.copy() or {}
cart_object = self.env["donations.details.lines"]
cart_details = dict()
total_count = cart_object.search_count(
[('donation_name', '=', self.id), ('sponsorship_id', '=', context.get('sponsorship_id'))]) # , ("cart_flag", "=", True)
cart_details["total_count"] = total_count
cart_data = cart_object.search(
[('donation_name', '=', self.id), ('sponsorship_id', '=', context.get('sponsorship_id'))]) # , ("cart_flag", "=", True)
cart_details["cart_data"] = cart_data
return cart_details
def initiate_sol(self, operation, sponsorship_id):
"""
Initiate Donation Details Lines By Cart Functionality.
"""
so_object = self.env["takaful.sponsorship"]
sale_object = so_object.search([("id", "=", sponsorship_id)])
if operation == "add":
so_object.sol_by_cart(operation, self, sale_object)
elif operation == "remove":
so_object.sol_by_cart(operation, self, sale_object)
elif operation == "update":
so_object.sol_by_cart(operation, self, sale_object)
def set_quantity_so(self, quantity, operation=None):
context = self._context.copy() or {}
cart_details = self.utilizable_cart_details()
if operation == "remove":
self._quantity -= quantity
if cart_details.get("total_count") != 0:
self.initiate_sol("remove", context.get("sponsorship_id"))
else:
if self._quantity == 0:
self._quantity += quantity
if cart_details.get("total_count") != 0:
self.initiate_sol("update", context.get("sponsorship_id"))
else:
self.initiate_sol("add", context.get("sponsorship_id"))
def remove_quantity_button_so(self):
if self._quantity == 0:
self._quantity = 0
return
return self.set_quantity_so(1, operation="remove")
def add_quantity_button_so(self):
return self.set_quantity_so(1, operation="add")
class PointsOfSaleCustom(models.Model):
_name = "points.of.sale.custom"
_description = "Points Of Sale Custom"
name = fields.Char(string="Sequence/Point Name",readonly=True)
department_name = fields.Selection([('men', 'Men'),('women', 'Women')], string='Department Name')
branch_custom_ids = fields.Many2many('branch.settings',relation='points_sale_branch_settings_rel',column1='points_sale_id', column2='branch_id',string="Branch")
journal_id = fields.Many2one('account.journal', string="Journal",domain="[('type','=','bank')]")
@api.model
def create(self, vals):
res = super(PointsOfSaleCustom, self).create(vals)
if not res.name or res.name == _('New'):
res.name = self.env['ir.sequence'].sudo().next_by_code('point.of.sale.sequence') or _('New')
return res
class RefundReason(models.Model):
_name = "refund.reasons"
_description = "Refund Reason"
name = fields.Char(string="Name")

View File

@ -0,0 +1,122 @@
# -*- coding: utf-8 -*-
from odoo.exceptions import UserError , ValidationError
from odoo import api, fields, models, _
import logging
_logger = logging.getLogger(__name__)
class TakafulContribution(models.Model):
_name = "takaful.contribution"
_description = "Financial Contribution"
name = fields.Char(string="Operation Name")
sponsor_id = fields.Many2one(
'res.partner',
string='The Sponsor',
ondelete='set null'
)
need_id = fields.Many2one('benefits.needs')
benefit_id = fields.Many2one(
'grant.benefit',
string='Beneficiary',
ondelete='set null'
)
benefit_ids = fields.Many2many(
'grant.benefit',
string='Beneficiaries'
)
benefit_type = fields.Selection([
('orphan', 'Orphans'),
('widow', 'Widows'),
('general', 'General')],
string='Beneficiaries Type',
compute='_compute_benefit_type_values',
related=False,
readonly=True,
)
operation_type = fields.Selection([
('contribution', 'Needs Contribution'),
('gift', 'Financial Gift')],
string='Operation Type',
)
amount = fields.Float(string="Amount")
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
note = fields.Text(string='Note/Message')
date = fields.Datetime(string="Date", default=fields.Datetime.now)
entry_id = fields.Many2one('account.move', string="Entry")
is_confirmed = fields.Boolean(default=False)
def _compute_benefit_type_values(self):
for rec in self:
b_type = []
if rec.benefit_ids:
for i in rec.benefit_ids:
b_type.append(i.benefit_type)
if rec.benefit_id:
b_type.append(rec.benefit_id.benefit_type)
if 'orphan' in b_type and 'widow' not in b_type:
rec.benefit_type = 'orphan'
if 'widow' in b_type and 'orphan' not in b_type:
rec.benefit_type = 'widow'
if 'widow' in b_type and 'orphan' in b_type:
rec.benefit_type = 'general'
if b_type == []:
rec.benefit_type = ''
def create_entry(self):
sudoConf = self.env['ir.config_parameter'].sudo()
journal_id = sudoConf.get_param('odex_takaful_base.kafala_journal_id', default=False)
if not journal_id:
# Raise an error
raise ValidationError(
_(u'No Journal for Sponsorships, Please configure it'))
need_inv = self.env['needs.payment.line'].sudo().create({
"need_id" : self.need_id.id,
"invoice_id" : inv.id,
})
product_id = self.env['product.product'].search([('default_code', '=', 'financial_gift')], limit=1)
partner_id = self.sponsor_id
product_id.sudo().write({
"list_price": self.amount,
})
# Do your staf ..
this_products_line = [[0, 0, {'product_id': product_id.id,
'tax_id': False,
}]
]
so_id = self.env['sale.order'].create({
'partner_id': partner_id.id,
'partner_invoice_id': partner_id.id,
'partner_shipping_id': partner_id.id,
'client_order_ref': u'مساهمة مالية',
'note': u'مساهمة مالية لصالح:' + '\n' + (self.benefit_id.name if self.benefit_id else ""),
'order_line': this_products_line
})
# Invoicing
so_id.action_confirm()
inv_id = so_id.action_invoice_create()
inv = self.env['account.move'].browse(inv_id)
inv.journal_id = int(journal_id)
move_name = u'مساهمة مالية بالأمر %s' % inv.origin
ctx = self.env.context.copy()
ctx.update({'sponsorship' : {
'name': move_name,
'ref': inv.origin,
}
})
inv.with_context(ctx).action_invoice_open()
self.entry_id = inv.move_id.id

View File

@ -0,0 +1,372 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from datetime import datetime, date, timedelta
from datetime import timedelta
from dateutil.relativedelta import relativedelta
from dateutil.parser import parse
from odoo.exceptions import UserError, ValidationError, Warning
import logging
_logger = logging.getLogger(__name__)
class TakafulGrantBenefit(models.Model):
_inherit = "grant.benefit"
is_active_sponsorship = fields.Boolean(
string="Currently Has Sponsorship?", compute='_get_sponsorship_ids')
sponsorship_ids = fields.Many2many(
'takaful.sponsorship', string='Sponsorships', compute='_get_sponsorship_ids')
has_kafala_delay = fields.Boolean(
string='Has Kafala Delay?', compute='_get_sponsorship_ids')
overdue_kafalat_amount = fields.Float(
string="Current Overdue Kafalat Amount", compute='_get_sponsorship_ids')
# These fields work to calculate the value of the need and its percentage
total_kafala_value = fields.Integer(
string='Total Kafala Value', compute='_needs_value')
benefit_needs_value = fields.Float(compute='_needs_value')
benefit_needs_percent = fields.Float(compute='_needs_value')
# Monthly sponsorship Payments
# sponsorship_payment_ids = fields.One2many(
# 'benefit.sponsorship.payment.line',
# 'benefit_id', 'Sponsorship Monthly Payments')
# @api.onchange('arrears_ids')
# def _compute_sponsorships_arrears(self):
# for rec in self:
# rec.benefit_arrears_value = sum(rec.arrears_ids.mapped('arrears_total'))
@api.onchange('total_expenses', 'total_income')
def _needs_value(self):
for rec in self:
rec.total_kafala_value = rec.total_expenses
kafala_income = 0.0
for kafala in rec.sponsorship_ids:
# if kafala.state not in ['draft', 'canceled', 'closed']: #todo
kafala_income += kafala.contribution_value
rec.benefit_needs_value = abs(
rec.total_expenses - rec.total_income - kafala_income) # todo
try:
rec.benefit_needs_percent = 100 - \
(((rec.total_income + kafala_income) / rec.total_kafala_value) * 100)
except:
rec.benefit_needs_percent = 0.0
pass
def _get_sponsorship_ids(self):
""" Get Sponsorships of Benefit"""
for rec in self:
sponsorships = self.env['takaful.sponsorship'].sudo().search(
[('benefit_id', '=', rec.id), ('state', 'in', ['wait_pay', 'progress', 'to_cancel'])])
overdue_kafala = 0
ls_ids = []
today = datetime.today().date().replace(day=1)
for spon in sponsorships:
spon._compute_next_due_date()
ls_ids.append(spon.id)
if spon.has_delay:
start_date = parse(str(spon.start_date)).date().replace(day=1)
if spon.paid_month_count > 0:
last_pay_date = start_date + \
relativedelta(months=spon.paid_month_count)
else:
spon._compute_next_due_date()
last_pay_date = (spon.next_due_date or start_date +
relativedelta(months=spon.paid_month_count))
if spon.paid_month_count == 0:
num_months = 1
else:
num_months = (today.year - last_pay_date.year) * \
12 + (today.month - last_pay_date.month)
overdue_kafala += (num_months * spon.contribution_value)
if ls_ids:
rec.sponsorship_ids = [(6, 0, ls_ids)]
rec.is_active_sponsorship = True
else:
rec.sponsorship_ids = [(6, 0, [])]
rec.is_active_sponsorship = False
if overdue_kafala > 0:
rec.has_kafala_delay = True
rec.overdue_kafalat_amount = overdue_kafala
else:
rec.has_kafala_delay = False
rec.overdue_kafalat_amount = 0
class GrantBenefitInvoice(models.Model):
_name = "grant.benefit.invoice"
_description = 'Invoice for Beneficiaries'
# _rec_name = 'code'
benefit_ids = fields.Many2many('grant.benefit', string='Beneficiaries')
operation_invoice_id = fields.Many2one('account.move',
string="Invoice", ondelete='set null', readonly=True)
operation_code = fields.Char(string='Operation Code', readonly=True)
operation_type = fields.Selection([
('sponsorship', 'Sponsorship'),
('financial_gift', 'Financial Gift'),
('need_contribution', 'Needs Contribution')],
string='Operation Type',
)
operation_id = fields.Integer(readonly=True)
benefit_type = fields.Selection([
('orphan', 'Orphans'),
('widow', 'Widows')],
string='Beneficiaries Type',
)
benefit_target = fields.Selection([
('person', 'Individual'),
('group', 'Group')],
string='Target of Beneficiaries',
)
paid_amount = fields.Float(string='Paid Amount', readonly=True)
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
partner_id = fields.Many2one('res.partner', string='From',
store=True,
related='operation_invoice_id.partner_id')
journal_id = fields.Many2one('account.journal', string='Journal',
store=True,
related='operation_invoice_id.journal_id')
due_date = fields.Date(string='Due Date', store=True,
related='operation_invoice_id.invoice_date')
due_code = fields.Char(string='Due Code', store=True,
compute='_get_due_code', )
payment_date = fields.Date(string='Payment Date', readonly=True)
note = fields.Text(string='Note/Message')
is_recorded = fields.Boolean(
string='Is Recorded In Beneficiaries', default=False)
def _get_due_code(self):
""" Extract due code from due date """
for rec in self:
if rec.due_date:
date = parse(str(rec.due_date)).date()
rec.due_code = date.strftime("%Y_%m")
class AccountInvoice(models.Model):
_inherit = "account.move"
benefit_invoice_ids = fields.One2many('grant.benefit.invoice', 'operation_invoice_id',
string='The Beneficiaries', ondelete='restrict')
class AccountPayment(models.Model):
_inherit = "account.payment"
direct_debit = fields.Boolean(string='Direct Debit', default=False)
is_benefit_registered = fields.Boolean(
string='Is Registered To Beneficiary', default=False)
def sponsorship_validate_invoice_payment(self, invoice):
sponsorship_obj = self.env['takaful.sponsorship'].sudo().browse(
invoice.operation_id)
# Create an invoice for benefits.
benefit_invoice = self.env['grant.benefit.invoice'].sudo().create({
'operation_invoice_id': invoice.id,
'operation_type': 'sponsorship',
'operation_id': sponsorship_obj.id,
'operation_code': sponsorship_obj.code,
'benefit_type': sponsorship_obj.benefit_type,
'benefit_target': sponsorship_obj.sponsorship_type,
'paid_amount': self.amount,
'payment_date': self.payment_date,
})
if sponsorship_obj.sponsorship_type == 'person':
benefit_invoice.write(
{'benefit_ids': [(4, sponsorship_obj.benefit_id.id)]})
else:
for benefit in sponsorship_obj.benefit_ids:
benefit_invoice.write({'benefit_ids': [(4, benefit.id)]})
if invoice.state == 'paid':
self.is_benefit_registered = True
# Change State
if not sponsorship_obj.has_delay:
sponsorship_obj.state = "progress"
# Send SMS and Email Notifications
paid_template = self.env['takaful.message.template'].search(
[('template_name', '=', 'sponsorship_paid')], limit=1)
subject = paid_template.title
message = paid_template.body + '\n' + _('Sponsorship: ') + '{}'.format(sponsorship_obj.code) + '\n' + _(
'Paid Value: ') + '{}'.format(self.amount) + '\n' + _('Invoice Ref: ') + '{}'.format(invoice.number)
user_id = sponsorship_obj.sponsor_id.user_id
push = self.env['takaful.push.notification'].sudo().create({
'user_id': user_id.id,
'title': subject,
'body': message,
})
push.sudo().send_sms_notification()
push.sudo().send_email_notification()
def action_validate_invoice_payment(self):
res = super(AccountPayment, self).action_validate_invoice_payment()
# Handle payment for every invoice
for invoice in self.invoice_ids:
# move = invoice.invoice_id
if invoice.operation_type == 'sponsorship':
self.sudo().sponsorship_validate_invoice_payment(invoice)
return res
class TakafulGrantBenefit(models.Model):
_inherit = "grant.benefit"
@api.model
def create(self, values):
name = values.get('name', False)
if name is False:
first_name = values.get('first_name')
second_name = values.get('second_name')
middle_name = values.get('middle_name')
family_name = values.get('family_name')
name = ''
if all([second_name,first_name,middle_name,family_name]):
name = first_name + " " + second_name + " " + middle_name + " " + family_name
values.update({'name': name})
values.update({'lang': 'ar_001'})
values.update({'tz': 'Asia/Riyadh'})
return super(TakafulGrantBenefit, self).create(values)
arrears_ids = fields.One2many(
'sponsorship.benefit.arrears', 'sponsor_id', string="Sponsorships Arrears")
benefit_arrears_value = fields.Float(
string='Total Sponsorships Arrears', compute='_compute_sponsorships_arrears', store=True)
has_arrears = fields.Boolean(
string='Has Arrears', compute='_compute_sponsorships_arrears', store=True)
# analytic_account_id = fields.Many2one(
# 'account.analytic.account', 'Cost Center')
def finish_complete_data(self):
for rec in self:
res = super(TakafulGrantBenefit, self).finish_complete_data()
# main_analytic_account_id = ""
# self.ensure_one()
# sudoConf = self.env['ir.config_parameter'].sudo()
# main_widows_analytic_account_id = sudoConf.get_param(
# 'odex_benefit.main_widows_analytic_account_id', default=False)
# main_orphan_analytic_account_id = sudoConf.get_param(
# 'odex_benefit.main_orphan_analytic_account_id', default=False)
# if rec.benefit_type == "orphan":
# if not main_orphan_analytic_account_id:
# raise ValidationError(
# _(''' Please set orphan restricted income account in settings '''))
# main_analytic_account_id = main_orphan_analytic_account_id
# elif rec.benefit_type == "widow":
# if not main_widows_analytic_account_id:
# raise ValidationError(
# _(''' Please set widow restricted income account in settings '''))
# main_analytic_account_id = main_widows_analytic_account_id
# if main_analytic_account_id and not rec.analytic_account_id:
# ID = self.env['account.analytic.account'].create({'parent_id': main_analytic_account_id,'name': rec.name})
# rec.write({'analytic_account_id': ID.id})
def action_accepted(self):
for rec in self:
res = super(TakafulGrantBenefit, self).action_accepted()
# main_analytic_account_id = ""
# self.ensure_one()
# sudoConf = self.env['ir.config_parameter'].sudo()
# main_widows_analytic_account_id = sudoConf.get_param(
# 'odex_benefit.main_widows_analytic_account_id', default=False)
# main_orphan_analytic_account_id = sudoConf.get_param(
# 'odex_benefit.main_orphan_analytic_account_id', default=False)
# if rec.benefit_type == "orphan":
# if not main_orphan_analytic_account_id:
# raise ValidationError(
# _(''' Please set orphan restricted income account in settings '''))
# main_analytic_account_id = main_orphan_analytic_account_id
# elif rec.benefit_type == "widow":
# if not main_widows_analytic_account_id:
# raise ValidationError(
# _(''' Please set widow restricted income account in settings '''))
# main_analytic_account_id = main_widows_analytic_account_id
# if main_analytic_account_id and not rec.analytic_account_id:
# ID = self.env['account.analytic.account'].create({'parent_id': main_analytic_account_id,'name': rec.name})
# rec.write({'analytic_account_id': ID.id})
@api.onchange('arrears_ids')
def _compute_sponsorships_arrears(self):
for rec in self:
rec.benefit_arrears_value = sum(
rec.arrears_ids.mapped('arrears_total'))
if rec.benefit_arrears_value > 0:
rec.has_arrears = True
else:
rec.has_arrears = False
class SponsorshipBenefitArrears(models.Model):
_name = "sponsorship.benefit.arrears"
_description = 'Sponsorship Arrears for a Beneficiary'
_rec_name = 'code'
benefit_id = fields.Many2one('grant.benefit', string='Beneficiary')
benefit_type = fields.Selection(
string="Beneficiary Type", related="benefit_id.benefit_type", store=True)
sponsorship_id = fields.Many2one(
'takaful.sponsorship',
string='Sponsorship'
)
sponsor_id = fields.Many2one(
'res.partner',
string='The Sponsor',
ondelete='set null'
)
code = fields.Char(string="Sponsorship Number",
related="sponsorship_id.code", store=True)
month_amount = fields.Float(string="Month Sponsorship Amount",
related="sponsorship_id.load_amount", store=True, readonly=True)
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
arrears_month_number = fields.Integer(string="Arrears Months Number")
arrears_total = fields.Float(string="Arrears Total")
date = fields.Date('Date', readonly=True, default=fields.Date.today())
is_paid = fields.Float(string="Is Paid", compute='_get_arrears_amount')
paid_amount = fields.Float(
string="Paid Amount", compute='_get_arrears_amount', store=True)
arrears_amount = fields.Float(
string="Remine Arrears Amount", compute='_get_arrears_amount', store=True)
invoice_ids = fields.Many2many(
'account.move', string='Payment Invoices')
def _get_arrears_amount(self):
""" Compute Arrears Amount, Paid and Remine"""
for rec in self:
if rec.invoice_ids:
paid_amount = 0
for inv in rec.invoice_ids:
if inv.state == 'paid':
paid_amount += inv.amount
if paid_amount > 0:
rec.paid_amount = paid_amount
rec.arrears_amount = abs(rec.arrears_total - paid_amount)
else:
rec.paid_amount = 0
rec.arrears_amount = rec.arrears_total
if paid_amount >= rec.arrears_total:
rec.is_paid = True
else:
rec.is_paid = False
else:
rec.is_paid = False
rec.arrears_amount = rec.arrears_total

View File

@ -0,0 +1,268 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from datetime import datetime, date, timedelta
from odoo.exceptions import UserError, ValidationError
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from ..utils import formats
from dateutil.relativedelta import relativedelta
from dateutil.parser import parse
import logging
_logger = logging.getLogger(__name__)
class MonthPayment(models.Model):
_name = 'month.payment'
_inherit = ['mail.thread', 'mail.activity.mixin']
name = fields.Char(string="Name")
code = fields.Char(string="Code", copy=False, readonly=True, default=lambda x: _('New'))
journal_id = fields.Many2one('account.journal')
account_id = fields.Many2one('account.account', )
date = fields.Date(string="Date", default=fields.Datetime.now)
amount = fields.Float(string="Total Amount", compute='_compute_payment_total', store=True)
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
count = fields.Integer(string="Count", compute='_compute_payment_total', store=True)
user_id = fields.Many2one('res.users', string="Issued By", default=lambda self: self.env.user)
company_id = fields.Many2one('res.company', string="Company", default=lambda self: self.env.user.company_id)
line_ids = fields.One2many('month.payment.line', 'month_id', string="Lines")
due_invoice_ids = fields.Many2many('grant.benefit.invoice', string="Due Payments")
state = fields.Selection([
('draft', 'Draft'),
('create', 'Create Lines'),
('approve', 'Approved'),
('submit', 'Submit To Pay'),
('paid', 'Paid'),
('refused', 'Refused'),
('cancel', 'Cancel'),
], string='state', default="draft", tracking=True)
month_code = fields.Char(string="Month Code", store=True, compute='_compute_payment_month_code')
entry_id = fields.Many2one('account.move', string="Entry")
@api.depends('line_ids')
def _compute_payment_total(self):
for rec in self:
if rec.line_ids:
rec.amount = sum(rec.line_ids.mapped('amount'))
rec.count = len(rec.line_ids)
else:
rec.amount = 0
rec.count = 0
@api.onchange('name', 'date')
def _compute_payment_name(self):
if self.date and not self.name:
date = parse(str(self.date)).date()
self.name = _('Sponsorship Due Payments') + ' {}'.format(date.strftime("%m-%Y"))
def _compute_payment_month_code(self):
""" Extract month code from date """
for rec in self:
if rec.date:
date = parse(str(rec.date)).date()
rec.month_code = date.strftime("%Y_%m")
@api.model
def create(self, vals):
res = super(MonthPayment, self).create(vals)
if not res.code or res.code == _('New'):
res.code = self.env['ir.sequence'].sudo().next_by_code('month.payment.sequence') or _('New')
return res
def open_payments(self):
return {
'name': _('Payments'),
'view_type': 'form',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_takaful.benefit_month_payment_line_tree').id, 'tree'),
(self.env.ref('odex_takaful.benefit_month_payment_line_form').id, 'form')],
'res_model': 'month.payment.line',
'type': 'ir.actions.act_window',
'domain': "[('month_id','=',%s)]" % (self.id),
'target': 'current',
}
def action_create_lines(self):
if not self.line_ids:
due_invoices = self.env['grant.benefit.invoice'].sudo().search([
('operation_type', '=', 'sponsorship'),
('due_code', '=', self.month_code),
('is_recorded', '=', False),
])
for rec in due_invoices:
if rec.benefit_target == "person" and len(rec.benefit_ids) ==1:
line = self.env['month.payment.line'].sudo().create({
'month_id': self.id,
'sponsorship_id': rec.operation_id,
'benefit_id': rec.benefit_ids[0].id,
'responsible_id': rec.benefit_ids[0].responsible_id.id if rec.benefit_ids[0].responsible_id else False,
'partner_id': rec.benefit_ids[0].responsible_id.partner_id.id if rec.benefit_ids[0].responsible_id else False,
'amount': rec.paid_amount,
'date': datetime.now(),
})
else:
amount = (rec.paid_amount / len(rec.benefit_ids))
now = datetime.now()
for ben in rec.benefit_ids:
line = self.env['month.payment.line'].sudo().create({
'month_id': self.id,
'sponsorship_id': rec.operation_id,
'benefit_id': ben.id,
'responsible_id': ben.responsible_id.id if ben.responsible_id else False,
'partner_id': ben.responsible_id.partner_id.id if ben.responsible_id else False,
'amount': amount,
'date': now,
})
self.write({'due_invoice_ids': [(4, rec.id)]})
# Now true for rec.is_recorded
# rec.is_recorded = True
self.state = 'create'
def create_entry(self):
move_name = self.name + ' - %s' % self.code
move_id = self.env['account.move'].sudo().create({
'name': move_name,
'journal_id': self.company_id.kafala_benefit_journal_id.id,
'ref': self.code})
move_line = []
move_line.append({
'debit': self.amount,
'credit': 0.0,
'account_id': self.company_id.kafala_benefit_account_id.id,
})
move_line.append({
'debit': 0.0,
'credit': self.amount,
'account_id': self.company_id.kafala_benefit_bank_account_id.id,
})
move_id.write({'line_ids': [(0, 0, line) for line in move_line]})
move_id.post()
self.entry_id = move_id.id
for inv in self.due_invoice_ids:
inv.is_recorded = True
def action_notify(self):
if self.state == 'submit':
payment = self.env['month.payment.line'].search([('month_id', '=', self.id)])
for i in payment:
if i.responsible_id.email:
email_from = self.env.user.company_id.email
company_name = self.env.user.company_id.name
template_id = self.env.ref('odex_takaful.push_notification_email_template').id
context = {
'email_from': email_from,
'email_to': i.responsible_id.email,
'partner_name': i.responsible_id.name,
'body': _("You have recieved money in tolal of %s in your account.") % str(i.amount),
'title': _("Recieving Money"),
'company_name': company_name
}
# Start to SEND Email
self.env['mail.template'].browse(template_id).with_context(context).send_mail(self.id, force_send=True, raise_exception=False)
self.state = 'paid'
else:
raise ValidationError(
_(u' No benefits for pay'))
def action_approve(self):
if self.line_ids:
self.sudo().create_entry()
self.state = 'approve'
def action_refuse(self):
self.state = 'refused'
def action_submit(self):
self.state = 'submit'
def action_cancel(self):
for i in self.line_ids:
i.sudo().unlink()
self.state = 'cancel'
class MonthPaymentLine(models.Model):
_name = 'month.payment.line'
_rec_name = 'month_id'
month_id = fields.Many2one('month.payment')
sponsorship_id = fields.Many2one("takaful.sponsorship", string="Sponsorship")
s_code = fields.Char(string="Sponsorship Number", related="sponsorship_id.code",store=True)
sponsor_id = fields.Many2one(string="The Sponsor", related="sponsorship_id.sponsor_id",store=True)
benefit_id = fields.Many2one('grant.benefit', string="Benefit")
benefit_type = fields.Selection(string="Benefit Type", related="benefit_id.benefit_type",store=True)
responsible_id = fields.Many2one('grant.benefit', string="Responsible Benefit")
partner_id = fields.Many2one('res.partner', string="Responsible Partner")
date = fields.Date(string="Date")
state = fields.Selection(related="month_id.state", store=True)
code = fields.Char(related="month_id.code", store=True)
amount = fields.Float(string="Amount")
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
"""
@api.model
def payment_cron(self):
payment = self.env['month.payment'].search([('state', '=', 'approve'), ('date', '=', str(datetime.now().date())),
('line_ids', '=', False)], limit=1)
if payment:
payment.action_create_lines()
def create_records(self, benefits, support=False):
if benefits:
self.sudo().is_benefits = True
for p in benefits:
p.get_amount_month()
amount = float("{:.2f}".format(p.amount * self.amount))
if self.is_appendix:
payment = self.env['month.payment.line'].search([('month_id', '=', self.parent_id.id)])
for i in payment:
amount += i.amount
line = self.env['month.payment.line'].sudo().create({
'month_id': self.id,
'benefit_id': p.id,
'responsible_id': p.id if not support else p.parent_id.id,
'amount': amount,
'date': datetime.now(),
})
if self.is_appendix:
payment = self.env['month.payment.line'].search([('month_id', '=', self.id)])
self.amount = 0.0
for pay in payment:
self.amount += pay.amount
def action_create_lines(self):
if not self.line_ids:
if not self.parent_id:
benefit = self.env['grant.benefit'].search([('state', '=', 'approve')])
benefits = benefit.filtered(lambda r: r.benefit_type in ['benefit', 'support'])
self.create_records(benefits)
parent = benefit.filtered(lambda r: r.benefit_type == 'parent')
self.get_child(parent)
self.get_child(benefits)
else:
ben = self.parent_id.line_ids.mapped('benefit_id')
benefit = self.env['grant.benefit'].search([('state', '=', 'approve')])
benefits = benefit.filtered(lambda r: r.benefit_type in ['benefit', 'support'] and r.id not in ben.ids)
self.create_records(benefits)
parent = benefit.filtered(lambda r: r.benefit_type == 'parent')
self.get_child(parent, sub=ben.ids)
self.get_child(benefits, sub=ben.ids)
self.state = 'create'
"""

View File

@ -0,0 +1,61 @@
from odoo import models, fields, api, _
class TakafulNotification(models.Model):
_inherit = 'takaful.notification'
name = fields.Char(string='Notification Name', required=True)
notification_type = fields.Selection([
('create_kafala', _('Create Kafala')),
('before_finish', _('Before Kafala End Date')),
('after_kafala_end', _('After Kafala End Date')),
('cancel_kafala', _('Cancel Kafala')),
('refund_full_kafala', _('Fully Refund Kafala')),
('refund_partial_kafala', _('Partially refund Kafala')),
('replace_orphan', _('Replace Orphan / Widow')),
('full_payment', _('Full Payment')),
('partial_payment', _('Partial Payment')),
('before_cancel', _('Before Cancel')),
],
string='Notification Type',
default='create_kafala',
required=True
)
notification_state_ids = fields.Many2many('sponsorship.states', required=True)
message = fields.Html(string="Message")
@api.onchange('notification_type')
def _onchange_notification_type(self):
"""Filter available states based on notification_type."""
if not self.notification_type:
return
allowed_states = {
'create_kafala': ['draft'],
'before_finish': ['confirmed', 'wait_pay'],
'after_kafala_end': ['paid', 'closed'],
'cancel_kafala': ['canceled'],
'refund_full_kafala': ['fully_refund'],
'refund_partial_kafala': ['partial_refund'],
'replace_orphan': ['under_replacement', 'replacement_done'],
'full_payment': ['paid'],
'partial_payment': ['wait_pay'],
'before_cancel': ['confirmed'],
}
state_names = allowed_states.get(self.notification_type, [])
domain = [('name', 'in', state_names)]
if allowed_states:
self.notification_state_ids = self.env['sponsorship.states'].search(domain)
return {
'domain': {
'notification_state_ids': domain
}
}

View File

@ -0,0 +1,18 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
class TakafulPaymentMethod(models.Model):
_name = 'takaful.payment.method'
name = fields.Char(required=True)
payment_method = fields.Selection([
("cash", "Cash"),
("bank", "Bank Transfer"),
("direct_debit", "Direct Debit"),
("check", "Check"),
("network", "Network"),
], required=True)
journal_id = fields.Many2one('account.journal', string="Journal", required=True)

View File

@ -0,0 +1,92 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, _
from odoo.exceptions import UserError
class TakafulMessageTemplate(models.Model):
_name = "takaful.message.template"
_description = "Message Template"
_rec_name = 'title'
title = fields.Char(string='Subject')
body = fields.Text(string='Message', required=True)
template_name = fields.Char('Template Name', readonly=True, copy=False)
_sql_constraints = [
('template_name_uniq', 'unique (template_name)', 'Template Name Is Already Exist!')
]
class TakafulPushNotification(models.Model):
_name = 'takaful.push.notification'
_description = 'Push Notification'
user_id = fields.Many2one('res.users', string="Sponsor User", required=True)
email = fields.Char(string='Email', related='user_id.login',store=True)
mobile = fields.Char(string='Mobile', related='user_id.phone',store=True)
title = fields.Char(string='Subject')
body = fields.Text(string='Message', required=True)
sent_on = fields.Datetime(string="Sent On", default=fields.Datetime.now)
is_read = fields.Boolean(string="Seen", default=False)
# @api.multi
def send_sms_notification(self):
self.ensure_one()
return self.user_id.partner_id.sudo().send_sms_notification(body=self.body, phone=self.mobile)
# @api.multi
def send_email_notification(self):
self.ensure_one()
if not all([self.email, self.body]):
# Missing email message information"
return False
email_from = self.env.user.company_id.email
company_name = self.env.user.company_id.name
template_id = self.env.ref('odex_takaful.push_notification_email_template').id
context = {
'email_from': email_from,
'email_to': self.email,
'partner_name': self.user_id.partner_id.name,
'body': self.body,
'title': self.title or _("Notification"),
'company_name': company_name
}
try:
# Start to SEND Email
self.env['mail.template'].browse(template_id).with_context(context).send_mail(self.id, force_send=True)
except Exception as e:
return False
"""
And getting the values (context) in email template
${ctx.get('your_key')}
"""
# Email is SENT ...
return True
# @api.multi
def send_all(self):
self.ensure_one()
for tool in self.notification_type_ids:
if tool.tool_type == "sms":
sms = self.send_sms_notification()
if sms:
print("SMS is sent.")
elif tool.tool_type == "app":
print("App message is sent.")
elif tool.tool_type == "email":
email= self.send_email_notification()
if email:
print("Email is sent.")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,74 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, _
from dateutil.parser import parse
class TakafulSponsorOperation(models.Model):
_name = 'takaful.sponsor.operation'
# _rec_name = 'sponsor_id'
name = fields.Char(string="Operation Name")
title = fields.Char(string="Operation Title")
sponsor_id = fields.Many2one(
'res.partner',
string='The Sponsor',
ondelete='set null'
)
benefit_ids = fields.Many2many(
'grant.benefit',
string='Beneficiaries'
)
benefit_id = fields.Many2one(
'grant.benefit',
string='Beneficiary',
ondelete='set null'
)
benefit_type = fields.Selection([
('orphan', 'Orphans'),
('widow', 'Widows'),
('general', 'General')],
string='Beneficiaries Type',
compute='_compute_benefit_type_value',
related=False,
readonly=True,
)
operation_type = fields.Selection([
('sponsorship', 'Sponsorship'),
('contribution', 'Needs Contribution'),
('gift', 'Financial Gift')],
string='Operation Type',
)
date = fields.Date(string="Date", default=fields.Date.today)
operation_on = fields.Datetime(string="Operation Time", default=fields.Datetime.now)
month = fields.Integer(string="The Month", compute='_compute_period_filter')
origin_id = fields.Integer(readonly=True)
period_code = fields.Char(string="Period Code", compute='_compute_period_filter')
amount = fields.Float(string="Amount")
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
def _compute_period_filter(self):
""" Extract period code from date """
for rec in self:
if rec.date:
date = parse(str(rec.date)).date()
rec.period_code = date.strftime("%Y_%m")
rec.month = int(date.strftime("%m"))
def _compute_benefit_type_value(self):
for rec in self:
b_type = []
if rec.benefit_ids:
for i in rec.benefit_ids:
b_type.append(i.benefit_type)
if rec.benefit_id:
b_type.append(rec.benefit_id.benefit_type)
if 'orphan' in b_type and 'widow' not in b_type:
rec.benefit_type = 'orphan'
if 'widow' in b_type and 'orphan' not in b_type:
rec.benefit_type = 'widow'
if 'widow' in b_type and 'orphan' in b_type:
rec.benefit_type = 'general'
if b_type == []:
rec.benefit_type = ''

View File

@ -0,0 +1,110 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo import SUPERUSER_ID
class SponsorshipStopReason(models.Model):
_name = "sponsorship.reason.stop"
_description = "Sponsorship Stop Reason"
_order = 'sequence'
sequence = fields.Integer(help="Determine the display order", index=True,
string='Sequence')
name = fields.Char(string='Reason', required=True)
class SponsorshipCancellation(models.Model):
_name = 'sponsorship.cancellation'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "Sponsorship Cancellation"
_rec_name = "code"
sponsorship_id = fields.Many2one("takaful.sponsorship", string="Sponsorship")
code = fields.Char(string="Sponsorship Number", related="sponsorship_id.code",store=True)
sponsor_id = fields.Many2one(string="The Sponsor", related="sponsorship_id.sponsor_id",store=True)
create_date = fields.Date(string='Create Date', readonly=True, default=fields.Date.today)
confirm_date = fields.Date(string='Confirm Date', readonly=True)
cancel_type = fields.Selection([
('user', 'Manually'),
('sys', 'Automatically'),
], string='Cancellation Type', default="user", readonly=True)
cancel_user_id = fields.Many2one('res.users', 'Cancelled By', readonly=True)
confirm_user_id = fields.Many2one('res.users', 'Confirmed By', readonly=True)
reason_id = fields.Many2one('sponsorship.reason.stop', string='Cancellation Reason')
note = fields.Text(string='Comment')
state = fields.Selection([
('draft', 'Draft'),
('cancel', 'Cancelled'),
], string='state', default="draft")
# @api.multi
def do_cancel_action(self):
"""Confirm cancellation for Sponsorship"""
for rec in self:
if rec.sponsorship_id:
rec.confirm_user_id = self.env.uid or SUPERUSER_ID
rec.confirm_date = fields.Date.today()
rec.state = "cancel"
# Send SMS and Email Notifications
canceled_template = self.env['takaful.message.template'].sudo().search(
[('template_name', '=', 'sponsorship_canceled')], limit=1)
subject = canceled_template.title
message = canceled_template.body
partner_id = rec.sponsor_id
user_id = self.env['res.users'].sudo().search([('partner_id', '=', partner_id.id)], limit=1)
push = self.env['takaful.push.notification'].sudo().create({
'user_id': user_id.id,
'title': subject,
'body': message,
})
push.sudo().send_sms_notification()
push.sudo().send_email_notification()
month_count = 0
residual_amount = 0
# Get other open invoices
open_invoices = self.env['account.move'].sudo().search([('state', '=', 'open'), ('operation_id', '=', rec.sponsorship_id.id), ('operation_type', '=', 'sponsorship')])
for inv in open_invoices:
# Get residual amount
month_count += 1
residual_amount += inv.residual_company_signed
# Enable Removing for journal_id
if inv.journal_id:
inv.journal_id.sudo().write({"update_posted": True,})
inv.sudo().action_cancel()
rec.sponsorship_id.journal_entry_ids.button_draft()
rec.sponsorship_id.journal_entry_ids.button_cancel()
rec.sponsorship_id.state = "canceled"
rec.sponsorship_id.cancel_reason_id = self.id
# Moving the arrears
if month_count >0 and rec.sponsorship_id.sponsorship_type =='person':
arrears_id = self.env['sponsorship.benefit.arrears'].sudo().create({
'sponsorship_id': rec.sponsorship_id.id,
'benefit_id': rec.sponsorship_id.benefit_id.id,
'sponsor_id': rec.sponsorship_id.sponsor_id.id,
'arrears_month_number': month_count,
'arrears_total': residual_amount,
})
elif month_count >0 and rec.sponsorship_id.sponsorship_type =='group':
for ben in rec.sponsorship_id.benefit_ids:
arrears_id = self.env['sponsorship.benefit.arrears'].sudo().create({
'sponsorship_id': rec.sponsorship_id.id,
'benefit_id': ben.id,
'sponsor_id': rec.sponsorship_id.sponsor_id.id,
'arrears_month_number': month_count,
'arrears_total': rec.sponsorship_id.load_amount * month_count,
})

View File

@ -0,0 +1,217 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from dateutil.parser import parse
from odoo.exceptions import UserError,ValidationError, Warning
import logging
_logger = logging.getLogger(__name__)
class SponsorshipPayment(models.Model):
_name = 'sponsorship.payment'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "Payments for Sponsorship system in Takaful project"
_rec_name = 'code'
_order = 'date desc'
sponsorship_id = fields.Many2one(
'takaful.sponsorship',
string='Sponsorship'
)
sponsor_id = fields.Many2one(
'res.partner',
string='Sponsor Name'
)
code = fields.Char(string="Sponsorship Number", related="sponsorship_id.code",store=True)
payment_month_number = fields.Integer(string="Sponsorships Number To Pay")
month_amount = fields.Float(string="Sponsorship Amount", related="sponsorship_id.contribution_value",store=True, readonly=True)
amount = fields.Float(string="Total Amount", compute="get_amount_month", store=True)
currency_id = fields.Many2one('res.currency', string='Currency',
default=lambda self: self.env.company.currency_id, readonly=True)
iban = fields.Char(string='IBAN / Account Number', tracking=True)
transfer_receipt = fields.Binary(string='Transfer Receipt')
bank_id = fields.Many2one('res.bank', string="Bank Name")
has_bank_account = fields.Boolean(string="Has Another Account?")
payment_method = fields.Char(string='Method Of Payment', store=False)
user_id = fields.Many2one('res.users',string="Issued By", default=lambda self: self.env.user)
state = fields.Selection([
('draft', 'Draft'),
('financial', 'Financial'),
('paid', 'Paid'),
], string='state', default="draft", tracking=True)
date = fields.Date('Date', readonly=True,default=fields.Date.today())
invoice_ids = fields.Many2many('account.move', string="Invoices")
is_invoiced = fields.Boolean(string='Is Invoiced?', compute='check_is_invoiced')
def check_is_invoiced(self):
for rec in self:
if rec.invoice_ids and rec.state == "financial":
total_paid = 0
for invoice in rec.invoice_ids:
if invoice.state == 'paid':
payments = self.env['account.payment'].sudo().search([('invoice_ids', 'in', [invoice.id])])
# if len(payments) > 0:
for payment in payments:
total_paid += payment.amount
if total_paid >0 and total_paid >= rec.amount:
rec.is_invoiced = True
rec.state = "paid"
else:
rec.is_invoiced = False
elif rec.invoice_ids and rec.state == "paid":
rec.is_invoiced = True
else:
rec.is_invoiced = False
@api.onchange('sponsor_id')
def onchange_sponsor_id(self):
res = {}
sponsorships = self.env['takaful.sponsorship'].sudo().search([('sponsor_id', '=', self.sponsor_id.id)])
sponsorships_ids = []
for record in sponsorships:
sponsorships_ids.append(record.id)
res['domain'] = {'sponsorship_id': [('id', 'in', sponsorships_ids)]}
return res
@api.onchange('has_bank_account', 'payment_method')
def onchange_bank_account(self):
for rec in self:
if rec.payment_method and rec.payment_method != "cash" and not rec.has_bank_account:
self.bank_id = self.sponsor_id.bank_id.id
self.iban = self.sponsor_id.iban
else:
self.bank_id = None
self.iban = ''
# @api.constrains('month_amount')
# def check_month_amount(self):
# if int(self.month_amount) <= 0:
# raise ValidationError(
# _(u'Month Amount Is Invalid'))
@api.constrains('payment_month_number')
def check_payment_month_number(self):
if int(self.month_amount) <= 0:
raise ValidationError(
_(u'Payment Month Number should be at least for one month'))
@api.depends('month_amount', 'payment_month_number')
def get_amount_month(self):
for rec in self:
rec.amount = rec.month_amount * rec.payment_month_number
def action_pay(self):
# Check for already sponsored beneficiaries only for sponsorship records
count = 0
invoices = []
if self.sponsorship_id.state in ['confirmed','wait_pay','progress' , 'to_cancel']:
if self.sponsorship_id.next_due_date:
next_date = parse(str(self.sponsorship_id.next_due_date)).date()
while (count < self.payment_month_number):
count +=1
invoice_id = self.sponsorship_id.sudo().create_next_invoice(next_date)
invoices.append(invoice_id.id)
try:
next_date = next_date.replace(month=(next_date.month +1))
except Exception as e:
next_date = next_date.replace(year=(next_date.year +1), month=1)
# Update invoices Ids
for _id in invoices:
self.write({'invoice_ids': [(4, _id)]})
self.state = 'financial'
self.sponsorship_id.sudo().donations_details_lines_mechanism_ids.filtered(lambda line: line.benefit_id).write({'state': 'active'})
self.sponsorship_id.sudo().donations_details_lines_mechanism_ids.filtered(lambda line: not line.benefit_id).write({'state': 'waiting'})
all_lines = self.sponsorship_id.sudo().donations_details_lines_mechanism_ids + self.sponsorship_id.sudo().donations_details_lines_ids
payment_method_ids = all_lines.mapped('payment_method_id')
invoice_id = self.env['account.move'].search([('takaful_sponsorship_id', '=', self.sponsorship_id.id)], limit=1)
if invoice_id and payment_method_ids and invoice_id.state == 'posted':
receivable_lines = invoice_id.line_ids.filtered(
lambda l: l.account_id.account_type == 'asset_receivable' and not l.reconciled
)
if not receivable_lines:
_logger.warning(f"No receivable lines found for invoice {invoice_id.name}")
return
for payment_method_id in payment_method_ids:
if not payment_method_id.journal_id:
continue
lines_with_method = all_lines.filtered(lambda l: l.payment_method_id == payment_method_id)
payment_amount = sum(lines_with_method.mapped('donation_amount'))
if payment_amount <= 0:
continue
payment_method_line = self.env['account.payment.method.line'].search([
('journal_id', '=', payment_method_id.journal_id.id),
('payment_type', '=', 'inbound')
], limit=1)
if not payment_method_line:
_logger.warning(
f"No inbound payment method found for journal {payment_method_id.journal_id.name}. "
f"Skipping payment creation for payment method {payment_method_id.name}"
)
continue
payment_register_vals = {
'payment_date': fields.Date.today(),
'amount': payment_amount,
'journal_id': payment_method_id.journal_id.id,
'payment_method_line_id': payment_method_line.id,
'communication': f"{self.sponsorship_id.code} - {payment_method_id.name}",
}
if payment_method_id.bank_id:
payment_register_vals['partner_bank_id'] = payment_method_id.bank_id.id
payment_register = self.env['account.payment.register'].with_context(
active_model='account.move',
active_ids=[invoice_id.id]
).create(payment_register_vals)
payment_register.action_create_payments()
# @api.multi
def open_account_invoice_action(self):
"""Open Sponsorship Payments Entries"""
domain = []
if self.invoice_ids:
domain = [('id', 'in', self.invoice_ids.ids)]
if self.is_invoiced is True:
self.state ="paid"
context = dict(self.env.context or {})
context["create"] = False
context["edit"] = False
flags = {'initial_mode': 'readonly'} # default is 'edit'
return {
'name': _('Financial'),
'domain': domain,
'view_type': 'form',
'res_model': 'account.move',
'view_mode': 'tree,form',
'type': 'ir.actions.act_window',
'flags': flags,
'context': context,
}

View File

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import takaful_reports
from . import month_payment_report

View File

@ -0,0 +1,177 @@
# -*- coding: utf-8 -*-
from odoo import api, fields, models, tools, _
from odoo.exceptions import ValidationError, UserError
from datetime import datetime, timedelta, date
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
from dateutil.parser import parse
class BenefitREP(models.AbstractModel):
_name = 'report.odex_takaful.benefit_payment_report_pdf'
def get_result(self, data=None):
form = data
domain = []
if form['benefit_ids']:
domain += [('benefit_id', 'in', form['benefit_ids'])]
if form['date_from'] and form['date_to']:
domain = [('month_id.date', '>=', form['date_from']), ('month_id.date', '<=', form['date_to'])]
payment = self.env['month.payment.line'].sudo().search(domain)
return payment
@api.model
def get_report_values(self, docids, data=None):
record = self.get_result(data)
date_to, date_from = '', ''
if data['date_from'] and data['date_to']:
date_from = data['date_from']
date_to = data['date_to']
if not record:
raise ValidationError(_("Sorry, there are no results for this selection !"))
return {
'date_from': date_from,
'date_to': date_to,
'docs': record,
}
class BenefitMonth(models.AbstractModel):
_name = 'report.odex_takaful.benefit_month_payment_report_pdf'
def get_result(self, data=None):
form = data
domain = []
if form['benefit_ids']:
domain += [('benefit_id', 'in', form['benefit_ids'])]
if form['date_from'] and form['date_to']:
domain += [('month_id.date', '>=', form['date_from']), ('month_id.date', '<=', form['date_to'])]
payment = self.env['month.payment.line'].sudo().search(domain)
month_payment = payment.mapped('month_id')
li = []
for y in month_payment:
date = parse(str(y.date))
li.append({'name': y.name , 'code': y.code, 'month_payment': date.strftime("%m-%Y"), 'payment': payment.filtered(lambda r: r.month_id == y)})
return li
@api.model
def get_report_values(self, docids, data=None):
record = self.get_result(data)
# if record.get('data'):
# gender = record.get('gender').title()
# record.update({'gender': _(gender)})
date_to, date_from = '', ''
if data['date_from'] and data['date_to']:
date_from = data['date_from']
date_to = data['date_to']
if not record:
raise ValidationError(_("Sorry, there are no results for this selection !"))
return {
'date_from': date_from,
'date_to': date_to,
'docs': record,
}
class MonthReportXlsx(models.AbstractModel):
_name = "report.odex_takaful.benefit_month_payment_report_xlsx"
_inherit = 'report.report_xlsx.abstract'
@api.model
def generate_xlsx_report(self, workbook, data, objs):
docs = objs
sheet = workbook.add_worksheet(_('Bank Sheet'))
if self.env.user.lang != 'en_US':
sheet.right_to_left()
format0 = workbook.add_format(
{'bottom': True, 'bg_color': '#b8bcbf', 'right': True, 'left': True, 'top': True, 'align': 'center', })
format1 = workbook.add_format({'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center', })
format2 = workbook.add_format(
{'font_size': 14, 'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center',
'bold': True, 'bg_color': '#0f80d6', 'font_color': 'white'})
for doc in docs:
format2.set_align('center')
sheet.merge_range('A9:L9',
(_("Month Payment Sheet")) + " - " + doc.name + " / " + doc.code, format2)
sheet.set_column('B:D', 15)
sheet.set_column('E:F', 10)
row = 10
clm = 0
labels = [(_("#")), (_("Benefit Name")), (_("Benefit Type")), (_("Benefit ID Number")), (_("Birth Date")),
(_("Sponsorship Number")), (_("The Sponsor")),
(_("Amount")), (_("Iban")), (_("Bank Name")), (_("Responsible Name")), (_("Responsible ID Number"))]
for res in labels:
sheet.write(row, clm, res, format0)
clm += 1
row = 11
seq = 0
for rec in doc.line_ids:
seq += 1
clm = 0
sheet.write(row, clm, seq, format1)
sheet.write(row, clm + 1, rec.benefit_id.name, format1)
sheet.write(row, clm + 2, rec.benefit_id.benefit_type, format1)
sheet.write(row, clm + 3, rec.benefit_id.id_number, format1)
sheet.write(row, clm + 4, rec.benefit_id.birth_date, format1)
sheet.write(row, clm + 5, rec.s_code, format1)
sheet.write(row, clm + 6, rec.sponsor_id.name, format1)
sheet.write(row, clm + 7, rec.amount, format1)
sheet.write(row, clm + 8, rec.benefit_id.iban, format1)
sheet.write(row, clm + 9, rec.benefit_id.bank_id.name, format1)
sheet.write(row, clm + 10, rec.responsible_id.name, format1)
sheet.write(row, clm + 11, rec.responsible_id.id_number, format1)
row += 1
row += 3
class BankSheetReportXlsx(models.AbstractModel):
_name = "report.odex_takaful.benefit_month_payment_bank_sheet"
_inherit = 'report.report_xlsx.abstract'
@api.model
def generate_xlsx_report(self, workbook, data, objs):
docs = objs
sheet = workbook.add_worksheet('Bank Sheet')
if self.env.user.lang != 'en_US':
sheet.right_to_left()
format0 = workbook.add_format(
{'bottom': True, 'bg_color': '#b8bcbf', 'right': True, 'left': True, 'top': True, 'align': 'center', })
format1 = workbook.add_format({'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center', })
format2 = workbook.add_format(
{'font_size': 14, 'bottom': True, 'right': True, 'left': True, 'top': True, 'align': 'center',
'bold': True, 'bg_color': '#0f80d6', 'font_color': 'white'})
for doc in docs:
format2.set_align('center')
sheet.merge_range('A9:F9',
(_("Bank Sheet")) + " - " + doc.name + " / " + doc.code, format2)
sheet.set_column('B:D', 15)
sheet.set_column('E:F', 10)
row = 9
clm = 0
labels = [(_("#")), (_("Bank Name")), (_("Account Number")), (_("Amount")),
(_("Benefit Name")), (_("Benefit ID Number")), (_("Responsible Name")), (_("Responsible ID Number"))]
for res in labels:
sheet.write(row, clm, res, format0)
clm += 1
row = 10
seq = 0
for rec in doc.line_ids:
seq += 1
clm = 0
sheet.write(row, clm, seq, format1)
sheet.write(row, clm + 1, rec.benefit_id.bank_id.name, format1)
sheet.write(row, clm + 2, rec.benefit_id.iban, format1)
sheet.write(row, clm + 3, rec.amount, format1)
sheet.write(row, clm + 4, rec.benefit_id.name, format1)
sheet.write(row, clm + 5, rec.benefit_id.id_number, format1)
sheet.write(row, clm + 6, rec.responsible_id.name, format1)
sheet.write(row, clm + 7, rec.responsible_id.id_number, format1)
row += 1
row += 3

View File

@ -0,0 +1,369 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<!-- Benefits Payments Report -->
<template id="benefit_payment_report_pdf">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<div class="text-center">
<h2><span>Benefits Payments Report</span></h2>
<span>
<t t-if="date_from">
<span t-esc="date_from"/>
/
</t>
<t t-if="date_to">
<span t-esc="date_to"/>
</t>
</span>
</div>
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">#</th>
<th style="text-align:center;">Benefit Name</th>
<th style="text-align:center;">Benefit Type</th>
<th style="text-align:center;">Benefit ID Number</th>
<th style="text-align:center;">Sponsorship Number</th>
<th style="text-align:center;">Month Payment</th>
<th style="text-align:center;">Payment Code</th>
<th style="text-align:center;">Amount</th>
<th style="text-align:center;">Date</th>
<th style="text-align:center;">Status</th>
</tr>
</thead>
<tbody class="text-center">
<t t-set="sequence" t-value="0"/>
<t t-foreach="docs" t-as="o">
<tr>
<td>
<t t-set="sequence" t-value="sequence +1"/>
<t t-esc="sequence"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.name"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['benefit_type'])['benefit_type']['selection'])[o.benefit_id.benefit_type]"/>
</span>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.id_number"/>
</td>
<td class="text-center">
<span t-esc="o.s_code"/>
</td>
<td class="text-center">
<span t-esc="o.month_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.code"/>
</td>
<td class="text-center">
<span t-esc="o.amount"/>
</td>
<td class="text-center">
<span t-esc="o.date"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['state'])['state']['selection'])[o.state]"/>
</span>
</td>
</tr>
</t>
</tbody>
</table>
<div style="page-break-before: always;"></div>
</div>
</t>
</t>
</template>
<!-- End Template -->
<report
id="benefit_payment_report_pdf_act"
model="month.payment.line"
string="Benefit Payment Report"
report_type="qweb-pdf"
name="odex_takaful.benefit_payment_report_pdf"
file="odex_takaful.benefit_payment_report_pdf"
menu="False"/>
<!-- Sponsorship Monthly Payments of Benefits Report -->
<template id="benefit_month_payment_report_pdf">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<div class="text-center">
<h2><span>Sponsorship Monthly Payments of Benefits :</span></h2>
<span>
<t t-if="date_from">
<span t-esc="date_from"/>
/
</t>
<t t-if="date_to">
<span t-esc="date_to"/>
</t>
</span>
</div>
<br></br>
<t t-foreach="docs" t-as="doc">
<div class="text-center" style="font-size:20px">
<span t-esc="doc['name']"/>
</div>
<div class="text-center" style="font-size:20px">
Month :
<span t-esc="doc['month_payment']"/>
</div>
<div class="text-center" style="font-size:20px">
Number :
<span t-esc="doc['code']"/>
</div>
<br></br>
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">#</th>
<th style="text-align:center;">Benefit Name</th>
<th style="text-align:center;">Benefit Type</th>
<th style="text-align:center;">Sponsorship Number</th>
<th style="text-align:center;">The Sponsor</th>
<th style="text-align:center;">Amount</th>
<th style="text-align:center;">Benefit ID Number</th>
<th style="text-align:center;">IBAN</th>
<th style="text-align:center;">Bank</th>
<th style="text-align:center;">Responsible Name</th>
<th style="text-align:center;">Responsible ID Number</th>
<th style="text-align:center;">Status</th>
</tr>
</thead>
<tbody class="text-center">
<t t-set="sequence" t-value="0"/>
<t t-foreach="doc['payment']" t-as="o">
<tr>
<td>
<t t-set="sequence" t-value="sequence +1"/>
<t t-esc="sequence"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.name"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['benefit_type'])['benefit_type']['selection'])[o.benefit_id.benefit_type]"/>
</span>
</td>
<td class="text-center">
<span t-esc="o.s_code"/>
</td>
<td class="text-center">
<span t-esc="o.sponsor_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.amount"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.id_number"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.iban"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.bank_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.responsible_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.responsible_id.id_number"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['state'])['state']['selection'])[o.state]"/>
</span>
</td>
</tr>
</t>
</tbody>
</table>
</t>
<div style="page-break-before: always;"></div>
</div>
</t>
</t>
</template>
<!-- End monthly -->
<report
id="benefit_month_payment_report_pdf_act"
model="month.payment.line"
string="Month Payment Report"
report_type="qweb-pdf"
name="odex_takaful.benefit_month_payment_report_pdf"
file="odex_takaful.benefit_month_payment_report_pdf"
menu="False"/>
<!-- Benefits Payments Shares Report -->
<template id="benefit_month_payment_share">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<div class="text-center">
<h2><span>Benefits Payments Shares Report From Sponsorship:</span></h2>
<span>
<t t-if="date_from">
<span t-esc="date_from"/>
/
</t>
<t t-if="date_to">
<span t-esc="date_to"/>
</t>
</span>
</div>
<br></br>
<t t-foreach="docs" t-as="doc">
<br></br>
<div class="text-center" style="font-size:20px">
<span t-esc="doc.name"/> /
<span t-esc="doc.code"/>
</div>
<br></br>
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">#</th>
<th style="text-align:center;">Benefit Name</th>
<th style="text-align:center;">Benefit Type</th>
<th style="text-align:center;">Benefit ID Number</th>
<th style="text-align:center;">Birth Date</th>
<th style="text-align:center;">Sponsorship Number</th>
<th style="text-align:center;">The Sponsor</th>
<th style="text-align:center;">Amount</th>
<th style="text-align:center;">IBAN</th>
<th style="text-align:center;">Bank</th>
<th style="text-align:center;">Responsible Name</th>
<th style="text-align:center;">Responsible ID Number</th>
<th style="text-align:center;">Status</th>
</tr>
</thead>
<tbody class="text-center">
<t t-set="sequence" t-value="0"/>
<t t-foreach="doc.line_ids" t-as="o">
<tr>
<td>
<t t-set="sequence" t-value="sequence +1"/>
<t t-esc="sequence"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.name"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['benefit_type'])['benefit_type']['selection'])[o.benefit_id.benefit_type]"/>
</span>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.id_number"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.birth_date"/>
</td>
<td class="text-center">
<span t-esc="o.s_code"/>
</td>
<td class="text-center">
<span t-esc="o.sponsor_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.amount"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.iban"/>
</td>
<td class="text-center">
<span t-esc="o.benefit_id.bank_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.responsible_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.responsible_id.id_number"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['state'])['state']['selection'])[o.state]"/>
</span>
</td>
</tr>
</t>
</tbody>
</table>
</t>
<div style="page-break-before: always;"></div>
</div>
</t>
</t>
</template>
<!-- End Template -->
<report
id="benefit_month_payment_share_report_pdf_act"
model="month.payment"
string="Month Payments Shares PDF"
report_type="qweb-pdf"
name="odex_takaful.benefit_month_payment_share"
file="odex_takaful.benefit_month_payment_share"
menu="True"/>
<!-- xlx-->
<report
id="benefit_month_payment_report_xlsx_act"
model="month.payment"
string="Month Payments Shares Xlsx"
report_type="xlsx"
name="odex_takaful.benefit_month_payment_report_xlsx"
file="odex_takaful.benefit_month_payment_report_xlsx"
menu="True"/>
<!-- Bank Statement-->
<report
id="benefit_month_payment_bank_Sheet_act"
model="month.payment"
string="Print Bank Sheet"
report_type="xlsx"
name="odex_takaful.benefit_month_payment_bank_sheet"
file="odex_takaful.benefit_month_payment_bank_sheet"
menu="True"/>
</data>
</odoo>

View File

@ -0,0 +1,75 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_payment_voucher">
<t t-call="web.html_container">
<t t-set="sar_currency_id" t-value="docs.env.ref('base.SAR')"/>
<t t-foreach="docs" t-as="o">
<t t-call="web.external_layout">
<div class="page">
<t t-if="o.sponsorship_scheduling_line_id">
<t t-set="donnation_details_id" t-value="o.sponsorship_scheduling_line_id.donation_detail_linked_id"/>
</t>
<t t-else="1">
<t t-set="donnation_details_id" t-value="o.sponsorship_scheduling_line_ids.donation_detail_linked_id"/>
</t>
<h3 class="text-center"><t-esc t-field="o.name"/></h3>
<div class="row mt-4">
<div class="col-12 mb-3">
<strong>Scheduling Sequence(s):</strong> <span t-field="o.sponsorship_scheduling_ref" />
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<strong>Sponsor Name:</strong> <span t-field="o.sponsorship_id.sponsor_id" />
</div>
<div class="col-6 mb-3">
<strong>Point of Sale:</strong> <span t-field="o.branch_custom_id" />
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<strong>Donation Type:</strong> <span t-field="o.sponsorship_id.record_type" />
</div>
<div class="col-6 mb-3">
<strong>Donation Name:</strong> <span t-field="donnation_details_id.product_template_id" />
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<strong>Beneficiary:</strong> <span t-field="donnation_details_id.benefit_id" />
</div>
<div class="col-6 mb-3">
<strong>Payment Date:</strong> <span t-field="o.donation_date" />
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<strong>Payment Method:</strong> <span t-field="o.payment_method" />
</div>
<div class="col-6 mb-3">
<strong>Donation Amount:</strong> <span t-field="o.donation_amount" t-options="{'widget': 'monetary', 'display_currency': sar_currency_id}" />
</div>
</div>
<div class="row">
<div class="col-6 mb-3">
<strong>Amount Paid:</strong> <span t-field="o.donation_amount" t-options="{'widget': 'monetary', 'display_currency': sar_currency_id}" />
</div>
</div>
</div>
</t>
</t>
</t>
</template>
<report
id="action_payment_voucher_report"
string="Payment Voucher Report"
model="payment.details.lines"
report_type="qweb-pdf"
name="odex_takaful.report_payment_voucher"
file="odex_takaful.report_payment_voucher"
print_report_name="object.print_report_name()"
/>
</odoo>

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
from odoo import api, models, fields, _
class ReportMakfuleen(models.AbstractModel):
_name = 'report.odex_takaful.makfuleen_report_pdf'
@api.model
def get_report_values(self, docids, data=None):
selected_id = data.get('sponsor_id', False)
domain = [('sponsor_id', '=', selected_id)]
records = self.env['takaful.sponsorship'].sudo().search(domain)
return {
'docs': records,
'name': data.get('name', ""),
}
class ReportKafalatPayment(models.AbstractModel):
_name = 'report.odex_takaful.kafalat_payment_report_pdf'
@api.model
def get_report_values(self, docids, data=None):
sponsor_id = data.get('sponsor_id', False)
overdue_sponsorships = self.env['takaful.sponsorship'].sudo().search([('sponsor_id','=', sponsor_id), ('has_delay','=', False), ('state','in', ['wait_pay','progress' , 'to_cancel'])])
overdue_amount = sum(overdue_sponsorships.mapped('overdue_amount')) or 0
return {
'docs': overdue_sponsorships or [],
'name': data.get('name', ""),
'overdue_amount': overdue_amount,
'overdue_count': len(overdue_sponsorships),
}
class ReportKafalatCancel(models.AbstractModel):
_name = 'report.odex_takaful.kafalat_cancel_report_pdf'
@api.model
def get_report_values(self, docids, data=None):
start_date = data.get('start_date', False)
end_date = data.get('end_date', False)
if start_date and end_date:
canceled_kafalat = self.env['sponsorship.cancellation'].sudo().search([
('confirm_date', '>=', start_date),
('confirm_date', '<=', end_date),
('state', '=', 'cancel'),
])
else:
canceled_kafalat = []
return {
'docs': canceled_kafalat,
'cancel_count': len(canceled_kafalat),
'start_date': start_date,
'end_date': end_date,
}

View File

@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="paperformat_transfer_deduction_landscape" model="report.paperformat">
<field name="name">Transfer Deduction Report Landscape</field>
<field name="default" eval="False"/>
<field name="format">A4</field> <!-- You can use Letter, Legal, etc. -->
<field name="page_height">0</field>
<field name="page_width">0</field>
<field name="orientation">Landscape</field>
<field name="margin_top">40</field> <!-- Adjust margins as needed -->
<field name="margin_bottom">25</field>
<field name="margin_left">7</field>
<field name="margin_right">7</field>
<field name="header_line" eval="False"/>
<field name="header_spacing">30</field>
<field name="dpi">120</field>
</record>
<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>
</data>
</odoo>

View File

@ -0,0 +1,102 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_transfer_deduction_document">
<t t-call="web.html_container">
<t t-set="report_title" t-value="data.get('report_title', 'Transfer and Deduction Report')"/>
<t t-set="criteria" t-value="data.get('criteria', {})"/>
<t t-set="sponsorship_lines" t-value="data.get('sponsorship_lines_details', [])"/>
<t t-call="web.external_layout">
<div class="page">
<h2 class="text-center"><span t-esc="report_title"/></h2>
<h3 class="mt-4"><u>Selected Criteria</u></h3>
<table class="table table-sm table-bordered mt-2" style="width: 100%;">
<tbody>
<tr>
<td style="width: 15%;"><strong>Start Date</strong></td>
<td style="width: 35%;"><span t-esc="criteria.get('start_date')"/></td>
<td style="width: 15%;"><strong>Payment Method</strong></td>
<td style="width: 35%;"><span t-esc="criteria.get('payment_method_name')"/></td>
</tr>
<tr>
<td><strong>End Date</strong></td>
<td><span t-esc="criteria.get('end_date')"/></td>
<td><strong>Branches</strong></td>
<td><span t-esc="criteria.get('branch_names')"/></td>
</tr>
<tr>
<td><strong>Sponsors</strong></td>
<td><span t-esc="criteria.get('sponsor_names')"/></td>
<td><strong>Benefit Members</strong></td>
<td><span t-esc="criteria.get('benefit_member_names')"/></td>
</tr>
</tbody>
</table>
<h3 class="mt32"><u>Sponsorship Details</u></h3>
<t t-if="sponsorship_lines">
<table class="table table-sm table-condensed table-bordered mt-2">
<thead>
<tr style="background-color: #f2f2f2;">
<th>Sponsor</th>
<th>Sponsor Mobile</th>
<th>Sponsorship Creator</th>
<th>Sponsorship Creator Branch</th>
<th>Sponsorship Branch</th>
<th>Beneficiary</th>
<th>Sponsorship Creation Date</th>
<th>Sponsorship Number</th>
<th>Sponsor Bank</th>
<th>Charity Bank</th>
<th>Sponsor Account Number</th>
<th>Payment Method</th>
<th>Donation Type</th>
<th>Donation Name</th>
<th>Direct Debit Start</th>
<th>Direct Debit End</th>
<th>Donation Date</th>
<th class="text-right">Amount</th>
<th class="text-right">Total Amount</th>
</tr>
</thead>
<tbody>
<t t-foreach="sponsorship_lines" t-as="line">
<tr>
<td><span t-esc="line.get('sponsor_name')"/></td>
<td><span t-esc="line.get('sponsor_mobile')"/></td>
<td><span t-esc="line.get('sponsorship_create_uid_name')"/></td>
<td><span t-esc="line.get('sponsorship_create_uid_branch_name')"/></td>
<td><span t-esc="line.get('sponsorship_branch_name')"/></td>
<td><span t-esc="line.get('beneficiary_name')"/></td>
<td><span t-esc="line.get('sponsorship_create_date')" t-options="{'widget': 'date'}"/></td>
<td><span t-esc="line.get('sponsorship_sequence_no')"/></td>
<td><span t-esc="line.get('bank_name')"/></td>
<td><span t-esc="line.get('charity_bank_name')"/></td>
<td><span t-esc="line.get('sponsor_account_number')"/></td>
<td><span t-esc="line.get('payment_method_name')"/></td>
<td><span t-esc="line.get('donation_type')"/></td>
<td><span t-esc="line.get('donation_name')"/></td>
<td><span t-esc="line.get('direct_debit_start_date')" t-options="{'widget': 'date'}"/></td>
<td><span t-esc="line.get('direct_debit_end_date')" t-options="{'widget': 'date'}"/></td>
<td><span t-esc="line.get('donation_date')" t-options="{'widget': 'date'}"/></td>
<td class="text-right">
<span t-esc="line.get('amount')" t-options="{'widget': 'monetary', 'display_currency': docs.env.company.currency_id}"/>
</td>
<td class="text-right">
<span t-esc="line.get('total_amount')" t-options="{'widget': 'monetary', 'display_currency': docs.env.company.currency_id}"/>
</td>
</tr>
</t>
</tbody>
</table>
<p class="mt-2"><strong>Total lines found: <span t-esc="len(sponsorship_lines)"/></strong></p>
</t>
<t t-else="">
<p class="mt-2">No sponsorship scheduling lines found for the selected criteria.</p>
</t>
</div>
</t>
</t>
</template>
</odoo>

View File

@ -0,0 +1,57 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_sponsorship_payment_user,Full access on sponsorship.payment to Payment User,model_sponsorship_payment,group_kufula_user,1,1,1,1
access_month_payment_full,Full access on month.payment to Month Payment Manager,model_month_payment,odex_takaful.group_kufula_user,1,1,1,1
access_takaful_message_template,Full access on takaful.message.template,model_takaful_message_template,odex_takaful.group_kufula_user,1,1,1,1
access_sponsorship_cancellation,Full access on sponsorship.cancellation,model_sponsorship_cancellation,odex_takaful.group_kufula_user,1,1,1,1
access_takaful_contribution,Full access on takaful.contribution,model_takaful_contribution,odex_takaful.group_kufula_user,1,1,1,1
access_takaful_push_notification,Full access on takaful.push.notification,model_takaful_push_notification,odex_takaful.group_kufula_user,1,1,1,1
access_month_payment_line,Full access on month.payment.line,model_month_payment_line,odex_takaful.group_kufula_user,1,1,1,1
access_sponsorship_benefit_arrears,Full access on sponsorship.benefit.arrears,model_sponsorship_benefit_arrears,odex_takaful.group_kufula_user,1,1,1,1
access_sponsorship_reason_stop,Full access on sponsorship.reason.stop,model_sponsorship_reason_stop,odex_takaful.group_kufula_user,1,1,1,1
access_donate_for_another_person,access_donate_for_another_person,model_donate_for_another_person,odex_takaful.group_kufula_user,1,1,1,1
access_donations_items,access_donations_items,model_donations_items,odex_takaful.group_kufula_user,1,1,1,1
access_replacement_reasons,access_replacement_reasons,model_replacement_reasons,odex_takaful.group_orphan_replacement,1,1,1,1
access_replacement_process,access_replacement_process,model_replacement_process,odex_takaful.group_orphan_replacement,1,1,1,0
access_takaful_notification,access_takaful_notification,model_takaful_notification,,1,1,1,1
access_sponsorship_states,access_sponsorship_states,model_sponsorship_states,,1,1,1,1
access_replacement_wiz,access_replacement_wiz,model_replacement_wiz,,1,1,1,1
access_donations_details_lines,access_donations_details_lines,model_donations_details_lines,odex_takaful.group_kufula_user,1,1,1,1
access_refund_details_lines,access_refund_details_lines,model_refund_details_lines,odex_takaful.group_kufula_user,1,1,1,1
access_points_of_sale_custom,access_points_of_sale_custom,model_points_of_sale_custom,odex_takaful.group_kufula_user,1,1,1,1
access_payment_details_lines,access_payment_details_lines,model_payment_details_lines,odex_takaful.group_kufula_user,1,1,1,1
access_sponsorship_scheduling_line,access_sponsorship_scheduling_line,model_sponsorship_scheduling_line,odex_takaful.group_kufula_user,1,0,0,0
access_refund_reasons,access_refund_reasons,model_refund_reasons,odex_takaful.group_kufula_user,1,1,1,1
access_takaful_sponsorship_user,Full access on takaful.sponsorship to Sponsorship User,model_takaful_sponsorship,group_kufula_user,1,1,1,1
access_res_partner_user,Access on res.pfartner to Sponsorship User,base.model_res_partner,group_kufula_user,1,1,0,0
access_res_users_user,Access on res.users to Sponsorship User,base.model_res_users,group_kufula_user,1,1,0,0
access_grant_benefit_invoice,Full access on grant.benefit.invoice to Month Payment Manager,model_grant_benefit_invoice,base.group_user,1,1,1,1
access_refund_wiz,access_refund_wiz,model_refund_wiz,,1,1,1,1
access_add_details_wiz,access_add_details_wiz,model_add_details_wiz,,1,1,1,1
access_preferred_communication,access_preferred_communication,model_preferred_communication,,1,1,1,1
access_takaful_payment_method,access_takaful_payment_method,model_takaful_payment_method,,1,1,1,1
access_replacement_line_method,access_takaful_replacement_line,model_replacement_line,,1,1,1,1
access_replacement_process_line_method,access_takaful_replacement_process_line,model_replacement_process_line,,1,1,1,1
access_transfer_deduction_wizard,transfer.deduction.wizard.access,model_transfer_deduction_wizard,base.group_user,1,1,1,1
access_account_payment_register_donation_officer,account_payment_register_donation_officer,account.model_account_payment_register,odex_takaful.donation_officer_group,1,1,1,0
access_product_template_donation_officer,product_template_donation_officer,product.model_product_template,odex_takaful.donation_officer_group,1,1,1,0
access_product_product_donation_officer,product_product_donation_officer,product.model_product_product,odex_takaful.donation_officer_group,1,1,1,0
access_group_kufula_user_account_payment,access_group_kufula_user_account_payment,account.model_account_payment,odex_takaful.group_kufula_user,1,1,1,0
access_group_kufula_user_account_partial_reconcile,access_group_kufula_user_account_partial_reconcile,account.model_account_partial_reconcile,odex_takaful.group_kufula_user,1,1,1,0
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_donation_replacement_log,donation.replacement.log.access,model_donation_replacement_log,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
access_add_benefit_wizard,add.benefit.wizard.access,model_add_benefit_wizard,odex_takaful.group_kufula_user,1,1,1,1
access_extension_payment_wizard_line,extension.payment.wizard.line.access,model_extension_payment_wizard_line,odex_takaful.group_kufula_user,1,1,1,1
access_group_kufula_user_product_template,access_group_kufula_user_product_template,product.model_product_template,odex_takaful.group_kufula_user,1,1,0,0
access_group_kufula_user_account_move,access_group_kufula_user_account_move,account.model_account_move,odex_takaful.group_kufula_user,1,1,1,0
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
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_sponsorship_payment_user Full access on sponsorship.payment to Payment User model_sponsorship_payment group_kufula_user 1 1 1 1
3 access_month_payment_full Full access on month.payment to Month Payment Manager model_month_payment odex_takaful.group_kufula_user 1 1 1 1
4 access_takaful_message_template Full access on takaful.message.template model_takaful_message_template odex_takaful.group_kufula_user 1 1 1 1
5 access_sponsorship_cancellation Full access on sponsorship.cancellation model_sponsorship_cancellation odex_takaful.group_kufula_user 1 1 1 1
6 access_takaful_contribution Full access on takaful.contribution model_takaful_contribution odex_takaful.group_kufula_user 1 1 1 1
7 access_takaful_push_notification Full access on takaful.push.notification model_takaful_push_notification odex_takaful.group_kufula_user 1 1 1 1
8 access_month_payment_line Full access on month.payment.line model_month_payment_line odex_takaful.group_kufula_user 1 1 1 1
9 access_sponsorship_benefit_arrears Full access on sponsorship.benefit.arrears model_sponsorship_benefit_arrears odex_takaful.group_kufula_user 1 1 1 1
10 access_sponsorship_reason_stop Full access on sponsorship.reason.stop model_sponsorship_reason_stop odex_takaful.group_kufula_user 1 1 1 1
11 access_donate_for_another_person access_donate_for_another_person model_donate_for_another_person odex_takaful.group_kufula_user 1 1 1 1
12 access_donations_items access_donations_items model_donations_items odex_takaful.group_kufula_user 1 1 1 1
13 access_replacement_reasons access_replacement_reasons model_replacement_reasons odex_takaful.group_orphan_replacement 1 1 1 1
14 access_replacement_process access_replacement_process model_replacement_process odex_takaful.group_orphan_replacement 1 1 1 0
15 access_takaful_notification access_takaful_notification model_takaful_notification 1 1 1 1
16 access_sponsorship_states access_sponsorship_states model_sponsorship_states 1 1 1 1
17 access_replacement_wiz access_replacement_wiz model_replacement_wiz 1 1 1 1
18 access_donations_details_lines access_donations_details_lines model_donations_details_lines odex_takaful.group_kufula_user 1 1 1 1
19 access_refund_details_lines access_refund_details_lines model_refund_details_lines odex_takaful.group_kufula_user 1 1 1 1
20 access_points_of_sale_custom access_points_of_sale_custom model_points_of_sale_custom odex_takaful.group_kufula_user 1 1 1 1
21 access_payment_details_lines access_payment_details_lines model_payment_details_lines odex_takaful.group_kufula_user 1 1 1 1
22 access_sponsorship_scheduling_line access_sponsorship_scheduling_line model_sponsorship_scheduling_line odex_takaful.group_kufula_user 1 0 0 0
23 access_refund_reasons access_refund_reasons model_refund_reasons odex_takaful.group_kufula_user 1 1 1 1
24 access_takaful_sponsorship_user Full access on takaful.sponsorship to Sponsorship User model_takaful_sponsorship group_kufula_user 1 1 1 1
25 access_res_partner_user Access on res.pfartner to Sponsorship User base.model_res_partner group_kufula_user 1 1 0 0
26 access_res_users_user Access on res.users to Sponsorship User base.model_res_users group_kufula_user 1 1 0 0
27 access_grant_benefit_invoice Full access on grant.benefit.invoice to Month Payment Manager model_grant_benefit_invoice base.group_user 1 1 1 1
28 access_refund_wiz access_refund_wiz model_refund_wiz 1 1 1 1
29 access_add_details_wiz access_add_details_wiz model_add_details_wiz 1 1 1 1
30 access_preferred_communication access_preferred_communication model_preferred_communication 1 1 1 1
31 access_takaful_payment_method access_takaful_payment_method model_takaful_payment_method 1 1 1 1
32 access_replacement_line_method access_takaful_replacement_line model_replacement_line 1 1 1 1
33 access_replacement_process_line_method access_takaful_replacement_process_line model_replacement_process_line 1 1 1 1
34 access_transfer_deduction_wizard transfer.deduction.wizard.access model_transfer_deduction_wizard base.group_user 1 1 1 1
35 access_account_payment_register_donation_officer account_payment_register_donation_officer account.model_account_payment_register odex_takaful.donation_officer_group 1 1 1 0
36 access_product_template_donation_officer product_template_donation_officer product.model_product_template odex_takaful.donation_officer_group 1 1 1 0
37 access_product_product_donation_officer product_product_donation_officer product.model_product_product odex_takaful.donation_officer_group 1 1 1 0
38 access_group_kufula_user_account_payment access_group_kufula_user_account_payment account.model_account_payment odex_takaful.group_kufula_user 1 1 1 0
39 access_group_kufula_user_account_partial_reconcile access_group_kufula_user_account_partial_reconcile account.model_account_partial_reconcile odex_takaful.group_kufula_user 1 1 1 0
40 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
41 access_donation_extension_wizard donation.extension.wizard.access model_donation_extension_wizard base.group_user 1 1 1 1
42 access_donation_extension_history donation.extension.history.access model_donation_extension_history odex_takaful.group_kufula_user 1 1 1 0
43 access_donation_extension_wizard_line donation.extension.wizard.line.access model_donation_extension_wizard_line odex_takaful.group_kufula_user 1 1 1 0
44 access_donation_replacement_log donation.replacement.log.access model_donation_replacement_log odex_takaful.group_kufula_user 1 1 1 0
45 access_replace_sponsor_wizard replace.sponsor.wizard.access model_replace_sponsor_wizard odex_takaful.group_replace_sponsor 1 1 1 1
46 access_add_benefit_wizard add.benefit.wizard.access model_add_benefit_wizard odex_takaful.group_kufula_user 1 1 1 1
47 access_extension_payment_wizard_line extension.payment.wizard.line.access model_extension_payment_wizard_line odex_takaful.group_kufula_user 1 1 1 1
48 access_group_kufula_user_product_template access_group_kufula_user_product_template product.model_product_template odex_takaful.group_kufula_user 1 1 0 0
49 access_group_kufula_user_account_move access_group_kufula_user_account_move account.model_account_move odex_takaful.group_kufula_user 1 1 1 0
50 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
51 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
52 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

View File

@ -0,0 +1,312 @@
<odoo>
<data noupdate="0">
<record id="module_category_kufula" model="ir.module.category">
<field name="name">Kufula System</field>
<field name="description">Helps you manage Kafleen and Kafalat in kufula System</field>
<field name="sequence">3</field>
</record>
<!-- <record id="group_kufula_viewer" model="res.groups">
<field name="name">Viewer</field>
<field name="category_id" ref="module_category_kufula"/>
</record>
<record id="group_kufula_officer" model="res.groups">
<field name="name">Officer</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_viewer'))]"/>
<field name="users" eval="[(4, ref('base.group_user'))]"/>
</record>
<record id="group_kufula_manager" model="res.groups">
<field name="name">Administrator</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_officer'))]"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record> -->
<record id="group_can_make_sponsorship_payment" model="res.groups">
<field name="name">Make Sponsorship Payments</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Can Make Payments For Sponsorships?</field>
</record>
<record id="group_can_recieve_sponsorship_payment" model="res.groups">
<field name="name">Recieve Sponsorship Payments</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Can Recieve Payments For Sponsorships?</field>
</record>
<record id="takaful_group_user_sponsor" model="res.groups">
<field name="name">Sponsor Account</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Is this user a Sponsor?</field>
</record>
<record id="group_can_activate_sponsor" model="res.groups">
<field name="name">Can Activate Inactive Sponsors</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Can make Sponsor active again?</field>
</record>
<record id="group_refund_approval" model="res.groups">
<field name="name">Refund Approval</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Can make Approval for refund?</field>
</record>
<record id="group_orphan_replacement" model="res.groups">
<field name="name">Orphan Replacement</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Orphan Replacement</field>
</record>
<record id="group_replace_sponsor" model="res.groups">
<field name="name">Replace Sponsor</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Can Replace Sponsor on Donation Lines</field>
</record>
<record id="group_show_donation_item_product" model="res.groups">
<field name="name">Show Donation Item Product</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Can Show Donation Item Product?</field>
</record>
<!-- <record id="group_donations_coordinator" model="res.groups">
<field name="name">Donations Coordinator</field>
<field name="category_id" ref="module_category_kufula"/>
</record>
<record id="group_sponsorship_coordinator" model="res.groups">
<field name="name">Sponsorship Coordinator</field>
<field name="category_id" ref="module_category_kufula"/>
</record> -->
<!-- <record id="group_branch_manager" model="res.groups">
<field name="name">Branch Manager</field>
<field name="category_id" ref="module_category_kufula"/>
</record> -->
<!-- <record id="group_sponsorship_system_manager" model="res.groups">
<field name="name">Sponsorship System Manager</field>
<field name="category_id" ref="module_category_kufula"/>
</record> -->
<!-- <record id="donations_coordinator_rule" model="ir.rule">
<field name="name">Donations Coordinator - Record Type Donation</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('group_donations_coordinator'))]"/>
<field name="domain_force">[('record_type', '=', 'donation')]</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="sponsorship_coordinator_rule" model="ir.rule">
<field name="name">Sponsorship Coordinator - Record Type Sponsorship</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('group_sponsorship_coordinator'))]"/>
<field name="domain_force">[('record_type', '=', 'sponsorship')]</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="branch_manager_rule" model="ir.rule">
<field name="name">Branch Manager - Can Only See Their Branch</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('group_branch_manager'))]"/>
<field name="domain_force">[('manager_id.user_id', '=', 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="sponsorship_system_manager_rule" model="ir.rule">
<field name="name">Sponsorship System Manager</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('group_sponsorship_system_manager'))]"/>
<field name="domain_force">[(1,'=',1)]</field>
</record> -->
<record id="group_kufula_user" model="res.groups">
<field name="name">Kufula User</field>
<field name="category_id" ref="module_category_kufula"/>
</record>
<record id="donation_officer_group" model="res.groups">
<field name="name">Donations Officer</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_user'))]"/>
</record>
<record id="donation_officer_restrictions" model="ir.rule">
<field name="name">Donations Officer can only see his donations or his branch sponsors</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('donation_officer_group'))]"/>
<field name="domain_force">[
('record_type', 'in', [False, 'donation']),
('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="sponsorship_officer_group" model="res.groups">
<field name="name">Sponsorships Officer</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_user'))]"/>
</record>
<record id="sponsorship_officer_restrictions" model="ir.rule">
<field name="name">Sponsorships Officer can only see his sponsorships or his branch sponsors</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('sponsorship_officer_group'))]"/>
<field name="domain_force">[
('record_type', 'in', [False, 'sponsorship']),
('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="branch_manager_group" model="res.groups">
<field name="name">Branch Manager</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_user'))]"/>
</record>
<record id="branch_manager_restrictions" model="ir.rule">
<field name="name">Branch Manager can only see all his branch sponsorships and donations</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('branch_manager_group'))]"/>
<field name="domain_force">[('branch_custom_id.branch.manager_id.user_id', 'in', [user.id, False])]</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="sponsorship_system_manager_group" model="res.groups">
<field name="name">Sponsorship System Manager</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_user'))]"/>
</record>
<record id="sponsorship_restrict_orphan_group" model="res.groups">
<field name="name">Sponsorship General Restriction</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="implied_ids" eval="[(4, ref('group_kufula_user'))]"/>
</record>
<record id="responsible_user_sponsorship_access" model="ir.rule">
<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">[('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"/>
<field name="perm_unlink" eval="1"/>
</record>
<record id="sponsorship_system_manager_restrictions" model="ir.rule">
<field name="name">Sponsorship System Manager can see everything and settings</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="groups" eval="[(4, ref('sponsorship_system_manager_group'))]"/>
<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"/>
<field name="perm_unlink" eval="1"/>
</record>
<!-- Groups for Department-based Access Control -->
<record id="group_beneficiary_department_access" model="res.groups">
<field name="name">Beneficiary - Department Access</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Limits beneficiary records to user's department</field>
</record>
<record id="group_sponsor_department_access" model="res.groups">
<field name="name">Sponsor - Department Access</field>
<field name="category_id" ref="module_category_kufula"/>
<field name="comment">Limits sponsor records to user's department</field>
</record>
<!-- Record Rules for Department-based Access Control -->
<record id="grant_benefit_department_rule" model="ir.rule">
<field name="name">Grant Benefit - Department Based Access</field>
<field name="model_id" ref="odex_benefit.model_grant_benefit"/>
<field name="groups" eval="[(4, ref('group_beneficiary_department_access'))]"/>
<field name="domain_force">[('branch_custom_id.branch', 'child_of', user.employee_id.department_id.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="family_member_department_rule" model="ir.rule">
<field name="name">Family Member - Department Based Access</field>
<field name="model_id" ref="odex_benefit.model_family_member"/>
<field name="groups" eval="[(4, ref('group_beneficiary_department_access'))]"/>
<field name="domain_force">[('benefit_id.branch_custom_id.branch', 'child_of',
user.employee_id.department_id.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="sponsor_department_rule" model="ir.rule">
<field name="name">Sponsor - Department Based Access</field>
<field name="model_id" ref="odex_takaful.model_takaful_sponsor"/>
<field name="groups" eval="[(4, ref('group_sponsor_department_access'))]"/>
<field name="domain_force">[('branch_custom_id.branch', 'child_of', user.employee_id.department_id.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="sponsorship_marketer_restrictions" model="ir.rule">
<!-- <field name="name">Sponsorship Marketer can see and select all employees</field>-->
<field name="name">Sponsorship Marketer can see his employees</field>
<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="perm_read" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_create" eval="0"/>
<field name="perm_unlink" eval="0"/>
</record>
</data>
</odoo>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

View File

@ -0,0 +1,25 @@
odoo.define('odex_takaful.CustomKanbanRecord', function (require) {
"use strict";
const KanbanRecord = require('web.KanbanRecord');
const CustomKanbanRecord = KanbanRecord.extend({
events: _.extend({}, KanbanRecord.prototype.events, {
'click .oe_dynamic_button': '_onClickDynamicButton',
}),
/**
* Hide the button when clicked
*
* @private
* @param {MouseEvent} ev
*/
_onClickDynamicButton: function (ev) {
ev.preventDefault();
ev.stopPropagation();
$(ev.currentTarget).hide(); // Hide the button
},
});
return CustomKanbanRecord;
});

View File

@ -0,0 +1,92 @@
odoo.define('odex_takaful.custom_dialog', function (require) {
"use strict";
const AbstractAction = require('web.AbstractAction');
const Dialog = require('web.Dialog');
const core = require('web.core');
const _t = core._t;
const ActionManager = require('web.ActionManager');
ActionManager.include({
//----------------------------------------------------------------------
// Public
//----------------------------------------------------------------------
/**
* Returns the action of the controller currently opened in a dialog,
* i.e. a target='new' action, if any.
*
* @returns {Object|null}
*/
getCurrentActionInDialog: function () {
if (this.currentDialogController) {
return this.actions[this.currentDialogController.actionID];
}
return null;
},
/**
* Returns the controller currently opened in a dialog, if any.
*
* @returns {Object|null}
*/
getCurrentControllerInDialog: function () {
return this.currentDialogController;
},
});
Dialog.include({
/**
* @override
*/
open: function () {
var self = this;
this.opened(function () {
setTimeout(function () {
var parent = self.getParent();
if (parent instanceof ActionManager) {
var action = parent.getCurrentActionInDialog();
if (action) {
if (action.context) {
let context = action.context;
if (context.action_code) {
if (context.action_code === 'donation_items') {
if (self.$footer) {
const closeBtn = $('<button/>', {
text: _t('Add'),
class: 'btn btn-primary btn-close-custom',
}).on('click', () => self.close());
self.$footer.append(closeBtn);
}
if (self.$modal) {
self.$modal.find('.modal-header button.close').hide();
self.$modal.find('.modal-header .modal-title').css("width", "100%");
}
if (self.$el) {
self.$el.find('.o_cp_top_left').hide();
self.$el.find('.o_cp_bottom_left').hide();
self.$el.find('.o_cp_top_right').css("width", "100%");
self.$el.find('.o_cp_bottom_right').css("width", "100%");
}
if (context.sponsorship_id) {
$('#cspid').remove();
$('body').append(`<input type="hidden" id="cspid" value="${context.sponsorship_id}"/>`)
}
}
}
}
}
}
}, 0);
});
return this._super.apply(this, arguments);
},
});
});

View File

@ -0,0 +1,165 @@
odoo.define('odex_takaful.DonationQuantityWidget', function (require) {
"use strict";
const Widget = require('web.Widget');
const rpc = require('web.rpc');
const core = require('web.core');
const QWeb = core.qweb;
const _t = core._t;
let o_cart_kanban_donation = $('.o_cart_kanban_donation');
if(o_cart_kanban_donation){
$(o_cart_kanban_donation).parents('.o_act_window').find('.o_cp_top_left').remove();
}
$(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();
handleQuantityChange($(this), 'add');
return false; // ensure Odoo's default kanban action handler does not run
});
$(document).on('click', 'button[data-name="remove_quantity_button_so"]', function (e) {
e.preventDefault();
e.stopPropagation();
handleQuantityChange($(this), 'remove');
return false; // ensure Odoo's default kanban action handler does not run
});
// Expose imperative handlers as a reliable fallback (callable from inline onclick if needed)
window.__dc_add = function (btn) {
return __dc_handle(btn, 'add');
};
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 {
const $btn = $(btn);
handleQuantityChange($btn, operation);
} catch (_e) {
// no-op
}
return false;
}
async function handleQuantityChange($button, operation) {
// Get the kanban record (product card) container
const $kanbanRecord = $button.closest('.o_kanban_record');
if (!$kanbanRecord.length) {
return;
}
// Get quantity display element from the button's parent container using stable custom classes
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;
// }
const imgSrc = $img.attr('src');
const match = imgSrc.match(/[&?]id=(\d+)/);
// if (!match || !match[1]) {
// return;
// }
const productId = parseInt(match[1]);
let currentQuantity = parseFloat($quantityDisplay.text()) || 0;
// Prevent going below zero for remove operation
if (operation === 'remove' && currentQuantity <= 0) {
return;
}
// Resolve sponsorship id from multiple sources (robust against context differences)
let sponsorship_id;
if (!sponsorship_id) {
const $input = $('#cspid');
if ($input) sponsorship_id = parseInt($input.val());
}
if (!sponsorship_id) {
return;
}
// Disable buttons during operation
$button.prop('disabled', true).addClass('o_btn_loading');
$button.siblings('button').prop('disabled', true);
// Calculate new quantity
let newQuantity = currentQuantity;
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);
try {
// Call server to update quantity
await $.ajax({
url: "/qtyupdatecart_so",
method: "GET",
dataType: 'json',
data: {
quantity: newQuantity,
product_id: productId,
sponsorship_id: sponsorship_id
}
}).catch(function (jqXHR) {
// Re-throw with more details
const info = {
status: jqXHR?.status,
responseText: jqXHR?.responseText,
readyState: jqXHR?.readyState
};
throw info;
});
} catch (error) {
// Revert on error
$quantityDisplay.text(currentQuantity);
// $quantityDisplay.addClass('bg-danger').removeClass('bg-secondary');
setTimeout(() => {
// $quantityDisplay.removeClass('bg-danger').addClass('bg-secondary');
}, 1000);
} finally {
// Re-enable buttons
$button.prop('disabled', false).removeClass('o_btn_loading');
$button.siblings('button').prop('disabled', false);
}
}
});

View File

@ -0,0 +1,45 @@
function change_input_so(params) {
let id = params.className
console.log(id)
let _quantity = params.getElementsByTagName("span")[0];
if (_quantity) {
params.innerHTML = `<input class='text-center px-1 mx-1' value='${_quantity.innerHTML}' id='inputid${id}' onchange='change_quantity_so("${id}","${_quantity.innerHTML}",event)' min='0' max='999999999' type='number'/>`;
}
}
const change_quantity_so = async (id, _quantity, event) => {
let qtyspantag = document.createElement("span");
let tag = event.target
if (Number(tag.value) < 0) {
console.log("changing")
tag.value = '0.00'
// qtyspantag.innerText = '0';
// tag.replaceWith(qtyspantag);
return;
}
let data = JSON.parse(sessionStorage.getItem("current_action"));
if (data) {
data = JSON.parse(data);
let _sponsorship_id = data.context.sponsorship_id;
// let uom_category = await $.ajax({
// url: "/getuom_so",
// method: "GET",
// dataType: 'json',
// data: { quantity: Number(tag.value), product_id: id, sale_id: _sale_id }
// });
// if(uom_category["uom_category"] == 'unit'){
// tag.value = Math.round(tag.value);
// tag.value = tag.value.concat('.00')
// }
$.ajax({
url: "/qtyupdatecart_so",
method: "GET",
dataType: 'json',
data: { quantity: Number(tag.value), product_id: id, sponsorship_id: _sponsorship_id }
});
qtyspantag.innerText = tag.value;
tag.replaceWith(qtyspantag);
}
}

View File

@ -0,0 +1,40 @@
.o_cart_industry_product {
.o_button_invisible {
position: absolute;
top: 0;
left: 0;
opacity: 0;
}
}
.o_product_quantity {
z-index: 1;
font-size: $font-size-lg * 1.5;
input {
width: 104px;
&:not(.small) {
width: 74px;
}
&.o_input {
// to prevent the "mini flicker" on the display name of the product.
margin-bottom: -1px;
}
&:not(.o_input) {
border: 0;
}
// Remove arrow buttons input type="number"
appearance: textfield;
&::-webkit-outer-spin-button,
&::-webkit-inner-spin-button {
appearance: none;
margin: 0;
}
}
}

View File

@ -0,0 +1,153 @@
.o_form_view .o_form_sheet_bg > .o_form_sheet {
width: 95%!important;
max-width: initial;
}
@media (max-width: 480px) {
.fix_overflow {
.table-responsive{
width: 80vw;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
@media screen and (min-width: 481px) and (max-width: 767px){
.fix_overflow {
.table-responsive{
width: 400px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
@media (min-width: 576px) {
.fix_overflow {
.table-responsive{
width: 510px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
@media (min-width: 768px) {
.fix_overflow {
.table-responsive{
width: 680px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
@media (min-width: 992px) {
.fix_overflow {
.table-responsive{
width: 900px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
@media (min-width: 1200px) {
.fix_overflow {
.table-responsive{
width: 1070px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
// HD laptops (1315)
@media screen and (min-width: 1366px) and (max-width: 1599px){
.fix_overflow {
.table-responsive{
width: 1230px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
// Large laptops / small desktops
@media screen and (min-width: 1600px) and (max-width: 1919px){
.fix_overflow {
.table-responsive{
width: 1510px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
// Full HD monitors (1080p)
@media screen and (min-width: 1920px) and (max-width: 2559px){
.fix_overflow {
.table-responsive{
width: 1820px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
// 2K monitors (1440p)
@media screen and (min-width: 2560px) and (max-width: 3839px){
.fix_overflow {
.table-responsive{
width: 2480px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}
// 4K monitors (2160p+)
@media screen and (min-width: 3840px){
.fix_overflow {
.table-responsive{
width: 3750px;
overflow-x: auto;
table.o_list_table{
width: 100%;
max-width: 100%;
}
}
}
}

View File

@ -0,0 +1 @@
# -*- coding: utf-8 -*-

View File

@ -0,0 +1,13 @@
# -*- coding: utf-8 -*-
import re
PHONE_FORMAT = re.compile(r'^0*(\d{9})$')
ID_FORMATS = re.compile(r'^0*(\d{10})$')
PHONE_FORMAT_BACKEND = re.compile(r'^0*(\d{14})$')
MOBILE_FORMAT = re.compile(r'^(\d{8})$')
MOBILE_FORMAT_BACKEND = re.compile(r'^(\d{14})$')
EMAIL_FORMAT = re.compile(r'^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$')
ID_FORMAT = re.compile(r'^.+$')
# IBAN_FORMAT = re.compile(r'^[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}$')
IBAN_FORMAT = re.compile(r'^(\d{22})$')
PASSWORD_FORMAT = re.compile(r'^(?=.*[A-Zء-يa-z])(?=.*\d)[A-Zء-يa-z\d]{6,}$')

View File

@ -0,0 +1,16 @@
<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>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,333 @@
<?xml version="1.0"?>
<odoo>
<template id="assets_backend" name="product_catalogue_assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet" type="text/scss" href="/odex_takaful/static/src/scss/donation_item_views.scss"/>
<link rel="stylesheet" type="text/scss" href="/odex_takaful/static/src/scss/fix_table_overflow.scss"/>
<script type="text/javascript" src="/odex_takaful/static/src/js/product_product_views.js"/>
<script type="text/javascript" src="/odex_takaful/static/src/js/donation_catalog_button.js"/>
<script type="text/javascript" src="/odex_takaful/static/src/js/donation_catalog_controls.js"/>
<!-- <script type="text/javascript" src="/odex_takaful/static/src/js/catalog_kanban_dynamic_button.js"/>-->
</xpath>
</template>
<!-- تحسينات بسيطة للتكافل -->
<template id="takaful_simple_enhancements" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<style>
/* تحسينات بسيطة فقط */
.o_form_label {
font-weight: 500;
}
.o_field_widget.o_field_monetary input {
font-weight: 600;
}
.o_field_widget.o_field_phone input {
direction: ltr;
}
/* Fix top spacing caused by h1 */
h1 {
margin-bottom: 5px !important;
margin-top: 5px !important;
}
/* Record Type Simple &amp; Clean Design */
.o_record_type_simple {
background: #f8f9fa;
padding: 8px 15px;
border-radius: 8px;
margin: 0;
text-align: center;
}
.record_type_options {
display: flex;
justify-content: center;
gap: 20px;
margin-top: 5px;
}
.record_option {
background: white;
border: 2px solid #e9ecef;
border-radius: 8px;
padding: 15px 25px;
cursor: pointer;
transition: all 0.2s ease;
min-width: 120px;
display: flex;
flex-direction: column;
align-items: center;
gap: 8px;
}
.record_option:hover {
border-color: #007bff;
transform: translateY(-1px);
box-shadow: 0 2px 8px rgba(0,123,255,0.15);
}
.record_option.selected {
border-color: #28a745;
background: #f8fff9;
box-shadow: 0 2px 8px rgba(40,167,69,0.15);
}
.record_option i {
font-size: 24px;
color: #6c757d;
}
.donation_option.selected i {
color: #28a745;
}
.sponsorship_option.selected i {
color: #007bff;
}
/* Donation Mechanism Simple Design */
.o_donation_mechanism_simple {
margin: 8px 0;
padding: 8px 15px;
background: #fff8e1;
border-radius: 6px;
border-left: 4px solid #ffc107;
text-align: center;
}
.mechanism_options {
display: flex;
justify-content: center;
gap: 15px;
margin-top: 5px;
}
.mechanism_option {
background: white;
border: 2px solid #e9ecef;
border-radius: 6px;
padding: 10px 20px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
gap: 8px;
min-width: 120px;
justify-content: center;
}
.mechanism_option i {
width: 20px;
text-align: center;
font-size: 16px;
}
.mechanism_option span {
min-width: 90px;
display: inline-block;
text-align: center;
}
.mechanism_option:hover {
border-color: #ffc107;
background: #fffbf0;
}
.mechanism_option.selected {
border-color: #ff9800;
background: #fff3e0;
color: #e65100;
}
/* Help Messages Styling */
.alert {
margin: 8px 0;
padding: 8px 15px;
border-radius: 6px;
font-size: 14px;
}
.alert-info {
background-color: #e8f4fd;
border: 1px solid #bee5eb;
color: #0c5460;
}
.alert-primary {
background-color: #cce7ff;
border: 1px solid #b3d7ff;
color: #004085;
}
</style>
<script type="text/javascript">
odoo.define('takaful.simple_ui_enhancement', function (require) {
'use strict';
var FormController = require('web.FormController');
FormController.include({
start: function () {
var self = this;
return this._super.apply(this, arguments).then(function () {
if (self.modelName === 'takaful.sponsorship') {
self._setupSimpleUI();
}
});
},
_update: function () {
var result = this._super.apply(this, arguments);
if (this.modelName === 'takaful.sponsorship') {
var self = this;
setTimeout(function() {
self._setupSimpleUI();
}, 50);
}
return result;
},
_onSave: function () {
var result = this._super.apply(this, arguments);
if (this.modelName === 'takaful.sponsorship') {
var self = this;
setTimeout(function() {
self._setupSimpleUI();
}, 100);
}
return result;
},
_setupSimpleUI: function () {
var self = this;
var currentData = self.model.localData[self.handle].data;
var isNewRecord = !currentData.id;
var isDraftState = currentData.state === 'draft';
var isEditMode = self.mode === 'edit';
var isEditable = isNewRecord || (isDraftState &amp;&amp; isEditMode);
// Remove old event handlers to prevent duplicates
this.$('.record_option').off('click');
this.$('.mechanism_option').off('click');
// Maintain visual selection (selected class) but disable interaction
// Update selected state based on current values
var recordType = currentData.record_type;
var donationMechanism = currentData.donation_mechanism;
// Update visual selection for record_type
this.$('.record_option').each(function() {
var $opt = $(this);
if ($opt.data('value') === recordType) {
$opt.addClass('selected');
} else {
$opt.removeClass('selected');
}
});
// Update visual selection for donation_mechanism
this.$('.mechanism_option').each(function() {
var $opt = $(this);
if ($opt.data('value') === donationMechanism) {
$opt.addClass('selected');
} else {
$opt.removeClass('selected');
}
});
if (!isEditable) {
this.$('.record_option').css({
'pointer-events': 'none',
'cursor': 'not-allowed'
});
this.$('.mechanism_option').css({
'pointer-events': 'none',
'cursor': 'not-allowed'
});
return;
} else {
this.$('.record_option').css({
'pointer-events': 'auto',
'cursor': 'pointer'
});
this.$('.mechanism_option').css({
'pointer-events': 'auto',
'cursor': 'pointer'
});
}
// Record Type Options - Odoo 14 Compatible Method
this.$('.record_option').on('click', function () {
var $option = $(this);
var recordType = $option.data('value');
var currentData = self.model.localData[self.handle].data;
// Clear sponsor_id when changing type if not registered
var sponsorOrDonorType = currentData.sponsor_or_donor_type;
var sponsorDonorType = currentData.sponsor_donor_type;
var changes = {record_type: recordType};
// Clear sponsor_id if switching types and not 'registered'
if (sponsorOrDonorType !== 'registered' &amp;&amp; sponsorDonorType !== 'registered') {
changes.sponsor_id = false;
}
// Update field value using Odoo 14 method
self.trigger_up('field_changed', {
dataPointID: self.handle,
changes: changes
});
// Update visual selection
self.$('.record_option').removeClass('selected');
$option.addClass('selected');
});
// Donation Mechanism Options - Odoo 14 Compatible Method
this.$('.mechanism_option').on('click', function () {
var $option = $(this);
var mechanism = $option.data('value');
// Update field value using Odoo 14 method
self.trigger_up('field_changed', {
dataPointID: self.handle,
changes: {donation_mechanism: mechanism}
});
// Update visual selection
self.$('.mechanism_option').removeClass('selected');
$option.addClass('selected');
});
// Set default selection on load
setTimeout(function() {
var currentRecordType = self.model.localData[self.handle].data.record_type;
if (currentRecordType) {
self.$('.record_option[data-value="' + currentRecordType + '"]').addClass('selected');
} else {
// Default to donation as requested
self.$('.record_option[data-value="donation"]').addClass('selected');
}
var currentMechanism = self.model.localData[self.handle].data.donation_mechanism;
if (currentMechanism) {
self.$('.mechanism_option[data-value="' + currentMechanism + '"]').addClass('selected');
} else {
// Default to without_conditions (غير مشروط) as requested
self.$('.mechanism_option[data-value="without_conditions"]').addClass('selected');
}
}, 100);
}
});
});
</script>
</xpath>
</template>
</odoo>

View File

@ -0,0 +1,35 @@
<odoo>
<!-- Inherit the original form view -->
<record id="inherit_grant_benefit_form_add_replaced" model="ir.ui.view">
<field name="name">grant.benefit.form.inherit.replaced</field>
<field name="model">grant.benefit</field>
<field name="inherit_id" ref="odex_benefit.grant_benefit_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button name="action_open_replacements" class="oe_stat_button" string="Replacement Processes"
type="object" icon="fa-users">
</button>
</xpath>
<xpath expr="//field[@name='member_ids']/tree/field[@name='state']" position="before">
<field name="replaced" readonly="1" invisible="1"/>
</xpath>
</field>
</record>
<record id="family_member_form_inherit_add_replaced" model="ir.ui.view">
<field name="name">family.member.form.inherit.add.replaced</field>
<field name="model">family.member</field>
<field name="inherit_id" ref="odex_benefit.family_member_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='member_status']" position="after">
<field name="replaced" readonly="1" invisible="1"/>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Tree View -->
<record id="donation_extension_history_tree" model="ir.ui.view">
<field name="name">donation.extension.history.tree</field>
<field name="model">donation.extension.history</field>
<field name="arch" type="xml">
<tree create="0" edit="0" delete="0">
<field name="extension_ref"/>
<field name="sponsor_id"/>
<field name="product_template_id"/>
<field name="extension_months"/>
<field name="extension_amount"/>
<field name="old_end_date"/>
<field name="new_end_date"/>
<field name="extension_date"/>
<field name="user_id"/>
<field name="invoice_id"/>
</tree>
</field>
</record>
<!-- Form View -->
<record id="donation_extension_history_form" model="ir.ui.view">
<field name="name">donation.extension.history.form</field>
<field name="model">donation.extension.history</field>
<field name="arch" type="xml">
<form create="0" edit="0" delete="0">
<sheet>
<group>
<group>
<field name="extension_ref"/>
<field name="donation_detail_id"/>
<field name="sponsor_id"/>
<field name="sponsorship_id"/>
<field name="product_template_id"/>
</group>
<group>
<field name="extension_amount"/>
<field name="extension_months"/>
<field name="old_end_date"/>
<field name="new_end_date"/>
<field name="extension_date"/>
<field name="user_id"/>
<field name="invoice_id"/>
<field name="old_direct_debit"/>
<field name="new_direct_debit"/>
</group>
</group>
<group>
<field name="notes"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Action -->
<record id="action_donation_extension_history" model="ir.actions.act_window">
<field name="name">Extension History</field>
<field name="res_model">donation.extension.history</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No extension history found
</p>
<p>
Extension history will appear here when donations are extended.
</p>
</field>
</record>
<!-- Menu Item (Optional - can be added to existing menu structure) -->
<!-- <menuitem id="menu_donation_extension_history"
name="Extension History"
parent="existing_parent_menu"
action="action_donation_extension_history"
sequence="100"/> -->
</data>
</odoo>

View File

@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="product_product_view_kanban" model="ir.ui.view">
<field name="name">product.product.view.kanban</field>
<field name="model">donations.items</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="donation_types"/>
<field name="payment_method_id"/>
<templates>
<t t-name="kanban-box">
<div class="o_product_quantity d-flex flex-column justify-content-between"
style="min-height: 100px">
<div class="o_kanban_image">
</div>
<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">
<strong>
<field name="name"/>
</strong>
</div>
<div style="z-index:1;align-items: center;">
<button id="add_payment_method" string="Add Payment Method" style="width:140px;height:27px"
class="btn btn-primary"
type="object" name="add_payment_method">
Add Payment
</button>
</div>
<div class="d-flex w-100 justify-content-between">
<ul>
<li>
<strong>Amount :
<field name="fixed_donation_amount" widget="monetary"></field>
</strong>
</li>
</ul>
</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">
<i class="fa fa-plus" title="Increase"/>
</button>
</div>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
</odoo>

View File

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<!-- Tree View -->
<record id="donation_replacement_log_tree" model="ir.ui.view">
<field name="name">donation.replacement.log.tree</field>
<field name="model">donation.replacement.log</field>
<field name="arch" type="xml">
<tree create="0" edit="0" delete="0">
<field name="replacement_ref"/>
<field name="sponsor_id"/>
<field name="record_type"/>
<field name="old_benefit"/>
<field name="new_benefit"/>
<field name="replacement_date"/>
<field name="replacement_reason_id"/>
<field name="user_id"/>
</tree>
</field>
</record>
<!-- Form View -->
<record id="donation_replacement_log_form" model="ir.ui.view">
<field name="name">donation.replacement.log.form</field>
<field name="model">donation.replacement.log</field>
<field name="arch" type="xml">
<form create="0" edit="0" delete="0">
<sheet>
<group>
<group>
<field name="replacement_ref"/>
<field name="donation_detail_id"/>
<field name="sponsor_id"/>
<field name="sponsorship_id"/>
<field name="replacement_reason_id"/>
</group>
<group>
<field name="old_benefit"/>
<field name="new_benefit"/>
<field name="replacement_date"/>
<field name="user_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<!-- Action -->
<record id="action__replacement_log_history" model="ir.actions.act_window">
<field name="name">Replacement Log</field>
<field name="res_model">donation.replacement.log</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
No extension history found
</p>
<p>
Replacement Log will appear here when Benefit donations are replaced.
</p>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,485 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="donations_details_lines_view_search" model="ir.ui.view">
<field name="name">donations.details.lines.view.search</field>
<field name="model">donations.details.lines</field>
<field name="arch" type="xml">
<search string="Search Donation Details Lines">
<field name="sequence_no"/>
<field name="sponsor_id"/>
<field name="benefit_id"/>
<field name="product_template_id"/>
<field name="branch_custom_id"/>
<separator/>
<!-- State Filters -->
<filter string="To Pay" name="filter_draft" domain="[('state', '=', 'draft')]"/>
<filter string="Waiting" name="filter_waiting" domain="[('state', '=', 'waiting')]"/>
<filter string="To Replace" name="filter_replace" domain="[('state', '=', 'replace')]"/>
<filter string="Active" name="filter_active" domain="[('state', '=', 'active')]"/>
<filter string="Closed" name="filter_closed" domain="[('state', '=', 'closed')]"/>
<filter string="Extended" name="filter_extended" domain="[('state', '=', 'extended')]"/>
<separator/>
<!-- Record Type Filters -->
<filter string="Sponsorship" name="filter_sponsorship" domain="[('donation_type', '=', 'sponsorship')]"/>
<filter string="Donation" name="filter_donation" domain="[('donation_type', '=', 'donation')]"/>
<filter string="Waqf" name="filter_waqf" domain="[('donation_type', '=', 'waqf')]"/>
<separator/>
<!-- Sponsorship Duration Filters -->
<filter string="Permanent" name="filter_permanent" domain="[('sponsorship_duration', '=', 'permanent')]"/>
<filter string="Temporary" name="filter_temporary" domain="[('sponsorship_duration', '=', 'temporary')]"/>
<separator/>
<!-- Donation Mechanism Filters -->
<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')]"/>
<separator/>
<group expand="0" string="Group By">
<filter string="State" name="group_state" context="{'group_by': 'state'}"/>
<filter string="Donation Type" name="group_donation_type" context="{'group_by': 'donation_type'}"/>
<filter string="Sponsorship Duration" name="group_duration" context="{'group_by': 'sponsorship_duration'}"/>
<filter string="Donation Mechanism" name="group_mechanism" context="{'group_by': 'donation_mechanism'}"/>
<filter string="Sponsor" name="group_sponsor" context="{'group_by': 'sponsor_id'}"/>
<filter string="Branch" name="group_branch" context="{'group_by': 'branch_custom_id'}"/>
<filter string="Product" name="group_product" context="{'group_by': 'product_template_id'}"/>
<filter string="Creation Date" name="group_creation_date" context="{'group_by': 'create_date'}"/>
</group>
<separator/>
<searchpanel>
<field name="state" enable_counters="1"/>
<field name="record_type" enable_counters="1"/>
<field name="sponsorship_duration" enable_counters="1"/>
<field name="donation_mechanism" enable_counters="1"/>
</searchpanel>
</search>
</field>
</record>
<record id="donations_details_lines_view_tree" model="ir.ui.view">
<field name="name">donations.details.lines.view.tree</field>
<field name="model">donations.details.lines</field>
<field name="arch" type="xml">
<tree default_order="create_date asc , waiting_date asc " create="0" edit="0" >
<field name="sponsorship_scheduling_line_ids" invisible="1" />
<field name="direct_debit" invisible="1" />
<field name="sequence_no" />
<field name="sponsor_id" />
<field name="sponsor_phone" widget="phone"/>
<field name="donation_type" optional="show"/>
<field name="sponsorship_duration" optional="hide"/>
<field name="donation_mechanism" optional="hide"/>
<field name="product_template_id" />
<field name="benefit_status" widget="badge"
decoration-success="benefit_status == 'benefit'"
decoration-danger="benefit_status == 'non_benefit'"/>
<field name="start_date" widget="date"/>
<field name="end_date" widget="date"/>
<field name="donation_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="total_donation_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="branch_custom_id" optional="hide" />
<field name="benefit_family_code" optional="hide" />
<field name="benefit_id" optional="hide" />
<!-- <field name="sponsorship_creation_date" />-->
<field name="create_date" optional="hide"/>
<field name="waiting_date" widget="date" optional="hide"/>
<field name="state" widget="badge"
decoration-muted="state == 'draft'"
decoration-warning="state == 'waiting'"
decoration-success="state in ['active', 'paid','confirmed']"
decoration-danger="state == 'closed'"
decoration-info="state == 'extended'" />
<field name="age_category" widget="state" />
<button name="action_view_scheduling_lines"
string="View Scheduling Lines"
type="object"
attrs="{'invisible': ['|', ('direct_debit', '=', False), ('sponsorship_scheduling_line_ids', '=', [])]}"
class="btn-secondary"
icon="fa-calendar" />
</tree>
</field>
</record>
<record id="donations_details_lines_view_form" model="ir.ui.view">
<field name="name">donations.details.lines.view.form</field>
<field name="model">donations.details.lines</field>
<field name="arch" type="xml">
<form string="Donation Details" create="0" edit="0" >
<header>
<!-- <button name="action_register_payment"
string="Register Payment"
type="object"
class="btn-primary"
attrs="{'invisible': ['|', '|', ('direct_debit', '=', True), ('is_paid', '=', True), ('parent_state', '!=', 'confirmed')]}" /> -->
<button string="Compute Sponsorships"
name="compute_sponsorships_lines"
type="object"
class="oe_highlight"
attrs="{'invisible': ['|', ('sponsorships_computed', '=', True), ('direct_debit', '=', False)]}" />
<button string="Extend Donation"
name="action_extend_sponsorship"
type="object"
class="btn-primary"
icon="fa-plus-circle"
attrs="{'invisible': [('show_extend_button', '=', False)]}" />
<button string="Orphan Replacement"
name="action_view_replacement_wizard"
type="object"
class="btn-primary"
icon="fa-exchange"
attrs="{'invisible': [('show_replaced_button', '=', False)]}"
groups="odex_takaful.group_orphan_replacement" />
<button string="Replace Sponsor"
name="replace_sponsor_wizard"
type="object"
class="btn-primary"
icon="fa-exchange"
attrs="{'invisible': [('sponsor_id', '=', False)]}"
groups="odex_takaful.group_replace_sponsor" />
<button string="Add Benefit"
name="add_benefit_wizard"
type="object"
class="btn-primary"
icon="fa-plus-circle"
attrs="{'invisible': [('show_add_benefit_button', '=', False)]}"
groups="odex_takaful.group_kufula_user" />
<field name="state" widget="statusbar"
statusbar_visible="draft,confirmed,waiting,active,replace,closed" />
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_extension_history"
type="object"
class="oe_stat_button"
icon="fa-history"
attrs="{'invisible': [('extension_count', '=', 0)]}">
<field name="extension_count" widget="statinfo" string="Extensions"/>
</button>
</div>
<div class="oe_button_box" name="button_box">
<button name="action_view_replacement_log"
type="object"
class="oe_stat_button"
icon="fa-exchange"
attrs="{'invisible': [('replacement_count', '=', 0)]}">
<field name="replacement_count" widget="statinfo" string="Replacement"/>
</button>
</div>
<div class="oe_title">
<h1>
<field name="sequence_no" readonly="1" />
</h1>
</div>
<group>
<group string="Donation Information">
<field name="ages" invisible="1" />
<field name="period_display" invisible="0" />
<field name="waiting_date" widget="date" invisible="1"/>
<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')]}"
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"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="total_donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
</group>
<group string="Sponsorship Information">
<field name="sponsorship_id" readonly="1"
attrs="{'invisible': [('sponsorship_id', '=', False)]}" />
<field name="sponsorship_mechanism_id" readonly="1"
attrs="{'invisible': [('sponsorship_mechanism_id', '=', False)]}" />
<field name="sponsor_id"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="sponsor_phone" widget="phone"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="branch_custom_id"
attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="sponsorship_creation_date" invisible="1" />
<field name="parent_state" invisible="1" />
<field name="is_paid" invisible="1" />
<field name="show_extend_button" invisible="1" />
<field name="show_replaced_button" invisible="1" />
<field name="show_add_benefit_button" invisible="1" />
</group>
</group>
<notebook>
<page string="Sponsorship Details" attrs="{'invisible': [('donation_mechanism', '!=', 'with_conditions')]}">
<group>
<group>
<field name="display_type" invisible="1" />
<field name="sequence" invisible="1" />
<field name="sponsorships_computed" invisible="1" />
<field name="record_type" invisible="1" />
<field name="donation_type"
attrs="{'invisible': [('record_type', '!=', 'sponsorship')], 'readonly': ['|', ('record_type', '=', 'sponsorship'), ('parent_state', '!=', 'draft')]}"
force_save="1" />
<field name="age_category" widget="state" />
<field name="direct_debit" invisible="1" />
<field name="donation_types"
attrs="{
'invisible': [('record_type', '!=', 'donation')],
'required': [('record_type', '=', 'donation')],
'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="sponsorship_duration"
attrs="{'invisible': [('donation_type','!=','sponsorship')], 'required': [('donation_type','=','sponsorship')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="payment_option"
attrs="{'invisible': [('sponsorship_duration','!=','temporary')], 'required': [('sponsorship_duration','=','temporary')], 'readonly': [('parent_state', '!=', 'draft')]}"
readonly="1" force_save="1" />
<field name="payment_month_count"
attrs="{'invisible': ['&amp;', ('sponsorship_duration','!=','temporary'), ('direct_debit', '=', False)], 'required': [('sponsorship_duration','=','temporary')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="start_date" string="Start Date" widget="date"
attrs="{'invisible': ['&amp;', ('sponsorship_duration', '!=', 'temporary'), ('direct_debit', '=', False)], 'required': [('sponsorship_duration', '=','temporary')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="end_date" string="End Date" widget="date"
attrs="{'invisible': ['&amp;', ('sponsorship_duration', '!=', 'temporary'), ('direct_debit', '=', False)], 'readonly': [('parent_state', '!=', 'draft')]}" />
</group>
<group>
<field name="donation_mechanism" invisible="1" />
<field name="fixed_value" invisible="1" />
<field name="donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly':['|', ('fixed_value','=',True), ('parent_state', '!=', 'draft')]}"
force_save="1" required="1" />
<field name="benefits_count"
attrs="{'invisible':[('sponsorship_type','!=','group')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="total_donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'invisible':[('sponsorship_type','!=','group')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="name" attrs="{'readonly': [('parent_state', '!=', 'draft')]}" />
</group>
</group>
<group string="Benefit Details"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')]}">
<group>
<field name="members_domain_ids" invisible="1" />
<field name="family_domain_ids" invisible="1" />
<field name="sponsorship_type"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'required': [('donation_mechanism','=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="benefit_type"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'required': [('donation_mechanism','=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="benefit_id"
attrs="{'invisible': ['|', ('sponsorship_type','!=','person'), ('donation_mechanism','!=','with_conditions')], 'required': [('members_domain_ids', '!=', []), ('sponsorship_type','=','person'), ('donation_mechanism','=','with_conditions'), ('state', 'in', ['active', 'closed', 'extended'])], 'readonly': ['&amp;', ('parent_state', '!=', 'draft'), ('state', '!=', 'waiting')]}"
options="{'no_create': True, 'no_create_edit':True}" />
<field name="family_id"
attrs="{'invisible': ['&amp;', ('sponsorship_type','=','group'), ('record_type','=','sponsorship')],
'readonly': ['|', '|', ('sponsorship_type', '!=', 'group'), ('record_type','!=','donation'), ('parent_state', '!=', 'draft')],
'required': ['&amp;', ('sponsorship_type', '=','group'), ('record_type','=','donation')]}"
groups="odex_takaful.sponsorship_system_manager_group" />
</group>
<!-- <group/> -->
<group
attrs="{'invisible': ['&amp;', ('sponsorship_type','=','group'), ('record_type','=','donation')]}">
<field name="gender"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="age_category_id"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="education_status"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="education_level"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="benefit_id_number"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
<field name="benefit_family_code"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'readonly': [('parent_state', '!=', 'draft')]}" />
</group>
</group>
<group string="Orphans List"
attrs="{'invisible': ['|', '|',('record_type','!=','sponsorship'), ('sponsorship_type', '!=', 'group'), ('benefit_type', '!=', 'orphan')]}">
<field name="benefit_ids" nolabel="1" attrs="{'readonly': ['&amp;', ('parent_state', '!=', 'draft'), ('state', '!=', 'waiting')]}" />
</group>
<group string="Widows List"
attrs="{'invisible': ['|', '|',('record_type','!=','sponsorship'), ('sponsorship_type', '!=', 'group'), ('benefit_type', '!=', 'widow')]}">
<field name="benefit_ids" nolabel="1" attrs="{'readonly': ['&amp;', ('parent_state', '!=', 'draft'), ('state', '!=', 'waiting')]}" />
</group>
<group string="Orphans and Widows List"
attrs="{'invisible': ['|', '|',('record_type','!=','sponsorship'), ('sponsorship_type', '!=', 'group'), ('benefit_type', '!=', 'both')]}">
<field name="benefit_ids" nolabel="1" attrs="{'readonly': ['&amp;', ('parent_state', '!=', 'draft'), ('state', '!=', 'waiting')]}" />
</group>
</page>
<page string="Sponsorship Scheduling"
attrs="{'invisible': [('sponsorship_scheduling_line_ids', '=', False)]}">
<field name="sponsorship_scheduling_line_ids" mode="tree">
<tree create="false" delete="false" edit="false">
<field name="sequence_no" />
<field name="beneficiary_id" />
<field name="month_year" />
<field name="currency_id" invisible="1"/>
<field name="amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="refunded_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="status" widget="badge"
decoration-danger="status == 'unpaid'"
decoration-success="status == 'paid'"
decoration-muted="status in ('partial_refund','fully_refund')" />
<field name="sponsorship_state" invisible="1" />
<field name="cancel_refund" invisible="1" />
<!-- To approve refund for donation lines -->
<button string="Approve Refund" name="approve_refund"
type="object" class="oe_highlight"
attrs="{'invisible': ['|', ('parent.donation_type', '!=', 'donation'), ('sponsorship_state', '!=', 'approve_refund')]}"
groups="odex_takaful.group_refund_approval" />
<!-- To action refund paid line -->
<button string="Action Refund" name="action_refund"
type="object" class="oe_highlight"
attrs="{'invisible': ['|', '|', '|', ('parent.donation_type', '!=', 'donation'), ('cancel_refund', '=', True), ('status', 'not in', ['paid', 'partial_refund']), ('sponsorship_state', 'not in', ['paid','partial_refund'])]}" />
</tree>
</field>
</page>
</notebook>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" />
<field name="message_ids" />
</div>
</form>
</field>
</record>
<record id="donations_details_lines_view_tree_waiting" model="ir.ui.view">
<field name="name">donations.details.lines.view.tree.waiting</field>
<field name="model">donations.details.lines</field>
<field name="arch" type="xml">
<tree default_order="waiting_date asc" create="0" edit="0" >
<field name="sponsorship_scheduling_line_ids" invisible="1" />
<field name="direct_debit" invisible="1" />
<field name="sequence_no" />
<field name="sponsor_id" />
<field name="sponsor_phone" widget="phone"/>
<field name="donation_type" optional="show"/>
<field name="sponsorship_duration" optional="hide"/>
<field name="donation_mechanism" optional="hide"/>
<field name="product_template_id" />
<field name="benefit_status" widget="badge"
decoration-success="benefit_status == 'benefit'"
decoration-danger="benefit_status == 'non_benefit'"/>
<field name="start_date" widget="date"/>
<field name="end_date" widget="date"/>
<field name="donation_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="total_donation_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="branch_custom_id" optional="hide" />
<field name="benefit_family_code" optional="hide" />
<field name="benefit_id" optional="hide" />
<!-- <field name="sponsorship_creation_date" />-->
<field name="create_date" optional="hide"/>
<field name="waiting_date" />
<field name="waiting_date" string='مدة الانتظار' widget="remaining_days" />
<!-- <field name="period_display" />-->
<field name="state" widget="badge"
decoration-muted="state == 'draft'"
decoration-warning="state == 'waiting'"
decoration-success="state in ['active', 'paid','confirmed']"
decoration-danger="state == 'closed'"
decoration-info="state == 'extended'" />
<field name="age_category" widget="state" />
<button name="action_view_scheduling_lines"
string="View Scheduling Lines"
type="object"
attrs="{'invisible': ['|', ('direct_debit', '=', False), ('sponsorship_scheduling_line_ids', '=', [])]}"
class="btn-secondary"
icon="fa-calendar" />
</tree>
</field>
</record>
<record id="donations_details_lines_view_tree_replace" model="ir.ui.view">
<field name="name">donations.details.lines.view.tree.replace</field>
<field name="model">donations.details.lines</field>
<field name="arch" type="xml">
<tree default_order="end_date asc" create="0" edit="0" >
<field name="sponsorship_scheduling_line_ids" invisible="1" />
<field name="direct_debit" invisible="1" />
<field name="sequence_no" />
<field name="sponsor_id" />
<field name="sponsor_phone" widget="phone"/>
<field name="donation_type" optional="show"/>
<field name="sponsorship_duration" optional="hide"/>
<field name="donation_mechanism" optional="hide"/>
<field name="product_template_id" />
<field name="benefit_status" widget="badge"
decoration-success="benefit_status == 'benefit'"
decoration-danger="benefit_status == 'non_benefit'"/>
<field name="start_date" widget="date"/>
<field name="end_date" widget="date"/>
<field name="donation_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="total_donation_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="branch_custom_id" optional="hide" />
<field name="benefit_family_code" optional="hide" />
<field name="benefit_id" optional="hide" />
<!-- <field name="sponsorship_creation_date" />-->
<field name="create_date" optional="hide"/>
<field name="actual_end_date" widget="date" string="تاريخ خروج المستفيد" />
<field name="actual_end_date" widget="remaining_days" string="فترة الخروج" />
<field name="state" widget="badge"
decoration-muted="state == 'draft'"
decoration-warning="state == 'waiting'"
decoration-success="state in ['active', 'paid','confirmed']"
decoration-danger="state == 'closed'"
decoration-info="state == 'extended'" />
<field name="age_category" widget="state" />
<button name="action_view_scheduling_lines"
string="View Scheduling Lines"
type="object"
attrs="{'invisible': ['|', ('direct_debit', '=', False), ('sponsorship_scheduling_line_ids', '=', [])]}"
class="btn-secondary"
icon="fa-calendar" />
</tree>
</field>
</record>
<record id="donations_details_lines_action" model="ir.actions.act_window">
<field name="name">Donations Details Lines</field>
<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>
</record>
<record id="donations_details_lines_waiting_action" model="ir.actions.act_window">
<field name="name">Donations Details Lines waiting</field>
<field name="res_model">donations.details.lines</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state', '=', 'waiting')]</field>
<field name="search_view_id" ref="donations_details_lines_view_search"/>
<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>
</record>
<record id="donations_details_lines_replace_action" model="ir.actions.act_window">
<field name="name">Donations Details Lines Replacement</field>
<field name="res_model">donations.details.lines</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('state', '=', 'replace')]</field>
<field name="view_ids" eval="[(5, 0, 0),
(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>
</record>
</odoo>

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Inherit Family Member Form to Add Donation Details Smart Button -->
<record id="family_member_form_inherit_donation_button" model="ir.ui.view">
<field name="name">family.member.form.inherit.donation.button</field>
<field name="model">family.member</field>
<field name="inherit_id" ref="odex_benefit.family_member_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@name='button_box']" position="inside">
<button icon="fa-money" name="action_open_donation_detail" type="object"
attrs="{'invisible': [('donation_details_count', '=', 0)]}">
<field name="donation_details_count" string="Donation Details"
widget="statinfo"/>
</button>
</xpath>
<xpath expr="//field[@name='sponsor_related_id']" position="replace">
<field name="sponsor_related_id" readonly="1" invisible="1"/>
</xpath>
<xpath expr="//page[4]" position="after">
<page name="kafala_info" string="Kafala Information">
<group>
<field name="kafala_status" readonly="1"/>
<field name="sponsor_related_id"
readonly="1"/>
<field name="sponsor_id"
attrs="{'readonly':[('state','not in',['draft','complete_info'])]}"
invisible="1"/>
<field name="sponsorship_id" invisible="1"
attrs="{'readonly':[('state','not in',['draft','complete_info'])]}"/>
<field name="sponsorship_end_date" readonly="1"/>
</group>
<group>
<field name="is_restricted" widget="boolean_toggle"/>
<field name="general_restriction" widget="boolean_toggle"/>
</group>
</page>
</xpath>
<xpath expr="//header" position="inside">
<button name="action_not_available_for_sponsorship" type="object"
string="Not Available For Sponsorship" class="oe_highlight"
attrs="{'invisible': [('general_restriction','=', True)]}"
groups="odex_takaful.sponsorship_restrict_orphan_group"
/>
<button name="action_available_for_sponsorship" type="object"
string="Available For Sponsorship" class="oe_highlight"
attrs="{'invisible': [('general_restriction','!=', True)]}"
groups="odex_takaful.sponsorship_restrict_orphan_group"
/>
</xpath>
</field>
</record>
<record id="family_member_search_inherit" model="ir.ui.view">
<field name="name">family.member.search.inherit</field>
<field name="model">family.member</field>
<field name="inherit_id" ref="odex_benefit.family_member_search"/>
<field name="arch" type="xml">
<field name="benefit_id" position="after">
<separator/>
<filter name="have_kafala" string="Have Kafala"
domain="[('kafala_status','=','have_kafala')]"/>
<filter name="have_not_kafala" string="Have not Kafala"
domain="[('kafala_status','=','have_not_kafala')]"/>
<separator/>
<filter name="orphan_benefit_type" string="Orphans"
domain="[('relationn_type', 'in', ['son', 'daughter'])]"/>
<filter name="widow_benefit_type" string="Widows"
domain="[('relationn_type', 'in', ['mother', 'replacement_mother'])]"/>
<separator/>
<filter name="male_gender" string="Male"
domain="[('relationn_type', '=', 'son')]"/>
<filter name="female_gender" string="Female"
domain="[('relationn_type', '!=', 'son')]"/>
<separator/>
<filter name="age_category_0_to_6" string="Age From 0 To 6"
domain="[('age', '>=', 0), ('age', '&lt;', 7)]"/>
<filter name="age_category_7_to_10" string="Age From 7 To 10"
domain="[('age', '>=', 7), ('age', '&lt;', 11)]"/>
<filter name="age_category_11_to_15" string="Age From 11 To 15"
domain="[('age', '>=', 11), ('age', '&lt;', 16)]"/>
<filter name="age_category_16_to_18" string="Age From 16 To 18"
domain="[('age', '>=', 16), ('age', '&lt;', 19)]"/>
<filter name="age_category_over_18" string="Age Over 18"
domain="[('age', '>', 18)]"/>
<separator/>
<filter name="educated_educated_status" string="Educated"
domain="[('education_status', '=', 'educated')]"/>
<filter name="illiterate_educated_status" string="Illiterate"
domain="[('education_status', '=', 'illiterate')]"/>
<filter name="under_study_age_educated_status" string="Under Study Age"
domain="[('education_status', '=', 'under_study_age')]"/>
<separator/>
</field>
</field>
</record>
<record id="view_family_member_tree_inherit" model="ir.ui.view">
<field name="name">family.member.tree.inherit</field>
<field name="model">family.member</field>
<field name="inherit_id" ref="odex_benefit.family_member_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='member_status']" position="after">
<field name="kafala_status" widget="badge"
decoration-success="kafala_status == 'have_kafala'"
decoration-danger="kafala_status == 'have_not_kafala'"/>
<field name="sponsorship_end_date" optional="hide" />
</xpath>
</field>
</record>
<record id="family_member_kanban_kafala_inherit" model="ir.ui.view">
<field name="name">family.member.kanban.kafala.inherit</field>
<field name="model">family.member</field>
<field name="inherit_id" ref="odex_benefit.family_member_kanban"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='total_member_service_requests']" position="after">
<field name="kafala_status"/>
<field name="sponsorship_end_date"/>
</xpath>
<xpath expr="//div[@t-attf-class]" position="attributes">
<attribute name="t-attf-style">background: linear-gradient(135deg, #{record.member_status.raw_value == 'non_benefit' ? '#fff5f5' : '#ffffff'} 0%, #{record.member_status.raw_value == 'non_benefit' ? '#ffe0e0' : '#f8f9fa'} 100%); border: 2px solid #{record.member_status.raw_value == 'non_benefit' ? '#dc3545' : '#198754'}; border-radius: 15px; box-shadow: 0 4px 15px rgba(0,0,0,0.1); transition: all 0.3s ease; margin-bottom: 15px; overflow: hidden; position: relative; min-height: 300px; opacity: #{record.member_status.raw_value == 'non_benefit' ? '0.85' : '1'};</attribute>
</xpath>
<xpath expr="//div[@style='padding: 10px; background: white;']" position="after">
<div style="background: linear-gradient(135deg, #f8f9fa 0%, #e9ecef 100%); padding: 10px 5px; border-top: 2px solid #198754; text-align: right;">
<div style="display: flex; justify-content: space-between; align-items: center; font-size: 11px;">
<div style="display: inline-flex; align-items: center;">
<i class="fa fa-shield" style="color: #6c757d; margin-left: 4px;"/>
<span style="font-weight: 600; color: #495057; margin-left: 4px;"></span>
<span style="font-weight: 600;">
<t t-if="record.kafala_status.raw_value == 'have_kafala'">
<span style="background: linear-gradient(135deg, #e8f5e8 0%, #c8e6c9 100%); color: #2e7d32; padding: 2px 6px; border-radius: 8px; font-weight: 700; font-size: 10px; border: 1px solid #4caf50;">
مكفول
</span>
</t>
<t t-elif="record.kafala_status.raw_value == 'have_not_kafala'">
<span style="background: linear-gradient(135deg, #fff8e1 0%, #ffecb3 100%); color: #e65100; padding: 2px 6px; border-radius: 8px; font-weight: 700; font-size: 10px; border: 1px solid #ff9800;">
غير مكفول
</span>
</t>
<t t-else="">
<span style="color: #6c757d;">--</span>
</t>
</span>
</div>
<t t-if="record.kafala_status.raw_value == 'have_kafala'">
<div style="display: inline-flex; align-items: center;">
<i class="fa fa-calendar" style="color: #6c757d; margin-left: 4px;"/>
<span style="font-weight: 600; color: #495057; margin-left: 4px;">تنتهي الكفالة: </span>
<span style="color: #212529; font-weight: 500;">
<t t-if="record.sponsorship_end_date.raw_value">
<field name="sponsorship_end_date"/>
</t>
<t t-else="">
<span style="color: #6c757d;">--</span>
</t>
</span>
</div>
</t>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="view_payment_details_wizard_form" model="ir.ui.view">
<field name="name">payment.details.wizard.form</field>
<field name="model">payment.details.lines</field>
<field name="arch" type="xml">
<form string="Payment Details">
<group>
<group>
<field name="payment_method" invisible="1"/>
<field name="payment_method_id" readonly="1"/>
<field name="direct_debit_start_date" attrs="{'invisible': [('payment_method','!=','direct_debit')]}"/>
<field name="name" attrs="{'invisible': [('payment_method','!=','card'),('payment_method','!=','debit_card')]}"/>
<field name="check_number" attrs="{'invisible': [('payment_method','!=','check')]}"/>
<field name="bank_id" attrs="{'invisible': ['|',('payment_method','=','cash'),('payment_method','=',False)]}"/>
<field name="bank_name" attrs="{'invisible': ['|',('payment_method','!=','credit_card'),('payment_method','=',False)]}"/>
<field name="bank_journal_id" attrs="{'invisible': ['|',('payment_method','!=','credit_card'),('payment_method','=',False)]}" />
<field name="charity_bank_id" attrs="{'invisible': [('payment_method','!=','bank_transfer'),('payment_method','!=','direct_debit')]}"/>
<label for="sponsor_account_number" attrs="{'invisible': [('payment_method','!=','bank_transfer'),('payment_method','!=','direct_debit')]}"/>
<div class="o_row" attrs="{'invisible': [('payment_method','!=','bank_transfer'),('payment_method','!=','direct_debit')]}">
<field name="sponsor_account_number" width="100%" />
<field name="sa_iban"/>
</div>
<field name="journal_id"/>
<field name="branch_custom_id" invisible="1"/>
<field name="points_of_sale" attrs="{'invisible': [('payment_method','!=','card'),('payment_method','!=','credit_card')]}"/>
</group>
<group>
<field name="payment_date"/>
<field name="direct_debit_end_date" attrs="{'invisible': [('payment_method','!=','direct_debit')]}"/>
<field name="donation_date"/>
<field name="charity_journal_id" attrs="{'invisible': [('payment_method','!=','card'),('payment_method','!=','credit_card')]}"/>
<field name="currency_id" invisible="1"/>
<field name="donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1" force_save="1"/>
<field name="sponsorship_id" invisible="1" readonly="1" force_save="1"/>
<field name="account_payment_method" attrs="{'invisible': [('payment_method','!=','card'),('payment_method','!=','credit_card')]}"/>
<field name="note"/>
<field name="payment_attachment" widget="many2many_attachment_preview" attrs="{'invisible': [('payment_method','!=','bank_transfer'),('payment_method','!=','direct_debit')]}"/>
</group>
</group>
<footer>
<button name="action_confirm" type="object" string="Confirm" class="btn-primary"/>
<button string="Cancel" class="btn-secondary" special="cancel"/>
</footer>
</form>
</field>
</record>
</odoo>

View File

@ -0,0 +1,37 @@
<odoo>
<record id="view_preferred_communication_form" model="ir.ui.view">
<field name="name">preferred.communication.form</field>
<field name="model">preferred.communication</field>
<field name="arch" type="xml">
<form string="Preferred Communication">
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_preferred_communication_tree" model="ir.ui.view">
<field name="name">preferred.communication.tree</field>
<field name="model">preferred.communication</field>
<field name="arch" type="xml">
<tree string="Preferred Communication">
<field name="name"/>
</tree>
</field>
</record>
<record id="action_preferred_communication" model="ir.actions.act_window">
<field name="name">Preferred Communication</field>
<field name="res_model">preferred.communication</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_preferred_communication"
name="Preferred Communication"
parent="odex_takaful.sponsor_setting_menu"
action="action_preferred_communication"/>
</odoo>

View File

@ -0,0 +1,129 @@
<odoo>
<record id="product_template_view_kanban_odex_takaful" model="ir.ui.view">
<field name="name">product.template.view.kanban.odex.takaful</field>
<field name="model">product.template</field>
<field name="arch" type="xml">
<kanban edit="0" create="0" class="o_kanban_mobile o_cart_kanban o_cart_kanban_donation">
<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="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" 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"/>
<svg id="Layer_1" data-name="Layer 1" viewBox="0 0 1124.14 1256.39" style="height: 11px"><defs><style>.cls-1 {fill: #231f20;}</style></defs><path class="cls-1" d="M699.62,1113.02h0c-20.06,44.48-33.32,92.75-38.4,143.37l424.51-90.24c20.06-44.47,33.31-92.75,38.4-143.37l-424.51,90.24Z"/><path class="cls-1" d="M1085.73,895.8c20.06-44.47,33.32-92.75,38.4-143.37l-330.68,70.33v-135.2l292.27-62.11c20.06-44.47,33.32-92.75,38.4-143.37l-330.68,70.27V66.13c-50.67,28.45-95.67,66.32-132.25,110.99v403.35l-132.25,28.11V0c-50.67,28.44-95.67,66.32-132.25,110.99v525.69l-295.91,62.88c-20.06,44.47-33.33,92.75-38.42,143.37l334.33-71.05v170.26l-358.3,76.14c-20.06,44.47-33.32,92.75-38.4,143.37l375.04-79.7c30.53-6.35,56.77-24.4,73.83-49.24l68.78-101.97v-.02c7.14-10.55,11.3-23.27,11.3-36.97v-149.98l132.25-28.11v270.4l424.53-90.28Z"/></svg>
</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 w-100" style="text-align: center;">
<strong>
<field name="name" />
</strong>
</div>
<div class="d-flex w-100 justify-content-between">
<!-- <ul>
<li>
<strong> Amount: <field name="lst_price"
widget="monetary"
options="{'currency_field': 'currency_id'}" />
</strong>
</li> -->
<!-- <field name="currency_id" invisible="1"/> -->
<!-- <div> -->
<!-- <span>On Hand:</span> -->
<!-- <field name="qty_available"/> -->
<!-- <field name="uom_id" class="ms-1" -->
<!-- groups="uom.group_uom"/> -->
<!-- </div> -->
<!-- </ul> -->
</div>
<div class="d-flex w-100 justify-content-center align-items-center mt-4">
<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>
<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" style="min-width: 40px;text-align: center;">
<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>
</div>
</div>
</t>
</templates>
</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>
<field name="model">product.template</field>
<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" />
</header>
<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="arch" type="xml">
<field name="uom_id" position="before">
<field name="payment_method_id" options="{'no_create': True}" />
</field>
</field>
</record>
</odoo>

View File

@ -0,0 +1,100 @@
<odoo>
<!-- Tree View -->
<record id="view_replacement_process_tree" model="ir.ui.view">
<field name="name">replacement.process.tree</field>
<field name="model">replacement.process</field>
<field name="arch" type="xml">
<tree string="Replacement Process" create="false" edit="true">
<field name="code"/>
<field name="sponsorship_id"/>
<field name="sponsor_id"/>
<field name="branch_id"/>
<field name="record_type"/>
<field name="sponsor_donor_type"/>
<field name="replacement_reason_id"/>
<field name="state"/>
</tree>
</field>
</record>
<!-- Form View -->
<record id="view_replacement_process_form" model="ir.ui.view">
<field name="name">replacement.process.form</field>
<field name="model">replacement.process</field>
<field name="arch" type="xml">
<form string="Replacement Process" create="false" edit="true">
<header>
<button name="confirm_replacement" type="object" string="Confirm Replacement"
class="btn-primary" attrs="{'invisible': [('replaced', '=', True)]}" groups="odex_takaful.group_orphan_replacement"/>
<field name="state" widget="statusbar" statusbar_visible="draft,replaced"/>
</header>
<sheet>
<group>
<group>
<field name="code" readonly="1"/>
<field name="branch_id" readonly="1"/>
<field name="registered_type" readonly="1"/>
<field name="record_type"/>
<field name="replaced" invisible="1"/>
<field name="family_ids" invisible="1"/>
</group>
<group>
<field name="sponsorship_id" readonly="1"/>
<field name="user_id" readonly="1"/>
<field name="sponsor_donor_type" readonly="1"/>
<field name="sponsor_id" readonly="1"/>
<field name="replacement_reason_id" readonly="1"/>
</group>
<group>
<field name="replacement_line_ids" attrs="{'readonly': [('replaced','=',True)]}">
<tree editable="bottom">
<field name="members_domain_ids" invisible="1"/>
<field name="sponsorship_type" readonly="1"/>
<field name="from_benefit_id" readonly="1"/>
<field name="to_benefit_id" attrs="{'readonly': [('sponsorship_type','!=','person')]}"/>
<field name="from_benefit_ids" readonly="1" widget="many2many_tags"/>
<field name="to_benefit_ids" widget="many2many_tags" attrs="{'readonly': [('sponsorship_type','!=','group')]}"/>
<field name="process_id" invisible="1"/>
</tree>
</field>
</group>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- Action -->
<record id="action_replacement_process" model="ir.actions.act_window">
<field name="name">Replacement Processes</field>
<field name="res_model">replacement.process</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create your first Replacement Process
</p>
</field>
</record>
<!-- Menu Item -->
<menuitem id="menu_replacement_root" name="Kafala Processes" sequence="11"
parent="odex_takaful.takaful_kufula_app_top_menu" groups="odex_takaful.group_orphan_replacement"/>
<!-- <menuitem id="menu_replacement_process"-->
<!-- name="Orphan Replacement"-->
<!-- parent="menu_replacement_root"-->
<!-- action="action_replacement_process"-->
<!-- sequence="1"/>-->
</odoo>

View File

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<odoo>
<!-- Tree View -->
<record id="view_replacement_reasons_tree" model="ir.ui.view">
<field name="name">replacement.reasons.tree</field>
<field name="model">replacement.reasons</field>
<field name="arch" type="xml">
<tree string="Replacement Reasons">
<field name="name"/>
</tree>
</field>
</record>
<!-- Form View -->
<record id="view_replacement_reasons_form" model="ir.ui.view">
<field name="name">replacement.reasons.form</field>
<field name="model">replacement.reasons</field>
<field name="arch" type="xml">
<form string="Replacement Reasons">
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Action -->
<record id="action_replacement_reasons" model="ir.actions.act_window">
<field name="name">Replacement Reasons</field>
<field name="res_model">replacement.reasons</field>
<field name="view_mode">tree,form</field>
</record>
<!-- Menu -->
<menuitem id="menu_replacement_reasons" name="Replacement Reasons" parent="odex_takaful.takaful_app_top_menu" action="action_replacement_reasons" groups="odex_takaful.group_orphan_replacement"/>
</odoo>

View File

@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<report
id ="makfuleen_report_pdf_act"
model ="report.odex_takaful.makfuleen_report_pdf"
string ="Makfuleen Report"
report_type ="qweb-pdf"
name ="odex_takaful.makfuleen_report_pdf"
file ="odex_takaful.makfuleen_report_pdf"
menu="False" />
<!-- paperformat="odex_takaful.takaful_report_paperformat_id" -->
<report
id ="kafalat_payment_report_pdf_act"
model ="report.odex_takaful.kafalat_payment_report_pdf"
string ="Kafalat Payment Report"
report_type ="qweb-pdf"
name ="odex_takaful.kafalat_payment_report_pdf"
file ="odex_takaful.kafalat_payment_report_pdf"
menu="False" />
<report
id ="kafalat_cancel_report_pdf_act"
model ="report.odex_takaful.kafalat_cancel_report_pdf"
string ="Canceled Kafalat Report"
report_type ="qweb-pdf"
name ="odex_takaful.kafalat_cancel_report_pdf"
file ="odex_takaful.kafalat_cancel_report_pdf"
menu="False" />
</data>
</odoo>

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="UTF-8" ?>
<odoo>
<data>
<!-- Create PaperFormat -->
<record id="takaful_report_paperformat_id" model="report.paperformat">
<field name="name">Takaful Paper Format</field>
<field name="default" eval="True" />
<field name="format">A4</field>
<field name="page_height">0</field>
<field name="page_width">0</field>
<field name="orientation">Portrait</field>
<field name="margin_top">50</field>
<field name="margin_bottom">40</field>
<field name="margin_left">7</field>
<field name="margin_right">7</field>
<field name="header_line" eval="False" />
<field name="header_spacing">50</field>
<field name="dpi">110</field>
</record>
<!-- set paper format to any report action -->
<!-- <record id="odex_takaful.action_report_beneficiary_sponsorships_number" model="ir.actions.report.xml">
<field name="paperformat_id" ref="odex_takaful.takaful_report_paperformat_id" />
</record> -->
</data>
</odoo>

View File

@ -0,0 +1,307 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Makfuleen Report -->
<template id="makfuleen_report_pdf">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<div class="text-center">
<h2><span> Sponsor Name: </span><span t-esc='name'/></h2>
<h2>Makfuleen Report</h2>
</div>
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">#</th>
<th style="text-align:center;">Sponsorship</th>
<th style="text-align:center;">Start Date</th>
<th style="text-align:center;">End Date</th>
<th style="text-align:center;">Sponsorship Type</th>
<th style="text-align:center;">Sponsorship Value</th>
<th style="text-align:center;">Sponsorship State</th>
<th style="text-align:center;">Makfool Name/Makfuleen Names</th>
<th style="text-align:center;">Total Payment</th>
</tr>
</thead>
<tbody class="text-center">
<t t-set="sequence" t-value="0"/>
<t t-foreach="docs" t-as="o">
<tr>
<td>
<t t-set="sequence" t-value="sequence +1"/>
<t t-esc="sequence"/>
</td>
<td class="text-center">
<span t-esc="o.code"/>
</td>
<td class="text-center">
<span t-esc="o.start_date"/>
</td>
<td class="text-center">
<span t-esc="o.end_date"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['sponsorship_type'])['sponsorship_type']['selection'])[o.sponsorship_type]"/>
</span>
</td>
<td class="text-center">
<span t-esc="o.contribution_value"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['state'])['state']['selection'])[o.state]"/>
</span>
</td>
<td class="text-center">
<t t-if="o.sponsorship_type == 'person'">
<span t-esc="o.benefit_id.name"/>
</t>
<t t-if="o.sponsorship_type == 'group'">
<p t-foreach="o.benefit_ids" t-as="ben">
<p><span t-esc="ben.name"/></p>
</p>
</t>
</td>
<td class="text-center">
<span t-esc="o.total_contribution"/>
</td>
</tr>
</t>
</tbody>
</table>
<div style="page-break-before: always;"></div>
</div>
</t>
</t>
</template>
<!-- Kafalat Payments and Delays report -->
<template id="kafalat_payment_report_pdf">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<div class="text-center">
<h2><span> Sponsor Name: </span><span t-esc='name'/></h2>
<h2>Kafalat Overdue Report</h2>
</div>
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">Kafalat Overdue Count</th>
<th style="text-align:center;">Total Overdues</th>
</tr>
</thead>
<tbody class="text-center">
<t>
<tr>
<td class="text-center">
<span t-esc='overdue_count'/>
</td>
<td class="text-center">
<span t-esc='overdue_amount' t-options='{"widget": "float", "precision": 2}' />
</td>
</tr>
</t>
</tbody>
</table>
<br/>
<br/>
<!-- Overdue details -->
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">#</th>
<th style="text-align:center;">Sponsorship</th>
<th style="text-align:center;">Contribution Value</th>
<th style="text-align:center;">Sponsorship Duration</th>
<th style="text-align:center;">Sponsorship Type</th>
<th style="text-align:center;">Benefit Type</th>
<th style="text-align:center;">Start Date</th>
<th style="text-align:center;">End Date</th>
<th style="text-align:center;">Overdue Amount</th>
<th style="text-align:center;">Expected Cancel Date</th>
<th style="text-align:center;">Status</th>
</tr>
</thead>
<tbody class="text-center">
<t t-set="sequence" t-value="0"/>
<t t-foreach="docs" t-as="o">
<tr>
<td>
<t t-set="sequence" t-value="sequence +1"/>
<t t-esc="sequence"/>
</td>
<td class="text-center">
<span t-esc="o.code"/>
</td>
<td class="text-center">
<span t-esc="o.contribution_value" t-options='{"widget": "float", "precision": 2}' />
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['sponsorship_duration'])['sponsorship_duration']['selection'])[o.sponsorship_duration]"/>
</span>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['sponsorship_type'])['sponsorship_type']['selection'])[o.sponsorship_type]"/>
</span>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['benefit_type'])['benefit_type']['selection'])[o.benefit_type]"/>
</span>
</td>
<td class="text-center">
<span t-esc="o.start_date"/>
</td>
<td class="text-center">
<span t-esc="o.end_date"/>
</td>
<td class="text-center">
<span t-esc="o.overdue_amount"/>
</td>
<td class="text-center">
<span t-esc="o.expected_cancel_date"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['state'])['state']['selection'])[o.state]"/>
</span>
</td>
</tr>
</t>
</tbody>
</table>
<div style="page-break-before: always;"></div>
</div>
</t>
</t>
</template>
<!-- Canceled Kafalat Report -->
<template id="kafalat_cancel_report_pdf">
<t t-call="web.html_container">
<t t-call="web.external_layout">
<div class="page">
<div class="text-center">
<h2>Canceled Kafalat Report </h2>
</div>
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">Canceled Kafalat Count</th>
<th style="text-align:center;">From Date</th>
<th style="text-align:center;">To Date</th>
</tr>
</thead>
<tbody class="text-center">
<t>
<tr>
<td class="text-center">
<span t-esc='cancel_count'/>
</td>
<td class="text-center">
<span t-esc='start_date'/>
</td>
<td class="text-center">
<span t-esc='end_date'/>
</td>
</tr>
</t>
</tbody>
</table>
<br/>
<br/>
<!-- Cancel details -->
<table class="table table-condensed table-bordered">
<thead class="text-center">
<tr style="background-color: #b8bcbf;width:100%;">
<th style="text-align:center;">#</th>
<th style="text-align:center;">Sponsorship</th>
<th style="text-align:center;">The Sponsor</th>
<th style="text-align:center;">Cancel Date</th>
<th style="text-align:center;">Cancel Type</th>
<th style="text-align:center;">Cancel Reason</th>
<th style="text-align:center;">Notes</th>
</tr>
</thead>
<tbody class="text-center">
<t t-set="sequence" t-value="0"/>
<t t-foreach="docs" t-as="o">
<tr>
<td>
<t t-set="sequence" t-value="sequence +1"/>
<t t-esc="sequence"/>
</td>
<td class="text-center">
<span t-esc="o.code"/>
</td>
<td class="text-center">
<span t-esc="o.sponsor_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.confirm_date"/>
</td>
<td class="text-center">
<span>
<t t-esc="dict(o.fields_get(allfields=['cancel_type'])['cancel_type']['selection'])[o.cancel_type]"/>
</span>
</td>
<td class="text-center">
<span t-esc="o.reason_id.name"/>
</td>
<td class="text-center">
<span t-esc="o.note"/>
</td>
</tr>
</t>
</tbody>
</table>
<div style="page-break-before: always;"></div>
</div>
</t>
</t>
</template>
</odoo>

View File

@ -0,0 +1,136 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- This added for Takaful settings -->
<odoo>
<record id="takaful_settings_view2" model="ir.ui.view">
<field name="name">takaful.res.config.settings.view.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
<field name="arch" type="xml">
<xpath expr="//div[@data-key='odex_takaful_base']">
<h2>Sponsorship Restriction Period</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<div class="content-group mt16">
<label for="restriction_period"/>
<field name="restriction_period" class="text-center oe_inline"
style="margin-right:50px;"/>
<span class="text-muted">Day</span>
</div>
</div>
</div>
</div>
<h2>Faal Kheer Partner</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="faal_kheer_partner_id"/>
<div class="content-group">
<div class="mt16">
<field name="faal_kheer_partner_id" class="o_light_label"/>
</div>
</div>
</div>
</div>
</div>
<h2>Whatsapp API Integration</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="twilio_account_sid"/>
<div class="content-group">
<div class="mt16">
<field name="twilio_account_sid" class="o_light_label"/>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="twilio_auth_token"/>
<div class="content-group">
<div class="mt16">
<field name="twilio_auth_token" class="o_light_label" password="True"/>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="twilio_from_whatsapp"/>
<div class="content-group">
<div class="mt16">
<field name="twilio_from_whatsapp" class="o_light_label"/>
</div>
</div>
</div>
</div>
</div>
<h2>Refund Cancel Time</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="cancel_refund"/>
<div class="content-group">
<div class="mt16">
<field name="cancel_refund" class="o_light_label"/>
<span class="text-muted">Hours</span>
</div>
</div>
</div>
</div>
</div>
<h2>SMS Templates</h2>
<div class="row mt16 o_settings_container">
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="donation_extension_reminder_sms_template_id"/>
<div class="content-group">
<div class="mt16">
<field name="donation_extension_reminder_sms_template_id" class="o_light_label"/>
</div>
</div>
</div>
</div>
<div class="col-xs-12 col-md-6 o_setting_box">
<div class="o_setting_right_pane">
<label for="donation_ended_sms_template_id"/>
<div class="content-group">
<div class="mt16">
<field name="donation_ended_sms_template_id" class="o_light_label"/>
</div>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
<!-- <record id="odex_takaful_takaful_settings_view2" model="ir.ui.view">-->
<!-- <field name="name">odex.takaful.takaful.res.config.settings.view.form</field>-->
<!-- <field name="model">res.config.settings</field>-->
<!-- <field name="inherit_id" ref="odex_takaful_base.takaful_settings_view2"/>-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="//div[hasclass('col-md-12')][1]" position="inside">-->
<!-- <div class="content-group mt16">-->
<!-- <label for="restriction_period"/>-->
<!-- <field name="restriction_period" class="text-center oe_inline" style="margin-right:50px;"/>-->
<!-- <span class="text-muted">Day</span>-->
<!-- </div>-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
</odoo>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="res_partner_bank_view_form_quick_create" model="ir.ui.view">
<field name="name">res.partner.bank.view.form.quick.create</field>
<field name="model">res.partner.bank</field>
<field name="arch" type="xml">
<form string="">
<sheet>
<group>
<group>
<field name="acc_number"/>
<field name="acc_holder_name"/>
</group>
<group>
<field name="bank_id"/>
<field name="partner_id" readonly="1"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
</odoo>

View File

@ -0,0 +1,21 @@
<odoo>
<record id="res_users_inherit_EXP" model="ir.ui.view">
<field name="name">res_users_inherit_EXP</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="branch.view_users_form_inherit_branch"/>
<field name="arch" type="xml">
<xpath expr="//group[2]" position="after">
<!-- Add your fields or attributes here -->
<group>
<field name="branch_custom_id"/>
</group>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,94 @@
<odoo>
<data>
<record id="sponsorship_close_reason_tree" model="ir.ui.view">
<field name="name">Sponsorship Reason Tree</field>
<field name="model">sponsorship.reason.stop</field>
<field name="arch" type="xml">
<tree editable="bottom">
<field name="sequence" widget="handle"/>
<field name="name" colspan="3"/>
</tree>
</field>
</record>
<record id="action_config_sponsorship_stop" model="ir.actions.act_window">
<field name="name">Sponsorship Reason</field>
<field name="res_model">sponsorship.reason.stop</field>
<field name="view_mode">tree</field>
</record>
<record model="ir.ui.view" id="sponsorship_cancellation_form">
<field name="name">sponsorship.cancellation.form</field>
<field name="model">sponsorship.cancellation</field>
<field name="arch" type="xml">
<form string="Sponsorship Cancellation" delete="false">
<header>
<button name="do_cancel_action" type="object" string="Cancel" class="oe_highlight" attrs="{'invisible': [('state', '=', 'cancel')]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group>
<field name="sponsorship_id" invisible="1"/>
<field name="code" readonly="1"/>
<field name="sponsor_id" readonly="1"/>
<field name="reason_id" required="1"/>
<field name="create_date" readonly="1"/>
<field name="cancel_type"/>
<field name="note"/>
<field name="cancel_user_id"/>
<field name="confirm_user_id" attrs="{'invisible': [('state', '!=', 'cancel')]}"/>
<field name="confirm_date" attrs="{'invisible': [('state', '!=', 'cancel')]}"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="sponsorship_cancellation_tree">
<field name="name">sponsorship.cancellation.tree</field>
<field name="model">sponsorship.cancellation</field>
<field name="arch" type="xml">
<tree string="Sponsorships Cancellations List" decoration-warning="state=='draft'" decoration-danger="state=='cancel'">
<field name="sponsor_id"/>
<field name="code"/>
<field name="reason_id"/>
<field name="cancel_type"/>
<field name="note"/>
<field name="state"/>
<field name="confirm_date"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="sponsorship_cancellation_search">
<field name="name">sponsorship.cancellation.search</field>
<field name="model">sponsorship.cancellation</field>
<field name="arch" type="xml">
<search>
<field name="sponsor_id"/>
<field name="code"/>
<field name="reason_id"/>
<field name="cancel_type"/>
<field name="state"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="sponsorship_cancellation_action">
<field name="name">Sponsorship Cancellation</field>
<field name="res_model">sponsorship.cancellation</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the Sponsorship Cancellation
</p>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,101 @@
<odoo>
<data>
<record model="ir.ui.view" id="takaful_sponsorship_payment_form">
<field name="name">sponsorship.payment.form</field>
<field name="model">sponsorship.payment</field>
<field name="arch" type="xml">
<form string="Sponsorship Payment" delete="false">
<header>
<button name="action_pay" class="oe_highlight" type="object" string="Send to Finance" attrs="{'invisible': ['|', ('state', 'in', ('financial', 'paid')), ('id', '=', False)]}"/>
<button name="open_account_invoice_action" string="Financial" type="object" class="oe_highlight" attrs="{'invisible': [('state', '=', 'draft')]}"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<group name="group_top">
<group name="group_left">
<field name="code" readonly="1"/>
<field name="sponsor_id" force_save="1" attrs="{'readonly': [('id', '>', 0)]}"/>
<field name="sponsorship_id" force_save="1" attrs="{'readonly': [('id', '>', 0)]}"/>
<label for="payment_month_number" />
<div>
<field name="payment_month_number" required="1" class="oe_inline" style="margin-right:50px; margin-bottom:20px;"/>
<span class="oe_inline text-muted"> Months</span>
</div>
<field name="payment_method" style="margin-bottom:20px;"/>
<field name="has_bank_account" attrs="{'invisible': [('payment_method', '=', 'cash')]}" style="margin-bottom:10px;"/>
<field name="currency_id" invisible="1"/>
<field name="month_amount" widget="monetary"
options="{'currency_field': 'currency_id'}" force_save="1"/>
<field name="amount" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1"/>
</group>
<group name="group_right" attrs="{'invisible': [('payment_method', '=', 'cash')]}">
<field name="bank_id"/>
<field name="iban"/>
<field name="transfer_receipt"/>
</group>
</group>
<group>
<field name="user_id" attrs="{'invisible': [('state', '=', 'draft')]}"/>
<field name="date" attrs="{'invisible': [('state', '=', 'draft')]}"/>
<field name="is_invoiced" invisible="1"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="takaful_sponsorship_payment_tree">
<field name="name">sponsorship.payment.tree</field>
<field name="model">sponsorship.payment</field>
<field name="arch" type="xml">
<tree string="Payments List" decoration-danger="state=='financial'" decoration-success="state=='paid'">
<field name="sponsor_id"/>
<field name="code"/>
<field name="amount" sum="Total Payments" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="date" widget="date"/>
<field name="state"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="takaful_sponsorship_payment_search">
<field name="name">sponsorship.payment.search</field>
<field name="model">sponsorship.payment</field>
<field name="arch" type="xml">
<search>
<field name="sponsor_id"/>
<field name="code"/>
<field name="date"/>
<field name="state"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="takaful_sponsorship_payment_action">
<field name="name">Sponsorship Payment</field>
<field name="res_model">sponsorship.payment</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the Sponsorship Payment
</p>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,87 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Tree View for Sponsorship Scheduling Line -->
<record id="view_sponsorship_scheduling_line_tree" model="ir.ui.view">
<field name="name">sponsorship.scheduling.line.tree</field>
<field name="model">sponsorship.scheduling.line</field>
<field name="arch" type="xml">
<tree string="Sponsorship Scheduling Lines" decoration-success="status == 'paid'"
decoration-info="status == 'unpaid'" decoration-danger="status == 'fully_refund'"
decoration-warning="status in ('approve_refund', 'under_refund', 'partial_refund')">
<field name="sequence_no"/>
<field name="sponsorship_id"/>
<field name="sponsorship_state"/>
<field name="donation_detail_linked_id"/>
<field name="beneficiary_id"/>
<field name="month_year"/>
<field name="scheduled_date"/>
<field name="amount" sum="Total Amount"/>
<field name="refunded_amount" sum="Total Refunded"/>
<field name="direct_debit"/>
<field name="status"/>
<button name="action_register_payment"
string="Register Payment"
type="object"
class="btn-primary"
attrs="{'invisible': ['|', ('status', '!=', 'unpaid'), ('direct_debit', '=', True)]}" />
</tree>
</field>
</record>
<!-- Search View for Sponsorship Scheduling Line -->
<record id="view_sponsorship_scheduling_line_search" model="ir.ui.view">
<field name="name">sponsorship.scheduling.line.search</field>
<field name="model">sponsorship.scheduling.line</field>
<field name="arch" type="xml">
<search string="Search Sponsorship Scheduling Lines">
<field name="sequence_no"/>
<field name="sponsorship_id"/>
<field name="beneficiary_id"/>
<field name="month_year"/>
<field name="scheduled_date"/>
<field name="donation_detail_linked_id"/>
<separator/>
<filter string="Scheduled Today" name="scheduled_today" domain="[('scheduled_date', '=', context_today().strftime('%Y-%m-%d'))]"/>
<filter string="Scheduled This Week" name="scheduled_this_week" domain="[('scheduled_date', '&gt;=', (context_today() - datetime.timedelta(days=context_today().weekday())).strftime('%Y-%m-%d')), ('scheduled_date', '&lt;=', (context_today() + datetime.timedelta(days=6-context_today().weekday())).strftime('%Y-%m-%d'))]"/>
<separator/>
<filter string="Unpaid" name="unpaid" domain="[('status', '=', 'unpaid')]"/>
<filter string="Paid" name="paid" domain="[('status', '=', 'paid')]"/>
<filter string="Approve Refund" name="approve_refund" domain="[('status', '=', 'approve_refund')]"/>
<filter string="Under Refund" name="under_refund" domain="[('status', '=', 'under_refund')]"/>
<filter string="Partial Refund" name="partial_refund" domain="[('status', '=', 'partial_refund')]"/>
<filter string="Fully Refund" name="fully_refund" domain="[('status', '=', 'fully_refund')]"/>
<separator/>
<filter string="Direct Debit" name="direct_debit" domain="[('direct_debit', '=', True)]"/>
<separator/>
<group expand="0" string="Group By">
<filter string="Sponsorship" name="group_sponsorship" context="{'group_by': 'sponsorship_id'}"/>
<filter string="Beneficiary" name="group_beneficiary" context="{'group_by': 'beneficiary_id'}"/>
<filter string="Status" name="group_status" context="{'group_by': 'status'}"/>
<filter string="Direct Debit" name="group_direct_debit" context="{'group_by': 'direct_debit'}"/>
<filter string="Month/Year" name="group_month_year" context="{'group_by': 'month_year'}"/>
<filter string="Scheduled Date" name="group_scheduled_date" context="{'group_by': 'scheduled_date'}"/>
<filter string="Sponsorship State" name="group_sponsorship_state" context="{'group_by': 'sponsorship_state'}"/>
</group>
</search>
</field>
</record>
<!-- Action for Sponsorship Scheduling Line -->
<record id="action_sponsorship_scheduling_line" model="ir.actions.act_window">
<field name="name">Sponsorship Scheduling Lines</field>
<field name="res_model">sponsorship.scheduling.line</field>
<field name="view_mode">tree</field>
<field name="search_view_id" ref="view_sponsorship_scheduling_line_search"/>
<field name="context">{'create': False}</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a new Sponsorship Scheduling Line
</p>
<p>
Track and manage sponsorship payment schedules for beneficiaries.
</p>
</field>
</record>
</odoo>

View File

@ -0,0 +1,39 @@
<odoo>
<record model="ir.ui.view" id="sponsorship_states_form">
<field name="name">sponsorship.states.form</field>
<field name="model">sponsorship.states</field>
<field name="arch" type="xml">
<form string="Sponsorship States">
<sheet>
<group>
<field name="name"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="sponsorship_states_tree" model="ir.ui.view">
<field name="name">sponsorship.states.tree</field>
<field name="model">sponsorship.states</field>
<field name="arch" type="xml">
<tree string="Sponsorship States">
<field name="name"/>
</tree>
</field>
</record>
<record id="sponsorship_states_action" model="ir.actions.act_window">
<field name="name">Sponsorship States</field>
<field name="res_model">sponsorship.states</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a Sponsorship States
</p>
</field>
</record>
<menuitem id="menu_sponsorship_states_items" name="Sponsorship States"
parent="sponsor_setting_menu"
action="sponsorship_states_action"/>
</odoo>

View File

@ -0,0 +1,103 @@
<odoo>
<data>
<record model="ir.ui.view" id="donations_items_form">
<field name="name">donations.items.form</field>
<field name="model">donations.items</field>
<field name="arch" type="xml">
<form string="Donations Items">
<sheet>
<group>
<group>
<field name="name" required="1"/>
<field name="donation_type" required="1"/>
<field name="fixed_value"/>
<field name="currency_id" invisible="1"/>
<field name="fixed_donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'invisible': [('fixed_value', '=', False)],'required': [('fixed_value', '=', True)]}"/>
</group>
<group>
<field name="branch_custom_id" required="1"/>
<field name="show_donation_item"/>
<field name="account_id" required="1"/>
<field name="product_id" readonly="1" groups="odex_takaful.group_show_donation_item_product"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="donations_items_tree" model="ir.ui.view">
<field name="name">donations.items.tree</field>
<field name="model">donations.items</field>
<field name="arch" type="xml">
<tree string="Donations Items">
<field name="name"/>
<field name="donation_type"/>
<field name="branch_custom_id"/>
<field name="show_donation_item"/>
</tree>
</field>
</record>
<record id="donations_items_action" model="ir.actions.act_window">
<field name="name">Donations Items</field>
<field name="res_model">donations.items</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a Donation Item
</p>
</field>
</record>
<!-- Points Of sale custom -->
<record model="ir.ui.view" id="points_of_sale_custom_form">
<field name="name">points.of.sale.custom.form</field>
<field name="model">points.of.sale.custom</field>
<field name="arch" type="xml">
<form string="Points of sale custom">
<sheet>
<group>
<group>
<field name="name"/>
<field name="department_name"/>
<field name="branch_custom_ids" widget="many2many_tags"/>
<field name="journal_id"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="points_of_sale_custom_tree" model="ir.ui.view">
<field name="name">points.of.sale.custom.tree</field>
<field name="model">points.of.sale.custom</field>
<field name="arch" type="xml">
<tree string="Points of sale custom">
<field name="name"/>
<field name="department_name"/>
<field name="branch_custom_ids" widget="many2many_tags"/>
<field name="department_name"/>
<field name="journal_id"/>
</tree>
</field>
</record>
<record id="points_of_sale_custom_action" model="ir.actions.act_window">
<field name="name">Points Of Sale Custom</field>
<field name="res_model">points.of.sale.custom</field>
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="o_view_nocontent_smiling_face">
Create a points of sale
</p>
</field>
</record>
<menuitem id="menu_donations_items" name="Donations Items"
parent="sponsor_setting_menu"
action="donations_items_action" />
<menuitem id="menu_points_of_sale_custom" name="Points of Sale"
parent="sponsor_setting_menu"
action="points_of_sale_custom_action" />
</data>
</odoo>

View File

@ -0,0 +1,89 @@
<odoo>
<data noupdate="0">
<record id="financial_gift" model="product.product">
<field name="name">هدية مالية</field>
<field name="type">service</field>
<!-- <field name="standard_price">0</field> -->
<field name="list_price">300.0</field>
<field name="default_code">financial_gift</field>
</record>
</data>
<data>
<!-- Form View -->
<record model="ir.ui.view" id="takaful_contribution_form">
<field name="name">takaful.contribution.form</field>
<field name="model">takaful.contribution</field>
<field name="arch" type="xml">
<form string="The Financial Contribution" duplicate="false">
<header>
<!-- <button name="action_confirm_gift" type="object"-->
<!-- string="Confirm Gift" class="oe_highlight"-->
<!-- attrs="{'invisible': [('operation_type','!=','gift'),('is_confirmed','=', False)]}"/>-->
</header>
<sheet>
<group>
<field name="is_confirmed" invisible='1'/>
<field name="name"/>
<field name="sponsor_id"/>
<field name="benefit_id" attrs="{'invisible': [('benefit_ids','=', False)]}"/>
<field name="benefit_ids" attrs="{'invisible': [('benefit_id','!=', False)]}"/>
<field name="operation_type"/>
<field name="currency_id" invisible="1"/>
<field name="amount" widget="monetary"
options="{'currency_field': 'currency_id'}"/>
<field name="note"/>
<field name="date"/>
<field name="entry_id" invisible='1'/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Tree View -->
<record model="ir.ui.view" id="takaful_contribution_tree">
<field name="name">takaful.contribution.tree</field>
<field name="model">takaful.contribution</field>
<field name="arch" type="xml">
<tree string="Financial Contributions List" duplicate="false">
<field name="name"/>
<field name="sponsor_id"/>
<field name="operation_type"/>
<field name="amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="date" widget="datetime"/>
</tree>
</field>
</record>
<!-- Search View -->
<record model="ir.ui.view" id="takaful_contribution_search">
<field name="name">takaful.contribution.search</field>
<field name="model">takaful.contribution</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="sponsor_id"/>
<field name="operation_type"/>
<field name="amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="date" widget="datetime"/>
</search>
</field>
</record>
<!-- Windows Action -->
<record model="ir.actions.act_window" id="takaful_financial_contribution_action">
<field name="name">Financial Contributions</field>
<field name="res_model">takaful.contribution</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">No Any Financial Contribution!
</p>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,238 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- <record id="benefit_invoice_form_inherit_view" model="ir.ui.view">-->
<!-- <field name="name">benefit.invoice.form.inherit.view</field>-->
<!-- <field name="model">account.move</field>-->
<!-- <field name="inherit_id" ref="account.view_move_form" />-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="/form/sheet/notebook/page[2]/field[@name='line_ids']" position="after">-->
<!-- <field name="benefit_invoice_ids" />-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
<!-- <record id="takaful_grant_benefit_form" model="ir.ui.view">-->
<!-- <field name="name">takaful.grant.benefit.form</field>-->
<!-- <field name="model">grant.benefit</field>-->
<!-- <field name="inherit_id" ref="odex_benefit.grant_benefit_form" />-->
<!-- <field name="arch" type="xml">-->
<!-- <xpath expr="/form/sheet/notebook/page[9]" position="before">-->
<!-- <page string="Sponsorships">-->
<!-- <group name="sponsorship_needs_info">-->
<!-- <field name="is_active_sponsorship" />-->
<!-- </group>-->
<!-- <group col="4">-->
<!-- <field name="benefit_needs_value" />-->
<!-- <field name="benefit_needs_percent" />-->
<!-- <field name="benefit_arrears_value" />-->
<!-- </group>-->
<!-- <group>-->
<!-- <field name="has_kafala_delay" />-->
<!-- <field name="overdue_kafalat_amount" />-->
<!-- <field name="sponsorship_ids" />-->
<!-- </group>-->
<!-- &lt;!&ndash; <page string="Sponsorships" name="sponsorships_info_page">&ndash;&gt;-->
<!-- &lt;!&ndash; <group>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="sponsorship_payment_ids">&ndash;&gt;-->
<!-- &lt;!&ndash; <tree editable="bottom">&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="benefit_id" invisible="1"/>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="partner_id"/>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="operation_code"/>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="due_date"/>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="amount"/>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="status"/>&ndash;&gt;-->
<!-- &lt;!&ndash; <field name="recieve_date"/>&ndash;&gt;-->
<!-- &lt;!&ndash; </tree>&ndash;&gt;-->
<!-- &lt;!&ndash; </field>&ndash;&gt;-->
<!-- &lt;!&ndash; </group>&ndash;&gt;-->
<!-- &lt;!&ndash; </page>&ndash;&gt;-->
<!-- </page>-->
<!-- </xpath>-->
<!-- </field>-->
<!-- </record>-->
<!-- New Added -->
<!-- Beneficiaries Invoice Form View -->
<record model="ir.ui.view" id="benefit_grant_due_invoice_form">
<field name="name">grant.benefit.invoice.form</field>
<field name="model">grant.benefit.invoice</field>
<field name="arch" type="xml">
<form string="Due Payment" create="false" edit="false" delete="false" duplicate="false">
<sheet>
<group>
<field name="operation_code" readonly="1" />
<field name="operation_type" readonly="1" />
<field name="partner_id" readonly="1" />
<field name="operation_invoice_id" readonly="1" />
<field name="due_date" />
<field name="journal_id" readonly="1" />
<field name="currency_id" invisible="1"/>
<field name="paid_amount" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1" />
<field name="payment_date" widget="date" readonly="1" />
<field name="benefit_target" readonly="1" />
<field name="note" readonly="1" />
<field name="is_recorded" readonly="1" />
<field name="due_code" />
<field name="benefit_ids" readonly="1">
<tree>
<field name="name" />
<field name="gender" />
<field name="city_id" />
<field name="phone" />
<field name="email" />
</tree>
</field>
</group>
</sheet>
</form>
</field>
</record>
<!-- Beneficiaries Invoice Tree View -->
<record model="ir.ui.view" id="benefit_grant_due_invoice_tree">
<field name="name">grant.benefit.invoice.tree</field>
<field name="model">grant.benefit.invoice</field>
<field name="arch" type="xml">
<tree string="Due Payments List" create="false" edit="false" delete="false"
duplicate="false"
decoration-danger="is_recorded==False">
<field name="operation_type" />
<field name="operation_code" />
<field name="benefit_type" />
<field name="benefit_target" />
<field name="benefit_ids" widget="many2many_tags" />
<field name="partner_id" />
<field name="due_date" widget="date"/>
<field name="payment_date" widget="date"/>
<field name="paid_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="is_recorded" />
</tree>
</field>
</record>
<!-- Beneficiaries Invoice Search View -->
<record model="ir.ui.view" id="benefit_grant_due_invoice_search">
<field name="name">grant.benefit.invoice.search</field>
<field name="model">grant.benefit.invoice</field>
<field name="arch" type="xml">
<search>
<field name="operation_type" />
<field name="operation_code" />
<field name="benefit_type" />
<field name="benefit_target" />
<field name="benefit_ids" />
<field name="partner_id" />
<field name="due_date" />
<field name="payment_date" />
<field name="is_recorded" />
</search>
</field>
</record>
<!-- Beneficiaries Invoice Window Action -->
<record model="ir.actions.act_window" id="benefit_grant_due_invoice_action">
<field name="name">Beneficiaries Due Payments</field>
<field name="res_model">grant.benefit.invoice</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">No Due Payments for Beneficiaries
</p>
</field>
</record>
<!-- Sponsorships Arrears for Benefits -->
<record model="ir.ui.view" id="sponsorship_benefit_arrears_form">
<field name="name">sponsorship.benefit.arrears.form</field>
<field name="model">sponsorship.benefit.arrears</field>
<field name="arch" type="xml">
<form string="Sponsorships Arrears" delete="false">
<sheet>
<group>
<field name="is_paid" invisible="1" />
<field name="sponsorship_id" invisible="1" />
<field name="code" readonly="1" />
<field name="sponsor_id" readonly="1" />
<field name="benefit_id" required="1" />
<field name="benefit_type" readonly="1" />
<field name="currency_id" invisible="1"/>
<field name="month_amount" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1" />
<field name="arrears_month_number" readonly="1" />
<field name="arrears_total" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1" />
<field name="date" widget="date" readonly="1" />
</group>
<group string="Payment Information">
<field name="arrears_amount" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1" />
<field name="paid_amount" widget="monetary"
options="{'currency_field': 'currency_id'}" readonly="1" />
<field name="invoice_ids" widget="one2many" />
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="sponsorship_benefit_arrears_tree">
<field name="name">sponsorship.benefit.arrears.tree</field>
<field name="model">sponsorship.benefit.arrears</field>
<field name="arch" type="xml">
<tree string="Sponsorships Arrears List" decoration-danger="is_paid==False"
decoration-success="is_paid==True">
<field name="is_paid" invisible="1" />
<field name="code" />
<field name="sponsor_id" />
<field name="benefit_id" />
<field name="benefit_type" />
<field name="date" widget="date"/>
<field name="arrears_month_number" />
<field name="arrears_total" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="arrears_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="paid_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="sponsorship_benefit_arrears_search">
<field name="name">sponsorship.benefit.arrears.search</field>
<field name="model">sponsorship.benefit.arrears</field>
<field name="arch" type="xml">
<search>
<field name="code" />
<field name="sponsor_id" />
<field name="benefit_id" />
<field name="benefit_type" />
<field name="date" widget="date"/>
<field name="arrears_month_number" />
<field name="arrears_total" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="arrears_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="paid_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="sponsorship_benefit_arrears_action">
<field name="name">Sponsorships Arrears</field>
<field name="res_model">sponsorship.benefit.arrears</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">No Any Sponsorships Arrears
</p>
</field>
</record>
</odoo>

View File

@ -0,0 +1,146 @@
<?xml version="1.0"?>
<odoo>
<menuitem id="takaful_kufula_app_top_menu" sequence="15" name="Kafalat System" web_icon="odex_takaful,static/description/icon.png" groups="odex_takaful.group_kufula_user"/>
<!-- Main Kafalat-->
<menuitem id="kafalat_main_menu" parent="takaful_kufula_app_top_menu"
sequence="10" name="Kafalat"/>
<menuitem id="takaful_sponsorship_app_menu" parent="kafalat_main_menu"
name="Sponsorships" action="takaful_sponsorship_action" sequence="1"/>
<menuitem id="donations_details_lines_app_menu" parent="kafalat_main_menu"
name="Donations Details Lines" action="donations_details_lines_action" sequence="2"/>
<menuitem id="donations_details_lines_to_replace_app_menu" parent="menu_replacement_root"
name="Donations Details Lines To Replace Benefit" action="donations_details_lines_replace_action" sequence="3"/>
<menuitem id="donations_details_lines_waiting_app_menu" parent="menu_replacement_root"
name="Donations Details Lines Waiting Benefit" action="donations_details_lines_waiting_action" sequence="4"/>
<!-- TODO WE WILL USE IT LATER DON'T REMOVE THIS -->
<!-- START OF THE BLOCK -->
<!-- <menuitem id="takaful_sponsorship_payment_menu" name="Sponsorship Payment"
parent="kafalat_main_menu" action="takaful_sponsorship_payment_action" sequence="2" />
<menuitem id="sponsorship_cancellation_menu" name="Sponsorship Cancellation"
parent="kafalat_main_menu" action="sponsorship_cancellation_action" sequence="3" />
<menuitem id="takaful_contribution_app_menu" name="The Financial Contributions"
parent="kafalat_main_menu" action="takaful_financial_contribution_action" sequence="4"/>
<menuitem id="takaful_push_notification_menu" name="Notifications Messages"
parent="kafalat_main_menu" action="takaful_push_notification_action" sequence="5" /> -->
<!-- END OF THE BLOCK -->
<!-- Main Kafileen-->
<menuitem id="kafileen_main_menu" parent="takaful_kufula_app_top_menu"
sequence="12" name="Kafileen"/>
<menuitem id="takaful_sponsor_menu" parent="kafileen_main_menu"
name="Sponsors Record" action="takaful_sponsor_action" sequence="1"/>
<!-- <menuitem id="takaful_sponsor_operation_menu" name="Operations Records" parent="kafileen_main_menu" action="takaful_sponsor_operation_action" sequence="2"/> -->
<!-- Main Online Payments
<menuitem id="account_takaful_core_online_paycard_menu" name="Online Payments"
parent="takaful_kufula_app_top_menu" sequence="15"/>
<menuitem sequence="1" id="account_takaful_core_account_move_menu" name="Online Invoices"
parent="account_takaful_core_online_paycard_menu" action="takaful_core.takaful_account_move_list_action"/>
<menuitem sequence="2" id="account_takaful_core_bank_transfer_menu" name="Bank Transfers" parent="account_takaful_core_online_paycard_menu" action="takaful_core.act_takaful_bank_transfer_view"/>
-->
<!-- Main Beneficiaries -->
<!-- TODO WE WILL USE IT LATER DON'T REMOVE THIS -->
<!-- START OF THE BLOCK -->
<!-- <menuitem id="takaful_benefit_operation_menu" name="Beneficiaries" parent="takaful_kufula_app_top_menu" sequence="20"/>
<menuitem id="benefit_grant_due_invoice_menu" name="Due Payments" parent="takaful_benefit_operation_menu" action="benefit_grant_due_invoice_action" sequence="1"/>
<menuitem id="benefit_month_payment_menu" name="Monthly Payments"
parent="takaful_benefit_operation_menu" action="benefit_month_payment_action" sequence="2"/>
<menuitem id="benefit_month_payment_line_menu" name="Beneficiaries Payments"
parent="takaful_benefit_operation_menu" action="benefit_month_payment_line_action" sequence="3"/>
<menuitem id="sponsorship_benefit_arrears_menu" name="Beneficiaries Arrears" parent="takaful_benefit_operation_menu" action="sponsorship_benefit_arrears_action" sequence="4"/> -->
<!-- END OF THE BLOCK -->
<!-- Main Reports -->
<menuitem id="sponsor_report_menu" parent="takaful_kufula_app_top_menu"
name="Reports" sequence="40" />
<menuitem id="active_sponsor_report_menu" parent="sponsor_report_menu" sequence="10" name="Active Sponsors Report" action="action_active_sponsor_report"/>
<menuitem id="makfuleen_report_menu" parent="sponsor_report_menu" sequence="15" name="Makfuleen Report" action="makfuleen_wizard_report_action"/>
<menuitem id="payment_overdue_report_menu" parent="sponsor_report_menu" sequence="20" name="Kafalat Overdue Report" action="kafalat_payment_wizard_report_action"/>
<menuitem id="canceled_kafalat_report_menu" parent="sponsor_report_menu" sequence="25" name="Canceled Kafalat Report" action="kafalat_cancel_wizard_report_action"/>
<menuitem id="benefit_payment_sponsorship_menu_report"
name="Benefits Payments"
parent="sponsor_report_menu"
action="sponsor_report_menu_action"
sequence="30"
/>
<menuitem id="benefit_month_payment_sponsorship_menu_report"
name="Benefits Month Payments"
parent="sponsor_report_menu"
action="benefit_month_report_action"
sequence="35"
/>
<!-- Main Settings -->
<menuitem id="sponsor_setting_menu" parent="takaful_kufula_app_top_menu"
name="Global Settings" sequence="99" groups="odex_takaful.sponsorship_system_manager_group"/>
<!-- <menuitem id="base_takaful_notification_menu"
name="Notifications"
parent="odex_takaful.sponsor_setting_menu"
action="odex_takaful_base.takaful_notification_action"
sequence="1"/> -->
<menuitem id="sponsorship_stop_reason_menu"
name="Reasons To Stop"
parent="odex_takaful.sponsor_setting_menu"
action="odex_takaful.action_config_sponsorship_stop"
sequence="2"/>
<menuitem id="takaful_message_template_menu"
name="Messages Templates"
parent="odex_takaful.sponsor_setting_menu"
action="odex_takaful.takaful_message_template_action"
sequence="3"/>
<!-- Begin Kufala Settings -->
<menuitem id="takaful_app_top_menu" parent="sponsor_setting_menu" sequence="99"
name="Kufala Settings" />
<menuitem id="message_type_menu" action="odex_takaful_base.takaful_message_type_action"
name="Message Types" sequence="5"
parent="takaful_app_top_menu"/>
<menuitem id="takaful_notification_menu" action="odex_takaful_base.takaful_notification_action"
name="Notifications" sequence="10"
parent="takaful_app_top_menu"/>
<record model="ir.ui.menu" id="takaful_app_top_menu">
<field name="groups_id" eval="[(6,0,[ref('odex_takaful.sponsorship_system_manager_group')])]"/>
</record>
<menuitem id="takaful_settings_menu" name="Kufala Global Settings"
parent="takaful_app_top_menu" action="odex_takaful_base.takaful_settings_action" sequence="99"/>
<!-- END Kufala Settings -->
</odoo>

View File

@ -0,0 +1,187 @@
<odoo>
<data>
<record model="ir.ui.view" id="benefit_month_payment_form">
<field name="name">month.payment.form</field>
<field name="model">month.payment</field>
<field name="arch" type="xml">
<form string="Month Payment">
<header>
<button name="action_create_lines" class="oe_highlight" type="object" string="Create Lines"
confirm="Are you sure you want to Create lines Manually?" states="draft"/>
<button name="action_approve" class="oe_highlight" type="object" string="Approve"
confirm="Are you sure you want to Approve?" states="create"/>
<button name="action_submit" class="oe_highlight" type="object" string="Submit To Pay"
confirm="Are you sure you want to Submit?" states="approve"/>
<button name="action_notify" class="oe_highlight" type="object" string="Pay Notify"
confirm="Are you sure you want to Send Pay Notify?" states="submit"/>
<button name="action_refuse" class="oe_highlight" type="object" string="Refuse"
confirm="Are you sure you want to Refuse?"
states="create"/>
<button name="action_cancel" type="object" string="Cancel"
states="create,refused"
confirm="Are you sure you want to Cancel?"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="open_payments"
type="object" class="oe_stat_button" icon="fa-users">
<field string=" Payments" name="count" widget="statinfo"/>
</button>
</div>
<div class="oe_title">
<h1>
<field placeholder="Name" name="name" class="oe_inline"
attrs="{'readonly':[('state','!=','draft')],'required':True}"/>
</h1>
<h2>
<field name="code"/>
</h2>
</div>
<group col="4" colspan="2">
<field name="date" widget="date" attrs="{'readonly':[('state','!=','draft')],'required':True}"/>
<field name="user_id" readonly="1" force_save="1"/>
<field name="entry_id" readonly="1" force_save="1"/>
<field name="currency_id" invisible="1"/>
<field name="amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly':[('state','!=','draft')],'required':True}"/>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers" groups="base.group_user"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record model="ir.ui.view" id="benefit_month_payment_tree">
<field name="name">month.payment.tree</field>
<field name="model">month.payment</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="code"/>
<field name="state"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="benefit_month_payment_search">
<field name="name">month.payment.search</field>
<field name="model">month.payment</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<field name="code"/>
<field name="state"/>
</search>
</field>
</record>
<!--line-->
<record model="ir.ui.view" id="benefit_month_payment_line_form">
<field name="name">month.payment.line.form</field>
<field name="model">month.payment.line</field>
<field name="arch" type="xml">
<!-- delete="false"-->
<form string="Month Payment" create="false" edit="false">
<sheet>
<div class="oe_title">
<h1>
<field placeholder="Name" name="benefit_id" class="oe_inline" force_save="1"
attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="benefit_type"/>
</h1>
<group col="4" colspan="2">
<field name="s_code"/>
<field name="sponsor_id"/>
<field name="responsible_id"/>
<field name="partner_id"/>
</group>
<group col="4" colspan="2">
<field name="code"/>
<field name="month_id" force_save="1" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="date" force_save="1" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="amount" force_save="1" attrs="{'readonly':[('state','!=','draft')]}"/>
<field name="state" invisible="1"/>
</group>
</div>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="benefit_month_payment_line_tree">
<field name="name">month.payment.line.tree</field>
<field name="model">month.payment.line</field>
<field name="arch" type="xml">
<tree create="false" edit="false" delete="false">
<field name="benefit_id"/>
<field name="benefit_type"/>
<field name="s_code"/>
<field name="sponsor_id"/>
<field name="month_id"/>
<field name="code"/>
<field name="date"/>
<field name="amount"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="benefit_month_payment_line_search">
<field name="name">month.payment.line.search</field>
<field name="model">month.payment.line</field>
<field name="arch" type="xml">
<search>
<field name="benefit_id"/>
<field name="benefit_type"/>
<field name="s_code"/>
<field name="sponsor_id"/>
<field name="month_id"/>
<field name="code"/>
<field name="date"/>
<field name="amount"/>
</search>
</field>
</record>
<!-- Window Actions -->
<record model="ir.actions.act_window" id="benefit_month_payment_action">
<field name="name">Month Payment</field>
<field name="res_model">month.payment</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create a Month Payment
</p>
</field>
</record>
<record model="ir.actions.act_window" id="benefit_month_payment_line_action">
<field name="name">Benefit Month Payment</field>
<field name="res_model">month.payment.line</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">Create the Month Payment Line
</p>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,46 @@
<odoo>
<!-- Inherit the original form view -->
<record id="inherit_takaful_sponsorship_notification_form" model="ir.ui.view">
<field name="name">takaful.notification.form.inherit</field>
<field name="model">takaful.notification</field>
<field name="inherit_id" ref="odex_takaful_base.takaful_notification_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='duration']" position="before">
<field name="name"/>
</xpath>
<xpath expr="//field[@name='notification_type']" position="after">
<field name="notification_state_ids" widget="many2many_tags" options="{'no_create': True}">
<tree>
<field name="display_name"/>
</tree>
</field>
</xpath>
<xpath expr="//page[@name='Types']" position="after">
<page string="Messages">
<group>
<field name="message"/>
</group>
</page>
</xpath>
</field>
</record>
<record id="inherit_takaful_sponsorship_notification_tree" model="ir.ui.view">
<field name="name">takaful.notification.tree.inherit</field>
<field name="model">takaful.notification</field>
<field name="inherit_id" ref="odex_takaful_base.takaful_notification_tree"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='duration']" position="before">
<field name="name"/>
<field name="notification_state_ids" widget="many2many_tags"/>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,41 @@
<odoo>
<record id="view_takaful_payment_method_form" model="ir.ui.view">
<field name="name">takaful.payment.method.form</field>
<field name="model">takaful.payment.method</field>
<field name="arch" type="xml">
<form string="Takaful Payment Method">
<sheet>
<group>
<field name="name"/>
<field name="payment_method"/>
<field name="journal_id"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="view_takaful_payment_method_tree" model="ir.ui.view">
<field name="name">takaful.payment.method.tree</field>
<field name="model">takaful.payment.method</field>
<field name="arch" type="xml">
<tree string="Takaful Payment Method">
<field name="name"/>
<field name="payment_method"/>
<field name="journal_id"/>
</tree>
</field>
</record>
<record id="action_takaful_payment_method" model="ir.actions.act_window">
<field name="name">Takaful Payment Method</field>
<field name="res_model">takaful.payment.method</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="menu_takaful_payment_method"
name="Takaful Payment Method"
parent="odex_takaful.sponsor_setting_menu"
action="action_takaful_payment_method"/>
</odoo>

View File

@ -0,0 +1,111 @@
<odoo>
<data>
<!-- Form View -->
<record model="ir.ui.view" id="takaful_push_notification_form">
<field name="name">takaful.push.notification.form</field>
<field name="model">takaful.push.notification</field>
<field name="arch" type="xml">
<form string="Notification Message" create="false" edit="false" delete="false" duplicate="false">
<sheet>
<group>
<field name="user_id" readonly="1"/>
<field name="email" readonly="1"/>
<field name="mobile" readonly="1"/>
<field name="title" readonly="1"/>
<field name="body" readonly="1"/>
<field name="sent_on" readonly="1"/>
<field name="is_read" readonly="1"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Tree View -->
<record model="ir.ui.view" id="takaful_push_notification_tree">
<field name="name">takaful.push.notification.tree</field>
<field name="model">takaful.push.notification</field>
<field name="arch" type="xml">
<tree string="Notifications Messages List" create="false" edit="false" delete="false" duplicate="false">
<field name="user_id"/>
<field name="title"/>
<field name="mobile"/>
<field name="email"/>
<field name="sent_on"/>
<field name="is_read"/>
</tree>
</field>
</record>
<!-- Search View -->
<record model="ir.ui.view" id="takaful_push_notification_search">
<field name="name">takaful.push.notification.search</field>
<field name="model">takaful.push.notification</field>
<field name="arch" type="xml">
<search>
<field name="user_id"/>
<field name="mobile"/>
<field name="email"/>
<field name="sent_on"/>
<field name="is_read"/>
</search>
</field>
</record>
<!-- Message Template Form View -->
<record model="ir.ui.view" id="takaful_message_template_form">
<field name="name">Message Template Form</field>
<field name="model">takaful.message.template</field>
<field name="arch" type="xml">
<form string="Message Template" delete="false" duplicate="false">
<sheet>
<group>
<field name="title"/>
<field name="body"/>
<field name="template_name"/>
</group>
</sheet>
</form>
</field>
</record>
<!-- Message Template Tree View -->
<record model="ir.ui.view" id="takaful_message_template_tree">
<field name="name">Messages Templates List</field>
<field name="model">takaful.message.template</field>
<field name="arch" type="xml">
<tree string="Messages Templates List" delete="false" duplicate="false">
<field name="title"/>
<field name="body"/>
<field name="template_name"/>
</tree>
</field>
</record>
<!-- Windows Action -->
<record model="ir.actions.act_window" id="takaful_push_notification_action">
<field name="name">Notification Message</field>
<field name="res_model">takaful.push.notification</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">No Notification Messege
</p>
</field>
</record>
<!-- Message Template Window Action -->
<record model="ir.actions.act_window" id="takaful_message_template_action">
<field name="name">Message Template</field>
<field name="res_model">takaful.message.template</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">No Message Template
</p>
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,829 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record id="sponsorship" model="product.product">
<field name="name">كفالة</field>
<field name="type">service</field>
<field name="default_code">sponsorship</field>
<!-- <field name="standard_price">0</field> -->
<field name="list_price">300.0</field>
</record>
</data>
<record id="grant_benefit_kafala_needs_tree" model="ir.ui.view">
<field name="name">grant.benefit.tree</field>
<field name="model">grant.benefit</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="benefit_needs_percent"/>
<field name="benefit_needs_value"/>
</tree>
</field>
</record>
<record id="takaful_sponsorship_form" model="ir.ui.view">
<field name="name">takaful.sponsorship.form</field>
<field name="model">takaful.sponsorship</field>
<field name="arch" type="xml">
<form string="Takaful Sponsorship">
<header>
<field name="show_register_payment" invisible="1"/>
<!-- <button name="action_open_donation_catalog" type="object"-->
<!-- <button name="donation_catelog" type="object"-->
<!-- string="Donation Catalog" class="btn-primary"-->
<!-- icon="fa-shopping-cart"-->
<!-- attrs="{'invisible': ['|', '|', ('state', '!=', 'draft'), ('record_type', '!=', 'donation'), ('donation_mechanism', '!=', 'without_conditions')]}"/>-->
<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 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)]}"/>
<button name="action_set_cancel" type="object"
string="To Cancel" class="oe_highlight"
attrs="{'invisible': [('state','not in',['confirmed'])]}"/>
<button name="action_reset_to_draft" type="object"
string="Reset to Draft" class="btn-link"
attrs="{'invisible': [('state','!=','confirmed')]}"/>
<button name="action_set_close" type="object"
string="Close" class="oe_highlight"
attrs="{'invisible': [('state', 'not in', ['wait_pay', 'paid'])]}"/>
<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 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"/>
<field name="state" widget="statusbar"
statusbar_visible="draft,confirmed,wait_pay,paid,canceled,closed"/>
</header>
<sheet>
<div name="oe_button_box" class="oe_button_box">
<button name="action_view_journal_entries" type="object"
class="oe_stat_button" icon="fa-book">
<field name="journal_entry_count" string="Invoices" widget="statinfo"/>
</button>
<button name="action_view_journal_entries_vendor" type="object"
class="oe_stat_button" icon="fa-book"
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_refund_moves" type="object"
class="oe_stat_button" icon="fa-money">
<field name="refund_move_count" string="Refund Invoices"
widget="statinfo"/>
</button>
<!-- <button name="action_replacement_processes" type="object"-->
<!-- string="Replacement Processes" class="oe_stat_button" icon="fa-users">-->
<!-- </button>-->
</div>
<!-- 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;">
<i class="fa fa-barcode"/> <field name="code" nolabel="1" readonly="1"/>
</span>
</div> -->
<!-- Record Type Selection - Simple & Clean Design -->
<div class="o_record_type_simple">
<div class="record_type_options">
<div class="record_option donation_option" data-value="donation">
<i class="fa fa-heart"></i>
<span>تبرع</span>
</div>
<div class="record_option sponsorship_option" data-value="sponsorship">
<i class="fa fa-users"></i>
<span>كفالة</span>
</div>
</div>
<!-- Hidden field for actual value -->
<field name="record_type" readonly="0" nolabel="1" invisible="1"
groups="!odex_takaful.branch_manager_group,!odex_takaful.sponsorship_system_manager_group,odex_takaful.donation_officer_group,odex_takaful.sponsorship_officer_group"/>
<field name="record_type" nolabel="1" invisible="1"
groups="odex_takaful.branch_manager_group,odex_takaful.sponsorship_system_manager_group"
attrs="{'readonly': [('state','!=','draft')]}"/>
</div>
<!-- Donation Type Selection - Only for Donations -->
<div class="o_donation_mechanism_simple"
attrs="{'invisible': [('record_type','!=','donation')]}">
<div class="mechanism_options">
<div class="mechanism_option without_conditions" data-value="without_conditions">
<i class="fa fa-check-circle"></i>
<span>غير مشروط</span>
</div>
<div class="mechanism_option with_conditions" data-value="with_conditions">
<i class="fa fa-list-alt"></i>
<span>مشروط</span>
</div>
</div>
<!-- Hidden field for actual value -->
<field name="donation_mechanism" invisible="1" nolabel="1"
attrs="{'required': [('record_type','=','donation')], 'readonly': [('state','!=','draft')]}"/>
</div>
<!-- Help Messages Section -->
<div class="alert alert-info text-center"
attrs="{'invisible': [('record_type','!=','donation')]}">
<i class="fa fa-heart text-success"/>
أدخل بيانات المتبرع ثم حدد تفاصيل التبرع
</div>
<div class="alert alert-primary text-center"
attrs="{'invisible': [('record_type','!=','sponsorship')]}">
<i class="fa fa-users text-primary"/>
أدخل بيانات الكافل ثم انتقل لإضافة تفاصيل الكفالة
</div>
<group name="group_top">
<group name="group_left" string="Donor Information">
<field name="manager_id" invisible="1"/>
<field name="is_donations_coordinator" invisible="1"/>
<field name="is_sponsorship_coordinator" invisible="1"/>
<field name="registered_type" invisible="1" attrs="{'readonly': [('state','!=','draft')]}"/>
<label string="Sponsor / Donor Type" for="sponsor_or_donor_type"/>
<div class="o_row">
<field name="sponsor_or_donor_type"
attrs="{'invisible': [('record_type','!=','donation')], 'required': [('record_type','=','donation')], 'readonly': [('state','!=','draft')]}"/>
<field name="sponsor_donor_type"
attrs="{'invisible': [('record_type','!=','sponsorship')], 'required': [('record_type','=','sponsorship')], 'readonly': [('state','!=','draft')]}"/>
</div>
<label string="اسم الكافل/المتبرع" for="sponsor_id"
attrs="{
'invisible': ['|',
'&amp;', ('record_type','=','donation'), ('sponsor_or_donor_type','=','unknown'),
'&amp;', ('record_type','=','sponsorship'), ('sponsor_donor_type','=','unknown')
]
}"/>
<div class="o_row">
<field name="sponsor_id" nolabel="1"
context="{'form_view_ref': 'odex_takaful.view_takaful_sponsor_form'}"
attrs="{
'invisible': ['|',
'&amp;', ('record_type','=','donation'), ('sponsor_or_donor_type','=','unknown'),
'&amp;', ('record_type','=','sponsorship'), ('sponsor_donor_type','=','unknown')
],
'required': ['|',
'&amp;', ('record_type','=','donation'), ('sponsor_or_donor_type','=','registered'),
'&amp;', ('record_type','=','sponsorship'), ('sponsor_donor_type','=','registered')
],
'readonly': [('state','!=','draft')]
}"
force_save="1"
options="{'no_create': True, 'no_create_edit': True}"/>
<button name="create_new_sponsor" type="object"
string="إنشاء مشترك"
class="btn-primary oe_highlight"
icon="fa-plus"
attrs="{
'invisible': ['|', '|',
('sponsor_id','!=',False),
'&amp;', ('record_type', '=', 'donation'), ('sponsor_or_donor_type', '!=', 'new_sponsor'),
'&amp;', ('record_type', '=', 'sponsorship'), ('sponsor_donor_type', '!=', 'new_sponsor')
]
}"/>
</div>
<field name="sponsor_phone" string="رقم الجوال" widget="phone"
attrs="{
'invisible': ['|',
'&amp;', ('record_type','=','donation'), ('sponsor_or_donor_type','!=','unknown'),
'&amp;', ('record_type','=','sponsorship'), ('sponsor_donor_type','!=','unknown')
],
'readonly': [('state','!=','draft')]
}"
placeholder="05xxxxxxxx"/>
<field name="preferred_communication" string="طريقة التواصل المفضلة"
attrs="{
'invisible': ['|',
'&amp;', ('record_type','=','donation'), ('sponsor_or_donor_type','=','unknown'),
'&amp;', ('record_type','=','sponsorship'), ('sponsor_donor_type','=','unknown')
],
'readonly': [True]
}"
force_save="1"
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"/>
<field name="has_delay" invisible="1"/>
<field name="members_domain_ids" invisible="1"/>
<field name="donate_for_another_person" widget="boolean_toggle"
attrs="{'readonly': [('state', '!=', 'draft')]}"/>
<field name="sponsorship_creation_date" readonly="1"/>
<field name="create_uid" string="Sponsorship Creator" readonly="1"/>
<field name="branch_custom_id" groups="!odex_takaful.sponsorship_system_manager_group"
readonly="0"/>
<field name="branch_custom_id"
groups="odex_takaful.sponsorship_system_manager_group"
attrs="{'readonly': [('state','!=','draft')]}"/>
<field name="marketer_id" attrs="{'readonly': [('state','!=','draft')]}"
context="{'default_domain_force_all': True}"/>
</group>
</group>
<group>
<field name="is_gift" invisible="1"/>
<field name="show_payment_details" invisible="1"/>
</group>
<group string="Gifter Information"
attrs="{'invisible': [('is_gift', '!=', 'yes')]}">
<field name="gifter_id" readonly="1"/>
<field name="gifter_name" readonly="1"/>
<field name="gifter_mobile" widget="phone" readonly="1"/>
<field name="gifter_message" readonly="1"/>
</group>
<group attrs="{'invisible': [('state', '!=', 'canceled')]}">
<field name="cancel_reason_id" invisible="1"/>
<field name="reason" readonly="1"
attrs="{'invisible': [('state', '!=', 'canceled')]}" style="color: red;"/>
</group>
<group>
<notebook>
<page string="Another Sponsors"
attrs="{'invisible':[('donate_for_another_person','=',False)]}">
<field name="another_sponsors">
<tree editable="bottom">
<field name="sponsor_name"/>
<field name="sponsor_phone" widget="phone"/>
<field name="sponsor_id_number"/>
<field name="receive_messages" widget="boolean_toggle"/>
<field name="note"/>
</tree>
</field>
</page>
<page name="sponsorship_details" string="Donation Details">
<field name="donations_details_lines"
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">
<control>
<create name="add_line_control" string="Add a line"/>
<!-- <create name="add_section_control" string="Add a section"-->
<!-- context="{'default_display_type': 'line_section'}"/>-->
<!-- <button name="action_delegate_to_catalog" string="Catalog" type="object" class="px-4 btn-link" context="{'sponsorship_id': parent.id}"/>-->
</control>
<field name="sponsorship_duration" invisible="1"/>
<field name="payment_option" invisible="1"/>
<field name="state" invisible="1"/>
<field name="is_paid" invisible="1"/>
<field name="donation_mechanism" invisible="1"/>
<field name="display_type" invisible="1"/>
<field name="sponsorships_computed" invisible="1"/>
<field name="direct_debit" invisible="1"/>
<field name="members_domain_ids" invisible="1"/>
<field name="family_domain_ids" invisible="1"/>
<field name="fixed_value" invisible="1"/>
<field name="sequence" widget="handle"/>
<field name="sequence_no" readonly="1" optional="hide"/>
<field name="sponsorship_scheduling_line_ids" invisible="1"/>
<field name="show_extend_button" invisible="1"/>
<field name="donation_type"
invisible="1"/>
<!-- attrs="{'column_invisible': [('parent.record_type', '=', 'donation')],'required': ['|',('parent.record_type', '=', 'donation'),('display_type', '=', False)]}"/>-->
<field name="donation_types"
invisible="1" force_save="1"/>
<!-- attrs="{'column_invisible': [('parent.record_type', '!=', 'donation')], 'required': [('parent.record_type', '=', 'donation'), ('display_type', '=', False)]}"-->
<field name="product_template_id"
attrs="{'required': [('display_type', '=', False)]}"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
<field name="name" widget="section_and_note_text" optional="show"/>
<field name="direct_debit"/>
<field name="journal_id"
attrs="{'invisible': [('direct_debit', '=', False)], 'required': [('direct_debit', '=', True)]}"/>
<!-- <field name="cheque_number"
attrs="{'required': [('payment_method', '=', 'check')], 'invisible': [('payment_method', '!=', 'check')]}"/>
<field name="cheque_due_date"
attrs="{'required': [('payment_method', '=', 'check')], 'invisible': [('payment_method', '!=', 'check')]}"/>
<field name="cheque_file_attachment" widget="binary"
filename="cheque_attachment_file_name"
attrs="{'required': [('payment_method', '=', 'check')], 'invisible': [('payment_method', '!=', 'check')]}"/>
<field name="cheque_attachment_file_name" invisible="1"/>
<field name="bank_transfer_file_attachment" widget="binary"
filename="bank_transfer_attachment_file_name"
attrs="{'required': [('payment_method', '=', 'bank')], 'invisible': [('payment_method', '!=', 'bank')]}"/>
<field name="bank_transfer_attachment_file_name" invisible="1"/>
-->
<field name="debit_payment_attachment_file_name" invisible="1"/>
<field name="debit_payment_file_attachment" widget="binary"
filename="debit_payment_attachment_file_name"
attrs="{'required': [('direct_debit', '=', True)], 'invisible': [('direct_debit', '=', False)]}"
optional="hide"/>
<field name="sponsorship_type"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')]}"/>
<field name="benefit_id"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')]}"/>
<field name="payment_month_count" optional="hide"
attrs="{'invisible': [('direct_debit', '=', False)]}"/>
<field name="start_date" string="From" optional="hide" widget="date"
attrs="{'invisible': [('direct_debit', '=', False)],'readonly': [('direct_debit', '=', False)], 'required': [('direct_debit', '=', True)]} "/>
<field name="end_date" string="To" optional="hide" widget="date"
attrs="{'invisible': [('direct_debit', '=', False)]}"
readonly="1"/>
<field name="currency_id" invisible="1"/>
<field name="donation_qty" force_save="1"/>
<field name="donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly':[('fixed_value','=',True)]}"
force_save="1"
required="1"/>
<field name="total_donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
readonly="1" force_save="1"/>
<button name="action_view_scheduling_lines"
string="View Scheduling Lines"
type="object"
class="btn-secondary"
icon="fa-calendar"
attrs="{'invisible': ['|', ('direct_debit', '=', False), ('sponsorship_scheduling_line_ids', '=', [])]}"/>
<button name="action_extend_sponsorship"
string="Extend"
type="object"
class="btn-success"
icon="fa-plus-circle"
attrs="{'invisible': [('show_extend_button', '=', False)]}"/>
<!-- <button name="action_register_payment"
string="Register Payment"
type="object"
class="btn-primary"
attrs="{'column_invisible': [('parent.state', 'not in', ['confirmed', 'wait_pay'])], 'invisible': ['|', ('direct_debit', '=', True), ('state', 'in', ['paid', 'active', 'waiting'])]}"/> -->
</tree>
</field>
<field name="donations_details_lines_mechanism_ids"
context="{'default_active_id': id, 'default_donation_mechanism': 'with_conditions','default_start_date': sponsorship_creation_date, 'default_sponsor_id': sponsor_id, }"
attrs="{'invisible': [('donation_mechanism', '=', 'without_conditions')], 'readonly': [('state','!=','draft')]}">
<tree>
<field name="sponsorships_computed" invisible="1"/>
<field name="sponsorship_scheduling_line_ids" invisible="1"/>
<field name="show_extend_button" invisible="1"/>
<field name="show_replaced_button" invisible="1"/>
<field name="show_add_benefit_button" invisible="1"/>
<field name="sequence" widget="handle"/>
<field name="display_type" invisible="1"/>
<field name="state" invisible="1"/>
<field name="is_paid" invisible="1"/>
<field name="direct_debit" invisible="1"/>
<field name="sequence_no" readonly="1"/>
<field name="donation_type"
invisible="1"/>
<!-- attrs="{'column_invisible': [('parent.record_type', '=', 'donation')],'required': ['|',('parent.record_type', '=', 'donation'),('display_type', '=', False)]}"/>-->
<field name="donation_types"
invisible="1"/>
<!-- attrs="{-->
<!-- 'column_invisible': [('parent.record_type', '!=', 'donation')],-->
<!-- 'required': [('parent.record_type', '=', 'donation'), ('display_type', '=', False)]}"/>-->
<field name="product_template_id"
attrs="{'required': [('display_type', '=', False)]}"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
<field name="name"
widget="section_and_note_text" optional="show"/>
<field name="direct_debit"/>
<!-- <field name="cheque_number"
attrs="{'required': [('payment_method', '=', 'check')], 'invisible': [('payment_method', '!=', 'check')]}"/>
<field name="cheque_due_date"
attrs="{'required': [('payment_method', '=', 'check')], 'invisible': [('payment_method', '!=', 'check')]}"/>
<field name="cheque_file_attachment" widget="binary"
filename="cheque_attachment_file_name"
attrs="{'required': [('payment_method', '=', 'check')], 'invisible': [('payment_method', '!=', 'check')]}"/>
<field name="cheque_attachment_file_name" invisible="1"/>
<field name="bank_transfer_file_attachment" widget="binary"
filename="bank_transfer_attachment_file_name"
attrs="{'required': [('payment_method', '=', 'bank')], 'invisible': [('payment_method', '!=', 'bank')]}"/>
<field name="bank_transfer_attachment_file_name" invisible="1"/>
<field name="debit_payment_file_attachment" widget="binary"
filename="debit_payment_attachment_file_name"
attrs="{'required': [('payment_method', '=', 'direct_debit')], 'invisible': [('payment_method', '!=', 'direct_debit')]}"/>
<field name="debit_payment_attachment_file_name" invisible="1"/> -->
<field name="sponsorship_type"
invisible="1"/>
<!-- attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')]}"/>-->
<field name="members_domain_ids" invisible="1"/>
<field name="family_domain_ids" invisible="1"/>
<field name="benefit_id"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')]}"/>
<field name="sponsorship_duration" invisible="1"/>
<field name="payment_option"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')],'invisible': [('sponsorship_duration','!=','temporary')]}"
readonly="1"/>
<field name="payment_month_count_visibility" invisible="1"/>
<field name="payment_month_count"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')],'invisible': [('direct_debit', '=', False)]}"
/>
<field name="start_date" widget="date"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')],'invisible': [('payment_option', '!=', 'month')],'readonly': [('direct_debit', '=', False)]}"
string="Start Date"/>
<field name="end_date" widget="date"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions'),('parent.record_type','!=','sponsorship')],'invisible': [('payment_option', '!=', 'month')]}"
string="End Date"/>
<field name="currency_id" invisible="1"/>
<field name="donation_qty" invisible="1" force_save="1"/>
<field name="record_type" invisible="1"/>
<field name="donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
force_save="1"
attrs="{'readonly': [('record_type','=','sponsorship')]}"/>
<field name="total_donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
force_save="1"/>
<field name="donation_mechanism"
attrs="{'column_invisible': [('parent.donation_mechanism','!=','with_conditions')]}"/>
<button name="action_view_scheduling_lines"
string="View Scheduling Lines"
type="object"
class="btn-secondary"
icon="fa-calendar"
attrs="{'invisible': ['|', ('direct_debit', '=', False), ('sponsorship_scheduling_line_ids', '=', [])]}"/>
<button name="action_extend_sponsorship"
string="Extend"
type="object"
class="btn-success"
icon="fa-plus-circle"
attrs="{'invisible': [('show_extend_button', '=', False)]}"/>
<button string="Add Benefit"
name="add_benefit_wizard"
type="object"
class="btn-primary"
icon="fa-plus-circle"
attrs="{'invisible': [('show_add_benefit_button', '=', False)]}"
groups="odex_takaful.group_kufula_user"/>
<button name="action_view_replacement_wizard"
string="Orphan Replacement"
type="object"
class="btn-primary"
icon="fa-exchange"
attrs="{'invisible': [('show_replaced_button', '=', False)]}"
groups="odex_takaful.group_orphan_replacement"/>
<!-- <button name="action_register_payment"
string="Register Payment"
type="object"
class="btn-primary"
attrs="{'column_invisible': [('parent.state', 'not in', ['confirmed', 'wait_pay'])], 'invisible': ['|', ('direct_debit', '=', True), ('state', 'in', ['paid', 'active', 'waiting'])]}"/> -->
</tree>
<form string="Donation Details">
<header>
<button string="Add Benefit"
name="add_benefit_wizard"
type="object"
class="btn-primary"
icon="fa-plus-circle"
attrs="{'invisible': [('show_add_benefit_button', '=', False)]}"
groups="odex_takaful.group_kufula_user"/>
<button name="action_view_replacement_wizard"
string="Orphan Replacement"
type="object"
class="btn-primary"
icon="fa-exchange"
attrs="{'invisible': [('show_replaced_button', '=', False)]}"
groups="odex_takaful.group_orphan_replacement"/>
<button name="action_extend_sponsorship"
string="Extend"
type="object"
class="btn-success"
icon="fa-plus-circle"
attrs="{'invisible': [('show_extend_button', '=', False)]}"/>
</header>
<group>
<group>
<field name="ages" invisible="1"/>
<field name="waiting_date" invisible="1" widget="date"/>
<field name="family_id"
attrs="{'invisible': [('sponsorship_type','=','group'), ('parent.record_type','=','sponsorship')],
'readonly': ['|', ('sponsorship_type', '!=', 'group'), ('parent.record_type','!=','donation')],
'required': [('hide_beneficiary_group','=', False),('sponsorship_type', '=','group'), ('parent.record_type','=','donation')]}"
groups="odex_takaful.sponsorship_system_manager_group"/>
<field name="display_type" invisible="1"/>
<field name="sequence" invisible="1"/>
<field name="state" invisible="1"/>
<field name="show_extend_button" invisible="1"/>
<field name="show_replaced_button" invisible="1"/>
<field name="show_add_benefit_button" invisible="1"/>
<field name="sequence_no" invisible="1"/>
<field name="donation_type" invisible="1"/>
<field name="direct_debit" invisible="1"/>
<field name="hide_beneficiary_group" invisible="1"/>
<field name="payment_option" invisible="1"/>
<field name="record_type" invisible="1"/>
<field name="sponsorship_duration"
attrs="{'invisible': [('record_type','!=','sponsorship')], 'required': [('record_type','=','sponsorship')]}"/>
<field name="product_template_id"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
<field name="payment_month_count_visibility" invisible="1"/>
<field name="direct_debit"
attrs="{'invisible': [('sponsorship_duration','=','permanent')]}"/>
<field name="payment_month_count"
attrs="{'invisible': [('payment_month_count_visibility','!=', True)], 'required': [('direct_debit', '=', True)]}"/>
<field name="donation_types"
invisible="1"/>
<field name="sponsor_id" invisible="1"/>
<field name="direct_debit_partner_bank_id"
context="{'form_view_ref': 'odex_takaful.res_partner_bank_view_form_quick_create', 'default_partner_id': sponsor_id}"
attrs="{'invisible': ['|', ('payment_month_count_visibility','!=', True),('direct_debit', '=', False)], 'required': [('direct_debit', '=', True)]}"/>
<field name="journal_id"
attrs="{'invisible': ['|', ('payment_month_count_visibility','!=', True),('direct_debit', '=', False)], 'required': [('direct_debit', '=', True)]}"/>
<field name="debit_payment_file_attachment" widget="binary"
filename="debit_payment_attachment_file_name"
attrs="{'required': [('direct_debit', '=', True)], 'invisible': ['|', ('payment_month_count_visibility','!=', True),('direct_debit', '=', False)]}"/>
<field name="debit_payment_attachment_file_name" invisible="1"/>
</group>
<group>
<field name="start_date" string="Start Date" widget="date"
attrs="{'invisible': [('payment_month_count_visibility','!=', True)], 'required': [('direct_debit', '=', True)], 'readonly': [('direct_debit', '=', False)],}"/>
<field name="end_date" string="End Date" widget="date" readonly="1"
attrs="{'invisible': [('payment_month_count_visibility','!=', True)]}"/>
<field name="donation_mechanism" invisible="1" force_save="1"/>
<field name="fixed_value" invisible="1"/>
<field name="donation_qty" force_save="1" invisible="1"/>
<field name="donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'readonly':[('fixed_value','=',True)]}"
force_save="1" required="1"/>
<field name="total_months_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'invisible':[('payment_month_count_visibility','=', False)]}"/>
<field name="benefits_count"
attrs="{'invisible':['|', ('sponsorship_type','!=','group'), ('record_type','!=','sponsorship')]}"/>
<field name="total_donation_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"
attrs="{'invisible':['|', ('sponsorship_type','!=','group'), ('record_type','!=','sponsorship')]}"
force_save="1"/>
</group>
<group>
<field name="benefit_type"
invisible="1"/>
<!-- attrs="{'invisible': [('donation_mechanism','!=','with_conditions')]}"/>-->
</group>
<field name="name"/>
<field name="sponsorship_type" widget="radio" nolabel="1"
options="{'horizontal': true}"
invisible="1"/>
<!-- attrs="{'invisible': [('donation_mechanism','!=','with_conditions')], 'required': [('hide_beneficiary_group','=', False), ('donation_mechanism','=','with_conditions')]}"/>-->
<field name="members_domain_ids" invisible="1"/>
<field name="family_domain_ids" invisible="1"/>
<field name="benefit_id"
invisible="1"
options="{'no_create': True, 'no_create_edit':True}"/>
</group>
<notebook>
<!-- <page string="Orphans List" autofocus="autofocus"-->
<!-- attrs="{'invisible': ['|', '|', '|', ('hide_beneficiary_group','=', True), ('parent.record_type','!=','sponsorship'), ('sponsorship_type', '!=', 'group'), ('benefit_type', '!=', 'orphan')]}">-->
<!-- <field name="benefit_ids" nolabel="1">-->
<!-- <tree editable="bottom">-->
<!-- <field name="name"/>-->
<!-- <field name="age"/>-->
<!-- <field name="member_status"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </page>-->
<!-- <page string="Widows List"-->
<!-- attrs="{'invisible': ['|', '|', '|', ('hide_beneficiary_group','=', True), ('parent.record_type','!=','sponsorship'), ('sponsorship_type', '!=', 'group'), ('benefit_type', '!=', 'widow')]}">-->
<!-- <field name="benefit_ids" nolabel="1">-->
<!-- <tree editable="bottom">-->
<!-- <field name="name"/>-->
<!-- <field name="age"/>-->
<!-- <field name="member_status"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </page>-->
<page string="Orphans and Widows List"
attrs="{'invisible': ['|',('sponsorship_type', '!=', 'group'), ('hide_beneficiary_group', '=', True)]}">
<!-- attrs="{'invisible': ['|', '|', '|', ('hide_beneficiary_group','=', True), ('parent.record_type','!=','sponsorship'), ('sponsorship_type', '!=', 'group'), ('benefit_type', '!=', 'both')]}">-->
<field name="benefit_ids" nolabel="1" options="{'no_create': True}">
<tree editable="bottom">
<field name="name"/>
<field name="age"/>
<field name="member_status"/>
</tree>
</field>
</page>
<page string="Beneficiary Filters" autofocus="false"
invisible="1">
<group>
<group>
<field name="gender"
invisible="1"/>
<!-- attrs="{'invisible': [('donation_mechanism','!=','with_conditions')]}"/>-->
<field name="age_category_id"
invisible="1"/>
<field name="education_status"
invisible="1"/>
<field name="education_level"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')]}"/>
<field name="benefit_id_number"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')]}"/>
<field name="benefit_family_code"
attrs="{'invisible': [('donation_mechanism','!=','with_conditions')]}"/>
</group>
</group>
</page>
</notebook>
</form>
</field>
<group class="oe_subtotal_footer oe_right" colspan="2"
name="donation_total">
<field name="currency_id" invisible="1"/>
<field name="total_sponsorship_amount" string="Total Amount" widget="monetary"
options="{'currency_field': 'currency_id'}"/>
<field name="donations_count"/>
</group>
<button name="donation_catelog" type="object" string="Donation Catalog"
class="btn-primary" icon="fa-shopping-cart"
attrs="{'invisible': ['|', '|', ('state', '!=', 'draft'), ('record_type', '!=', 'donation'), ('donation_mechanism', '!=', 'without_conditions')]}"/>
<div class="oe_clear"/>
</page>
<page string="Payment Details"
attrs="{'invisible': [('state', '=', 'draft')]}"
groups="odex_takaful.group_refund_approval">
<field name="payment_ids" readonly="1"
context="{'tree_view_ref': 'account.view_account_payment_tree'}"/>
</page>
<page string="Refund Details"
attrs="{'invisible': [('state', 'not in', ('approve_refund','under_refund','partial_refund','fully_refund'))]}">
<field name="refund_details_lines_ids" mode="tree"
options="{'no_open': True}" readonly="1">
<tree create="false" delete="false" edit="false">
<field name="refund_date"/>
<field name="payment_details_line"/>
<field name="refund_reason"/>
<field name="payment_method_id"/>
<field name="sponsor_id"/>
<field name="refund_amount" widget="monetary"
options="{'currency_field': 'currency_id'}"/>
<field name="journal_id"/>
<field name="attachment_ids"
widget="many2many_attachment_preview"/>
<field name="sponsorship_scheduling_line" invisible="1"/>
<field name="sponsorship_scheduling_line_ids" invisible="1"/>
<field name="sponsorship_id" invisible="1"/>
<field name="invoiced" invisible="1"/>
</tree>
</field>
</page>
</notebook>
</group>
</sheet>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<record id="takaful_sponsorship_tree" model="ir.ui.view">
<field name="name">takaful.sponsorship.tree</field>
<field name="model">takaful.sponsorship</field>
<field name="arch" type="xml">
<tree string="Sponsorship List" decoration-danger="has_delay==True">
<field name="has_delay" invisible="1"/>
<field name="code"/>
<field name="create_uid"/>
<field name="sponsorship_creation_date"/>
<field name="record_type"/>
<field name="branch_custom_id"/>
<field name="sponsor_or_donor_type"/>
<field name="registered_type"/>
<field name="sponsor_id"/>
<field name="sponsor_name" string="Unregistered Sponsor Name" optional="show"/>
<field name="total_sponsorship_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="state" widget="badge"
decoration-muted="state == 'draft'"
decoration-warning="state in ['confirmed', 'wait_pay', 'approve_refund']"
decoration-success="state == 'paid'"
decoration-danger="state in ['canceled', 'fully_refund']"
decoration-info="state in ['closed', 'replacement_done', 'partial_refund', 'under_refund', 'under_replacement']"/>
<!-- <field name="code" />
<field name="sponsorship_duration"/>
<field name="sponsorship_type"/>
<field name="benefit_type"/>
<field name="contribution_value" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="end_date" widget="date"/>
<field name="overdue_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/> -->
</tree>
</field>
</record>
<!-- All actions -->
<record id="takaful_sponsorship_action" model="ir.actions.act_window">
<field name="name">The Sponsorship</field>
<field name="res_model">takaful.sponsorship</field>
<field name="view_mode">tree,form</field>
</record>
<record id="takaful_sponsorship_view_search" model="ir.ui.view">
<field name="name">takaful.sponsorship.view.search</field>
<field name="model">takaful.sponsorship</field>
<field name="arch" type="xml">
<search string="Takaful SponsorShip Search">
<field name="code"/>
<field name="create_uid"/>
<field name="sponsorship_creation_date" widget="datetime"/>
<field name="record_type"/>
<field name="branch_custom_id"/>
<field name="sponsor_or_donor_type"/>
<field name="registered_type"/>
<field name="sponsor_id"/>
<field name="total_sponsorship_amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="state"/>
<separator/>
<!-- State Filters -->
<filter string="Draft" name="filter_draft" domain="[('state', '=', 'draft')]"/>
<filter string="Confirmed" name="filter_confirmed" domain="[('state', '=', 'confirmed')]"/>
<filter string="Enter Payment Details" name="filter_wait_pay" domain="[('state', '=', 'wait_pay')]"/>
<filter string="Paid" name="filter_paid" domain="[('state', '=', 'paid')]"/>
<filter string="Partial Refund" name="filter_partial_refund"
domain="[('state', '=', 'partial_refund')]"/>
<filter string="Fully Refund" name="filter_fully_refund" domain="[('state', '=', 'fully_refund')]"/>
<filter string="Approve Refund" name="filter_approve_refund"
domain="[('state', '=', 'approve_refund')]"/>
<filter string="Under Refund Procedure" name="filter_under_refund"
domain="[('state', '=', 'under_refund')]"/>
<filter string="Under Replacement" name="filter_under_replacement"
domain="[('state', '=', 'under_replacement')]"/>
<filter string="Replacement Done" name="filter_replacement_done"
domain="[('state', '=', 'replacement_done')]"/>
<filter string="Canceled" name="filter_canceled" domain="[('state', '=', 'canceled')]"/>
<filter string="Closed" name="filter_closed" domain="[('state', '=', 'closed')]"/>
<separator/>
<!-- Record Type Filters -->
<filter string="Sponsorship" name="filter_sponsorship" domain="[('record_type', '=', 'sponsorship')]"/>
<filter string="Donation" name="filter_donation" domain="[('record_type', '=', 'donation')]"/>
<separator/>
<group expand="0" string="Group By">
<filter name="create_uid" context="{'group_by':'create_uid'}"/>
<filter name="record_type" context="{'group_by':'record_type'}"/>
<filter name="branch_custom_id" context="{'group_by':'branch_custom_id'}"/>
<filter name="sponsor_or_donor_type"
context="{'group_by':'sponsor_or_donor_type'}"/>
<filter name="registered_type" context="{'group_by':'registered_type'}"/>
<filter name="sponsor_id" context="{'group_by':'sponsor_id'}"/>
<filter name="state" context="{'group_by':'state'}"/>
</group>
<separator/>
<searchpanel>
<field name="state" enable_counters="1"/>
<field name="record_type" enable_counters="1"/>
</searchpanel>
</search>
</field>
</record>
<!--print_report
method is called from server action-->
<record id="action_makfuleen_report" model="ir.actions.server">
<field name="name">Makfuleen Report</field>
<field name="type">ir.actions.server</field>
<field name="model_id" ref="model_takaful_sponsorship"/>
<field name="state">code</field>
<field name="code">
action = model.print_makfuleen_report()
</field>
</record>
</odoo>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record model="ir.ui.view" id="takaful_sponsor_operation_form">
<field name="name">partner.sponsor.operation.form</field>
<field name="model">takaful.sponsor.operation</field>
<field name="arch" type="xml">
<form string="Sponsor Operations" delete="false">
<sheet>
<group>
<field name="origin_id" invisible="1" />
<field name="sponsor_id" readonly="1" />
<field name="name" readonly="1" />
<field name="operation_type" readonly="1" />
<field name="title" readonly="1" />
<field name="benefit_id" attrs="{'invisible': [('benefit_ids','=', False)]}" />
<field name="benefit_ids"
attrs="{'invisible': [('benefit_id','!=', False)]}" />
<field name="benefit_type" readonly="1" />
<field name="month" invisible="1" />
<field name="period_code" invisible="1" />
<field name="currency_id" invisible="1"/>
<field name="amount" widget="monetary" options="{'currency_field': 'currency_id'}" readonly="1" />
<field name="date" widget="date" invisible="1" />
<field name="operation_on" widget="datetime" readonly="1" />
</group>
</sheet>
</form>
</field>
</record>
<record model="ir.ui.view" id="takaful_sponsor_operation_tree">
<field name="name">takaful.sponsor.operation.tree</field>
<field name="model">takaful.sponsor.operation</field>
<field name="arch" type="xml">
<tree string="Sponsor Operations List">
<field name="name" />
<field name="title" />
<field name="operation_type" />
<field name="sponsor_id" />
<field name="benefit_type" />
<field name="amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="currency_id" invisible="1"/>
<field name="date" widget="date"/>
<field name="operation_on" widget="datetime"/>
</tree>
</field>
</record>
<record model="ir.ui.view" id="takaful_sponsor_operation_search">
<field name="name">takaful.sponsor.operation.search</field>
<field name="model">takaful.sponsor.operation</field>
<field name="arch" type="xml">
<search>
<field name="name" />
<field name="title" />
<field name="operation_type" />
<field name="sponsor_id" />
<field name="benefit_type" />
<field name="amount" widget="monetary" options="{'currency_field': 'currency_id'}"/>
<field name="date" widget="date"/>
</search>
</field>
</record>
<record model="ir.actions.act_window" id="takaful_sponsor_operation_action">
<field name="name">Sponsor Operation</field>
<field name="res_model">takaful.sponsor.operation</field>
<!-- <field name="view_type">form</field>-->
<field name="view_mode">tree,form</field>
<field name="help" type="html">
<p class="oe_view_nocontent_create">No Any Sponsor Operations
</p>
</field>
</record>
</odoo>

View File

@ -0,0 +1,262 @@
<?xml version="1.0"?>
<odoo>
<record id="takaful_sponsor_sequence" model="ir.sequence">
<field name="name">Takaful Sponsor Sequence</field>
<field name="code">takaful.sponsor.sequence</field>
<field name="prefix">S/</field>
<field name="padding">4</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
</record>
<record id="takaful_sponsor_tree" model="ir.ui.view">
<field name="name">partner.sponsor.tree</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<tree string="Sponsors List" decoration-danger="active==False">
<field name="name"/>
<field name="company_type"/>
<field name="mobile"/>
<field name="id_number"/>
<field name="city_id"/>
<field name="state" invisible="1"/>
<field name="active" invisible="1"/>
</tree>
</field>
</record>
<record id="view_takaful_sponsor_form" model="ir.ui.view">
<field name="name">partner.sponsor.form</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<form string="The sponsor" create="false">
<header>
<button name="action_unlink_sponsor_and_related" string="Unlink Partners" type="object"
groups="base.group_no_one" invisible="1"/>
</header>
<sheet>
<separator string="Inactive" style="color: red;" attrs="{'invisible': [('active', '=', True)]}"/>
<field name="active" invisible="1"/>
<field name="company_type" invisible="1"/>
<field name="parent_id" invisible="1"/>
<field name="country_id" invisible="1"/>
<field name="state" invisible="1"/>
<field name="type" invisible="1"/>
<field name="lang" invisible="1"/>
<div name="button_box" class="oe_button_box" attrs="{'invisible': [('id', '=', False)]}">
<button class="oe_stat_button" type="object" name="view_sponsorship_action" icon="fa-dollar">
<field string="Kafalat" name="kafalat_count" widget="statinfo"/>
</button>
<button class="oe_stat_button" type="object" name="action_open_benefit_records" icon="fa-users">
<field string="Benefits" name="related_benefits_count" widget="statinfo"/>
</button>
<!-- <button class="oe_stat_button" name="_compute_contribution_count" type="action"
icon="fa-money">
<field string="Contributions" name="contribution_count" widget="statinfo"/>
</button>
<button class="oe_stat_button" name="_compute_gift_count" type="action" icon="fa-gift">
<field string="Gifts" name="gift_count" widget="statinfo"/>
</button>
<button name="action_open_sponsor_operation" type="object" class="oe_stat_button" icon="fa-history">
<field string=" Operations Records" name="operation_count" widget="statinfo"/>
</button> -->
</div>
<div class="oe_title" style="margin:10px;" invisible="1">
<h4>
<field name="serial_code" readonly="1"/>
</h4>
<h2>
<field name="name" placeholder="Name"
attrs="{'readonly': [('company_type', '=', 'person')]}" force_save="1"/>
</h2>
</div>
<group attrs="{'invisible': [('company_type', '!=', 'person')]}">
<div class="o_row">
<field placeholder="اللقب" name="title" class="oe_inline" nolabel="1" style="width: 20%;"
domain="[('position', 'in', ['prefix','both'])]"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
<field placeholder="الاسم" name="first_name" class="oe_inline" nolabel="1" style="width: 60%;" required="1"/>
<field placeholder="العبارة الختامية" name="suffix_title_id" class="oe_inline" nolabel="1" style="width: 20%;"
domain="[('position', 'in', ['suffix','both'])]"
options="{'no_create': True, 'no_create_edit':True, 'no_open': True}"/>
</div>
</group>
<group>
<field name="kafel_id" readonly="1" invisible="1"/>
</group>
<group name="group_top">
<group name="group_main" colspan="2">
<field name="mobile" string="رقم الجوال" widget="phone" placeholder="05xxxxxxxx" attrs="{'required': [('parent_id', '=', False)]}" />
<field name="preferred_communication" string="طريقة التواصل المفضلة" required="1"/>
<field name="gender" attrs="{'required': [('company_type', '=', 'person')],'invisible': [('company_type', '!=', 'person')]}"/>
<field name="street" attrs="{'invisible': [('company_type', '=', 'person')]}"/>
<field name="zip" attrs="{'invisible': [('company_type', '=', 'person')]}"/>
<field name="email"/>
<field name="id_number" attrs="{'invisible': [('company_type', '!=', 'person')]}"/>
<field name="branch_custom_id"/>
<field name="city_id" invisible="1"/>
<field name="district_id" invisible="1"/>
<field name="user_id" invisible="1" options="{'no_create': True, 'no_create_edit':True}"
readonly="1"/>
</group>
</group>
<notebook>
<page string="Related Donors" name="related_donors" autofocus="autofocus" invisible="context.get('default_type') == 'other'" >
<field name="child_ids" mode="kanban" context="{'form_view_ref': 'odex_takaful.view_takaful_sponsor_form', 'default_parent_id': active_id, 'default_street': street, 'default_city_id': city_id, 'default_zip': zip, 'default_country_id': country_id, 'default_lang': lang, 'default_type': 'other', 'default_user_id': user_id, 'default_is_donor': True, 'default_is_sponsor_portal': True}">
<kanban>
<field name="id"/>
<field name="color"/>
<field name="name"/>
<field name="title"/>
<field name="type"/>
<field name="email"/>
<field name="parent_id"/>
<field name="is_company"/>
<field name="function"/>
<field name="phone"/>
<field name="street"/>
<field name="street2"/>
<field name="zip"/>
<field name="city"/>
<field name="country_id"/>
<field name="mobile"/>
<field name="state_id"/>
<field name="image_128"/>
<field name="lang"/>
<!-- fields in form x2many view to diminish requests -->
<field name="comment"/>
<field name="display_name"/>
<templates>
<t t-name="kanban-box">
<t t-set="color" t-value="kanban_color(record.color.raw_value)"/>
<div t-att-class="color + (record.title.raw_value == 1 ? ' oe_kanban_color_alert' : '') + ' oe_kanban_global_click'">
<div class="o_kanban_image">
<img alt="Contact image" t-if="record.image_128.raw_value"
t-att-src="kanban_image('res.partner', 'image_128', record.id.raw_value)"/>
<t t-if="!record.image_128.raw_value">
<img alt="Delivery" t-if="record.type.raw_value === 'delivery'"
t-att-src="_s + &quot;/base/static/img/truck.png&quot;"/>
<img alt="Invoice" t-if="record.type.raw_value === 'invoice'"
t-att-src="_s + &quot;/base/static/img/money.png&quot;"/>
<t t-if="record.type.raw_value !== 'invoice' &amp;&amp; record.type.raw_value !== 'delivery'">
<img alt="Logo" t-if="record.is_company.raw_value === true"
t-att-src="_s + &quot;/base/static/img/company_image.png&quot;"/>
<img alt="Avatar"
t-if="record.is_company.raw_value === false"
t-att-src="_s + &quot;/base/static/img/avatar_grey.png&quot;"/>
</t>
</t>
</div>
<div class="oe_kanban_details">
<field name="name"/>
<div t-if="record.function.raw_value">
<field name="function"/>
</div>
<div t-if="record.email.raw_value">
<field name="email" widget="email"/>
</div>
<div t-if="record.type.raw_value != 'contact'">
<div>
<field name="zip"/>
<field name="city"/>
</div>
<field t-if="record.state_id.raw_value" name="state_id"/>
<field name="country_id"/>
</div>
<div t-if="record.phone.raw_value">Phone:
<t t-esc="record.phone.value"/>
</div>
<div t-if="record.mobile.raw_value">Mobile:
<t t-esc="record.mobile.value"/>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</page>
</notebook>
</sheet>
<footer>
<button name="action_save_and_close" string="حفظ وإغلاق" type="object" class="btn-primary"/>
<button string="تجاهل" class="btn-secondary" special="cancel"/>
</footer>
<div class="oe_chatter">
<field name="message_follower_ids" widget="mail_followers"/>
<field name="message_ids" widget="mail_thread"/>
</div>
</form>
</field>
</record>
<!-- All actions -->
<record id="takaful_sponsor_action" model="ir.actions.act_window">
<field name="name">The Sponsor</field>
<field name="res_model">res.partner</field>
<field name="view_mode">tree,form</field>
<field name="domain">[('is_sponsor_portal', '=', True), ('company_type', '=', 'person')]</field>
<field name="context">
{
'default_company_type': 'person',
'default_is_sponsor_portal': True,
'default_is_donor': True,
'sponsor_contact': True
}
</field>
</record>
<record id="action_takaful_sponsor_action_form" model="ir.actions.act_window.view">
<field name="sequence" eval="2"/>
<field name="view_mode">form</field>
<field name="act_window_id" ref="takaful_sponsor_action"/>
<field name="view_id" ref="view_takaful_sponsor_form"/>
</record>
<record id="action_takaful_sponsor_action_tree" model="ir.actions.act_window.view">
<field name="sequence" eval="1"/>
<field name="view_mode">tree</field>
<field name="act_window_id" ref="takaful_sponsor_action"/>
<field name="view_id" ref="takaful_sponsor_tree"/>
</record>
<record id="active_sponsor_report_pivot_view" model="ir.ui.view">
<field name="name">active.sponsors.count.pivot</field>
<field name="model">res.partner</field>
<field name="arch" type="xml">
<pivot string="Active Sponsors Count" disable_linking="True">
<field name="active_counts" type="col"/>
</pivot>
</field>
</record>
<record id="action_active_sponsor_report" model="ir.actions.server">
<field name="name">Active Sponsors Count</field>
<field name="type">ir.actions.server</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="state">code</field>
<field name="code">
action = model.show_active_sponsor_report_report()
</field>
</record>
<!-- Unarchive Sponsor -->
<record id="activate_sponsor_multi" model="ir.actions.server">
<field name="name">Make Active</field>
<field name="binding_model_id" ref="base.model_res_partner"/>
<field name="model_id" ref="base.model_res_partner"/>
<field name='groups_id' eval="[(4, ref('odex_takaful.group_can_activate_sponsor'))]"/>
<field name="state">code</field>
<field name="code">records.on_activate_sponsor_multi()</field>
</record>
</odoo>

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from . import takaful_reports_wizards
from . import benefit_month_payment_wiz
from . import refund_payment_wizard
from . import add_details_wizard
from . import orphan_replacement_wizard
from . import transfer_deduction_wizard
from . import donation_extension_wizard
from . import replace_sponsor_wizard
from . import add_benefit_wizard
from . import account_payment_register

View File

@ -0,0 +1,213 @@
from odoo import api, fields, models, _
import logging
_logger = logging.getLogger(__name__)
class AccountRegisterPayment(models.TransientModel):
_inherit = 'account.payment.register'
@api.model
def _default_payment_method_id(self):
payment_method = self.env['takaful.payment.method'].sudo().search(
[('payment_method', '=', 'cash')],
limit=1
)
return payment_method.id if payment_method else False
takaful_sponsorship_id = fields.Many2one('takaful.sponsorship')
takaful_payment_method_id = fields.Many2one('takaful.payment.method', string="Payment Method", required=True, default=_default_payment_method_id)
takaful_payment_method = fields.Selection([
("cash", "Cash"),
("bank", "Bank Transfer"),
("direct_debit", "Direct Debit"),
("check", "Check"),
("network", "Network"),
],
compute="_compute_takaful_payment_method", string="Payment Method")
is_refund_sponsorship = fields.Boolean(string='Is Refund Sponsorship')
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' , 'الماكينة')
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)
@api.onchange("machine_id")
def onchange_machine_id(self):
for rec in self:
if rec.machine_id:
rec.journal_id = rec.machine_id.journal_id
@api.onchange("takaful_payment_method_id")
def onchange_takaful_payment_method_id(self):
for rec in self:
if rec.takaful_payment_method_id and rec.takaful_payment_method_id.journal_id:
rec.journal_id = rec.takaful_payment_method_id.journal_id.id
payment_method = rec.takaful_payment_method_id.payment_method
j_type = ""
if payment_method == "cash":
j_type = "cash"
elif payment_method in ("bank", "check","network"):
j_type = "bank"
if j_type:
return {"domain": {"journal_id": [("type", "=", j_type)]}}
@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_skip_compute_amount'):
self.amount = self.amount
else:
super(AccountRegisterPayment, self)._compute_amount()
@api.depends('takaful_payment_method_id')
def _compute_takaful_payment_method(self):
for rec in self:
if rec.takaful_payment_method_id:
if rec.takaful_payment_method_id.payment_method in ["cash", "direct_debit", "check", "network"]:
rec.takaful_payment_method = rec.takaful_payment_method_id.payment_method
else:
rec.takaful_payment_method = "bank"
else:
rec.takaful_payment_method = "cash"
def _create_payments(self):
sponsorship_line_ids = self.env.context.get('sponsorship_line_ids')
sponsorship_lines = self.env['donations.details.lines'].browse(sponsorship_line_ids).filtered(lambda r: r.display_type == False)
sponsorship = self.env['takaful.sponsorship'].browse(self.env.context.get('sponsorship_id'))
payments = super(AccountRegisterPayment, self)._create_payments()
if sponsorship_lines:
for line in sponsorship_lines:
state = ''
if line.record_type == 'sponsorship':
if not (line.benefit_id | line.benefit_ids):
state = 'waiting'
elif line.sponsorship_duration == 'temporary':
state = 'active'
else:
state = 'paid'
elif line.record_type == 'donation':
if line.donation_mechanism == 'with_conditions':
state = 'active'
else:
state = 'paid'
line.write({'state': state})
if self.env.context.get('schedule_line_payment'):
schedule_line = self.env['sponsorship.scheduling.line'].browse(self.env.context.get('schedule_line_id'))
schedule_line.sudo().write({'status': 'paid'})
all_schedule_lines_paid = schedule_line.donation_detail_linked_id.sponsorship_scheduling_line_ids.filtered(
lambda l: l.status == 'paid')
if len(all_schedule_lines_paid) == len(
schedule_line.donation_detail_linked_id.sponsorship_scheduling_line_ids):
schedule_line.donation_detail_linked_id.state = 'paid'
if sponsorship.record_type == 'donation' and sponsorship.donation_mechanism == 'with_conditions':
benefit_journal_id = self.env.company.kafala_benefit_journal_id.id
donation_line = schedule_line.donation_detail_linked_id
family_id = donation_line.family_id
bill_values = {
'takaful_sponsorship_id': sponsorship.id,
'name': self.env['ir.sequence'].next_by_code('account.move.accrsp'),
'move_type': 'in_invoice',
'journal_id': benefit_journal_id,
'date': fields.Date.today(),
'invoice_date': fields.Date.today(),
'partner_id': family_id.partner_id.id,
'invoice_line_ids': [(0, 0, {
'product_id': donation_line.product_id.id,
'price_unit': schedule_line.amount,
'quantity': 1,
'name': _("Benefit Number %s %s") % (donation_line.sequence_no, f"Cheque Number: {self.check_number} Cheque Due Date: {self.check_due_date}" if self.takaful_payment_method == 'check' else " "),
'analytic_account_id': sponsorship.branch_custom_id.branch.analytic_account_id.id,
})]
}
bill_id = self.env['account.move'].sudo().create(bill_values)
for line in bill_id.invoice_line_ids:
line.account_id = line._get_computed_account()
taxes = line._get_computed_taxes()
if taxes and line.move_id.fiscal_position_id:
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
if line.sponsorship_type == 'group':
line.benefit_ids.write({
'sponsor_related_id': line.sponsorship_mechanism_id.sponsor_id.id,
'sponsorship_id': line.sponsorship_mechanism_id.id,
'sponsorship_end_date': line.end_date if line.end_date else False,
'kafala_status': 'have_kafala',
})
if line.sponsorship_type == 'person':
line.benefit_id.write({
'sponsor_related_id': line.sponsorship_mechanism_id.sponsor_id.id,
'sponsorship_id': line.sponsorship_mechanism_id.id,
'sponsorship_end_date': line.end_date if line.end_date else False,
'kafala_status': 'have_kafala',
})
line.sponsorship_mechanism_id.sponsor_id.sudo().is_sponsor_portal = True
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({
'name': f'{"/".join(sponsorship_lines.mapped("sequence_no"))} - {self.takaful_payment_method}',
'datas': self.transaction_file_attachment,
'res_model': 'account.payment',
'res_id': payments[0].id,
'type': 'binary',
})
return payments
@api.model
def _get_line_batch_key(self, line):
res = super(AccountRegisterPayment, self)._get_line_batch_key(line)
if self.env.context.get('force_sponsorship_line_partner_id'):
res['partner_id'] = self.env.context.get('force_sponsorship_line_partner_id')
return res
def _create_payment_vals_from_wizard(self):
res = super(AccountRegisterPayment, self)._create_payment_vals_from_wizard()
if self.env.context.get('force_sponsorship_line_partner_id'):
res['partner_id'] = self.env.context.get('force_sponsorship_line_partner_id')
return res
@api.model
def _get_batch_available_partner_banks(self, batch_result, journal):
sponsorship_line_ids = self.env.context.get('sponsorship_line_ids')
sponsorship_lines = self.env['donations.details.lines'].browse(sponsorship_line_ids).filtered(lambda r: r.display_type == False)
if sponsorship_lines:
return sponsorship_lines.sponsor_id.bank_ids
return super(AccountRegisterPayment, self)._get_batch_available_partner_banks(batch_result, journal)
def action_create_payments(self):
res = super(AccountRegisterPayment, self).action_create_payments()
if self.env.context.get('dont_redirect_to_payments'):
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Payment registered successfully'),
'type': 'success',
'sticky': False,
'next': {'type': 'ir.actions.act_window_close'}
},
}
return res

View File

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="view_account_payment_register_form" model="ir.ui.view">
<field name="name">account.payment.register.inherit.form</field>
<field name="model">account.payment.register</field>
<field name="inherit_id" ref="account.view_account_payment_register_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='amount']" position="after">
<field name="is_refund_sponsorship" invisible="1"/>
</xpath>
<!-- <xpath expr="//field[@name='amount']" position="attributes">-->
<!-- <attribute name="attrs">{'readonly':[('group_payment','=',True)]}</attribute>-->
<!-- </xpath>-->
<xpath expr="//field[@name='journal_id']" position="attributes">
<attribute name="attrs">{'readonly':[('is_refund_sponsorship','=',True)]}</attribute>
<attribute name="string">Association Journal</attribute>
</xpath>
<xpath expr="//field[@name='partner_bank_id']" position="attributes">
<attribute name="invisible">context.get('sponsorship_payment')</attribute>
</xpath>
<xpath expr="//field[@name='payment_method_line_id']" position="attributes">
<attribute name="invisible">context.get('sponsorship_payment')</attribute>
</xpath>
<xpath expr="//field[@name='branch_id']" position="attributes">
<attribute name="invisible">context.get('sponsorship_payment')</attribute>
</xpath>
<xpath expr="//field[@name='payment_date']" position="attributes">
<attribute name="readonly">context.get('sponsorship_payment')</attribute>
</xpath>
<xpath expr="//field[@name='journal_id']" position="before">
<field name="takaful_payment_method_id" attrs="{'invisible': [('sponsorship_payment', '=', False)]}" options="{'no_create': True, 'no_create_edit': True}"/>
</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" 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','=','bank')], 'invisible': ['|', ('sponsorship_payment', '=', False), ('takaful_payment_method','!=','bank')]}"/>
<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"/>
</xpath>
<!--<xpath expr="//group" position="after">-->
<!-- <notebook>-->
<!-- <page string="Sub Payments" attrs="{'invisible': [('group_payment', '=', False)]}">-->
<!-- <field name="account_payment_register_ids" attrs="{'invisible': [('group_payment', '=', False)]}" nolabel="1">-->
<!-- <tree editable="bottom" delete="true" create="true">-->
<!-- <field name="sponsorship_payment" invisible="1"/>-->
<!-- <field name="takaful_payment_method" invisible="1"/>-->
<!-- <field name="available_partner_bank_ids" invisible="1"/>-->
<!-- <field name="company_id" invisible="1"/>-->
<!-- <field name="takaful_payment_method_id" options="{'no_create': True, 'no_create_edit': True}"/>-->
<!-- <field name="journal_id" string="Association Journal"/>-->
<!-- <field name="amount"/>-->
<!-- <field name="check_number"-->
<!-- attrs="{-->
<!-- 'invisible': [-->
<!-- ('takaful_payment_method','!=','check')-->
<!-- ],-->
<!-- 'required': [-->
<!-- ('takaful_payment_method','=','check')-->
<!-- ]-->
<!-- }"-->
<!-- optional="hide"/>-->
<!-- <field name="check_due_date"-->
<!-- attrs="{-->
<!-- 'invisible': [-->
<!-- ('takaful_payment_method','!=','check')-->
<!-- ],-->
<!-- 'required': [-->
<!-- ('takaful_payment_method','=','check')-->
<!-- ]-->
<!-- }"-->
<!-- optional="hide"/>-->
<!-- <field name="partner_bank_id"-->
<!-- 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': [-->
<!-- ('takaful_payment_method','=','bank')-->
<!-- ],-->
<!-- 'invisible': [-->
<!-- ('takaful_payment_method','!=','bank')-->
<!-- ]-->
<!-- }"-->
<!-- readonly="0"-->
<!-- optional="hide"/>-->
<!-- <field name="transaction_file_attachment"-->
<!-- widget="binary"-->
<!-- filename="transaction_attachment_file_name"-->
<!-- attrs="{-->
<!-- 'invisible': [-->
<!-- ('takaful_payment_method','not in',['bank', 'check'])-->
<!-- ],-->
<!-- 'required': ['|',-->
<!-- ('takaful_payment_method','=','bank'),-->
<!-- ('takaful_payment_method','=','check')-->
<!-- ]-->
<!-- }"-->
<!-- optional="hide"/>-->
<!-- </tree>-->
<!-- </field>-->
<!-- </page>-->
<!-- </notebook>-->
<!-- </xpath>-->
<!-- <xpath expr="//footer/button[@name='action_create_payments']" position="after">-->
<!-- <button name="action_register_all_lines"-->
<!-- type="object"-->
<!-- string="Register All Lines"-->
<!-- class="btn-secondary"-->
<!-- attrs="{'invisible': [('line_ids','=',False)]}"/>-->
<!-- </xpath>-->
</field>
</record>
</data>
</odoo>

View File

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
import logging
_logger = logging.getLogger(__name__)
class AddBenefitWizard(models.TransientModel):
_name = 'add.benefit.wizard'
_description = "Add Benefit"
donation_detail_id = fields.Many2one(
'donations.details.lines',
string='Donation Detail',
readonly=True
)
members_domain_ids = fields.Many2many('family.member', related='donation_detail_id.members_domain_ids')
benefit_id = fields.Many2one('family.member', string='Beneficiary Name', ondelete='restrict',
domain="[('id', 'in', members_domain_ids)]",required = True, tracking=True)
def action_add_benefit(self):
"""
Add Benefit on the donation detail line and post a message to the chatter
"""
self.ensure_one()
if not self.donation_detail_id:
raise ValidationError(_("No donation detail line found."))
if not self.benefit_id:
raise ValidationError(_("Please select a Benefit."))
donation_line = self.donation_detail_id
new_benefit_name = self.benefit_id.name
# Get the sponsorship record (could be sponsorship_id or sponsorship_mechanism_id)
sponsorship = donation_line.sponsorship_id or donation_line.sponsorship_mechanism_id
if not sponsorship:
raise ValidationError(_("No sponsorship found for this donation detail line."))
# Update the Benefit on the donation detail line
donation_line.write({
'benefit_id': self.benefit_id.id,
'benefit_ids': [(6, 0, [self.benefit_id.id])],
})
(donation_line.benefit_id | donation_line.benefit_ids).sudo().write({
'sponsor_related_id': donation_line.sponsor_id.id,
'kafala_status': 'have_kafala'
})
# Post message to the donation detail line chatter
message_body = _(
"Add Benefit: %s"
) % (new_benefit_name)
donation_line.message_post(
body=message_body,
subject=_("Add Benefit"),
message_type='notification',
)
_logger.info(
"Add Benefit on donation line : %s",
new_benefit_name
)
return {
'type': 'ir.actions.client',
'tag': 'display_notification',
'params': {
'title': _('Success'),
'message': _('Benefit has been successfully %s') % (
new_benefit_name
),
'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'}

Some files were not shown because too many files have changed in this diff Show More