Browse Source

[ADD] Initial Commit

pull/29/head
SHEREEF PT 8 years ago
parent
commit
895e371909
  1. 24
      salon_management/__init__.py
  2. 52
      salon_management/__manifest__.py
  3. 23
      salon_management/controllers/__init__.py
  4. 88
      salon_management/controllers/main.py
  5. 26
      salon_management/models/__init__.py
  6. 84
      salon_management/models/salon_booking.py
  7. 75
      salon_management/models/salon_config.py
  8. 418
      salon_management/models/salon_management.py
  9. 20
      salon_management/security/ir.model.access.csv
  10. BIN
      salon_management/static/description/banner.jpg
  11. BIN
      salon_management/static/description/cybro_logo.png
  12. BIN
      salon_management/static/description/icon.png
  13. 278
      salon_management/static/description/index.html
  14. BIN
      salon_management/static/description/screenshot_salon_ services.png
  15. BIN
      salon_management/static/description/screenshot_salon_booking_forms.png
  16. BIN
      salon_management/static/description/screenshot_salon_booking_tree.png
  17. BIN
      salon_management/static/description/screenshot_salon_chair.png
  18. BIN
      salon_management/static/description/screenshot_salon_dashboard.png
  19. BIN
      salon_management/static/description/screenshot_salon_online_1.png
  20. BIN
      salon_management/static/description/screenshot_salon_online_2.png
  21. BIN
      salon_management/static/description/screenshot_salon_order_form.png
  22. BIN
      salon_management/static/description/screenshot_salon_order_kanban.png
  23. BIN
      salon_management/static/description/screenshot_salon_settings.png
  24. 57
      salon_management/static/src/css/salon_dashboard.css
  25. 74
      salon_management/static/src/js/salon_booking.js
  26. 16
      salon_management/static/src/less/salon_dashboard.less
  27. 61
      salon_management/views/booking_backend.xml
  28. 12
      salon_management/views/booking_demo.xml
  29. 234
      salon_management/views/salon_bookings.xml
  30. 37
      salon_management/views/salon_config.xml
  31. 65
      salon_management/views/salon_data.xml
  32. 41
      salon_management/views/salon_email_template.xml
  33. 27
      salon_management/views/salon_holiday.xml
  34. 91
      salon_management/views/salon_management_chair.xml
  35. 96
      salon_management/views/salon_management_dashboard.xml
  36. 38
      salon_management/views/salon_management_services.xml
  37. 221
      salon_management/views/salon_order_view.xml
  38. 68
      salon_management/views/working_hours.xml

24
salon_management/__init__.py

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import models
import controllers

52
salon_management/__manifest__.py

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
{
'name': 'Beauty Spa Management',
'summary': """Beauty Parlour Management with Online Booking System""",
'version': '10.0.1.0.0',
'author': 'Cybrosys Techno Solutions',
'website': "http://www.cybrosys.com",
'company': 'Cybrosys Techno Solutions',
"category": "Industries",
'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',
],
'demo': [
'views/booking_demo.xml',
],
'images': ['static/description/banner.jpg'],
'license': 'LGPL-3',
'installable': True,
'application': True,
}

23
salon_management/controllers/__init__.py

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<http://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import main

88
salon_management/controllers/main.py

@ -0,0 +1,88 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<http://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import json
from datetime import datetime, date
from odoo import http
from odoo.http import request
class SalonBookingWeb(http.Controller):
@http.route('/page/salon_details', csrf=False, type="http", methods=['POST', 'GET'], auth="public", website=True)
def salon_details(self, **kwargs):
name = kwargs['name']
date = kwargs['date']
time = kwargs['time']
phone = kwargs['phone']
email = kwargs['email']
chair = kwargs['chair']
j = 0
service_list = []
while(j < (int(kwargs['number']))):
item = "list_service["+str(j)+"][i]"
service_list.append(int(kwargs[item]))
j += 1
salon_service_obj = request.env['salon.service'].search([('id', 'in', service_list)])
dates_time = date+" "+time+":00"
date_and_time = datetime.strptime(dates_time, '%m/%d/%Y %H:%M:%S')
salon_booking = request.env['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(booking_data)
return json.dumps({'result': True})
@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_thank_you', type='http', auth="public", website=True)
def thank_you(self, **post):
return request.render('salon_management.salon_booking_thank_you', {})
@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.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})

26
salon_management/models/__init__.py

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
import salon_management
import salon_booking
import salon_config

84
salon_management/models/salon_booking.py

@ -0,0 +1,84 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<http://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import date
from odoo import models, fields, api
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"

75
salon_management/models/salon_config.py

@ -0,0 +1,75 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<http://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from odoo 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

418
salon_management/models/salon_management.py

@ -0,0 +1,418 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Cybrosys Technologies Pvt. Ltd.
# Copyright (C) 2017-TODAY Cybrosys Technologies(<https://www.cybrosys.com>).
# Author: Avinash Nk(<https://www.cybrosys.com>)
# 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 <http://www.gnu.org/licenses/>.
#
##############################################################################
from datetime import date, datetime, timedelta
from odoo import models, fields, api
from odoo.tools.translate import _
from odoo.exceptions import UserError, ValidationError
class PartnerSalon(models.Model):
_inherit = 'res.partner'
partner_salon = fields.Boolean(string="Is a Salon Partner")
class SequenceUpdaterSalon(models.Model):
_name = 'salon.sequence.updater'
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['salon.sequence.updater'].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")
chair_created_user = fields.Integer(string="Salon Chair Created User",
default=lambda self: self._uid)
@api.model
def create(self, cr):
sequence_code = 'chair.sequence'
sequence_number = self.env['ir.sequence'].next_by_code(sequence_code)
self.env['salon.sequence.updater'].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 = (time_takes - hours)*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")
chair_user = fields.Many2one('res.users', string="Chair User")
salon_order_created_user = fields.Integer(string="Salon Order Created User",
default=lambda self: self._uid)
@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):
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
self.chair_user = self.chair_id.user_of_chair
@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", required=True, translate=True)

20
salon_management/security/ir.model.access.csv

@ -0,0 +1,20 @@
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
view_salon_order3,view.salon.order3,model_salon_order,base.group_public,1,1,1,1
view_salon_order_lines3,view.salon.order3.lines,model_salon_order_lines,base.group_public,1,1,1,1
view_salon_stages3,view.salon.stages3,model_salon_stages,base.group_public,1,1,1,1
view_salon_chair3,view.salon.chair3,model_salon_chair,base.group_public,1,1,1,1
view_salon_service3,view.salon.service3,model_salon_service,base.group_public,1,1,1,1
view_salon_booking3,view.salon.booking3,model_salon_booking,base.group_public,1,1,1,1
view_salon_working_hours3,view.salon.working.hours3,model_salon_working_hours,base.group_public,1,1,1,1
view_salon_holiday3,view.salon.holiday3,model_salon_holiday,base.group_public,1,1,1,1
view_salon_config_settings3,view.salon.config.settings3,model_salon_config_settings,base.group_public,1,1,1,1
view_res_partner3,view.res.partner3,model_res_partner,base.group_public,1,1,1,1
view_res_users3,view.res.users3,model_res_users,base.group_public,1,1,1,1
view_salon_chair_user3,view.salon.chair.user3,model_salon_chair_user,base.group_public,1,1,1,1
view_salon_sequence_updater3,view.salon.sequence.updater3,model_salon_sequence_updater,base.group_public,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 view_salon_order view.salon.order model_salon_order base.group_user 1 1 1 1
3 view_salon_order_lines view.salon.order.lines model_salon_order_lines base.group_user 1 1 1 1
4 view_salon_stages view.salon.stages model_salon_stages base.group_user 1 1 1 1
5 view_salon_chair view.salon.chair model_salon_chair base.group_user 1 1 1 1
6 view_salon_service view.salon.service model_salon_service base.group_user 1 1 1 1
7 view_salon_order3 view.salon.order3 model_salon_order base.group_public 1 1 1 1
8 view_salon_order_lines3 view.salon.order3.lines model_salon_order_lines base.group_public 1 1 1 1
9 view_salon_stages3 view.salon.stages3 model_salon_stages base.group_public 1 1 1 1
10 view_salon_chair3 view.salon.chair3 model_salon_chair base.group_public 1 1 1 1
11 view_salon_service3 view.salon.service3 model_salon_service base.group_public 1 1 1 1
12 view_salon_booking3 view.salon.booking3 model_salon_booking base.group_public 1 1 1 1
13 view_salon_working_hours3 view.salon.working.hours3 model_salon_working_hours base.group_public 1 1 1 1
14 view_salon_holiday3 view.salon.holiday3 model_salon_holiday base.group_public 1 1 1 1
15 view_salon_config_settings3 view.salon.config.settings3 model_salon_config_settings base.group_public 1 1 1 1
16 view_res_partner3 view.res.partner3 model_res_partner base.group_public 1 1 1 1
17 view_res_users3 view.res.users3 model_res_users base.group_public 1 1 1 1
18 view_salon_chair_user3 view.salon.chair.user3 model_salon_chair_user base.group_public 1 1 1 1
19 view_salon_sequence_updater3 view.salon.sequence.updater3 model_salon_sequence_updater base.group_public 1 1 1 1

BIN
salon_management/static/description/banner.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
salon_management/static/description/cybro_logo.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
salon_management/static/description/icon.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

278
salon_management/static/description/index.html

@ -0,0 +1,278 @@
<section class="oe_container oe_dark">
<div class="oe_row oe_spaced">
<h2 class="oe_slogan">Beauty Spa Management</h2>
<h3 class="oe_slogan">This Module is for Managing the Process's in a Spa</h3>
<h4 class="oe_slogan">Author : Cybrosys Techno Solutions, www.cybrosys.com</h4>
<div>
<h3>Major Features</h3>
<ul>
<li style="list-style:none !important;"><span style="color:green;">&#9745</span>Online Booking Facility</li>
<li style="list-style:none !important;"><span style="color:green;"> &#9745</span>Accounting Facility</li>
<li style="list-style:none !important;"><span style="color:green;"> &#9745</span>Customer Notification Through Mail</li>
<li style="list-style:none !important;"><span style="color:green;"> &#9745</span>User Interactive Dashboard</li>
<li style="list-style:none !important;"><span style="color:green;"> &#9745</span>Customer Can view the Available chairs and order details</li>
<li style="list-style:none !important;"><span style="color:green;"> &#9745</span>Different access levels for Users and Administrator</li>
<li style="list-style:none !important;"><span style="color:green;"> &#9745</span>Track the chair user by date</li>
</ul>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div>
<p class='oe_mt32'>
This Spa management system developed by Cybrosys Techno Solutions helps
your customers to do the online booking for using the service. This module
integrates with other Odoo modules like accounting and website.
</p>
<p class='oe_mt32'>Another advantage of having this Spa management system is your customers
who have done the online booking will get the booking information via email.
By using an app like this, you can enhance your business.
</p>
</div>
</div>
<div class="oe_row oe_spaced">
<div class="oe_span10">
<div class="oe_demo oe_picture oe_screenshot">
<img src="screenshot_salon_dashboard.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_padded">
<div class="oe_span12">
<p class='oe_mt32'>
Go to 'Salon Menu'</p>
<p class='oe_mt32'>
'Salon Menu' will direct you to the 'Dashboard' of the Salon.
</p>
<p class='oe_mt32'>
*Note : It will be shown as empty(False) if you have not created chairs</p>
<p class='oe_mt32'>
Dashboard view is shown in the above image. Your customers can book
the service in two ways, direct booking and online booking. The pink
color chairs are the only ones available for online booking and blue
chairs for direct booking.</p>
<p class='oe_mt32'>In Dashboard, you get the daily collection of that chair
and also the customer will be able to know when will be the chair free,
in case if that chair is currently in use. Also you can see the active
orders of that chair and if you click on it, that will directly take
you to the active orders of that chair.</p>
<p class='oe_mt32'>If you want to change the settings of chair, you can just
click the settings button in the dashboard.</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span12">
<p class='oe_mt32'>
Sub Menu : Salon -> Chair</p>
<p class='oe_mt32'>Here you can create and edit details of each chair.
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.
Using this tab, you can track which user is active on the Chair on a
particular date or time.</p>
</div>
<div class="oe_span12">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_chair.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_padded">
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_ services.png">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
Sub Menu : Salon -> Services</p>
<p>
List of services provided by the Spa. You can create and edit services here.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<p class='oe_mt32'>
Sub Menu : Salon -> Salon Orders</p>
<div class="oe_span6">
<p>
Here you have all the orders in the Spa.
</p>
</div>
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_order_kanban.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_padded">
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_order_form.png">
</div>
</div>
<div class="oe_span6">
<p>
Form view of the salon order is shown in the image.
You will get the corresponding invoice details of the
order by clicking the Invoice button in the upper right
side of the form view.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span6">
<p class='oe_mt32'>
Sub Menu : Salon -> Bookings</p>
<p>
Here you can see all the online bookings.
You can either approve a booking or reject a booking.
In both cases the notification is send to the customer mail address.
The approved bookings will be changed to salon orders.
</p>
</div>
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_booking_tree.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_padded">
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_booking_forms.png">
</div>
</div>
<div class="oe_span6">
<p class='oe_mt32'>
Form View of Booking</p>
<p>
Here you can see all the salon orders on the corresponding date.
After checking the time available,
you can decide to approve/reject the booking accordingly.
</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div class="oe_span6">
<p class='oe_mt32'>
Sub Menu : Salon -> Settings</p>
<p>
Here you can assign the chairs for booking purpose.
Only the assigned chairs can be booked by a customer through online.
</p>
</div>
<div class="oe_span6">
<div class="oe_row_img oe_centered">
<img class="oe_picture oe_screenshot"
src="screenshot_salon_settings.png">
</div>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<div class="oe_row oe_padded">
<div>
&#x261B; Online Booking Form
</div>
</div>
<div class="oe_row oe_spaced">
<div class="oe_span10">
<div class="oe_demo oe_picture oe_screenshot">
<img src="screenshot_salon_online_1.png">
</div>
</div>
<div class="oe_span12">
<p class='oe_mt32'>
Here the customer can fill the details. and send the form.</p>
</div>
</div>
</section>
<section class="oe_container">
<div class="oe_row oe_spaced">
<div>
&#x261B; Online Booking Chair Details
</div>
</div>
<div class="oe_row oe_spaced">
<div class="oe_span10">
<div class="oe_demo oe_picture oe_screenshot">
<img src="screenshot_salon_online_2.png">
</div>
</div>
<div class="oe_span12">
<p class='oe_mt32'>
Here the customer can check the availability of the chair by date.</p>
</div>
</div>
</section>
<section class="oe_container oe_dark">
<h2 class="oe_slogan" style="margin-top:20px;" >You Looking for a free Documentation of this Application.?</h2>
<h3 class="oe_slogan">Give a Request Mail to:&nbsp;&nbsp;<i class="fa fa-envelope" aria-hidden="true"></i>&nbsp;&nbsp;<a href="#" style="color:blue;">odoo@cybrosys.com</a></h3>
</section>
<section class="oe_container">
<h2 class="oe_slogan" style="margin-top:20px;" >Need Any Help?</h2>
<div class="oe_slogan" style="margin-top:10px !important;">
<div>
<a class="btn btn-primary btn-lg mt8"
style="color: #FFFFFF !important;border-radius: 0;" href="https://www.cybrosys.com"><i
class="fa fa-envelope"></i> Email </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;"
href="https://www.cybrosys.com/contact/"><i
class="fa fa-phone"></i> Contact Us </a> <a
class="btn btn-primary btn-lg mt8" style="color: #FFFFFF !important;border-radius: 0;"
href="https://www.cybrosys.com/odoo-customization-and-installation/"><i
class="fa fa-check-square"></i> Request Customization </a>
</div>
<br>
<img src="cybro_logo.png" style="width: 190px; margin-bottom: 20px;" class="center-block">
<div>
<a href="https://twitter.com/cybrosys" target="_blank"><i class="fa fa-2x fa-twitter" style="color:white;background: #00a0d1;width:35px;"></i></a></td>
<a href="https://www.linkedin.com/company/cybrosys-technologies-pvt-ltd" target="_blank"><i class="fa fa-2x fa-linkedin" style="color:white;background: #31a3d6;width:35px;padding-left: 3px;"></i></a></td>
<a href="https://www.facebook.com/cybrosystechnologies" target="_blank"><i class="fa fa-2x fa-facebook" style="color:white;background: #3b5998;width:35px;padding-left: 8px;"></i></a></td>
<a href="https://plus.google.com/106641282743045431892/about" target="_blank"><i class="fa fa-2x fa-google-plus" style="color:white;background: #c53c2c;width:35px;padding-left: 3px;"></i></a></td>
<a href="https://in.pinterest.com/cybrosys" target="_blank"><i class="fa fa-2x fa-pinterest" style="color:white;background: #ac0f18;width:35px;padding-left: 3px;"></i></a></td>
</div>
</div>
</section>

BIN
salon_management/static/description/screenshot_salon_ services.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

BIN
salon_management/static/description/screenshot_salon_booking_forms.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

BIN
salon_management/static/description/screenshot_salon_booking_tree.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

BIN
salon_management/static/description/screenshot_salon_chair.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
salon_management/static/description/screenshot_salon_dashboard.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
salon_management/static/description/screenshot_salon_online_1.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 69 KiB

BIN
salon_management/static/description/screenshot_salon_online_2.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

BIN
salon_management/static/description/screenshot_salon_order_form.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
salon_management/static/description/screenshot_salon_order_kanban.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

BIN
salon_management/static/description/screenshot_salon_settings.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 33 KiB

57
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;
}

74
salon_management/static/src/js/salon_booking.js

@ -0,0 +1,74 @@
odoo.define('salon_management.website_salon_booking_system', function (require) {
'use strict';
var ajax = require('web.ajax');
var base = require('web_editor.base');
var core = require('web.core');
var _t = core._t;
$(document).on('click',"#submit_button",function() {
var name = $( "#name" ).val();
var date = $( "#date" ).val();
var time = $( "#time" ).val();
var phone = $( "#phone" ).val();
var email = $( "#email" ).val();
var service = $( "#service" ).val();
var chair = $( "#chair" ).val();
var list_service = [];
var number = service.length
for (var i=0; i<(service.length); i++){
var k = {i : service[i]}
list_service.push(k)
}
var time_left_char = time.substring(0, 2)
var time_right_char = time.substring(3, 5)
var time_separator = time.substring(2,3)
if(date != ""){
if (isNaN(time_left_char) || isNaN(time_right_char) || time_separator != ":"){
if(time != ""){
alert("Select a valid Time")
}
}
else{
var time_left = parseInt(time_left_char)
var time_right = parseInt(time_right_char)
if ((time_left < 24) && (time_right < 60) && (time_left >= 0) && (time_right >= 0)){
if (name != "" && phone != "" && email != "" && service != "" && chair != ""){
var booking_record = {'name': name, 'date': date, 'time': time, 'phone': phone,
'email': email, service, 'list_service':list_service,'chair': chair,'number': number }
$.ajax({
url: "/page/salon_details",
method: "POST",
dataType: "json",
data: booking_record,
success: function( data ) {
window.location.href = "/page/salon_management.salon_booking_thank_you";
},
error: function (error) {
alert('error: ' + error);
}
});
}
else{
alert("Fill all the required fields")
}
}
else {
alert("Select a valid time")
}
}
}
});
$(document).on('click',"#check_button",function() {
var check_date = $( "#check_date" ).val();
if (check_date != "")
{
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
})
}
else
{
alert("Fill the Field")
}
});
});

16
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;
}
}
}

61
salon_management/views/booking_backend.xml

@ -0,0 +1,61 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="salons_booking_form" model="ir.ui.view">
<field name="name">salon_booking_form.form</field>
<field name="model">salon.booking</field>
<field name="arch" type="xml">
<form>
<header>
<button name="booking_approve" states="draft" string="Approve" class="oe_highlight" type="object"/>
<button name="booking_reject" states="draft" string="Reject" class="oe_highlight" type="object"/>
<field name="state" widget="statusbar" statusbar_visible="draft,approved,rejected"/>
</header>
<sheet>
<group>
<group>
<field name="name"/>
<field name="phone"/>
<field name="services" widget="many2many_tags"/>
</group>
<group>
<field name="time"/>
<field name="email"/>
<field name="chair_id"/>
<field name="lang" invisible="1"/>
<field name="company_id" invisible="1"/>
<field name="state" invisible="1"/>
</group>
</group>
<notebook>
<page>
<field name="filtered_orders"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="salons_booking_tree" model="ir.ui.view">
<field name="name">salon_booking_tree.tree</field>
<field name="model">salon.booking</field>
<field name="arch" type="xml">
<tree colors="#046a8c:state=='draft';#f20b07:state=='rejected';#01471f:state=='approved'">
<field name="name"/>
<field name="time"/>
<field name="phone"/>
<field name="email"/>
<field name="state"/>
</tree>
</field>
</record>
<record id="salon_booking_action" model="ir.actions.act_window">
<field name="name">Salon Bookings</field>
<field name="res_model">salon.booking</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="salon_management_bookings" name="Bookings" parent="salon_management_salon" action="salon_booking_action"/>
</data>
</odoo>

12
salon_management/views/booking_demo.xml

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="website_menu_salon_booking_demo" model="website.menu">
<field name="name">Bookings</field>
<field name="url">/page/salon_management.salon_booking_form</field>
<field name="parent_id" ref="website.website2_main_menu"/>
<field name="sequence" type="int">80</field>
<field name="website_id" ref="website.website2"/>
</record>
</data>
</odoo>

234
salon_management/views/salon_bookings.xml

@ -0,0 +1,234 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="website_menu_salon_booking" model="website.menu">
<field name="name">Bookings</field>
<field name="url">/page/salon_management.salon_booking_form</field>
<field name="parent_id" ref="website.main_menu"/>
<field name="sequence" type="int">80</field>
<field name="website_id" ref="website.default_website"/>
</record>
<template id="salon_web" inherit_id="website.assets_frontend" name="Website assets">
<xpath expr="." position="inside">
<script type="text/javascript" src="/salon_management/static/src/js/salon_booking.js"></script>
</xpath>
</template>
<template id="salon_booking_form" name="Salon Booking" page="True">
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css"/>
<link rel="stylesheet" href="/resources/demos/style.css"/>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>$( function() {$( "#date" ).datepicker();} );</script>
<script>$( function() {$( "#check_date" ).datepicker();} );</script>
<t t-call="website.layout">
<div class="container">
<h1 style="text-align:center;padding-bottom: 26px;padding-top: 20px;">Book Your Chair</h1>
<form>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-offset-1 col-md-1 col-sm-4 control-label" style="padding-top: 8px;" for="search">NAME*</label>
<div class="col-md-5 col-sm-8">
<input type="text" id="name" class="search-query form-control oe_search_box" required="True" placeholder="Enter your Name"/>
</div>
</div>
</div>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-offset-1 col-md-1 col-sm-4 control-label" style="padding-top: 8px;" for="search">SERVICE*</label>
<div class="col-md-5 col-sm-8">
<select multiple="multiple" id="service" required="True" class="form-control" style="width: 432px; height: 40px;">
<t t-foreach="salon_services" t-as="service">
<option t-att-value="service.id" t-esc="service.name"/></t>
</select>
</div>
<div class="col-md-5" style="padding-left:0px !important;">
<p style="font-size: 16px;">( You can select multiple services or Remove a selection by pressing down on the Ctrl button )</p>
</div>
</div>
</div>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-offset-1 col-md-1 col-sm-4 control-label" style="padding-top: 8px;" for="search">TIME*</label>
<div class="col-md-5 col-sm-8">
<input type="text" id="date" placeholder="dd/mm/yyyy"
onkeyup="var v = this.value;if (v.match(/^\d{2}$/) !== null) {this.value = v + '/';} else if (v.match(/^\d{2}\/\d{2}$/) !== null) {this.value = v + '/';}" maxlength="10"
style="width: 250px;height: 35px;"/>
<input type="text" id="time" placeholder="HH:MM"
onkeyup="var v = this.value;if (v.match(/^\d{2}$/) !== null) {this.value = v + ':';}" maxlength="5"
style="width: 178px;height: 35px;"/>
</div>
<div class="col-md-5" style="padding-left:0px !important;">
<p style="font-size: 16px;padding-top: 9px;">( Select a date and time based on the availability of the chair )</p>
</div>
</div>
</div>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-offset-1 col-md-1 col-sm-4 control-label" style="padding-top: 8px;" for="search">CHAIR*</label>
<div class="col-md-5 col-sm-8">
<select id="chair" required="True" class="form-control" style="width: 432px; height: 35px;">
<t t-foreach="chair_details" t-as="chair">
<option t-att-value="chair.id" t-esc="chair.name"/></t>
</select>
</div>
<div class="col-md-5" style="padding-left:0px !important;">
<p style="font-size: 16px;padding-top: 9px;">( Select the chair that free in the preferred time )</p>
</div>
</div>
</div>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-offset-1 col-md-1 col-sm-4 control-label" style="padding-top: 8px;" for="search">PHONE*</label>
<div class="col-md-5 col-sm-8">
<input type="text" id="phone" class="search-query form-control oe_search_box" required="True" placeholder="Enter your Phone number(eg:999**12345)"/>
</div>
</div>
</div>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-offset-1 col-md-1 col-sm-4 control-label" style="padding-top: 8px;" for="search">E-MAIL*</label>
<div class="col-md-5 col-sm-8">
<input type="email" id="email" class="search-query form-control oe_search_box" required="True" placeholder="Enter your E-Mail Address(eg:avinashnk916@gmail.com)"/>
</div>
</div>
</div>
<div class="form-group">
<div class="col-md-12">
<div class="col-md-offset-1 col-md-1 col-sm-4"></div>
<div class="col-sm-8 col-md-5">
<button type="button" id="submit_button" class="btn btn-primary btn-md o_website_form_send">Send</button>
<span id="o_website_form_result"></span>
</div>
</div>
</div>
</form>
</div>
<div class="container">
<h1 style="text-align:center;">Working Time</h1>
<div>
<table class="table">
<th>Day</th>
<th>Starting Time</th>
<th>Closing Time</th>
<div>
<tbody>
<t t-foreach="working_time" t-as="working_time_obj">
<tr>
<td>
<span t-field="working_time_obj.name"/>.
</td>
<td>
<span t-field="working_time_obj.from_time"/>
</td>
<td>
<span t-field="working_time_obj.to_time"/>
</td>
</tr>
</t>
</tbody>
</div>
</table>
</div>
</div>
<section id="chair_details">
<div class="container" style="margin-bottom:100px">
<h1 style="text-align:center;">Available Chairs and Details</h1>
<hr/>
<div class="form-group form-field o_website_form_required_custom">
<div class="col-md-12" style="margin-bottom:10px;">
<label class="col-md-1 col-sm-4 control-label" style="padding-top: 8px; padding-right:0px !important" for="search">TIME</label>
<div class="col-md-2 col-sm-4" style="padding-left: 0px;">
<input style="padding-right:0px;" id="check_date" type="text" class="search-query form-control oe_search_box" required="" placeholder="Select a date"/>
</div>
<div class="col-sm-2 col-md-1" style="padding-left: 0px;" >
<button type="submit" id="check_button" class="btn btn-primary btn-md o_website_form_send">Check</button>
<span id="o_website_form_result"></span>
</div>
<div class="col-sm-3 col-md-3" style="padding-left: 33px;" >
<h3 style="text-align:left; float:left; margin-top: 4px;font-weight: 600;">Date :</h3>
<h3 style="float:left; margin-top: 4px;font-weight: 600;"><t t-esc="date_search"/></h3>
</div>
<div class="col-sm-3 col-md-5" style="padding-left: 0px;" >
<h3 style="text-align:left; float:left; margin-top: 4px;font-weight: 600; padding-right:6px;">Holidays :</h3>
<div t-foreach="holiday" t-as="holiday_obj">
<h4 t-field="holiday_obj.name" style="float:left;font-weight: 600; "/>
<h4 style="float:left;font-weight: 600;">&amp;nbsp;</h4>
</div>
</div>
</div>
</div>
<div class="col-md-12">
<div t-foreach="chair_details" t-as="chair_obj">
<div class="col-md-4" t-if="chair_obj.active_booking_chairs == 1">
<div style="height: 268px!important; text-align: center; border: 1px solid #666;padding: 15px 0px;box-shadow: 7px 8px 5px #888888;background-color: #a52694;color: #fff;margin-bottom: 10px;">
<span style="font-size: 40px;" t-field="chair_obj.name"/><br/>
<a style="color: #fff;font-size: 40px;">Order Details</a>
<style>
#style-2::-webkit-scrollbar-track
{
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
border-radius: 10px;
background-color: #a52694;
width:8px !important;
}
#style-2::-webkit-scrollbar
{
width: 12px;
background-color: #a52694;
width:8px !important;
}
#style-2::-webkit-scrollbar-thumb
{
border-radius: 10px;
-webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.3);
background-color: rgba(130, 0, 112, 0.69);
width:8px !important;
}
</style>
<div id="style-2" style="overflow: overlay; height: 136px; padding-right: 25px;padding-left: 25px;">
<table class="table">
<th>Order No.</th>
<th>Start Time</th>
<th>End Time</th>
<div>
<tbody>
<t t-foreach="order_details" t-as="order_obj">
<t t-if="order_obj.chair_id.id == chair_obj.id">
<tr>
<td>
<span t-field="order_obj.id"/>.
</td>
<td>
<span t-field="order_obj.start_time_only"/>
</td>
<td>
<span t-field="order_obj.end_time_only"/>
</td>
</tr>
</t>
</t>
</tbody>
</div>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
</t>
</template>
<template id="salon_booking_thank_you" name="Thank you" page="True">
<t t-call="website.layout">
<form>
<div class="form-group" style="text-align: center; padding-top: 11%; padding-bottom: 10%;">
<h1>Thank you</h1>
</div>
</form>
</t>
</template>
</data>
</odoo>

37
salon_management/views/salon_config.xml

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="salon_config_settings_view" model="ir.ui.view">
<field name="name">salon settings</field>
<field name="model">salon.config.settings</field>
<field name="arch" type="xml">
<form string="Configure Salon" class="oe_form_configuration">
<header>
<button string="Apply" type="object" name="execute" class="oe_highlight"/>
<button string="Cancel" name="cancel" class="oe_link"/>
</header>
<div id="main">
<group string="Booking Chairs(Choose the chair when its free)">
<field name="salon_booking_chairs" widget="many2many_checkboxes"/>
</group>
<group string="Holidays">
<field name="salon_holidays" widget="many2many_checkboxes"/>
</group>
</div>
</form>
</field>
</record>
<record id="salon_config_settings_action" model="ir.actions.act_window">
<field name="name">Settings</field>
<field name="type">ir.actions.act_window</field>
<field name="res_model">salon.config.settings</field>
<field name="view_id" ref="salon_config_settings_view"/>
<field name="view_mode">form</field>
<field name="target">inline</field>
</record>
<menuitem id="salon_config_settings_menu" parent="salon_management_menu"
name="Configuration"/>
<menuitem id="salon_settings_menu" parent="salon_config_settings_menu"
string="Settings" action="salon_config_settings_action" />
</odoo>

65
salon_management/views/salon_data.xml

@ -0,0 +1,65 @@
<?xml version="1.0"?>
<odoo>
<data>
<record id="user_salon_boolean" model="ir.ui.view">
<field name="name">user_salon_boolean.view</field>
<field name="model">res.users</field>
<field name="inherit_id" ref="base.view_users_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='in_group_12']" position="after">
<field name="user_salon_active"/>
</xpath>
</field>
</record>
<record id="salon_stages_form" model="ir.ui.view">
<field name="name">salon_stages_form.form</field>
<field name="model">salon.stages</field>
<field name="arch" type="xml">
<form>
<sheet>
<h1>
<field name="name"/>
</h1>
</sheet>
</form>
</field>
</record>
<record model="salon.stages" id="salon_stage_00">
<field name="name">Draft</field>
</record>
<record model="salon.stages" id="salon_stage_01">
<field name="name">Open</field>
</record>
<record model="salon.stages" id="salon_stage_02">
<field name="name">Invoiced</field>
</record>
<record model="salon.stages" id="salon_stage_03">
<field name="name">Closed</field>
</record>
<record model="salon.stages" id="salon_stage_04">
<field name="name">Cancelled</field>
</record>
<record model="res.partner" id="salon_partner_01">
<field name="name">Salon Default Customer</field>
<field name="partner_salon">1</field>
</record>
<record model="product.template" id="salon_service_product_01">
<field name="name">Salon Service</field>
<field name="partner_salon">1</field>
<field name="type">service</field>
</record>
</data>
<data noupdate="1">
<record model="salon.sequence.updater" id="salon_sequence_updater_01">
<field name="name">Salon Sequence Updater</field>
<field name="sequence_salon">Chair-1</field>
</record>
</data>
</odoo>

41
salon_management/views/salon_email_template.xml

@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="salon_email_template_approved" model="mail.template">
<field name="name">Salon e-mail template</field>
<field name="email_from">${object.company_id and object.company_id.email or ''}</field>
<field name="subject">Congratz ${object.name}</field>
<field name="email_to">${object.email|safe}</field>
<field name="lang">${object.lang}</field>
<field name="model_id" ref="salon_management.model_salon_booking"/>
<field name="auto_delete" eval="True"/>
<field name="body_html">
<![CDATA[
<p>Dear ${(object.name)},<br/><br/>
Thank you for choosing ${(object.company_id.name)}, your booking was registered!<br/></p>
Regards,<br/>
${(object.company_id.name)}
]]>
</field>
</record>
<record id="salon_email_template_rejected" model="mail.template">
<field name="name">Salon e-mail template</field>
<field name="email_from">${object.company_id and object.company_id.email or ''}</field>
<field name="subject">We are Sorry ${object.name}</field>
<field name="email_to">${object.email|safe}</field>
<field name="lang">${object.lang}</field>
<field name="model_id" ref="salon_management.model_salon_booking"/>
<field name="auto_delete" eval="True"/>
<field name="body_html">
<![CDATA[
<p>Dear ${(object.name)},<br/><br/>
Thank you for choosing ${(object.company_id.name)}, but your booking was rejected!<br/>
there is no seats available for the time you chosen.<br/>
better luck next time.<br/></p>
Regards,<br/>
${(object.company_id.name)}
]]>
</field>
</record>
</data>
</odoo>

27
salon_management/views/salon_holiday.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record model="salon.holiday" id="salon_holiday_01">
<field name="name">Sunday</field>
<field name="holiday">True</field>
</record>
<record model="salon.holiday" id="salon_holiday_02">
<field name="name">Monday</field>
</record>
<record model="salon.holiday" id="salon_holiday_03">
<field name="name">Tuesday</field>
</record>
<record model="salon.holiday" id="salon_holiday_04">
<field name="name">Wednesday</field>
</record>
<record model="salon.holiday" id="salon_holiday_05">
<field name="name">Thursday</field>
</record>
<record model="salon.holiday" id="salon_holiday_06">
<field name="name">Friday</field>
</record>
<record model="salon.holiday" id="salon_holiday_07">
<field name="name">Saturday</field>
</record>
</data>
</odoo>

91
salon_management/views/salon_management_chair.xml

@ -0,0 +1,91 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data noupdate="1">
<record id="sequence_chair" model="ir.sequence">
<field name="name">Chair Sequence</field>
<field name="code">chair.sequence</field>
<field name="prefix">Chair-</field>
<field name="number_next">2</field>
<field name="number_increment">1</field>
<field name="padding">1</field>
</record>
</data>
<data>
<record forcecreate="True" id="ir_cron_collections_today" model="ir.cron">
<field name="name">Collection Today</field>
<field eval="True" name="active" />
<field name="user_id" ref="base.user_root" />
<field name="interval_number">1</field>
<field name="interval_type">days</field>
<field name="numbercall">-1</field>
<field eval="False" name="doall" />
<field eval="'salon.chair'" name="model" />
<field eval="'collection_today_updater'" name="function" />
</record>
<record id="salon_chair_form" model="ir.ui.view">
<field name="name">salon_chair_form.form</field>
<field name="model">salon.chair</field>
<field name="arch" type="xml">
<form>
<sheet>
<h1>
<field name="name"/>
</h1>
<group>
<group>
<field name="user_of_chair"/>
<field name="number_of_orders" invisible="1"/>
<field name="collection_today" invisible="1"/>
<field name="active_booking_chairs" invisible="1"/>
</group>
<group>
<field name="date"/>
</group>
</group>
<notebook>
<page string="Users">
<field name="user_line" mode="tree">
<tree string="Salon User Lines" editable="bottom" delete="false">
<field name="read_only_checker" invisible="1"/>
<field name="user_id" domain="[('user_salon_active', '=', False)]"
attrs="{'readonly':[ ('read_only_checker', '!=', False)]}"/>
<field name="start_date"
attrs="{'readonly':[ ('read_only_checker', '!=', False)]}"/>
<field name="end_date"/>
</tree>
</field>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="salon_chair_tree" model="ir.ui.view">
<field name="name">salon_chair_tree.tree</field>
<field name="model">salon.chair</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
</tree>
</field>
</record>
<record id="salon_dashboard_action" model="ir.actions.act_window">
<field name="name">Dashboard</field>
<field name="res_model">salon.chair</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,form</field>
<field name="context">{}</field>
</record>
<record id="salon_chair_action" model="ir.actions.act_window">
<field name="name">Chair</field>
<field name="res_model">salon.chair</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="salon_management_menu" name="Salon"/>
<menuitem id="salon_management_dashboard" parent="salon_management_menu" action="salon_dashboard_action"/>
<menuitem id="salon_management_salon" name="Salon" parent="salon_management_menu"/>
<menuitem id="salon_management_chair" name="Chair" parent="salon_management_salon" action="salon_chair_action"/>
</data>
</odoo>

96
salon_management/views/salon_management_dashboard.xml

@ -0,0 +1,96 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="salon_management_kanban" model="ir.ui.view" >
<field name="name">salon_management_kanban.dashboard</field>
<field name="model">salon.chair</field>
<field name="type">kanban</field>
<field name="arch" type="xml">
<kanban class="oe_background_grey o_kanban_dashboard o_salon_kanban" create="0">
<field name="name"/>
<field name="number_of_orders"/>
<field name="active_booking_chairs"/>
<templates>
<t t-name="kanban-box">
<div>
<div t-if="record.active_booking_chairs.raw_value == false">
<div class="o_primary style_chair">
<field name="name"/>
<div>
<button type="edit" string="Settings" class="button_background" > <i class="fa fa-cog fa-spin"/></button>
</div>
</div>
</div>
<div t-if="record.active_booking_chairs.raw_value == true">
<div class="o_primary style_chair_booking">
<field name="name"/>
<div>
<button type="edit" string="Settings" class="button_background" > <i class="fa fa-cog fa-spin"/></button>
</div>
</div>
</div>
<a href="#" name="%(salon_active_orders_action_dashboard)d" type="action" string="Active Orders">
<div t-if="record.active_booking_chairs.raw_value == false">
<div class="o_primary no_of_people">
<field name="number_of_orders"/>
</div>
</div>
<div t-if="record.active_booking_chairs.raw_value == true">
<div class="o_primary no_of_people_booking">
<field name="number_of_orders"/>
</div>
</div>
</a>
<div t-if="record.active_booking_chairs.raw_value == false">
<div class=" o_primary style_collection">
<span class=" o_primary style_collection">
<span class=" o_primary style_collection" style="float: left;">Today's Collection :</span>
<span class=" o_primary style_collection" style="float: center;">
<field name="collection_today"/>
</span>
</span>
</div>
</div>
<div t-if="record.active_booking_chairs.raw_value == true">
<div class=" o_primary style_collection_booking">
<span class=" o_primary style_collection_booking">
<span class=" o_primary style_collection_booking" style="float: left;">Today's Collection :</span>
<span class=" o_primary style_collection_booking" style="float: center;">
<field name="collection_today"/>
</span>
</span>
</div>
</div>
<div t-if="record.active_booking_chairs.raw_value == false">
<div class=" o_primary style_collection">
<span class=" o_primary style_collection">
<span class=" o_primary style_collection" style="float: left;">Free After (Hours) :</span>
<span class=" o_primary style_collection" style="float: center;">
<field name="total_time_taken_chair" widget="float_time"/>
</span>
</span>
</div>
</div>
<div t-if="record.active_booking_chairs.raw_value == true">
<div class=" o_primary style_collection_booking">
<span class=" o_primary style_collection_booking">
<span class=" o_primary style_collection_booking" style="float: center;">Reserved For Booking</span>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<template id="assets_backend" name="sales_team assets" inherit_id="web.assets_backend">
<xpath expr="." position="inside">
<link rel="stylesheet"
href="/salon_management/static/src/less/salon_dashboard.less"/>
<link rel="stylesheet"
href="/salon_management/static/src/css/salon_dashboard.css"/>
</xpath>
</template>
</data>
</odoo>

38
salon_management/views/salon_management_services.xml

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="salon_service_form" model="ir.ui.view">
<field name="name">salon_service_form.form</field>
<field name="model">salon.service</field>
<field name="arch" type="xml">
<form>
<sheet>
<group>
<field name="name"/>
<field name="price"/>
<field name="time_taken" widget="float_time"/>
</group>
</sheet>
</form>
</field>
</record>
<record id="salon_service_tree" model="ir.ui.view">
<field name="name">salon_service_tree.tree</field>
<field name="model">salon.service</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="price"/>
<field name="time_taken" widget="float_time"/>
</tree>
</field>
</record>
<record id="salon_service_action" model="ir.actions.act_window">
<field name="name">Services</field>
<field name="res_model">salon.service</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="salon_management_service" parent="salon_management_salon" action="salon_service_action"/>
</data>
</odoo>

221
salon_management/views/salon_order_view.xml

@ -0,0 +1,221 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="partner_salon_boolean" model="ir.ui.view">
<field name="name">partner_salon_boolean.view</field>
<field name="model">res.partner</field>
<field name="inherit_id" ref="base.view_partner_form"/>
<field name="arch" type="xml">
<xpath expr="//field[@name='customer']" position="after">
<field name="partner_salon"/>
</xpath>
</field>
</record>
<record id="sequence_salon_order" model="ir.sequence">
<field name="name">Salon Order Sequence</field>
<field name="code">salon.order.sequence</field>
<field name="prefix">SALON/%(range_year)s/</field>
<field eval="1" name="number_next"/>
<field eval="1" name="number_increment"/>
<field eval="True" name="use_date_range"/>
<field name="padding">4</field>
</record>
<record id="salon_order_tree" model="ir.ui.view">
<field name="name">salon_order_tree.tree</field>
<field name="model">salon.order</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="chair_id"/>
<field name="start_time"/>
<field name="end_time"/>
<field name="time_taken_total" widget="float_time"/>
<field name="price_subtotal"/>
<field name="stage_id"/>
</tree>
</field>
</record>
<record id="salon_order_kanban" model="ir.ui.view">
<field name="name">salon_order_kanban.kanban</field>
<field name="model">salon.order</field>
<field name="arch" type="xml">
<kanban default_group_by="stage_id" class="o_kanban_small_column" quick_create="false">
<field name="color"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="#{kanban_color(record.color.raw_value)} oe_kanban_global_click">
<div class="o_dropdown_kanban dropdown">
<a class="dropdown-toggle btn" data-toggle="dropdown" href="#" >
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable"><li><a type="edit">Edit</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li>
<ul class="oe_kanban_colorpicker" data-field="color"/>
</li>
</ul>
</div>
<div class="oe_kanban_content">
<div>
<strong><field name="name"/></strong>
</div>
<div class="text-muted">
<a>Customer :</a>
<field name="customer_name"/>
<div style="float: right;">
<a>Chair :</a>
<field name="chair_id"/>
</div>
</div>
<div class="text-muted">
<a>Amount :</a>
<field name="price_subtotal"/>
</div>
<div class="text-muted">
<a>Total time taken :</a>
<field name="time_taken_total" widget="float_time"/>
</div>
<div class="text-muted">
<a>Date :</a>
<field name="date"/>
</div>
</div>
<div class="oe_clear"></div>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<record id="salon_order_form" model="ir.ui.view">
<field name="name">salon_order_form.form</field>
<field name="model">salon.order</field>
<field name="arch" type="xml">
<form>
<header>
<button name="salon_validate" attrs="{'invisible': ['|',('stage_id', '!=', 1), ('validation_controller', '=', True)]}" string="Validate" type="object"
class="oe_highlight"/>
<button name="salon_confirm" attrs="{'invisible': ['|',('stage_id', '!=', 1), ('validation_controller', '!=', True)]}" string="Confirm" type="object"
class="oe_highlight"/>
<button name="salon_invoice_create" attrs="{'invisible': [('stage_id', '!=', 2)]}" string="Create Invoice"
type="object" class="oe_highlight"/>
<button name="salon_cancel" string="Cancel" attrs="{'invisible': [('stage_id', 'not in', [1,2])]}" type="object"/>
<button name="salon_close" attrs="{'invisible': [('stage_id', '!=', 3)]}" string="Close" type="object"/>
<field name="stage_id" widget="statusbar" domain="[('id','in',[1,2,4])]"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button name="action_view_invoice_salon"
type="object"
class="oe_stat_button"
icon="fa-pencil-square-o"
attrs="{'invisible': [('stage_id', 'not in', [3,4])]}"
string="Invoice">
</button>
</div>
<group>
<group>
<field name="partner_id" domain="[('partner_salon','=',True)]" attrs="{'readonly': [('stage_id', '!=', 1)]}"/>
<field name="customer_name" attrs="{'readonly': [('stage_id', '!=', 1)]}"/>
<field name="chair_id" domain="[('active_booking_chairs','!=',True)]" attrs="{'readonly': [('stage_id', '!=', 1)]}"/>
</group>
<group>
<field name="booking_identifier" invisible="1"/>
<field name="date" attrs="{'readonly': [('stage_id', '!=', 1)]}"/>
<field name="start_time" attrs="{'readonly': [('stage_id', '!=', 1)], 'invisible': ['|',('stage_id', '!=', 1), ('booking_identifier', '!=', True)]}"/>
<field name="end_time" attrs="{'readonly': [('stage_id', '!=', 1)], 'invisible': ['|',('stage_id', '!=', 1), ('booking_identifier', '!=', True)]}"/>
<field name="start_date_only" invisible="1"/>
<field name="inv_stage_identifier" invisible="1"/>
<field name="invoice_number" invisible="1"/>
<field name="time_taken_total" invisible="1"/>
<field name="validation_controller" invisible="1"/>
</group>
</group>
<notebook>
<page string="Order Lines">
<field name="order_line" mode="tree,kanban" attrs="{'readonly': [('stage_id', '!=', 1)]}">
<form string="Salon Order Lines">
<group>
<group>
<field name="service_id"/>
<field name="time_taken"/>
<field name="price"/>
</group>
</group>
</form>
<tree string="Salon Order Lines" editable="bottom">
<field name="service_id"/>
<field name="time_taken" widget="float_time"/>
<field name="price"/>
<field name="price_subtotal"/>
</tree>
<kanban class="o_kanban_mobile">
<field name="service_id"/>
<field name="time_taken"/>
<field name="price_subtotal"/>
<templates>
<t t-name="kanban-box">
<div t-attf-class="oe_kanban_card oe_kanban_global_click">
<div class="row">
<div class="col-xs-12">
<strong>
<span>
<t t-esc="record.service_id.value"/>
</span>
</strong>
</div>
</div>
<div class="row">
<div class="col-xs-4 text-muted">
<span class="pull-right text-right">
<t t-esc="record.time_taken.value"/>
</span>
</div>
</div>
<div class="row">
<div class="col-xs-4 text-muted">
<span class="pull-right text-right">
<t t-esc="record.price_subtotal.value"/>
</span>
</div>
</div>
</div>
</t>
</templates>
</kanban>
</field>
<group class="oe_subtotal_footer oe_right" colspan="2" name="salon_total">
<div class="oe_subtotal_footer_separator oe_inline o_td_label">
<label for="price_subtotal"/>
<button name="button_total_update" string="(update)" type="object"
class="oe_edit_only oe_link"/>
</div>
<field name="price_subtotal" nolabel="1" class="oe_subtotal_footer_separator"/>
</group>
<field name="note" class="oe_inline"
placeholder="Setup default terms and conditions in your company settings."/>
<div class="oe_clear"/>
</page>
</notebook>
</sheet>
</form>
</field>
</record>
<record id="salon_order_action" model="ir.actions.act_window">
<field name="name">Salon</field>
<field name="res_model">salon.order</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
</record>
<record id="salon_active_orders_action_dashboard" model="ir.actions.act_window">
<field name="name">Salon Orders</field>
<field name="res_model">salon.order</field>
<field name="view_type">form</field>
<field name="view_mode">kanban,tree,form</field>
<field name="domain">[('chair_id', '=', active_id)]</field>
</record>
<menuitem id="salon_order" parent="salon_management_salon" name="Salon Orders" action="salon_order_action"/>
</data>
</odoo>

68
salon_management/views/working_hours.xml

@ -0,0 +1,68 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<data>
<record id="salon_working_form" model="ir.ui.view">
<field name="name">salon_working_form.form</field>
<field name="model">salon.working.hours</field>
<field name="arch" type="xml">
<form>
<sheet>
<h1>
<field name="name"/>
</h1>
<group>
<group>
<field name="from_time" widget="float_time"/>
</group>
<group>
<field name="to_time" widget="float_time"/>
</group>
</group>
</sheet>
</form>
</field>
</record>
<record id="salon_working_tree" model="ir.ui.view">
<field name="name">salon_working_tree.tree</field>
<field name="model">salon.working.hours</field>
<field name="arch" type="xml">
<tree>
<field name="name"/>
<field name="from_time" widget="float_time"/>
<field name="to_time" widget="float_time"/>
</tree>
</field>
</record>
</data>
<record id="salon_config_working_action" model="ir.actions.act_window">
<field name="name">Working Hours</field>
<field name="res_model">salon.working.hours</field>
<field name="view_type">form</field>
<field name="view_mode">tree,form</field>
</record>
<menuitem id="salon_working_hours_menu" parent="salon_config_settings_menu"
string="Working Hours" action="salon_config_working_action" />
<data noupdate="1">
<record model="salon.working.hours" id="salon_working_01">
<field name="name">Sunday</field>
</record>
<record model="salon.working.hours" id="salon_working_02">
<field name="name">Monday</field>
</record>
<record model="salon.working.hours" id="salon_working_03">
<field name="name">Tuesday</field>
</record>
<record model="salon.working.hours" id="salon_working_04">
<field name="name">Wednesday</field>
</record>
<record model="salon.working.hours" id="salon_working_05">
<field name="name">Thursday</field>
</record>
<record model="salon.working.hours" id="salon_working_06">
<field name="name">Friday</field>
</record>
<record model="salon.working.hours" id="salon_working_07">
<field name="name">Saturday</field>
</record>
</data>
</odoo>
Loading…
Cancel
Save