# -*- 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)) 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='') # 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) total_income = fields.Float('Total Income', compute="get_total_income", store=True) benefit_member_count = fields.Integer(string="Members count", compute="get_members_count") non_member_count = fields.Integer(string="Non Benefit Members count", compute="get_non_members_count") member_income = fields.Integer(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'), ('5', '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,) _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('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)] @api.depends('mother_income', 'is_mother_work','mother_expenses_ids','mother_debits_ids') def _compute_mother_net_income(self): for rec in self: if not rec.is_mother_work: rec.mother_net_income = 0.0 continue 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')) ) rec.mother_net_income = max(rec.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 if rec.rent_amount > 0 and rec.property_type_id and rec.property_type_code == 'rent': if rec.branch_custom_id.branch_type == 'branches': estimated_rent_amount = self.env['rent.lines'].search( [('benefit_count', '=', rec.benefit_member_count)], order="estimated_rent_branches desc",limit=1).estimated_rent_branches else: estimated_rent_amount = self.env['rent.lines'].search( [('benefit_count', '=', rec.benefit_member_count)], order="estimated_rent_governorate desc",limit=1).estimated_rent_governorate rec.estimated_rent_amount = min(estimated_rent_amount, rec.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'') rec.url_html = f'