diff --git a/salon_management/__init__.py b/salon_management/__init__.py
new file mode 100644
index 000000000..2c4eac3f8
--- /dev/null
+++ b/salon_management/__init__.py
@@ -0,0 +1 @@
+import models
\ No newline at end of file
diff --git a/salon_management/__openerp__.py b/salon_management/__openerp__.py
new file mode 100644
index 000000000..b6a3fac87
--- /dev/null
+++ b/salon_management/__openerp__.py
@@ -0,0 +1,49 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2009-TODAY Cybrosys Technologies().
+# Author: Avinash Nk()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+{
+ 'name': 'Beauty Spa Management',
+ 'summary': """Beauty Parlour Management with Online Booking System""",
+ 'version': '0.1',
+ 'author': 'Cybrosys Techno Solutions',
+ 'website': "http://www.cybrosys.com",
+ 'company': 'Cybrosys Techno Solutions',
+ "category": "Tools",
+ 'depends': ['base', 'account', 'mail', 'website'],
+ 'data': ['views/salon_holiday.xml',
+ 'views/salon_data.xml',
+ 'views/salon_management_chair.xml',
+ 'views/salon_management_services.xml',
+ 'views/salon_order_view.xml',
+ 'views/salon_management_dashboard.xml',
+ 'views/booking_backend.xml',
+ 'views/salon_bookings.xml',
+ 'views/salon_email_template.xml',
+ 'views/salon_config.xml',
+ 'views/working_hours.xml',
+ 'security/ir.model.access.csv',
+ ],
+ 'images': ['static/description/banner.jpg'],
+ 'license': 'AGPL-3',
+ 'installable': True,
+ 'application': True,
+}
\ No newline at end of file
diff --git a/salon_management/models/__init__.py b/salon_management/models/__init__.py
new file mode 100644
index 000000000..4b79cf330
--- /dev/null
+++ b/salon_management/models/__init__.py
@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2009-TODAY Cybrosys Technologies().
+# Author: Avinash Nk()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+import salon_management
+import salon_booking
+import salon_config
+
diff --git a/salon_management/models/salon_booking.py b/salon_management/models/salon_booking.py
new file mode 100644
index 000000000..da3cde90a
--- /dev/null
+++ b/salon_management/models/salon_booking.py
@@ -0,0 +1,141 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2009-TODAY Cybrosys Technologies().
+# Author: Avinash Nk()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+from openerp.addons.web import http
+from openerp import models, fields, _, SUPERUSER_ID, api
+from openerp.addons.web.http import request
+from datetime import datetime, date
+
+
+class SalonBookingBackend(models.Model):
+
+ _name = 'salon.booking'
+
+ name = fields.Char(string="Name")
+ state = fields.Selection([('draft', 'Draft'), ('approved', 'Approved'), ('rejected', 'Rejected')], default="draft")
+ time = fields.Datetime(string="Date")
+ phone = fields.Char(string="Phone")
+ email = fields.Char(string="E-Mail")
+ services = fields.Many2many('salon.service', string="Services")
+ chair_id = fields.Many2one('salon.chair', string="Chair")
+ company_id = fields.Many2one('res.company', 'Company',
+ default=lambda self: self.env['res.company'].browse(1))
+ lang = fields.Many2one('res.lang', 'Language',
+ default=lambda self: self.env['res.lang'].browse(1))
+
+ def all_salon_orders(self):
+ if self.time:
+ date_only = str(self.time)[0:10]
+ else:
+ date_only = date.today()
+ all_salon_service_obj = self.env['salon.order'].search([('chair_id', '=', self.chair_id.id),
+ ('start_date_only', '=', date_only)])
+ self.filtered_orders = [(6, 0, [x.id for x in all_salon_service_obj])]
+
+ filtered_orders = fields.Many2many('salon.order', string="Salon Orders", compute="all_salon_orders")
+
+ @api.multi
+ def booking_approve(self):
+ salon_order_obj = self.env['salon.order']
+ salon_service_obj = self.env['salon.order.lines']
+ order_data ={
+ 'customer_name': self.name,
+ 'chair_id': self.chair_id.id,
+ 'start_time': self.time,
+ 'date': date.today(),
+ 'stage_id': 1,
+ 'booking_identifier': True,
+ }
+ order = salon_order_obj.create(order_data)
+ for records in self.services:
+ service_data = {
+ 'service_id': records.id,
+ 'time_taken': records.time_taken,
+ 'price': records.price,
+ 'price_subtotal': records.price,
+ 'salon_order': order.id,
+ }
+ salon_service_obj.create(service_data)
+ template = self.env.ref('salon_management.salon_email_template_approved')
+ self.env['mail.template'].browse(template.id).send_mail(self.id)
+ self.state = "approved"
+
+ @api.multi
+ def booking_reject(self):
+ template = self.env.ref('salon_management.salon_email_template_rejected')
+ self.env['mail.template'].browse(template.id).send_mail(self.id)
+ self.state = "rejected"
+
+
+class SalonBookingWeb(http.Controller):
+
+ @http.route('/page/salon_details', type='json', auth="public", website=True)
+ def salon_details(self, **kwargs):
+ booking_info = kwargs.get('salon_data')
+ name = booking_info[0]
+ date = booking_info[1]
+ phone = booking_info[2]
+ email = booking_info[3]
+ services = booking_info[4]
+ chair = booking_info[5]
+ salon_service_obj = request.env['salon.service'].search([('id', 'in', services)])
+ date = str(date)
+ dates = date[0:10]
+ time = date[11:16]
+ dates_time = dates+" "+time+":00"
+ date_and_time = datetime.strptime(dates_time, '%Y-%m-%d %H:%M:%S')
+ salon_booking = request.registry['salon.booking']
+ booking_data = {
+ 'name': name,
+ 'phone': phone,
+ 'time': date_and_time,
+ 'email': email,
+ 'chair_id': chair,
+ 'services': [(6, 0, [x.id for x in salon_service_obj])],
+ }
+ salon_booking.create(request.cr, SUPERUSER_ID, booking_data, context=request.context)
+ return
+
+ @http.route('/page/salon_check_date', type='json', auth="public", website=True)
+ def salon_check(self, **kwargs):
+ date_info = kwargs.get('check_date')
+ return date_info
+
+ @http.route('/page/salon_management.salon_booking_form', type='http', auth="public", website=True)
+ def chair_info(self, **post):
+
+ salon_service_obj = request.env['salon.service'].search([])
+ salon_working_hours_obj = request.env['salon.working.hours'].search([])
+ salon_holiday_obj = request.env['salon.holiday'].search([('holiday', '=', True)])
+ date_check = date.today()
+ if 'x' in post.keys():
+ date_check = post['x']
+ chair_obj = request.env['salon.chair'].search([('active_booking_chairs', '=', True)])
+ order_obj = request.env['salon.order'].search([('chair_id.active_booking_chairs', '=', True),
+ ('stage_id', 'in', [1, 2, 3])])
+ date_check = str(date_check)
+ order_obj = order_obj.search([('start_date_only', '=', date_check)])
+ return request.website.render('salon_management.salon_booking_form',
+ {'chair_details': chair_obj, 'order_details': order_obj,
+ 'salon_services': salon_service_obj, 'date_search': date_check,
+ 'holiday': salon_holiday_obj,
+ 'working_time': salon_working_hours_obj})
\ No newline at end of file
diff --git a/salon_management/models/salon_config.py b/salon_management/models/salon_config.py
new file mode 100644
index 000000000..c1fde5cb8
--- /dev/null
+++ b/salon_management/models/salon_config.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2009-TODAY Cybrosys Technologies().
+# Author: Avinash Nk()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+from openerp import models, fields, api
+
+
+class SalonWorkingHours(models.Model):
+ _name = 'salon.working.hours'
+ name = fields.Char(string="Name")
+ from_time = fields.Float(string="Starting Time")
+ to_time = fields.Float(string="Closing Time")
+
+
+class SalonHoliday(models.Model):
+ _name = 'salon.holiday'
+ name = fields.Char(string="Name")
+ holiday = fields.Boolean(string="Holiday")
+
+
+class WorkshopSetting(models.Model):
+
+ _name = "salon.config.settings"
+
+ @api.model
+ def booking_chairs(self):
+ return self.env['salon.chair'].search([('active_booking_chairs', '=', True)])
+
+ @api.model
+ def holidays(self):
+ return self.env['salon.holiday'].search([('holiday', '=', True)])
+
+ salon_booking_chairs = fields.Many2many('salon.chair', string="Booking Chairs", default=booking_chairs)
+ salon_holidays = fields.Many2many('salon.holiday', string="Holidays", default=holidays)
+
+ @api.multi
+ def execute(self):
+ salon_chair_obj = self.env['salon.chair'].search([])
+ book_chair = []
+ for chairs in self.salon_booking_chairs:
+ book_chair.append(chairs.id)
+ for records in salon_chair_obj:
+ if records.id in book_chair:
+ records.active_booking_chairs = True
+ else:
+ records.active_booking_chairs = False
+
+ salon_holiday_obj = self.env['salon.holiday'].search([])
+ holiday = []
+ for days in self.salon_holidays:
+ holiday.append(days.id)
+ for records in salon_holiday_obj:
+ if records.id in holiday:
+ records.holiday = True
+ else:
+ records.holiday = False
diff --git a/salon_management/models/salon_management.py b/salon_management/models/salon_management.py
new file mode 100644
index 000000000..21055b1fc
--- /dev/null
+++ b/salon_management/models/salon_management.py
@@ -0,0 +1,426 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+# Cybrosys Technologies Pvt. Ltd.
+# Copyright (C) 2009-TODAY Cybrosys Technologies().
+# Author: Avinash Nk()
+# you can modify it under the terms of the GNU LESSER
+# GENERAL PUBLIC LICENSE (LGPL v3), Version 3.
+#
+# It is forbidden to publish, distribute, sublicense, or sell copies
+# of the Software or modified copies of the Software.
+#
+# 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 LESSER GENERAL PUBLIC LICENSE (LGPL v3) for more details.
+#
+# You should have received a copy of the GNU LESSER GENERAL PUBLIC LICENSE
+# GENERAL PUBLIC LICENSE (LGPL v3) along with this program.
+# If not, see .
+#
+##############################################################################
+from openerp import models, fields, api
+from datetime import date, datetime, timedelta
+from openerp.tools.translate import _
+from openerp.exceptions import UserError, ValidationError
+
+
+class PartnerSalon(models.Model):
+
+ _inherit = 'res.partner'
+
+ partner_salon = fields.Boolean(string="Is a Salon Partner")
+
+
+class CompanySalon(models.Model):
+
+ _inherit = 'res.company'
+
+ sequence_salon = fields.Char(string="Salon Sequence")
+
+
+class UserSalon(models.Model):
+
+ _inherit = 'res.users'
+
+ user_salon_active = fields.Boolean(string="Active Salon Users")
+
+
+class SalonChair(models.Model):
+
+ _name = 'salon.chair'
+ name = fields.Char(string="Chair", required=True,
+ default=lambda self: self.env['res.company'].browse(1).sequence_salon or "Chair-1")
+ number_of_orders = fields.Integer(string="No.of Orders")
+ collection_today = fields.Float(string="Today's Collection")
+ user_of_chair = fields.Many2one('res.users', string="User", readonly=True,
+ help="You can select the user from the Users Tab."
+ "Last user from the Users Tab will be selected as the Current User.")
+ date = fields.Datetime(string="Date", readonly=True)
+ user_line = fields.One2many('salon.chair.user', 'salon_chair', string="Users")
+ total_time_taken_chair = fields.Float(string="Time Reserved(Hrs)")
+ active_booking_chairs = fields.Boolean(string="Active booking chairs")
+
+ @api.model
+ def create(self, cr):
+ sequence_code = 'chair.sequence'
+ sequence_number = self.env['ir.sequence'].next_by_code(sequence_code)
+ self.env['res.company'].browse(1).write({'sequence_salon': sequence_number})
+ if 'user_line' in cr.keys():
+ if cr['user_line']:
+ date_changer = []
+ for elements in cr['user_line']:
+ date_changer.append(elements[2]['start_date'])
+ number = 0
+ for elements in cr['user_line']:
+ number += 1
+ if len(cr['user_line']) == number:
+ break
+ elements[2]['end_date'] = date_changer[number]
+ cr['user_of_chair'] = cr['user_line'][len((cr['user_line']))-1][2]['user_id']
+ cr['date'] = cr['user_line'][len((cr['user_line']))-1][2]['start_date']
+ return super(SalonChair, self).create(cr)
+
+ @api.multi
+ def write(self, cr):
+ if 'user_line' in cr.keys():
+ if cr['user_line']:
+ date_changer = []
+ for elements in cr['user_line']:
+ if elements[1] is False:
+ date_changer.append(elements[2]['start_date'])
+ number = 0
+ num = 0
+ for records in self.user_line:
+ if records.end_date is False:
+ records.end_date = date_changer[0]
+ for elements in cr['user_line']:
+ number += 1
+ if elements[2] is not False:
+ num += 1
+ if len(cr['user_line']) == number:
+ break
+ elements[2]['end_date'] = date_changer[num]
+ cr['user_of_chair'] = cr['user_line'][len((cr['user_line']))-1][2]['user_id']
+ cr['date'] = cr['user_line'][len((cr['user_line']))-1][2]['start_date']
+ return super(SalonChair, self).write(cr)
+
+ def collection_today_updater(self, cr, uid, context=None):
+ salon_chair = self.pool.get('salon.chair')
+ for values in self.search(cr, uid, []):
+ chair_obj = salon_chair.browse(cr, uid, values, context=context)
+ invoiced_records = chair_obj.env['salon.order'].search([('stage_id', 'in', [3, 4]),
+ ('chair_id', '=', chair_obj.id)])
+ total = 0
+ for rows in invoiced_records:
+ invoiced_date = rows.date
+ invoiced_date = invoiced_date[0:10]
+ if invoiced_date == str(date.today()):
+ total = total + rows.price_subtotal
+ chair_obj.collection_today = total
+
+
+class SalonChairUserLines(models.Model):
+
+ _name = 'salon.chair.user'
+
+ read_only_checker = fields.Boolean(string="Checker", default=False)
+ user_id = fields.Many2one('res.users', string="User", required=True)
+ start_date = fields.Datetime(string="Start Date", default=date.today(), required=True)
+ end_date = fields.Datetime(string="End Date", readonly=True, default=False)
+ salon_chair = fields.Many2one('salon.chair', string="Chair", required=True, ondelete='cascade',
+ index=True, copy=False)
+
+ @api.model
+ def create(self, cr):
+ chairs = self.env['salon.chair'].search([])
+ all_active_users = []
+ for records in chairs:
+ if records.user_of_chair:
+ all_active_users.append(records.user_of_chair.id)
+ records.user_of_chair.write({'user_salon_active': True})
+ users = self.env['res.users'].search([('id', 'not in', all_active_users)])
+ for records in users:
+ records.write({'user_salon_active': False})
+ cr['read_only_checker'] = True
+ return super(SalonChairUserLines, self).create(cr)
+
+
+class SalonOrder(models.Model):
+
+ _name = 'salon.order'
+
+ @api.depends('order_line.price_subtotal')
+ def sub_total_update(self):
+ for order in self:
+ amount_untaxed = 0.0
+ for line in order.order_line:
+ amount_untaxed += line.price_subtotal
+ order.price_subtotal = amount_untaxed
+ for order in self:
+ total_time_taken = 0.0
+ for line in order.order_line:
+ total_time_taken += line.time_taken
+ order.time_taken_total = total_time_taken
+ time_takes = total_time_taken
+ hours = int(time_takes)
+ minutes = 0.0
+ if time_takes != 0:
+ minutes = (time_takes % int(time_takes))*60
+ start_time_store = datetime.strptime(self.start_time, "%Y-%m-%d %H:%M:%S")
+ self.write({'end_time': start_time_store + timedelta(hours=hours, minutes=minutes)})
+ if self.end_time:
+ self.write({'end_time_only': str(self.end_time)[11:16]})
+ if self.start_time:
+ salon_start_time = self.start_time
+ salon_start_time_date = salon_start_time[0:10]
+ self.write({'start_date_only': salon_start_time_date})
+ self.write({'start_time_only': str(self.start_time)[11:16]})
+
+ name = fields.Char(string='Salon', required=True, copy=False, readonly=True,
+ default='Draft Salon Order')
+ start_time = fields.Datetime(string="Start time", default=date.today(), required=True)
+ end_time = fields.Datetime(string="End time")
+ date = fields.Datetime(string="Date", required=True, default=date.today())
+ color = fields.Integer(string="Colour", default=6)
+ partner_id = fields.Many2one('res.partner', string="Customer", required=False,
+ help="If the customer is a regular customer, "
+ "then you can add the customer in your database")
+ customer_name = fields.Char(string="Name", required=True)
+ amount = fields.Float(string="Amount")
+ chair_id = fields.Many2one('salon.chair', string="Chair", required=True)
+ price_subtotal = fields.Float(string='Total', compute='sub_total_update', readonly=True, store=True)
+ time_taken_total = fields.Float(string="Total time taken")
+ note = fields.Text('Terms and conditions')
+ order_line = fields.One2many('salon.order.lines', 'salon_order', string="Order Lines")
+ stage_id = fields.Many2one('salon.stages', string="Stages", default=1)
+ inv_stage_identifier = fields.Boolean(string="Stage Identifier")
+ invoice_number = fields.Integer(string="Invoice Number")
+ validation_controller = fields.Boolean(string="Validation controller", default=False)
+ start_date_only = fields.Date(string="Date Only")
+ booking_identifier = fields.Boolean(string="Booking Identifier")
+ start_time_only = fields.Char(string="Start Time Only")
+ end_time_only = fields.Char(string="End Time Only")
+
+ @api.onchange('start_time')
+ def start_date_change(self):
+ salon_start_time = self.start_time
+ salon_start_time_date = salon_start_time[0:10]
+ self.write({'start_date_only': salon_start_time_date})
+
+ @api.multi
+ def action_view_invoice_salon(self):
+ imd = self.env['ir.model.data']
+ action = imd.xmlid_to_object('account.action_invoice_tree1')
+ list_view_id = imd.xmlid_to_res_id('account.invoice_tree')
+ form_view_id = imd.xmlid_to_res_id('account.invoice_form')
+ result = {
+ 'name': action.name,
+ 'help': action.help,
+ 'type': action.type,
+ 'views': [[form_view_id, 'form'], [list_view_id, 'tree'], [False, 'graph'], [False, 'kanban'],
+ [False, 'calendar'], [False, 'pivot']],
+ 'target': action.target,
+ 'context': action.context,
+ 'res_model': action.res_model,
+ 'res_id': self.invoice_number,
+ }
+ return result
+
+ @api.multi
+ def write(self, cr):
+
+ self.chair_id.number_of_orders = len(self.env['salon.order'].search([("chair_id", "=", self.chair_id.id),
+ ("stage_id", "in", [2, 3])]))
+ if 'stage_id' in cr.keys():
+ if self.stage_id.id == 3 and cr['stage_id'] != 4:
+ raise ValidationError(_("You can't perform that move !"))
+ if self.stage_id.id == 1 and cr['stage_id'] not in [2, 5]:
+ raise ValidationError(_("You can't perform that move!"))
+ if self.stage_id.id == 4:
+ raise ValidationError(_("You can't move a salon order from closed stage !"))
+ if self.stage_id.id == 5:
+ raise ValidationError(_("You can't move a salon order from cancel stage !"))
+ if self.stage_id.id == 2 and (cr['stage_id'] == 1 or cr['stage_id'] == 4):
+ raise ValidationError(_("You can't perform that move !"))
+ if self.stage_id.id == 2 and cr['stage_id'] == 3 and self.inv_stage_identifier is False:
+ self.salon_invoice_create()
+ if 'stage_id' in cr.keys() and self.name == "Draft Salon Order":
+ if cr['stage_id'] == 2:
+ self.salon_confirm()
+ return super(SalonOrder, self).write(cr)
+
+ @api.multi
+ def salon_confirm(self):
+ sequence_code = 'salon.order.sequence'
+ order_date = self.date
+ order_date = order_date[0:10]
+ self.name = self.env['ir.sequence'].with_context(ir_sequence_date=order_date).next_by_code(sequence_code)
+ if self.partner_id:
+ self.partner_id.partner_salon = True
+ self.stage_id = 2
+ self.chair_id.number_of_orders = len(self.env['salon.order'].search([("chair_id", "=", self.chair_id.id),
+ ("stage_id", "in", [2, 3])]))
+ self.chair_id.total_time_taken_chair = self.chair_id.total_time_taken_chair + self.time_taken_total
+
+ @api.multi
+ def salon_validate(self):
+ self.validation_controller = True
+
+ @api.multi
+ def salon_close(self):
+ self.stage_id = 4
+ self.chair_id.number_of_orders = len(self.env['salon.order'].search([("chair_id", "=", self.chair_id.id),
+ ("stage_id", "in", [2, 3])]))
+ self.chair_id.total_time_taken_chair = self.chair_id.total_time_taken_chair - self.time_taken_total
+
+ @api.multi
+ def salon_cancel(self):
+ self.stage_id = 5
+ self.chair_id.number_of_orders = len(self.env['salon.order'].search([("chair_id", "=", self.chair_id.id),
+ ("stage_id", "in", [2, 3])]))
+ if self.stage_id.id != 1:
+ self.chair_id.total_time_taken_chair = self.chair_id.total_time_taken_chair - self.time_taken_total
+
+ @api.multi
+ def button_total_update(self):
+ for order in self:
+ amount_untaxed = 0.0
+ for line in order.order_line:
+ amount_untaxed += line.price_subtotal
+ order.price_subtotal = amount_untaxed
+
+ @api.onchange('chair_id')
+ def onchange_chair(self):
+ if 'active_id' in self._context.keys():
+ self.chair_id = self._context['active_id']
+
+ @api.multi
+ def salon_invoice_create(self):
+ inv_obj = self.env['account.invoice']
+ inv_line_obj = self.env['account.invoice.line']
+ if self.partner_id:
+ supplier = self.partner_id
+ else:
+ supplier = self.partner_id.search([("name", "=", "Salon Default Customer")])
+ company_id = self.env['res.users'].browse(1).company_id
+ currency_salon = company_id.currency_id.id
+
+ inv_data = {
+ 'name': supplier.name,
+ 'reference': supplier.name,
+ 'account_id': supplier.property_account_payable_id.id,
+ 'partner_id': supplier.id,
+ 'currency_id': currency_salon,
+ 'journal_id': 1,
+ 'origin': self.name,
+ 'company_id': company_id.id,
+ }
+ inv_id = inv_obj.create(inv_data)
+ self.invoice_number = inv_id
+ product_id = self.env['product.product'].search([("name", "=", "Salon Service")])
+ for records in self.order_line:
+ if product_id.property_account_income_id.id:
+ income_account = product_id.property_account_income_id.id
+ elif product_id.categ_id.property_account_income_categ_id.id:
+ income_account = product_id.categ_id.property_account_income_categ_id.id
+ else:
+ raise UserError(_('Please define income account for this product: "%s" (id:%d).') % (product_id.name,
+ product_id.id))
+
+ inv_line_data = {
+ 'name': records.service_id.name,
+ 'account_id': income_account,
+ 'price_unit': records.price,
+ 'quantity': 1,
+ 'product_id': product_id.id,
+ 'invoice_id': inv_id.id,
+ }
+ inv_line_obj.create(inv_line_data)
+
+ imd = self.env['ir.model.data']
+ action = imd.xmlid_to_object('account.action_invoice_tree1')
+ list_view_id = imd.xmlid_to_res_id('account.invoice_tree')
+ form_view_id = imd.xmlid_to_res_id('account.invoice_form')
+
+ result = {
+ 'name': action.name,
+ 'help': action.help,
+ 'type': 'ir.actions.act_window',
+ 'views': [[list_view_id, 'tree'], [form_view_id, 'form'], [False, 'graph'], [False, 'kanban'],
+ [False, 'calendar'], [False, 'pivot']],
+ 'target': action.target,
+ 'context': action.context,
+ 'res_model': 'account.invoice',
+ }
+ if len(inv_id) > 1:
+ result['domain'] = "[('id','in',%s)]" % inv_id.ids
+ elif len(inv_id) == 1:
+ result['views'] = [(form_view_id, 'form')]
+ result['res_id'] = inv_id.ids[0]
+ else:
+ result = {'type': 'ir.actions.act_window_close'}
+ self.inv_stage_identifier = True
+ self.stage_id = 3
+ invoiced_records = self.env['salon.order'].search([('stage_id', 'in', [3, 4]),
+ ('chair_id', '=', self.chair_id.id)])
+ total = 0
+ for rows in invoiced_records:
+ invoiced_date = rows.date
+ invoiced_date = invoiced_date[0:10]
+ if invoiced_date == str(date.today()):
+ total = total + rows.price_subtotal
+ self.chair_id.collection_today = total
+ self.chair_id.number_of_orders = len(self.env['salon.order'].search([("chair_id", "=", self.chair_id.id),
+ ("stage_id", "in", [2, 3])]))
+ return result
+
+ @api.multi
+ def unlink(self):
+ for order in self:
+ if order.stage_id.id == 3 or order.stage_id.id == 4:
+ raise UserError(_("You can't delete an invoiced salon order!"))
+ return super(SalonOrder, self).unlink()
+
+
+class SalonServices(models.Model):
+
+ _name = 'salon.service'
+
+ name = fields.Char(string="Name")
+ price = fields.Float(string="Price")
+ time_taken = fields.Float(string="Time Taken", help="Approximate time taken for this service in Hours")
+
+
+class SalonOrderLine(models.Model):
+
+ _name = 'salon.order.lines'
+
+ service_id = fields.Many2one('salon.service', string="Service")
+ price = fields.Float(string="Price")
+ salon_order = fields.Many2one('salon.order', string="Salon Order", required=True, ondelete='cascade',
+ index=True, copy=False)
+ price_subtotal = fields.Float(string='Subtotal')
+ time_taken = fields.Float(string='Time Taken')
+
+ @api.onchange('service_id')
+ def onchange_service(self):
+ self.price = self.service_id.price
+ self.price_subtotal = self.service_id.price
+ self.time_taken = self.service_id.time_taken
+
+ @api.onchange('price')
+ def onchange_price(self):
+ self.price_subtotal = self.price
+
+ @api.onchange('price_subtotal')
+ def onchange_subtotal(self):
+ self.price = self.price_subtotal
+
+
+class SalonStages(models.Model):
+
+ _name = 'salon.stages'
+
+ name = fields.Char(string="Name", translate=True, required=True)
diff --git a/salon_management/security/ir.model.access.csv b/salon_management/security/ir.model.access.csv
new file mode 100644
index 000000000..ab56a9295
--- /dev/null
+++ b/salon_management/security/ir.model.access.csv
@@ -0,0 +1,6 @@
+id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
+view_salon_order,view.salon.order,model_salon_order,base.group_user,1,1,1,1
+view_salon_order_lines,view.salon.order.lines,model_salon_order_lines,base.group_user,1,1,1,1
+view_salon_stages,view.salon.stages,model_salon_stages,base.group_user,1,1,1,1
+view_salon_chair,view.salon.chair,model_salon_chair,base.group_user,1,1,1,1
+view_salon_service,view.salon.service,model_salon_service,base.group_user,1,1,1,1
\ No newline at end of file
diff --git a/salon_management/static/description/banner.jpg b/salon_management/static/description/banner.jpg
new file mode 100644
index 000000000..a948a4c14
Binary files /dev/null and b/salon_management/static/description/banner.jpg differ
diff --git a/salon_management/static/description/cybro_logo.png b/salon_management/static/description/cybro_logo.png
new file mode 100644
index 000000000..bb309114c
Binary files /dev/null and b/salon_management/static/description/cybro_logo.png differ
diff --git a/salon_management/static/description/icon.png b/salon_management/static/description/icon.png
new file mode 100644
index 000000000..ddb8bedeb
Binary files /dev/null and b/salon_management/static/description/icon.png differ
diff --git a/salon_management/static/description/index.html b/salon_management/static/description/index.html
new file mode 100644
index 000000000..a319b14c9
--- /dev/null
+++ b/salon_management/static/description/index.html
@@ -0,0 +1,249 @@
+
+
+
Beauty Spa Management
+ This Module is for Managing the Process's in a Spa
+ Author : Cybrosys Techno Solutions, www.cybrosys.com
+
+
+
Major Features
+
+ ☑ Online Booking Facility
+ ☑ Accounting Facility
+ ☑ Customer Notification Through Mail
+ ☑ User Interactive Dashboard
+ ☑ Customer Can view the Available chairs and order details
+ ☑ Different access levels for Users and Administrator
+ ☑ Track the chair user by date
+
+
+
+
+ This Spa Management system contains Online Booking Facility to Enhance Your
+ Business.Also you can Managing your Accounting Sections through this Module.
+ Another Facility is, Online Booked Customers get the Notification of Booking information
+ through Mail.
+
+
+
+
+ ☛ Installation : When you Install This Module, The supporting modules website,
+ accounting...are installed
+
+
+
+
+
+
+
+
+
+
+ Go to Salon Menu
+
+ Salon Menu Direct you to the Dashboard of the Salon.
+
+
+ *Note : First it is empty(False) because you have to create Chairs
+
+ Dashboard view is shown in the above image.Blue Chair Represents the Normal
+ Chair and the Rose Chair Represents the Chairs Reserved For Booking.
+ In the Dashboard, you get the today's collection on that chair.and how much time
+ it's take the chair free.You can also see the active orders on that chair
+ and go to that orders by clicking on it.You can change the settings of
+ chair by clicking the settings button in the dashboard
+
+
+
+
+
+
+
+
+ Sub Menu : Salon -> Chair
+
+ Here you can create and edit each chair details.
+ You can assign a user to the chair by adding new user to the Users Tab in the
+ form view of Chair(Check the image shown below).The last added user will be
+ Turned to the current user of the chair.By this Tab, you can Track which User
+ is Active on the Chair In a particular Date or Time.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sub Menu : Salon -> Services
+
+ List of services of Spa.You can create and edit Services here.
+
+
+
+
+
+
+
+ Sub Menu : Salon -> Salon Orders
+
+
+ Here you have the all Orders in the Spa.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form view of the Salon order is shown in the image.
+ You can get the corresponding invoice details of the
+ order by clicking the Invoice button in the upper right
+ side of the Form view
+
+
+
+
+
+
+
+
+
+ Sub Menu : Salon -> Bookings
+
+ Here you can see all the online bookings. You can either approve a booking
+ or Reject a booking. Both cases the notification is send to the customer mail
+ address. The approved bookings changed to salon orders.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Form View of Booking
+
+ Here you can see all the salon orders on the corresponding date.
+ by checking the availability of the time, you can decide to approve the
+ booking.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Sub Menu : Salon -> Settings
+
+ Here you can assign the chairs for booking purpose.
+ Only the assigned chairs can book a customer through
+ online.
+
+
+
+
+
+
+
+
+
+
+
+
+ ☛ Online Booking Form
+
+
+
+
+
+
+
+
+
+
+ Here the customer can fill the details. and send the form.
+
+
+
+
+
+
+ ☛ Online Booking Chair Details
+
+
+
+
+
+
+
+
+
+
+ Here the customer can check the availability of the chair by date.
+
+
+
+
+ You Looking for a free Documentation of this Application.?
+
+
+
+
+ Need Any Help?
+
+
+
+
+
diff --git a/salon_management/static/description/screenshot_salon_ services.png b/salon_management/static/description/screenshot_salon_ services.png
new file mode 100644
index 000000000..1ea1aa39d
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_ services.png differ
diff --git a/salon_management/static/description/screenshot_salon_booking_forms.png b/salon_management/static/description/screenshot_salon_booking_forms.png
new file mode 100644
index 000000000..f7583ed91
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_booking_forms.png differ
diff --git a/salon_management/static/description/screenshot_salon_booking_tree.png b/salon_management/static/description/screenshot_salon_booking_tree.png
new file mode 100644
index 000000000..1de327a64
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_booking_tree.png differ
diff --git a/salon_management/static/description/screenshot_salon_chair.png b/salon_management/static/description/screenshot_salon_chair.png
new file mode 100644
index 000000000..82fe9702c
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_chair.png differ
diff --git a/salon_management/static/description/screenshot_salon_dashboard.png b/salon_management/static/description/screenshot_salon_dashboard.png
new file mode 100644
index 000000000..951c455e7
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_dashboard.png differ
diff --git a/salon_management/static/description/screenshot_salon_online_1.png b/salon_management/static/description/screenshot_salon_online_1.png
new file mode 100644
index 000000000..1a27d2054
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_online_1.png differ
diff --git a/salon_management/static/description/screenshot_salon_online_2.png b/salon_management/static/description/screenshot_salon_online_2.png
new file mode 100644
index 000000000..8a41e490d
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_online_2.png differ
diff --git a/salon_management/static/description/screenshot_salon_order_form.png b/salon_management/static/description/screenshot_salon_order_form.png
new file mode 100644
index 000000000..cae0f546c
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_order_form.png differ
diff --git a/salon_management/static/description/screenshot_salon_order_kanban.png b/salon_management/static/description/screenshot_salon_order_kanban.png
new file mode 100644
index 000000000..55a05dc6d
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_order_kanban.png differ
diff --git a/salon_management/static/description/screenshot_salon_settings.png b/salon_management/static/description/screenshot_salon_settings.png
new file mode 100644
index 000000000..3975cf769
Binary files /dev/null and b/salon_management/static/description/screenshot_salon_settings.png differ
diff --git a/salon_management/static/src/css/salon_dashboard.css b/salon_management/static/src/css/salon_dashboard.css
new file mode 100644
index 000000000..6f57a3d56
--- /dev/null
+++ b/salon_management/static/src/css/salon_dashboard.css
@@ -0,0 +1,57 @@
+.style_chair{
+ text-align: center;
+ color: black;
+ font-size: 21px;
+ background: #337ab7;
+}
+.style_chair_booking{
+ text-align: center;
+ color: black;
+ font-size: 21px;
+ background: #a52694;
+}
+.style_collection{
+ color: black !important;
+ font-size: 12px;
+ text-align: center;
+ background: #337ab7 !important;
+ padding: 2px 0px 2px 3px;
+}
+.style_collection_booking{
+ color: black !important;
+ font-size: 12px;
+ text-align: center;
+ background: #a52694 !important;
+ padding: 2px 0px 2px 3px;
+}
+.no_of_people{
+ text-align: center;
+ font-size: 60px;
+ margin: 0px;
+ background: #337ab7;
+ color: white;
+ border-bottom: 1px solid #fff;
+ border-top: 1px solid #fff;
+}
+.no_of_people_booking{
+ text-align: center;
+ font-size: 60px;
+ margin: 0px;
+ background: #a52694;
+ color: white;
+ border-bottom: 1px solid #fff;
+ border-top: 1px solid #fff;
+}
+.button_background{
+ background-color: Transparent;
+ border: transparent;
+}
+
+.chair_box_website{
+ text-align: center;
+ border: 1px solid #666;
+ padding: 10px 15px;
+ box-shadow: 7px 8px 5px #888888;
+ background-color: #337ab7;
+ color: #fff;
+}
diff --git a/salon_management/static/src/js/salon_booking.js b/salon_management/static/src/js/salon_booking.js
new file mode 100644
index 000000000..2bd889bc8
--- /dev/null
+++ b/salon_management/static/src/js/salon_booking.js
@@ -0,0 +1,34 @@
+odoo.define('website_salon_booking_system', function (require) {
+'use strict';
+var ajax = require('web.ajax');
+$(document).on('click',"#submit_button",function() {
+ var name = $( "#name" ).val();
+ var date = $( "#date" ).val();
+ var phone = $( "#phone" ).val();
+ var email = $( "#email" ).val();
+ var service = $( "#service" ).val();
+ var chair = $( "#chair" ).val();
+ if (name != "" && date != "" && phone != "" && email != "" && service != "" && chair != "")
+ {
+ var booking_record = [name, date, phone, email, service, chair];
+ var salon_record = ajax.jsonRpc("/page/salon_details", 'call', {'salon_data':booking_record })
+ .then(function(){
+ window.location= "/page/salon_management.salon_booking_thank_you"
+ })
+ }
+ else
+ {
+ alert("Fill all the required fields")
+ }
+});
+
+$(document).on('click',"#check_button",function() {
+ var check_date = $( "#check_date" ).val();
+ var salon_check_date = ajax.jsonRpc("/page/salon_check_date", 'call', {'check_date':check_date })
+ .then(function(date_info){
+ window.location= "/page/salon_management.salon_booking_form?x=" + date_info
+ })
+});
+});
+
+
diff --git a/salon_management/static/src/less/salon_dashboard.less b/salon_management/static/src/less/salon_dashboard.less
new file mode 100644
index 000000000..cb2db4c9a
--- /dev/null
+++ b/salon_management/static/src/less/salon_dashboard.less
@@ -0,0 +1,16 @@
+@dashboard-bg-color: white;
+
+.o_kanban_view.o_kanban_dashboard.o_salon_kanban {
+ @sale-table-spacing: 10px;
+
+ .o_kanban_record {
+ min-height: 120px;
+ max-width: 180px !important;
+ box-shadow: 0px 0px 1px 3px #000 !important;
+ @media (min-width: @screen-sm-min) {
+ min-width: 20px;
+
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/salon_management/views/booking_backend.xml b/salon_management/views/booking_backend.xml
new file mode 100644
index 000000000..12a247b5e
--- /dev/null
+++ b/salon_management/views/booking_backend.xml
@@ -0,0 +1,61 @@
+
+
+
+
+ salon_booking_form.form
+ salon.booking
+
+
+
+
+
+ salon_booking_tree.tree
+ salon.booking
+
+
+
+
+
+
+
+
+
+
+
+ Salon Bookings
+ salon.booking
+ form
+ tree,form
+
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_bookings.xml b/salon_management/views/salon_bookings.xml
new file mode 100644
index 000000000..54117ac56
--- /dev/null
+++ b/salon_management/views/salon_bookings.xml
@@ -0,0 +1,229 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Working Time
+
+
+ Day
+ Starting Time
+ Closing Time
+
+
+
+
+
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Available Chairs and Details
+
+
+
+
+
+
+
+
Order Details
+
+
+
+ Order No.
+ Start Time
+ End Time
+
+
+
+
+
+
+ .
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_config.xml b/salon_management/views/salon_config.xml
new file mode 100644
index 000000000..0079a79d0
--- /dev/null
+++ b/salon_management/views/salon_config.xml
@@ -0,0 +1,37 @@
+
+
+
+ salon settings
+ salon.config.settings
+
+
+
+
+
+
+ Settings
+ ir.actions.act_window
+ salon.config.settings
+
+ form
+ inline
+
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_data.xml b/salon_management/views/salon_data.xml
new file mode 100644
index 000000000..248083070
--- /dev/null
+++ b/salon_management/views/salon_data.xml
@@ -0,0 +1,59 @@
+
+
+
+
+ user_salon_boolean.view
+ res.users
+
+
+
+
+
+
+
+
+ salon_stages_form.form
+ salon.stages
+
+
+
+
+
+ Draft
+
+
+
+ Open
+
+
+
+ Invoiced
+
+
+
+ Closed
+
+
+
+ Cancelled
+
+
+
+ Salon Default Customer
+ 1
+
+
+
+ Salon Service
+ 1
+ service
+
+
+
+
diff --git a/salon_management/views/salon_email_template.xml b/salon_management/views/salon_email_template.xml
new file mode 100644
index 000000000..5082d1f19
--- /dev/null
+++ b/salon_management/views/salon_email_template.xml
@@ -0,0 +1,41 @@
+
+
+
+
+ Salon e-mail template
+ ${object.company_id and object.company_id.email or ''}
+ Congratz ${object.name}
+ ${object.email|safe}
+ ${object.lang}
+
+
+
+ Dear ${(object.name)},
+ Thank you for choosing ${(object.company_id.name)}, your booking was registered!
+ Regards,
+ ${(object.company_id.name)}
+ ]]>
+
+
+
+ Salon e-mail template
+ ${object.company_id and object.company_id.email or ''}
+ We are Sorry ${object.name}
+ ${object.email|safe}
+ ${object.lang}
+
+
+
+ Dear ${(object.name)},
+ Thank you for choosing ${(object.company_id.name)}, but your booking was rejected!
+ there is no seats available for the time you chosen.
+ better luck next time.
+ Regards,
+ ${(object.company_id.name)}
+ ]]>
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_holiday.xml b/salon_management/views/salon_holiday.xml
new file mode 100644
index 000000000..861311c77
--- /dev/null
+++ b/salon_management/views/salon_holiday.xml
@@ -0,0 +1,33 @@
+
+
+
+
+ Sunday
+ 0
+
+
+ Monday
+ 0
+
+
+ Tuesday
+ 0
+
+
+ Wednesday
+ 0
+
+
+ Thursday
+ 0
+
+
+ Friday
+ 0
+
+
+ Saturday
+ 0
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_management_chair.xml b/salon_management/views/salon_management_chair.xml
new file mode 100644
index 000000000..2a54cea12
--- /dev/null
+++ b/salon_management/views/salon_management_chair.xml
@@ -0,0 +1,91 @@
+
+
+
+
+ Chair Sequence
+ chair.sequence
+ Chair-
+ 2
+ 1
+ 1
+
+
+
+
+ Collection Today
+
+
+ 1
+ minutes
+ -1
+
+
+
+
+
+ salon_chair_form.form
+ salon.chair
+
+
+
+
+
+ salon_chair_tree.tree
+ salon.chair
+
+
+
+
+
+
+
+
+ Dashboard
+ salon.chair
+ form
+ kanban,form
+ {}
+
+
+ Chair
+ salon.chair
+ form
+ tree,form
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_management_dashboard.xml b/salon_management/views/salon_management_dashboard.xml
new file mode 100644
index 000000000..54549e793
--- /dev/null
+++ b/salon_management/views/salon_management_dashboard.xml
@@ -0,0 +1,96 @@
+
+
+
+
+ salon_management_kanban.dashboard
+ salon.chair
+ kanban
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Today's Collection :
+
+
+
+
+
+
+
+
+
+ Today's Collection :
+
+
+
+
+
+
+
+
+
+ Free After (Hours) :
+
+
+
+
+
+
+
+
+
+ Reserved For Booking
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_management_services.xml b/salon_management/views/salon_management_services.xml
new file mode 100644
index 000000000..e0c7f955b
--- /dev/null
+++ b/salon_management/views/salon_management_services.xml
@@ -0,0 +1,38 @@
+
+
+
+
+ salon_service_form.form
+ salon.service
+
+
+
+
+
+ salon_service_tree.tree
+ salon.service
+
+
+
+
+
+
+
+
+
+ Services
+ salon.service
+ form
+ tree,form
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/salon_order_view.xml b/salon_management/views/salon_order_view.xml
new file mode 100644
index 000000000..f1976f7b3
--- /dev/null
+++ b/salon_management/views/salon_order_view.xml
@@ -0,0 +1,221 @@
+
+
+
+
+ partner_salon_boolean.view
+ res.partner
+
+
+
+
+
+
+
+
+ Salon Order Sequence
+ salon.order.sequence
+ SALON/%(range_year)s/
+
+
+
+ 4
+
+
+ salon_order_tree.tree
+ salon.order
+
+
+
+
+
+
+
+
+
+
+
+
+
+ salon_order_kanban.kanban
+ salon.order
+
+
+
+
+
+
+
+
+
+
+
+
+ salon_order_form.form
+ salon.order
+
+
+
+
+
+ Salon
+ salon.order
+ form
+ kanban,tree,form
+
+
+ Salon Orders
+ salon.order
+ form
+ kanban,tree,form
+ [('chair_id', '=', active_id)]
+
+
+
+
\ No newline at end of file
diff --git a/salon_management/views/working_hours.xml b/salon_management/views/working_hours.xml
new file mode 100644
index 000000000..e97226b1e
--- /dev/null
+++ b/salon_management/views/working_hours.xml
@@ -0,0 +1,68 @@
+
+
+
+
+ salon_working_form.form
+ salon.working.hours
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ salon_working_tree.tree
+ salon.working.hours
+
+
+
+
+
+
+
+
+
+
+ Working Hours
+ salon.working.hours
+ form
+ tree,form
+
+
+
+
+ Sunday
+
+
+ Monday
+
+
+ Tuesday
+
+
+ Wednesday
+
+
+ Thursday
+
+
+ Friday
+
+
+ Saturday
+
+
+
\ No newline at end of file