1090 lines
42 KiB
Python
1090 lines
42 KiB
Python
import datetime
|
|
import time
|
|
# from typing_extensions import Self
|
|
|
|
from odoo import netsvc
|
|
# from odoo.addons import decimal_precision as dp
|
|
from odoo import api, fields, models, SUPERUSER_ID, _
|
|
from odoo.exceptions import AccessError, UserError, ValidationError
|
|
from odoo.tools import float_is_zero, float_compare
|
|
from odoo.tools.translate import html_translate
|
|
import math
|
|
import logging
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class hotel_floor(models.Model):
|
|
_name = "hotel.floor"
|
|
_description = "Floor"
|
|
|
|
name = fields.Char('Floor Name', required=True, index=True)
|
|
sequence = fields.Integer('Sequence')
|
|
|
|
|
|
class product_category(models.Model):
|
|
_inherit = "product.category"
|
|
|
|
isroomtype = fields.Boolean('Is Room Type')
|
|
isamenitype = fields.Boolean('Is amenities Type')
|
|
isservicetype = fields.Boolean('Is Service Type')
|
|
|
|
company_id = fields.Many2one('res.company', string='Company')
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals):
|
|
# for val_list1 in vals:
|
|
# # val_list1['company_id']=self.env.user.company_id.id
|
|
res = super(product_category, self).create(vals)
|
|
res.company_id = self.env.user.company_id.id
|
|
|
|
return res
|
|
|
|
|
|
class hotel_room_type(models.Model):
|
|
_name = "hotel.room_type"
|
|
_inherits = {'product.category': 'cat_id'}
|
|
_description = "Room Type"
|
|
|
|
room_type_amenities = fields.Many2many(
|
|
'hotel.room_amenities', 'temp_tab_type', 'room_type_amenities', 'rcateg_id', 'Room Amenities')
|
|
cat_id = fields.Many2one(
|
|
'product.category', string='Category', required=True, ondelete="cascade")
|
|
description = fields.Html('Description')
|
|
# facilities = fields.Html('Facilities and Services')
|
|
amenities = fields.Html('Amenities')
|
|
services = fields.Html('services')
|
|
img_ids = fields.One2many('hotel.room.images', 'room_images_id', 'Image')
|
|
company_id = fields.Many2one(
|
|
'res.company', string='Company',
|
|
domain="[('id', 'in', [current_company_id])]",
|
|
required=True)
|
|
isroomtype = fields.Boolean(
|
|
'Is Room Type', related='cat_id.isroomtype', inherited=True, default=True)
|
|
|
|
@api.onchange('company_id')
|
|
def product_category_company_change(self):
|
|
product_category_id = self.env['product.category'].search([('name', '=', self.name)])
|
|
_logger.info("Product Category===>>>>>>>>>>>>>{}".format(product_category_id))
|
|
product_category_id.write({'company_id': self.company_id})
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals):
|
|
res = super(hotel_room_type, self).create(vals)
|
|
return res
|
|
|
|
# @api.multi
|
|
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.cat_id.unlink()
|
|
return super(hotel_room_type, self).unlink()
|
|
|
|
|
|
class hotel_room_images(models.Model):
|
|
_name = "hotel.room.images"
|
|
_description = "Store multiple images for each room"
|
|
|
|
room_images_id = fields.Many2one('hotel.room_type', 'img_ids')
|
|
name = fields.Char("Title", required=True)
|
|
img = fields.Binary(
|
|
"Image", help="This field holds the image for Room, limited to 1024x1024px")
|
|
|
|
|
|
class product_product(models.Model):
|
|
_inherit = "product.product"
|
|
|
|
isroom = fields.Boolean('Is Room')
|
|
iscategid = fields.Boolean('Is categ id')
|
|
isservice = fields.Boolean('Is Service id')
|
|
state = fields.Selection([('', ''),
|
|
('draft', 'Available'),
|
|
('sellable', 'Booked'),
|
|
], 'Status', default='draft', help="Tells the user if room is available of booked.")
|
|
|
|
|
|
class hotel_room_amenities_type(models.Model):
|
|
_name = 'hotel.room_amenities_type'
|
|
_description = 'amenities Type'
|
|
_inherits = {'product.category': 'cat_id'}
|
|
|
|
cat_id = fields.Many2one(
|
|
'product.category', string='category', required=True, ondelete="cascade")
|
|
isamenitype = fields.Boolean(
|
|
'Is amenities Type', related='cat_id.isamenitype', inherited=True, default=True)
|
|
company_id = fields.Many2one(
|
|
'res.company', string='Company',
|
|
domain="[('id', 'in', [current_company_id])]",
|
|
required=True)
|
|
|
|
# @api.multi
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.cat_id.unlink()
|
|
return super(hotel_room_amenities_type, self).unlink()
|
|
|
|
|
|
class hotel_room_amenities(models.Model):
|
|
_name = 'hotel.room_amenities'
|
|
_description = 'Room amenities'
|
|
_inherits = {'product.product': 'room_categ_id'}
|
|
_inherit = ['mail.thread']
|
|
|
|
room_categ_id = fields.Many2one(
|
|
'product.product', string='product category', required=True, ondelete="cascade")
|
|
rcateg_id = fields.Many2one(
|
|
'hotel.room_amenities_type', 'Amenity Catagory')
|
|
amenity_rate = fields.Integer('Amenity Rate')
|
|
|
|
iscategid = fields.Boolean(
|
|
'Is categ id', related='room_categ_id.iscategid', inherited=True, default=True)
|
|
|
|
def action_open_documents(self):
|
|
self.room_categ_id.product_tmpl_id.action_open_documents()
|
|
|
|
@api.onchange('shop_id')
|
|
def on_change_shop_id(self):
|
|
if not self.shop_id:
|
|
return {'value': {}}
|
|
temp = self.shop_id
|
|
self.company_id = temp.company_id.id
|
|
|
|
def action_compute_bom_days(self):
|
|
return True
|
|
|
|
def action_open_label_layout(self):
|
|
action = self.env['ir.actions.act_window']._for_xml_id('product.action_open_label_layout')
|
|
action['context'] = {'default_product_tmpl_ids': self.ids}
|
|
return action
|
|
|
|
def open_pricelist_rules(self):
|
|
self.ensure_one()
|
|
domain = ['|',
|
|
('product_tmpl_id', '=', self.id),
|
|
('product_id', 'in', self.product_variant_ids.ids)]
|
|
return {
|
|
'name': ('Price Rules'),
|
|
'view_mode': 'tree,form',
|
|
'views': [(self.env.ref('product.product_pricelist_item_tree_view_from_product').id, 'tree'),
|
|
(False, 'form')],
|
|
'res_model': 'product.pricelist.item',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
'domain': domain,
|
|
'context': {
|
|
'default_product_tmpl_id': self.id,
|
|
'default_applied_on': '1_product',
|
|
'product_without_variants': self.product_variant_count == 1,
|
|
},
|
|
}
|
|
|
|
# @api.multi
|
|
|
|
def read_followers_data(self, follower_ids):
|
|
result = []
|
|
technical_group = self.env['ir.model.data'].get_object(
|
|
'base', 'group_no_one')
|
|
for follower in self.env['res.partner'].browse(self._ids):
|
|
is_editable = self._uid in map(
|
|
lambda x: x.id, technical_group.users)
|
|
is_uid = self._uid in map(lambda x: x.id, follower.user_ids)
|
|
data = (follower.id,
|
|
follower.name,
|
|
{'is_editable': is_editable, 'is_uid': is_uid},
|
|
)
|
|
result.append(data)
|
|
return result
|
|
|
|
@api.onchange('type')
|
|
def onchange_type(self):
|
|
res = {}
|
|
if type in ('consu', 'service'):
|
|
res = {'value': {'valuation': 'manual_periodic'}}
|
|
return res
|
|
|
|
@api.onchange('tracking')
|
|
def onchange_tracking(self):
|
|
if not self.tracking:
|
|
return {}
|
|
product_product = self.env['product.product']
|
|
variant_ids = product_product.search(
|
|
[('product_tmpl_id', 'in', self._ids)])
|
|
for variant_id in variant_ids:
|
|
variant_id.onchange_tracking()
|
|
|
|
# @api.multi
|
|
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.room_categ_id.unlink()
|
|
return super(hotel_room_amenities, self).unlink()
|
|
|
|
def message_get_subscription_data(self, user_pid=None, ):
|
|
""" Wrapper to get subtypes data. """
|
|
return self.env['mail.thread']._get_subscription_data(None, None, user_pid=user_pid, context=self._context)
|
|
|
|
|
|
class product_template(models.Model):
|
|
_inherit = "product.template"
|
|
|
|
max_adult = fields.Integer('Max Adult')
|
|
max_child = fields.Integer('Max Child')
|
|
|
|
class hotel_room(models.Model):
|
|
_name = 'hotel.room'
|
|
_inherits = {'product.product': 'product_id'}
|
|
_description = 'Hotel Room'
|
|
_inherit = ['mail.thread']
|
|
|
|
def action_compute_bom_days(self):
|
|
return True
|
|
|
|
def action_open_documents(self):
|
|
self.product_id.product_tmpl_id.action_open_documents()
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals):
|
|
_logger.info("VALS====>>>>>>>>>>>>>>{}".format(vals))
|
|
|
|
return super(hotel_room, self).create(vals)
|
|
|
|
def action_open_label_layout(self):
|
|
action = self.env['ir.actions.act_window']._for_xml_id('product.action_open_label_layout')
|
|
action['context'] = {'default_product_tmpl_ids': self.ids}
|
|
return action
|
|
|
|
def open_website_url(self):
|
|
self.ensure_one()
|
|
res = self.product_id.product_tmpl_id.open_website_url()
|
|
res['url'] = self.product_id.website_url
|
|
return res
|
|
|
|
def open_pricelist_rules(self):
|
|
self.ensure_one()
|
|
domain = ['|',
|
|
('product_tmpl_id', '=', self.id),
|
|
('product_id', 'in', self.product_variant_ids.ids)]
|
|
return {
|
|
'name': ('Price Rules'),
|
|
'view_mode': 'tree,form',
|
|
'views': [(self.env.ref('product.product_pricelist_item_tree_view_from_product').id, 'tree'),
|
|
(False, 'form')],
|
|
'res_model': 'product.pricelist.item',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
'domain': domain,
|
|
'context': {
|
|
'default_product_tmpl_id': self.id,
|
|
'default_applied_on': '1_product',
|
|
'product_without_variants': self.product_variant_count == 1,
|
|
},
|
|
}
|
|
|
|
def action_open_label_layout(self):
|
|
action = self.env['ir.actions.act_window']._for_xml_id('product.action_open_label_layout')
|
|
action['context'] = {'default_product_tmpl_ids': self.ids}
|
|
return action
|
|
|
|
# @api.one
|
|
# @api.returns('self', lambda value: value.id if value.id else False)
|
|
# def copy(self, default=None):
|
|
# context = self._context or {}
|
|
# default = dict(default or {}, name=("%s (Copy)") % self.name)
|
|
# context_wo_lang = dict(context or {})
|
|
# context_wo_lang.pop('lang', None)
|
|
# context = context_wo_lang
|
|
# room = self.browse(self.ids)
|
|
# if context.get('variant'):
|
|
# # if we copy a variant or create one, we keep the same template
|
|
# default['product_id'] = room.product_id.id
|
|
# elif 'name' not in default:
|
|
# default['name'] = _("%s (copy)") % (room.name,)
|
|
#
|
|
# print('----------------default------------------')
|
|
# print(default)
|
|
# return super(hotel_room, self).copy(default=default)
|
|
|
|
@api.onchange('type')
|
|
def onchange_type(self):
|
|
res = {}
|
|
if type in ('consu', 'service'):
|
|
res = {'value': {'valuation': 'manual_periodic'}}
|
|
return res
|
|
|
|
@api.onchange('tracking')
|
|
def onchange_tracking(self):
|
|
if not self.tracking:
|
|
return {}
|
|
product_product = self.env['product.product']
|
|
variant_ids = product_product.search(
|
|
[('product_tmpl_id', 'in', self._ids)])
|
|
for variant_id in variant_ids:
|
|
variant_id.onchange_tracking()
|
|
|
|
product_id = fields.Many2one(
|
|
'product.product', string='Product_id', required=True, ondelete="cascade")
|
|
floor_id = fields.Many2one('hotel.floor', 'Floor No')
|
|
# max_adult = fields.Integer('Max Adult')
|
|
# max_child = fields.Integer('Max Child')
|
|
room_amenities = fields.Many2many(
|
|
'hotel.room_amenities', 'temp_tab', 'room_amenities', 'rcateg_id', 'Room Amenities')
|
|
|
|
isroom = fields.Boolean(
|
|
'Is Hotel Room', related='product_id.isroom', inherited=True, default=True)
|
|
# rental = fields.Boolean(
|
|
# 'Is Rental', related='product_id.rental', inherited=True, default=True)
|
|
rental = fields.Boolean(
|
|
'Is Rental', default=True)
|
|
allow_out_of_stock_order = fields.Boolean(string='Continue selling when out-of-stock', default=True)
|
|
show_availability = fields.Boolean(string='Show availability Qty', default=False)
|
|
available_threshold = fields.Float(string='Show Threshold', default=5.0)
|
|
out_of_stock_message = fields.Html(string="Out-of-Stock Message", translate=html_translate)
|
|
|
|
# @api.multi
|
|
|
|
def read_followers_data(self):
|
|
result = []
|
|
technical_group = self.env['ir.model.data'].get_object(
|
|
'base', 'group_no_one', context=self._context)
|
|
for follower in self.env['res.partner'].browse(self._ids):
|
|
is_editable = self._uid in map(
|
|
lambda x: x.id, technical_group.users)
|
|
is_uid = self._uid in map(lambda x: x.id, follower.user_ids)
|
|
data = (follower.id,
|
|
follower.name,
|
|
{'is_editable': is_editable, 'is_uid': is_uid},
|
|
)
|
|
result.append(data)
|
|
return result
|
|
|
|
def message_get_subscription_data(self, user_pid=None):
|
|
""" Wrapper to get subtypes data. """
|
|
return self.env['mail.thread']._get_subscription_data(None, None, user_pid=user_pid)
|
|
|
|
# @api.multi
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.product_id.unlink()
|
|
|
|
|
|
class hotel_folio(models.Model):
|
|
|
|
# @api.one
|
|
@api.returns('self', lambda value: value.id)
|
|
def copy(self, default=None, ):
|
|
context = self._context or {}
|
|
default = dict(default or {}, name=_("%s (Copy)") % self.name)
|
|
context_wo_lang = dict(context or {})
|
|
context_wo_lang.pop('lang', None)
|
|
context = context_wo_lang
|
|
room = self.browse(self._ids)
|
|
if context.get('variant'):
|
|
# if we copy a variant or create one, we keep the same template
|
|
default['order_id'] = room.order_id.id
|
|
elif 'name' not in default:
|
|
default['name'] = _("%s (copy)") % (room.name,)
|
|
|
|
return super(hotel_folio, self).copy(default=default)
|
|
|
|
# @api.multi
|
|
|
|
def button_dummy11(self):
|
|
val = val1 = 0.0
|
|
for order in self:
|
|
for line in order.order_line:
|
|
val1 += line.price_subtotal
|
|
val += self.env['sale.order']._amount_line_tax(line)
|
|
total = val1 + val
|
|
if val:
|
|
self._cr.execute(
|
|
"""UPDATE sale_order SET amount_untaxed =%s, amount_tax =%s, amount_total =%s WHERE id =%s""",
|
|
(val1, val, total, order.order_id.id))
|
|
else:
|
|
self._cr.execute(
|
|
"""UPDATE sale_order SET amount_untaxed =%s, amount_total =%s WHERE id =%s""",
|
|
(val1, val1, order.order_id.id))
|
|
self._cr.commit()
|
|
return True
|
|
|
|
_name = 'hotel.folio'
|
|
_description = 'hotel folio new'
|
|
_inherit = ['mail.thread']
|
|
_inherits = {'sale.order': 'order_id'}
|
|
order_id = fields.Many2one(
|
|
'sale.order', required=True, string='Order Id', ondelete='cascade')
|
|
room_lines = fields.One2many(
|
|
'hotel_folio.line', 'folio_id', string="Rooms")
|
|
service_lines = fields.One2many(
|
|
'hotel_service.line', 'folio_id')
|
|
order_reserve_invoice_ids = fields.Many2many(
|
|
'account.move', 'order_reserve_invoice_rel', 'folio_id', 'invoice_id', 'Order Reservation Invoices',
|
|
readonly=True)
|
|
table_order_invoice_ids = fields.Many2many(
|
|
'account.move', 'table_order_invoice_rel', 'order_id', 'invoice_id', 'Table Order Invoices', readonly=True)
|
|
note = fields.Text(string='Note')
|
|
shop_id = fields.Many2one('sale.shop', 'Hotel', domain="[('company_id', '=', [current_company_id])]",)
|
|
currency_id = fields.Many2one('res.currency', 'Currency', required=True, related='company_id.currency_id',
|
|
default=lambda self: self.env.user.company_id.currency_id.id)
|
|
|
|
# @api.multi
|
|
def _get_report_base_filename(self):
|
|
return "Room-Guest-WiseReport"
|
|
|
|
def action_view_invoice1(self):
|
|
invoices = self.mapped('invoice_ids')
|
|
action = self.env.ref('account.view_invoice_tree').read()[0]
|
|
if len(invoices) > 1:
|
|
action['domain'] = [('id', 'in', invoices.ids)]
|
|
elif len(invoices) == 1:
|
|
form_view = [
|
|
(self.env.ref('account.view_move_line_form').id, 'form')]
|
|
if 'views' in action:
|
|
action['views'] = form_view + \
|
|
[(state, view)
|
|
for state, view in action['views'] if view != 'form']
|
|
else:
|
|
action['views'] = form_view
|
|
action['res_id'] = invoices.ids[0]
|
|
else:
|
|
action = {'type': 'ir.actions.act_window_close'}
|
|
return action
|
|
|
|
def action_view_invoice(self):
|
|
invoices = self.mapped('invoice_ids')
|
|
action = self.env.ref('account.action_move_out_invoice_type').read()[0]
|
|
if len(invoices) > 1:
|
|
action['domain'] = [('id', 'in', invoices.ids)]
|
|
elif len(invoices) == 1:
|
|
form_view = [(self.env.ref('account.view_move_form').id, 'form')]
|
|
if 'views' in action:
|
|
action['views'] = form_view + \
|
|
[(state, view)
|
|
for state, view in action['views'] if view != 'form']
|
|
else:
|
|
action['views'] = form_view
|
|
action['res_id'] = invoices.id
|
|
else:
|
|
action = {'type': 'ir.actions.act_window_close'}
|
|
|
|
# context = {
|
|
# 'default_type': 'out_invoice',
|
|
# }
|
|
context = {}
|
|
if len(self) == 1:
|
|
context.update({
|
|
'default_partner_id': self.partner_id.id,
|
|
'default_partner_shipping_id': self.partner_shipping_id.id,
|
|
'default_invoice_payment_term_id': self.payment_term_id.id or self.partner_id.property_payment_term_id.id or
|
|
self.env['account.move'].default_get(
|
|
['invoice_payment_term_id']).get('invoice_payment_term_id'),
|
|
'default_invoice_origin': self.mapped('name'),
|
|
'default_user_id': self.user_id.id,
|
|
})
|
|
action['context'] = context
|
|
return action
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals):
|
|
for val in vals:
|
|
tmp_room_lines = val.get('room_lines', [])
|
|
tmp_service_lines = val.get('service_lines', [])
|
|
if "folio_id" not in val:
|
|
val.update({'room_lines': [], 'service_lines': []})
|
|
folio_id = super(hotel_folio, self).create(val)
|
|
for line in tmp_room_lines:
|
|
line[2].update({'folio_id': folio_id})
|
|
for line in tmp_service_lines:
|
|
line[2].update({'folio_id': folio_id})
|
|
val.update(
|
|
{'room_lines': tmp_room_lines, 'service_lines': tmp_service_lines})
|
|
super(hotel_folio, self).write(val)
|
|
|
|
else:
|
|
folio_id = super(hotel_folio, self).create(val)
|
|
return folio_id
|
|
|
|
|
|
def action_confirm(self):
|
|
for record in self:
|
|
# record.room_lines.update({
|
|
# 'checkout_date': datetime.datetime.now()
|
|
# })
|
|
for line in record.room_lines:
|
|
room_his_id = self.env['hotel.room.booking.history'].search(
|
|
[('booking_id', '=', record.reservation_id.id),
|
|
('history_id.name', '=', line.product_id.name)])
|
|
if room_his_id:
|
|
room_his_id.sudo().write({
|
|
'check_out': line.checkout_date
|
|
})
|
|
|
|
self.write({'state': 'sale'})
|
|
self.order_id.action_confirm()
|
|
return True
|
|
|
|
def action_button_confirm(self):
|
|
assert len(
|
|
self._ids) == 1, 'This option should only be used for a single id at a time.'
|
|
wf_service = netsvc.LocalService('workflow')
|
|
wf_service.trg_validate(self.uid, 'hotel.folio',
|
|
self._ids[0], 'order_confirm', self._cr)
|
|
|
|
view_ref = self.env['ir.model.data'].get_object_reference(
|
|
'hotel', 'view_hotel_folio1_form')
|
|
view_id = view_ref and view_ref[1] or False,
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': ('Hotel Folio'),
|
|
'res_model': 'hotel.folio',
|
|
'res_id': self.ids[0],
|
|
'view_type': 'form',
|
|
'view_mode': 'form',
|
|
'view_id': view_id,
|
|
'target': 'current',
|
|
'nodestroy': True,
|
|
}
|
|
|
|
# @api.onchange('shop_id')
|
|
# def onchange_shop_id(self):
|
|
# return self.order_id.onchange_shop_id()
|
|
|
|
@api.onchange('partner_id')
|
|
def onchange_partner_id(self):
|
|
if self.ids:
|
|
return self.order_id.onchange_partner_id()
|
|
|
|
# @api.multi
|
|
|
|
def button_dummy(self):
|
|
for record in self:
|
|
return self.env['sale.order'].browse(record.order_id).button_dummy()
|
|
|
|
# ====================corrected============================================
|
|
# @api.multi
|
|
|
|
def action_invoice_create(self, grouped=False, states=['confirmed', 'done']):
|
|
for record in self._ids:
|
|
i = record.order_id.action_invoice_create(
|
|
grouped=False, states=['confirmed', 'done'])
|
|
|
|
for line in self._ids:
|
|
# print ("line", line)
|
|
line.write({'invoiced': True})
|
|
if grouped:
|
|
line.write({'state': 'progress'})
|
|
else:
|
|
line.write({'state': 'progress'})
|
|
for obj in line.room_lines:
|
|
obj.product_id.write({'state': 'draft'})
|
|
if line.order_reserve_invoice_ids:
|
|
for order_line in line.order_reserve_invoice_ids:
|
|
if order_line.state == 'draft':
|
|
raise ValidationError(
|
|
('Error !', 'Checkout Table Reservation Invoices are not validated !'))
|
|
if line.table_order_invoice_ids:
|
|
|
|
for table_line in line.table_order_invoice_ids:
|
|
if table_line.state == 'draft':
|
|
raise ValidationError(
|
|
('Error !', 'Checkout Table Order Invoices are not validated !'))
|
|
return i
|
|
|
|
# @api.multi
|
|
|
|
def action_invoice_cancel(self):
|
|
for record in self:
|
|
res = record.order_id.action_invoice_cancel()
|
|
for line in record.order_line:
|
|
line.write({'invoiced': False, 'state': 'draft'})
|
|
record.write({'state': 'invoice_except', 'invoice_id': False})
|
|
return res
|
|
|
|
# @api.multi
|
|
|
|
def action_cancel(self):
|
|
for record in self:
|
|
c = record.order_id.action_cancel()
|
|
for r in self.read(['picking_ids']):
|
|
for pick in r['picking_ids']:
|
|
wf_service = netsvc.LocalService("workflow")
|
|
wf_service.trg_validate(
|
|
'stock.picking', pick, 'button_cancel')
|
|
for r in self.read(['invoice_ids']):
|
|
for inv in r['invoice_ids']:
|
|
wf_service = netsvc.LocalService("workflow")
|
|
wf_service.trg_validate(
|
|
'account.move', inv, 'invoice_cancel')
|
|
|
|
record.write({'state': 'cancel'})
|
|
return c
|
|
|
|
# @api.multi
|
|
|
|
def action_wait(self):
|
|
for o in self:
|
|
if (not o.invoice_ids):
|
|
o.write({'state': 'manual'})
|
|
else:
|
|
o.write({'state': 'progress'})
|
|
return True
|
|
|
|
def _message_get_suggested_recipients(self):
|
|
""" Returns suggested recipients for ids. Those are a list of
|
|
tuple (partner_id, partner_name, reason), to be managed by Chatter. """
|
|
result = dict((res_id, []) for res_id in self.ids)
|
|
if 'user_id' in self._fields:
|
|
for obj in self: # SUPERUSER because of a read on res.users that would crash otherwise
|
|
if not obj.user_id or not obj.user_id.partner_id:
|
|
continue
|
|
# obj._message_add_suggested_recipient(result, partner=obj.user_id.partner_id, reason=self._fields['user_id'].string)
|
|
return result
|
|
|
|
|
|
class hotel_folio_line(models.Model):
|
|
_name = 'hotel_folio.line'
|
|
_description = 'hotel folio1 room line'
|
|
_inherits = {'sale.order.line': 'order_line_id'}
|
|
|
|
order_line_id = fields.Many2one(
|
|
'sale.order.line', string='order_line_id', ondelete='cascade', required=True, )
|
|
folio_id = fields.Many2one(
|
|
'hotel.folio', string='Folio', ondelete='cascade')
|
|
checkin_date = fields.Datetime('Check In')
|
|
checkout_date = fields.Datetime('Check Out')
|
|
categ_id = fields.Many2one(
|
|
'product.category', 'Room Type', domain="[('isroomtype','=',True)]", required=True)
|
|
|
|
@api.onchange('product_id')
|
|
def product_id_change(self):
|
|
if self.product_id:
|
|
self.product_uom = self.product_id.uom_id
|
|
product_browse = self.product_id
|
|
pricelist = self.folio_id.pricelist_id.id
|
|
|
|
ctx = self._context and self._context.copy() or {}
|
|
ctx.update({'date': self.checkin_date})
|
|
|
|
price = self.env['product.pricelist']._price_get(
|
|
self.product_id, self.product_uom_qty,uom=product_browse.uom_id, date=self.checkin_date)[pricelist]
|
|
|
|
self.price_unit = price
|
|
self.name = self.product_id.description_sale
|
|
|
|
# @api.multi
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals):
|
|
for val in vals:
|
|
if not self._context:
|
|
self._context = {}
|
|
if "folio_id" in val:
|
|
folio = self.env["hotel.folio"].browse([val['folio_id']])[0]
|
|
# self.env["product.product"].browse(
|
|
# vals['product_id']).write({'state': 'sellable'})
|
|
val.update({'order_id': folio.order_id.id})
|
|
|
|
roomline = super(hotel_folio_line, self).create(val)
|
|
|
|
if roomline:
|
|
cnt2 = 0
|
|
cnt1 = 0
|
|
for lines_k in folio.room_lines:
|
|
cnt2 = cnt2 + 1
|
|
for lines_k in folio.reservation_id.reservation_line:
|
|
cnt1 = cnt1 + 1
|
|
if roomline:
|
|
if cnt2 > cnt1:
|
|
ff = self.env['hotel.reservation.line'].create(
|
|
{
|
|
'checkin': val['checkin_date'],
|
|
'checkout': val['checkout_date'],
|
|
'categ_id': val['categ_id'],
|
|
'room_number': val['product_id'],
|
|
'line_id': folio.reservation_id.id,
|
|
'price': val['price_unit'],
|
|
'discount': val['discount'],
|
|
|
|
}
|
|
)
|
|
roomline.write({"hotel_reservation_line_id": ff.id})
|
|
|
|
return roomline
|
|
|
|
@api.model
|
|
def write(self, vals):
|
|
for line_obj in self:
|
|
line_search = self.env['hotel.reservation.line'].search(
|
|
[('id', '=', line_obj.hotel_reservation_line_id.id)])
|
|
if 'product_id' in vals:
|
|
if line_search.room_number.id != vals['product_id']:
|
|
room_id_room_data = self.env['hotel.room'].search(
|
|
[('name', '=', line_search.room_number.name)])
|
|
for history in room_id_room_data.room_folio_ids:
|
|
if history.booking_id.id == line_search.line_id.id and line_obj.checkin_date == history.check_in and line_obj.checkout_date == history.check_out:
|
|
history.unlink()
|
|
# product_name = self.env['product.product'].search([('id', '=', vals['product_id'])])
|
|
room_name = self.env['hotel.room'].search(
|
|
[('product_id', '=', vals['product_id'])])
|
|
|
|
value_history = {
|
|
|
|
'partner_id': line_search.line_id.partner_id.id,
|
|
'history_id': room_name.id,
|
|
'booking_id': line_search.line_id.id,
|
|
'state': 'done',
|
|
'category_id': room_name.categ_id.id, # room_line_id.categ_id.id,
|
|
'name': room_name.name,
|
|
}
|
|
if 'check_in' in vals:
|
|
value_history.update(
|
|
{'check_in': vals['check_in']})
|
|
value_history.update(
|
|
{'check_in_date': vals['check_in']})
|
|
|
|
else:
|
|
value_history.update(
|
|
{'check_in': line_obj.checkin_date})
|
|
value_history.update(
|
|
{'check_in_date': line_obj.checkin_date})
|
|
|
|
if 'checkout_date' in vals:
|
|
value_history.update(
|
|
{'check_out': vals['checkout_date']})
|
|
value_history.update(
|
|
{'check_out_date': vals['checkout_date']})
|
|
|
|
else:
|
|
value_history.update(
|
|
{'check_out': line_obj.checkout_date})
|
|
value_history.update(
|
|
{'check_out_date': line_obj.checkout_date})
|
|
|
|
if 'product_id' in vals:
|
|
value_history.update(
|
|
{'product_id': vals['product_id']})
|
|
|
|
else:
|
|
value_history.update(
|
|
{'product_id': line_obj.product_id.id})
|
|
room_his_id = self.env['hotel.room.booking.history'].create(
|
|
value_history)
|
|
|
|
room_name_K = self.env['hotel.room'].search(
|
|
[('product_id', '=', line_search.room_number.id)])
|
|
|
|
for history_k in room_name_K.room_folio_ids:
|
|
if history_k.booking_id.id == line_search.line_id.id and line_obj.checkin_date == history_k.check_in and line_obj.checkout_date == history_k.check_out:
|
|
|
|
if 'checkout_date' in vals:
|
|
|
|
if history_k:
|
|
history_k.write(
|
|
{'check_out': vals['checkout_date']})
|
|
history_k.write(
|
|
{'check_out_date': vals['checkout_date']})
|
|
|
|
if 'checkin_date' in vals:
|
|
|
|
if history_k:
|
|
history_k.write({'check_in': vals['checkin_date']})
|
|
history_k.write(
|
|
{'check_in_date': vals['checkin_date']})
|
|
|
|
if line_search:
|
|
|
|
if 'checkout_date' in vals:
|
|
line_search.write({
|
|
|
|
'checkout': vals['checkout_date']})
|
|
|
|
if 'checkin_date' in vals:
|
|
line_search.write({
|
|
|
|
'checkin': vals['checkin_date']})
|
|
|
|
if 'categ_id' in vals:
|
|
line_search.write({
|
|
|
|
'categ_id': vals['categ_id']})
|
|
|
|
if 'product_id' in vals:
|
|
line_search.write({
|
|
|
|
'room_number': vals['product_id']})
|
|
|
|
if 'discount' in vals:
|
|
line_search.write({
|
|
'discount': vals['discount']})
|
|
|
|
if 'price_unit' in vals:
|
|
line_search.write({
|
|
'sub_total1': vals['price_unit'],
|
|
'price': vals['price_unit']
|
|
})
|
|
if 'product_uom_qty' in vals:
|
|
line_search.write({
|
|
'number_of_days': vals['product_uom_qty']})
|
|
line_search.count_price()
|
|
|
|
if not 'price_unit' in vals:
|
|
vals.update({
|
|
'price_unit': line_obj.price_unit
|
|
})
|
|
return super(hotel_folio_line, self).write(vals)
|
|
|
|
@api.onchange('checkout_date', 'checkin_date')
|
|
@api.depends('checkin_date', 'checkout_date', 'product_id', 'folio_id.shop_id')
|
|
def on_change_checkout(self):
|
|
|
|
product_uom_id = ""
|
|
if self.checkout_date and self.checkin_date > self.checkout_date:
|
|
return {'warning': {'title': "Error", 'message': "Departure date must be greater than Arrival Date"}, }
|
|
if self.checkin_date and self.checkout_date:
|
|
print('---------self: ', self)
|
|
print('---------self.folio_id: ', self.folio_id)
|
|
print('---------self.folio_id.name: ', self.folio_id.name)
|
|
print('---------self.folio_id.shop_id: ', self.folio_id.shop_id)
|
|
policy_obj = self.env['checkout.configuration'].search(
|
|
[('shop_id', '=', self.folio_id.shop_id.id)])
|
|
if not policy_obj:
|
|
raise UserError(
|
|
'Configuration Error! Checkout policy is not define.')
|
|
check_in = self.checkin_date
|
|
|
|
check_out = self.checkout_date
|
|
|
|
day_count1 = (check_out - check_in).days
|
|
if not policy_obj.name == '24hour':
|
|
check_in = self.checkin_date
|
|
|
|
check_out = self.checkout_date
|
|
_logger.info("DAY COUNT====>>>>%s", check_in)
|
|
_logger.info("DAY COUNT====>>>>%s", check_out)
|
|
day_count1 = check_out - check_in
|
|
|
|
day_count2 = day_count1.total_seconds()
|
|
|
|
day_count2 = day_count2 / 86400
|
|
day_count2 = "{:.2f}".format(day_count2)
|
|
_logger.info("DIFFERENCE==>>>>>>>>>{}".format(day_count2))
|
|
day_count2 = math.ceil(float(day_count2))
|
|
|
|
_logger.info("DAY COUNT22===>>>>>>>>>>>>>>>>{}".format(day_count2))
|
|
|
|
day_count1 = day_count2
|
|
|
|
else:
|
|
check_in = self.checkin_date
|
|
check_out = self.checkout_date
|
|
_logger.info("CHECK IN ===>>>>>>>>>>>>>>>{}".format(check_in))
|
|
_logger.info("CHECK OUT===>>>>>>>>>>>>{}".format(check_out))
|
|
|
|
day_count1 = check_out - check_in
|
|
|
|
day_count2 = day_count1.total_seconds()
|
|
day_count2 = day_count2 / 86400
|
|
day_count2 = "{:.2f}".format(day_count2)
|
|
|
|
_logger.info("DIFFERENCE==>>>>>>>>>{}".format(day_count2))
|
|
day_count2 = math.ceil(float(day_count2))
|
|
|
|
day_count1 = day_count2
|
|
self.product_uom_qty = day_count1 if day_count1 else 1
|
|
|
|
|
|
class hotel_service_line(models.Model):
|
|
_name = 'hotel_service.line'
|
|
_description = 'hotel Service line'
|
|
_inherits = {'sale.order.line': 'service_line_id'}
|
|
|
|
service_line_id = fields.Many2one(
|
|
'sale.order.line', string='service_line_id', required=True, ondelete='cascade')
|
|
folio_id = fields.Many2one('hotel.folio', string='Folio', ondelete='cascade')
|
|
|
|
# @api.multi
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.service_line_id.unlink()
|
|
return super(hotel_service_line, self).unlink()
|
|
|
|
@api.model_create_multi
|
|
def create(self, vals):
|
|
if not self._context:
|
|
self._context = {}
|
|
for line in vals:
|
|
if line.get("folio_id"):
|
|
folio = self.env["hotel.folio"].browse([line['folio_id']])[0]
|
|
line.update({'order_id': folio.order_id.id})
|
|
roomline = super(hotel_service_line, self).create(vals)
|
|
return roomline
|
|
|
|
@api.onchange('folio_id')
|
|
def on_change_checkout(self):
|
|
qty = 1
|
|
for i in self.folio_id.room_lines:
|
|
checkout_date = str(i.checkout_date)
|
|
checkin_date = str(i.checkin_date)
|
|
break
|
|
if checkout_date < checkin_date:
|
|
raise ValidationError(
|
|
'Error !', 'Checkout must be greater or equal checkin date')
|
|
if checkin_date:
|
|
diffDate = datetime.datetime(*time.strptime(checkout_date, '%Y-%m-%d %H:%M:%S')[
|
|
:5]) - datetime.datetime(
|
|
*time.strptime(checkin_date, '%Y-%m-%d %H:%M:%S')[:5])
|
|
qty = diffDate.days
|
|
return {'value': {'product_uom_qty': qty}}
|
|
|
|
# @api.onchange('product_id')
|
|
# def product_id_change(self):
|
|
# _logger.info('------------- onchange_product_id: 2')
|
|
# if self.product_id:
|
|
# self.product_uom = self.product_id.uom_id
|
|
# self.price_unit = self.product_id.lst_price
|
|
# self.name = self.product_id.description_sale
|
|
|
|
|
|
class hotel_service_type(models.Model):
|
|
_name = "hotel.service_type"
|
|
_inherits = {'product.category': 'ser_id'}
|
|
_description = "Service Type"
|
|
|
|
ser_id = fields.Many2one('product.category', string='Category',
|
|
required=True, index=True, ondelete="cascade")
|
|
isservicetype = fields.Boolean(
|
|
'Is Service Type', related='ser_id.isservicetype', inherited=True, default=True)
|
|
company_id = fields.Many2one('res.company', string='Company',
|
|
domain="[('id', 'in', [current_company_id])]",
|
|
required=True)
|
|
|
|
# @api.multi
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.ser_id.unlink()
|
|
return super(hotel_service_type, self).unlink()
|
|
|
|
|
|
class hotel_services(models.Model):
|
|
_name = 'hotel.services'
|
|
_description = 'Hotel Services and its charges'
|
|
_inherits = {'product.product': 'service_id'}
|
|
_inherit = ['mail.thread']
|
|
|
|
service_id = fields.Many2one(
|
|
'product.product', string='Service Id', required=True, ondelete='cascade')
|
|
isservice = fields.Boolean(
|
|
'Is Service', related='service_id.isservice', inherited=True, default=True)
|
|
|
|
def action_open_documents(self):
|
|
self.service_id.product_tmpl_id.action_open_documents()
|
|
|
|
@api.onchange('shop_id')
|
|
def on_change_shop_id(self):
|
|
if not self.shop_id:
|
|
return {'value': {}}
|
|
temp = self.shop_id
|
|
self.company_id = temp.company_id.id
|
|
|
|
def action_compute_bom_days(self):
|
|
return True
|
|
|
|
def open_pricelist_rules(self):
|
|
self.ensure_one()
|
|
domain = ['|',
|
|
('product_tmpl_id', '=', self.id),
|
|
('product_id', 'in', self.product_variant_ids.ids)]
|
|
return {
|
|
'name': ('Price Rules'),
|
|
'view_mode': 'tree,form',
|
|
'views': [(self.env.ref('product.product_pricelist_item_tree_view_from_product').id, 'tree'),
|
|
(False, 'form')],
|
|
'res_model': 'product.pricelist.item',
|
|
'type': 'ir.actions.act_window',
|
|
'target': 'current',
|
|
'domain': domain,
|
|
'context': {
|
|
'default_product_tmpl_id': self.id,
|
|
'default_applied_on': '1_product',
|
|
'product_without_variants': self.product_variant_count == 1,
|
|
},
|
|
}
|
|
|
|
@api.onchange('type')
|
|
def onchange_type(self):
|
|
res = {}
|
|
if self.type in ('consu', 'service'):
|
|
res = {'value': {'valuation': 'manual_periodic'}}
|
|
return res
|
|
|
|
@api.onchange('tracking')
|
|
def onchange_tracking(self):
|
|
if not self.tracking:
|
|
return {}
|
|
product_product = self.env['product.product']
|
|
variant_ids = product_product.search(
|
|
[('product_tmpl_id', 'in', self._ids)])
|
|
for variant_id in variant_ids:
|
|
variant_id.onchange_tracking()
|
|
|
|
# @api.multi
|
|
|
|
def unlink(self):
|
|
for categ in self:
|
|
categ.service_id.unlink()
|
|
return super(hotel_services, self).unlink()
|
|
|
|
# @api.multi
|
|
|
|
def read_followers_data(self):
|
|
result = []
|
|
technical_group = self.env['ir.model.data'].get_object(
|
|
'base', 'group_no_one', context=self._context)
|
|
for follower in self.env['res.partner'].browse(self._ids):
|
|
is_editable = self.uid in map(
|
|
lambda x: x.id, technical_group.users)
|
|
is_uid = self.uid in map(lambda x: x.id, follower.user_ids)
|
|
data = (follower.id,
|
|
follower.name,
|
|
{'is_editable': is_editable, 'is_uid': is_uid},
|
|
)
|
|
result.append(data)
|
|
return result
|
|
|
|
def message_get_subscription_data(self, user_pid=None):
|
|
""" Wrapper to get subtypes data. """
|
|
return self.env['mail.thread']._get_subscription_data(None, None, user_pid=user_pid)
|
|
|
|
def action_open_label_layout(self):
|
|
action = self.env['ir.actions.act_window']._for_xml_id('product.action_open_label_layout')
|
|
action['context'] = {'default_product_tmpl_ids': self.ids}
|
|
return action
|
|
|
|
|
|
class sale_order_line(models.Model):
|
|
_inherit = 'sale.order.line'
|
|
_description = 'Inherit Order Line'
|
|
|
|
product_uom_qty = fields.Float(
|
|
'Quantity', default=1.00, digits='Product Unit of Measure', required=True)
|
|
|
|
@api.model
|
|
def write(self, values):
|
|
if 'display_type' in values and self.filtered(lambda line: line.display_type != values.get('display_type')):
|
|
raise UserError(
|
|
_("You cannot change the type of a sale order line. Instead you should delete the current line and create a new line of the proper type."))
|
|
|
|
if 'product_uom_qty' in values:
|
|
precision = self.env['decimal.precision'].precision_get(
|
|
'Product Unit of Measure')
|
|
self.filtered(
|
|
lambda r: r.state == 'sale' and float_compare(r.product_uom_qty, values['product_uom_qty'],
|
|
precision_digits=precision) != 0)._update_line_quantity(
|
|
values)
|
|
|
|
# Prevent writing on a locked SO.
|
|
protected_fields = self._get_protected_fields()
|
|
|
|
res = super(sale_order_line, self).write(values)
|
|
|
|
return res
|