odex25_standard/odex25_benefit/odex_benefit/models/benefit.py

2790 lines
138 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
import logging
from datetime import datetime, date
from dateutil.relativedelta import relativedelta as rd
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
import qrcode
import base64
from io import BytesIO
import re
from odoo.osv import expression
SAUDI_MOBILE_PATTERN = "(^(05|5)(5|0|3|6|4|9|1|8|7)([0-9]{7})$)"
ALPHABETIC_PATTERN = "^[\u0600-\u065F\u066A-\u06EF\u06FA-\u06FFA-Za-z ]+$"
_logger = logging.getLogger(__name__)
class GrantBenefitProfile(models.Model):
_name = 'grant.benefit'
_description = "Benefits - Profiles"
_inherit = ['mail.thread', 'mail.activity.mixin']
_inherits = {'res.partner': 'partner_id'}
_order = 'create_date desc'
def get_url(self):
return "wwww"
#def name_get(self):
# result = []
# for rec in self:
# if rec.name and rec.code:
# display_name = f"{rec.code} - {rec.name}"
# result.append((rec.id, display_name))
# else:
# result.append((rec.id, rec.name or rec.code or ""))
# return result
@api.model
def _name_search(self, name, args=None, operator='ilike', limit=100, name_get_uid=None):
args = args or []
name = name.strip() if name else ""
if operator == "ilike" and not name:
domain = []
else:
domain = ["|", "|", "|",
("name", operator, name),
("code", operator, name),
("sms_phone", operator, name),
("father_id_number", operator, name),
]
return self._search(expression.AND([domain, args]), limit=limit, access_rights_uid=name_get_uid)
profile_step_count = fields.Integer()
complete_registration_step = fields.Char(string="Complete Registration Step")
complete_registration_done = fields.Boolean('Does Complete Registration Done ?')
partner_id = fields.Many2one('res.partner', string='partner', required=True, ondelete="cascade")
code = fields.Char(string="Code", copy=False, default=lambda x: _('New'))
benefit_type = fields.Selection([('benefit', 'benefit'), ('orphan', 'orphan'), ('widow', 'widow')
], string='Benefit Type', tracking=True)
mother_status = fields.Selection(string='Mother Status', related="mother_family_member_id.member_status")
mother_salary_certificate = fields.Many2many('ir.attachment', 'mother_member_salary_cert_rel', 'mother_grant_benefit_id', 'attachment_id',
string="Salary Certificate")
phone2 = fields.Char(string="Phone2")
relative_phone = fields.Char(string="Relative Phone")
relative_relation = fields.Char(string="Relative Relation")
sms_phone = fields.Char(string="Contact Phone",tracking=True)
name_in_bank = fields.Char()
family_bank = fields.Many2one('res.partner.bank')
acc_number = fields.Char('Account Number',copy=False,tracking=True)
acc_holder_name = fields.Char('Account Holder Name')
acc_holder_id_number = fields.Char(string="Account Holder ID Number")
bank_id = fields.Many2one("res.bank",string='Bank')
account_relation = fields.Many2one('relation.settings',string="Account Owner Relation")
orphan_status = fields.Selection(
selection=[('father', 'Father-Orphan'), ('mother', 'Mother-Orphan'), ('parent', 'Parent-Orphan'), ],
compute="_compute_orphan_Type", store=True)
iban_attach = fields.Many2many('ir.attachment',
relation="ir_iban_attach_rel",
column1="iban",
column2="name",
string="Iban Attach")
id_number_attach = fields.Many2many('ir.attachment',
relation="ir_id_number_attach_rel",
column1="id_number",
column2="name",
string="Id Number Attach")
instrument_number = fields.Char()
instrument_attach = fields.Many2many('ir.attachment',
relation="ir_instrument_attach_rel",
column1="instrument_number",
column2="name",
string="Instrument Attach")
step = fields.Integer('Step')
has_needs = fields.Boolean(compute='_onchange_is_has_needs',
store=True) # This boolean filed for check if benefit has need in
# Job
job_position = fields.Char()
job_department = fields.Char()
job_company = fields.Char()
# login info
user_id = fields.Many2one('res.users', string="User")
password = fields.Char('Password')
# Category And Family
benefit_category_id = fields.Many2one('benefit.category', string='Benefit Category', compute="get_benefit_category",store=True,tracking=True)
benefit_category_old = fields.Many2one('benefit.category', string='Family category in the old system')
family_id = fields.Many2one('benefit.family', string='Benefit Family')
# address
housing_id = fields.Many2one('benefit.housing', string='Benefit Housing')
lat = fields.Float(string='Lat', digits=(16, 5))
lon = fields.Float(string='Long', digits=(16, 5))
block = fields.Char(string='block')
street = fields.Char(string='street')
house_number = fields.Char(string='house number')
floor = fields.Char(string='floor')
housing_number = fields.Char(string='housing number')
rent_amount = fields.Float(string='Rent Amount',compute='_compute_rent_from_contract',store=True)
estimated_rent_amount = fields.Float(string="Estimated Rent Amount", compute="_compute_estimated_rent_amount",store=True)
housing_type = fields.Selection([
('apartment', 'apartment'),
('villa', 'villa'),
('popular_house', 'popular house'),
('tent', 'tent'),
('Appendix', 'Appendix'), ], default='apartment',tracking=True)
property_instrument_number = fields.Char(string='Property Instrument number')
property_instrument_attach = fields.Many2many('ir.attachment','rel_property_instrument_attach_attachment','benefit_id','attachment_id',string='Property Instrument Attach')
electricity_attach = fields.Many2many('ir.attachment','rel_electricity_attach_attachment','benefit_id','attachment_id',string='Electricity Attach',compute='_compute_rent_from_contract',store=True,)
property_instrument_date = fields.Date(string='Property Instrument Date')
location_url = fields.Char(string='Location URL')
location = fields.Char(string='location')
rooms_number = fields.Integer('Rooms Number')
water_bill_account_number = fields.Char(string='water Bill Account Number', )
electricity_bill_account_number = fields.Char(string='Electricity Bill Account Number')
domestic_labor_ids = fields.Many2many('domestic.labor')
responsible = fields.Selection(string='responsible', selection=[('father', 'Father'),
('mother', 'mother'),
('other', 'other')], required=False, )
responsible_id = fields.Many2one('grant.benefit', domain="[('is_responsible','=',True)]", string='', required=False)
qr_code = fields.Binary( attachment=True, compute='_compute_qr_code')
## car data
car_ids = fields.One2many('cars.line', 'benefit_id')
car_count = fields.Integer(compute='_onchange_car_count')
# compute = 'count_car'
####clothing data #
cloth_ids = fields.One2many('benefit.cloth', 'benefit_id')
expenses_request_ids = fields.One2many('benefit.expenses', 'benefit_id')
expenses_ids = fields.One2many('expenses.line', 'benefit_id')
mother_expenses_ids = fields.One2many('expenses.line','mother_benefit_id',string="Mother Commitments / Expenses")
# Father's case and his data # Birth Date # Address # dead data
# Father's case and his data
# family_name = fields.Char(string="Family Name", tracking=True)
benefit_partner_name = fields.Char(string="Name",related='partner_id.name',store=True)
# father_name = fields.Char(string="Father First Name", tracking=True)
# father_second_name = fields.Char(string="Father Second Name", tracking=True)
# father_third_name = fields.Char(string="Father Third Name", tracking=True)
# father_family_name = fields.Char(string="Father Family Name", tracking=True)
father_id_number = fields.Char(string="Id Number", tracking=True)
father_marital = fields.Selection(
[('single', _('Single')), ('married', _('Married')), ('widower', _('Widower')), ('divorced', _('Divorced'))],
_('Marital Status'), default='single', tracking=True)
father_job_id = fields.Many2one('job.settings')
father_job_id_not_defined = fields.Boolean(related="father_job_id.not_defined")
father_job = fields.Char(string='Father Job')
father_id_number_type = fields.Selection([('citizen', _('Citizen')),('resident', _('Resident')),('visitor', _('Visitor'))],string='Father ID number type')
father_birth_date = fields.Date(string="Birth Date")
father_age = fields.Integer(string="Age", compute='_compute_get_father_age')
father_country_id = fields.Many2one('res.country', 'Father Nationality', tracking=True)
father_city_id = fields.Many2one('res.country.city', string='City')
father_dead_reason_id = fields.Many2one('death.reason.settings', string='Dead Reason', required=False)
father_dead_reason_id_not_defined = fields.Boolean(related='father_dead_reason_id.not_defined')
father_dead_reason = fields.Char(string='Dead Reason', required=False)
father_dead_date = fields.Date(string="Father Dead Date")
father_dead_country_id = fields.Many2one('res.country', string='Father Dead Country', tracking=True)
father_dead_country_id_code = fields.Char(related='father_dead_country_id.code')
father_dead_city_id = fields.Many2one('res.country.city', string='Father Dead City',domain="[('country_id', '=', father_dead_country_id)]")
father_dead_res_city_id = fields.Many2one('res.country.city', string='Father Dead City',domain="['|', ('country_id', '=', father_dead_country_id), ('country_id', '=', False)]")
father_dead_city = fields.Char(string='Father Dead City')
father_dead_certificate = fields.Many2many('ir.attachment', 'rel_father_dead_attachment','benefit_id','attachment_id',string='Father Dead Certificate')
# Mother's case and her data # Birth Date # Address # dead data
mother_relation = fields.Selection(
[('mother', _('Mother')), ('replacement_mother', _('Replacement Mother'))])
mother_relationn = fields.Many2one('relation.settings',domain="['|',('relation_type','=','mother'),('relation_type','=','replacement_mother')]")
replacement_mother_relation = fields.Many2one('relation.settings',domain="[('relation_type','=','replacement_mother')]")
mother_id = fields.Many2one('grant.benefit', domain="[('benefit_type','!=','orphan'),('gender','=','female')]")
mother_name = fields.Char(string="Mother Name", tracking=True)
mother_second_name = fields.Char(string="Mother Second Name", tracking=True)
mother_third_name = fields.Char(string="Mother Third Name", tracking=True)
mother_family_name = fields.Char(string="MotherFamily Name", tracking=True)
mother_country_id = fields.Many2one('res.country', 'Mother Nationality', tracking=True)
mother_id_number = fields.Char(string="Id Number", tracking=True)
mother_id_number_type = fields.Selection([('citizen', _('Citizen')),('resident', _('Resident')),('visitor', _('Visitor'))],string='Mother ID number type')
mother_marital = fields.Selection(
[('married', _('Married')), ('widower', _('Widower')), ('divorced', _('Divorced')),
('divorced_from_another_man', _('Divorced From Another Man'))
, ('prisoner', _('Prisoner')), ('dead', _('Dead')), ('hanging', _('Hanging'))],
_('Marital Status'))
mother_marital_conf = fields.Many2one('marital.status',string='Mother Marital')
mother_is_dead = fields.Boolean(string='Mother Is Dead?',related='mother_marital_conf.is_dead')
mother_dead_country_id = fields.Many2one('res.country', string='Mother Dead Country', tracking=True)
mother_dead_country_id_code = fields.Char(related='mother_dead_country_id.code')
mother_dead_city_id = fields.Many2one('res.country.city', string='Mother Dead City',domain="[('country_id', '=', mother_dead_country_id)]")
mother_dead_reason_id = fields.Many2one('death.reason.settings', string='Mother Dead Reason', required=False)
mother_dead_reason_id_not_defined = fields.Boolean(related='mother_dead_reason_id.not_defined')
mother_dead_reason = fields.Char(string='Mother Dead Reason', required=False)
mother_dead_res_city_id = fields.Many2one('res.country.city', string='Mother Dead City',domain="[('country_id', '=', mother_dead_country_id)]")
mother_dead_city = fields.Char(string='Mother Dead City')
mother_location = fields.Selection(
[('with_husband_and_children', _('With Husband And Children')), ('with_children', _('With Children')),
('not_live_with_children', _('Not live with children'))], string='Mother Location')
mother_location_conf = fields.Many2one('location.settings',string='Mother Location',domain="[('location_type','=','mother_location')]")
is_mother_work = fields.Boolean('Is Mother Work?')
mother_has_disabilities = fields.Boolean('Has Disabilities?')
mother_income = fields.Float("Mother Income", digits=(16, 0),compute='calculate_income', store=True,tracking=True)
mother_net_income = fields.Float(string="Mother Net Income",compute='_compute_mother_net_income',
store=True,help="Mother gross income minus her deducted expenses and monthly debt installments")
mother_birth_date = fields.Date(string="Birth Date")
mother_age = fields.Integer(string="Age", compute='_compute_get_mother_age')
mother_city_id = fields.Many2one('res.country.city', string='City')
mother_dead_reason = fields.Char(string='Dead Reason', required=False)
mother_dead_date = fields.Date(string="Mother Dead Date")
mother_dead_certificate = fields.Many2many('ir.attachment', 'rel_mother_dead_attachment','benefit_id','attachment_id',string='Mother Dead Certificate')
mother_family_member_id = fields.Many2one('family.member', string='Mother Family Member', domain="[('id','in',member_ids)]")
replacement_mother_family_member_id = fields.Many2one('family.member', string='Mother Family Member', domain="[('id','in',member_ids)]")
member_ids = fields.One2many('family.member', 'benefit_id')
# orphan
orphan_ids = fields.Many2many('grant.benefit', 'orphan_list', 'id_number', 'mother_id',
compute='_orphan_list_compute')
orphan_count = fields.Integer(
string='',
required=False)
# widows and divorcees
widows_ids = fields.One2many('widow.family', 'benefit_id', string='Widows', required=False)
divorcee_ids = fields.One2many('divorcee.family', 'benefit_id', string='divorcee', required=False)
# Husband info
husband_name = fields.Char('Husband')
husband_id = fields.Char('Husband ID')
date_death_husband = fields.Date()
date_divorcee = fields.Date()
# Education_data
mother_education_status_ids = fields.One2many('education.status', 'mother_grant_benefit_id')
mother_diseases_attachment_ids = fields.One2many('ir.attachment', 'mother_grant_benefit_id', string='Diseases Attachments',domain=[('diseases_id', '!=', False)])
mother_disabilities_attachment_ids = fields.One2many('ir.attachment', 'mother_grant_benefit_id', string='Disabilities Attachments',domain=[('disabilities_id', '!=', False)])
education_status = fields.Selection(
string='Education Status',
selection=[('educated', 'educated'), ('illiterate', 'illiterate')],
defualt='illiterate'
)
case_study = fields.Selection(string='Case Study',
selection=[('continuous', 'continuous'), ('intermittent', 'intermittent'),
('graduate', 'Graduate')])
illiterate_reason = fields.Char(string='Illiterate Reason')
intermittent_reason = fields.Many2one('education.illiterate.reason',string='Intermittent Reason')
education_entity = fields.Selection(string='Education Entity', selection=[('governmental', 'Governmental'),
('special', 'Special')])
education_start_date = fields.Date(string='Education Start Date')
education_end_date = fields.Date(string='Education End Date')
educational_certificate = fields.Many2many('ir.attachment','rel_educational_certificate_attachment','benefit_id','attachment_id',string='Educational Certificate')
last_education_entity = fields.Selection(string='Last Education Entity',
selection=[('governmental', 'Governmental'),
('special', 'Special')])
entities = fields.Many2one("res.partner", string='Entity')
last_entities = fields.Many2one("res.partner", string='Last Entity')
education_levels = fields.Many2one("education.level", string='Education Levels')
last_education_levels = fields.Many2one("education.level", string='Last Education Levels')
nearest_literacy_school = fields.Char(string='The Nearest Literacy School', required=False)
literacy_school_note = fields.Text(string="Literacy School Note", required=False)
classroom = fields.Many2one('education.classroom', string='Classroom')
last_classroom = fields.Many2one('education.classroom', string='Last Classroom')
degree = fields.Many2one('education.result', string='Degree')
last_degree = fields.Many2one('education.result', string='Last Degree')
percentage = fields.Float(string="Percentage%")
last_percentage = fields.Float(string="Last Percentage%")
last_education_start_date = fields.Date(string='Last Education Start Date')
last_education_end_date = fields.Date(string='Last Education End Date')
last_educational_certificate = fields.Many2many('ir.attachment','rel_last_educational_certificate_attachment','benefit_id','attachment_id',string='Last Educational Certificate')
end_date = fields.Date('End Date')
specialization_ids = fields.Many2one('specialization.specialization', string='specialization')
last_specialization_ids = fields.Many2one('specialization.specialization', string='Last Specialization')
weak_study = fields.Many2many('study.material',relation='grant_benefit_weak_study_rel',string='Weak Study')
educational_institution_information = fields.Char('Educational institution information')
graduation_status = fields.Selection(string='Education Status', selection=[('graduated', 'graduated'),
('ungraduated', 'ungraduated'),
('intermittent', 'intermittent')])
graduation_date = fields.Date('Graduation Date')
reasons_for_interruption = fields.Char('Reasons for interruption')
interruption_date = fields.Date('Interruption Date')
# attach
study_document_attached = fields.Many2many('ir.attachment','rel_study_document_attachment','benefit_id','attachment_id',string="Study Document Attached")
acadimec_regsteration_attached = fields.Binary(string="Acadimec Regsteration Attached",attachment=True )
Transcript_attached = fields.Binary(string="Transcript Attached",attachment=True )
# Quran memorize
quran_memorize_name = fields.Char(string='')
number_parts = fields.Integer(string='')
# is craft skills
craft_skill_ids = fields.One2many('craft.skills', 'benefit_id', string='Craft Skill')
training_inclinations_ids = fields.One2many('training.inclinations', 'benefit_id', string='Training Inclinations')
### alhaju , amra and zakat fitr ####
amra_date = fields.Date(string='')
######################
food_surplus_type = fields.Many2many('food.surplus.type', string='')
# Income and salary
salary_ids = fields.One2many('salary.line', 'benefit_id', string='')
mother_salary_ids = fields.One2many('salary.line', 'mother_benefit_id', string="Mother Income")
# Commercial Record
is_active = fields.Boolean(string='')
commercial_record_code = fields.Char(string='Commercial Record Code')
commercial_record_attach = fields.Binary(attachment=True)
commercial_record_amount = fields.Float(string='')
# other_associations
associations_ids = fields.One2many('associations.line', 'benefit_id', string='')
benefit_behavior_ids = fields.One2many('benefit.behaviors', 'benefit_id', string='')
# Refuse Reason
first_refusal_reason = fields.Text(string='First Refusal Reason', tracking=True)
first_refuse_date = fields.Date(tracking=True)
final_refusal_reason = fields.Text(string='Final Refusal Reason', tracking=True)
final_refuse_date = fields.Date(tracking=True)
black_list_reason = fields.Text(string='Black List Reason', tracking=True)
black_list_message = fields.Text(string='Black List Message')
# health information#
# diseases
hospital_id = fields.Many2one('hospital.hospital', string='')
hospital_attach = fields.Binary(attach=True)
diseases_type = fields.Selection(string='Diseases Type', selection=[('chronic', 'chronic'),
('psycho', 'psycho'),
('organic', 'organic')])
treatment_used = fields.Char(string='')
treatment_amount = fields.Float(string='')
is_treatment_amount_country = fields.Boolean(string='')
treatment_amount_country_Monthly = fields.Float(string='')
treatment_amount_country_description = fields.Text(string="")
treatment_amount_country_attach = fields.Binary(attachment=True)
# Hospital information
hospital_card = fields.Binary(attachment=True)
# disability
disability_type = fields.Char(string='')
disability_accessories = fields.Char(string='')
disability_attach = fields.Binary(attachment=True)
disability_amount = fields.Float()
# Medical Insurance
insurance_type = fields.Many2one('insurance.type')
insurance_company = fields.Many2one('insurance.company')
insurance_amount = fields.Float()
insurance_attach = fields.Binary(attachment=True)
insured_party = fields.Many2one('res.company')
# Weight rate
weight = fields.Float('Weight')
height = fields.Float('Height')
p_weight = fields.Float('Overweight', store=True, compute="_compute_obesity_rate", )
sport_ids = fields.One2many('sport.line', 'benefit_id')
wife_number = fields.Integer(string="Wife")
child_number = fields.Integer(string="Children")
old_stage = fields.Char(string='old Stage', tracking=True)
dead_certificate = fields.Binary(string="Certificate",attachment=True)
dead_certificate_date = fields.Date(string="Certificate Date")
approve_date = fields.Date(string="Approve Date")
benefit_needs_value = fields.Float()
benefit_needs_percent = fields.Float()
followers_total = fields.Integer(string="followers Total")
followers_out_total = fields.Integer(string="followers Total", )
expenses_total = fields.Integer(string="Expenses", compute="get_total_expenses",store=True)
#################################################################
# Boolean Fields to use in filters#TODO
#################################################################
is_responsible = fields.Boolean(string='') # Differentiate between a primary beneficiary and a dependent
father_is_life = fields.Boolean(string="Life")
mother_is_life = fields.Boolean(string="Life")
is_widows = fields.Boolean(string='is widows', required=False)
is_divorcee = fields.Boolean(string='is Divorcee', required=False)
is_want_education = fields.Boolean(string='is Want Education', required=False)
is_quran_memorize = fields.Boolean('memorize the quran ?')
is_craft = fields.Boolean(string='')
is_zakat_fitr = fields.Boolean(string='Zakat Al-Fitr')
has_car= fields.Boolean('Has Car?',compute='_onchange_car_count',store=True)
is_producer = fields.Boolean(string='Producer')
is_food_surplus = fields.Boolean(string='food surplus')
is_loans = fields.Boolean('loans')
is_al_al_bayt = fields.Boolean(string='Al al-Bayt')
is_commercial_record = fields.Boolean(string='Commercial Record')
is_other_associations = fields.Boolean(string='other associations?')
is_smoke = fields.Boolean('Smoke')
# health_status
is_diseases = fields.Boolean()
is_disability = fields.Boolean(string='')
is_insurance = fields.Boolean()
is_sport = fields.Boolean()
support_separation = fields.Boolean(string="Support Separation", tracking=True)
is_life = fields.Boolean(string="Life", default=True)
total_expenses = fields.Float('Total Expenses', compute="get_total_expenses",store=True,tracking=True)
total_income = fields.Float('Total Income', compute="get_total_income", store=True,tracking=True)
benefit_member_count = fields.Integer(string="Members count", compute="get_members_count",store=True)
non_member_count = fields.Integer(string="Non Benefit Members count", compute="get_members_count")
member_income = fields.Float(string="Member Income Average", compute="get_member_income",store=True,tracking=True)
request_activity_id = fields.Many2one('mail.activity')
state = fields.Selection([
('draft', 'Draft'),
('new', 'Researcher Assignment'),
('complete_info', 'Waiting for Researcher'),
('waiting_approve', 'Waiting for Operation Manager'),
('first_approve', 'Waiting for Branch Manager'),
('family_services_manager', 'Waiting Family Services Manager'),
('first_refusal', 'First Refusal'),
('second_approve', 'Second Approved'),
('refused', 'Refused'),
('temporary_suspended', 'Temporary Suspended'),
('suspended_second_approve', 'Suspended Second Approved'),
('exception_second_approve', 'Waiting for General Manager'),
('black_list', 'Black List'),
], string='state', default="draft", tracking=True, group_expand='_expand_states')
branch_custom_id = fields.Many2one('branch.settings', string="Branch",tracking=True)
branch_family_id = fields.Many2one('branch.settings', string="Family Branch",tracking=True)
branch_has_employees = fields.Boolean('Has Employees In branch',related="branch_custom_id.has_employees")
district_id = fields.Many2one('res.districts', string="District", domain="[('branch_custom_id','=',branch_custom_id)]",tracking=True)
meal_card = fields.Boolean(string="Meal Card",related="district_id.meal_card", store=True,related_sudo=True)
attachment_ids = fields.One2many('ir.attachment', 'benefit_id')
family_debits_ids = fields.One2many('family.debits', 'benefit_id')
mother_debits_ids = fields.One2many('family.debits','mother_benefit_id',string="Mother Debts")
researcher_id = fields.Many2one("committees.line", string="Researcher",tracking=True)
assigned_researcher_id = fields.Many2one('committees.line',string='Assigned Researcher',tracking=True)
auto_accept_for_member = fields.Boolean(string="Auto Accept For members", default=True)
last_visit_date = fields.Datetime(string='Last Visit Date')
# Benefit Housing Information
# housing_name = fields.Char(compute='_compute_get_name')
zip = fields.Char('Zip', change_default=True, readonly=False, store=True)
short_number = fields.Char(
readonly=False,
required=False,
states={
'second_approve': [('readonly', True)],
'complete_info': [('required', True)]
}
)
extra_code = fields.Char(
readonly=False,
required=False,
states={
'second_approve': [('readonly', True)],
}
)
zip = fields.Char('Zip', change_default=True, readonly=False, store=True)
# res_city_id = fields.Many2one('res.city', domain="[('country_city_id', '=', city_id)]")
# housing_city = fields.Char()
url = fields.Char()
url_html = fields.Html(
sanitize=False,
compute="get_html")
image = fields.Binary(string="", )
image_1 = fields.Binary(string="", )
image_2 = fields.Binary(string="", )
image_3 = fields.Binary(string="", )
image_4 = fields.Binary(string="", )
nearby_mosque = fields.Char(string='Nearby mosque')
housing_note = fields.Char(string='housing note')
note_neighborhood = fields.Char()
contract_num = fields.Char(string="Contract Number",compute='_compute_rent_from_contract',store=True)
rent_start_date = fields.Date(string='Rent Start Date',compute='_compute_rent_from_contract',store=True)
rent_end_date = fields.Date(string='Rent End Date',compute='_compute_rent_from_contract',store=True)
rent_attachment = fields.Many2many('ir.attachment','rel_rent_attachment_attachment','benefit_id','attachment_id',string='Rent Attachment',compute='_compute_rent_from_contract',store=True,)
national_address_attachment = fields.Many2many('ir.attachment','rel_national_address_attachment','benefit_id','attachment_id',string='National Address Attachment')
payment_type = fields.Selection(
[
('1', 'Yearly'),
('2', 'Half-yearly'),
('4', 'Quarterly'),
('12', 'Monthly')
],
string='Payment Type',
compute='_compute_rent_from_contract',store=True,
)
housing_cat = fields.Selection([
('excellent', 'Excellent'),
('good', 'Good'),
('bad', 'Bad'),
('collapsible', 'Collapsible'),
('collapsed', 'Collapsed')])
property_type = fields.Selection([
('ownership', 'ownership'),
('rent', 'rent'),
('charitable', 'charitable'),
('ownership_shared', 'Ownership Shared'),
('rent_shared', 'Rent Shared')])
property_type_id = fields.Many2one('property.type.settings',string="Property Type",tracking=True)
property_type_code = fields.Selection([
('ownership', 'Ownership'),
('rent', 'Rent')
], string="Property Type Code",related='property_type_id.type', store=True)
room_ids = fields.One2many('benefit.housing.rooms', inverse_name='housing_id')
request_producer_id = fields.Many2one('res.partner',string='Request Producer', compute='_compute_request_producer_id')
request_producer = fields.Many2one('res.partner',string='Request Producer',default=lambda self: self.env.user.partner_id)
request_producer_relation = fields.Many2one('relation.settings',string='Request Producer Relation',domain="[('relation_type','=','other relation')]")
# Suspend
is_excluded_suspension = fields.Boolean('Excluded from suspension?')
suspend_reason = fields.Many2one('suspend.reason', string='Suspend Reason')
reason = fields.Text(string='Reason')
suspend_description = fields.Text(string='Suspend Description')
suspend_attachment = fields.Many2many('ir.attachment','rel_suspend_attachment_attachment','benefit_id','attachment_id',string='Suspend Attachment')
suspend_type = fields.Selection(
selection=[('temporarily_suspend', 'Temporarily Suspended'), ('suspend', 'Suspend')], string="Suspend Type")
suspend_method = fields.Selection(selection=[('manual', 'Manual'), ('auto', 'Auto')], string="Suspend Method")
#Exception fields
exception_reason = fields.Many2one('exception.reason', string='Exception Reason')
exception_description = fields.Text(string='Exception Description')
exception_type = fields.Selection(
selection=[('temporarily_exception', 'Temporarily Exception'), ('permanent_exception', 'Permanent Exception')],
string="Exception Type")
exception_attachment = fields.Many2many('ir.attachment','rel_exception_attachment','benefit_id','attachment_id',string='Exception Attachment')
exception_start_date = fields.Datetime(string='Exception Start Date')
exception_end_date = fields.Datetime(string='Exception End Date')
# sponsor_id = fields.Many2one('res.partner', string='Sponsor',domain="[('account_type','=','sponsor')]")
sponsor_id = fields.Many2one('res.partner', string='Sponsor',domain="[('is_sponsor_portal', '=', True)]")
family_monthly_income = fields.Float(string="Family Monthly Income", compute='_get_family_monthly_values')
family_monthly_meals = fields.Float(string="Family Monthly Meals", compute='_get_family_monthly_values')
family_monthly_clotting = fields.Float(string="Family Monthly Clotting", compute='_get_family_monthly_values')
total_family_expenses = fields.Float(string="Total Family Expenses", compute='_get_family_monthly_values')
total_move_lines = fields.Float(string="Total Move Lines", compute='_get_total_move_lines')
visit_location_count = fields.Integer(string="Visit Location Count", compute='_compute_visit_location_count')
total_service_requests = fields.Integer(compute='_get_total_service_requests')
total_seasonal_service_requests = fields.Integer(compute='_get_total_seasonal_service_requests')
invoices_count = fields.Integer(string="Invoices Count", compute='_get_invoices_count')
required_attach = fields.Selection(selection=[('true', 'True'), ('false', 'False')],compute='get_required_attach',store=True)
income_required_attach = fields.Selection(selection=[('true', 'True'), ('false', 'False')],compute='get_income_required_attach',store=True)
sa_iban = fields.Char('SA',default='SA',readonly=True)
iban_document = fields.Many2many('ir.attachment', 'rel_iban_document', 'benefit_id', 'attachment_id')
#Replacement Mother
add_replacement_mother = fields.Boolean('Add Replacement Mother?')
replacement_mother_name = fields.Char(string="Replacement Mother Name", tracking=True)
replacement_mother_second_name = fields.Char(string="Replacement Mother Second Name", tracking=True)
replacement_mother_third_name = fields.Char(string="Replacement Mother Third Name", tracking=True)
replacement_mother_family_name = fields.Char(string="Replacement Mother Family Name", tracking=True)
replacement_mother_country_id = fields.Many2one('res.country', 'Replacement Mother Nationality', tracking=True)
replacement_mother_id_number = fields.Char(string="Replacement Mother Id Number", tracking=True)
replacement_mother_id_number_type = fields.Selection([('citizen', _('Citizen')),('resident', _('Resident')),('visitor', _('Visitor'))],string='Replacement Mother ID number type')
replacement_mother_marital_conf = fields.Many2one('marital.status', string='Replacement Mother Marital')
replacement_mother_is_dead = fields.Boolean(string='Replacement Mother Is Dead?',related='replacement_mother_marital_conf.is_dead')
replacement_mother_dead_country_id = fields.Many2one('res.country', string='Replacement Mother Dead Country', tracking=True)
replacement_dead_country_id_code = fields.Char(related='replacement_mother_dead_country_id.code')
replacement_mother_dead_city_id = fields.Many2one('res.country.city', string='Replacement Mother Dead City',domain="[('country_id', '=', replacement_mother_dead_country_id)]")
replacement_dead_reason_id = fields.Many2one('death.reason.settings', string='Replacement Mother Dead Reason', required=False)
replacement_dead_reason_id_not_defined = fields.Boolean(related='replacement_dead_reason_id.not_defined')
replacement_dead_reason = fields.Char(string='Replacement Mother Dead Reason', required=False)
replacement_dead_res_city_id = fields.Many2one('res.country.city', string='Replacement Mother Dead City',domain="[('country_id', '=', replacement_dead_country_id)]")
replacement_dead_city = fields.Char(string='Replacement Mother Dead City')
replacement_mother_location = fields.Selection(
[('with_husband_and_children', _('With Husband And Children')), ('with_children', _('With Children')),
('not_live_with_children', _('Not live with children'))], string='Replacement Mother Location')
replacement_mother_location_conf = fields.Many2one('location.settings',string='Replacement Mother Location',domain="[('location_type','=','mother_location')]")
replacement_is_mother_work = fields.Boolean('Is Replacement Mother Work?')
replacement_mother_has_disabilities = fields.Boolean('Has Disabilities?')
replacement_mother_income = fields.Float("Replacement Mother Income")
replacement_mother_birth_date = fields.Date(string="Replacement Mother Birth Date")
replacement_mother_age = fields.Integer(string="Replacement Mother Age", compute='_compute_get_replacement_mother_age')
replacement_mother_city_id = fields.Many2one('res.country.city', string='City')
replacement_mother_dead_reason = fields.Char(string='Dead Reason', required=False)
replacement_mother_dead_date = fields.Date(string="Replacement Mother Dead Date")
replacement_mother_dead_certificate = fields.Many2many('ir.attachment', 'rel_replacement_mother_dead_attachment', 'benefit_id', 'attachment_id', string='Replacement Mother Dead Certificate')
replacement_mother_status = fields.Selection(string='Replacement Mother Status', related="replacement_mother_family_member_id.member_status")
replacement_mother_salary_certificate = fields.Many2many('ir.attachment', 'replacement_mother_member_salary_cert_rel',
'replacement_mother_grant_benefit_id', 'attachment_id',
string="Salary Certificate")
# Education_data for replacement mother
replacement_education_status_ids = fields.One2many('education.status', 'replacement_grant_benefit_id')
replacement_education_status = fields.Selection(
string='Education Status',
selection=[('educated', 'educated'), ('illiterate', 'illiterate')],
default='illiterate'
)
replacement_case_study = fields.Selection(string='Case Study',
selection=[('continuous', 'continuous'), ('intermittent', 'intermittent'),
('graduate', 'Graduate')])
replacement_illiterate_reason = fields.Char(string='Illiterate Reason')
replacement_intermittent_reason = fields.Many2one('education.illiterate.reason', string='Intermittent Reason')
replacement_education_entity = fields.Selection(string='Education Entity', selection=[('governmental', 'Governmental'),
('special', 'Special')])
replacement_entities = fields.Many2one("res.partner", string='Entity')
replacement_specialization_ids = fields.Many2one('specialization.specialization', string='specialization')
replacement_classroom = fields.Many2one('education.classroom', string='Classroom')
replacement_degree = fields.Many2one('education.result', string='Degree')
replacement_percentage = fields.Float(string="Percentage%")
replacement_education_start_date = fields.Date(string='Education Start Date')
replacement_education_end_date = fields.Date(string='Education End Date')
replacement_last_education_entity = fields.Selection(string='Last Education Entity',
selection=[('governmental', 'Governmental'),
('special', 'Special')])
replacement_last_entities = fields.Many2one("res.partner", string='Last Entity')
replacement_education_levels = fields.Many2one("education.level", string='Education Levels')
replacement_last_education_levels = fields.Many2one("education.level", string='Last Education Levels')
replacement_last_specialization_ids = fields.Many2one('specialization.specialization', string='Last Specialization')
replacement_educational_certificate = fields.Many2many('ir.attachment','rel_replacement_educational_certificate_attachment','benefit_id','attachment_id',string='Educational Certificate')
replacement_last_classroom = fields.Many2one('education.classroom', string='Last Classroom')
replacement_last_degree = fields.Many2one('education.result', string='Last Degree')
replacement_last_percentage = fields.Float(string="Last Percentage%")
replacement_last_education_start_date = fields.Date(string='Last Education Start Date')
replacement_last_education_end_date = fields.Date(string='Last Education End Date')
replacement_last_educational_certificate = fields.Many2many('ir.attachment','rel_replacement_last_educational__certificate_attachment','benefit_id','attachment_id',string='Last Educational Certificate')
replacement_weak_study = fields.Many2many('study.material',relation='grant_benefit_replacement_weak_study_rel',string='Weak Study')
replacement_mother_diseases_attachment_ids = fields.One2many('ir.attachment', 'replacement_mother_grant_benefit_id', string='Diseases Attachments',domain=[('diseases_id', '!=', False)])
replacement_mother_disabilities_attachment_ids = fields.One2many('ir.attachment', 'replacement_mother_grant_benefit_id',string='Disabilities Attachments',domain=[('disabilities_id', '!=', False)])
sponsorship_id = fields.Many2one('takaful.sponsorship',string='Sponsorship')
#check if Account Holder is Family memeber of not
is_family_member = fields.Boolean(string='Is Family member?' , help="check if Account Holder is Family memeber",default=True)
family_member_id = fields.Many2one('family.member', string='Account Holder Name', domain="[('id','in',member_ids)]")
owner_identity_attachment_ids = fields.Many2many('ir.attachment', 'rel_identity_attachment','benefit_id','attachment_id',string='Account holder identity')
family_approval_attachment_ids = fields.Many2many('ir.attachment', 'rel_approval_attachment','benefit_id','attachment_id',string='Family approval of transfer')
seasonal_service_id = fields.Many2one('seasonal.service', string="Seasonal Service")
is_from_portal = fields.Boolean(string='is Created from Portal?', default=False, readonly=True)
applicant_name = fields.Char(readonly=True)
doc_count = fields.Integer(compute='_compute_attached_docs_count', string="Number of documents attached")
action_type = fields.Selection(selection=[
('new', 'New'),
('edit_info', 'Edit Information'),
('approved', 'Approved'),
('suspended', 'Suspended'),
('resume_from_temporary', 'Resume from Temporary Suspension'),
('resume_from_final', 'Resume from Final Suspension'),
('exception', 'Exception'),
], string='Action Type', default='new', tracking=True)
contact_type = fields.Selection([
('email', 'Email'),
('sms', 'SMS'),
], string='Contact Type',default='sms')
company_id = fields.Many2one('res.company', default=lambda self: self.env.company)
currency_id = fields.Many2one(
comodel_name='res.currency',
string="Company Currency",
related='company_id.currency_id')
family_edit = fields.Boolean(string='Family Edit', default=False)
family_return_reason = fields.Text(string="Family Return Reason")
last_disbursement_date = fields.Date(string="Last disbursement date", readonly=True)
total_father_families = fields.Integer(string="Father Families", compute='_compute_total_families')
total_mother_families = fields.Integer(string="Mother Families", compute='_compute_total_families')
total_replacement_mother_families = fields.Integer(string="Replacement Mother Families", compute='_compute_total_families')
final_suspend_date = fields.Date(string="Final Suspend Date")
resume_reason_id = fields.Many2one('suspend.reason', string='Return Reason')
resume_date = fields.Date(string="Return Date")
resume_notes = fields.Text(string="Return Notes")
rent_contract_ids = fields.One2many('rent.contract', 'family_id',string='Rent Contracts')
rent_contract_count = fields.Integer(
string="Number of Rent Contracts",
compute='_compute_rent_contract_count',
store=True
)
current_rent_contract_id = fields.Many2one('rent.contract',string='Current Active Rent Contract',compute='_compute_current_rent_contract',store=True,)
notes = fields.Html(string='Notes', tracking=True)
color = fields.Integer(string="Color Index",related='benefit_category_id.color')
decoration_color = fields.Selection([
('danger', 'Red'),
('success', 'Green'),
('warning', 'Orange'),
('info', 'Blue'),
('primary', 'Primary'),
('muted', 'Muted'),
],related='benefit_category_id.decoration_color')
_sql_constraints = [
('unique_code', "unique (code) WHERE state NOT IN ('draft', 'new')", 'This code already exists')
]
@api.depends('rent_contract_ids')
def _compute_rent_contract_count(self):
for record in self:
record.rent_contract_count = len(record.rent_contract_ids)
def action_view_all_rent_contracts(self):
self.ensure_one()
ctx = self.env.context.copy()
ctx.update({
'default_family_id': self.id,
'default_landlord_type': 'family'
})
return {
'name': _('Rent Contracts - Full Details'),
'type': 'ir.actions.act_window',
'res_model': 'rent.contract',
'view_mode': 'tree,form',
'domain': [('family_id', '=', self.id)],
'context': ctx,
'target': 'current',
}
@api.depends('rent_contract_ids', 'rent_contract_ids.state', 'rent_contract_ids.start_date')
def _compute_current_rent_contract(self):
for family in self:
if not family.rent_contract_ids:
family.current_rent_contract_id = False
continue
active_contracts = family.rent_contract_ids.filtered(
lambda c: c.state == 'active' and c.landlord_type == 'family'
).sorted('start_date', reverse=True)
family.current_rent_contract_id = active_contracts[:1] or False
@api.depends('member_ids', 'member_ids.member_status', 'add_replacement_mother',
'replacement_mother_family_member_id', 'replacement_mother_status', 'mother_family_member_id',
'mother_status','mother_marital_conf','mother_location_conf','mother_income')
def get_members_count(self):
for ben in self:
if ben.id:
ben.non_member_count = len(ben.member_ids.filtered(lambda x: x.member_status == 'non_benefit'))
ben.benefit_member_count = len(ben.member_ids.filtered(lambda x: x.member_status == 'benefit'))
if ben.add_replacement_mother and not ben.replacement_mother_family_member_id and ben.replacement_mother_status == 'benefit':
ben.benefit_member_count += 1
if not ben.mother_family_member_id and ben.mother_status == 'benefit':
ben.benefit_member_count += 1
else:
ben.benefit_member_count = 0.0
ben.non_member_count = 0.0
@api.depends('current_rent_contract_id')
def _compute_rent_from_contract(self):
for family in self:
contract = family.current_rent_contract_id
if contract:
family.contract_num = contract.name
family.rent_start_date = contract.start_date
family.rent_end_date = contract.end_date
family.rent_amount = contract.rent_amount
family.payment_type = contract.payment_type
family.rent_attachment = [(6, 0, contract.contract_attachment.ids)]
#family.electricity_attach = [(6, 0, contract.electricity_bill_attachment.ids)]
else:
family.contract_num = False
family.rent_start_date = False
family.rent_end_date = False
family.rent_amount = 0.0
family.payment_type = False
family.rent_attachment = [(5, 0, 0)]
#family.electricity_attach = [(5, 0, 0)]
def _sms_get_number_fields(self):
return ['sms_phone']
@api.onchange('family_member_id')
def _onchange_family_member_id(self):
for record in self:
if record.is_family_member and record.family_member_id:
record.acc_holder_name = record.family_member_id.name
record.acc_holder_id_number = record.family_member_id.member_id_number
else:
record.acc_holder_name = False
record.acc_holder_id_number = False
@api.depends('is_mother_work','mother_salary_ids','mother_expenses_ids','mother_debits_ids')
def _compute_mother_net_income(self):
for rec in self:
deductions = (
sum(rec.mother_expenses_ids.filtered('deduct_from_family_income').mapped('amount')) +
sum(rec.mother_debits_ids.filtered('deduct_from_family_income').mapped('monthly_installment'))
)
mother_income = sum(rec.mother_salary_ids.filtered(lambda e: e.approved and e.is_mother_salary).mapped('salary_amount'))
rec.mother_net_income = max(mother_income - deductions, 0.0)
def _compute_total_families(self):
for record in self:
record.total_father_families = self.search_count([('father_id_number','=',record.father_id_number),('id','!=',record.id)])
record.total_mother_families = self.search_count([('mother_id_number','=',record.mother_id_number),('id','!=',record.id)])
record.total_replacement_mother_families = self.search_count([('replacement_mother_id_number','=',record.replacement_mother_id_number),('id','!=',record.id)])
def action_open_related_father_families(self):
self.ensure_one()
return {
'name': _("Father Families"),
'type': 'ir.actions.act_window',
'res_model': 'grant.benefit',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_benefit.grant_benefit_tree').id, 'tree'),
(self.env.ref('odex_benefit.grant_benefit_form').id, 'form')],
'domain': [('father_id_number','=',self.father_id_number),('id','!=',self.id)],
'context': {'create': False},
}
def action_open_related_mother_families(self):
self.ensure_one()
return {
'name': _("Mother Families"),
'type': 'ir.actions.act_window',
'res_model': 'grant.benefit',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_benefit.grant_benefit_tree').id, 'tree'),
(self.env.ref('odex_benefit.grant_benefit_form').id, 'form')],
'domain': [('mother_id_number','=',self.mother_id_number),('id','!=',self.id)],
'context': {'create': False},
}
def action_open_related_replacement_mother_families(self):
self.ensure_one()
return {
'name': _("Replacement Mother Families"),
'type': 'ir.actions.act_window',
'res_model': 'grant.benefit',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_benefit.grant_benefit_tree').id, 'tree'),
(self.env.ref('odex_benefit.grant_benefit_form').id, 'form')],
'domain': [('replacement_mother_id_number','=',self.replacement_mother_id_number),('id','!=',self.id)],
'context': {'create': False},
}
def _expand_states(self, states, domain, order):
return [key for key, val in type(self).state.selection]
@api.constrains('short_number')
def _check_short_number(self):
pattern = re.compile(r'^[A-Za-z]{4}[0-9]{4}$')
for record in self:
if record.short_number and not pattern.match(record.short_number):
raise ValidationError(_("Short Number must be 4 letters followed by 4 digits (e.g., ABCD1234)."))
@api.constrains('father_name', 'father_second_name', 'father_third_name', 'father_family_name',
'mother_name', 'mother_second_name', 'mother_third_name', 'mother_family_name',
'replacement_mother_name','replacement_mother_second_name','replacement_mother_third_name','replacement_mother_family_name')
def _check_names_alphabetic(self):
char_fields = {
'father_name': _('Father First Name'),
'father_second_name': _('Father Second Name'),
'father_third_name': _('Father Third Name'),
'father_family_name': _('Father Family Name'),
'mother_name': _('Mother Name'),
'mother_second_name': _('Mother Second Name'),
'mother_third_name':_('Mother Third Name'),
'mother_family_name': _('MotherFamily Name'),
'replacement_mother_name': _('Replacement Mother Name'),
'replacement_mother_second_name': _('Replacement Mother Second Name'),
'replacement_mother_third_name': _('Replacement Mother Third Name'),
'replacement_mother_family_name': _('Replacement Mother Family Name')
}
for record in self:
for field_name, field_label in char_fields.items():
field_value = getattr(record, field_name)
if field_value and not re.match(ALPHABETIC_PATTERN, field_value.strip()):
raise ValidationError(
_("%s must contain only alphabetic characters and spaces. "
"Numbers and special characters are not allowed.") % field_label
)
@api.constrains('active', 'state')
def _prevent_archive_unless_allowed(self):
for rec in self:
if not rec.active and rec.state not in ['refused', 'suspended_second_approve', 'black_list']:
raise ValidationError(_(
"You can only archive the family if its status is: Refused, Final Suspension, or Blacklisted."
))
@api.depends('rent_amount','property_type_id','benefit_member_count', 'branch_custom_id.branch_type')
def _compute_estimated_rent_amount(self):
for rec in self:
estimated_rent_amount = 0.0
rent_line = False
if rec.property_type_id and rec.property_type_code == 'rent':
if rec.branch_custom_id.branch_type == 'branches':
rent_line = self.env['rent.lines'].search(
[('benefit_count', '=', rec.benefit_member_count)], order="estimated_rent_branches desc",limit=1)
if rent_line:
estimated_rent_amount = rent_line.estimated_rent_branches
else:
rent_line = self.env['rent.lines'].search(
[('benefit_count', '=', rec.benefit_member_count)], order="estimated_rent_governorate desc",limit=1)
if rent_line:
estimated_rent_amount = rent_line.estimated_rent_governorate
if rec.property_type_id.is_shared and rent_line and rent_line.discount_rate_shared_housing:
discount = rent_line.discount_rate_shared_housing / 100.0
estimated_rent_amount *= discount
rec.estimated_rent_amount = estimated_rent_amount / 12.0
def assign_sequence_to_all(self):
sequence = self.env['ir.sequence'].search([('code', '=', 'benefit.sequence')], limit=1)
if not sequence:
raise UserError(_("Sequence with code 'benefit.sequence' not found"))
sequence.sudo().write({'number_next': 1})
records = self.search([], order='create_date')
for rec in records:
code = self.env['ir.sequence'].sudo().next_by_code('benefit.sequence')
rec.with_context(force_website=True).write({'code':code})
def action_set_waiting_if_needed(self):
records = self.env['grant.benefit'].browse(self._context.get('active_ids', []))
print("hh")
for rec in records:
if rec.salary_ids:
for recored in rec.salary_ids:
if recored.state not in ['accepted', 'refused']:
recored.state = 'waiting'
if rec.expenses_ids:
for recorede in rec.expenses_ids:
if recorede.state not in ['accepted', 'refused']:
recorede.state = 'waiting'
@api.depends('request_producer')
def _compute_request_producer_id(self):
for rec in self:
rec.request_producer_id = rec.user_id.partner_id if rec.request_producer.id == rec.env.ref('base.public_partner').id else rec.request_producer
def validate_attachments(self):
for rec in self:
if not rec.owner_identity_attachment_ids and rec.is_family_member == False and rec.state == 'first_approve':
raise ValidationError(_("Account Holder Identity Attachment is required."))
if not rec.family_approval_attachment_ids and rec.is_family_member == False and rec.state == 'first_approve':
raise ValidationError(_("Family approval of transfer Attachment is required."))
def _validate_required_attachments(self):
"""Validate required Many2many attachments"""
for rec in self:
if not rec.father_dead_certificate:
raise ValidationError(_("Father Dead Certificate is required."))
if rec.state not in ['draft', 'new', 'complete_info'] and not rec._context.get('bypass_attachments_requirement', False) and not rec.national_address_attachment:
raise ValidationError(_("National Address Attachment is required."))
@api.constrains('father_birth_date', 'father_dead_date', 'mother_birth_date', 'replacement_mother_birth_date')
def _check_dates(self):
today = date.today()
for rec in self:
# Check that dates are not in the future
if rec.father_birth_date and rec.father_birth_date > today:
raise ValidationError("Father's Birth Date cannot be in the future.")
if rec.father_dead_date and rec.father_dead_date > today:
raise ValidationError("Father's Death Date cannot be in the future.")
if rec.mother_birth_date and rec.mother_birth_date > today:
raise ValidationError("Mother's Birth Date cannot be in the future.")
if rec.replacement_mother_birth_date and rec.replacement_mother_birth_date > today:
raise ValidationError("Replacement Mother's Birth Date cannot be in the future.")
# Check that father_dead_date is after father_birth_date
if (
rec.father_birth_date
and rec.father_dead_date
and rec.father_dead_date < rec.father_birth_date
):
raise ValidationError("Father's Death Date must be after the Birth Date.")
# @api.depends('attachment_ids')
# def get_required_attach(self):
# for rec in self.attachment_ids:
# if rec.is_required and not rec.datas:
# self.required_attach = None
# break
# elif rec.is_required and rec.datas:
# self.required_attach = 'true'
# elif rec.is_default and not rec.is_required and (rec.datas or not rec.datas):
# self.required_attach = 'true'
# else:
# self.required_attach = 'true'
@api.depends('attachment_ids.datas', 'attachment_ids.is_required', 'attachment_ids.is_default')
def get_required_attach(self):
bypass_verify_backend_require_attachs = self._context.get('bypass_verify_backend_require_attachs', False)
for record in self:
required_missing = False
for att in record.attachment_ids:
if (not bypass_verify_backend_require_attachs or att.show_in_portal) and att.is_required and not att.datas:
required_missing = True
break
if required_missing:
record.required_attach = 'false'
else:
record.required_attach = 'true'
def get_attached_domain(self):
self.ensure_one()
visit_location = self.env['visit.location'].search([('benefit_id', '=', self.id)]).ids
service_requests = self.env['service.request'].search([('family_id', '=', self.id)]).ids
family_complaints = self.env['family.complaints'].search([('family_id', '=', self.id)]).ids
hobby_ids = self.member_ids.mapped('hobbies_ids').ids
member_education_status_ids = self.member_ids.mapped('member_education_status_ids').ids
diseases_ids = self.member_ids.mapped('diseases_ids').ids
disabilities_ids = self.member_ids.mapped('disabilities_ids').ids
return ['|', '|', '|','|','|','|','|','|','|','|','|','|','|',
'&', ('res_model', '=', 'grant.benefit'),
('res_id', 'in', self.ids),
('benefit_id', 'in', self.ids),
'&', ('res_model', '=', 'visit.location'),
('res_id', 'in', visit_location),
'&', ('res_model', '=', 'service.request'),
('res_id', 'in', service_requests),
'&', ('res_model', '=', 'family.complaints'),
('res_id', 'in', family_complaints),
'&', ('res_model', '=', 'education.status'),
('res_id', 'in', self.mother_education_status_ids.ids),
'&', ('res_model', '=', 'family.debits'),
('res_id', 'in', (self.family_debits_ids + self.mother_debits_ids).ids),
'&', ('res_model', '=', 'salary.line'),
('res_id', 'in', self.salary_ids.ids),
'&', ('res_model', '=', 'family.member'),
('res_id', 'in', self.member_ids.ids),
('member_id', 'in', self.member_ids.ids),
'&', ('res_model', '=', 'member.hobbies'),
('res_id', 'in', hobby_ids),
'&', ('res_model', '=', 'education.status'),
('res_id', 'in', member_education_status_ids),
'&', ('res_model', '=', 'member.diseases'),
('res_id', 'in', diseases_ids),
'&', ('res_model', '=', 'member.disabilities'),
('res_id', 'in', disabilities_ids),
]
def _compute_attached_docs_count(self):
Attachment = self.env['ir.attachment']
for benefit in self:
benefit.doc_count = Attachment.search_count(benefit.get_attached_domain())
def view_attachments(self):
action = self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
action['domain'] = str(self.get_attached_domain())
action['context'] = {'create': False}
return action
@api.depends('salary_ids')
def get_income_required_attach(self):
for rec in self.salary_ids:
if rec.is_required and not rec.salary_attach:
self.income_required_attach = None
break
elif rec.is_required and rec.salary_attach:
self.income_required_attach = 'true'
elif rec.is_default and not rec.is_required and (rec.salary_attach or not rec.salary_attach):
self.income_required_attach = 'true'
else:
self.income_required_attach = 'true'
def _get_invoices_count(self):
for rec in self:
rec.invoices_count = self.env['account.move'].search_count([
('benefit_family_ids', 'in', [rec.id]),('move_type','=','in_invoice')
])
def _get_total_move_lines(self):
for rec in self:
move_lines = self.env['account.move.line'].search([('benefit_family_id', '=', rec.id),('family_confirm_id','!=', False)])
rec.total_move_lines = sum(move_lines.mapped('debit')) - sum(move_lines.mapped('credit'))
def _compute_visit_location_count(self):
for rec in self:
rec.with_context(bypass_attachments_requirement=True).write({
'visit_location_count': self.env['visit.location'].search_count([('benefit_id', '=', rec.id)]),
})
def action_view_benefit_members(self):
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': _('Benefit Members'),
'res_model': 'family.member',
'view_mode': 'tree,form',
'domain': [('id', 'in', self.member_ids.filtered(lambda m: m.member_status == 'benefit').ids)],
'target': 'current',
}
def action_view_non_benefit_members(self):
self.ensure_one()
action = {
'type': 'ir.actions.act_window',
'name': _('Non Benefit Members'),
'res_model': 'family.member',
'view_mode': 'tree,form',
'domain': [('id', 'in', self.member_ids.filtered(lambda m: m.member_status == 'non_benefit').ids)],
'target': 'current',
}
return action
def action_open_related_move_line_records(self):
""" Opens a tree view with related records filtered by a dynamic domain """
move_lines = self.env['account.move.line'].search([
('benefit_family_id', '=', self.id),('family_confirm_id','!=', False)
]).ids
action = {
'type': 'ir.actions.act_window',
'name': 'Move Lines',
'res_model': 'account.move.line',
'view_mode': 'tree,form',
'domain': [('id', 'in', move_lines)],
'target': 'current',
}
return action
def action_open_visit_location(self):
""" Opens a tree view with related records filtered by a dynamic domain """
visit_location = self.env['visit.location'].search([('benefit_id', '=', self.id)]).ids
action = {
'type': 'ir.actions.act_window',
'name': _('Visit Location'),
'res_model': 'visit.location',
'view_mode': 'tree,form',
'domain': [('id', 'in', visit_location)],
'target': 'current',
}
return action
def _get_total_service_requests(self):
for rec in self:
rec.total_service_requests = self.env['service.request'].search_count([('family_id', '=', rec.id),('is_seasonal','=',False)])
def action_open_related_service_requests(self):
""" Opens a tree view with related records filtered by a dynamic domain """
service_requests = self.env['service.request'].search([('family_id', '=', self.id),('is_seasonal','=',False)]).ids
action = {
'type': 'ir.actions.act_window',
'name': _('Service Requests'),
'res_model': 'service.request',
'view_mode': 'tree,form',
'domain': [('id', 'in', service_requests)],
'target': 'current',
}
return action
def _get_total_seasonal_service_requests(self):
for rec in self:
rec.total_seasonal_service_requests = len(self.env['service.request'].search([('family_id', '=', self.id), ('is_seasonal', '=', True)]))
def action_open_related_seasonal_service_requests(self):
""" Opens a tree view with related records filtered by a dynamic domain """
seasonal_service_requests = self.env['service.request'].search([('family_id', '=', self.id), ('is_seasonal', '=', True)]).ids
action = {
'type': 'ir.actions.act_window',
'name': _('Seasonal Service Requests'),
'res_model': 'service.request',
'view_mode': 'tree,form',
'domain': [('id', 'in', seasonal_service_requests)],
'target': 'current',
}
return action
def action_open_related_invoice_records(self):
""" Opens a tree view with related records filtered by a dynamic domain """
invoices = self.env['account.move'].search([
('benefit_family_ids', 'in', [self.id]),('move_type','=','in_invoice')
]).ids
action = {
'type': 'ir.actions.act_window',
'name': 'Invoices',
'res_model': 'account.move',
'view_mode': 'tree,form',
'domain': [('id', 'in', invoices)],
'target': 'current',
}
return action
def _get_family_monthly_values(self):
validation_setting = self.env["family.validation.setting"].search([], limit=1)
for rec in self:
if rec.benefit_category_id.id in validation_setting.benefit_category_ids.ids:
total_family_members = rec.benefit_member_count
rec.family_monthly_income = total_family_members * validation_setting.cash_expense
rec.family_monthly_meals = total_family_members * validation_setting.meal_expense
rec.family_monthly_clotting = total_family_members * validation_setting.clothing_expense
rec.total_family_expenses = rec.family_monthly_income + rec.family_monthly_meals + rec.family_monthly_clotting
else:
rec.family_monthly_income = 0
rec.family_monthly_meals = 0
rec.family_monthly_clotting = 0
rec.total_family_expenses = 0
def get_html(self):
for rec in self:
print(f'<iframe id="custom_src" height="500" width="500" src="{rec.url}"></iframe>')
rec.url_html = f'<iframe id="custom_src" height="500" width="500" src="{rec.url}"/>'
# @api.multi
def open_map(self):
for Location in self:
url = "http://maps.google.com/maps?oi=map&q="
if Location.street:
url += Location.street.replace(' ', ',')
if Location.city_id:
url += '+' + Location.district_id.name.replace(' ', ',')
# url += '+' + Location.city_id.name.replace(' ', ',')
url += '+' + Location.city_id.state_id.name.replace(' ', '')
url += '+' + Location.zip.replace(' ', ',')
url += '+' + Location.city_id.country_id.name.replace(' ', ',')
if Location.nearby_mosque:
url += Location.nearby_mosque.replace(' ', ',')
return {
'type': 'ir.actions.act_url',
'target': 'new',
'url': url
}
@api.onchange('url')
def onchange_image_url(self):
if self.image_url:
self.img_attach = '<img id="img" src="%s"/>' % self.url
def get_researchers_email(self):
email_ids = ''
for rec in self.researcher_id.employee_id:
if email_ids:
email_ids = email_ids + ',' + str(rec.work_email)
else:
email_ids = str(rec.work_email)
return email_ids
@api.depends('room_ids')
def get_rooms_total(self):
for rec in self:
if rec.id:
rooms = rec.env['benefit.housing.rooms'].sudo().search([('housing_id', '=', rec.id)])
rec.rooms_number = len(rooms)
@api.onchange('room_ids')
def onchange_room_ids(self):
res = {}
items_ids = []
for record in self:
items_ids.append(record.id)
res['domain'] = {'items': [('room_id', 'in', items_ids)]}
return res
@api.onchange('branch_family_id')
def _onchange_branch_family_id(self):
if self.branch_family_id:
branch = self.branch_family_id
if branch.has_employees:
chosen_branch = branch
else:
chosen_branch = branch.replacement_branch_id
self.branch_custom_id = chosen_branch
else:
self.branch_custom_id = False
@api.onchange("father_country_id", 'mother_country_id')
def onchange_father_mother_country_id(self):
res = {}
for rec in self:
if rec.father_country_id and rec.mother_country_id:
if rec.mother_country_id.code != 'SA' and rec.father_country_id.code != 'SA' and not rec.mother_country_id.is_excluded and not rec.father_country_id.is_excluded :
rec.mother_country_id = False
res['warning'] = {'title': _('ValidationError'),
'message': _('Non-Saudi mothers and fathers cannot register')}
return res
@api.constrains('acc_holder_id_number')
def _check_acc_holder_id_number(self):
for record in self:
id_number = record.acc_holder_id_number
if id_number:
if not re.match(r'^\d{10}$', id_number):
raise ValidationError(_("Account Holder ID Number must contain exactly 10 digits."))
@api.constrains('father_id_number', 'mother_id_number', 'replacement_mother_id_number')
def _onchange_id_numbers(self):
id_numbers = {
'رقم هوية الأب': self.father_id_number,
'رقم هوية الأم': self.mother_id_number,
'رقم هوية الأم البديلة': self.replacement_mother_id_number,
}
# Check each ID number for 10-digit format and uniqueness within the parent model
unique_ids = set()
for label, id_number in id_numbers.items():
if id_number == 'NULL' and label == 'رقم هوية الأم':
continue
if id_number:
if not re.match(r'^\d{10}$', id_number):
raise ValidationError(_("%s must contain exactly 10 digits.")%label)
if id_number in unique_ids:
raise ValidationError(_("%s must be unique within the same record.") % label)
if id_number.startswith('1') and label == 'رقم هوية الأب':
self.father_country_id = self.env["res.country"].search([('code','=','SA')],limit=1).id
self.father_id_number_type = 'citizen'
if id_number.startswith('1') and label == 'رقم هوية الأم':
self.mother_country_id = self.env["res.country"].search([('code','=','SA')],limit=1).id
self.mother_id_number_type = 'citizen'
if id_number.startswith('1') and label == 'رقم هوية الأم البديلة':
self.replacement_mother_country_id = self.env["res.country"].search([('code','=','SA')],limit=1).id
self.replacement_mother_id_number_type = 'citizen'
unique_ids.add(id_number)
# Check for uniqueness against `member_id_number` in child records and across database records
for member in self.member_ids:
if member.member_id_number == 'NULL':
continue
if member.member_id_number and member.member_id_number in unique_ids and member.id not in [self.mother_family_member_id.id,self.replacement_mother_family_member_id.id]:
raise ValidationError(_("The ID number %s in the Family Members list must be unique across the record.")%member.member_id_number)
for id_number in unique_ids:
if id_number == 'NULL':
continue
if id_number == self.father_id_number:
conflict = self.env['grant.benefit'].search([
('id', '!=', self._origin.id),
'|',
('mother_id_number', '=', id_number),
('replacement_mother_id_number', '=', id_number),
], limit=1)
if conflict:
raise ValidationError(
_("Father ID %s is already used in another family (as non-father) with code %s.") %
(id_number, conflict.code))
elif id_number == self.mother_id_number:
conflict = self.env['grant.benefit'].search([
('id', '!=', self._origin.id),
'|',
('father_id_number', '=', id_number),
('replacement_mother_id_number', '=', id_number),
], limit=1)
if conflict:
raise ValidationError(
_("Mother ID %s is already used in another family with code %s.") %
(id_number, conflict.code))
continue
elif id_number == self.replacement_mother_id_number:
conflict = self.env['grant.benefit'].search([
('id', '!=', self.id),
'|',
('father_id_number', '=', id_number),
('mother_id_number', '=', id_number),
], limit=1)
if conflict:
raise ValidationError(
_("Replacement Mother ID %s is already used in another family (as non-replacement) with code %s.") %
(id_number, conflict.code)
)
duplicate_record_members = self.env['family.member'].search([('member_id_number', '=', id_number)])
for member in duplicate_record_members:
if member.relationn and member.relationn.relation_type in ['mother', 'replacement_mother']:
continue
if member.benefit_id.id != self.id:
raise ValidationError(
_("The ID number %s already exists in family with code %s. Please enter a unique ID number.") %
(id_number, member.benefit_id.code)
)
@api.onchange("family_bank")
def onchange_family_bank(self):
for rec in self:
if rec.family_bank:
exist = self.search([('family_bank', '=', rec.family_bank.id)])
if exist:
raise ValidationError(
_('The Family Bank Already Exist!'))
@api.model
def _geo_localize(self, street='', zip='', city='', state='', country=''):
geo_obj = self.env['base.geocoder']
search = geo_obj.geo_query_address(
street=street, zip=zip, city=city, state=state, country=country
)
result = geo_obj.geo_find(search, force_country=country)
if result is None:
search = geo_obj.geo_query_address(
city=city, state=state, country=country
)
result = geo_obj.geo_find(search, force_country=country)
return result, search
def geo_localize(self):
for location in self.with_context(lang='en_US'):
result = self._geo_localize(
street=location.street,
zip=location.zip,
city=location.city_id.name,
state=location.state_id.name,
country=location.country_id.name,
)
if result:
location.write(
{
'lat': result[0][0],
'lon': result[0][1],
}
)
return True
def get_location_on_map(self):
for location in self.with_context(lang='en_US'):
url = "http://maps.google.com/maps/search/?api=1&query=%s,%s" % (location.lat, location.lon),
return {
'type': 'ir.actions.act_url',
'target': 'new',
'url': url
}
def check_mother_status(self):
validation_setting = self.env["family.validation.setting"].search([], limit=1)
mini_income_for_mother = validation_setting.mini_income_for_mother
max_income_for_mother = validation_setting.max_income_for_mother
for rec in self:
reasons = []
status = 'benefit'
if rec.mother_location_conf and rec.mother_marital_conf:
if not rec.mother_location_conf.is_benefit or not rec.mother_marital_conf.is_benefit or rec.state in ['suspended_second_approve','refused']:
reasons.append(_("The mother's marital or location conditions are not eligible."))
status = 'non_benefit'
elif rec.mother_marital_conf.is_benefit :
if rec.is_mother_work and rec.mother_country_id.code == 'SA' or (
rec.mother_country_id.code != 'SA' and rec.father_country_id.code == 'SA'):
if mini_income_for_mother < rec.mother_net_income <= max_income_for_mother:
reasons.append(_("The mother's income is between minimum and maximum thresholds."))
status = 'non_benefit'
elif rec.mother_net_income <= mini_income_for_mother:
status = 'benefit'
elif rec.mother_net_income > max_income_for_mother:
status = 'benefit'
elif not rec.is_mother_work and rec.mother_country_id.code == 'SA' or (
rec.mother_country_id.code != 'SA' and rec.father_country_id.code == 'SA'):
status = 'benefit'
return status, reasons
def check_replacement_mother_status(self):
for rec in self:
reasons = []
status = 'benefit'
if not rec.add_replacement_mother:
continue
if rec.state in ['suspended_second_approve', 'refused']:
status = 'non_benefit'
reasons.append(_("Family is suspended or refused."))
return status, reasons
if not rec.replacement_mother_marital_conf or not rec.replacement_mother_location_conf:
status = 'non_benefit'
reasons.append(_("Replacement mother marital or location information is missing."))
return status, reasons
if not rec.replacement_mother_marital_conf.replacement_mother_is_benefit:
status = 'non_benefit'
reasons.append(_("The replacement mother's marital status is not eligible for benefits."))
if not rec.replacement_mother_location_conf.replacement_mother_is_benefit:
status = 'non_benefit'
reasons.append(_("The replacement mother's location is not eligible for benefits."))
return status, reasons
def delete_from_db(self):
find_id = self.env['benefit.housing'].search([])
for r in find_id:
r.unlink()
@api.model
def default_get(self, fields):
res = super(GrantBenefitProfile, self).default_get(fields)
# Get default attachments
default_attachment = self.env["attachments.settings"].search([('is_default', '=', True)])
# Prepare the list of default attachments for the one2many field
default_attachments_data = []
income_attachments_data = []
for attach in default_attachment:
if attach.attach_type == 'family_attach':
default_attachments_data.append((0, 0, {
'name': attach.name,
'is_required': attach.is_required,
'is_default': attach.is_default,
'show_in_portal': attach.show_in_portal
}))
if attach.attach_type == 'income_attach':
income_attachments_data.append((0, 0, {
'income_type': attach.id,
'is_required': attach.is_required,
'is_default': attach.is_default,
# 'show_in_portal': attach.show_in_portal
}))
# Add the default attachments to the res dictionary for attachment_ids
if 'attachment_ids' in fields:
res['attachment_ids'] = default_attachments_data
if 'salary_ids' in fields:
res['salary_ids'] = income_attachments_data
return res
def write(self, vals):
res = super(GrantBenefitProfile, self).write(vals)
if "name" in vals and self.user_id:
self.user_id.sudo().write({"name": vals.get("name")})
if any(field in vals for field in ["name", "first_name", "second_name", "middle_name", "family_name",
"father_name", "father_second_name", "father_third_name",
"father_family_name"]):
for record in self:
for member in record.member_ids:
member.get_partner_name()
# record.partner_id.get_partner_name() # Force recomputation of name
if record.user_id:
record.sudo().user_id.write({"name": record.partner_id.name})
if 'active' in vals:
for rec in self:
rec.member_ids.write({'active': vals['active']})
#if not self.env.context.get('force_website', False) and not self.env.context.get('bypass_attachments_requirement', False):
# self._validate_required_attachments()
# Handle mother update/create
mother_fields = [
'mother_name', 'mother_second_name', 'mother_third_name', 'mother_family_name', 'mother_id_number',
'mother_birth_date', 'mother_marital_conf', 'mother_location_conf', 'is_mother_work',
'mother_net_income', 'mother_age','education_status','mother_diseases_attachment_ids',
'mother_education_status_ids','mother_disabilities_attachment_ids'
]
if any(field in vals for field in mother_fields):
for rec in self:
#rec.calculate_income(rec.mother_net_income, rec.mother_status, rec.salary_ids)
rec.add_or_replace_mother_as_member()
# Handle replacement mother update/create
replacement_fields = [
'replacement_mother_name', 'replacement_mother_second_name', 'replacement_mother_third_name',
'replacement_mother_family_name','replacement_mother_id_number',
'replacement_mother_birth_date', 'replacement_mother_marital_conf',
'replacement_mother_location_conf','replacement_mother_relation',
'replacement_is_mother_work', 'replacement_mother_income', 'replacement_education_status',
'replacement_mother_age','replacement_mother_disabilities_attachment_ids',
'replacement_education_status_ids', 'replacement_mother_diseases_attachment_ids'
]
if any(field in vals for field in replacement_fields):
for rec in self:
if rec.add_replacement_mother:
#rec.calculate_income(rec.replacement_mother_income, rec.replacement_mother_status, rec.salary_ids)
rec.add_or_replace_replacement_mother_as_member()
return res
@api.model
def create(self, vals):
res = super(GrantBenefitProfile, self).create(vals)
if "applicant_name" not in vals:
res.applicant_name = self.env.user.display_name
if "name" in vals and res.user_id:
res.user_id.sudo().write({"name": vals.get("name")})
if res.user_id:
res.sudo().user_id.write({"name": res.name})
#if not self.env.context.get('force_website', False):
##res._validate_required_attachments()
if not res.code or res.code == _('New'):
res.code = self.env['ir.sequence'].sudo().next_by_code('benefit.sequence') or _('New')
# Add mother
if res.mother_id_number:
#res.calculate_income(res.mother_net_income, res.mother_status, res.salary_ids)
res.add_or_replace_mother_as_member()
# Add replacement mother
if res.add_replacement_mother and res.replacement_mother_id_number:
#res.calculate_income(res.replacement_mother_income, res.replacement_mother_status, res.salary_ids)
res.add_or_replace_replacement_mother_as_member()
return res
def unlink(self):
users_to_delete = self.env['res.users']
skip_user = self.env.context.get('skip_user_unlink')
force_unlink = self.env.context.get('force_unlink', False)
for record in self:
if not force_unlink and record.state not in ['draft']:
raise UserError(_('You cannot delete this record'))
self.env['ir.attachment'].search([('benefit_id', '=', record.id)]).unlink()
if record.member_ids:
record.member_ids.unlink()
if not skip_user and record.user_id:
other_benefits = self.env['grant.benefit'].search([
('user_id', '=', record.user_id.id),
('id', '!=', record.id)
])
if other_benefits:
raise UserError(
_("Cannot delete user '%s': still linked to other benefit profiles.")
% record.user_id.name
)
users_to_delete |= record.user_id
res = super().unlink()
if not skip_user:
users_to_delete.unlink()
return res
def copy(self, default=None):
"""Override the copy method to prevent duplicating the record."""
raise UserError(_('You cannot Duplicate this record'))
def complete_data(self):
message = self.create_message('complete_info')
self.partner_id.send_sms_notification(message, self.phone)
ctx = dict(self.env.context or {})
ctx['create_visit'] = True
return {
'name': _('Rerearcher Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'researcher.family.wizard',
'view_id': self.env.ref('odex_benefit.view_resarcher_family_wizard_form').id,
'target': 'new',
'context': ctx,
}
def action_assign_specialist_mass(self):
ctx = dict(self.env.context or {})
return {
'name': _('Rerearcher Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'researcher.family.wizard',
'view_id': self.env.ref('odex_benefit.view_assigned_researcher_family_wizard_form').id,
'target': 'new',
'context': ctx,
}
def finish_complete_data(self):
message = self.create_message('waiting_approve')
self.partner_id.send_sms_notification(message, self.phone)
for rec in self:
visits = self.env['visit.location'].search([('benefit_id', '=', rec.id),('state', 'not in', ['close', 'done'])])
if not rec.benefit_category_id.is_benefit:
raise ValidationError(_("The procedure cannot be continued; the family is not a beneficiary."))
if rec.action_type == 'new' and visits:
raise ValidationError(_("Please complete your pending visits before proceeding."))
rec.validate_attachments()
self.state = 'waiting_approve'
def action_first_accepted(self):
"""Accept registration"""
for rec in self:
rec.state = "first_approve"
def action_second_accepted(self):
"""Accept registration"""
for rec in self:
messages = []
if rec.total_family_expenses:
if not rec.acc_number:
messages.append(_("Account Number is required."))
if not rec.bank_id:
messages.append(_("Bank is required."))
if rec.is_family_member and not rec.family_member_id:
messages.append(_("Family Member must be selected."))
if not rec.is_family_member and not rec.owner_identity_attachment_ids:
messages.append(_("Owner Identity Attachment is required."))
if not rec.is_family_member and not rec.family_approval_attachment_ids:
messages.append(_("Family Approval Attachment is required."))
if not rec.acc_holder_name:
messages.append(_("Account Holder Name is required."))
if not rec.acc_holder_id_number:
messages.append(_("Account Holder ID Number is required."))
if messages:
raise UserError("\n".join(messages))
#if not rec.user_id:
# self.sudo().create_user()
if rec.user_id:
rec.user_id.sudo().write({
'groups_id': [(3, self.env.ref('base.group_user', False).id)],
})
# rec.user_id.sudo().write({
# 'groups_id': [(4, self.env.ref('odex_benefit.group_benefit_user', False).id)],
# })
rec.user_id.sudo().write({
'groups_id': [(4, self.env.ref('base.group_portal', False).id)],
})
if rec.action_type == 'new':
rec.approve_date = datetime.now()
self.sudo().send_approval_benefit_email()
partner_ids = []
for id in self.message_follower_ids.ids:
partner_ids.append(self.env['mail.followers'].search([('id', '=', id)]).partner_id)
self.state = "second_approve"
self.action_type = "approved"
#self.sudo()._send_notification(partner_ids, rec.state)
# for member in self.member_ids:
# member.create_member_partner()
# @api.multi
def action_first_refusal(self):
"""First refusal to entity registration"""
domain = []
context = {}
context = dict(self.env.context or {})
context['state'] = "first_refusal"
self.partner_id.send_sms_notification("First Refusal", self.phone)
context['active_id'] = self.id
return {
'name': _('Refuse Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'entity.refused.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_entity_refused_reason_wizard_form').id,
'target': 'new',
'domain': domain,
'context': context,
}
def action_set_to_draft(self):
context = dict(self.env.context or {})
context['target_state'] = "draft"
context['active_id'] = self.id
return {
'name': _('Return Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'entity.return.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_entity_return_reason_wizard_form').id,
'target': 'new',
'context': context,
}
def action_set_to_new(self):
context = dict(self.env.context or {})
context['target_state'] = "complete_info"
context['active_id'] = self.id
return {
'name': _('Return Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'entity.return.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_entity_return_reason_wizard_form').id,
'target': 'new',
'context': context,
}
def action_set_waiting_approve(self):
context = dict(self.env.context or {})
context['target_state'] = "waiting_approve"
context['active_id'] = self.id
return {
'name': _('Return Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'entity.return.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_entity_return_reason_wizard_form').id,
'target': 'new',
'context': context,
}
# @api.multi
def action_refuse(self):
"""Refuse entity registration"""
domain = []
context = dict(self.env.context or {})
context['state'] = "refused"
context['active_id'] = self.id
return {
'name': _('Refuse Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'entity.refused.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_entity_final_refused_reason_wizard_form').id,
'target': 'new',
'domain': domain,
'context': context,
}
# @api.multi
def action_black_list(self):
"""Move benefit to black list"""
domain = []
context = dict(self.env.context or {})
context['state'] = "black_list"
context['active_id'] = self.id
return {
'name': _('Black List Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'entity.black.list.wizard',
'view_id': self.env.ref('odex_benefit.view_entity_black_list_wizard_form').id,
'target': 'new',
'domain': domain,
'context': context,
}
# @api.multi
def action_edit_info(self):
#user = self.user_id
#if not user:
# user = self.env['res.users'].sudo().search(
# [('partner_id', '=', self.partner_id.id), ('active', '=', False)])
# if user:
# user.write({'active': True})
# else:
# user = self.create_user()
#group_e = self.env.ref('odex_benefit.group_benefit_edit', False)
try:
#group_e.sudo().write({'users': [(4, user.id)]})
self.old_stage = self.state
template = self.env.ref('odex_benefit.edit_benefit_email', False)
except:
pass
self.state = 'complete_info'
self.action_type = 'edit_info'
def action_suspend(self):
return {
'name': _('Suspend Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'suspend.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_suspend_reason_wizard_form').id,
'target': 'new',
}
def action_resume_family(self):
ctx = dict(self.env.context or {})
ctx['resume_family'] = True
return {
'name': _('Resume Reason Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'suspend.reason.wizard',
'view_id': self.env.ref('odex_benefit.view_resume_reason_wizard_form').id,
'target': 'new',
'context': ctx,
}
def action_suspend_first_accept(self):
for rec in self:
rec.state = 'first_approve'
def action_resume_first_accept(self):
for rec in self:
rec.state = 'first_approve'
def action_suspend_second_accept(self):
for rec in self:
rec.action_type = 'suspended'
if rec.suspend_reason.need_service_manager_approval:
rec.state = 'family_services_manager'
elif rec.suspend_reason.suspend_type == 'temporarily_suspend':
rec.state = 'temporary_suspended'
else:
rec.state = 'suspended_second_approve'
def action_resume_second_accept(self):
for rec in self:
if rec.suspend_reason.need_service_manager_approval:
rec.state = 'family_services_manager'
else:
rec.state = 'second_approve'
rec.action_type = 'approved'
def action_suspend_third_accept(self):
for rec in self:
if rec.suspend_reason.suspend_type == 'temporarily_suspend':
rec.state = 'temporary_suspended'
else:
rec.state = 'suspended_second_approve'
def action_resume_third_accept(self):
for rec in self:
rec.state = 'second_approve'
rec.action_type = 'approved'
def action_final_suspend(self):
today = fields.Date.today()
for rec in self:
if rec.final_suspend_date and today >= rec.final_suspend_date:
rec.write({
'state': 'suspended_second_approve',
'suspend_type': 'suspend',
})
else:
raise UserError(_("Final suspension cannot be executed until after the specified final suspension date."))
def action_auto_suspend(self):
# Fetch grants in second approval state that are not excluded from suspension
#case_one :
grants = self.env["grant.benefit"].search(
[('state', '=', 'second_approve'), ('is_excluded_suspension', '=', False)]
)
for grant in grants:
# Check if there are no benefit members
if grant.benefit_member_count == 0:
grant.state = 'complete_info'
grant.suspend_method = 'auto'
grant.action_type = 'suspended'
#case two :
members = self.env["family.member"].search(
[('state', '=', 'second_approve'), ('is_excluded_suspension', '=', False), ('member_status', '=', 'non_benefit')]
)
for member in members:
member.state_a = 'complete_info'
member.suspend_method = 'auto'
member.action_type = 'suspended'
member.is_member_workflow = True
def check_actt(self):
# case_one :
grants = self.env["grant.benefit"].search(
[('state', '=', 'second_approve'), ('is_excluded_suspension', '=', False)]
)
for grant in grants:
# Check if any attachment of the grant is expired
for attachment in grant.attachment_ids:
if attachment.attach_status == 'expired':
# Change state to temporarily suspended if there are benefit members
if grant.benefit_member_count != 0:
grant.state = 'complete_info'
grant.action_type = 'suspended'
grant.suspend_method = 'auto'
break # Exit attachment loop after processing
# Check each member's attachments
for member in grant.member_ids:
for member_attachment in member.attachment_ids:
if member_attachment.attach_status == 'expired':
# Change state to temporarily suspended if there are benefit members
if grant.benefit_member_count != 0:
grant.state = 'complete_info'
grant.action_type = 'suspended'
grant.suspend_method = 'auto'
break # Exit member attachment loop after processing
def action_suspend_refuse(self):
for rec in self:
rec.state = 'second_approve'
rec.action_type = 'approved'
rec.get_member_income()
def action_reject_resume(self):
for rec in self:
if rec.action_type == 'resume_from_temporary':
rec.state = 'temporary_suspended'
elif rec.action_type == 'resume_from_final':
rec.state = 'suspended_second_approve'
rec.action_type = 'suspended'
#Excption Work flow
def action_exception(self):
return {
'name': _('Exception Wizard'),
'view_mode': 'form',
'view_type': 'form',
'type': 'ir.actions.act_window',
'res_model': 'exception.wizard',
'view_id': self.env.ref('odex_benefit.view_exception_wizard_form').id,
'target': 'new',
}
def action_exception_first_accept(self):
for rec in self:
rec.state = 'first_approve'
def action_exception_second_accept(self):
for rec in self:
rec.state = 'exception_second_approve'
def action_exception_final_accept(self):
for rec in self:
rec.is_excluded_suspension = True
rec.state = 'second_approve'
for member in self.member_ids:
member.is_excluded_suspension = True
rec.get_member_income()
def action_auto_exception(self):
obj = self.env["grant.benefit"].search(
[('state', '=', 'second_approve'), ('is_excluded_suspension', '=', True)])
for rec in obj:
if rec.exception_end_date and rec.exception_end_date <= fields.Datetime.now():
rec.is_excluded_suspension = False
rec.state = 'suspended_second_approve'
rec.action_type = 'suspended'
for member in rec.member_ids:
member.is_excluded_suspension = False
def run_auto_final_suspend(self):
today = date.today()
records = self.search([
('state', '=', 'temporary_suspended'),
('final_suspend_date', '<=', today),
])
for rec in records:
rec.state = 'suspended_second_approve'
def action_exception_refuse(self):
for rec in self:
rec.state = 'suspended_second_approve'
rec.action_type = 'suspended'
# @api.multi
def action_remove_from_black_list(self):
"""Remove entity from black list"""
partner_ids = []
for entity in self:
if self.old_stage == 'draft':
entity.state = 'draft'
else:
entity.state = 'second_approve'
entity.black_list_message = False
user = self.env['res.users'].search([('partner_id', '=', entity.partner_id.id)], limit=1)
user.toggle_active()
# activate user
subject = _('Beneficiaries')
state_label = dict(entity.fields_get(allfields=['state'])['state']['selection'])[entity.state]
body = ' '.join(
(_(u'The Beneficial '), entity.name, _(u' State changed to '), state_label, u'.')).encode(
'utf-8')
partner_ids += [(6, 0, entity.message_follower_ids.ids)]
message_vals = {
'subject': subject,
'body': body,
'partner_ids': partner_ids,
}
# entity.message_post(body=body, subject=subject, message_type='email')
# entity.send_remove_from_black_list_email()
@api.depends('car_ids')
def _onchange_car_count(self):
for rec in self:
rec.car_count = len(rec.car_ids)
rec.has_car = any(line.member_id for line in rec.car_ids)
@api.onchange('is_diseases')
def onchange_is_diseases(self):
for rec in self:
rec.is_diseases = 'sick' if rec.is_diseases else 'healthy'
def _onchange_is_has_needs(self):
for rec in self:
benefits_needs = rec.env['benefits.needs'].sudo().search(['|',
('benefit_id', '=', rec.id),
('benefit_ids', 'in', rec.id)])
needs = []
for need in benefits_needs:
if need.state == 'published' and need.remaining_amount > 0.0:
needs.append(need.id)
if len(needs) > 0:
rec.sudo().has_needs = True
elif len(needs) == 0:
rec.sudo().has_needs = False
def _orphan_list_compute(self):
for rec in self:
benefits = rec.env['grant.benefit'].sudo().search([('mother_id', '=', rec.id)])
rec.orphan_ids = [(6, 0, benefits.ids)]
rec.orphan_count = len(rec.orphan_ids)
def _compute_orphan_Type(self):
for rec in self:
if rec.benefit_type == "orphan":
if not rec.father_is_life and not rec.mother_is_life:
rec.orphan_status = 'parent'
elif not rec.father_is_life:
rec.orphan_status = 'father'
elif not rec.mother_is_life:
rec.orphan_status = 'mother'
# TODO FIXME: i commented these lines because this field doen't exist in model grant.benefit
# else:
# rec.orphan_type = ''
# else:
# rec.orphan_type = ''
@api.onchange('birth_date')
def onchange_category(self):
for rec in self:
rec.expenses_ids = False
for expenses in rec.benefit_category_id:
if expenses.state == 'second_pprove':
for i in expenses.expenses_ids:
expenses = {}
expenses['expenses_type'] = i.expenses_type
expenses['amount'] = i.amount
rec.expenses_ids = [(0, 0, expenses)]
expenses = self.env['benefit.expenses'].sudo().search(
[('benefit_id', '=', self._origin.id), ('state', '=', 'accreditation')])
for expenses_extra in expenses:
expenses = {}
expenses['expenses_type'] = expenses_extra.expenses_type
expenses['amount'] = expenses_extra.amount
expenses['note'] = expenses_extra.name
rec.expenses_ids = [(0, 0, expenses)]
# Todo
def create_message(self, case):
sms_template = self.env['benefit.sms.configuration'].sudo().search([('state', '=', case)])
if sms_template:
message = sms_template.case_text
if '$اسم_المستفيد' in message:
if self.name:
message = message.replace("$اسم_المستفيد", self.name)
else:
raise ValidationError(_("عفواءً القالب المخصص يتوجب وجود اسم المستفيد"))
if '$رقم_الهوية' in message:
if self.id_number:
message = message.replace("$رقم_الهوية", self.id_number)
else:
raise ValidationError(_("عفواءً القالب المخصص يتوجب وجود رقم الهوية"))
if '$اسم_العائلة' in message:
if self.institution_id:
message = message.replace("$اسم_العائلة", self.institution_id.name)
else:
raise ValidationError(_("عفواءً القالب المخصص يتوجب وجود اسم العائلة"))
return message
def get_error_response(self, result):
if result == "105":
raise ValidationError(_("Sorry, there is not enough credit!"))
if result == "102":
raise ValidationError(_("Sorry, wrong username!"))
if result == "103":
raise ValidationError(_("Sorry, wrong password!"))
if result == "106":
raise ValidationError(_("Sorry, sender name is not available!"))
if result == "1013":
raise ValidationError(_("Sorry, no message has been posted!"))
if result == "1011":
raise ValidationError(_("Sorry, no message has been posted!"))
@api.depends('name')
def _compute_qr_code(self):
for rec in self:
qr = qrcode.QRCode(
version=1,
error_correction=qrcode.constants.ERROR_CORRECT_L,
box_size=15,
border=4,
)
name = rec.name
qr.add_data(name)
qr.make(fit=True)
img = qr.make_image()
temp = BytesIO()
img.save(temp, format="PNG")
qr_image = base64.b64encode(temp.getvalue())
rec.qr_code = qr_image
@api.onchange('bank_id')
def _compute_prefix_iban(self):
if self.bank_id:
self.iban = self.bank_id.iban
@api.onchange('weight', 'height')
def _compute_obesity_rate(self):
for rec in self:
if rec.weight and rec.height:
height = (rec.height / 100)
rec.p_weight = (rec.weight / (height * height))
@api.depends(
'expenses_ids',
'estimated_rent_amount',
'expenses_ids.deduct_from_family_income',
'expenses_ids.amount',
'family_debits_ids',
'family_debits_ids.deduct_from_family_income',
'family_debits_ids.monthly_installment',
)
def get_total_expenses(self):
for ben in self:
followers = ben.env['benefit.followers'].sudo().search([('benefit_id', '=', ben.id)])
expenses = ben.env['expenses.line'].sudo().search([('benefit_id', '=', ben.id)])
total_expenses = 0.0
if ben.expenses_ids and ben.family_debits_ids:
total_expenses = sum(ben.expenses_ids.filtered(lambda e: e.deduct_from_family_income).mapped('amount')) + sum(ben.family_debits_ids.filtered(lambda e: e.deduct_from_family_income).mapped('monthly_installment'))
elif ben.expenses_ids and not ben.family_debits_ids:
total_expenses = sum(ben.expenses_ids.filtered(lambda e: e.deduct_from_family_income).mapped('amount'))
elif ben.family_debits_ids and not ben.expenses_ids:
total_expenses = sum(ben.family_debits_ids.filtered(lambda e: e.deduct_from_family_income).mapped('monthly_installment'))
if followers:
ben.followers_total = len(followers)
if expenses:
ben.expenses_total = len(expenses)
ben.total_expenses = total_expenses + ben.estimated_rent_amount
@api.depends('mother_net_income', 'mother_status')
def calculate_income(self):
validation_setting = self.env["family.validation.setting"].search([], limit=1)
max_income_for_mother = validation_setting.max_income_for_mother
for rec in self:
add_mother_net_income = (rec.mother_status == 'benefit' and rec.mother_net_income > max_income_for_mother)
if add_mother_net_income:
rec.mother_income = rec.mother_net_income
else:
rec.mother_income = 0.0
@api.depends(
'salary_ids',
'salary_ids.salary_amount',
'salary_ids.approved',
'mother_income',
)
def get_total_income(self):
for rec in self:
total = 0.0
rec.total_income = 0.0
if rec.mother_status == 'non_benefit':
total = sum(rec.salary_ids.filtered(lambda e: e.approved).mapped('salary_amount'))
elif rec.mother_status == 'benefit':
total = sum(rec.salary_ids.filtered(lambda e: e.approved).mapped('salary_amount')) + rec.mother_income
rec.total_income = total
def get_mother_name(self):
for rec in self:
name = ''
if all([rec.mother_name, rec.mother_second_name, rec.mother_third_name, rec.mother_family_name]):
name = rec.mother_name + " " + rec.mother_second_name + " " + rec.mother_third_name + " " + rec.mother_family_name
else:
name = name
return name
def get_replacement_mother_name(self):
for rec in self:
name = ''
if all([rec.replacement_mother_name, rec.replacement_mother_second_name, rec.replacement_mother_third_name,
rec.replacement_mother_family_name]):
name = rec.replacement_mother_name + " " + rec.replacement_mother_second_name + " " + rec.replacement_mother_third_name + " " + rec.replacement_mother_family_name
else:
name = name
return name
def add_or_replace_mother_as_member(self):
FamilyMember = self.env['family.member']
Relation = self.env['relation.settings'].search([('relation_type', '=', 'mother')], limit=1)
for rec in self:
mother_name = rec.get_mother_name()
val = {
'name': mother_name,
'mother_first_name': rec.mother_name,
'mother_second_name': rec.mother_second_name,
'mother_third_name': rec.mother_third_name,
'mother_family_name': rec.mother_family_name,
'member_id_number': rec.mother_id_number,
'is_mother': True,
'birth_date': rec.mother_birth_date,
'gender': 'female',
'relationn': Relation.id,
'mother_marital_conf': rec.mother_marital_conf.id,
'member_location_conf': rec.mother_location_conf.id,
'age': rec.mother_age,
'is_work': rec.is_mother_work,
'member_income': rec.mother_net_income,
'education_status': rec.education_status,
#'member_status': rec.mother_status,
'member_education_status_ids': [(5, 0)] + [(4, edu.id) for edu in rec.mother_education_status_ids],
'salary_certificate': [(6, 0, rec.mother_salary_certificate.ids)],
}
mother_family_member = rec.mother_family_member_id
if mother_family_member:
mother_family_member.write(val)
else:
val['benefit_id'] = rec.id
mother_family_member = FamilyMember.create(val)
rec.write({'mother_family_member_id': mother_family_member.id})
rec.mother_diseases_attachment_ids.write({'member_id': mother_family_member.id})
rec.mother_disabilities_attachment_ids.write({'member_id': mother_family_member.id})
def add_or_replace_replacement_mother_as_member(self):
FamilyMember = self.env['family.member']
for rec in self:
mother_name = rec.get_replacement_mother_name()
val = {
'name': mother_name,
'mother_first_name': rec.replacement_mother_name,
'mother_second_name': rec.replacement_mother_second_name,
'mother_third_name': rec.replacement_mother_third_name,
'mother_family_name': rec.replacement_mother_family_name,
'member_id_number': rec.replacement_mother_id_number,
'is_mother': False,
'birth_date': rec.replacement_mother_birth_date,
'gender': 'female',
'relationn': rec.replacement_mother_relation.id,
'mother_marital_conf': rec.replacement_mother_marital_conf.id,
'member_location_conf': rec.replacement_mother_location_conf.id,
'age': rec.replacement_mother_age,
'is_work': rec.replacement_is_mother_work,
'member_income': rec.replacement_mother_income,
'education_status': rec.replacement_education_status,
#'member_status': rec.replacement_mother_status,
'member_education_status_ids': [(5, 0)] + [(4, edu.id) for edu in rec.replacement_education_status_ids],
'salary_certificate': [(6, 0, rec.replacement_mother_salary_certificate.ids)],
}
if rec.replacement_mother_family_member_id:
rec.replacement_mother_family_member_id.write(val)
replacement_member = rec.replacement_mother_family_member_id
else:
val['benefit_id'] = rec.id
replacement_member = FamilyMember.create(val)
rec.write({'replacement_mother_family_member_id': replacement_member.id})
rec.replacement_mother_diseases_attachment_ids.write({'member_id': replacement_member.id})
rec.replacement_mother_disabilities_attachment_ids.write({'member_id': replacement_member.id})
@api.depends('benefit_member_count','total_income','total_expenses')
def get_member_income(self):
for ben in self:
income = 0.0
family_income = ben.total_income - ben.total_expenses
if ben.benefit_member_count:
if ben.benefit_member_count > 3:
income = family_income / ben.benefit_member_count
elif ben.benefit_member_count <= 3:
income = family_income / 3
else:
income = family_income
ben.member_income = round(income, 0)
@api.depends("member_income")
def get_benefit_category(self):
default_category = self.env['benefit.category'].sudo().search(
[('is_benefit', '=', False)], limit=1
)
for record in self:
if record.benefit_member_count <= 0:
record.benefit_category_id = default_category.id if default_category else False
continue
category = self.env['benefit.category'].sudo().search(
[
('mini_income_amount', '<=', record.member_income),
('max_income_amount', '>=', record.member_income)
],
limit=1
)
record.benefit_category_id = category.id if category else default_category.id
def open_followers(self):
context = {}
context['default_benefit_id'] = self.id
return {
'name': _('Benefit Followers'),
'view_type': 'form',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_benefit.benefit_followers_tree').id, 'tree'),
(self.env.ref('odex_benefit.benefit_followers_form').id, 'form')],
'res_model': 'benefit.followers',
'type': 'ir.actions.act_window',
'context': context,
'domain': "[('benefit_id','=',%s)]" % (self.id),
'target': 'current',
}
def open_expenses(self):
context = {}
context['default_benefit_id'] = self.id
return {
'name': _('Benefit Expenses'),
'view_type': 'form',
'view_mode': 'tree,form',
'views': [(self.env.ref(
'odex_benefit.benefit_expenses_tree').id, 'tree'),
(self.env.ref('odex_benefit.expenses_line_form').id, 'form')],
'res_model': 'benefit.expenses',
'type': 'ir.actions.act_window',
'context': context,
'domain': "[('benefit_id','=',%s)]" % (self.id),
'target': 'current',
}
@api.depends('father_birth_date')
def _compute_get_father_age(self):
for rec in self:
if rec.father_birth_date:
today = date.today()
day = datetime.strptime(str(rec.father_birth_date), DEFAULT_SERVER_DATE_FORMAT)
age = rd(today, day)
rec.father_age = age.years
else:
rec.father_age = 0
@api.depends('mother_birth_date')
def _compute_get_mother_age(self):
for rec in self:
if rec.mother_birth_date:
today = date.today()
day = datetime.strptime(str(rec.mother_birth_date), DEFAULT_SERVER_DATE_FORMAT)
age = rd(today, day)
rec.mother_age = age.years
else:
rec.mother_age = 0
@api.depends('replacement_mother_birth_date')
def _compute_get_replacement_mother_age(self):
for rec in self:
if rec.replacement_mother_birth_date:
today = date.today()
day = datetime.strptime(str(rec.replacement_mother_birth_date), DEFAULT_SERVER_DATE_FORMAT)
age = rd(today, day)
rec.replacement_mother_age = age.years
else:
rec.replacement_mother_age = 0
def action_finish_edit(self):
for rec in self:
#group_e = self.env.ref('odex_benefit.group_benefit_edit', False)
#group_e.write({'users': [(3, self.user_id.id)]})
rec.state = rec.old_stage
# @api.multi
def edit_password(self):
if self.user_id:
self.user_id.sudo().action_reset_password()
def create_family_partner(self):
bank_val = {
'acc_number':self.acc_number,
'acc_holder_name':self.acc_holder_name,
'bank_id':self.bank_id.id,
}
partner = self.env['res.partner'].create({
'name': self.name,
'email': self.email,
'phone': self.phone,
# 'account_type':'family',
'is_family': True,
'code':self.code,
'bank_ids': [(0,0,bank_val)]
})
self.partner_id = partner.id
# def create_member_partner(self):
# # bank_val = {
# # 'acc_number':self.acc_number,
# # 'partner_id':self.account_holder,
# # 'bank_name':self.bank_name,
# # }
# partner = self.env['res.partner'].create({
# 'name': self.name,
# 'email': self.email,
# 'phone': self.phone,
# 'account_type':'member',
# 'code':self.code,
# # 'bank_ids': [(0,0,bank_val)]
# })
# self.partner_id = partner.id
def create_user(self):
bank_val = {
'acc_number':self.acc_number,
'acc_holder_name':self.acc_holder_name,
'bank_id':self.bank_id.id,
}
for follower in self['message_follower_ids']:
follower.sudo().unlink()
if not self.partner_id:
partner = self.create_family_partner()
self.partner_id.write({
'name': self.name,
'email': self.email,
'phone': self.phone,
# 'account_type': 'family',
'is_family': True,
'code': self.code,
})
if bank_val['acc_number'] and bank_val['acc_holder_name'] and bank_val['bank_id']:
self.partner_id.write({
'bank_ids': [(0,0,bank_val)]
})
user = self.env['res.users'].sudo().with_context(no_reset_password=True).create({
'name': self.name,
'login': self.sms_phone or self.email,
'partner_id': self.partner_id.id,
'active': True,
'otp_mobile_phone': self.sms_phone,
})
self.user_id = user.id
if self.password:
user.sudo().write({'password': self.password, })
user.sudo().write({
'groups_id': [(3, self.env.ref('base.group_user', False).id)],
})
user.sudo().write({
'groups_id': [(4, self.env.ref('base.group_portal', False).id)],
})
# @api.multi
def send_approval_benefit_email(self):
"""Send approval email when benefit registration is accepted"""
template = self.env.ref('odex_benefit.approval_benefit_email', False)
if not template:
return
template.with_context(lang=self.env.user.lang).send_mail(self.id, force_send=True, raise_exception=False)
# @api.multi
def _send_notification(self, partner_ids, state):
"""Send notification when entity state changes"""
subject = _('Beneficial')
state_label = dict(self.fields_get(allfields=['state'])['state']['selection'])[state]
body = ' '.join((_(u'The Beneficiaries '), self.name, _(u' State changed to '), state_label, u'.')).encode(
'utf-8')
partner_list_ids = []
for id in partner_ids:
partner_list_ids.append(id.id)
message_vals = {
'subject': subject,
'body': body,
'partner_ids': partner_list_ids,
# 'model': self._name,
# 'res_id': self.id,
}
test = self.sudo().message_post(message_type="notification", subtype_xmlid="mt_comment",
**message_vals)
def send_black_list_email(self):
"""Send black list email when entity black list"""
template = self.env.ref('odex_benefit.black_list_entity_email', False)
if not template:
return
template.with_context(lang=self.env.user.lang).send_mail(self.id, force_send=True, raise_exception=False)
# @api.multi
def send_remove_from_black_list_email(self):
"""Send black list email when entity black list"""
template = self.env.ref('odex_benefit.black_list_remove_benefit_email', False)
if not template:
return
template.with_context(lang=self.env.user.lang).send_mail(self.id, force_send=True, raise_exception=False)
# # Validation Opertaion
# @api.onchange('phone', 'phone2','sms_phone')
# def _onchange_mobile_validation(self):
# if self.phone:
# if self.phone.startswith('+966'):
# phone = self.phone[4:]
# self.phone = phone
# if re.match(SAUDI_MOBILE_PATTERN, self.phone) == None:
# raise ValidationError(
# _('Enter a valid Saudi mobile number'))
# if self.phone2:
# if self.phone2.startswith('+966'):
# phone2 = self.phone2[4:]
# self.phone2 = phone2
# if re.match(SAUDI_MOBILE_PATTERN, self.phone2) == None:
# raise ValidationError(
# _('Enter a valid Saudi mobile number'))
# if self.sms_phone:
# if self.sms_phone.startswith('+966'):
# sms_phone = self.sms_phone[4:]
# self.sms_phone = sms_phone
# if re.match(SAUDI_MOBILE_PATTERN, self.sms_phone) == None:
# raise ValidationError(
# _('Enter a valid Saudi mobile number'))
@api.constrains('phone', 'phone2','sms_phone')
def _onchange_phone_numbers(self):
phone_numbers = {
#'الهاتف': self.phone,
'رقم الجوال الثاني': self.phone2,
'رقم الجوال للتواصل': self.sms_phone,
}
# Check each ID number for 10-digit format and uniqueness within the parent model
unique_ids = set()
for label, phone_number in phone_numbers.items():
if phone_number:
if re.match(SAUDI_MOBILE_PATTERN,phone_number) == None:
raise ValidationError(
_('Enter a valid Saudi mobile number'))
if phone_number in unique_ids:
raise ValidationError(_("%s must be unique within the same record.") % label)
unique_ids.add(phone_number)
# Check for uniqueness against `member_phone` in child records and across database records
for member in self.member_ids:
if member.member_phone and member.member_phone in unique_ids:
raise ValidationError(
_("The Phone Number %s in the Family Members list must be unique across the record.") % member.member_phone)
# Check for duplicate IDs across records in the database
for phone_number in unique_ids:
duplicate_record_family = self.env['grant.benefit'].search([
'|', ('phone2', '=', phone_number),
('sms_phone', '=', phone_number), ('id', '!=', self._origin.id)
], limit=1)
duplicate_record_member = self.env['family.member'].search([('member_phone', '=', phone_number)], limit=1)
if duplicate_record_family:
raise ValidationError(
_("The phone number {} already exists in family with code {}.").format(
phone_number, duplicate_record_family.code))
if duplicate_record_member:
raise ValidationError(
_("The phone {} already exists in family with code {}.").format(
phone_number, duplicate_record_member.benefit_id.code))
@api.onchange('email')
def onchange_email(self):
if self.email:
for rec in self:
exist = self.search([('email', '=', rec.email)])
if exist:
raise ValidationError(
_('The Email Already Exist!'))
@api.onchange('sms_phone')
def onchange_sms_phone(self):
if self.sms_phone:
for rec in self:
exist = self.search([('sms_phone', '=', rec.sms_phone)])
if exist:
raise ValidationError(
_('The SMS phone Already Exist!'))
@api.onchange('acc_number')
def onchange_acc_number(self):
if self.acc_number:
# Check if the value is numeric before anything else
if not self.acc_number.isdigit():
raise ValidationError(_("The account number should contain only digits."))
# Check if the account number contains exactly 22 digits
if len(self.acc_number) != 22:
raise ValidationError(_("The IBAN number must contain exactly 22 digits."))
# Check if the account number already exists in the partner bank or benefit
#partner_exist = self.env['res.partner.bank'].search([('acc_number', '=', self.acc_number)], limit=1)
#benefit_exist = self.search([('acc_number', '=', self.acc_number)], limit=1)
#if partner_exist or benefit_exist:
# raise ValidationError(_("The account number already exists!"))
@api.onchange('mother_marital_conf', 'mother_location_conf', 'mother_net_income')
def _onchange_mother_info(self):
res = {}
if self.mother_status == 'non_benefit':
res['warning'] = {'title': _('ValidationError'),
'message': _('Not Benefit')}
return res
@api.onchange('replacement_mother_marital_conf', 'replacement_mother_location_conf')
def _onchange_replacement_mother_info(self):
res = {}
for rec in self:
if rec.replacement_mother_status == 'non_benefit':
res['warning'] = {'title': _('ValidationError'),
'message': _('Not Benefit')}
return res
def create_scheduled_visit(self):
records = self.env["grant.benefit"].search([('state', '=', 'second_approve')])
recurrence_visit_id = self.env.ref('odex_benefit.recurrence_visit')
period_unit = {
recurrence_visit_id.recurrence_period: recurrence_visit_id.recurrence_interval
}
for rec in records.filtered(lambda r: r.last_visit_date and (r.last_visit_date + rd(**period_unit)).date() <= fields.Date.context_today(self)):
self.env['visit.location'].create({
'benefit_id': rec.id,
'visit_date': date.today(),
'visit_types': recurrence_visit_id.id,
'selector': 'researcher',
'researcher_id': rec.researcher_id.id,
# 'researcher_team': rec.researcher_team.id,
'state': 'draft'
})
def create_manual_visit(self):
self.env['visit.location'].create({
'benefit_id': self.id,
'visit_date': date.today(),
'visit_types': 2,
# 'selector': 'researcher',
'researcher_id': self.researcher_id.id,
# 'researcher_team': rec.researcher_team.id,
'state': 'draft'
})
def change_attachment_status(self):
obj = self.env["grant.benefit"].search([])
for attach in obj.attachment_ids:
attach.get_status()
# Notifications
def send_expiry_date_notification(self):
self.change_attachment_status()
obj = self.env["grant.benefit"].search([])
for rec in obj:
for attach in rec.attachment_ids:
if attach.attach_status == 'expired':
template = self.env.ref('odex_benefit.attachment_expiration_family_email_template', False)
if not template:
return
template.with_context(lang=self.env.user.lang).send_mail(rec.id, force_send=True,
raise_exception=False)
#Update data automatically daily
def update_data_automatically(self):
obj = self.env["grant.benefit"].search([])
for member in obj.member_ids:
# member._compute_get_age_date()
member.check_member_status()
self.action_auto_suspend()
class BenefitFollowers(models.Model):
_name = 'benefit.followers'
_inherit = ['mail.thread', 'mail.activity.mixin']
benefit_id = fields.Many2one('grant.benefit', )
name = fields.Many2one('grant.benefit', domain="[('is_responsible','=',False)]")
follower_type = fields.Selection(
[('benefit', 'benefit'), ('orphan', 'orphan'), ('widow', 'widow'), ('poor', 'poor'), ('other', 'other'),
], string='Benefit Type', tracking=True, related="name.benefit_type", )
birth_date = fields.Date(related="name.birth_date", string="Birth Date")
age = fields.Integer(string="Age", compute='_compute_get_age_date', store=True)
gender = fields.Selection(selection=[('male', 'Male'), ('female', 'Female')], string="Gender",
related="name.gender", )
is_live_with_family = fields.Boolean('Is Live With Family')
@api.depends('birth_date')
def _compute_get_age_date(self):
for rec in self:
if rec.birth_date:
today = date.today()
day = datetime.strptime(rec.birth_date, DEFAULT_SERVER_DATE_FORMAT)
age = rd(today, day)
rec.age = age.years
class WidowFamily(models.Model):
_name = 'widow.family'
benefit_id = fields.Many2one('grant.benefit')
widow_name = fields.Many2one('grant.benefit', domain="[('benefit_type','=','widow')]", string='Widow Name')
widows_husband = fields.Char('Widows Husband', related="widow_name.husband_name")
widows_husband_id = fields.Char('Widows Husband ID', related="widow_name.husband_id")
date_death_husband = fields.Date(related="widow_name.date_death_husband")
class divorceeFamily(models.Model):
_name = 'divorcee.family'
benefit_id = fields.Many2one('grant.benefit')
divorcee_name = fields.Many2one('grant.benefit', 'divorcee Name')
divorcee_husband = fields.Char('Widows Husband', related="divorcee_name.husband_name")
divorcee_husband_id = fields.Char('Widows Husband ID', related="divorcee_name.husband_id")
date_divorcee = fields.Date(related="divorcee_name.date_divorcee")
class ExternalBenefit(models.Model):
_name = 'external.benefits'
_inherits = {'res.partner': 'partner_id'}
_inherit = ['mail.thread', 'mail.activity.mixin']
location = fields.Char(string='location')
benefit_nationality = fields.Many2one('res.country', 'Benefit Nationality')
block = fields.Char('Benefit Block')
work = fields.Char()
partner_id = fields.Many2one('res.partner', string='partner', required=True, ondelete="cascade")
@api.onchange('first_name', 'second_name', 'middle_name', 'family_name')
def get_benefit_name(self):
for rec in self:
if rec.first_name and rec.second_name and rec.middle_name and rec.family_name:
rec.name = rec.first_name + " " + rec.second_name + " " + rec.middle_name + " " + rec.family_name
def create_partner(self):
partner = self.env['res.partner'].create({
'name': self.name,
'email': self.email,
'phone': self.phone,
# 'city': self.city_id.name if self.city_id else False,
# 'country_id': self.country_id.id,
})
self.partner_id = partner.id
# neighborhood representative
class Representative(models.Model):
_name = 'benefits.representative'
_inherits = {'res.partner': 'partner_id'}
_inherit = ['mail.thread', 'mail.activity.mixin']
location = fields.Char(string='location')
block = fields.Char('Benefit Block')
work = fields.Char()
partner_id = fields.Many2one('res.partner', string='partner', required=True, ondelete="cascade")