diff --git a/odex25_realstate/property_management/i18n/ar_001.po b/odex25_realstate/property_management/i18n/ar_001.po index d2ffd0fae..f47ffa71c 100644 --- a/odex25_realstate/property_management/i18n/ar_001.po +++ b/odex25_realstate/property_management/i18n/ar_001.po @@ -633,11 +633,24 @@ msgstr "رقم سند سداد الكهرباء" msgid "Electric Read" msgstr "قراءة العداد" +#. module: property_management +#: code:addons/property_management/models/rent_payment.py:0 +#: model:ir.model.fields,field_description:property_management.field_rent_payment__electricity_cost +#: model_terms:ir.ui.view,arch_db:property_management.rental_contract_form_view +#, python-format +msgid "Electricity Cost" +msgstr "قيمة خدمة الكهرباء" + #. module: property_management #: model:ir.model.fields,field_description:property_management.field_rental_contract__electricity_meter_no msgid "Electricity Meter No." msgstr "رقم عداد الكهرباء" +#. module: property_management +#: model:ir.model.fields,field_description:property_management.field_rental_contract__electricity_cost +msgid "Electricity cost" +msgstr "قيمة خدمة الكهرباء" + #. module: property_management #: model:ir.model.fields,field_description:property_management.field_end_rent_line__end_rent_id msgid "End Contract" @@ -1893,6 +1906,15 @@ msgstr "مراجعة" msgid "SMS Delivery error" msgstr "خطأ في تسليم الرسائل القصيرة" +#. module: property_management +#: code:addons/property_management/models/rent_payment.py:0 +#: model:ir.model.fields,field_description:property_management.field_rent_payment__sanitation_cost +#: model:ir.model.fields,field_description:property_management.field_rental_contract__sanitation_cost +#: model_terms:ir.ui.view,arch_db:property_management.rental_contract_form_view +#, python-format +msgid "Sanitation Cost" +msgstr "قيمة خدمة الصرف الصحي" + #. module: property_management #: model_terms:ir.ui.view,arch_db:property_management.property_maintenance_filter_view #: model_terms:ir.ui.view,arch_db:property_management.rent_end__filter_view @@ -1917,7 +1939,7 @@ msgstr "متسلسل" #. module: property_management #: model:ir.model.fields,field_description:property_management.field_rental_contract__service msgid "Service" -msgstr "خدمة" +msgstr "خدمات أخرى" #. module: property_management #: model:ir.model.fields,field_description:property_management.field_end_of_rent__service_amount @@ -1930,11 +1952,21 @@ msgstr "قيمة الخدمات" msgid "Service Cost" msgstr "قيمة الخدمات" +#. module: property_management +#: model:ir.model.fields,field_description:property_management.field_rent_payment__service_note +msgid "Service Note" +msgstr "وصف الخدمة" + #. module: property_management #: model:ir.model.fields,field_description:property_management.field_rental_contract__is_services msgid "Services Exist?" msgstr "توجد خدمات؟" +#. module: property_management +#: model:ir.model.fields,field_description:property_management.field_rental_contract__service_note +msgid "Services Notes" +msgstr "وصف الخدمة" + #. module: property_management #: code:addons/property_management/models/rent_payment.py:0 #, python-format diff --git a/odex25_realstate/property_management/models/rent_payment.py b/odex25_realstate/property_management/models/rent_payment.py index eb429a032..cfbcd583f 100644 --- a/odex25_realstate/property_management/models/rent_payment.py +++ b/odex25_realstate/property_management/models/rent_payment.py @@ -12,6 +12,7 @@ from odoo.addons.property_management.models import amount_to_text_ar from odoo.exceptions import UserError from datetime import datetime, timedelta + class RentPayment(models.Model): _name = "rent.payment" _description = "Rental Contract Payment" @@ -20,11 +21,11 @@ class RentPayment(models.Model): code = fields.Char(string="Sequence") collected_from_company = fields.Boolean(string="Is Payment Collected from Company") - commission_amount = fields.Float(string="Commission Amount",store=True,compute='_compute_commission_amount') + commission_amount = fields.Float(string="Commission Amount", store=True, compute='_compute_commission_amount') name = fields.Char(string="Description") contract_id = fields.Many2one('rental.contract', string="Rental Contract") - renter_id = fields.Many2one('res.partner',string="Renter",related='contract_id.partner_id',readonly=1) - + renter_id = fields.Many2one('res.partner', string="Renter", related='contract_id.partner_id', readonly=1) + investor_id = fields.Many2one('res.partner', string="Investor", related="contract_id.property_id.owner_id", store=True) partner_id = fields.Many2one('res.partner', string="Customer", related="contract_id.partner_id", store=True) @@ -33,13 +34,17 @@ class RentPayment(models.Model): user_id = fields.Many2one('res.users', string="Responsible") company_id = fields.Many2one('res.company', string="Company") due_date = fields.Date(string="Due Date") - paid_date = fields.Date(string="Paid Date",) + paid_date = fields.Date(string="Paid Date", ) payment_method = fields.Selection([('check', 'Bank Check'), ('cash', 'Cash'), ('transfer', 'Transfer')], string="Payment Method", default='transfer') amount = fields.Float(string="Amount") water_cost = fields.Float(string="Water Cost") service_cost = fields.Float(string="Service Cost") + service_note = fields.Char(string="Service Note", related='contract_id.service_note') + electricity_cost = fields.Float(string="Electricity Cost", related='contract_id.electricity_cost') + sanitation_cost = fields.Float('Sanitation Cost', related='contract_id.sanitation_cost') + profit = fields.Float(string="Profit") tax_id = fields.Many2one('account.tax', string="Tax") untaxed_amount = fields.Float(string="Untaxed Amount", compute="get_untaxed_amount", store=True) @@ -53,101 +58,131 @@ class RentPayment(models.Model): ('invoice', 'Invoice'), ('paid', 'Paid'), ('cancel', 'Canceled')], string="Status", default='draft') - invoice_id = fields.Many2one('account.move', string="Invoice",readonly=1) - invoice_commission_id = fields.Many2one('account.move', string="Invoice Commission",readonly=1) + invoice_id = fields.Many2one('account.move', string="Invoice", readonly=1) + invoice_commission_id = fields.Many2one('account.move', string="Invoice Commission", readonly=1) note = fields.Text(string="Note") - + @api.depends('total_amount') def _compute_commission_amount(self): for record in self: - commission_percentage = self.env['ir.config_parameter'].sudo().get_param('property_management.commission_percentage') - record.commission_amount = record.total_amount * (commission_percentage / 100) if commission_percentage else 0 + commission_percentage = self.env['ir.config_parameter'].sudo().get_param( + 'property_management.commission_percentage') + record.commission_amount = record.total_amount * ( + commission_percentage / 100) if commission_percentage else 0 @api.depends('contract_id') def _compute_renter(self): - for rec in self: - if rec.contract_id: - rec.renter_id = rec.contract_id.partner_id.id - if rec.invoice_id and rec.invoice_id.payment_state in ['paid', 'in_payment']: - rec.write({'state': 'paid','paid_date':rec.invoice_id.payment_id.date}) - payment_obj = self.env['account.payment'].search([('ref','=',rec.invoice_id.name)],limit=1) - rec.paid_date=payment_obj.date + for rec in self: + if rec.contract_id: + rec.renter_id = rec.contract_id.partner_id.id + if rec.invoice_id and rec.invoice_id.payment_state in ['paid', 'in_payment']: + rec.write({'state': 'paid', 'paid_date': rec.invoice_id.payment_id.date}) + payment_obj = self.env['account.payment'].search([('ref', '=', rec.invoice_id.name)], limit=1) + rec.paid_date = payment_obj.date @api.depends('invoice_id') def _compute_payment(self): - for rec in self: - if rec.invoice_id and rec.invoice_id.payment_state in ['paid', 'in_payment']: - rec.write({'state': 'paid','paid_date':rec.invoice_id.payment_id.date}) - payment_obj = self.env['account.payment'].search([('ref','=',rec.invoice_id.name)],limit=1) - rec.paid_date=payment_obj.date + for rec in self: + if rec.invoice_id and rec.invoice_id.payment_state in ['paid', 'in_payment']: + rec.write({'state': 'paid', 'paid_date': rec.invoice_id.payment_id.date}) + payment_obj = self.env['account.payment'].search([('ref', '=', rec.invoice_id.name)], limit=1) + rec.paid_date = payment_obj.date def read(self, records): res = super(RentPayment, self).read(records) for rec in self: if rec.invoice_id.payment_state in ['paid', 'in_payment']: rec.write({'state': 'paid'}) - payment_obj = self.env['account.payment'].search([('ref','=',rec.invoice_id.name)],limit=1) - rec.paid_date=payment_obj.date + payment_obj = self.env['account.payment'].search([('ref', '=', rec.invoice_id.name)], limit=1) + rec.paid_date = payment_obj.date return res - - @api.depends('invoice_id', 'invoice_id.state','invoice_id.payment_state', 'invoice_id.amount_residual') + @api.depends('invoice_id', 'invoice_id.state', 'invoice_id.payment_state', 'invoice_id.amount_residual') def get_invoice_state(self): self.paid = False for rec in self: if rec.invoice_id: if rec.invoice_id.amount_residual == 0.0: rec.paid = True - if rec.invoice_id.payment_state in ['paid','in_payment']: + if rec.invoice_id.payment_state in ['paid', 'in_payment']: rec.write({'state': 'paid'}) - payment_obj = self.env['account.payment'].search([('ref','=',rec.invoice_id.name)],limit=1) - rec.paid_date=payment_obj.date - + payment_obj = self.env['account.payment'].search([('ref', '=', rec.invoice_id.name)], limit=1) + rec.paid_date = payment_obj.date def _prepare_invoice_values(self, payment, amount): - + self.renter_id.property_account_receivable_id = payment.contract_id.debit_account_id.id unit_name = self.unit_ids[0].name if self.unit_ids else '' # Check if unit_ids is not empty - line_invoice=[] + line_invoice = [] line_journal = [] - - if payment.amount>0.00: + + if payment.amount > 0.00: line_invoice.append((0, 0, { - 'name':_('Reant Amount ') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str(self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str(payment.code or '') + ' - ' + str(payment.due_date or ''), + 'name': _('Reant Amount ') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str( + self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str( + payment.code or '') + ' - ' + str(payment.due_date or ''), 'quantity': 1.0, 'price_unit': self.amount, 'account_id': payment.contract_id.revenue_account_id.id, 'analytic_account_id': payment.property_id.account_analy_id.id if payment.property_id.account_analy_id else False, 'tax_ids': [(6, 0, [payment.tax_id.id])] if payment.tax_id else False, # Assigning tax_id to tax_ids })) - if payment.water_cost>0.00: + if payment.water_cost > 0.00: line_invoice.append((0, 0, { - 'name': _('Water Cost ')+ ' - ' + str(payment.contract_id.name or '') + ' - ' + str(self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str(payment.code or '') + ' - ' + str(payment.due_date or ''), - 'price_unit':self.water_cost, + 'name': _('Water Cost ') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str( + self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str( + payment.code or '') + ' - ' + str(payment.due_date or ''), + 'price_unit': self.water_cost, 'quantity': 1.0, 'account_id': payment.contract_id.revenue_account_id.id, 'analytic_account_id': payment.property_id.account_analy_id.id if payment.property_id.account_analy_id else False, 'tax_ids': [(6, 0, [payment.tax_id.id])] if payment.tax_id else False, # Assigning tax_id to tax_ids - }),) - if payment.service_cost>0.00: + }), ) + if payment.service_cost > 0.00: line_invoice.append((0, 0, { - 'name': _('Serviecs Cost') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str(self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str(payment.code or '') + ' - ' + str(payment.due_date or ''), + 'name': _('Serviecs Cost') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str( + self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str( + payment.code or '') + ' - ' + str(payment.due_date or ''), 'price_unit': self.service_cost, 'quantity': 1.0, 'analytic_account_id': payment.property_id.account_analy_id.id if payment.property_id.account_analy_id else False, 'account_id': payment.contract_id.revenue_account_id.id, 'tax_ids': [(6, 0, [payment.tax_id.id])] if payment.tax_id else False, # Assigning tax_id to tax_ids })) - if payment.amount==0.00 and payment.service_cost==0.00 and payment.water_cost==0.00: + if payment.electricity_cost > 0.00: + line_invoice.append((0, 0, { + 'name': _('Electricity Cost') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str( + self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str( + payment.code or '') + ' - ' + str(payment.due_date or ''), + 'price_unit': self.electricity_cost, + 'quantity': 1.0, + 'analytic_account_id': payment.property_id.account_analy_id.id if payment.property_id.account_analy_id else False, + 'account_id': payment.contract_id.revenue_account_id.id, + 'tax_ids': [(6, 0, [payment.tax_id.id])] if payment.tax_id else False, # Assigning tax_id to tax_ids + })) + if payment.sanitation_cost > 0.00: + line_invoice.append((0, 0, { + 'name': _('Sanitation Cost') + ' - ' + str(payment.contract_id.name or '') + ' - ' + str( + self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str( + payment.code or '') + ' - ' + str(payment.due_date or ''), + 'price_unit': self.sanitation_cost, + 'quantity': 1.0, + 'analytic_account_id': payment.property_id.account_analy_id.id if payment.property_id.account_analy_id else False, + 'account_id': payment.contract_id.revenue_account_id.id, + 'tax_ids': [(6, 0, [payment.tax_id.id])] if payment.tax_id else False, # Assigning tax_id to tax_ids + })) + if payment.amount == 0.00 and payment.service_cost == 0.00 and payment.water_cost == 0.00: line_invoice.append((0, 0, { - 'name': self.name + ' - ' + str(payment.contract_id.name or '') + ' - ' + str(self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str(payment.code or '') + ' - ' + str(payment.due_date or ''), - 'price_unit':self.total_amount, + 'name': self.name + ' - ' + str(payment.contract_id.name or '') + ' - ' + str( + self.property_id.name or '') + ' - ' + unit_name + ' - ' + str(self.name or '') + ' - ' + str( + payment.code or '') + ' - ' + str(payment.due_date or ''), + 'price_unit': self.total_amount, 'quantity': 1.0, 'analytic_account_id': payment.property_id.account_analy_id.id if payment.property_id.account_analy_id else False, 'account_id': payment.contract_id.revenue_account_id.id, 'tax_ids': [(6, 0, [payment.tax_id.id])] if payment.tax_id else False, # Assigning tax_id to tax_ids })) - + # line_journal.append((0, 0, { # 'account_id': payment.contract_id.revenue_account_id.id, # 'debit': 0.0, @@ -161,7 +196,7 @@ class RentPayment(models.Model): # 'credit': 0.0, # 'quantity': 1 # })) - + invoice_vals = { 'ref': payment.name, 'move_type': 'out_invoice', @@ -170,22 +205,21 @@ class RentPayment(models.Model): 'narration': payment.note, 'partner_id': payment.contract_id.partner_id.id, 'invoice_line_ids': line_invoice, - - + # 'tax_ids': [(6, 0, [payment.tax_id.id])], } return invoice_vals - def action_invoice(self): if not self.contract_id.accrued_account_id: - raise exceptions.ValidationError(_("Kindly, Contact Your Account Manager to set Income Account in contract account page")) + raise exceptions.ValidationError( + _("Kindly, Contact Your Account Manager to set Income Account in contract account page")) invoice_vals = self._prepare_invoice_values(self, self.total_amount) invoice = self.env['account.move'].sudo().create(invoice_vals).with_user(self.env.uid) # Get the ID of the second line # line_id = invoice.invoice_line_ids[1].id - # commands = [(2, line_id, 0)] - # invoice.write({'invoice_line_ids': commands}) + # commands = [(2, line_id, 0)] + # invoice.write({'invoice_line_ids': commands}) self.invoice_id = invoice.id self.write({'state': 'invoice'}) @@ -200,12 +234,12 @@ class RentPayment(models.Model): self.write(({'state': 'cancel'})) elif self.state == 'due': raise exceptions.ValidationError(_('Cannot Cancel This Payment Because it Due')) - + def create_vendor_bill_for_payments(self): active_ids = self._context.get('active_ids', []) # action = self.env['rent.payment'].browse(context.get('active_ids', [])) payments_to_invoice = self.env['rent.payment'].sudo().browse(active_ids).filtered( - lambda p: p.state == 'paid' and p.collected_from_company and not p.invoice_commission_id) + lambda p: p.state == 'paid' and p.collected_from_company and not p.invoice_commission_id) vendor_id = int(self.env['ir.config_parameter'].sudo().get_param('property_management.collecting_company_id')) account_id = int(self.env['ir.config_parameter'].sudo().get_param('property_management.commission_account_id')) total_commission_amount = sum(payments_to_invoice.mapped('commission_amount')) @@ -216,13 +250,13 @@ class RentPayment(models.Model): if not vendor_id or not account_id: raise UserError(_("Vendor or Account not configured properly in settings.")) - if payments_to_invoice: + if payments_to_invoice: vendor_bill = self.env['account.move'].sudo().create({ 'move_type': 'in_invoice', 'invoice_date': today_date, # Set the invoice date, 'partner_id': vendor_id, 'invoice_line_ids': [(0, 0, { - 'name': name+' - '+str(today_date), + 'name': name + ' - ' + str(today_date), 'quantity': 1, 'price_unit': total_commission_amount, 'account_id': account_id @@ -230,7 +264,7 @@ class RentPayment(models.Model): }) for payment in payments_to_invoice: payment.invoice_commission_id = vendor_bill.id - + def action_validate2(self): for record in self: if record.contract_id.state == 'confirm': @@ -248,18 +282,20 @@ class RentPayment(models.Model): record.write({"state": 'due'}) else: raise exceptions.ValidationError(_("You Must Confirm Contract First")) + def _check_due_payments(self): payments = self.search([('state', '=', 'draft'), ('due_date', '<=', fields.Date.today())]) for payment in payments: if payment.contract_id.state == 'confirm': payment.write({'state': 'due'}) if payment.code == '/' or not payment.code: - code = self.env['ir.sequence'].next_by_code('rent.payment') or '/' - payment.write({'code': code}) + code = self.env['ir.sequence'].next_by_code('rent.payment') or '/' + payment.write({'code': code}) + def _send_payment_notifications(self): today = fields.Date.today() next_week = today + timedelta(days=7) - + payments_today = self.search([('due_date', '=', today), ('state', '=', 'draft')]) payments_next_week = self.search([('due_date', '=', next_week), ('state', '=', 'draft')]) @@ -270,11 +306,12 @@ class RentPayment(models.Model): summary = _("Due Date Rent") for payment in payments_today: - email_list = [payment.renter_id.email,payment.user_id.email] + email_list = [payment.renter_id.email, payment.user_id.email] email_to = ','.join(email_list) payment.message_post_with_template(template_today.id) if template_today: - template_today.send_mail(payment.id, force_send=True,raise_exception=True,email_values={'email_to': email_to}) + template_today.send_mail(payment.id, force_send=True, raise_exception=True, + email_values={'email_to': email_to}) payment.sudo().activity_schedule( 'mail.mail_activity_data_todo', date_deadline, note=note, @@ -293,11 +330,12 @@ class RentPayment(models.Model): # يمكنك استخدام notification module للإشعارات أو mail.activity for payment in payments_next_week: - email_list = [payment.renter_id.email,payment.user_id.email] + email_list = [payment.renter_id.email, payment.user_id.email] email_to = ','.join(email_list) payment.message_post_with_template(template_next_week.id) if template_next_week: - template_next_week.send_mail(payment.id, force_send=True,raise_exception=True,email_values={'email_to':email_to}) + template_next_week.send_mail(payment.id, force_send=True, raise_exception=True, + email_values={'email_to': email_to}) payment.sudo().activity_schedule( 'mail.mail_activity_data_todo', date_deadline, note=note, @@ -314,7 +352,6 @@ class RentPayment(models.Model): ) return True - def action_validate(self): for record in self: if record.contract_id.state == 'confirm': @@ -334,21 +371,23 @@ class RentPayment(models.Model): else: raise exceptions.ValidationError(_("You Must Confirm Contract First")) - # @api.depends('untaxed_amount', 'tax_id', 'tax_id.amount') # def get_tax_amount(self): # for rec in self: # tax_value = rec.tax_id.amount / 100 # rec.tax_amount = rec.untaxed_amount * tax_value - @api.depends('amount', 'water_cost', 'service_cost','tax_id') + @api.depends('amount', 'water_cost', 'service_cost', 'tax_id') def get_untaxed_amount(self): for rec in self: - rec.untaxed_amount = round(rec.amount + rec.water_cost + rec.service_cost,2) - rec.tax_amount = round(rec.tax_id.amount/100*rec.amount,2) - @api.depends('amount', 'water_cost', 'service_cost','tax_id') + rec.untaxed_amount = round( + rec.amount + rec.water_cost + rec.service_cost + rec.electricity_cost + rec.sanitation_cost, 2) + rec.tax_amount = round(rec.tax_id.amount / 100 * rec.amount, 2) + + @api.depends('amount', 'water_cost', 'service_cost', 'tax_id') def get_total_amount(self): for rec in self: - rec.total_amount = round(rec.untaxed_amount + rec.tax_amount,2) - commission_percentage = float(self.env['ir.config_parameter'].sudo().get_param('property_management.commission_percentage')) + rec.total_amount = round(rec.untaxed_amount + rec.tax_amount, 2) + commission_percentage = float( + self.env['ir.config_parameter'].sudo().get_param('property_management.commission_percentage')) rec.commission_amount = rec.total_amount * (commission_percentage) if commission_percentage else 0 diff --git a/odex25_realstate/property_management/models/rental_contract.py b/odex25_realstate/property_management/models/rental_contract.py index 025b0cb5d..c9cbc78c8 100644 --- a/odex25_realstate/property_management/models/rental_contract.py +++ b/odex25_realstate/property_management/models/rental_contract.py @@ -149,8 +149,11 @@ class RentalContract(models.Model): rent_type = fields.Many2one('rent.type', string="Rent Type") space = fields.Float(string="Space", compute="get_property_unit_space", store=True) service = fields.Selection([('fixed', 'Fixed'), ('percentage', 'Percentage')], string="Service") + service_note = fields.Char('Services Notes') service_cost = fields.Float(string="service cost") service_amount = fields.Float(string="service amount", compute="compute_service_amount", store=True) + electricity_cost = fields.Float('Electricity cost') + sanitation_cost = fields.Float('Sanitation Cost') management_type = fields.Selection(related="property_id.management_type", string="Management Type") property_state_id = fields.Many2one('re.property.state', related="property_id.property_state_id") property_type_id = fields.Many2one('internal.property.type', related="property_id.property_type_id", string="Type") diff --git a/odex25_realstate/property_management/views/rent_payment_view.xml b/odex25_realstate/property_management/views/rent_payment_view.xml index 4f3ab16ba..fad866427 100644 --- a/odex25_realstate/property_management/views/rent_payment_view.xml +++ b/odex25_realstate/property_management/views/rent_payment_view.xml @@ -37,6 +37,9 @@ + + + @@ -84,6 +87,7 @@ + diff --git a/odex25_realstate/property_management/views/rental_contract_views.xml b/odex25_realstate/property_management/views/rental_contract_views.xml index 37740ce26..513db40c7 100644 --- a/odex25_realstate/property_management/views/rental_contract_views.xml +++ b/odex25_realstate/property_management/views/rental_contract_views.xml @@ -124,15 +124,15 @@