odex25_standard/odex25_realstate/real_estate/models/re_unit.py

278 lines
13 KiB
Python

# -*- coding: utf-8 -*-
##############################################################################
#
# Expert (LCT, Life Connection Technology)
# Copyright (C) 2021-2022 LCT
#
##############################################################################
import base64
import re
from odoo import models, fields, api, exceptions, _
class PropertyRole(models.Model):
_name = 'property.role'
_description = 'Property Role'
name = fields.Char('Name')
class Unit(models.Model):
_name = 're.unit'
_description = 'Property Unit'
_inherit = ['mail.thread', 'mail.activity.mixin']
_order = "id desc"
unit_category = fields.Selection([
('residential', 'Residential'),
('commercial', 'Commercial'),
('lands', 'Lands')], string="Unit Category")
attach_nbr = fields.Integer(compute='get_attachments')
content_ids = fields.One2many(comodel_name='property.content.details', inverse_name='unit_id', string='')
active = fields.Boolean(default=True)
role_id = fields.Many2one('property.role', string='Role')
unlock = fields.Boolean(default=True, string="Unlock")
name = fields.Char(string="Unit Name")
color = fields.Integer(string='Color Index', compute="set_color")
property_id = fields.Many2one('internal.property', string="Property")
seq = fields.Char(string="Unit Code", index=True)
state = fields.Selection([('draft', 'Draft'),
('available', 'Available'),
('reserved', 'Reserved'),
('rented', 'Rented'),
('sold', 'Sold')], string="Status", default='draft')
journal_id = fields.Many2one('account.journal', string='Journal')
accrued_account_id = fields.Many2one('account.account', string='Accrued Account')
debit_account_id = fields.Many2one('account.account', string='Debit Account')
revenue_account_id = fields.Many2one('account.account', string='Revenue Account')
unit_type_id = fields.Many2one('unit.type', string="Unit Type")
management_type = fields.Selection(related='property_id.management_type', string="Management Type", store=True)
market_type = fields.Selection(related="property_id.market_type", string="Market Type", store=True)
unit_market_type = fields.Selection(related="property_id.market_type", string="Unit Market Type", store=True)
other_type = fields.Char(related="property_id.other_type", string="Other Type")
action_type = fields.Selection([('sale', 'Sale')], string="Action Type", default="sale")
city_id = fields.Many2one('re.city', related="property_id.city_id", string="City", store=True)
district_id = fields.Many2one('district', related="property_id.district_id", string="District", store=True)
# length = fields.Float(string="Length")
width = fields.Float(string="Width")
space = fields.Float(string="Unit Space")
external_space = fields.Float(string="External Space", tracking=True)
external_price = fields.Float(string="External Meter Price", tracking=True)
mezzanine = fields.Boolean(string="Mezzanine")
mezzan_length = fields.Float(string="Mezzan Length")
mezzan_width = fields.Float(string="Mezzan Width")
meter_price = fields.Float(string="Meter Price", compute="get_rent_price", store=True, digits=(16, 2))
rent_price = fields.Float(string="Total Price")
limit_meter_price = fields.Float(string="Limit Meter Price", compute="get_limit_rent_price", store=True)
limit_rent = fields.Float(string="Limit Rent", store=True)
electric_meter = fields.Boolean(string="Electric Meter")
electric_serial = fields.Char(string="Electric Serial")
electric_subscription = fields.Char(string="Electric Subscription")
electric_account = fields.Char(string="Electric Account")
company_id = fields.Many2one('res.company', string='Company', required=True,
default=lambda self: self.env.user.company_id)
user_id = fields.Many2one('res.users', string="Marketer", default=lambda self: self.env.user)
room_no = fields.Integer(string="Room Count")
bathroom_no = fields.Integer(string="Bathroom Count")
hall_no = fields.Integer(string="Hall Count")
kitchen_no = fields.Integer(string="kitchen Count")
stamping_count = fields.Selection(string="Stamping Count", related='property_id.stamping_count')
stamping = fields.Char(string="Stamping Number", related='property_id.stamping')
stamping_date = fields.Date(string="Stamping Date", related='property_id.stamping_date')
stamping_state = fields.Selection(related='property_id.stamping_state')
stamping_attach = fields.Binary("Stamping Attach", attachment=True, related='property_id.stamping_attach')
stamping_2 = fields.Char(string="Stamping Number", related='property_id.stamping_2')
stamping_date_2 = fields.Date(string="Stamping Date", related='property_id.stamping_date_2')
stamping_attach_2 = fields.Binary("Stamping Attach", attachment=True,store=True, related='property_id.stamping_attach_2')
stamping_state_2 = fields.Selection([('updated', 'Updated'), ('not_updated', 'Not Updated')],
related='property_id.stamping_state_2')
stamping_3 = fields.Char(string="Stamping Number", related='property_id.stamping_3')
stamping_date_3 = fields.Date(string="Stamping Date", related='property_id.stamping_date_3')
stamping_attach_3 = fields.Binary("Stamping Attach", attachment=True,store=True, related='property_id.stamping_attach_3')
stamping_state_3 = fields.Selection([('updated', 'Updated'), ('not_updated', 'Not Updated')],
related='property_id.stamping_state_3')
stamping_new = fields.Char(string="Stamping Number New")
stamping_date_new = fields.Date(string="Stamping Date New")
stamping_attach_new = fields.Binary("Stamping Attach New", attachment=True)
_sql_constraints = [
('name', 'unique(name)', _('Name must be unique.')),
]
# Smart button to count related maintenance records
maintenance_count = fields.Integer(string="Maintenance Count", compute='_compute_maintenance_count')
def get_attachments(self):
action = self.env['ir.actions.act_window']._for_xml_id('base.action_attachment')
action['domain'] = str([('res_model', '=', 're.unit'), ('res_id', 'in', self.ids)])
action['context'] = "{'default_res_model': '%s','default_res_id': %d}" % (self._name, self.id)
domain = [('res_model', '=', 're.unit'), ('res_id', '=', self.id)]
self.attach_nbr = self.env['ir.attachment'].search_count(domain)
return action
def _compute_maintenance_count(self):
for record in self:
record.maintenance_count = self.env['property.management.maintenance'].search_count([
('unit_ids', 'in', record.id)
])
def action_view_maintenance(self):
return {
'type': 'ir.actions.act_window',
'name': 'Maintenance',
'view_mode': 'tree,form',
'res_model': 'property.management.maintenance',
'domain': [('unit_ids', 'in', self.id)],
'context': dict(self.env.context),
}
@api.depends('state')
def set_color(self):
for record in self:
color = 0
if record.state == 'draft':
color = 1
record.color = color
if record.state == 'reserved':
color = 2
record.color = color
if record.state == 'rented':
color = 3
record.color = color
@api.depends('limit_rent', 'space')
def get_limit_rent_price(self):
for rec in self:
if rec.limit_rent != 0.0 and rec.space != 0.0:
rec.limit_meter_price = rec.limit_rent / rec.space
else:
rec.limit_rent = 0.0
def action_available(self):
"""
after checking meter price and limit price meter
Write the state of unit and make it available for rent or reserved
:return:
"""
if self.limit_meter_price > self.meter_price or self.limit_rent > self.rent_price:
raise exceptions.ValidationError(_('Limit must be less than price per meter'))
if self.property_id.state == 'rent':
self.property_id.write({'state': 'approve'})
self.write({'state': 'available'})
def action_draft(self):
"""
set unit to draft if it available only
:return:
"""
state = dict(self.fields_get(allfields=['state'])['state']['selection'])[self.state]
if self.state == 'available':
self.write({'state': 'draft'})
else:
raise exceptions.ValidationError(_("Unit cannot be draft because it in state %s") % state)
# def name_get(self):
# result = []
# for rec in self:
# name = "%s,%s" % (rec.name, rec.seq)
# result.append((rec.id, name))
# return result
@api.constrains('electric_serial', 'electric_subscription', 'electric_account')
def fields_check(self):
"""
Check if name field contain an invalid value
:raise exception
"""
num_pattern = re.compile(r'\d', re.I | re.M)
white_space = re.compile(r'^\s')
if self.electric_meter:
if not num_pattern.search(self.electric_subscription):
raise exceptions.ValidationError(
_("Electric subscription field accept numbers or special character only"))
if not num_pattern.search(self.electric_account):
raise exceptions.ValidationError(_("Electric account field accept numbers or special character only"))
if not num_pattern.search(self.electric_serial):
raise exceptions.ValidationError(_("Electric serial field accept numbers or special character only"))
if white_space.search(self.electric_serial):
raise exceptions.ValidationError(_("Electric serial (cannot accept white space)"))
if white_space.search(self.electric_subscription):
raise exceptions.ValidationError(_("Electric subscription (cannot accept white space)"))
if white_space.search(self.electric_account):
raise exceptions.ValidationError(_("Electric account (cannot accept white space)"))
@api.constrains('limit_meter_price', 'space', 'meter_price', 'mezzan_width', 'mezzan_length')
def check_number(self):
"""
If the number less than zero then raise error
:return:
"""
for record in self:
if record.limit_meter_price < 0.0:
raise exceptions.ValidationError(_("Limit Meter space cannot be less than zero"))
if record.space < 0.0:
raise exceptions.ValidationError(_("Space cannot be less than zero"))
if record.meter_price < 0.0:
raise exceptions.ValidationError(_("Meter price cannot be less than zero"))
@api.depends('rent_price', 'space')
def get_rent_price(self):
"""
Get rent Price Per Meter
:return: total rent price
"""
for record in self:
if record.space != 0.0:
record.meter_price = record.rent_price / record.space
def action_toggle_is_locked(self):
self.ensure_one()
if self.unlock:
self.write({'unlock': False})
else:
self.write({'unlock': True})
@api.model
def create_duplicate_server_action(self):
# Create the server action to duplicate records
action = self.env['ir.actions.server'].create({
'name': 'Duplicate Selected Records',
'model_id': self.env['ir.model'].search([('model', '=', 're.unit')], limit=1).id,
'state': 'code',
'code': """
for record in records:
record.copy()
""",
})
# Create the action in the contextual action dropdown menu
self.env['ir.actions.actions'].create({
'name': 'Duplicate Selected Records',
'binding_model_id': self.env['ir.model'].search([('model', '=', 're.unit')], limit=1).id,
'type': 'ir.actions.server',
'binding_type': 'action',
'binding_view_types': 'list',
'server_action_ids': [(4, action.id)],
})
class PropertyContentDetails(models.Model):
_name = 'property.content.details'
_description = 'Property Unit Details'
unit_id = fields.Many2one('re.unit', string='Property', required=True, ondelete='cascade')
content_id = fields.Many2one('property.contents', 'Property Content')
qty = fields.Integer('QTY')
desc = fields.Char('Description')
attachment = fields.Binary(string="Property Docs")