123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- # -*- 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)
- 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")
- include_materials = fields.Boolean('Incluir')
-
- _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
- if self.include_materials==True:
- 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,))
- if self.include_materials==True:
- 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
- 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 _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
- 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
|