@ -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 |
@ -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, |
|||
} |
@ -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 |
@ -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}) |
@ -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 |
|||
|
@ -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" |
|||
|
@ -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 |
@ -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) |
|
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 11 KiB |
@ -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;">☑</span>Online Booking Facility</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span>Accounting Facility</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span>Customer Notification Through Mail</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span>User Interactive Dashboard</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span>Customer Can view the Available chairs and order details</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</span>Different access levels for Users and Administrator</li> |
|||
<li style="list-style:none !important;"><span style="color:green;"> ☑</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> |
|||
☛ 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> |
|||
☛ 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: <i class="fa fa-envelope" aria-hidden="true"></i> <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> |
|||
|
|||
|
After Width: | Height: | Size: 44 KiB |
After Width: | Height: | Size: 71 KiB |
After Width: | Height: | Size: 66 KiB |
After Width: | Height: | Size: 50 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 69 KiB |
After Width: | Height: | Size: 53 KiB |
After Width: | Height: | Size: 40 KiB |
After Width: | Height: | Size: 72 KiB |
After Width: | Height: | Size: 33 KiB |
@ -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; |
|||
} |
@ -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") |
|||
} |
|||
}); |
|||
}); |
@ -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; |
|||
|
|||
} |
|||
} |
|||
|
|||
} |
@ -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> |
@ -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> |
@ -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;">&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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |
@ -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> |