# -*- coding: utf-8 -*- ############################################################################# # # Cybrosys Technologies Pvt. Ltd. # # Copyright (C) 2024-TODAY Cybrosys Technologies(). # Author: Gayathri V (odoo@cybrosys.com) # # You can modify it under the terms of the GNU AFFERO # GENERAL PUBLIC LICENSE (AGPL v3), Version 3. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. # # You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE # (AGPL v3) along with this program. # If not, see . # ############################################################################# from datetime import date from odoo import api, fields, models, _ from odoo.exceptions import ValidationError class CleaningBooking(models.Model): """Create a new model for booking purposes. The system will incorporate three buttons to indicate the booking and cleaning status: "Confirm", "Clean" and "Cancel".""" _name = "cleaning.booking" _description = "Cleaning Booking" _inherit = ['mail.thread', 'mail.activity.mixin'] _rec_name = 'customer_name_id' def _default_cleaning_team_ids(self): """Returns default values for cleaning_team_ids records""" return self.env['cleaning.team'].search([]).ids customer_name_id = fields.Many2one('res.partner', string='Name of Customer', required=True, help="Choose customer name") address = fields.Char(string='Address', required=True, help="Enter address of customer") building_type_id = fields.Many2one('building.type', string='Building Type', required=True, help="Choose building type") booking_date = fields.Date(default=fields.date.today(), help="Choose the booking date", string='Booking Date') cleaning_team_ids = fields.Many2many('cleaning.team', string='Cleaning Team', help="Store cleaning team based on " "cleaning_time", default=_default_cleaning_team_ids) cleaning_team_id = fields.Many2one('cleaning.team', string='Cleaning Team', help="Choose cleaning team", required=True, domain="[('id', 'in', " "cleaning_team_ids)]") cleaning_inspection_id = fields.Many2one('cleaning.inspection', string="Cleaning Inspection", help="Choose Cleaning Inspection") cleaning_team_duty_id = fields.Many2one('cleaning.team.duty', string="Cleaning Team Duty", help="Choose Cleaning Team Duty") cleaning_date = fields.Date(string='Cleaning Date', required=True, help="Choose Date for cleaning") cleaning_time = fields.Selection([('morning', 'Morning'), ('evening', 'Evening'), ('night', 'Night')], string='Cleaning Time', help="Choose Time for cleaning", required=True) description = fields.Char(string='Description', help="Enter Description For Booking") duration = fields.Selection([('forever', 'Forever'), ('fixed', 'Fixed')], default='forever', string='Duration', help="Choose Duration For Cleaning") end_after = fields.Integer(string='End After', help="Choose End of cleaning management") end_duration = fields.Selection([('months', 'Months'), ('years', 'Years')], string="End Duration", help="Choose End duration of booking") cleaning_shift_id = fields.Many2one("cleaning.shift", help="Cleaning Shift", string="Choose Cleaning Shift") self_closable = fields.Boolean(string='Is Self Closable', help="When checked reservations will" "be automatically closed.") automatic_closing = fields.Integer(string='Automatic Closing', help="Automatic Closing Chooser") location_state_id = fields.Many2one('res.country.state', string="State", required=True, help="Choose State For Cleaning") place = fields.Char(string="Place", help="Enter Place of Customer") state = fields.Selection([('draft', 'Draft'), ('booked', 'Booked'), ('cleaned', 'Cleaned'), ('cancelled', 'Cancelled')], default='draft', string='Status', help="Stages For Cleaning Processes", tracking=True) confirm_stage = fields.Boolean(string="Is Confirm", default=True, help="When checked,the status" "" "will be 'Confirm'.") clean_stage = fields.Boolean(string="Clean", default=True, help="When checked,the status will be 'Clean'") cancel_stage = fields.Boolean(string="Cancel", default=True, help="When checked,the status" "will be 'Cancel'.") unit_price = fields.Float(string="Unit Price", default=0.0, required=True, help="Uit Price for an hour") total_hour_of_working = fields.Char(string="Total working hours", help="Total working hours done by Team") invoice_count = fields.Integer(compute="_compute_invoice_count", string='Invoice Count') @api.onchange('cleaning_time') def _onchange_cleaning_time(self): """The team leader will appear at the scheduled cleaning time.""" domain = [] if self.cleaning_time: res = self.env['cleaning.team.duty'].search( [('cleaning_date', '=', self.cleaning_date), ('cleaning_time', '=', self.cleaning_time), ('state', 'not in', ['cancelled', 'cleaned'])]) if res: domain = [('duty_type', '=', self.cleaning_time), ('id', 'not in', [duty.team_id.id for duty in res])] else: domain.append(('duty_type', '=', self.cleaning_time)) self.write({'cleaning_team_ids': [(6, 0, self.env ['cleaning.team'].search(domain).ids)]}) @api.onchange('cleaning_team_id') def _onchange_cleaning_team_id(self): """The team leader's time will appear when changing the leader.""" self.cleaning_time = self.cleaning_team_id.duty_type def action_booking(self): """The button action for "Confirm" typically involves finalizing and saving the booking details entered by the user.""" duty_ids_to_add = [] for rec in self: cleaning_team_duty = rec.cleaning_team_duty_id.create({ "team_id": rec.cleaning_team_id.id, "team_leader_id": rec.cleaning_team_id.team_leader_id.employee_name_id.id, "members_ids": rec.cleaning_team_id.members_ids.ids, "location_state_id": rec.location_state_id.id, "place": rec.place, "customer_id": rec.customer_name_id.id, "cleaning_date": rec.cleaning_date, "cleaning_time": rec.cleaning_time, "cleaning_id": rec.id }) rec.write( {'state': 'booked', 'confirm_stage': False, 'clean_stage': False, 'cancel_stage': False, 'cleaning_team_duty_id': cleaning_team_duty.id}) duty_ids_to_add.append((4, cleaning_team_duty.id)) def action_cancel(self): """The button action for "Cancel" typically involves canceling and removing a booking that was previously confirmed or reserved.""" for rec in self: rec.cleaning_team_duty_id.write({'state': 'cancelled'}) rec.write( {'state': 'cancelled', 'confirm_stage': False, 'cancel_stage': True, 'clean_stage': True}) def action_create_invoice(self): """Function for create an invoice for cleaning processes""" for rec in self: if rec.unit_price > 0.0: invoice = rec.env['account.move'].create({ 'move_type': 'out_invoice', 'partner_id': rec.customer_name_id.id, 'invoice_date': date.today(), 'payment_reference': rec.cleaning_date, 'cleaning_id': rec.id, 'invoice_line_ids': [(0, 0, { 'name': f"{rec.cleaning_team_id.name} ({rec.cleaning_inspection_id.inspection_date_and_time})", 'price_unit': float(rec.unit_price) * float( rec.total_hour_of_working), })], }) return { 'name': 'account.move.form', 'res_model': 'account.move', 'type': 'ir.actions.act_window', 'view_mode': 'form', 'view_type': 'form', 'view_id': rec.env.ref("account.view_move_form").id, 'res_id': invoice.id, 'target': 'current' } else: raise ValidationError(_("Specify the Unit Price for a hour")) def action_view_invoice(self): """Function for open Invoice Smart Button""" self.ensure_one() return { 'type': 'ir.actions.act_window', 'name': 'Invoice', 'view_mode': 'list,form', 'res_model': 'account.move', 'domain': [('cleaning_id', '=', self.id)], 'context': "{'create': False}" } def _compute_invoice_count(self): """Function for count number of Invoices""" for record in self: record.invoice_count = self.env['account.move'].search_count( [('cleaning_id', '=', self.id)])