#This file is part of Presik. The COPYRIGHT file at the top level of # this repository contains the full copyright notices and license terms. from datetime import datetime, date, timedelta from trytond.model import ModelView, ModelSQL, Workflow, fields from trytond.pyson import Eval from trytond.wizard import ( Wizard, StateView, Button, StateTransition, StateReport ) from trytond.pool import Pool from trytond.report import Report from trytond.transaction import Transaction ROOM_STATUS = [ ('inspected', 'Inspected'), ('not_authorized', 'Not Authorized'), ('dirty', 'Dirty'), ('clean', 'Clean'), ('maintenance', 'Maintenance'), ] class CleaningType(ModelSQL, ModelView): "Room Cleaning Type" __name__ = "hotel.room.cleaning_type" name = fields.Char('Name', required=True, select=True) description = fields.Text('Description') kind = fields.Selection([ ('tweak', 'Tweak'), ('deep', 'Deep'), ('standard', 'Standard'), ], 'Kind', required=True) class Room(Workflow, ModelSQL, ModelView): 'Hotel Room' __name__ = 'hotel.room' name = fields.Char('Name', required=True) code = fields.Char('Code') active = fields.Boolean('Active') templates = fields.Many2Many('hotel.room-product.template', 'room', 'template', 'Hotel Room - Product Accommodation', domain=[ ('type', '=', 'service'), ('kind', '=', 'accommodation'), ]) classification = fields.Many2One('hotel.room.classification', 'Classification') location = fields.Many2One('hotel.location', 'Location', select=True) amenities = fields.Many2Many('hotel.room-hotel.amenities', 'room', 'amenities', 'Amenities') space = fields.Integer('Space', help='Space on m2') channel_id = fields.Char('Channel Manager ID') main_accommodation = fields.Many2One('product.template', 'Main Accommodation', ondelete='RESTRICT', depends=['templates'], domain=[('id', 'in', Eval('templates', []))], ) # TODO: Maybe add require a Current State field min_unit_price = fields.Numeric('Min. Unit Price', digits=(16, 4)) max_unit_price = fields.Numeric('Max. Unit Price', digits=(16, 4)) state = fields.Selection(ROOM_STATUS, 'Status', required=True, readonly=True) state_string = state.translated('state') cleaning_type = fields.Function(fields.Many2One( 'hotel.room.cleaning_type', 'Cleaning Type', required=False), 'get_cleaning_type') last_check_in = fields.DateTime('Last Check In') last_check_out = fields.DateTime('Last Check Out') last_clean = fields.DateTime('Last Clean') housekeeping = fields.Many2One('company.employee', 'Employee') notes = fields.Text('Notes') max_accommodation = fields.Integer('Max. Accommodation') guests = fields.Function(fields.Integer('Guests'), 'get_guests') @classmethod def __setup__(cls): super(Room, cls).__setup__() cls._transitions |= set(( ('clean', 'dirty'), ('clean', 'inspected'), ('clean', 'maintenance'), ('not_authorized', 'clean'), ('not_authorized', 'dirty'), ('dirty', 'clean'), ('dirty', 'maintenance'), ('dirty', 'inspected'), ('dirty', 'not_authorized'), ('maintenance', 'inspected'), ('maintenance', 'dirty'), ('inspected', 'dirty'), ('inspected', 'maintenance'), ('inspected', 'clean'), )) cls._buttons.update({ 'clean': { 'invisible': Eval('state').in_(['maintenance', 'clean']), }, 'dirty': { 'invisible': Eval('state').in_(['dirty']), }, 'inspected': { 'invisible': Eval('state').in_(['inspected']), }, 'maintenance': { 'invisible': Eval('state').in_(['maintenance']), }, 'not_authorized': { 'invisible': Eval('state').in_(['maintenance']), }, }) @staticmethod def default_active(): return True @staticmethod def default_state(): return 'dirty' @classmethod @ModelView.button @Workflow.transition('clean') def clean(cls, records): for rec in records: rec.last_clean = datetime.now() rec.cleaning_type = None rec.save() @classmethod @ModelView.button @Workflow.transition('not_authorized') def not_authorized(cls, records): pass @classmethod @ModelView.button @Workflow.transition('dirty') def dirty(cls, records): Config = Pool().get('hotel.configuration') config = Config.get_configuration() for rec in records: rec.cleaning_type = config.cleaning_occupied.id @classmethod @ModelView.button @Workflow.transition('maintenance') def maintenance(cls, records): pass @classmethod @ModelView.button @Workflow.transition('inspected') def inspected(cls, records): pass def get_guests(self, name=None): pool = Pool() Folio = pool.get('hotel.folio') folios = Folio.search([ ('room', '=', self.id), ('arrival_date', '<=', date.today()), ('departure_date', '>', date.today()) ]) res = [] for folio in folios: res.append(len(folio.guests)) return sum(res) def get_cleaning_type(self, name=None): pool = Pool() Config = pool.get('hotel.configuration') Folio = pool.get('hotel.folio') config = Config.get_configuration() today = date.today() yesterday = today - timedelta(days=-1) read = Folio.search_read folios = read([ ('room', '=', self.id), ('departure_date', '=', today) ], fields_names=['registration_state'], ) if folios: return config.cleaning_check_out.id else: folios = read([ ('room', '=', self.id), ('departure_date', '>', today), ('arrival_date', '<', today), ], fields_names=['registration_state'], ) if folios: return config.cleaning_occupied.id else: return config.cleaning_check_in.id @classmethod def set_dirty_rooms(cls, name=None): pool = Pool() rooms = cls.search([]) cls.write(rooms, {'state': 'dirty'}) class RoomAmenities(ModelSQL): 'Room - Amenities' __name__ = 'hotel.room-hotel.amenities' _rec_name = 'name' room = fields.Many2One('hotel.room', 'Room', required=True, ondelete='CASCADE') amenities = fields.Many2One('hotel.amenities', 'Amenities', required=True, ondelete='CASCADE') class Amenities(ModelSQL, ModelView): 'Amenities' __name__ = 'hotel.amenities' _rec_name = 'name' name = fields.Char('Name', required=True) notes = fields.Text('Notes') type = fields.Selection([ ('', ''), ('lingerie', 'Lingerie Room'), ('service', 'Service'), ], 'Type of Service') cleaning_days = fields.One2Many('hotel.cleaning_days', 'amenities', 'Cleanning Days', states={ 'invisible': Eval('type') != 'lingerie', }, depends=['type']) class RoomClassification(ModelSQL, ModelView): 'Room Classification' __name__ = 'hotel.room.classification' name = fields.Char('Name', required=True) class CleanningDays(ModelSQL, ModelView): 'Cleanning Days' __name__ = 'hotel.cleaning_days' amenities = fields.Many2One('hotel.amenities', 'Amenities', required=True, ondelete='CASCADE') weekday = fields.Selection([ ('1', 'Monday'), ('2', 'Tuesday'), ('3', 'Wednesday'), ('4', 'Thursday'), ('5', 'Friday'), ('6', 'Saturday'), ('7', 'Sunday'), ], 'Weekday', required=True) note = fields.Text('Note') class RoomTemplate(ModelSQL): 'Room - Template' __name__ = 'hotel.room-product.template' room = fields.Many2One('hotel.room', 'Room', required=True, ondelete='CASCADE') template = fields.Many2One('product.template', 'Product Template', required=True, ondelete='CASCADE') class HousekeepingStart(ModelView): 'Print Housekeeping Service Start' __name__ = 'hotel.print_housekeeping.start' date = fields.Date('Date', required=True) employee = fields.Many2One('company.employee', 'Employee') company = fields.Many2One('company.company', 'Company', required=True) @staticmethod def default_date(): Date_ = Pool().get('ir.date') return Date_.today() @staticmethod def default_company(): return Transaction().context.get('company') class Housekeeping(Wizard): 'Housekeeping Service' __name__ = 'hotel.print_housekeeping' start = StateView('hotel.print_housekeeping.start', 'hotel.print_housekeeping_start_view_form', [ Button('Cancel', 'end', 'tryton-cancel'), Button('Open', 'print_', 'tryton-print', default=True), ]) print_ = StateReport('hotel.print_housekeeping.report') def do_print_(self, action): company = self.start.company data = { 'date': self.start.date, 'employee': self.start.employee.id if self.start.employee else None, 'company': company.id, } return action, data def transition_print_(self): return 'end' class HousekeepingReport(Report): __name__ = 'hotel.print_housekeeping.report' @classmethod def get_context(cls, records, header, data): report_context = super().get_context(records, header, data) pool = Pool() Company = pool.get('company.company') Room = pool.get('hotel.room') dom = [] if data['employee']: dom.append(('employee.id', '=', data['employee'])) rooms = Room.search(dom) total_guests = [] for room in rooms: total_guests.append(room.guests) report_context['records'] = rooms report_context['company'] = Company(data['company']) report_context['date'] = datetime.now() report_context['total_guests'] = sum(total_guests) return report_context class HotelTask(ModelSQL, ModelView): "Hotel Task" __name__ = "hotel.task" name = fields.Char('Name Task', required=True, select=True) frecuency = fields.Integer('Frecuency', select=True, help='In days') quantity = fields.Integer('Quantity', select=True) # class HotelHousekeepingTask(ModelView, ModelSQL): # 'Hotel Housekeeping Task' # __name__ = 'hotel.housekeeping.task' # room = fields.Many2One('hotel.room', 'Hotel Housekeeping', # ondelete='CASCADE', select=True, required=True) # task = fields.Many2One('hotel.task', 'Task', select=True, required=True) # frecuency = fields.Integer('Frecuency', select=True, help='In days') # quantity = fields.Integer('Quantity', select=True) # # @fields.depends('task', 'frecuency') # def on_change_task(self, name=None): # if self.task: # self.frecuency = self.task.frecuency