Rodney Enciso Arias пре 7 година
комит
7dbb709f22

+ 23 - 0
__init__.py

@@ -0,0 +1,23 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Cybrosys Technologies Pvt. Ltd.
+#    Copyright (C) 2008-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
+#    Author: Nilmar Shereef(<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 models


+ 30 - 0
__openerp__.py

@@ -0,0 +1,30 @@
+# -*- coding: utf-8 -*-
+{
+    'name': 'Eiru Base for Services',
+    'version': '8.0.1.1.0',
+    'summary': 'Base for services Operations',
+    'description': 'Vehicle workshop operations & Its reports',
+    'category': 'Industries',
+    'author': 'Cybrosys Techno Solutions - Eiru',
+    'company': 'Cybrosys Techno Solutions - Eiru',
+    'website': "http://www.eiru.com.py",
+    'depends': ['base',
+                'account_accountant'],
+    'data': [
+        'views/worksheet_views.xml',
+        'views/car_dashboard.xml',
+        'views/timesheet_view.xml',
+        'views/worksheet_stages.xml',
+        'views/vehicle.xml',
+        # 'views/report.xml',
+        'views/config_setting.xml',
+        'views/workshop_data.xml',
+        # 'security/workshop_security.xml',
+        # 'security/ir.model.access.csv',
+    ],
+    # 'images': ['static/description/banner.jpg'],
+    'license': 'AGPL-3',
+    'installable': True,
+    'auto_install': False,
+    'application': True,
+}

+ 26 - 0
models/__init__.py

@@ -0,0 +1,26 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Cybrosys Technologies Pvt. Ltd.
+#    Copyright (C) 2008-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
+#    Author: Nilmar Shereef(<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 car_workshop
+import timesheet
+import dashboard
+import config

BIN
models/__init__.pyc


+ 361 - 0
models/car_workshop.py

@@ -0,0 +1,361 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Cybrosys Technologies Pvt. Ltd.
+#    Copyright (C) 2008-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
+#    Author: Nilmar Shereef(<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 dateutil.relativedelta import relativedelta
+from openerp import models, api, fields, _
+from openerp.osv import osv
+
+
+class CarWorkshop(models.Model):
+    _name = 'car.workshop'
+    _inherit = ['mail.thread']
+
+    name = fields.Char(string='Title', track_visibility='onchange', required=True)
+    vehicle_id = fields.Many2one('car.car', string='Vehicle', track_visibility='onchange')
+    user_id = fields.Many2one('res.users', string='Assigned to', select=True)
+    active = fields.Boolean('Active')
+    partner_id = fields.Many2one('res.partner', string='Customer')
+    priority = fields.Selection([('0', 'Normal'), ('1', 'High')], string='Priority', select=True)
+    description = fields.Html('Description')
+    sequence = fields.Integer(string='Sequence', select=True, help="Gives the sequence order when displaying a list of tasks.")
+    tag_ids = fields.Many2many('worksheet.tags', string='Tags')
+    kanban_state = fields.Selection(
+        [('normal', 'In Progress'), ('done', 'Ready for next stage'), ('blocked', 'Blocked')], string='Kanban State',
+        help="A task's kanban state indicates special situations affecting it:\n"
+             " * Normal is the default situation\n"
+             " * Blocked indicates something is preventing the progress of this task\n"
+             " * Ready for next stage indicates the task is ready to be pulled to the next stage",
+        required=True, track_visibility='onchange', copy=False)
+    create_date = fields.Datetime(string='Create Date', readonly=True, select=True)
+    write_date = fields.Datetime(string='Last Modification Date', readonly=True, select=True)
+    date_start = fields.Datetime(string='Starting Date', select=True, copy=False)
+    date_end = fields.Datetime(string='Ending Date', select=True, copy=False)
+    date_assign = fields.Datetime(string='Assigning Date', select=True, copy=False, readonly=True)
+    date_deadline = fields.Datetime(string='Deadline', select=True, copy=False)
+    progress = fields.Integer(string="Working Time Progress(%)", copy=False, readonly=True)
+    date_last_stage_update = fields.Datetime(string='Last Stage Update', select=True, copy=False, readonly=True)
+    id = fields.Integer(string='ID', readonly=True)
+    color = fields.Integer(string='Color Index')
+    company_id = fields.Many2one('res.company', string='Company',
+                                 default=lambda self: self.env['res.company']._company_default_get('car.workshop'))
+    stage_id = fields.Many2one('worksheet.stages', string='Stage', track_visibility='onchange', copy=False)
+    state = fields.Selection([
+        ('waiting', 'Ready'),
+        ('workshop_create_invoices', 'Invoiced'),
+        ('cancel', 'Invoice Canceled'),
+    ], string='Status', readonly=True, default='waiting', track_visibility='onchange', select=True)
+    attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=lambda self: [('res_model', '=', self._name)],
+                                     auto_join=True, string='Attachments')
+    planned_works = fields.One2many('planned.work', 'work_id', string='Planned/Ordered Works')
+    works_done = fields.One2many('planned.work', 'work_id', string='Work Done', domain=[('completed', '=', True)])
+    materials_used = fields.One2many('material.used', 'material_id', string='Materials Used')
+    remaining_hour = fields.Float(string='Remaining Hour',readonly=True, compute="hours_left")
+    effective_hour = fields.Float(string='Hours Spent', readonly=True, compute="hours_spent")
+    amount_total = fields.Float(string='Total Amount', readonly=True, compute="amount_total1")
+
+    def _get_default_stages(self, cr, uid, context=None):
+        """ Gives default stage_id """
+        if context is None:
+            context = {}
+        default_vehicle_id = context.get('default_vehicle_id')
+        if not default_vehicle_id:
+            return False
+        return self.find_stage(cr, uid, [], default_vehicle_id, [('fold', '=', False)], context=context)
+
+    _defaults = {
+        'stage_id': 1,
+        'vehicle_id': lambda self, cr, uid, ctx=None: ctx.get('default_vehicle_id') if ctx is not None else False,
+        'date_last_stage_update': fields.datetime.now(),
+        'kanban_state': 'normal',
+        'priority': '0',
+        'sequence': 10,
+        'active': True,
+        'user_id': lambda obj, cr, uid, ctx=None: uid,
+        'partner_id': lambda self, cr, uid, ctx=None: self._get_default_vehicle(cr, uid, context=ctx),
+        'date_start': fields.datetime.now(),
+    }
+
+    @api.depends('planned_works.work_cost', 'materials_used.price')
+    def amount_total1(self):
+        for records in self:
+            for hour in records:
+                amount_totall = 0.0
+                for line in hour.planned_works:
+                    amount_totall += line.work_cost
+                for line2 in hour.materials_used:
+                    amount_totall += line2.price
+                records.amount_total = amount_totall
+
+    @api.multi
+    def cancel(self):
+        self.state = 'cancel'
+
+    @api.multi
+    def workshop_create_invoices(self):
+
+        self.state = 'workshop_create_invoices'
+        inv_obj = self.env['account.invoice']
+        inv_line_obj = self.env['account.invoice.line']
+        customer = self.partner_id
+        if not customer.name:
+            raise osv.except_osv(_('UserError!'), _('Please select a Customer.'))
+
+        company_id = self.env['res.users'].browse(1).company_id
+        currency_value = company_id.currency_id.id
+        self.ensure_one()
+        ir_values = self.env['ir.values']
+        journal_id = ir_values.get_default('workshop.config.setting', 'invoice_journal_type')
+        if not journal_id:
+            journal_id = 1
+        inv_data = {
+            'name': customer.name,
+            'reference': customer.name,
+            'account_id': customer.property_account_receivable.id,
+            'partner_id': customer.id,
+            'currency_id': currency_value,
+            'journal_id': journal_id,
+            'origin': self.name,
+            'company_id': company_id.id,
+        }
+        inv_id = inv_obj.create(inv_data)
+        for records in self.planned_works:
+            if records.planned_work.id:
+                income_account = records.planned_work.property_account_income.id
+            if not income_account:
+                raise osv.except_osv(_('UserError!'), _('There is no income account defined '
+                                                        'for this product: "%s".') % (records.planned_work.name,))
+            inv_line_data = {
+                'name': records.planned_work.name,
+                'account_id': income_account,
+                'price_unit': records.work_cost,
+                'quantity': 1,
+                'product_id': records.planned_work.id,
+                'invoice_id': inv_id.id,
+            }
+            inv_line_obj.create(inv_line_data)
+
+        for records in self.materials_used:
+            if records.material.id:
+                income_account = records.material.property_account_income.id
+            if not income_account:
+                raise osv.except_osv(_('UserError!'), _('There is no income account defined '
+                                                        'for this product: "%s".') % (records.material.name,))
+
+            inv_line_data = {
+                'name': records.material.name,
+                'account_id': records.material.property_account_income.id,
+                'price_unit': records.price,
+                'quantity': records.amount,
+                'product_id': records.material.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'}
+        invoiced_records = self.env['car.workshop']
+
+        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
+        print result
+        return result
+
+    @api.depends('works_done.duration')
+    def hours_spent(self):
+        for hour in self:
+            effective_hour = 0.0
+            for line in hour.works_done:
+                effective_hour += line.duration
+            self.effective_hour = effective_hour
+
+    @api.depends('planned_works.time_spent')
+    def hours_left(self):
+        for hour in self:
+            remaining_hour = 0.0
+            for line in hour.planned_works:
+                remaining_hour += line.time_spent
+            self.remaining_hour = remaining_hour-self.effective_hour
+
+    # def process_demo_scheduler_queue(self, cr, uid, context=None):
+    #     obj = self.pool.get('car.workshop')
+    #     obj1 = obj.search(cr, uid, [])
+    #     now = fields.Datetime.from_string(fields.Datetime.now())
+    #     for obj2 in obj1:
+    #         obj3 = obj.browse(cr, uid, obj2, context=context)
+    #         if obj3.stage_id.name != 'Done' and obj3.stage_id.name != 'Cancelled' and obj3.stage_id.name != 'Verified':
+    #             start_date = fields.Datetime.from_string(obj3.date_start)
+    #             end_date = fields.Datetime.from_string(obj3.date_deadline)
+    #             if obj3.date_deadline and end_date > start_date:
+    #                 if now < end_date:
+    #                     diff1 = relativedelta(end_date, start_date)
+    #                     if diff1.days == 0:
+    #                         total_hr = int(diff1.minutes)
+    #                     else:
+    #                         total_hr = int(diff1.days) * 24 * 60 + int(diff1.minutes)
+    #                     diff2 = relativedelta(now, start_date)
+    #                     if diff2.days == 0:
+    #                         current_hr = int(diff2.minutes)
+    #                     else:
+    #                         current_hr = int(diff2.days) * 24 * 60 + int(diff2.minutes)
+    #                     if total_hr != 0:
+    #                         obj3.progress = ((current_hr * 100) / total_hr)
+    #                     else:
+    #                         obj3.progress = 100
+    #                 else:
+    #                     obj3.progress = 100
+    #             else:
+    #                 obj3.progress = 0
+
+    def _track_subtype(self, cr, uid, ids, init_values, context=None):
+        record = self.browse(cr, uid, ids[0], context=context)
+        if 'kanban_state' in init_values and record.kanban_state == 'blocked':
+            return 'fleet_car_workshop.mt_task_blocked'
+        elif 'kanban_state' in init_values and record.kanban_state == 'done':
+            return 'fleet_car_workshop.mt_task_ready'
+        elif 'user_id' in init_values and record.user_id:  # assigned -> new
+            return 'fleet_car_workshop.mt_task_new'
+        elif 'stage_id' in init_values and record.stage_id and record.stage_id.sequence <= 1:  # start stage -> new
+            return 'fleet_car_workshop.mt_task_new'
+        elif 'stage_id' in init_values:
+            return 'fleet_car_workshop.mt_task_stage'
+        return super(CarWorkshop, self)._track_subtype(cr, uid, ids, init_values, context=context)
+
+    def create(self, cr, uid, vals, context=None):
+        context = dict(context or {})
+        if vals.get('vehicle_id') and not context.get('default_vehicle_id'):
+            context['default_vehicle_id'] = vals.get('vehicle_id')
+        if vals.get('user_id'):
+            vals['date_assign'] = fields.datetime.now()
+        create_context = dict(context, mail_create_nolog=True)
+        work_id = super(CarWorkshop, self).create(cr, uid, vals, context=create_context)
+        return work_id
+    #
+
+    def write(self, cr, uid, ids, vals, context=None):
+        if isinstance(ids, (int, long)):
+            ids = [ids]
+        if 'stage_id' in vals:
+            vals['date_last_stage_update'] = fields.datetime.now()
+            vals['date_assign'] = fields.datetime.now()
+        if vals and not'kanban_state' in vals and 'stage_id' in vals:
+            new_stage = vals.get('stage_id')
+            vals_reset_kstate = dict(vals, kanban_state='normal')
+            for t in self.browse(cr, uid, ids, context=context):
+                write_vals = vals_reset_kstate if t.stage_id.id != new_stage else vals
+                super(CarWorkshop, self).write(cr, uid, [t.id], write_vals, context=context)
+            result = True
+        else:
+            result = super(CarWorkshop, self).write(cr, uid, ids, vals, context=context)
+        return result
+
+    def _read_group_stages(self, cr, uid, ids, domain, read_group_order=None, access_rights_uid=None, context=None):
+        if context is None:
+            context = {}
+        stage_obj = self.pool.get('worksheet.stages')
+        order = stage_obj._order
+        access_rights_uid = access_rights_uid or uid
+        if read_group_order == 'stage_id desc':
+            order = '%s desc' % order
+        if 'default_vehicle_id' in context:
+            search_domain = ['|', ('vehicle_ids', '=', context['default_vehicle_id']), ('id', 'in', ids)]
+        else:
+            search_domain = [('id', 'in', ids)]
+        stage_ids = stage_obj._search(cr, uid, search_domain, order=order, access_rights_uid=access_rights_uid, context=context)
+        result = stage_obj.name_get(cr, access_rights_uid, stage_ids, context=context)
+        # restore order of the search
+        result.sort(lambda x, y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0])))
+
+        fold = {}
+        for stage in stage_obj.browse(cr, access_rights_uid, stage_ids, context=context):
+            fold[stage.id] = stage.fold or False
+        return result, fold
+
+    _group_by_full = {
+        'stage_id': _read_group_stages,
+    }
+
+    @api.cr_uid_ids_context
+    def onchange_vehicle(self, cr, uid, id, vehicle_id, context=None):
+        values = {}
+        if vehicle_id:
+            vehicle = self.pool.get('fleet.vehicle').browse(cr, uid, vehicle_id, context=context)
+            if vehicle.exists():
+                values['partner_id'] = vehicle.partner_id.id
+                values['stage_id'] = self.find_stage(cr, uid, [], vehicle_id, [('fold', '=', False)], context=context)
+        else:
+            values['stage_id'] = False
+        return {'value': values}
+
+    def _get_default_vehicle(self, cr, uid, context=None):
+        if context is None:
+            context = {}
+        if 'default_vehicle_id' in context:
+            vehicle = self.pool.get('car.car').browse(cr, uid, context['default_vehicle_id'], context=context)
+            if vehicle and vehicle.partner_id:
+                return vehicle.partner_id.id
+        return False
+
+    def find_stage(self, cr, uid, cases, section_id, domain=[], order='sequence', context=None):
+        if isinstance(cases, (int, long)):
+            cases = self.browse(cr, uid, cases, context=context)
+        section_ids = []
+        if section_id:
+            section_ids.append(section_id)
+        for task in cases:
+            if task.vehicle_id:
+                section_ids.append(task.vehicle_id.id)
+        search_domain = []
+        if section_ids:
+            search_domain = [('|')] * (len(section_ids) - 1)
+            for section_id in section_ids:
+                search_domain.append(('vehicle_ids', '=', section_id))
+        search_domain += list(domain)
+        # perform search, return the first found
+        stage_ids = self.pool.get('worksheet.stages').search(cr, uid, search_domain, order=order, context=context)
+        if stage_ids:
+            return stage_ids[0]
+        return False

BIN
models/car_workshop.pyc


+ 95 - 0
models/config.py

@@ -0,0 +1,95 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Cybrosys Technologies Pvt. Ltd.
+#    Copyright (C) 2008-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
+#    Author: Nilmar Shereef(<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 openerp import fields, models, api
+from openerp.tools.translate import _
+
+
+class WorkshopSetting(models.Model):
+    _name = "workshop.config.setting"
+
+    invoice_journal_type = fields.Many2one('account.journal', string="Car Workshop Journal")
+
+    @api.multi
+    def execute(self):
+        return self.env['ir.values'].sudo().set_default(
+            'workshop.config.setting', 'invoice_journal_type', self.invoice_journal_type.id)
+
+    def cancel(self, cr, uid, ids, context=None):
+        act_window = self.pool['ir.actions.act_window']
+        action_ids = act_window.search(cr, uid, [('res_model', '=', self._name)])
+        if action_ids:
+            return act_window.read(cr, uid, action_ids[0], [], context=context)
+        return {}
+
+
+class WorksheetTags(models.Model):
+
+    _name = "worksheet.tags"
+    _description = "Tags of vehicles's tasks, issues..."
+
+    name = fields.Char(string='Name', required=True)
+    color = fields.Integer(string='Color Index')
+
+    _sql_constraints = [
+            ('name_uniq', 'unique (name)', "Tag name already exists !"),
+    ]
+
+
+class WorksheetStages(models.Model):
+    _name = 'worksheet.stages'
+    _description = 'worksheet Stage'
+    _order = 'sequence'
+
+    name = fields.Char(string='Stage Name', required=True)
+    description = fields.Text(string='Description', translate=True)
+    sequence = fields.Integer(string='Sequence')
+    vehicle_ids = fields.Many2many('car.car', 'worksheet_type_rel', 'type_id', 'vehicle_id', string='Vechicles')
+    fold = fields.Boolean('Folded in Tasks Pipeline', help='This stage is folded in the kanban view when'
+                                'there are no records in that stage to display.')
+
+    def _get_default_vehicle_ids(self, cr, uid, ctx=None):
+        if ctx is None:
+            ctx = {}
+        default_vehicle_id = ctx.get('default_vehicle_id')
+        return [default_vehicle_id] if default_vehicle_id else None
+
+    _defaults = {
+        'sequence': 1,
+        'vehicle_ids': _get_default_vehicle_ids,
+    }
+    _order = 'sequence'
+
+
+class Services(models.Model):
+    _inherit = 'product.template'
+
+    type = fields.Selection([('consu', _('Consumable')), ('service', _('Service')),
+                             ('product', _('Stockable Product'))],
+                            string='Product Type', required=True,
+                            help="A consumable is a product for which you don't manage stock,"
+                                 " a service is a non-material product provided by a company or an individual.")
+
+    _defaults = {
+        'type': 'service',
+
+    }

BIN
models/config.pyc


+ 74 - 0
models/dashboard.py

@@ -0,0 +1,74 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Cybrosys Technologies Pvt. Ltd.
+#    Copyright (C) 2008-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
+#    Author: Nilmar Shereef(<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 openerp.tools.translate import _
+from openerp.osv import fields, osv
+
+
+class CarVehicle(osv.osv):
+    _name = 'car.car'
+    _inherit = ['mail.thread']
+
+    def get_task_count(self, cr, uid, ids, field_name, arg, context=None):
+        if context is None:
+            context = {}
+        res = {}
+        for vehicle in self.browse(cr, uid, ids, context=context):
+            res[vehicle.id] = len(vehicle.task_ids)
+        return res
+
+    _columns = {
+        'active': fields.boolean(string='Active'),
+        'name': fields.integer(string='Vehicle Name', required=True),
+        'sequence': fields.integer(string='Sequence', help="Gives the sequence order when displaying a list of Projects."),
+
+        'label_tasks': fields.char(string='Use Tasks as', help="Gives label to tasks on project's kanban view."),
+        'worksheet': fields.one2many('car.workshop', 'vehicle_id', string="Task Activities"),
+
+        'type_ids': fields.many2many('worksheet.stages', 'car_workshop_type_rel', 'vehicle_id',
+                                     'type_id', 'Worksheet Stages',
+                                     states={'close': [('readonly', True)], 'cancelled': [('readonly', True)]}),
+        'task_count': fields.function(get_task_count, type='integer', string="Tasks", ),
+        'task_ids': fields.one2many('car.workshop', 'vehicle_id',
+                                    domain=['|', ('stage_id.fold', '=', False), ('stage_id', '=', False)]),
+        'color': fields.integer('Color Index'),
+        'partner_id':  fields.many2one('res.partner', 'Customer'),
+
+        'state': fields.selection([('draft', 'Nuevo'),
+                                   ('open', 'En progreso'),
+                                   ('cancelled', 'Cancelado'),
+                                   ('pending', 'Pendiente'),
+                                   ('close', 'Cerrado')],
+                                  string='Status', required=True, track_visibility='onchange', copy=False),
+
+        'date_start': fields.date(string='Start Date'),
+        'date': fields.date(string='Expiration Date', select=True, track_visibility='onchange'),
+        'use_tasks': fields.boolean(string='Tasks'),
+        'image_medium': fields.binary('Binary File'),
+        }
+
+    _defaults = {
+        'active': True,
+        'use_tasks': True,
+        'label_tasks': 'Trabajos',
+        'state': 'open',
+    }

BIN
models/dashboard.pyc


+ 54 - 0
models/timesheet.py

@@ -0,0 +1,54 @@
+# -*- coding: utf-8 -*-
+##############################################################################
+#
+#    Cybrosys Technologies Pvt. Ltd.
+#    Copyright (C) 2008-TODAY Cybrosys Technologies(<http://www.cybrosys.com>).
+#    Author: Nilmar Shereef(<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 openerp import fields, models, api
+
+
+class PlannedWork (models.Model):
+    _name = 'planned.work'
+
+    planned_work = fields.Many2one('product.template', string='Planned work', domain=[('type', '=', 'service')])
+    time_spent = fields.Float(string='Estimated Time')
+    work_date = fields.Datetime(string='Date')
+    responsible = fields.Many2one('res.users', string='Responsible')
+    work_id = fields.Many2one('car.workshop', string="Work id")
+    work_cost = fields.Float(string="Service Cost")
+    completed = fields.Boolean(string="Completed")
+    duration = fields.Float(string='Duration')
+    work_date2 = fields.Datetime(string='Date')
+
+    @api.onchange('planned_work')
+    def get_price(self):
+        self.work_cost = self.planned_work.lst_price
+
+
+class MaterialUsed (models.Model):
+    _name = 'material.used'
+
+    material = fields.Many2one('product.template', string='Productos')
+    amount = fields.Integer(string='Cantidad')
+    price = fields.Float(string='Precio Unitario')
+    material_id = fields.Many2one(string='car.workshop')
+
+    @api.onchange('material')
+    def get_price(self):
+        self.price = self.material.lst_price

BIN
models/timesheet.pyc


+ 63 - 0
static/src/css/vehicles.css

@@ -0,0 +1,63 @@
+.oe_kanban_project {
+    width: 220px;
+    min-height: 160px;
+}
+
+.oe_kanban_project_list > a > span:hover{
+    margin: 4px 0;
+    text-decoration: underline;
+}
+
+.openerp .oe_kanban_content h4 {
+    margin: 0 0 8px;
+}
+
+.oe_kanban_content > table {
+    width: 100%;
+}
+
+.oe_kanban_content > table > th {
+    padding: 0;
+    border-right: 1px solid #DDD;
+    vertical-align: top;
+    font-weight: normal;
+}
+
+.oe_kanban_content > table > td {
+    padding: 2px 0 2px 8px;
+    color: #888;
+}
+
+.oe_kanban_content .oe_ellipsis {
+    overflow: hidden;
+    text-overflow: ellipsis;
+    max-height: 100px;
+}
+
+.oe_kanban_project_fields div:nth-child(odd) {
+    border-right: 1px solid #dddddd;
+    vertical-align: top;
+    padding-right: 8px;
+}
+
+.oe_kanban_project_fields div:nth-child(even) {
+    padding-left: 8px;
+    color: #888888;
+}
+
+.oe_kanban_project_avatars {
+    margin-top: 8px;
+}
+
+.oe_kanban_project_avatars img {
+    width: 30px;
+    height: 30px;
+    padding-left: 0px;
+    margin-top: 3px;
+    -moz-border-radius: 2px;
+    -webkit-border-radius: 2px;
+    border-radius: 2px;
+    -moz-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+    -webkit-box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+    -box-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
+}

+ 98 - 0
static/src/less/car_dashboard.less

@@ -0,0 +1,98 @@
+.o_kanban_view.o_kanban_dashboard.o_project_kanban {
+
+    .o_kanban_record {
+        .o-flex-display();
+        position: relative;
+    }
+
+    .o_project_kanban_main {
+        .o-flex(0, 0, auto);
+        padding: @odoo-horizontal-padding;
+        width: 70%; // for IE11 overflow issue
+
+        // give space for manage section at the bottom
+        margin-bottom: @odoo-horizontal-padding/2 + 19px;
+
+        .o_kanban_card_content {
+            font-size: 12px;
+            .o_primary {
+                font-size: larger;
+            }
+        }
+
+        .o_project_kanban_manage {
+            .o-position-absolute(@bottom: 0, @left: 0);
+            padding: @odoo-horizontal-padding/2 @odoo-horizontal-padding;
+        }
+        .o_kanban_card_manage_pane .o_kanban_card_manage_title {
+            margin: 0;
+        }
+    }
+
+    .o_project_kanban_boxes {
+        width: 30%;
+        .o-flex(0, 0, auto);
+
+        .o-flex-display();
+        .o-flex-flow(column, nowrap);
+
+        > a:hover {
+            text-decoration: none;
+        }
+
+        .o_value {
+            font-size: x-large;
+            color: white;
+            display: block;
+        }
+        .o_label {
+            color: white;
+        }
+        .o_needaction{
+            position: absolute;
+            top: 5px;
+            right: 5px;
+            color: white;
+            font-size: small;
+            opacity: 0.5;
+            &:hover{
+                opacity:1;
+            }
+            &::before {
+                content: "\f086";
+                font: normal normal normal 14px/1 FontAwesome;
+            }
+        }
+
+        .o_project_kanban_box {
+            position: relative;
+            text-align: center;
+            padding: 15px 0 15px 0;
+            .o-flex(1, 1, auto);
+            .o-flex-display();
+            .o-align-items(center);
+            .o-flex-flow(column, nowrap);
+            .o-justify-content(center);
+        }
+        .o_project_kanban_box:nth-child(even) {
+            background-color: grey;
+        }
+        .o_project_kanban_box:nth-child(odd) {
+            background-color: @odoo-brand-optional;
+        }
+    }
+}
+
+.o_kanban_task_cover_image {
+    .o-columns(200px, 4);
+    > img {
+        cursor: pointer;
+        margin-bottom: 1em;
+        border: 1px solid transparent;
+
+        &.o_selected {
+            border-color: @odoo-brand-secondary;
+            box-shadow: 0px 0px 2px 2px @odoo-brand-secondary;
+        }
+    }
+}

+ 134 - 0
views/car_dashboard.xml

@@ -0,0 +1,134 @@
+<openerp>
+    <data>
+        <record id="car_car_form" model="ir.ui.view">
+            <field name="name">car.car.form</field>
+            <field name="model">car.car</field>
+            <field name="arch" type="xml">
+                <form string="Vehicle">
+                    <header>
+                        <field name="state" widget="statusbar" clickable="True" attrs="{'invisible': [('state','=', 'close')]}"/>
+                        <!-- <field name="state" widget="statusbar" attrs="{'invisible': [('state','!=', 'close')]}"/> -->
+                    </header>
+                    <sheet>
+                        <field name="image_medium" widget='image' class="oe_avatar oe_left" attrs="{'readonly': [('state','=', 'close')]}"/>
+                        <div class="oe_title">
+                            <h1>
+                                <field name="name"/>
+                            </h1>
+                            <div>
+                                <field name="use_tasks" class="oe_inline" attrs="{'readonly': [('state','=', 'close')]}"/>
+                                <label for="use_tasks" class="oe_inline" string="Usar tareas"/>
+                                <span attrs="{'invisible':[('use_tasks', '=', False)]}">como </span>
+                                <field name="label_tasks" class="oe_inline oe_input_align" attrs="{'invisible': [('use_tasks', '=', False)],'readonly': [('state','=', 'close')]}"/>
+                            </div>
+                        </div>
+                        <div class="oe_right oe_button_box" name="buttons" groups="base.group_user">
+                            <button class="oe_stat_button"
+                                    icon="fa-tasks"
+                                    name="%(eiru_base_for_services.worksheet_action_super_button)d"
+                                    type="action">
+                               <field string="Tareas" name="task_count" widget="statinfo" />
+                           </button>
+                       </div>
+                        <notebook>
+                            <page string="Configuración">
+                                <group>
+                                    <group>
+                                        <field name="partner_id" string="Cliente" domain="[('customer', '=', True)]" attrs="{'readonly': [('state','=', 'close')]}"/>
+                                    </group>
+                                    <group name="extra_info">
+
+                                    </group>
+                                </group>
+                            </page>
+                        </notebook>
+                    </sheet>
+                </form>
+            </field>
+        </record>
+
+        <record id="view_car_car_filter" model="ir.ui.view">
+            <field name="name">car.car.select</field>
+            <field name="model">car.car</field>
+            <field name="arch" type="xml">
+                <search string="Search Vehicle">
+                    <field name="name" string="Nombre"/>
+                    <filter string="Abierto" name="Current" domain="[('state', '=','open')]"/>
+                    <filter string="Pendiente" name="Pending" domain="[('state', '=','pending')]"/>
+                    <separator/>
+                    <separator/>
+                    <group expand="0" string="Agrupar por ">
+                        <filter string="Cliente" name="Partner" context="{'group_by':'partner_id'}"/>
+                    </group>
+                </search>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="view_car_car_kanban">
+        <field name="name">car.car.kanban</field>
+        <field name="model">car.car</field>
+        <field name="arch" type="xml">
+            <kanban class="oe_background_grey">
+                <field name="name"/>
+                <field name="use_tasks"/>
+                <field name="color"/>
+                <field name="task_count"/>
+                <field name="label_tasks"/>
+                <field name="task_ids"/>
+                <templates>
+                    <t t-name="kanban-box">
+                        <div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_project oe_kanban_global_click">
+                            <div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
+                                <span class="oe_e">í</span>
+                                <ul class="oe_dropdown_menu">
+                                    <t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Configurar</a></li></t>
+                                    <li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
+                                </ul>
+                            </div>
+                            <div class="oe_kanban_content">
+                                <h4 class="text-center"><strong><field name="name"/></strong></h4>
+                                <div class="o_kanban_image text-center image_kanban_project">
+                                    <img t-att-src="kanban_image('car.car', 'image_medium', record.id.value)" style="width:80%;"/>
+                                </div>
+                                <div class="oe_kanban_project_list">
+                                    <div t-if="record.use_tasks.raw_value" class="o_project_kanban_box">
+                                        <a name="%(eiru_base_for_services.worksheet_action_super_button)d" type="action" style="margin-right: 10px">
+                                            <t t-raw="record.task_count.raw_value"/><t t-raw="record.label_tasks.raw_value" />
+                                        </a>
+                                    </div>
+                                </div>
+                            </div>
+                        </div>
+                    </t>
+                </templates>
+            </kanban>
+        </field>
+        </record>
+
+        <record id="view_car_car_tree" model="ir.ui.view">
+            <field name="name">car.car.tree</field>
+            <field name="model">car.car</field>
+            <field name="field_parent">child_ids</field>
+            <field name="arch" type="xml">
+                <tree  decoration-info="state in ('draft','pending')" decoration-muted="state in ('close','cancelled')" string="Vehicles">
+                    <field name="name" string="Nombre del vehiculo"/>
+                     <field name="partner_id" string="Cliente"/>
+                    <field name="state" string="Estado"/>
+                </tree>
+            </field>
+        </record>
+
+        <record id="open_view_vehicle_all" model="ir.actions.act_window">
+            <field name="name">Proyectos</field>
+            <field name="res_model">car.car</field>
+            <field name="view_type">form</field>
+            <field name="domain">[]</field>
+            <field name="view_mode">kanban,form</field>
+            <field name="search_view_id" ref="view_car_car_filter"/>
+            <field name="context">{'search_default_Current': 1}</field>
+        </record>
+
+        <menuitem name="Panel de Control" parent="main_workshop_menu" id="workshop_vehicles" sequence="1"/>
+        <menuitem name="Todos los proyectos" parent="workshop_vehicles" id="workshop_all_vehicles" sequence="1" action="open_view_vehicle_all"/>
+    </data>
+</openerp>

+ 35 - 0
views/config_setting.xml

@@ -0,0 +1,35 @@
+<openerp>
+    <data>
+     <record id="view_workshop_config_settings" model="ir.ui.view">
+            <field name="name">workshop Configuración</field>
+            <field name="model">workshop.config.setting</field>
+            <field name="arch" type="xml">
+                <form string="Configure Workshop" class="oe_form_configuration">
+                    <header>
+                        <button string="Aplicar" type="object" name="execute" class="oe_highlight"/>
+                        <button string="Cancelar" type="object" name="cancel" class="oe_link"/>
+                    </header>
+
+                    <div id="main">
+                        <group string="Diario">
+                            <field name="invoice_journal_type" />
+                        </group>
+                    </div>
+                </form>
+            </field>
+        </record>
+
+        <record id="action_workshop_config_settings" model="ir.actions.act_window">
+            <field name="name">Configuración</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">workshop.config.setting</field>
+            <field name="view_id" ref="view_workshop_config_settings"/>
+            <field name="view_mode">form</field>
+            <field name="target">inline</field>
+        </record>
+
+
+        <!-- <menuitem action="action_workshop_config_settings" id="menu_workshop_config_settings_act"
+                    string="Configuración" sequence = "1" parent="menu_worksheet_config" /> -->
+    </data>
+</openerp>

+ 18 - 0
views/report.xml

@@ -0,0 +1,18 @@
+<openerp>
+    <data>
+    <record model="ir.actions.act_window" id="action_car_workshop_report">
+                <field name="name">Worksheets</field>
+                <field name="res_model">car.workshop</field>
+                <field name="view_mode">graph</field>
+                <field name="help" type="html">
+                    <p>
+                        Odoo's car workshop management allows you to manage the pipeline of your work efficiently. You can track progress, discuss on works, attach documents, etc.
+                    </p>
+                </field>
+            </record>
+
+
+        <!-- <menuitem name ="Report" id="report_worksheet" parent="main_workshop_menu" sequence="3"/>
+        <menuitem name ="Worksheet" id="vehicle_report" parent="report_worksheet" action="action_car_workshop_report"/> -->
+    </data>
+</openerp>

+ 53 - 0
views/timesheet_view.xml

@@ -0,0 +1,53 @@
+<openerp>
+    <data>
+        <record model="ir.ui.view" id="planned_work_form_view">
+            <field name="name">planned.work.form</field>
+            <field name="model">planned.work</field>
+            <field name="arch" type="xml">
+                <form string="Planned Work">
+                    <group>
+                        <group>
+                            <field name="planned_work" />
+                            <field name="time_spent" widget="float_time" />
+                        </group>
+                        <group>
+                            <field name="responsible"/>
+                            <field name="work_date"/>
+                            <field name="work_cost"/>
+                        </group>
+                    </group>
+                </form>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="material_used_form_view">
+            <field name="name">material.used.form</field>
+            <field name="model">material.used</field>
+            <field name="arch" type="xml">
+                <form string="Work Done">
+                    <group>
+                        <group>
+                            <field name="material" />
+                        </group>
+                        <group>
+                            <field name="amount"/>
+                            <field name="price"/>
+                        </group>
+                    </group>
+                </form>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="material_used_tree_view">
+            <field name="name">material.used.tree</field>
+            <field name="model">material.used</field>
+            <field name="arch" type="xml">
+                <tree string="Materials" editable="bottom">
+                    <field name="material" />
+                    <field name="amount"/>
+                    <field name="price"/>
+                </tree>
+            </field>
+        </record>
+    </data>
+</openerp>

+ 11 - 0
views/vehicle.xml

@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data>
+        <template id="assets_backend" name="vehicle assets" inherit_id="web.assets_backend">
+            <xpath expr="." position="inside">
+                <link rel="stylesheet" href="/eiru_base_for_services/static/src/css/vehicles.css"/>
+                <link rel="stylesheet" href="/eiru_base_for_services/static/src/less/car_dashboard.less"/>
+            </xpath>
+        </template>
+    </data>
+</openerp>

+ 89 - 0
views/worksheet_stages.xml

@@ -0,0 +1,89 @@
+<openerp>
+    <data>
+        <record id="worksheet_stages_form" model="ir.ui.view">
+            <field name="name">worksheet.stages.form</field>
+            <field name="model">worksheet.stages</field>
+            <field name="arch" type="xml">
+                <form string="Worksheet Stages">
+                    <group>
+                        <group>
+                            <field name="name" string="Nombre de la etapa"/>
+                            <field name="sequence" groups="base.group_no_one" string="Sequencia"/>
+                        </group>
+                        <group>
+                            <field name="fold" string="Replegado en la lista kanban"/>
+                        </group>
+                    </group>
+                    <group>
+                        <field name="description" placeholder="Agregar descripción" nolabel="1" colspan="2"/>
+                    </group>
+                    <!-- <group string="Vehiculos que utilizan este estado">
+                        <field name="vehicle_ids" widget="many2many_tags"/>
+                    </group> -->
+                </form>
+            </field>
+        </record>
+
+        <record id="worksheet_stages_tree" model="ir.ui.view">
+           <field name="name">worksheet.stages.tree</field>
+            <field name="model">worksheet.stages</field>
+            <field name="arch" type="xml">
+                <tree string="Estado de la tarea">
+                    <field name="sequence" widget="handle" groups="base.group_no_one"/>
+                    <field name="name" string="Nombre de la etapa"/>
+                    <field name="fold" string="Replegado en la vista Kanban"/>
+                    <field name="description" string="Descripción"/>
+                </tree>
+            </field>
+        </record>
+
+        <record id="worksheet_stages_action" model="ir.actions.act_window">
+            <field name="name">Etapas</field>
+            <field name="res_model">worksheet.stages</field>
+            <field name="view_type">form</field>
+        </record>
+
+         <record model="ir.ui.view" id="worksheet_tags_form_view">
+            <field name="name">Etiquetas</field>
+            <field name="model">worksheet.tags</field>
+            <field name="arch" type="xml">
+                <form string="Etiquetas">
+                    <group col="4">
+                        <field name="name" string="Nombre de la etiqueta"/>
+                    </group>
+                </form>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="worksheet_tags_tree_view">
+           <field name="name">Etiquetas</field>
+           <field name="model">worksheet.tags</field>
+           <field name="arch" type="xml">
+               <tree string="Estado de la tarea">
+                    <field name="name" string="Etiqueta"/>
+               </tree>
+           </field>
+       </record>
+
+        <record id="worksheet_tags_action" model="ir.actions.act_window">
+            <field name="name">Etiquetas</field>
+            <field name="res_model">worksheet.tags</field>
+            <field name="view_mode">tree,form</field>
+            <field name="view_type">form</field>
+        </record>
+
+        <record id="workshop_services" model="ir.actions.act_window">
+            <field name="name">Servicios</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">product.template</field>
+            <field name="view_mode">kanban,tree,form</field>
+            <field name="view_type">form</field>
+            <field name="domain">[('type','=','service')]</field>
+        </record>
+
+        <menuitem action="worksheet_tags_action" id="menu_worksheet_tags_act" parent="menu_worksheet_config" string="Etiquetas"/>
+        <menuitem action="worksheet_stages_action" id="menu_worksheet_stages_action" parent="menu_worksheet_config" string="Etapas"/>
+        <menuitem action="workshop_services" id="menu_workshop_product_services" parent="menu_worksheet_config" string="Servicios"/>
+
+    </data>
+</openerp>

+ 254 - 0
views/worksheet_views.xml

@@ -0,0 +1,254 @@
+<openerp>
+    <data>
+
+        <!-- <record id="ir_cron_scheduler_demo_action" model="ir.cron">
+            <field name="name">Demo scheduler</field>
+            <field name="user_id" ref="base.user_root"/>
+            <field name="interval_number">1</field>
+            <field name="interval_type">minutes</field>
+            <field name="numbercall">-1</field>
+            <field eval="False" name="doall"/>
+            <field eval="'car.workshop'" name="model"/>
+            <field eval="'process_demo_scheduler_queue'" name="function"/>
+        </record> -->
+
+        <record model="ir.ui.view" id="worksheet_form_view">
+            <field name="name">worksheet.form.view</field>
+            <field name="model">car.workshop</field>
+            <field name="arch" type="xml">
+                <form string="Worksheet">
+                    <header>
+                        <button name="workshop_create_invoices" string="Crear Factura" type="object"
+                            class="btn-primary" states="waiting"/>
+                        <button class="btn-primary" name="cancel" string="Cancelar" type="object" states="waiting"/>
+                        <field name="stage_id" widget="statusbar" clickable="True"/>
+                        <field name="state" widget="statusbar" invisible="1"/>
+                    </header>
+
+                    <sheet string="Hoja de Tarea">
+                        <field name="kanban_state" widget="kanban_state_selection" invisible="1"/>
+                        <div class="oe_title">
+                            <h1 class="o_row">
+                                <field name="name" placeholder="Titulo de la tarea" attrs="{'readonly': [('state','!=', 'waiting')]}"/>
+                            </h1>
+                        </div>
+                        <group>
+                            <group>
+                                <field name="vehicle_id" string="Proyecto" required="1" attrs="{'readonly': [('state','!=','waiting')]}" domain="[('state','=','open')]"/>
+                                <field name="user_id" string="Responsable" required="1" attrs="{'readonly': [('state','!=', 'waiting')]}"/>
+                            </group>
+                            <group>
+                                <field name="date_deadline" string="Fecha limite entrega" attrs="{'readonly': [('state','!=', 'waiting')]}"/>
+                                <field name="tag_ids" widget="many2many_tags" string="Etiquetas" attrs="{'readonly': [('state','!=', 'waiting')]}"/>
+                            </group>
+                        </group>
+                        <notebook>
+                            <page name="description_page" string="Descripción">
+                                <field name="description" type="html"/>
+                                <div class="oe_clear"/>
+                            </page>
+                            <page name="timesheet_page" string="Hoja de trabajo">
+                                <group string ="Trabajo Planeado">
+                                    <field name="planned_works" nolabel="1" attrs="{'readonly': [('state','!=', 'waiting')]}">
+                                        <tree string="Planned Work" editable="bottom">
+                                             <field name="planned_work" string="Trabajo"/>
+                                             <field name="time_spent" sum= "Estimated Time" widget="float_time" string="Tiempo Estimado"/>
+                                             <field name="work_date" string="Fecha de trabajo"/>
+                                             <field name="responsible" string="Responsable"/>
+                                             <field name="work_cost" string="Precio"/>
+                                             <field name="completed" string="¿El trabajo esta terminado?"/>
+                                        </tree>
+                                    </field>
+                                </group>
+                                <group string = "Trabajos terminados">
+                                    <field name="works_done" nolabel="1" attrs="{'readonly': [('state','!=', 'waiting')]}">
+                                        <tree string="Planned Work" editable="bottom">
+                                            <field name="planned_work" string="Trabajo"/>
+                                            <field name="duration" sum= "Estimated Time" widget="float_time" string="Duracion"/>
+                                            <field name="work_date2" string="Fecha de trabajo"/>
+                                            <field name="responsible" string="Responsable"/>
+                                            <field name="work_cost" string="Precio"/>
+                                        </tree>
+                                    </field>
+                                </group>
+                                <group string = "Materiales Utilizados">
+                                    <field name="materials_used" nolabel="1" attrs="{'readonly': [('state','=', 'workshop_create_invoices')]}"/>
+                                </group>
+                                <group>
+                                    <field name="amount_total" string="Monto Total"/>
+                                </group>
+                                 <group class="oe_subtotal_footer oe_right" name="project_hours">
+                                      <field name="effective_hour" widget="float_time" string="Horas Gastadas"/>
+                                      <field name ="remaining_hour" class="oe_subtotal_footer_separator" widget="float_time" string="Horas Restantes"/>
+                                </group>
+
+                            </page>
+                            <page string="Informacion Extra">
+                                <group col="4">
+                                    <group col="2">
+                                        <field name="partner_id" string="Cliente" required="1" attrs="{'readonly': [('state','!=', 'waiting')]}"/>
+                                        <field name="company_id" string="Empresa" required="1" attrs="{'readonly': [('state','!=', 'waiting')]}"/>
+                                    </group>
+                                    <group col="2">
+                                        <field name="date_assign" string="Fecha de creación"/>
+                                        <field name="date_last_stage_update" string="Fecha de cambio de etapa"/>
+                                    </group>
+                                </group>
+                            </page>
+                        </notebook>
+                    </sheet>
+                </form>
+            </field>
+        </record>
+
+         <record model="ir.ui.view" id="worksheet_tree_view">
+            <field name="name">worksheet.tree.view</field>
+            <field name="model">car.workshop</field>
+            <field name="arch" type="xml">
+                <tree string="Hoja de Trabajo">
+                    <field name="name" string="Titulo"/>
+                    <field name="vehicle_id" invisible="context.get('user_invisible', False)" string="Proyecto"/>
+                    <field name="user_id" invisible="context.get('user_invisible', False)" string="Asignado a"/>
+                    <field name="date_deadline" invisible="context.get('deadline_visible',True)"/>
+                    <field name="amount_total" string="Monto"/>
+                    <field name="stage_id" invisible="context.get('set_visible',False)" string="Etapa"/>
+                </tree>
+            </field>
+        </record>
+
+        <record model="ir.ui.view" id="car_workshop_view_kanban">
+            <field name="name">car.workshop.kanban</field>
+            <field name="model">car.workshop</field>
+            <field name="arch" type="xml">
+                <kanban default_group_by="stage_id" class="o_kanban_small_column">
+                    <field name="color"/>
+                    <field name="priority"/>
+                    <field name="stage_id" options='{"group_by_tooltip": {"description": "Stage Description", "legend_priority": "Use of stars"}}'/>
+                    <field name="user_id"/>
+                    <field name="description"/>
+                    <field name="sequence"/>
+                    <field name="date_deadline"/>
+                    <field name="tag_ids"/>
+                    <field name="attachment_ids"/>
+                    <field name="active"/>
+                    <templates>
+                         <t t-name="kanban-box">
+                        <div t-attf-class="oe_kanban_color_#{kanban_getcolor(record.color.raw_value)} oe_kanban_card oe_kanban_global_click">
+                            <div class="oe_dropdown_toggle oe_dropdown_kanban" groups="base.group_user">
+                                <span class="oe_e">í</span>
+                                <ul class="oe_dropdown_menu">
+                                    <t t-if="widget.view.is_action_enabled('edit')"><li><a type="edit">Edit...</a></li></t>
+                                    <t t-if="widget.view.is_action_enabled('delete')"><li><a type="delete">Delete</a></li></t>
+                                    <li>
+                                      <ul class="oe_kanban_project_times" groups="project.group_time_work_estimation_tasks">
+                                        <li><a name="set_remaining_time_1" type="object" class="oe_kanban_button">1</a></li>
+                                        <li><a name="set_remaining_time_2" type="object" class="oe_kanban_button">2</a></li>
+                                        <li><a name="set_remaining_time_5" type="object" class="oe_kanban_button">5</a></li>
+                                        <li><a name="set_remaining_time_10" type="object" class="oe_kanban_button">10</a></li>
+                                      </ul>
+                                    </li>
+                                    <br/>
+                                    <li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
+                                </ul>
+                            </div>
+
+                            <div class="oe_kanban_content">
+                                <div><b><field name="name"/></b></div>
+                                <div>
+                                    <field name="vehicle_id"/><br/>
+                                    <t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())" t-set="red">oe_kanban_text_red</t>
+                                    <span t-attf-class="#{red || ''}"><i><field name="date_deadline"/></i></span>
+                                </div>
+                                <div class="oe_kanban_bottom_right">
+                                    <img t-att-src="kanban_image('res.users', 'image_small', record.user_id.raw_value)" t-att-title="record.user_id.value" width="24" height="24" class="oe_kanban_avatar pull-right"/>
+                                </div>
+                            </div>
+                            <div class="oe_clear"></div>
+                        </div>
+                    </t>
+                    </templates>
+                </kanban>
+            </field>
+        </record>
+
+        <record id="worksheet_calender_view" model="ir.ui.view">
+            <field name="name">worksheet.calender.view</field>
+            <field name="model">car.workshop</field>
+            <field eval="2" name="priority"/>
+            <field name="arch" type="xml">
+                <calendar color="user_id" date_start="date_deadline" string="Tasks">
+                    <field name="name"/>
+                    <field name="vehicle_id"/>
+                </calendar>
+            </field>
+        </record>
+
+        <record id="view_car_workshop_pivot" model="ir.ui.view">
+            <field name="name">car.workshop.pivot</field>
+            <field name="model">car.workshop</field>
+            <field name="arch" type="xml">
+                 <graph string="Vehicles" type="pivot">
+                    <field name="vehicle_id" type="row"/>
+                    <field name="stage_id" type="col"/>
+                </graph>
+            </field>
+        </record>
+
+        <record id="view_car_workshop_graph" model="ir.ui.view">
+            <field name="name">car.workshop.graph</field>
+            <field name="model">car.workshop</field>
+            <field name="arch" type="xml">
+                <graph string="Project Tasks">
+                    <field name="vehicle_id"/>
+                    <field name="stage_id"/>
+                </graph>
+            </field>
+        </record>
+
+        <record model="ir.actions.act_window" id="worksheet_action_super_button">
+            <field name="name">Hoja de Trabajo</field>
+            <field name="res_model">car.workshop</field>
+            <field name="context">{'search_default_vehicle_id': active_id}</field>
+            <field name="view_mode">kanban,tree,form,calendar,graph</field>
+        </record>
+
+        <record id="view_vehicle_search_form" model="ir.ui.view">
+            <field name="name">car.workshop.search.form</field>
+            <field name="model">car.workshop</field>
+            <field name="arch" type="xml">
+               <search string="Worksheet">
+                    <field name="name" string="Tasks"/>
+                    <field name="tag_ids"/>
+                    <field name="partner_id"/>
+                    <field name="vehicle_id"/>
+                    <field name="user_id"/>
+                    <field name="stage_id"/>
+                    <filter string="Mi hoja de trabajo" domain="[('user_id','=',uid)]"/>
+                    <separator/>
+                    <filter string="Nuevo" name="draft" domain="[('stage_id.sequence', '&lt;=', 1)]"/>
+                    <separator/>
+                    <filter string="Archivados" name="inactive" domain="[('active','=',False)]"/>
+                    <group expand="0" string="Agrupar por ">
+                        <filter string="Vehiculo" name="vehicle" context="{'group_by':'vehicle_id'}"/>
+                        <filter string="Hoja de trabajo" context="{'group_by':'name'}"/>
+                        <filter string="Asignado a" name="User" context="{'group_by':'user_id'}"/>
+                        <filter string="Etapa" name="Stage" context="{'group_by':'stage_id'}"/>
+                        <separator/>
+                    </group>
+                </search>
+            </field>
+        </record>
+
+        <record model="ir.actions.act_window" id="action_car_workshop_filtered">
+            <field name="name">Hoja de tareas</field>
+            <field name="res_model">car.workshop</field>
+            <field name="view_mode">kanban,tree,form,calendar</field>
+        </record>
+
+        <menuitem id="main_workshop_menu" name="Operaciones" />
+        <menuitem name="Buscar" id="search_worksheet" parent="main_workshop_menu" sequence="2"/>
+        <menuitem name="Lista de tareas" id="vehicle_works" parent="search_worksheet" action="action_car_workshop_filtered"/>
+        <menuitem id="menu_worksheet_config" name="Configuración" parent="main_workshop_menu" sequence="4"/>
+
+    </data>
+</openerp>

+ 78 - 0
views/workshop_data.xml

@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="utf-8"?>
+<openerp>
+    <data noupdate="1">
+
+        <!-- Requests Links -->
+        <record id="req_link_car" model="res.request.link">
+            <field name="name">Car</field>
+            <field name="object">car.car</field>
+        </record>
+
+        <record id="req_link_worksheet" model="res.request.link">
+            <field name="name">Car Worksheet</field>
+            <field name="object">car.workshop</field>
+        </record>
+
+    </data>
+    <data>
+        <record id="mt_task_new" model="mail.message.subtype">
+            <field name="name">Task Opened</field>
+            <field name="res_model">car.workshop</field>
+            <field name="default" eval="False"/>
+            <field name="hidden" eval="False"/>
+            <field name="description">Task opened</field>
+        </record>
+        <record id="mt_task_blocked" model="mail.message.subtype">
+            <field name="name">Task Blocked</field>
+            <field name="res_model">car.workshop</field>
+            <field name="default" eval="False"/>
+            <field name="description">Task blocked</field>
+        </record>
+        <record id="mt_task_ready" model="mail.message.subtype">
+            <field name="name">Task Ready</field>
+            <field name="res_model">car.workshop</field>
+            <field name="default" eval="False"/>
+            <field name="description">Task ready for Next Stage</field>
+        </record>
+        <record id="mt_task_stage" model="mail.message.subtype">
+            <field name="name">Stage Changed</field>
+            <field name="res_model">car.workshop</field>
+            <field name="default" eval="False"/>
+            <field name="description">Stage changed</field>
+        </record>
+
+        <record id="mt_project_task_new" model="mail.message.subtype">
+            <field name="name">Task Opened</field>
+            <field name="sequence">10</field>
+            <field name="res_model">car.car</field>
+            <field name="default" eval="True"/>
+            <field name="parent_id" eval="ref('mt_task_new')"/>
+            <field name="relation_field">vehicle_id</field>
+        </record>
+        <record id="mt_project_task_blocked" model="mail.message.subtype">
+            <field name="name">Task Blocked</field>
+            <field name="sequence">11</field>
+            <field name="res_model">car.car</field>
+            <field name="default" eval="False"/>
+            <field name="parent_id" eval="ref('mt_task_blocked')"/>
+            <field name="relation_field">vehicle_id</field>
+        </record>
+        <record id="mt_project_task_ready" model="mail.message.subtype">
+            <field name="name">Task Ready</field>
+            <field name="sequence">12</field>
+            <field name="res_model">car.car</field>
+            <field name="default" eval="False"/>
+            <field name="parent_id" eval="ref('mt_task_ready')"/>
+            <field name="relation_field">vehicle_id</field>
+        </record>
+        <record id="mt_project_task_stage" model="mail.message.subtype">
+            <field name="name">Task Stage Changed</field>
+            <field name="sequence">13</field>
+            <field name="res_model">car.car</field>
+            <field name="default" eval="False"/>
+            <field name="parent_id" eval="ref('mt_task_stage')"/>
+            <field name="relation_field">vehicle_id</field>
+        </record>
+
+    </data>
+    </openerp>