Rent Customization

This commit is contained in:
eman 2024-11-05 15:37:17 +02:00
parent 97881509ba
commit 78ad0d2a48
8 changed files with 192 additions and 32 deletions

View File

@ -8,7 +8,7 @@
'license': 'GPL-3',
'author': 'Expert Ltd',
'depends': ['base', 'takaful_core', 'website', 'account', 'report_xlsx', 'sale', 'product', 'stock', 'hr',
'purchase','web_google_maps'],
'purchase','web_google_maps','odex25_account_payment_fix'],
'data': [
'security/security_view.xml',
'security/ir.model.access.csv',

View File

@ -408,6 +408,7 @@ class GrantBenefitProfile(models.Model):
rent_start_date = fields.Date(string='Rent Start Date')
rent_end_date = fields.Date(string='Rent End Date')
rent_attachment = fields.Many2many('ir.attachment','rel_rent_attachment_attachment','benefit_id','attachment_id',string='Rent Attachment')
payment_type = fields.Selection([('1', 'Yearly'),('2', 'Half Year'),('4', 'Quarterly')],string='Payment Type')
housing_cat = fields.Selection([
('excellent', 'Excellent'),
('good', 'Good'),

View File

@ -1,3 +1,4 @@
from gevent.os import nb_write
from odoo import fields, models, api, _
from odoo.exceptions import UserError, ValidationError
from datetime import timedelta
@ -26,16 +27,38 @@ class ServiceRequest(models.Model):
service_cat = fields.Many2one('services.settings',string='Service Cat.')
service_attach = fields.Many2many('ir.attachment', 'rel_service_attachment_service_request', 'service_request_id','attachment_id', string='Service Attachment')
requested_service_amount = fields.Float(string="Requested Service Amount")
#yearly Estimated Rent Amount
estimated_rent_amount = fields.Float(string="Estimated Rent Amount",compute="_get_estimated_rent_amount")
#The value of payment by payment method(yearly-half-quartarly)
estimated_rent_amount_payment = fields.Float(string="Estimated Rent Amount Payment",compute="_get_estimated_rent_amount_payment")
paid_rent_amount = fields.Float(string="Paid Rent Amount",compute="_get_paid_rent_amount")
service_type = fields.Selection([('rent', 'Rent')],string='Service Type',related='service_cat.service_type')
# is_alternative_housing = fields.Boolean(string='Is Alternative Housing?')
rent_contract_number = fields.Char(string="Rent Contract Number",related ="family_id.contract_num")
rent_start_date = fields.Date(string='Rent Start Date',related ="family_id.rent_start_date")
rent_end_date = fields.Date(string='Rent End Date' ,related ="family_id.rent_end_date")
rent_amount = fields.Float(string='Rent Amount',related ="family_id.rent_amount")
rent_attachment = fields.Many2many('ir.attachment', 'rel_rent_attachment_service_request', 'service_request_id', 'attachment_id',string='Rent Attachment',related ="family_id.rent_attachment")
rent_contract_number = fields.Char(string="Rent Contract Number",compute='_compute_rent_details',store=True)
rent_start_date = fields.Date(string='Rent Start Date',compute='_compute_rent_details',store=True)
rent_end_date = fields.Date(string='Rent End Date' ,compute='_compute_rent_details',store=True)
rent_amount = fields.Float(string='Rent Amount',compute='_compute_rent_details',store=True)
rent_amount_payment = fields.Float(string='Rent Amount Payment',compute ='_get_rent_amount_payment')
payment_type = fields.Selection([('1', 'Yearly'),('2', 'Half Year'),('4', 'Quarterly')],string='Payment Type',compute='_compute_rent_details',store=True)
rent_attachment = fields.Many2many('ir.attachment', 'rel_rent_attachment_service_request', 'service_request_id', 'attachment_id',string='Rent Attachment',compute='_compute_rent_details',store=True)
rent_payment_date = fields.Date(string='Rent Payment Date')
rent_payment_date_exception = fields.Boolean(string='Rent Payment Date Exception?')
start = fields.Date(string="Start Date")
end = fields.Date(string='End Date')
#New Rent Contract
new_rent_contract = fields.Boolean(string='New Rent Contract?')
new_start = fields.Date(string="Start Date")
new_end = fields.Date(string='End Date')
new_rent_contract_number = fields.Char(string="Rent Contract Number")
new_rent_start_date = fields.Date(string='Rent Start Date')
new_rent_end_date = fields.Date(string='Rent End Date')
new_rent_amount = fields.Float(string='Rent Amount')
new_rent_amount_payment = fields.Float(string='New Rent Amount Payment',compute='_get_new_rent_amount_payment')
new_payment_type = fields.Selection([('1', 'Yearly'), ('2', 'Half Year'), ('4', 'Quarterly')], string='Payment Type')
new_rent_attachment = fields.Many2many('ir.attachment', 'rel_rent_attachment_service_request', 'service_request_id',
'attachment_id', string='Rent Attachment')
new_rent_payment_date = fields.Date(string='Rent Payment Date')
new_rent_payment_date_exception = fields.Boolean(string='Rent Payment Date Exception?')
# Rent details for member
member_rent_contract_number = fields.Char(string="Rent Contract Number")
member_rent_start_date = fields.Date(string='Rent Start Date')
@ -64,6 +87,13 @@ class ServiceRequest(models.Model):
('refused', 'Refused'),
], string='state', default="draft", tracking=True)
@api.model
def search(self, args, offset=0, limit=None, order=None, count=False):
if self.env.user and self.env.user.id and self.env.user.has_group(
"odex_benefit.group_benefit_accountant_accept"):
args += [('accountant_id', '=', self.env.user.id)]
return super(ServiceRequest, self).search(args, offset, limit, order, count)
@api.model
def create(self, vals):
res = super(ServiceRequest, self).create(vals)
@ -71,12 +101,59 @@ class ServiceRequest(models.Model):
res.name = self.env['ir.sequence'].sudo().next_by_code('service.request.sequence') or _('New')
return res
def write(self, vals):
# Define the list of fields you want to check
new_rent_fields = ['new_rent_contract_number', 'new_rent_start_date', 'new_rent_end_date', 'new_rent_amount',
'new_payment_type', 'new_rent_attachment']
# Call the original write method
result = super(ServiceRequest, self).write(vals)
# Prepare values for family_id write, only if any of the fields are present in vals
update_values = {}
if any(field in vals for field in new_rent_fields):
# Use `get` to avoid KeyError if a field is missing in vals
update_values = {
'contract_num': vals.get('new_rent_contract_number'),
'rent_start_date': vals.get('new_rent_start_date'),
'rent_end_date': vals.get('new_rent_end_date'),
'rent_amount': vals.get('new_rent_amount'),
'payment_type': vals.get('new_payment_type'),
}
# Check if 'new_rent_attachment' exists in vals before updating
if 'new_rent_attachment' in vals:
update_values['rent_attachment'] = vals['new_rent_attachment']
# Write the prepared update values to `family_id`
self.family_id.write(update_values)
return result
def unlink(self):
for request in self:
if request.state not in ['draft']:
raise UserError(_('You cannot delete this record'))
return super(ServiceRequest, self).unlink()
@api.depends('family_id')
def _compute_rent_details(self):
for rec in self:
# Compute values only if they are not already set
if rec.family_id:
if not rec.rent_contract_number:
rec.rent_contract_number = rec.family_id.contract_num
if not rec.rent_start_date:
rec.rent_start_date = rec.family_id.rent_start_date
if not rec.rent_end_date:
rec.rent_end_date = rec.family_id.rent_end_date
if not rec.rent_amount:
rec.rent_amount = rec.family_id.rent_amount
if not rec.payment_type:
rec.payment_type = rec.family_id.payment_type
if not rec.rent_attachment:
rec.rent_attachment = rec.family_id.rent_attachment
def _get_estimated_rent_amount(self):
for rec in self:
rec.estimated_rent_amount = 0.0 # Default value
@ -100,9 +177,31 @@ class ServiceRequest(models.Model):
rec.estimated_rent_amount = item.estimated_rent_governorate * (
item.discount_rate_shared_housing if is_shared_rent else 1)
def _get_estimated_rent_amount_payment(self):
for rec in self:
if rec.estimated_rent_amount and rec.payment_type:
rec.estimated_rent_amount_payment = rec.estimated_rent_amount / int(rec.payment_type)
elif rec.estimated_rent_amount and rec.new_payment_type:
rec.estimated_rent_amount_payment = rec.estimated_rent_amount / int(rec.new_payment_type)
else:
rec.estimated_rent_amount_payment = 0.0
def _get_rent_amount_payment(self):
for rec in self:
if rec.rent_amount and rec.payment_type:
rec.rent_amount_payment = rec.rent_amount / int(rec.payment_type)
else:
rec.rent_amount_payment = 0.0
def _get_new_rent_amount_payment(self):
for rec in self:
if rec.new_rent_amount and rec.new_payment_type:
rec.new_rent_amount_payment = rec.new_rent_amount / int(rec.new_payment_type)
else:
rec.new_rent_amount_payment = 0.0
def _get_paid_rent_amount(self):
for rec in self:
rec.paid_rent_amount = min(rec.estimated_rent_amount, rec.requested_service_amount)
rec.paid_rent_amount = min(rec.estimated_rent_amount_payment, rec.requested_service_amount)
def _get_added_amount_if_mother_dead(self):
for rec in self:
@ -161,14 +260,18 @@ class ServiceRequest(models.Model):
if rec.service_cat.service_type == 'home_restoration' and rec.family_id.property_type != 'ownership' and rec.family_id.property_type != 'ownership_shared' and rec.family_id.property_type != 'charitable' and rec.benefit_type == 'family':
raise UserError(_("You cannot benefit from this service (property type not ownership)"))
@api.onchange('rent_payment_date')
@api.onchange('rent_payment_date','new_rent_payment_date')
def onchange_rent_payment_date(self):
today_date = fields.Date.today()
for rec in self:
if rec.rent_payment_date :
if rec.rent_payment_date and not rec.rent_payment_date_exception and not rec.new_rent_payment_date:
month_before_rent_payment_date = rec.rent_payment_date - timedelta(days=30)
if today_date > month_before_rent_payment_date:
raise UserError(_("You Should request At least a month ago rent payment date"))
if rec.new_rent_payment_date and not rec.new_rent_payment_date_exception:
new_month_before_rent_payment_date = rec.new_rent_payment_date - timedelta(days=30)
if today_date > new_month_before_rent_payment_date:
raise UserError(_("You Should request At least a month ago rent payment date"))
@api.onchange('requested_service_amount','benefit_type','date')
def onchange_requested_service_amount(self):
for rec in self:
@ -191,6 +294,22 @@ class ServiceRequest(models.Model):
if rec.member_id and rec.member_id.member_location != 'study_inside_saudi_arabia':
raise UserError(_("You Cannot request Service if you not study inside Saudi Arabia"))
@api.onchange('start', 'end', 'rent_start_date', 'rent_end_date','new_start', 'new_end', 'new_rent_start_date', 'new_rent_end_date', 'new_rent_contract')
def _check_date_range(self):
for rec in self:
# Ensure both start and end dates are set
if rec.start and rec.end and rec.rent_start_date and rec.rent_end_date and not rec.new_rent_contract:
# Check if `start` and `end` are within `rent_start_date` and `rent_end_date`
if not (rec.rent_start_date <= rec.start <= rec.rent_end_date and
rec.rent_start_date <= rec.end <= rec.rent_end_date):
raise UserError(
"The Start Date and End Date must be within the Rent Start Date and Rent End Date range.")
if rec.new_start and rec.new_end and rec.new_rent_start_date and rec.new_rent_end_date and rec.new_rent_contract :
# Check if `start` and `end` are within `rent_start_date` and `rent_end_date`
if not (rec.new_rent_start_date <= rec.new_start <= rec.new_rent_end_date and
rec.new_rent_start_date <= rec.new_end <= rec.new_rent_end_date):
raise UserError(
"The Start Date and End Date must be within the Rent Start Date and Rent End Date range.")
@api.onchange('family_category', 'sub_service_category')
def _onchange_service_cat_domain(self):

View File

@ -60,13 +60,16 @@
<record id="group_benefit_accounting_accept" model="res.groups">
<field name="name">Accounting Accept</field>
<field name="category_id" ref="module_category_benefit"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
</record>
<record id="group_benefit_accountant_accept" model="res.groups">
<field name="name">Accountant Accept</field>
<field name="category_id" ref="odex25_account_payment_fix.module_category_payment_access"/>
<!-- <field name="implied_ids" eval="[(4, ref('group_benefit_info'))]"/>-->
</record>
<record id="group_accept_income_and_expenses" model="res.groups">
<field name="name">Accept income and expenses</field>
<field name="category_id" ref="module_category_benefit"/>
<field name="users" eval="[(4, ref('base.user_root'))]"/>
</record>
</data>
</odoo>

View File

@ -766,6 +766,7 @@
<field name="property_type"
attrs="{'required':[('state','!=','draft')],'readonly':[('state','not in',['draft','complete_info','edit_info'])]}"/>
<field name="rent_amount" attrs="{'readonly':[('state','not in',['draft','complete_info','edit_info'])],'invisible':[('property_type','!=','rent'),('property_type','!=','rent_shared')]}"/>
<field name="payment_type" attrs="{'readonly':[('state','not in',['draft','complete_info','edit_info'])],'invisible':[('property_type','!=','rent'),('property_type','!=','rent_shared')]}"/>
<field name="contract_num" attrs="{'readonly':[('state','not in',['draft','complete_info','edit_info'])],'invisible':[('property_type','!=','rent'),('property_type','!=','rent_shared')]}"/>
<field name="rent_start_date" attrs="{'readonly':[('state','not in',['draft','complete_info','edit_info'])],'invisible':[('property_type','!=','rent'),('property_type','!=','rent_shared')]}"/>
<field name="rent_end_date" attrs="{'readonly':[('state','not in',['draft','complete_info','edit_info'])],'invisible':[('property_type','!=','rent'),('property_type','!=','rent_shared')]}"/>

View File

@ -41,26 +41,26 @@
</h1>
</div>
<group>
<field name="date" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="benefit_type" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="family_id" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="date" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="benefit_type" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="family_id" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="family_category" force_save="1"/>
<field name="benefit_member_count" force_save="1"/>
<field name="branch_custom_id" force_save="1"/>
<field name="member_id" attrs="{'invisible':[('benefit_type','!=','member')],'readonly':[('state','not in',['draft','send_request'])],'required':[('benefit_type','=','member')]}"/>
<field name="member_id" attrs="{'invisible':[('benefit_type','!=','member')],'readonly':[('state','not in',['draft','researcher','send_request'])],'required':[('benefit_type','=','member')]}"/>
<field name="account_id"/>
<field name="accountant_id" attrs="{'invisible':[('state','in',['draft','researcher','send_request','first_approve','second_approve'])]}"/>
<field name="is_service_producer" invisible="1"/>
<field name="service_producer_id" attrs="{'invisible':[('is_service_producer','=',False)]}"/>
<field name="service_producer_id" attrs="{'invisible':[('is_service_producer','=',False)],'readonly':[('state','not in',['draft','researcher','send_request'])]}"/>
</group>
<group>
<field name="need_status" attrs="{'readonly':[('state','not in',['draft','send_request'])]}"/>
<field name="main_service_category" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="sub_service_category" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="service_cat" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="requested_service_amount" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" required="1"/>
<field name="description" attrs="{'readonly':[('state','not in',['draft','send_request'])]}"/>
<field name="service_attach" attrs="{'readonly':[('state','not in',['draft','send_request'])]}" widget="many2many_attachment_preview"/>
<field name="need_status" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}"/>
<field name="main_service_category" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="sub_service_category" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="service_cat" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="requested_service_amount" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" required="1"/>
<field name="description" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}"/>
<field name="service_attach" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" widget="many2many_attachment_preview"/>
<field name="service_type" invisible="1"/>
</group>
</group>
@ -82,26 +82,62 @@
<group>
<separator string="Rent Contract Information" colspan="2"/>
<br/>
<field name="rent_payment_date" attrs="{'required':[('service_type','=','rent')]}"/>
<field name="rent_payment_date_exception" widget="boolean_toggle"/>
<field name="rent_payment_date" attrs="{'required':[('service_type','=','rent'),('new_rent_contract','=',False)]}"/>
<field name="rent_contract_number" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="rent_start_date" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="rent_end_date" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<label for="start" string="Period" />
<div name="dates" class="o_row">
<field name="start" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}"/>
<i class="fa fa-long-arrow-right mx-2 oe_edit_only" aria-label="Arrow icon" title="Arrow" />
<i class="fa fa-long-arrow-right mx-2 oe_read_only" aria-label="Arrow icon" title="Arrow" attrs="{'invisible': [('start', '=', False), ('end', '=', False)]}" />
<field name="end" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" />
</div>
<field name="rent_amount" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="rent_amount_payment" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="payment_type" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="rent_attachment" widget="many2many_attachment_preview" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="member_rent_contract_number" attrs="{'invisible':[('benefit_type','!=','member')]}"/>
<field name="member_rent_start_date" attrs="{'invisible':[('benefit_type','!=','member')]}"/>
<field name="member_rent_end_date" attrs="{'invisible':[('benefit_type','!=','member')]}"/>
<field name="member_rent_attachment" widget="many2many_attachment_preview" attrs="{'invisible':[('benefit_type','!=','member')]}"/>
<field name="new_rent_contract" widget="boolean_toggle" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<!-- <field name="is_alternative_housing" widget="boolean_toggle"/>-->
</group>
<group attrs="{'invisible':[('benefit_type','!=','family')]}">
<separator string="Rent Amounts" colspan="2"/>
<br/>
<field name="estimated_rent_amount"/>
<field name="estimated_rent_amount_payment"/>
<field name="paid_rent_amount"/>
<field name="added_amount_if_mother_dead"/>
</group>
</group>
<group attrs="{'invisible':[('new_rent_contract','=',False)]}">
<group>
<separator string="New Rent Contract Information" colspan="2"/>
<br/>
<field name="new_rent_payment_date_exception" widget="boolean_toggle"/>
<field name="new_rent_payment_date" attrs="{'required':[('service_type','=','rent'),('new_rent_contract','=',True)]}"/>
<field name="new_rent_contract_number" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="new_rent_start_date" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="new_rent_end_date" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<label for="new_start" string="Period" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<div name="dates" class="o_row" attrs="{'invisible':[('benefit_type','!=','family')]}">
<field name="new_start" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}"/>
<i class="fa fa-long-arrow-right mx-2 oe_edit_only" aria-label="Arrow icon" title="Arrow" />
<i class="fa fa-long-arrow-right mx-2 oe_read_only" aria-label="Arrow icon" title="Arrow" attrs="{'invisible': [('new_start', '=', False), ('new_end', '=', False)]}" />
<field name="new_end" attrs="{'readonly':[('state','not in',['draft','researcher','send_request'])]}" />
</div>
<field name="new_rent_amount" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="new_rent_amount_payment" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="new_payment_type" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
<field name="new_rent_attachment" widget="many2many_attachment_preview" attrs="{'invisible':[('benefit_type','!=','family')]}"/>
</group>
<group>
</group>
</group>
</sheet>
</form>
</page>

View File

@ -10,15 +10,15 @@
<group>
<field name="service_name"/>
<field name="parent_service" attrs="{'invisible':[('is_main_service','=',True)]}"/>
<field name="is_main_service"/>
<field name="is_service_producer"/>
<field name="service_producer_id" attrs="{'invisible':[('is_service_producer','=',False)]}"/>
<field name="service_type" attrs="{'invisible':[('is_main_service','=',True)]}"/>
<field name="account_id" attrs="{'invisible':[('is_main_service','=',True)]}"/>
<field name="accountant_id" attrs="{'invisible':[('is_main_service','=',True)]}"/>
<field name="service_producer_id" attrs="{'invisible':['|',('is_main_service','=',True),('is_service_producer','=',False)]}"/>
</group>
<group>
<field name="service_type" attrs="{'invisible':[('is_main_service','=',True)]}"/>
<field name="is_this_service_for_student"/>
<field name="account_id"/>
<field name="accountant_id"/>
<field name="is_main_service"/>
<field name="is_service_producer" attrs="{'invisible':[('is_main_service','=',True)]}"/>
<field name="is_this_service_for_student" attrs="{'invisible':[('is_main_service','=',True)]}"/>
</group>
</group>
<notebook>

View File

@ -18,7 +18,7 @@ class ServiceRequestInherit(models.Model):
'name': (_('Home Restoration Service')) +"/"+ rec.family_id.name +"/"+ rec.family_id.code,
'partner_id': rec.service_producer_id.id,
'beneficiary_id': rec.family_id.partner_id.id,
'category_id' : rec.service_cat.category_id,
'category_id' : rec.service_cat.category_id.id,
'requested_service_amount' : rec.requested_service_amount,
'restoration_max_amount' : rec.restoration_max_amount,
'has_money_field_is_appearance': rec.has_money_field_is_appearance,