| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 | # -*- 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 datefrom dateutil.relativedelta import relativedeltafrom openerp import models, api, fields, _from openerp.osv import osvclass 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
 |