diff --git a/salon_operation/__init__.py b/salon_operation/__init__.py new file mode 100644 index 000000000..490f399c0 --- /dev/null +++ b/salon_operation/__init__.py @@ -0,0 +1 @@ +import models,sweep \ No newline at end of file diff --git a/salon_operation/__openerp__.py b/salon_operation/__openerp__.py new file mode 100644 index 000000000..9cbc01ae5 --- /dev/null +++ b/salon_operation/__openerp__.py @@ -0,0 +1,41 @@ +{ + 'name': 'Salon Booking', + 'summary': """ """, + 'description': """ """, + 'author': '', + 'website': 'http://www.example.com', + 'category': 'Test', + 'version': '0.1', + + 'depends': ['base', + 'sale', + 'hr', + ], + + 'data': [ + 'templates/template.xml', + 'security/ir.model.access.csv', + 'views/chair_view.xml', + 'views/period_view.xml', + 'views/day_view.xml', + 'views/month_view.xml', + 'views/autofill_month.xml', + 'views/salon_book_view.xml', + 'sweep/sweep_sale_order.xml', + 'sweep/sweep_menu_act.xml', + 'sweep/sweep_product.xml', + 'sweep/sweep_invoice.xml', + ], + + 'demo': ['demo/demo_chair.xml', + 'demo/demo_time.xml', + 'demo/demo_day.xml', + 'demo/demo_month.xml', + + ], + + 'installable': True, + 'auto_install': False, + 'application': True, +} + diff --git a/salon_operation/demo/demo_chair.xml b/salon_operation/demo/demo_chair.xml new file mode 100644 index 000000000..977408656 --- /dev/null +++ b/salon_operation/demo/demo_chair.xml @@ -0,0 +1,28 @@ + + + + + CH0001 + + + + + CH0002 + + + + + CH0003 + + + + + CH0004 + + + + + + + + \ No newline at end of file diff --git a/salon_operation/demo/demo_day.xml b/salon_operation/demo/demo_day.xml new file mode 100644 index 000000000..bf4aca42e --- /dev/null +++ b/salon_operation/demo/demo_day.xml @@ -0,0 +1,911 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salon_operation/demo/demo_month.xml b/salon_operation/demo/demo_month.xml new file mode 100644 index 000000000..94b13480f --- /dev/null +++ b/salon_operation/demo/demo_month.xml @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salon_operation/demo/demo_time.xml b/salon_operation/demo/demo_time.xml new file mode 100644 index 000000000..ffb57a4f9 --- /dev/null +++ b/salon_operation/demo/demo_time.xml @@ -0,0 +1,473 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 9.30 + + + + 11.30 + + + + 13.00 + off + Lunch Break + + + + 15.30 + + + + + 19.00 + + + + \ No newline at end of file diff --git a/salon_operation/models/__init__.py b/salon_operation/models/__init__.py new file mode 100644 index 000000000..4d50983d6 --- /dev/null +++ b/salon_operation/models/__init__.py @@ -0,0 +1 @@ +import chair,period,day,month,autofill_month,salon_book, confirm_booking \ No newline at end of file diff --git a/salon_operation/models/autofill_month.py b/salon_operation/models/autofill_month.py new file mode 100644 index 000000000..67fb866d7 --- /dev/null +++ b/salon_operation/models/autofill_month.py @@ -0,0 +1,55 @@ +from openerp import models, fields,api,http,SUPERUSER_ID,_ + + +class AutoFillWizard(models.TransientModel): + _name = 'salon.auto_fill.wizard' + + name = fields.Char('Name') + month = fields.Integer('Month') + year = fields.Integer('Year') + no_days = fields.Integer('No of Days') + + @api.one + @api.onchange('month') + def onchange_month(self): + days = {1: 31, 2: 29, 3: 31, + 4: 30, 5: 31, 6: 30, + 7: 31, 8: 31, 9: 30, + 10: 31, 11: 30, 12: 31, }.get(self.month) + if days: + self.no_days = days + + @api.one + def act_auto_fill(self): + if self.name: + month_name = self.name + else: + month_name = 'Untitled Month'+str(self.id) + times_list = [] + for Each_Time in self.env['salon.period'].search([('day_id', '=', None)]): + time_line_list = [] + for Each_Chair in self.env['salon.chair'].search([]): + time_line_list.append((0, 0, {'chair_id': Each_Chair.id})) + times_list.append((0, 0, {'name': Each_Time.name, + 'period_type': Each_Time.period_type, + 'off_reason': Each_Time.off_reason, + 'chair_lines': time_line_list})) + days_list = [] + for day_count in range(1, self.no_days+1): + day_line = {'name': day_count, + 'period_lines': times_list} + days_list.append((0, 0, day_line)) + + month_values = {'name': month_name, + 'month': self.month, + 'year': self.year, + 'day_lines': days_list} + + month_obj = self.pool.get('salon.month') + month_obj.create(self._cr, self._uid, month_values) + + + @api.one + def close_auto_fill(self): + pass + diff --git a/salon_operation/models/chair.py b/salon_operation/models/chair.py new file mode 100644 index 000000000..91df785bf --- /dev/null +++ b/salon_operation/models/chair.py @@ -0,0 +1,14 @@ +from openerp import models, fields,api,http,SUPERUSER_ID + + +class Chairs(models.Model): + _name = 'salon.chair' + + name = fields.Char() + related_employee = fields.Many2one('hr.employee', string='Related Employee') + + _sql_constraints = [ + ('name_unique', 'unique(name)', 'This chair is already exist !'), + ('related_employee_unique', 'unique(related_employee)', 'This person was reserved for another chair !')] + + diff --git a/salon_operation/models/confirm_booking.py b/salon_operation/models/confirm_booking.py new file mode 100644 index 000000000..9b83b3ede --- /dev/null +++ b/salon_operation/models/confirm_booking.py @@ -0,0 +1,78 @@ +from openerp import models, fields,api,http,SUPERUSER_ID,_ +from openerp.osv import fields, osv + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + def action_wait(self, cr, uid, ids, context=None): + context = context or {} + for o in self.browse(cr, uid, ids): + if not any(line.state != 'cancel' for line in o.order_line): + raise osv.except_osv(_('Error!'),_('You cannot confirm a this booking which has no line.')) + noprod = self.test_no_product(cr, uid, o, context) + if (o.order_policy == 'manual') or noprod: + self.write(cr, uid, [o.id], {'state': 'manual', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)}) + # ================================================================= + booking_no = o.name + values = self.get_values_booking(cr, uid, ids, context)[0] + for Each_Day in values['month'].day_lines: + if Each_Day.id == values['day'].id: + for Each_Time in Each_Day.period_lines: + if Each_Time.id == values['time'].id: + for Each_Time_Line in Each_Time.chair_lines: + if Each_Time_Line.chair_id.id == values['chair'].id: + print Each_Day.name, Each_Time.name, Each_Time_Line.chair_id.name + if Each_Time_Line.booked: + raise osv.except_osv(_('Booking Failed !'),_('Mismatch in booking, this chair may be already booked.')) + else: + print 'nooooooooooooo' + cr.execute("UPDATE salon_period_line SET partner_id = %s,book_no = %s where period_id = %s and chair_id = %s", (str(values['partner'].id), booking_no, str(values['time'].id), str(values['chair'].id))) + # ================================================================= + else: + self.write(cr, uid, [o.id], {'state': 'progress', 'date_confirm': fields.date.context_today(self, cr, uid, context=context)}) + # ================================================================= + booking_no = o.name + values = self.get_values_booking(cr, uid, ids, context)[0] + for Each_Day in values['month'].day_lines: + if Each_Day.id == values['day'].id: + for Each_Time in Each_Day.period_lines: + if Each_Time.id == values['time'].id: + for Each_Time_Line in Each_Time.chair_lines: + if Each_Time_Line.chair_id.id == values['chair'].id: + print Each_Day.name, Each_Time.name, Each_Time_Line.chair_id.name + if Each_Time_Line.booked: + raise osv.except_osv(_('Booking Failed !'),_('Mismatch in booking, this chair may be already booked.')) + else: + print 'nooooooooooooo' + cr.execute("UPDATE salon_period_line SET partner_id = %s,book_no = %s where period_id = %s and chair_id = %s", (str(values['partner'].id), booking_no, str(values['time'].id), str(values['chair'].id))) + # ================================================================= + self.pool.get('sale.order.line').button_confirm(cr, uid, [x.id for x in o.order_line if x.state != 'cancel']) + + return True + + @api.one + def get_values_booking(self): + return {'month': self.for_month, + 'day': self.for_day, + 'time': self.for_time, + 'chair': self.char_id, + 'partner': self.partner_id} + + + def action_button_confirm(self, cr, uid, ids, context=None): + # ====================================== + # values = self.get_values_booking(cr, uid, ids, context)[0] + # cr.execute("UPDATE salon_period_line SET partner_id = %s where period_id = %s and chair_id = %s", (str(values['partner'].id), str(values['time'].id), str(values['chair'].id))) + + # ====================================== + if not context: + context = {} + assert len(ids) == 1, 'This option should only be used for a single id at a time.' + self.signal_workflow(cr, uid, ids, 'order_confirm') + if context.get('send_email'): + self.force_quotation_send(cr, uid, ids, context=context) + return True + + + diff --git a/salon_operation/models/day.py b/salon_operation/models/day.py new file mode 100644 index 000000000..d1caf21d4 --- /dev/null +++ b/salon_operation/models/day.py @@ -0,0 +1,88 @@ +from openerp import models, fields,api,http,SUPERUSER_ID,_ + + +class Days(models.Model): + _name = 'salon.day' + _rec_name = 'display_booked' + + name = fields.Integer('Day') + day_type = fields.Selection([('on', 'On'), ('off', 'Off')], default='on', string='On/Off') + off_reason = fields.Char() + period_lines = fields.One2many('salon.period', 'day_id') + month_id = fields.Many2one('salon.month') + + @api.one + def _get_booked(self): + count = 0 + total = 0 + for Each_Line in self.period_lines: + if Each_Line.period_type == 'on': + if Each_Line.booked: + count += 1 + total += 1 + else: + total += 1 + + if count < total: + self.booked = False + else: + self.booked = True + + booked = fields.Boolean('Fully Booked', compute='_get_booked') + + + @api.one + def _get_display_booked(self): + count = 0 + for Each_Line in self.period_lines: + if Each_Line.booked: + count += 1 + if count < len(self.period_lines): + self.display_booked = str(self.name) + else: + self.display_booked = str(self.name) + '- Fully Booked' + + display_booked = fields.Char(compute='_get_display_booked') + + # @api.one + # def _get_day_stat(self): + # self.day_stat = self.days.day_type + # day_stat = fields.Char(compute='_get_day_stat', string='On/Off') + + + +# +# day_stat = fields.Selection([('on', 'On'), ('off', 'Off')], default='on') + +# period_lines = fields.One2many('salon.day.line', 'day_id') +# +# _sql_constraints = [ +# ('name_unique', 'unique(name)', 'This day is already exist !')] +# +# @api.one +# def get_day(self): +# if self.name >0 and self.name <= 31: +# return True +# else: +# return False +# +# def check_day_valid(self, cr, uid, ids, context=None): +# return self.get_day(cr, uid, ids, context)[0] +# +# _constraints = [ +# (check_day_valid, 'You created an invalid day', ['name']), +# ] +# +# +# class DayLines(models.Model): +# _name = 'salon.day.line' +# +# period_id = fields.Many2one('salon.period', string='Time') +# # @api.one +# # def _get_period_stat(self): +# # self.period_stat = self.period_id.period_type +# +# # period_stat = fields.Char(compute='_get_period_stat', string='On/Off') +# day_id = fields.Many2one('salon.day') +# period_stat = fields.Selection([('on', 'On'), ('off', 'Off')], default='on') +# diff --git a/salon_operation/models/month.py b/salon_operation/models/month.py new file mode 100644 index 000000000..1f99c09f0 --- /dev/null +++ b/salon_operation/models/month.py @@ -0,0 +1,112 @@ +from openerp import models, fields,api,http,SUPERUSER_ID + + +class Months(models.Model): + _name = 'salon.month' + _rec_name = 'display_booked' + + name = fields.Char('Name') + + _sql_constraints = [ + ('name_unique', 'unique(name)', 'This month is already exist !')] + + + month = fields.Integer('Month') + year = fields.Integer('Year') + day_lines = fields.One2many('salon.day', 'month_id') + + @api.one + def _get_booked(self): + count = 0 + total = 0 + for Each_Day in self.day_lines: + if Each_Day.day_type == 'on': + if Each_Day.booked: + count += 1 + total += 1 + else: + total += 1 + + if count < total: + self.booked = False + else: + self.booked = True + + # print 'count', count + # print 'total', total + # + # + # for Each_Day in self.day_lines: + # if Each_Day.booked: + # count += 1 + # if count < len(self.day_lines): + # self.booked = False + # else: + # self.booked = True + + booked = fields.Boolean('Fully Booked', compute='_get_booked', default=False) + + @api.one + def _get_display_booked(self): + count = 0 + for Each_Day in self.day_lines: + if Each_Day.booked: + count += 1 + if count < len(self.day_lines): + self.display_booked = str(self.name) + else: + self.display_booked = str(self.name) + ' - Fully Booked' + + display_booked = fields.Char(compute='_get_display_booked') + @api.one + def _get_month_show(self): + if self.month == 1: + self.month_show = 'JAN' + elif self.month == 2: + self.month_show = 'FEB' + elif self.month == 3: + self.month_show = 'MAR' + elif self.month == 4: + self.month_show = 'APR' + elif self.month == 5: + self.month_show = 'MAY' + elif self.month == 6: + self.month_show = 'JUN' + elif self.month == 7: + self.month_show = 'JUL' + elif self.month == 8: + self.month_show = 'AUG' + elif self.month == 9: + self.month_show = 'SEP' + elif self.month == 10: + self.month_show = 'OCT' + elif self.month == 11: + self.month_show = 'NOV' + elif self.month == 12: + self.month_show = 'DEC' + else: + self.month_show = 'None' + month_show = fields.Char(compute='_get_month_show') + + + + +# day_lines = fields.One2many('salon.month.line', 'month_id') +# +# +# class MonthLines(models.Model): +# _name = 'salon.month.line' +# +# days = fields.Many2one('salon.day') +# month_id = fields.Many2one('salon.month') +# +# # @api.one +# # def _get_day_stat(self): +# # self.day_stat = self.days.day_type +# # day_stat = fields.Char(compute='_get_day_stat', string='On/Off') +# +# day_stat = fields.Selection([('on', 'On'), ('off', 'Off')], default='on') + + + + diff --git a/salon_operation/models/period.py b/salon_operation/models/period.py new file mode 100644 index 000000000..0da999dcf --- /dev/null +++ b/salon_operation/models/period.py @@ -0,0 +1,83 @@ +from openerp import models, fields,api,http,SUPERUSER_ID,_ +from openerp.http import request + + +class Period(models.Model): + _name = 'salon.period' + _rec_name = 'display_booked' + + name = fields.Float('Time') + + # _sql_constraints = [ + # ('name_unique', 'unique(name)', 'This time is already exist !')] + + chair_lines = fields.One2many('salon.period.line', 'period_id') + period_type = fields.Selection([('on', 'On'), ('off', 'Off')], default='on', string='On/Off') + off_reason = fields.Char() + day_id = fields.Many2one('salon.day') + + @api.one + def _get_booked(self): + count = 0 + for Each_Chair in self.chair_lines: + if Each_Chair.partner_id.id: + count += 1 + if count < len(self.chair_lines): + self.booked = False + else: + self.booked = True + booked = fields.Boolean('Fully Booked', compute='_get_booked') + + @api.one + def _get_display_booked(self): + count = 0 + for Each_Chair in self.chair_lines: + if Each_Chair.partner_id.id: + count += 1 + if count < len(self.chair_lines): + self.display_booked = str(self.name) + else: + self.display_booked = str(self.name) + ' -Fully Booked' + + + + display_booked = fields.Char(compute='_get_display_booked') + # @api.onchange('chair_lines') + # def unique_chair(self): + # # GET VALUE TO CHILD CHAIR + # selected_chair = str(request.session.get('onchange_chair_selected')) + # request.session['onchange_chair_selected'] = None + # already_exist = 0 + # for Each_Chair in self.chair_lines: + # if Each_Chair.chair_id.name == selected_chair: + # already_exist += 1 + # if already_exist >= 2: + # return {'warning': { + # 'title': _('Constraint Error'), + # 'message': 'This chair is already selected for this period', + # }} + + +class PeriodLine(models.Model): + _name = 'salon.period.line' + + chair_id = fields.Many2one('salon.chair', string='Chair') + period_id = fields.Many2one('salon.period') + partner_id = fields.Many2one('res.partner', string='Customer') + + @api.one + def _get_related_emp(self): + self.related_employee = self.chair_id.related_employee + related_employee = fields.Many2one('hr.employee', compute='_get_related_emp', string='Dressing Person') + + @api.one + def _get_booked(self): + if self.partner_id: + self.booked = True + else: + self.booked = False + booked = fields.Boolean('Booked', compute='_get_booked') + book_no = fields.Char('Booking No', default=' ') + + + diff --git a/salon_operation/models/salon_book.py b/salon_operation/models/salon_book.py new file mode 100644 index 000000000..284b6ef2c --- /dev/null +++ b/salon_operation/models/salon_book.py @@ -0,0 +1,161 @@ +from openerp import models, fields,api,http,SUPERUSER_ID, _ +from openerp.addons.sale.sale import sale_order +from openerp.http import request +from datetime import timedelta +from dateutil import parser + + +class SaleOrder(models.Model): + _inherit = 'sale.order' + + @api.one + @api.onchange('char_id') + def onchange_chair(self): + self.employee_id = self.char_id.related_employee + + @api.one + @api.onchange('employee_id') + def onchange_employee(self): + have_any = False + for Each_Chair in self.env['salon.chair'].search([]): + if self.employee_id == Each_Chair.related_employee: + have_any = Each_Chair + self.char_id = have_any + + employee_id = fields.Many2one('hr.employee', 'Dressing Person', store=True) + char_id = fields.Many2one('salon.chair', string='Chair') + state = fields.Selection([ + ('draft', 'Draft'), + ('sent', 'Sent'), + ('cancel', 'Cancelled'), + ('waiting_date', 'Waiting Schedule'), + ('progress', 'Scheduled'), + ('manual', 'To Invoice'), + ('shipping_except', 'Shipping Exception'), + ('invoice_except', 'Invoice Exception'), + ('done', 'Done'), + ], 'Status', readonly=True, copy=False, help="Gives the status of the quotation or sales order.\ + \nThe exception status is automatically set when a cancel operation occurs \ + in the invoice validation (Invoice Exception) or in the picking list process (Shipping Exception).\nThe 'Waiting Schedule' status is set when the invoice is confirmed\ + but waiting for the scheduler to run on the order date.", select=True) + name = fields.Char('Order Reference', required=True, copy=False, + readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, select=True) + order_line = fields.One2many('sale.order.line', 'order_id', 'Items', readonly=True, states={'draft': [('readonly', False)], 'sent': [('readonly', False)]}, copy=True) + + @api.onchange('name') + def onchange_name(self): + request.session['name_schedule'] = self.name + + def create(self, cr, uid, vals, context=None): + if context is None: + context = {} + if vals.get('name', '/') == '/': + vals['name'] = self.pool.get('ir.sequence').get(cr, uid, 'sale.order', context=context) or '/' + # ==================================================================================== + vals['name'] = vals['name'].replace('SO', 'NO-') + if str(request.session.get('name_schedule')) == '/': + vals['name'] = str(vals['name']) + else: + vals['name'] = str(vals['name']) + ' ' + str(request.session.get('name_schedule')) + request.session['name_schedule'] = None + # ==================================================================================== + if vals.get('partner_id') and any(f not in vals for f in ['partner_invoice_id', 'partner_shipping_id', 'pricelist_id', 'fiscal_position']): + defaults = self.onchange_partner_id(cr, uid, [], vals['partner_id'], context=context)['value'] + if not vals.get('fiscal_position') and vals.get('partner_shipping_id'): + delivery_onchange = self.onchange_delivery_id(cr, uid, [], vals.get('company_id'), None, vals['partner_id'], vals.get('partner_shipping_id'), context=context) + defaults.update(delivery_onchange['value']) + vals = dict(defaults, **vals) + ctx = dict(context or {}, mail_create_nolog=True) + new_id = super(sale_order, self).create(cr, uid, vals, context=ctx) + self.message_post(cr, uid, [new_id], body=_("Quotation created"), context=ctx) + return new_id + + @api.one + def get_warning(self): + if self.for_month.booked: + self.for_month = False + self.month_state_show = ' ' \ + ' ' \ + 'Sorry, this month is fully booked' + else: + self.month_state_show = '' + + @api.one + def get_warning_for_day(self): + if self.for_day.booked: + self.for_day = False + self.month_state_show = ' ' \ + ' ' \ + 'Sorry, this day is fully booked' + else: + self.month_state_show = ' ' + + @api.one + def get_warning_for_time(self): + if self.for_time.booked: + self.for_time = False + self.month_state_show = ' ' \ + ' ' \ + 'Sorry, this time is fully booked' + else: + self.month_state_show = ' ' + @api.one + def get_selected_month(self): + return self.for_month.id + + @api.onchange('for_month') + def onchange_month(self): + # ====clear=other=fields========= + self.for_day = False + self.char_id = False + self.for_time = False + # =============================== + self.get_warning() + return {'domain': {'for_day': [('month_id', '=', self.get_selected_month()), + ('day_type', '=', 'on'), + ('booked', '=', False)]}} + + @api.one + def get_selected_day(self): + return self.for_day.id + + @api.onchange('for_day') + def onchange_day(self): + # ===Clear=other=fields======= + self.char_id = False + self.for_time = False + # ============================ + self.get_warning_for_day() + # for i in self.env['salon.period'].search([]): + # if i.day_id.id == False: + # print 'kkkkkkkk' + selected_day = self.get_selected_day() + if selected_day[0]: + print '' + else: + selected_day = -1 + + return {'domain': {'for_time': [('day_id', '=', selected_day), ('period_type', '=', 'on')]}} + + @api.one + def get_selected_time(self): + return self.for_time + + @api.onchange('for_time') + def onchange_time(self): + # ===Clear=other=fields======= + self.char_id = False + # ============================ + self.get_warning_for_time() + chair_ids = [] + for Each_Period_line in self.get_selected_time()[0].chair_lines: + if Each_Period_line.booked: + chair_ids.append(Each_Period_line.chair_id.id) + return {'domain': {'char_id': [('id', 'not in', chair_ids)]}} + + + created_domain = [('booked', '=', False)] + for_month = fields.Many2one('salon.month', domain=created_domain) + for_day = fields.Many2one('salon.day', domain=[('month_id', '=', -1)]) + for_time = fields.Many2one('salon.period', domain=[('day_id', 'in', [-69]), [('day_id', '!=', None)]]) + month_state_show = fields.Char(default=' ') diff --git a/salon_operation/security/ir.model.access.csv b/salon_operation/security/ir.model.access.csv new file mode 100644 index 000000000..6914eedc1 --- /dev/null +++ b/salon_operation/security/ir.model.access.csv @@ -0,0 +1,6 @@ +id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink +access_chair_sale_user,access_chair_sale_user,model_salon_chair,base.group_sale_salesman,1,1,1,0 +access_month_sale_user,access_month_sale_user,model_salon_month,base.group_sale_salesman,1,1,1,0 +access_day_sale_user,access_day_sale_user,model_salon_day,base.group_sale_salesman,1,1,1,0 +access_time_sale_user,access_time_sale_user,model_salon_period,base.group_sale_salesman,1,1,1,0 +access_time_line_sale_user,access_time_line_sale_user,model_salon_period_line,base.group_sale_salesman,1,1,1,0 \ No newline at end of file diff --git a/salon_operation/static/description/Times.png b/salon_operation/static/description/Times.png new file mode 100644 index 000000000..6d94e09dc Binary files /dev/null and b/salon_operation/static/description/Times.png differ diff --git a/salon_operation/static/description/auto_fill.png b/salon_operation/static/description/auto_fill.png new file mode 100644 index 000000000..2376e4351 Binary files /dev/null and b/salon_operation/static/description/auto_fill.png differ diff --git a/salon_operation/static/description/booked.png b/salon_operation/static/description/booked.png new file mode 100644 index 000000000..40b067c69 Binary files /dev/null and b/salon_operation/static/description/booked.png differ diff --git a/salon_operation/static/description/chair_under_conf.png b/salon_operation/static/description/chair_under_conf.png new file mode 100644 index 000000000..515737108 Binary files /dev/null and b/salon_operation/static/description/chair_under_conf.png differ diff --git a/salon_operation/static/description/chairs.png b/salon_operation/static/description/chairs.png new file mode 100644 index 000000000..1c11eeef3 Binary files /dev/null and b/salon_operation/static/description/chairs.png differ diff --git a/salon_operation/static/description/icon.png b/salon_operation/static/description/icon.png new file mode 100644 index 000000000..6427c2d53 Binary files /dev/null and b/salon_operation/static/description/icon.png differ diff --git a/salon_operation/static/description/index.html b/salon_operation/static/description/index.html new file mode 100644 index 000000000..4d16297f1 --- /dev/null +++ b/salon_operation/static/description/index.html @@ -0,0 +1,129 @@ +
+
+

Schedule days for salon

+

Handling more than one chair.

+ +
+ ☛ Create chairs. +
+
+
+
+
+ +
+
+ + +
+
+ +
+
+
+
+
+ ☛ Click Times menu to create Periods for a day. +
+
+
+
+
+ +
+
+ +
+
+
+ ☛ Schedule a Month using Auto-Filled Month . + It generates a month that filled days, period and chairs automatically. +
+
+
+
+
+ +
+
+
+ +
+
+ ☛ Go to Schedule month menu, you can edit days, time and chair.
+
+
+
+
+ +
+
+
+
+
+ ☛ Mark to identify the month is fully booked.
+
+
+
+
+ +
+
+
+ + +
+
+ ☛ 'Schedule booking' menu to perform the booking. + After adding month, days, time, and chair click confirm button.
+ To see booked, go to the corresponding month, day, time and chair +
+
+
+
+
+ +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
diff --git a/salon_operation/static/description/month.png b/salon_operation/static/description/month.png new file mode 100644 index 000000000..735c391fc Binary files /dev/null and b/salon_operation/static/description/month.png differ diff --git a/salon_operation/static/description/month_booked.png b/salon_operation/static/description/month_booked.png new file mode 100644 index 000000000..86aa98cec Binary files /dev/null and b/salon_operation/static/description/month_booked.png differ diff --git a/salon_operation/static/description/schedule_month.png b/salon_operation/static/description/schedule_month.png new file mode 100644 index 000000000..9e00a4a82 Binary files /dev/null and b/salon_operation/static/description/schedule_month.png differ diff --git a/salon_operation/static/src/img/calendar.jpg b/salon_operation/static/src/img/calendar.jpg new file mode 100644 index 000000000..59cc8d3e9 Binary files /dev/null and b/salon_operation/static/src/img/calendar.jpg differ diff --git a/salon_operation/static/src/img/calendar_icon.png b/salon_operation/static/src/img/calendar_icon.png new file mode 100644 index 000000000..9ce6ad054 Binary files /dev/null and b/salon_operation/static/src/img/calendar_icon.png differ diff --git a/salon_operation/static/src/img/tick_gray.png b/salon_operation/static/src/img/tick_gray.png new file mode 100644 index 000000000..939890567 Binary files /dev/null and b/salon_operation/static/src/img/tick_gray.png differ diff --git a/salon_operation/static/src/img/tick_green_001.png b/salon_operation/static/src/img/tick_green_001.png new file mode 100644 index 000000000..b8cbbb0b9 Binary files /dev/null and b/salon_operation/static/src/img/tick_green_001.png differ diff --git a/salon_operation/static/src/js/salon.js b/salon_operation/static/src/js/salon.js new file mode 100644 index 000000000..a1f35bbee --- /dev/null +++ b/salon_operation/static/src/js/salon.js @@ -0,0 +1,5 @@ +$(document).ready(function () { + + +}); + diff --git a/salon_operation/sweep/__init__.py b/salon_operation/sweep/__init__.py new file mode 100644 index 000000000..c29f17713 --- /dev/null +++ b/salon_operation/sweep/__init__.py @@ -0,0 +1 @@ +import sweep \ No newline at end of file diff --git a/salon_operation/sweep/sweep.py b/salon_operation/sweep/sweep.py new file mode 100644 index 000000000..821110a78 --- /dev/null +++ b/salon_operation/sweep/sweep.py @@ -0,0 +1,25 @@ +from openerp import models, fields,api,http,SUPERUSER_ID + + +class ProductTemplate(models.Model): + _inherit = 'product.template' + + type = fields.Selection([('consu', 'Consumable'), + ('service', 'Service')], + 'Product Type', + required=True, + help="Consumable are product where you don't manage stock, a service is a non-material product provided by a company or an individual.", + default='service') + + +class SaleAdvancePaymentInv(models.Model): + _inherit = "sale.advance.payment.inv" + + advance_payment_method =fields.Selection( + [('all', 'Invoice the whole Booking'), ('percentage','Percentage'), ('fixed','Fixed price (deposit)'), + ('lines', 'Some Booking lines')], + 'What do you want to invoice?', required=True, + help="""Use Invoice the whole sale order to create the final invoice. + Use Percentage to invoice a percentage of the total amount. + Use Fixed Price to invoice a specific amound in advance. + Use Some Order Lines to invoice a selection of the sales order lines.""") \ No newline at end of file diff --git a/salon_operation/sweep/sweep_invoice.xml b/salon_operation/sweep/sweep_invoice.xml new file mode 100644 index 000000000..0daa41ddf --- /dev/null +++ b/salon_operation/sweep/sweep_invoice.xml @@ -0,0 +1,17 @@ + + + + + + account.invoice.form.inherited + account.invoice + + + + Service + + + + + + diff --git a/salon_operation/sweep/sweep_menu_act.xml b/salon_operation/sweep/sweep_menu_act.xml new file mode 100644 index 000000000..cba4c7371 --- /dev/null +++ b/salon_operation/sweep/sweep_menu_act.xml @@ -0,0 +1,87 @@ + + + + + + + + Services + + + + + + + + + + + + + Schedule Booking + + + Schedule Booking + + + + + + + Services + + + + Services + + + Services + + + + + + + + Service Variants + + + Service Variants + {"search_default_filter_to_sell":1, "search_default_filter_services":1} + + + + + By Category + + + By Category + + + + + + + + Invisible (Developer must keep empty users) + + + + + + + + + + + + + + \ No newline at end of file diff --git a/salon_operation/sweep/sweep_product.xml b/salon_operation/sweep/sweep_product.xml new file mode 100644 index 000000000..fe161c17a --- /dev/null +++ b/salon_operation/sweep/sweep_product.xml @@ -0,0 +1,38 @@ + + + + + + product.template.search + product.template + + + + + + + + + + + + + + + + + + + + + + + {"search_default_filter_to_sell":1,"search_default_filter_services":1} + + + + + \ No newline at end of file diff --git a/salon_operation/sweep/sweep_sale_order.xml b/salon_operation/sweep/sweep_sale_order.xml new file mode 100644 index 000000000..8a37df5d7 --- /dev/null +++ b/salon_operation/sweep/sweep_sale_order.xml @@ -0,0 +1,214 @@ + + + + + + sale.order.form.inherited.sweep + sale.order + + + + Confirm + + + Cancel + + + New Copy + + + Cancel + + + Cancel + + + + +

+

+
+ + + Booking Items + + + + Service + + + + 1 + + +
+
+ + + sale.order.tree + sale.order + 1 + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ diff --git a/salon_operation/templates/template.xml b/salon_operation/templates/template.xml new file mode 100644 index 000000000..633b73fee --- /dev/null +++ b/salon_operation/templates/template.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/salon_operation/views/autofill_month.xml b/salon_operation/views/autofill_month.xml new file mode 100644 index 000000000..147428ad2 --- /dev/null +++ b/salon_operation/views/autofill_month.xml @@ -0,0 +1,56 @@ + + + + + + salon.month.form.auto + salon.auto_fill.wizard + +
+ + + + + + + + + + + +

+ Click the button 'Schedule' to generate a month that filled automatically. +

+
+ + +
+
+
+
+
+
+
+ + + Auto-Filled Month + salon.auto_fill.wizard + form + form + new + + + + +
+
\ No newline at end of file diff --git a/salon_operation/views/chair_view.xml b/salon_operation/views/chair_view.xml new file mode 100644 index 000000000..3845c2fd0 --- /dev/null +++ b/salon_operation/views/chair_view.xml @@ -0,0 +1,79 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + salon.chair.tree + salon.chair + + + + + + + + + + salon.chair.form + salon.chair + +
+ + + + + + + + + + +
+
+
+ + + Chairs + ir.actions.act_window + salon.chair + form + tree,form + {} + [] + +

+ Click to create a new chair. +

+
+
+ + +
+
+ diff --git a/salon_operation/views/day_view.xml b/salon_operation/views/day_view.xml new file mode 100644 index 000000000..b76c39c59 --- /dev/null +++ b/salon_operation/views/day_view.xml @@ -0,0 +1,86 @@ + + + + + + salon.day.tree + salon.day + + + + + + + + + + + salon.day.form + salon.day + +
+ + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ diff --git a/salon_operation/views/month_view.xml b/salon_operation/views/month_view.xml new file mode 100644 index 000000000..c55174f66 --- /dev/null +++ b/salon_operation/views/month_view.xml @@ -0,0 +1,137 @@ + + + + + + salon.month.kanban + salon.month + + + + + + + + +
+
+
+
+
+ + + + +
+
+

+ +

+ + + + + + +
+
+
+
+ +
+
+
+
+
+
+
+ + + salon.month.tree + salon.month + + + + + + + + + + + salon.month.form + salon.month + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Schedule Month + ir.actions.act_window + salon.month + form + kanban,tree,form + {} + [] + +

+ Click to create a new month. +

+
+
+ + + + + + + + + + + + + + + + + +
+
+ diff --git a/salon_operation/views/period_view.xml b/salon_operation/views/period_view.xml new file mode 100644 index 000000000..ad0d834be --- /dev/null +++ b/salon_operation/views/period_view.xml @@ -0,0 +1,112 @@ + + + + + + salon.period.tree + salon.period + + + + + + + + + + + salon.period.form + salon.period + +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + + Times + ir.actions.act_window + salon.period + form + tree,form + {} + [('day_id', '=', None)] + +

+ Click to create a new period. +

+
+
+ + + + + + + + + + + + + + + + + + + + salon.period.form + salon.period.line + +
+ + + + + + + + + + + + + +
+
+
+ +
+
+ diff --git a/salon_operation/views/salon_book_view.xml b/salon_operation/views/salon_book_view.xml new file mode 100644 index 000000000..99fd83375 --- /dev/null +++ b/salon_operation/views/salon_book_view.xml @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + sale.order.form.inherited.book + sale.order + + + + + + + + + + + +
+
+
+
+
+ + + +
+
+ + + Sales Orders + ir.actions.act_window + sale.order + form + tree,form + + {} + + [] + +

+ Click to schedule +

+
+
+
+
\ No newline at end of file