class RequestGroup(models.Model): _name = "hc.res.request.group" _description = "Request Group" identifier_id = fields.Many2one(comodel_name="hc.request.group.identifier", string="Identifier", help="Business identifier.") subject_type = fields.Selection( string="Subject Type", selection=[("Patient", "Patient"), ("Group", "Group")], help="Type of subject of the request group.") subject_name = fields.Char(string="Subject", compute="_compute_subject_name", store="True", help="Subject of the request group.") subject_patient_id = fields.Many2one( comodel_name="hc.res.patient", string="Subject Patient", help="Patient subject of the request group.") subject_group_id = fields.Many2one( comodel_name="hc.res.group", string="Subject Group", help="Group subject of the request group.") context_type = fields.Selection( string="Context Type", selection=[("Encounter", "Encounter"), ("Episode Of Care", "Episode Of Care")], help="Type of Encounter or Episode for the request group.") context_name = fields.Char( string="Context", compute="_compute_context_name", store="True", help="Encounter or Episode for the request group.") context_encounter_id = fields.Many2one( comodel_name="hc.res.encounter", string="Context Encounter", help="Encounter for the request group.") context_episode_of_care_id = fields.Many2one( comodel_name="hc.res.episode.of.care", string="Context Episode Of Care", help="Episode Of Care for the request group.") occurrence_date_time = fields.Datetime( string="Occurrence Date Time", help="When the request group was authored.") author_type = fields.Selection( string="Author Type", selection=[("Device", "Device"), ("Practitioner", "Practitioner")], help="Type of device or practitioner that authored the request group.") author_name = fields.Char( string="Author", compute="_compute_author_name", store="True", help="Device or practitioner that authored the request group.") author_device_id = fields.Many2one( comodel_name="hc.res.device", string="Author Device", help="Device that authored the request group.") author_practitioner_id = fields.Many2one( comodel_name="hc.res.practitioner", string="Author Practitioner", help="Practitioner that authored the request group.") reason_type = fields.Selection( string="Reason Type", selection=[("code", "Code"), ("string", "String"), ("Resource Type", "Resource Type")], help="Type of reason for the request group.") reason_name = fields.Char(string="Reason", compute="_compute_reason_name", store="True", help="Reason for the request group.") reason_code_id = fields.Many2one( comodel_name="hc.vs.request.group.reason", string="Reason Code", help="Code of reason for the request group.") reason_string = fields.Char(string="Reason String", help="String of reason for the request group.") reason_resource_id = fields.Many2one( comodel_name="hc.vs.resource.type", string="Reason Resource", help="Resource type of reason for the request group.") note_ids = fields.One2many(comodel_name="hc.request.group.note", inverse_name="request_group_id", string="Notes", help="Additional notes about the response.") action_ids = fields.One2many(comodel_name="hc.request.group.action", inverse_name="request_group_id", string="Actions", help="Proposed actions, if any.")
class event_event(models.Model): """Event""" _name = 'event.event' _description = 'Event' _inherit = ['mail.thread', 'ir.needaction_mixin'] _order = 'date_begin' name = fields.Char(string='Event Name', translate=True, required=True, readonly=False, states={'done': [('readonly', True)]}) active = fields.Boolean(default=True, track_visibility="onchange") user_id = fields.Many2one('res.users', string='Responsible', default=lambda self: self.env.user, readonly=False, states={'done': [('readonly', True)]}) company_id = fields.Many2one('res.company', string='Company', change_default=True, default=lambda self: self.env['res.company']. _company_default_get('event.event'), required=False, readonly=False, states={'done': [('readonly', True)]}) organizer_id = fields.Many2one( 'res.partner', string='Organizer', default=lambda self: self.env.user.company_id.partner_id) event_type_id = fields.Many2one('event.type', string='Category', readonly=False, states={'done': [('readonly', True)]}, oldname='type') color = fields.Integer('Kanban Color Index') event_mail_ids = fields.One2many( 'event.mail', 'event_id', string='Mail Schedule', default=lambda self: self._default_event_mail_ids(), copy=True) @api.model def _default_event_mail_ids(self): return [(0, 0, { 'interval_unit': 'now', 'interval_type': 'after_sub', 'template_id': self.env.ref('event.event_subscription') })] # Seats and computation seats_max = fields.Integer( string='Maximum Attendees Number', oldname='register_max', readonly=True, states={ 'draft': [('readonly', False)], 'confirm': [('readonly', False)] }, help= "For each event you can define a maximum registration of seats(number of attendees), above this numbers the registrations are not accepted." ) seats_availability = fields.Selection([('limited', 'Limited'), ('unlimited', 'Unlimited')], 'Maximum Attendees', required=True, default='unlimited') seats_min = fields.Integer( string='Minimum Attendees', oldname='register_min', help= "For each event you can define a minimum reserved seats (number of attendees), if it does not reach the mentioned registrations the event can not be confirmed (keep 0 to ignore this rule)" ) seats_reserved = fields.Integer(oldname='register_current', string='Reserved Seats', store=True, readonly=True, compute='_compute_seats') seats_available = fields.Integer(oldname='register_avail', string='Maximum Attendees', store=True, readonly=True, compute='_compute_seats') seats_unconfirmed = fields.Integer(oldname='register_prospect', string='Unconfirmed Seat Reservations', store=True, readonly=True, compute='_compute_seats') seats_used = fields.Integer(oldname='register_attended', string='Number of Participants', store=True, readonly=True, compute='_compute_seats') seats_expected = fields.Integer(string='Number of Expected Attendees', readonly=True, compute='_compute_seats') @api.multi @api.depends('seats_max', 'registration_ids.state') def _compute_seats(self): """ Determine reserved, available, reserved but unconfirmed and used seats. """ # initialize fields to 0 for event in self: event.seats_unconfirmed = event.seats_reserved = event.seats_used = event.seats_available = 0 # aggregate registrations by event and by state if self.ids: state_field = { 'draft': 'seats_unconfirmed', 'open': 'seats_reserved', 'done': 'seats_used', } query = """ SELECT event_id, state, count(event_id) FROM event_registration WHERE event_id IN %s AND state IN ('draft', 'open', 'done') GROUP BY event_id, state """ self._cr.execute(query, (tuple(self.ids), )) for event_id, state, num in self._cr.fetchall(): event = self.browse(event_id) event[state_field[state]] += num # compute seats_available for event in self: if event.seats_max > 0: event.seats_available = event.seats_max - ( event.seats_reserved + event.seats_used) event.seats_expected = event.seats_unconfirmed + event.seats_reserved + event.seats_used # Registration fields registration_ids = fields.One2many('event.registration', 'event_id', string='Attendees', readonly=False, states={'done': [('readonly', True)]}) # Date fields date_tz = fields.Selection('_tz_get', string='Timezone', required=True, default=lambda self: self.env.user.tz) date_begin = fields.Datetime(string='Start Date', required=True, track_visibility='onchange', states={'done': [('readonly', True)]}) date_end = fields.Datetime(string='End Date', required=True, track_visibility='onchange', states={'done': [('readonly', True)]}) date_begin_located = fields.Datetime(string='Start Date Located', compute='_compute_date_begin_tz') date_end_located = fields.Datetime(string='End Date Located', compute='_compute_date_end_tz') @api.model def _tz_get(self): return [(x, x) for x in pytz.all_timezones] @api.one @api.depends('date_tz', 'date_begin') def _compute_date_begin_tz(self): if self.date_begin: self_in_tz = self.with_context(tz=(self.date_tz or 'UTC')) date_begin = fields.Datetime.from_string(self.date_begin) self.date_begin_located = fields.Datetime.to_string( fields.Datetime.context_timestamp(self_in_tz, date_begin)) else: self.date_begin_located = False @api.one @api.depends('date_tz', 'date_end') def _compute_date_end_tz(self): if self.date_end: self_in_tz = self.with_context(tz=(self.date_tz or 'UTC')) date_end = fields.Datetime.from_string(self.date_end) self.date_end_located = fields.Datetime.to_string( fields.Datetime.context_timestamp(self_in_tz, date_end)) else: self.date_end_located = False state = fields.Selection( [('draft', 'Unconfirmed'), ('cancel', 'Cancelled'), ('confirm', 'Confirmed'), ('done', 'Done')], string='Status', default='draft', readonly=True, required=True, copy=False, help= "If event is created, the status is 'Draft'. If event is confirmed for the particular dates the status is set to 'Confirmed'. If the event is over, the status is set to 'Done'. If event is cancelled the status is set to 'Cancelled'." ) auto_confirm = fields.Boolean(string='Confirmation not required', compute='_compute_auto_confirm') @api.one def _compute_auto_confirm(self): self.auto_confirm = self.env['ir.values'].get_default( 'event.config.settings', 'auto_confirmation') reply_to = fields.Char( 'Reply-To Email', readonly=False, states={'done': [('readonly', True)]}, help= "The email address of the organizer is likely to be put here, with the effect to be in the 'Reply-To' of the mails sent automatically at event or registrations confirmation. You can also put the email address of your mail gateway if you use one." ) address_id = fields.Many2one( 'res.partner', string='Location', default=lambda self: self.env.user.company_id.partner_id, readonly=False, states={'done': [('readonly', True)]}) country_id = fields.Many2one('res.country', 'Country', related='address_id.country_id', store=True) description = fields.Html(string='Description', oldname='note', translate=True, readonly=False, states={'done': [('readonly', True)]}) # badge fields badge_front = fields.Html(string='Badge Front') badge_back = fields.Html(string='Badge Back') badge_innerleft = fields.Html(string='Badge Inner Left') badge_innerright = fields.Html(string='Badge Inner Right') event_logo = fields.Html(string='Event Logo') @api.multi @api.depends('name', 'date_begin', 'date_end') def name_get(self): result = [] for event in self: date_begin = fields.Datetime.from_string(event.date_begin) date_end = fields.Datetime.from_string(event.date_end) dates = [ fields.Date.to_string( fields.Datetime.context_timestamp(event, dt)) for dt in [date_begin, date_end] if dt ] dates = sorted(set(dates)) result.append( (event.id, '%s (%s)' % (event.name, ' - '.join(dates)))) return result @api.one @api.constrains('seats_max', 'seats_available') def _check_seats_limit(self): if self.seats_availability == 'limited' and self.seats_max and self.seats_available < 0: raise ValidationError(_('No more available seats.')) @api.one @api.constrains('date_begin', 'date_end') def _check_closing_date(self): if self.date_end < self.date_begin: raise ValidationError( _('Closing Date cannot be set before Beginning Date.')) @api.model def create(self, vals): res = super(event_event, self).create(vals) if res.organizer_id: res.message_subscribe([res.organizer_id.id]) if res.auto_confirm: res.button_confirm() return res @api.multi def write(self, vals): res = super(event_event, self).write(vals) if vals.get('organizer_id'): self.message_subscribe([vals['organizer_id']]) return res @api.one def button_draft(self): self.state = 'draft' @api.one def button_cancel(self): for event_reg in self.registration_ids: if event_reg.state == 'done': raise UserError( _("You have already set a registration for this event as 'Attended'. Please reset it to draft if you want to cancel this event." )) self.registration_ids.write({'state': 'cancel'}) self.state = 'cancel' @api.one def button_done(self): self.state = 'done' @api.one def button_confirm(self): self.state = 'confirm' @api.onchange('event_type_id') def _onchange_type(self): if self.event_type_id: self.seats_min = self.event_type_id.default_registration_min self.seats_max = self.event_type_id.default_registration_max self.reply_to = self.event_type_id.default_reply_to @api.multi def action_event_registration_report(self): res = self.env['ir.actions.act_window'].for_xml_id( 'event', 'action_report_event_registration') res['context'] = { "search_default_event_id": self.id, "group_by": ['create_date:day'], } return res @api.one def mail_attendees(self, template_id, force_send=False, filter_func=lambda self: True): for attendee in self.registration_ids.filtered(filter_func): self.env['mail.template'].browse(template_id).send_mail( attendee.id, force_send=force_send)
class website_url_tracker(models.Model): _name = 'website.url.tracker' timestamp = fields.Datetime(string='Time Stamp') user_id = fields.Many2one(comodel_name='res.users', string='Visitor') partner_id = fields.Many2one(comodel_name='res.partner', string='Partner')
class HrEmployeeFiscal(models.Model): _name = 'hr.employee.fiscal' _order = 'date_from desc' @api.one def _compute_create_user(self): self.user_create = "%s:%s" % (self.create_uid.login.split( '@')[0], datetime.strptime( self.create_date, '%Y-%m-%d %H:%M:%S').strftime('%d-%m-%Y-%H:%M:%S')) @api.one def _compute_last_user(self): self.user_last = "%s:%s" % (self.write_uid.login.split( '@')[0], datetime.strptime( self.write_date, '%Y-%m-%d %H:%M:%S').strftime('%d-%m-%Y %H:%M:%S')) user_create = fields.Char(compute='_compute_create_user', string='Creado', readonly=True, size=68, store=False) user_last = fields.Char(compute='_compute_last_user', string='Modificado', readonly=True, size=68, store=False) employee_id = fields.Many2one('hr.employee', 'Empleado', required=False) # TODO: poner company_id, obtener company company_id = fields.Many2one(related='employee_id.company_id', string='Compañia', required=False) date_from = fields.Date('Inicio', default=datetime.today().strftime('%Y-%m-01'), required=True, readonly=False) date_to = fields.Date('Termino', default=datetime.today().strftime('%Y-%m-30'), required=True, readonly=False) country_id = fields.Many2one('res.country', related='employee_id.country_id', string="Nacionalidad (País)", readonly=True, store=True) #home_state_id = fields.Char(related='employee_id.home_state_id.name', string='Provincia', readonly=True, store=False) date_irpf = fields.Datetime('Fecha Calculo', required=False, readonly=True) modif_id = fields.Many2one('hr.employee.fiscal.modif', 'Modificador IRPF', required=True) key_id = fields.Many2one('hr.employee.fiscal.key', 'Clave percepcion', required=True) marital = fields.Selection(related='employee_id.marital', string="Estado civil", readonly=True, store=False) situation = fields.Selection([ ('1', 'Monoparental'), ('2', 'Con conyuge a cargo'), ('3', 'Otras situacion'), ], string='Situacion familiar', default='', required=True, readonly=False) conyuge_nif = fields.Char( string="DNI/NIF Conyuge", size=12, required=False, ) minus = fields.Selection([ ('0', 'Sin Minusvalia'), ('3', 'Igual/Superior a 33% e inferior 65%'), ('A', 'Entre 33% y 65%, con asistencia'), ('6', 'Igual/Superior a 65%'), ('B', 'Igual/Superior a 65%, con asistencia'), ], string='Minusvalia', default='0', required=False) geo_move = fields.Selection([ ('S', 'Si'), ('N', 'No'), ], string='Movilidad geografica', default='N', required=False) geo_date = fields.Date( string="Fecha Movilidad", required=False, ) loan = fields.Selection([ ('S', 'Si'), ('N', 'No'), ], string='Prestamo vivienda', default='N', required=False)
class contract_service_deactivate(models.TransientModel): _name = 'contract.service.deactivate' @api.model def default_get(self, fields): res = super(contract_service_deactivate, self).default_get(fields) if self._context.get('active_model', '') == 'contract.service': active_id = self._context.get('active_id') contract_service = self.env['contract.service'].browse(active_id) res.update({ 'account_id': contract_service.account_id.id, 'service_id': contract_service.id }) return res deactivation_date = fields.Datetime('Deactivation Date', default=fields.datetime.now()) account_id = fields.Many2one('account.analytic.account', 'Account') service_id = fields.Many2one('contract.service', 'Service') @api.multi def deactivate(self): context = self._context or {} context = dict(context) contract_service_obj = self.env['contract.service'] context.update({'deactivation_date': self.deactivation_date}) contract_service_obj.action_desactivate([self.service_id.id], context=context) # If we activate again, we will need a new activation line, as # we will have refunded any extra, and will need to bill in # advance again. self.service_id.write({'activation_line_generated': False}) self._create_refund_lines() return True @api.multi def _create_refund_lines(self): contract_service_obj = self.env['contract.service'] deactivate_date = datetime.datetime.strptime( self.deactivation_date, DEFAULT_SERVER_DATETIME_FORMAT, ).date() contract_service_obj.create_refund_line([self.service_id.id], mode='prorata', date=deactivate_date) @api.constrains('deactivation_date') def _check_future_date(self): today = datetime.datetime.utcnow().date() for wiz in self: act_date = datetime.datetime.strptime( wiz.deactivation_date, DEFAULT_SERVER_DATETIME_FORMAT, ).date() if act_date > today: raise Warning( _('You cannot deactivate a ' 'service in the future.')) return False return True
class rbs_documento_mercantil_vehiculo(models.Model): _name = "rbs.documento.mercantil.vehiculo" _description = "Documento Mercantil Vehiculo" #name= field.Char('Nombre') anio_id = fields.Many2one('rbs.archivo.anio', string='Año', required=True) libro_id = fields.Many2one('rbs.archivo.libro', string='Libro', required=True) tomo_id = fields.Many2one("rbs.archivo.tomo", string='Tomo', required=True) persona_id = fields.Many2one('rbs.persona', string='Compareciente(n)') persona_nombres = fields.Char(string='Nombres del Compareciente') persona_apellidos = fields.Char(string='Apellidos del Compareciente') persona_cedula = fields.Char(string='Cedula del Compareciente') persona_representante = fields.Char( string='Representante del Compareciente') persona_razonSocial = fields.Char(string='Razon Social del Compareciente') tipo_compareciente_id = fields.Many2one('rbs.tipo.compareciente.v', string='Tipo de Compareciente') tipo_contrato_id = fields.Many2one('rbs.tipo.contrato', string='Tipo de Contrato', required=True) fecha_inscripcion = fields.Datetime(string='Fecha de Inscripcion', required=True) numero_inscripcion = fields.Char(string='Numero de Inscripcion', required=True) fecha_cancelacion = fields.Datetime(string='Fecha de Cancelacion') tipo_bien_id = fields.Many2one('rbs.tipo.bien', string='Tipo de Bien', required=True) chasis = fields.Char(string='Chasis') motor = fields.Char(string='Motor') marca = fields.Char(string='Marca') modelo = fields.Char(string='Modelo') anio_fabricacion = fields.Char(string='Año de Fabricacion') placa = fields.Char(string='Placa') ultima_modificacion = fields.Char(string='Ultima Modificacion') nombre_institucion = fields.Char(string='Nombre de la Institucion', required=True) canton_notaria = fields.Char(string='Canton de Notaria', required=True) fecha_escritura_contrato = fields.Datetime(string='Fecha de Escritura', required=True) estado = fields.Selection([ ('VIGENTE', 'VIGENTE'), ('NOVIGENTE', 'NO VIGENTE'), ], string='Estado', required=True) #filedata = fields.Binary('Archivo',filters='*.pdf') #filename = fields.Char('Nombre de archivo', default="Archivo.pdf") filedata_id = fields.Many2one('rbs.archivo.pdf') filedata = fields.Binary(related='filedata_id.filedata', filters='*.pdf') esPesado = fields.Boolean(related='filedata_id.esPesado', string='¿Es Pesado?') rutaFTP = fields.Char(related='filedata_id.rutaFTP', string='Escriba la ruta del Archivo') identificacion_unica = fields.Char( string='Identificador Unico Sistema Remoto', compute='_compute_upper', store=True) ubicacion_dato_id = fields.Many2one('rbs.ubicacion.dato', string='Ubicacion del Dato', required=True) def _getUltimoAnio(self, cr, uid, context=None): acta_id = self.pool.get("rbs.documento.mercantil.vehiculo").search( cr, uid, [], limit=1, order='id desc') anio = self.pool.get("rbs.documento.mercantil.vehiculo").browse( cr, uid, acta_id, context=None).anio_id.id return anio def _getUltimoLibro(self, cr, uid, context=None): acta_id = self.pool.get("rbs.documento.mercantil.vehiculo").search( cr, uid, [], limit=1, order='id desc') libro = self.pool.get("rbs.documento.mercantil.vehiculo").browse( cr, uid, acta_id, context=None).libro_id.id return libro def _getUltimoTomo(self, cr, uid, context=None): acta_id = self.pool.get("rbs.documento.mercantil.vehiculo").search( cr, uid, [], limit=1, order='id desc') tomo = self.pool.get("rbs.documento.mercantil.vehiculo").browse( cr, uid, acta_id, context=None).tomo_id.id return tomo def _create_pdf(self, cr, uid, context=None): return self.pool.get("rbs.archivo.pdf").create(cr, uid, {}, context=None) _defaults = { 'anio_id': _getUltimoAnio, 'libro_id': _getUltimoLibro, 'tomo_id': _getUltimoTomo, 'filedata_id': _create_pdf, } _rec_name = 'numero_inscripcion' @api.depends('ubicacion_dato_id', 'persona_cedula', 'numero_inscripcion') def _compute_upper(self): for rec in self: try: rec.identificacion_unica = '03' + rec.ubicacion_dato_id.name + rec.persona_cedula + rec.numero_inscripcion except: try: rec.identificacion_unica = '03' + rec.ubicacion_dato_id.name + rec.numero_inscripcion + rec.numero_inscripcion except: pass def on_change_anio_id(self, cr, uid, ids, anio_id, context=None): result = {} if (self._getUltimoAnio(cr, uid, context=None) != anio_id): result['libro_id'] = 0 return { 'value': result, } def on_change_libro_id(self, cr, uid, ids, libro_id, context=None): result = {} if (self._getUltimoLibro(cr, uid, context=None) != libro_id): result['tomo_id'] = 0 return { 'value': result, } def codigoascii(self, text): return unicode(text).encode('utf-8') def onchange_persona_id(self, cr, uid, ids, persona_id, context=None): persona_id = self.pool.get('rbs.persona').search( cr, uid, [ ('id', '=', persona_id), ]) persona = self.pool.get('rbs.persona').browse(cr, uid, persona_id, context=None) result = {} try: if persona: #raise osv.except_osv('Esto es un Mesaje!',establecimiento) try: if persona.persona_nombres: result['persona_nombres'] = self.codigoascii( persona.persona_nombres) except: pass try: if persona.persona_apellidos: result['persona_apellidos'] = self.codigoascii( persona.persona_apellidos) except: pass try: if persona.name: result['persona_cedula'] = str(persona.name) except: pass try: if persona.persona_representante: result['persona_representante'] = self.codigoascii( persona.persona_representante) except: pass try: if persona.persona_razonSocial: result['persona_razonSocial'] = self.codigoascii( persona.persona_razonSocial) except: pass except: pass return { 'value': result, } def onchange_inscripcion(self, cr, uid, ids, inscripcion_num, libro_id, context=None): vehiculo_id = self.pool.get('rbs.documento.mercantil.vehiculo').search( cr, uid, [('numero_inscripcion', '=', inscripcion_num), ('libro_id', '=', libro_id)]) vehiculo = self.pool.get('rbs.documento.mercantil.vehiculo').browse( cr, uid, vehiculo_id, context=None) result = {} try: if vehiculo: vehiculo = vehiculo[0] #raise osv.except_osv('Esto es un Mesaje!',establecimiento) try: if vehiculo.fecha_inscripcion: result['fecha_inscripcion'] = str( vehiculo.fecha_inscripcion) except: pass try: if vehiculo.anio_id: result['anio_id'] = vehiculo.anio_id.id except: pass try: if vehiculo.libro_id: result['libro_id'] = vehiculo.libro_id.id except: pass try: if vehiculo.tomo_id: result['tomo_id'] = vehiculo.tomo_id.id except: pass try: if vehiculo.tipo_contrato_id: result[ 'tipo_contrato_id'] = vehiculo.tipo_contrato_id.id except: pass try: if vehiculo.fecha_cancelacion: result['fecha_cancelacion'] = str( vehiculo.fecha_cancelacion) except: pass try: if vehiculo.tipo_bien_id: result['tipo_bien_id'] = vehiculo.tipo_bien_id except: pass try: if vehiculo.chasis: result['chasis'] = self.codigoascii(vehiculo.chasis) except: pass try: if vehiculo.motor: result['motor'] = self.codigoascii(vehiculo.motor) except: pass try: if vehiculo.marca: result['marca'] = self.codigoascii(vehiculo.marca) except: pass try: if vehiculo.modelo: result['modelo'] = self.codigoascii(vehiculo.modelo) except: pass try: if vehiculo.anio_fabricacion: result['anio_fabricacion'] = str( vehiculo.anio_fabricacion) except: pass try: if vehiculo.placa: result['placa'] = self.codigoascii(vehiculo.placa) except: pass try: if vehiculo.ultima_modificacion: result['ultima_modificacion'] = str( vehiculo.ultima_modificacion) except: pass try: if vehiculo.nombre_institucion: result['nombre_institucion'] = self.codigoascii( vehiculo.nombre_institucion) except: pass try: if vehiculo.canton_notaria: result['canton_notaria'] = self.codigoascii( vehiculo.canton_notaria) except: pass try: if vehiculo.fecha_escritura_contrato: result['fecha_escritura_contrato'] = str( vehiculo.fecha_escritura_contrato) except: pass try: if vehiculo.estado: result['estado'] = vehiculo.estado except: pass try: if vehiculo.filedata_id: result['filedata_id'] = vehiculo.filedata_id.id except: pass try: if vehiculo.ubicacion_dato_id: result[ 'ubicacion_dato_id'] = vehiculo.ubicacion_dato_id.id except: pass if not vehiculo: result['filedata_id'] = self._create_pdf(cr, uid, context=None) except: pass return { 'value': result, }
class event_track(models.Model): _name = "event.track" _description = 'Event Track' _order = 'priority, date' _inherit = ['mail.thread', 'ir.needaction_mixin', 'website.seo.metadata', 'website.published.mixin'] name = fields.Char('Title', required=True, translate=True) user_id = fields.Many2one('res.users', 'Responsible', track_visibility='onchange', default=lambda self: self.env.user) speaker_ids = fields.Many2many('res.partner', string='Speakers') tag_ids = fields.Many2many('event.track.tag', string='Tags') state = fields.Selection([ ('draft', 'Proposal'), ('confirmed', 'Confirmed'), ('announced', 'Announced'), ('published', 'Published'), ('refused', 'Refused')], 'Status', default='draft', required=True, copy=False, track_visibility='onchange') description = fields.Html('Track Description', translate=True) date = fields.Datetime('Track Date') duration = fields.Float('Duration', digits=(16, 2), default=1.5) location_id = fields.Many2one('event.track.location', 'Room') event_id = fields.Many2one('event.event', 'Event', required=True) color = fields.Integer('Color Index') priority = fields.Selection([ ('0', 'Low'), ('1', 'Medium'), ('2', 'High'), ('3', 'Highest')], 'Priority', required=True, default='1') image = fields.Binary('Image', compute='_compute_image', readonly=True, store=True) @api.one @api.depends('speaker_ids.image') def _compute_image(self): if self.speaker_ids: self.image = self.speaker_ids[0].image else: self.image = False @api.model def create(self, vals): res = super(event_track, self).create(vals) res.message_subscribe(res.speaker_ids.ids) return res @api.multi def write(self, vals): res = super(event_track, self).write(vals) if vals.get('speaker_ids'): self.message_subscribe([speaker['id'] for speaker in self.resolve_2many_commands('speaker_ids', vals['speaker_ids'], ['id'])]) return res @api.multi @api.depends('name') def _website_url(self, field_name, arg): res = super(event_track, self)._website_url(field_name, arg) res.update({(track.id, '/event/%s/track/%s' % (slug(track.event_id), slug(track))) for track in self}) return res def read_group(self, cr, uid, domain, fields, groupby, offset=0, limit=None, context=None, orderby=False, lazy=True): """ Override read_group to always display all states. """ if groupby and groupby[0] == "state": # Default result structure # states = self._get_state_list(cr, uid, context=context) states = [('draft', 'Proposal'), ('confirmed', 'Confirmed'), ('announced', 'Announced'), ('published', 'Published')] read_group_all_states = [{ '__context': {'group_by': groupby[1:]}, '__domain': domain + [('state', '=', state_value)], 'state': state_value, 'state_count': 0, } for state_value, state_name in states] # Get standard results read_group_res = super(event_track, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) # Update standard results with default results result = [] for state_value, state_name in states: res = filter(lambda x: x['state'] == state_value, read_group_res) if not res: res = filter(lambda x: x['state'] == state_value, read_group_all_states) res[0]['state'] = [state_value, state_name] result.append(res[0]) return result else: return super(event_track, self).read_group(cr, uid, domain, fields, groupby, offset=offset, limit=limit, context=context, orderby=orderby) def open_track_speakers_list(self, cr, uid, track_id, context=None): track_id = self.browse(cr, uid, track_id, context=context) return { 'name': _('Speakers'), 'domain': [('id', 'in', [partner.id for partner in track_id.speaker_ids])], 'view_type': 'form', 'view_mode': 'kanban,form', 'res_model': 'res.partner', 'view_id': False, 'type': 'ir.actions.act_window', }
class AccountAccount(models.Model): _name = "account.account" _description = "Account" _order = "code" #@api.multi #def _compute_has_unreconciled_entries(self): # print "ici dedans" # account_ids = self.ids # for account in self: # # Avoid useless work if has_unreconciled_entries is not relevant for this account # if account.deprecated or not account.reconcile: # account.has_unreconciled_entries = False # account_ids = account_ids - account # if account_ids: # res = dict.fromkeys([x.id for x in account_ids], False) # self.env.cr.execute( # """ SELECT s.account_id FROM( # SELECT # a.id as account_id, a.last_time_entries_checked AS last_time_entries_checked, # MAX(l.write_date) AS max_date # FROM # account_move_line l # RIGHT JOIN account_account a ON (a.id = l.account_id) # WHERE # a.id in %s # AND EXISTS ( # SELECT 1 # FROM account_move_line l # WHERE l.account_id = a.id # AND l.amount_residual > 0 # ) # AND EXISTS ( # SELECT 1 # FROM account_move_line l # WHERE l.account_id = a.id # AND l.amount_residual < 0 # ) # GROUP BY a.id, a.last_time_entries_checked # ) as s # WHERE (last_time_entries_checked IS NULL OR max_date > last_time_entries_checked) # """ % (account_ids,)) # res.update(self.env.cr.dictfetchall()) # for account in self.browse(res.keys()): # if res[account.id]: # account.has_unreconciled_entries = True @api.multi @api.constrains('internal_type', 'reconcile') def _check_reconcile(self): for account in self: if account.internal_type in ('receivable', 'payable') and account.reconcile == False: raise ValueError(_('You cannot have a receivable/payable account that is not reconciliable. (account code: %s)') % account.code) name = fields.Char(required=True, index=True) currency_id = fields.Many2one('res.currency', string='Account Currency', help="Forces all moves for this account to have this account currency.") code = fields.Char(size=64, required=True, index=True) deprecated = fields.Boolean(index=True, default=False) user_type_id = fields.Many2one('account.account.type', string='Type', required=True, oldname="user_type", help="Account Type is used for information purpose, to generate country-specific legal reports, and set the rules to close a fiscal year and generate opening entries.") internal_type = fields.Selection(related='user_type_id.type', store=True, readonly=True) #has_unreconciled_entries = fields.Boolean(compute='_compute_has_unreconciled_entries', # help="The account has at least one unreconciled debit and credit since last time the invoices & payments matching was performed.") last_time_entries_checked = fields.Datetime(string='Latest Invoices & Payments Matching Date', readonly=True, copy=False, help='Last time the invoices & payments matching was performed on this account. It is set either if there\'s not at least '\ 'an unreconciled debit and an unreconciled credit Or if you click the "Done" button.') reconcile = fields.Boolean(string='Allow Reconciliation', default=False, help="Check this box if this account allows invoices & payments matching of journal items.") tax_ids = fields.Many2many('account.tax', 'account_account_tax_default_rel', 'account_id', 'tax_id', string='Default Taxes') note = fields.Text('Internal Notes') company_id = fields.Many2one('res.company', string='Company', required=True, default=lambda self: self.env['res.company']._company_default_get('account.account')) tag_ids = fields.Many2many('account.account.tag', 'account_account_account_tag', string='Tags', help="Optional tags you may want to assign for custom reporting") _sql_constraints = [ ('code_company_uniq', 'unique (code,company_id)', 'The code of the account must be unique per company !') ] @api.model def name_search(self, name, args=None, operator='ilike', limit=100): args = args or [] domain = [] if name: domain = ['|', ('code', '=ilike', name + '%'), ('name', operator, name)] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = ['&'] + domain accounts = self.search(domain + args, limit=limit) return accounts.name_get() @api.onchange('internal_type') def onchange_internal_type(self): if self.internal_type in ('receivable', 'payable'): self.reconcile = True @api.multi @api.depends('name', 'code') def name_get(self): result = [] for account in self: name = account.code + ' ' + account.name result.append((account.id, name)) return result @api.one def copy(self, default=None): default = dict(default or {}) default.update(code=_("%s (copy)") % (self.code or '')) return super(AccountAccount, self).copy(default) @api.multi def write(self, vals): # Dont allow changing the company_id when account_move_line already exist if vals.get('company_id', False): move_lines = self.env['account.move.line'].search([('account_id', 'in', self.ids)], limit=1) for account in self: if (account.company_id.id <> vals['company_id']) and move_lines: raise UserError(_('You cannot change the owner company of an account that already contains journal items.')) return super(AccountAccount, self).write(vals) @api.multi def unlink(self): if self.env['account.move.line'].search([('account_id', 'in', self.ids)], limit=1): raise UserError(_('You cannot do that on an account that contains journal items.')) #Checking whether the account is set as a property to any Partner or not values = ['account.account,%s' % (account_id,) for account_id in self.ids] partner_prop_acc = self.env['ir.property'].search([('value_reference', 'in', values)], limit=1) if partner_prop_acc: raise UserError(_('You cannot remove/deactivate an account which is set on a customer or vendor.')) return super(AccountAccount, self).unlink() @api.multi def mark_as_reconciled(self): return self.write({'last_time_entries_checked': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT)}) @api.multi def action_open_reconcile(self): # Open reconciliation view for this account action_context = {'show_mode_selector': False, 'account_ids': [self.id,]} return { 'type': 'ir.actions.client', 'tag': 'manual_reconciliation_view', 'context': action_context, }
class PurchaseRequisition(models.Model): _inherit = "purchase.requisition" _description = "Call for Bids" # new fields bid_tendering_mode = fields.Selection( [('open', 'Open'), ('restricted', 'Restricted')], 'Call for Bids Mode', required=True, default='open', help="- Restricted : you select yourself the bidders and generate a " "RFQ for each of those. \n- Open : anybody can bid (you have to " "advertise the call for bids) and you directly encode the bids " "you received. You are still able to generate RFQ if you want to " "contact usual bidders.") bid_receipt_mode = fields.Selection( [('open', 'Open'), ('sealed', 'Sealed')], 'Bid Receipt Mode', required=True, help="- Open : The bids can be opened when received and encoded. \n" "- Closed : The bids can be marked as received but they have to " "be opened \nall at the same time after an opening ceremony " "(probably specific to public sector).", default='open') req_incoterm_id = fields.Many2one( 'stock.incoterms', 'Requested Incoterms', help="Default value requested to the supplier. International " "Commercial Terms are a series of predefined commercial terms " "used in international transactions.") req_incoterm_address = fields.Char( 'Requested Incoterms Place', help="Incoterm Place of Delivery. International Commercial Terms are a" " series of predefined commercial terms used in international " "transactions.") req_payment_term_id = fields.Many2one( 'account.payment.term', 'Requested Payment Term', help="Default value requested to the supplier.") req_terms_of_payment = fields.Char('Requested Terms of Payment') pricelist_id = fields.Many2one( 'product.pricelist', 'Pricelist', domain=[('type', '=', 'purchase')], help="If set that pricelist will be used to generate the RFQ." "Mostely used to ask a requisition in a given currency.") date_end = fields.Datetime( 'Bid Submission Deadline', help="All bids received after that date won't be valid (probably " "specific to public sector).") delivery_remark = fields.Text('Delivery Remarks') budget = fields.Float() selection_reasons = fields.Text(copy=False) @api.multi def _has_product_lines(self): """ Check there are products lines when confirming Call for Bids. Called from workflow transition draft->sent. """ for callforbids in self: if not callforbids.line_ids: raise except_orm( _('Error!'), _('You have to define some products before confirming the ' 'call for bids.')) return True @api.model def _prepare_purchase_order(self, requisition, supplier): values = super(PurchaseRequisition, self)._prepare_purchase_order(requisition, supplier) values.update({ 'bid_validity': requisition.req_validity, 'payment_term_id': requisition.req_payment_term_id.id, 'incoterm_id': requisition.req_incoterm_id.id, 'incoterm_address': requisition.req_incoterm_address, 'delivery_remark': requisition.delivery_remark, }) if requisition.pricelist_id: values['pricelist_id'] = requisition.pricelist_id.id return values @api.model def _prepare_purchase_order_line(self, requisition, requisition_line, purchase_id, supplier): vals = super(PurchaseRequisition, self)._prepare_purchase_order_line( requisition, requisition_line, purchase_id, supplier) vals.update( price_unit=0, requisition_line_id=requisition_line.id, remark=requisition_line.remark, ) return vals @api.model def check_valid_quotation(self, quotation): return False def _prepare_po_from_tender(self, cr, uid, tender, context=None): """Give the generated PO the correct type and state and propagate the Delivery Remarks from tender""" result = super(PurchaseRequisition, self)._prepare_po_from_tender(cr, uid, tender, context) result.update({ 'type': 'purchase', 'state': 'draftpo', 'keep_in_draft': True, }) return result @api.multi def generate_po(self): self.ensure_one() for po_line in self.po_line_ids: # set bid selected boolean to true on RFQ containing confirmed # lines if (po_line.state == 'confirmed' and not po_line.order_id.bid_partial): po_line.order_id.bid_partial = True result = super(PurchaseRequisition, self).generate_po() self.generated_order_ids.write({'keep_in_draft': False}) return result @api.model def quotation_selected(self, quotation): """Predicate that checks if a quotation has at least one line chosen :param quotation: record of 'purchase.order' :returns: True if one line has been chosen """ # This topic is subject to changes return quotation.bid_partial @api.model def cancel_unconfirmed_quotations(self, tender): """ Called from generate_po. Cancel only draft and sent rfq """ tender.refresh() for quotation in tender.purchase_ids: if quotation.state in ['draft', 'sent', 'draftbid', 'bid']: if self.quotation_selected(quotation): quotation.signal_workflow('select_requisition') else: quotation.signal_workflow('purchase_cancel') quotation.message_post( body=_('Canceled by the call for bids associated ' 'to this request for quotation.')) return True @api.multi def tender_open(self): """ Cancel RFQ that have not been sent. Ensure that there are RFQs." """ pos_to_cancel = self.env['purchase.order'] rfq_valid = False for callforbids in self: for purchase in callforbids.purchase_ids: if purchase.state == 'draft': pos_to_cancel |= purchase elif purchase.state != 'cancel': rfq_valid = True if pos_to_cancel: reason = self.env.ref('purchase_rfq_bid_workflow.' 'purchase_cancel_reason_rfq_canceled') pos_to_cancel.write({'cancel_reason': reason.id}) pos_to_cancel.action_cancel() if not rfq_valid: raise except_orm(_('Error'), _('You do not have valid sent RFQs.')) return super(PurchaseRequisition, self).tender_open() @api.multi def _get_po_to_cancel(self): """Get the list of PO/RFQ that can be cancelled on RFQ :returns: List of candidate PO/RFQ record """ purchases = self.mapped('purchase_ids') return purchases.filtered(lambda rec: rec.state in ('draft', 'sent')) @api.one def _check_can_be_canceled(self): """Raise an exception if callforbids can not be cancelled :returns: True or raise exception """ for purchase in self.purchase_ids: if purchase.state not in ('draft', 'sent'): raise except_orm( _('Error'), _('You cannot cancel a call for bids which ' 'has already received bids.')) return True @api.model def _cancel_po_with_reason(self, po_list, reason_id): """Cancel purchase order of a tender, using given reasons :param po_list: list of po record to cancel :param reason_id: reason id of cancelation :returns: cancel po record list """ po_list.write({'cancel_reason': reason_id}) po_list.signal_workflow('purchase_cancel') return po_list @api.model def _get_default_reason(self): """Return default cancel reason""" reason = self.env.ref('purchase_requisition_bid_selection' '.purchase_cancelreason_callforbids_canceled') return reason.id @api.multi def tender_cancel(self): """ Cancel call for bids and try to cancel related RFQs/PO """ reason_id = self._get_default_reason() for callforbid in self: callforbid._check_can_be_canceled() po_to_cancel = self._get_po_to_cancel() if po_to_cancel: self._cancel_po_with_reason(po_to_cancel, reason_id) self.state = 'cancel' @api.multi def update_selection_reasons(self): wizard = self.env['purchase.action_modal.' 'ask_selection_reasons'].browse( self.env.context['active_id']) self.selection_reasons = wizard.selection_reasons self.signal_workflow('bid_selected') @api.multi def tender_selected(self): self.state = 'selected' @api.multi def act_tender_closed(self): self.signal_workflow('close_bid') @api.multi def tender_closed(self): self.state = 'closed' @api.multi def open_rfq(self): """ This opens rfq view to view all generated rfq/bids associated to the call for bids """ ActWindow = self.env['ir.actions.act_window'] res = ActWindow.for_xml_id('purchase', 'purchase_rfq') res['domain'] = expression.AND([ safe_eval(res.get('domain', [])), [('requisition_id', 'in', self.ids)] ]) # FIXME: need to disable create - temporarily set as invisible in view return res @api.multi def open_po(self): """ This opens po view to view all generated po associated to the call for bids """ ActWindow = self.env['ir.actions.act_window'] res = ActWindow.for_xml_id('purchase', 'purchase_form_action') res['domain'] = expression.AND([ safe_eval(res.get('domain', [])), [('requisition_id', 'in', self.ids)] ]) return res @api.multi def confirm_selection(self): """ Check all quantities have been sourced """ self.ensure_one() dp_obj = self.env['decimal.precision'] precision = dp_obj.precision_get('Product Unit of Measure') for line in self.line_ids: qty = line.product_qty for pol in line.purchase_line_ids: if pol.state == 'confirmed': qty -= pol.quantity_bid if qty == line.product_qty: break # nothing selected compare = float_compare(qty, 0, precision_digits=precision) if compare != 0: break # too much or too few selected else: return self.ask_selection_reasons() # open a dialog to confirm that we want more / less or no qty ctx = self.env.context.copy() ctx.update({ 'action': 'ask_selection_reasons', 'active_model': self._name, 'active_ids': self._ids, }) view = self.env.ref('purchase_requisition_bid_selection' '.action_modal_confirm_different_quantity') return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'purchase.action_modal', 'view_id': view.id, 'views': [(view.id, 'form')], 'target': 'new', 'context': ctx, } @api.multi def ask_confirmation_to_close_selection(self): ctx = self.env.context.copy() ctx.update({ 'action': 'act_tender_closed', 'active_model': self._name, 'active_ids': self._ids, }) view = self.env.ref('purchase_requisition_bid_selection' '.modal_confirm_close_selection') return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'purchase.action_modal', 'view_id': view.id, 'views': [(view.id, 'form')], 'target': 'new', 'context': ctx, } def open_product_line(self, cr, uid, ids, context=None): """ Filter to show only lines from bids received. Group by requisition line instead of product for unicity. """ res = super(PurchaseRequisition, self).open_product_line(cr, uid, ids, context=context) ctx = res.setdefault('context', {}) if 'search_default_groupby_product' in ctx: del ctx['search_default_groupby_product'] if 'search_default_hide_cancelled' in ctx: del ctx['search_default_hide_cancelled'] ctx['search_default_groupby_requisitionline'] = True ctx['search_default_showbids'] = True return res @api.multi def ask_selection_reasons(self): ctx = self._context.copy() ctx.update({ 'action': 'update_selection_reasons', 'active_model': self._name, 'active_ids': self._ids, 'default_selection_reasons': self.selection_reasons, }) view = self.env.ref('purchase_requisition_bid_selection.' 'ask_selection_reasons') return { 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'purchase.action_modal.ask_selection_reasons', 'view_id': view.id, 'views': [(view.id, 'form')], 'target': 'new', 'context': ctx, }
class MrpProduction(models.Model): _inherit = 'mrp.production' _order = 'name desc' date_planned = fields.Datetime(readonly=False) # Redefined routing_id = fields.Many2one(ondelete='restrict') # Redefined date = fields.Datetime('Creation Date', states={ 'cancel': [('readonly', True)], 'done': [('readonly', True)] }, default=fields.Datetime.now, copy=False) state = fields.Selection(PRODUCTION_STATES) # Redefined note = fields.Text('Notes') workcenter_lines = fields.One2many(readonly=False) # Redefined origin = fields.Char( readonly=False, # Redefined states={ 'cancel': [('readonly', True)], 'done': [('readonly', True)] }) color_production = fields.Integer('Color production', compute='_get_color_production', readonly=True) theo_cost = fields.Float('Theorical Cost', digits=dp.get_precision('Product Price'), copy=False) production_type = fields.Selection(PRODUCTION_TYPES, 'Type of production', default='normal', copy=False) @api.multi def _get_color_production(self): for prod in self: color_production = -1 # blanco (cero da error al cargar la vista kanban) if prod.priority == '0': # Prioridad no urgente color_production = 4 # verde claro elif prod.priority == '1': # Prioridad normal color_production = 3 # amarillo elif prod.priority == '2': # Prioridad urgente color_production = 2 # rojo claro elif prod.priority == '3': # Prioridad muy urgente color_production = 1 # gris prod.color_production = color_production @api.multi def modify_consumption(self): ctx = dict(self._context, active_model=self._name, active_ids=self.ids, active_id=self.ids[0]) mod_cons_obj = self.env['mrp.modify.consumption'].with_context(ctx) return mod_cons_obj.create({}).wizard_view() @api.model def _costs_generate(self, production): """ Calculates total costs at the end of the production. @param production: Id of production order. @return: Calculated amount. """ amount = 0.0 analytic_line_obj = self.env['account.analytic.line'] for wc_line in production.workcenter_lines: wc = wc_line.workcenter_id if wc.costs_journal_id and wc.costs_general_account_id: # Cost per hour value = wc_line.hour * wc.costs_hour account = wc.costs_hour_account_id.id if value and account: amount += value analytic_line_obj.sudo().create({ 'name': wc_line.name + ' (H)', 'amount': value, 'account_id': account, 'general_account_id': wc.costs_general_account_id.id, 'journal_id': wc.costs_journal_id.id, 'ref': wc.code, 'product_id': wc.product_id.id, 'unit_amount': wc_line.hour, 'product_uom_id': wc.product_id and wc.product_id.uom_id.id or False }) return amount @api.model def _make_production_produce_line(self, production): move_id = super(MrpProduction, self)._make_production_produce_line(production) move = self.env['stock.move'].browse(move_id) move_name = _('PROD: %s') % production.name move.write({'name': move_name}) return move_id @api.onchange('product_uos_qty') def product_uos_qty_change(self): if self.product_id.uos_id: qty_uom = float(self.product_uos_qty / (self.product_id.uos_coeff or 1.0)) self.product_qty = qty_uom self.product_uos = self.product_id.uos_id else: self.product_uos_qty = False self.product_uos = False @api.model def action_produce(self, production_id, production_qty, production_mode, wiz=False): stock_move_obj = self.env['stock.move'] uom_obj = self.env['product.uom'] production = self.browse(production_id) production_qty_uom = uom_obj._compute_qty( production.product_uom.id, production_qty, production.product_id.uom_id.id) precision = self.env['decimal.precision'].precision_get( 'Product Unit of Measure') main_production_move = False default_mode = self._context.get('default_mode', False) if production_mode == 'produce': # New Case: Produce Only produced_products = {} for produced_product in production.move_created_ids2: if produced_product.scrapped: continue if not produced_products.get(produced_product.product_id.id, False): produced_products[produced_product.product_id.id] = 0 produced_products[produced_product.product_id. id] += produced_product.product_qty for produce_product in production.move_created_ids: subproduct_factor = self._get_subproduct_factor( production.id, produce_product.id) lot_id = wiz and wiz.lot_id.id or False qty = min(subproduct_factor * production_qty_uom, produce_product.product_qty ) # Needed when producing more than maximum quantity new_moves = produce_product.action_consume( qty, location_id=produce_product.location_id.id, restrict_lot_id=lot_id) stock_move_obj.browse(new_moves).write( {'production_id': production_id}) remaining_qty = subproduct_factor * production_qty_uom - qty if not float_is_zero(remaining_qty, precision_digits=precision): # In case you need to make more than planned # consumed more in wizard than previously planned extra_move_id = produce_product.copy( default={ 'product_uom_qty': remaining_qty, 'production_id': production_id }) extra_move_id.action_confirm() extra_move_id.action_done() if produce_product.product_id == production.product_id: main_production_move = produce_product.id if default_mode != 'consume' and not production.move_created_ids: production.signal_workflow('button_finished_validated') else: if not main_production_move: main_production_move = production.move_created_ids2 and production.move_created_ids2[ 0].id # Añadimos al contexto 'main_production_move' # para poder escribirlo en el write y en el action_consume() self = self.with_context(main_production_move=main_production_move) res = super(MrpProduction, self).action_produce(production_id, production_qty, production_mode, wiz=wiz) if default_mode != 'consume' and not production.move_created_ids: production.signal_workflow('button_finished_validated') if default_mode == 'consume': # Custom behaivor, set closed state production.signal_workflow('button_validated_closed') return True @api.multi def action_finished(self): for production in self: production.write({'state': 'finished'}) return True @api.multi def action_validated(self): tmpl_obj = self.env['product.template'] for production in self: theo_cost = tmpl_obj._calc_price(production.bom_id, test=True) production.write({'state': 'validated', 'theo_cost': theo_cost}) return True @api.multi def action_close(self): tmpl_obj = self.env['product.template'] precision = self.env['decimal.precision'].precision_get( 'Product Price') for production in self: date = max([ x.date for x in production.move_created_ids2 if x.state == 'done' and not x.scrapped ] or [None]) for move in production.move_lines2.filtered( lambda r: r.state == 'done'): # Establecemos en los movimiento de consumos los precios de coste de producto que tenía en la fecha # que se realizó el producto finalizado, para que coincida con la misma posición # en la que se calcula el theo_cost. Esto es debido a que los consumos se pueden hacer más # tarde que la validación del producto terminado (action_validated) price_unit = tmpl_obj.get_history_price( move.product_id.product_tmpl_id.id, move.company_id.id, date=date) # Aplicamos el redondeo que tendría el campo standard_price, # ya que get_history_price devuelve el valor sin precision price_unit = float_round(price_unit, precision_digits=precision) price_unit = price_unit or move.product_id.standard_price move.write({'price_unit': price_unit}) production.write({'state': 'closed'}) return True @api.multi def action_cancel(self): """ Cancels the production order and related stock moves. @return: True """ res = super(MrpProduction, self).action_cancel() # Put related procurements in cancel state proc_obj = self.env['procurement.order'] procs = proc_obj.search([('production_id', 'in', self.ids)]) procs.write({'state': 'cancel'}) return res @api.multi def action_in_production(self): """ Overwrite to set startworking state of all workcenter lines instead only one. """ for workcenter_line in self.mapped('workcenter_lines'): workcenter_line.signal_workflow('button_start_working') return super(MrpProduction, self).action_in_production() @api.multi def action_production_end(self): prod_line_obj = self.env['mrp.production.product.line'] res = super(MrpProduction, self).action_production_end() for production in self: bom = production.bom_id finished_qty = sum([ x.product_uom_qty for x in production.move_created_ids2 if x.state == 'done' and not x.scrapped ]) factor = self.env['product.uom']._compute_qty( production.product_uom.id, finished_qty, bom.product_uom.id) new_qty = factor / bom.product_qty routing_id = production.routing_id.id result, result2 = self.env['mrp.bom']._bom_explode( bom, production.product_id, new_qty, routing_id=routing_id) prod_lines = result production.product_lines.unlink() for line in prod_lines: line['production_id'] = production.id prod_line_obj.create(line) # Nos aseguramos de que la trazabilidad hacia arriba de la producción es correcta # Hay casos en los que se eliminan las lineas de consumos y se agragan nuevas, # momento en el que se pierde la traza self.update_production_traceability() return res @api.multi def update_production_traceability(self): for production in self: for move in production.move_created_ids2.filtered( lambda r: r.state == 'done'): if move.production_id: # Is final production move raw_ids = move.production_id.move_lines raw_ids |= move.production_id.move_lines2.filtered( lambda r: r.state != 'cancel' and not r.scrapped) move.write({'parent_ids': [(6, 0, raw_ids.ids)]}) return True @api.multi def unlink(self): """ Unlink the production order and related stock moves. @return: True """ if any(x.state not in ('draft', 'confirmed', 'ready', 'in_production', 'cancel') for x in self): raise exceptions.Warning( _('Error!'), _('You cannot delete a production which is not cancelled.')) prods_to_cancel = self.filtered(lambda r: r.state != 'cancel') if prods_to_cancel: prods_to_cancel.action_cancel() moves_to_unlink = self.mapped('move_created_ids2') + self.mapped( 'move_lines2') moves_to_unlink.unlink() wc_lines_to_unlink = self.mapped('workcenter_lines') wc_lines_to_unlink.unlink() res = super(MrpProduction, self).unlink() return res @api.multi def update_production_priority(self): domain = [('priority', '!=', '3'), ('state', 'in', ['confirmed', 'ready'])] production_ids = self or self.search(domain) for production in production_ids: product_id = production.product_id ctx = dict(self._context, location=production.location_dest_id.id) product_available = product_id.with_context( ctx)._product_available()[product_id.id] qty_to_compare = product_available[ 'qty_available'] - product_available['outgoing_qty'] company_id = production.company_id domain = company_id and [('company_id', '=', company_id.id)] or [] domain.append(('product_id', '=', product_id.id)) op = self.env['stock.warehouse.orderpoint'].search(domain, limit=1) min_qty = security_qty = 0 if op: min_qty = min(op.product_min_qty, op.product_max_qty) security_qty = op.product_security_qty if qty_to_compare <= 0: priority = '2' # Urgente elif qty_to_compare <= security_qty: priority = '1' # Normal elif qty_to_compare <= min_qty: priority = '0' # No urgente else: priority = '0' # No urgente if production.priority != priority: production.write({'priority': priority}) return True
class MailMandrillMessage(models.Model): _name = 'mail.mandrill.message' _order = 'timestamp desc' _rec_name = 'name' name = fields.Char(string='Subject', readonly=True) mandrill_id = fields.Char(string='Mandrill message ID', required=True, readonly=True) timestamp = fields.Integer(string='Mandrill UTC timestamp', readonly=True) time = fields.Datetime(string='Mandrill time', readonly=True) date = fields.Date(string='Mandrill date', readonly=True) recipient = fields.Char(string='Recipient email', readonly=True) sender = fields.Char(string='Sender email', readonly=True) state = fields.Selection([ ('deferred', 'Deferred'), ('sent', 'Sent'), ('opened', 'Opened'), ('rejected', 'Rejected'), ('spam', 'Spam'), ('unsub', 'Unsubscribed'), ('bounced', 'Bounced'), ('soft-bounced', 'Soft bounced'), ], string='State', index=True, readonly=True, help=" * The 'Sent' status indicates that message was succesfully " "delivered to recipient Mail Exchange (MX) server.\n" " * The 'Opened' status indicates that message was opened or " "clicked by recipient.\n" " * The 'Rejected' status indicates that recipient email " "address is blacklisted by Mandrill. It is recomended to " "delete this email address.\n" " * The 'Spam' status indicates that Mandrill consider this " "message as spam.\n" " * The 'Unsubscribed' status indicates that recipient has " "requested to be unsubscribed from this message.\n" " * The 'Bounced' status indicates that message was bounced " "by recipient Mail Exchange (MX) server.\n" " * The 'Soft bounced' status indicates that message was soft " "bounced by recipient Mail Exchange (MX) server.\n") bounce_type = fields.Char(string='Bounce type', readonly=True) bounce_description = fields.Char(string='Bounce description', readonly=True) tags = fields.Char(string='Tags', readonly=True) metadata = fields.Text(string='Metadata', readonly=True) event_ids = fields.One2many( string='Mandrill events', comodel_name='mail.mandrill.event', inverse_name='message_id') def _message_prepare(self, message_id, event_type, event): msg = event.get('msg') ts = msg.get('ts', 0) time = datetime.datetime.fromtimestamp(ts) tags = msg.get('tags', []) metadata = msg.get('metadata', {}) metatext = json.dumps(metadata, indent=4) if metadata else False return { 'mandrill_id': message_id, 'timestamp': ts, 'time': time.strftime('%Y-%m-%d %H:%M:%S') if ts else False, 'date': time.strftime('%Y-%m-%d') if ts else False, 'recipient': msg.get('email', False), 'sender': msg.get('sender', False), 'name': msg.get('subject', False), 'tags': ', '.join(tags) if tags else False, 'metadata': metatext, } def _event_prepare(self, message, event_type, event): m_event = self.env['mail.mandrill.event'] method = getattr(m_event, 'process_' + event_type, None) if method and hasattr(method, '__call__'): return method(message, event) else: _logger.info('Unknown event type: %s' % event_type) return False @api.model def process(self, message_id, event_type, event): if not (message_id and event_type and event): return False msg = event.get('msg') message = self.search([('mandrill_id', '=', message_id)]) if msg and not message: data = self._message_prepare(message_id, event_type, event) message = self.create(data) if data else False if message: m_event = self.env['mail.mandrill.event'] data = self._event_prepare(message, event_type, event) return m_event.create(data) if data else False return False
class WebsiteSupportTicketCompose(models.Model): _name = "website.support.ticket.compose" ticket_id = fields.Many2one('website.support.ticket', string='Ticket ID') partner_id = fields.Many2one('res.partner', string="Partner", readonly="True") email = fields.Char(string="Email", readonly="True") subject = fields.Char(string="Subject", readonly="True") body = fields.Text(string="Message Body") template_id = fields.Many2one( 'mail.template', string="Mail Template", domain= "[('model_id','=','website.support.ticket'), ('built_in','=',False)]") approval = fields.Boolean(string="Approval") planned_time = fields.Datetime(string="Planned Time") @api.onchange('template_id') def _onchange_template_id(self): if self.template_id: values = self.env[ 'mail.compose.message'].generate_email_for_composer( self.template_id.id, [self.ticket_id.id])[self.ticket_id.id] self.body = values['body'] @api.one def send_reply(self): #Change the approval state before we send the mail if self.approval: #Change the ticket state to awaiting approval awaiting_approval_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_awaiting_approval') self.ticket_id.state = awaiting_approval_state.id #One support request per ticket... self.ticket_id.planned_time = self.planned_time self.ticket_id.approval_message = self.body self.ticket_id.sla_active = False #Send email values = {} setting_staff_reply_email_template_id = self.env['ir.default'].get( 'website.support.settings', 'staff_reply_email_template_id') if setting_staff_reply_email_template_id: email_wrapper = self.env['mail.template'].browse( setting_staff_reply_email_template_id) values = email_wrapper.generate_email([self.id])[self.id] values['model'] = "website.support.ticket" values['res_id'] = self.ticket_id.id send_mail = self.env['mail.mail'].create(values) #send_mail.send() #Add to the message history to keep the data clean from the rest HTML self.env['website.support.ticket.message'].create({ 'ticket_id': self.ticket_id.id, 'by': 'staff', 'content': self.body.replace("<p>", "").replace("</p>", "") }) #Post in message history #self.ticket_id.message_post(body=self.body, subject=self.subject, message_type='comment', subtype='mt_comment') if self.approval: #Also change the approval awaiting_approval = self.env['ir.model.data'].get_object( 'website_support', 'awaiting_approval') self.ticket_id.approval_id = awaiting_approval.id else: #Change the ticket state to staff replied staff_replied = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_staff_replied') self.ticket_id.state = staff_replied.id
class WebsiteSupportTicket(models.Model): _name = "website.support.ticket" _description = "Website Support Ticket" _order = "create_date desc" _rec_name = "subject" _inherit = ['mail.thread'] _translate = True @api.model def _read_group_state(self, states, domain, order): """ Read group customization in order to display all the states in the kanban view, even if they are empty """ staff_replied_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_staff_replied') customer_replied_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_customer_replied') customer_closed = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_customer_closed') staff_closed = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_staff_closed') exclude_states = [ staff_replied_state.id, customer_replied_state.id, customer_closed.id, staff_closed.id ] # state_ids = states._search([('id','not in',exclude_states)], order=order, access_rights_uid=SUPERUSER_ID) state_ids = states._search([], order=order, access_rights_uid=SUPERUSER_ID) return states.browse(state_ids) def _default_state(self): return self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_open') def _default_state_new(self): state_obj = self.env['website.support.ticket.states'] state = 'Open' open_state = state_obj.search([('name', '=', state)]) #print("========================>",open_state.id) return open_state.id def _default_priority_id(self): default_priority = self.env['website.support.ticket.priority'].search([ ('sequence', '=', '1') ]) return default_priority[0] def _default_approval_id(self): return self.env['ir.model.data'].get_object('website_support', 'no_approval_required') attach_line = fields.One2many('sunfire.ticket.attach', 'attach_id') sun_channel = fields.Many2one('sunfire.ticket.channel', string='Channel') channel = fields.Char(string="Channel", default="Manual") create_user_id = fields.Many2one('res.users', "Create User") priority_id = fields.Many2one('website.support.ticket.priority', default=_default_priority_id, string="Priority") parent_company_id = fields.Many2one(string="Parent Company", related="partner_id.company_id") partner_id = fields.Many2one('res.partner', string="Partner") user_id = fields.Many2one('res.users', string="Assigned User") person_name = fields.Char(string='Person Name') email = fields.Char(string="Email") support_email = fields.Char(string="Support Email") category = fields.Many2one('website.support.ticket.categories', string="Category", track_visibility='onchange') sub_category_id = fields.Many2one('website.support.ticket.subcategory', string="Sub Category") subject = fields.Char(string="Subject") description = fields.Text(string="Description") state = fields.Many2one('website.support.ticket.states', group_expand='_read_group_state', default=_default_state, string="State") conversation_history = fields.One2many('website.support.ticket.message', 'ticket_id', string="Conversation History") attachment = fields.Binary(string="Attachments") attachment_filename = fields.Char(string="Attachment Filename") attachment_ids = fields.One2many('ir.attachment', 'res_id', domain=[('res_model', '=', 'website.support.ticket')], string="Media Attachments") unattended = fields.Boolean( string="Unattended", compute="_compute_unattend", store="True", help= "In 'Open' state or 'Customer Replied' state taken into consideration name changes" ) portal_access_key = fields.Char(string="Portal Access Key") ticket_number = fields.Char(string="Ticket Number", readonly=True, store=True) ticket_color = fields.Char(related="priority_id.color", string="Ticket Color") company_id = fields.Many2one( 'res.company', string="Company", default=lambda self: self.env['res.company']._company_default_get( 'website.support.ticket')) support_rating = fields.Integer(string="Support Rating") support_comment = fields.Text(string="Actions Taken") #comment_temp=fields.Text(string='Actions Taken') close_comment = fields.Text(string="Close Comment") close_time = fields.Datetime(string="Close Time") close_date = fields.Date(string="Close Date") closed_by_id = fields.Many2one('res.users', string="Closed By") time_to_close = fields.Integer(string="Time to close (seconds)") extra_field_ids = fields.One2many('website.support.ticket.field', 'wst_id', string="Extra Details") planned_time = fields.Datetime(string="Planned Time") planned_time_format = fields.Char(string="Planned Time Format", compute="_compute_planned_time_format") approval_id = fields.Many2one('website.support.ticket.approval', default=_default_approval_id, string="Approval") approval_message = fields.Text(string="Approval Message") approve_url = fields.Char(compute="_compute_approve_url", string="Approve URL") disapprove_url = fields.Char(compute="_compute_disapprove_url", string="Disapprove URL") tag_ids = fields.Many2many('website.support.ticket.tag', string="Tags") new_tag_ids = fields.Many2one('sunfire.ticket.tag', string="Tag") sla_id = fields.Many2one('website.support.sla', string="SLA") sla_timer = fields.Float(string="SLA Time Remaining") sla_timer_format = fields.Char(string="SLA Timer Format", compute="_compute_sla_timer_format") sla_active = fields.Boolean(string="SLA Active") sla_response_category_id = fields.Many2one('website.support.sla.response', string="SLA Response Category") sla_alert_ids = fields.Many2many( 'website.support.sla.alert', string="SLA Alerts", help="Keep record of SLA alerts sent so we do not resend them") time_assign = fields.Datetime('Time To Assign') time_open = fields.Datetime('Time To Open') time_resolve = fields.Datetime('Time To Resolve') action_taken_line = fields.One2many('sunfire.actions', 'action_taken_id') status = fields.Selection([('open', 'Open'), ('assigned', 'Assigned'), ('in_progress', 'Work in Progress'), ('awaiting', 'Awaiting Customer'), ('resolved', 'Resolved'), ('closed', 'Closed')], string='Status', readonly=True, copy=False, index=True, track_visibility='onchange', default='open') date_create_new = fields.Date("Create Date", compute='new_date_order', store=True) @api.depends('create_date') def new_date_order(self): lang_obj = self.env['res.lang'] lang = lang_obj.search([("name", "=", "English")]) for dt in self: if dt.create_date != False: temp = datetime.datetime.strptime(dt.create_date, "%Y-%m-%d %H:%M:%S").date() dt.date_create_new = temp else: dt.date_create_new = "" def status_mail(self): email_template = self.env['ir.model.data'].get_object( 'website_support', 'support_ticket_status_mail') email_values = email_template.generate_email([self.id])[self.id] email_values['model'] = "website.support.ticket" email_values['res_id'] = self.id #assigned_user = self.env['res.users'].browse( int(values['user_id']) ) email_values['email_to'] = self.partner_id.email or self.email email_values['body_html'] = email_values['body_html'].replace( "_user_name_", self.partner_id.name) email_values['body'] = email_values['body'].replace( "_user_name_", self.partner_id.name) send_mail = self.env['mail.mail'].create(email_values) #print("here======+>") send_mail.send() @api.multi def action_assigned(self): #self.status_mail() return self.write({ 'status': 'assigned', 'time_assign': datetime.datetime.now() }) @api.multi def action_in_progress(self): #self.status_mail() return self.write({'status': 'in_progress'}) @api.multi def action_awaiting(self): #self.status_mail() return self.write({'status': 'awaiting'}) @api.multi def action_resolved(self): #self.status_mail() return self.write({ 'status': 'resolved', 'time_resolve': datetime.datetime.now() }) @api.multi def action_close(self): #self.status_mail() return self.write({'status': 'closed'}) @api.onchange('user_id') def onchng_user(self): appr_obj = self.env['approval_types.info'].search([ ('approval_type', '=', 'Technical Services') ]) li = [] domain = {} for i in appr_obj.role_line: li.append(i.users.id) domain['user_id'] = [('id', 'in', li)] return {'domain': domain} @api.one @api.depends('sla_timer') def _compute_sla_timer_format(self): # Display negative hours in a positive format self.sla_timer_format = '{0:02.0f}:{1:02.0f}'.format( *divmod(abs(self.sla_timer) * 60, 60)) @api.model def update_sla_timer(self): # Subtract 1 minute from the timer of all active SLA tickets, this includes going into negative for active_sla_ticket in self.env['website.support.ticket'].search([ ('sla_active', '=', True), ('sla_id', '!=', False), ('sla_response_category_id', '!=', False) ]): # If we only countdown during busines hours if active_sla_ticket.sla_response_category_id.countdown_condition == 'business_only': # Check if the current time aligns with a timeslot in the settings, # setting has to be set for business_only or UserError occurs setting_business_hours_id = self.env['ir.default'].get( 'website.support.settings', 'business_hours_id') current_hour = datetime.datetime.now().hour current_minute = datetime.datetime.now().minute / 60 current_hour_float = current_hour + current_minute day_of_week = datetime.datetime.now().weekday() during_work_hours = self.env[ 'resource.calendar.attendance'].search([ ('calendar_id', '=', setting_business_hours_id), ('dayofweek', '=', day_of_week), ('hour_from', '<', current_hour_float), ('hour_to', '>', current_hour_float) ]) # If holiday module is installed take into consideration holiday_module = self.env['ir.module.module'].search([ ('name', '=', 'hr_public_holidays'), ('state', '=', 'installed') ]) if holiday_module: holiday_today = self.env['hr.holidays.public.line'].search( [('date', '=', datetime.datetime.now().date())]) if holiday_today: during_work_hours = False if during_work_hours: active_sla_ticket.sla_timer -= 1 / 60 else: #Countdown even if the business hours setting is not set active_sla_ticket.sla_timer -= 1 / 60 #Send an email out to everyone in the category about the SLA alert notification_template = self.env['ir.model.data'].sudo( ).get_object('website_support', 'support_ticket_sla_alert') for sla_alert in self.env['website.support.sla.alert'].search([ ('vsa_id', '=', active_sla_ticket.sla_id.id), ('alert_time', '>=', active_sla_ticket.sla_timer) ]): #Only send out the alert once if sla_alert not in active_sla_ticket.sla_alert_ids: for my_user in active_sla_ticket.category.cat_user_ids: values = notification_template.generate_email( active_sla_ticket.id) values['body_html'] = values['body_html'].replace( "_user_name_", my_user.partner_id.name) values['email_to'] = my_user.partner_id.email send_mail = self.env['mail.mail'].create(values) #send_mail.send() #Remove the message from the chatter since this would bloat the communication history by a lot send_mail.mail_message_id.res_id = 0 #Add the alert to the list of already sent SLA active_sla_ticket.sla_alert_ids = [(4, sla_alert.id)] def pause_sla(self): self.sla_active = False def resume_sla(self): self.sla_active = True @api.one @api.depends('planned_time') def _compute_planned_time_format(self): #If it is assigned to the partner, use the partners timezone and date formatting if self.planned_time and self.partner_id and self.partner_id.lang: partner_language = self.env['res.lang'].search([ ('code', '=', self.partner_id.lang) ])[0] my_planned_time = datetime.datetime.strptime( self.planned_time, DEFAULT_SERVER_DATETIME_FORMAT) #If we have timezone information translate the planned date to local time otherwise UTC if self.partner_id.tz: my_planned_time = my_planned_time.replace( tzinfo=tz.gettz('UTC')) local_time = my_planned_time.astimezone( tz.gettz(self.partner_id.tz)) self.planned_time_format = local_time.strftime( partner_language.date_format + " " + partner_language.time_format) + " " + self.partner_id.tz else: self.planned_time_format = my_planned_time.strftime( partner_language.date_format + " " + partner_language.time_format) + " UTC" else: self.planned_time_format = self.planned_time @api.one def _compute_approve_url(self): self.approve_url = "/support/approve/" + str(self.id) @api.one def _compute_disapprove_url(self): self.disapprove_url = "/support/disapprove/" + str(self.id) @api.onchange('sub_category_id') def _onchange_sub_category_id(self): if self.sub_category_id: add_extra_fields = [] for extra_field in self.sub_category_id.additional_field_ids: add_extra_fields.append((0, 0, {'name': extra_field.name})) self.update({ 'extra_field_ids': add_extra_fields, }) @api.onchange('partner_id') def _onchange_partner_id(self): self.person_name = self.partner_id.name self.email = self.partner_id.email def message_new(self, msg, custom_values=None): """ Create new support ticket upon receiving new email""" defaults = { 'support_email': msg.get('to'), 'subject': msg.get('subject') } #Extract the name from the from email if you can if "<" in msg.get('from') and ">" in msg.get('from'): start = msg.get('from').rindex("<") + 1 end = msg.get('from').rindex(">", start) from_email = msg.get('from')[start:end] from_name = msg.get('from').split("<")[0].strip() defaults['person_name'] = from_name else: from_email = msg.get('from') defaults['email'] = from_email defaults['channel'] = "Email" #Try to find the partner using the from email search_partner = self.env['res.partner'].sudo().search([('email', '=', from_email)]) if len(search_partner) > 0: defaults['partner_id'] = search_partner[0].id defaults['person_name'] = search_partner[0].name defaults['description'] = tools.html_sanitize(msg.get('body')) #Assign to default category setting_email_default_category_id = self.env['ir.default'].get( 'website.support.settings', 'email_default_category_id') if setting_email_default_category_id: defaults['category'] = setting_email_default_category_id return super(WebsiteSupportTicket, self).message_new(msg, custom_values=defaults) def message_update(self, msg_dict, update_vals=None): """ Override to update the support ticket according to the email. """ body_short = tools.html_sanitize(msg_dict['body']) #body_short = tools.html_email_clean(msg_dict['body'], shorten=True, remove=True) #Add to message history to keep HTML clean self.conversation_history.create({ 'ticket_id': self.id, 'by': 'customer', 'content': body_short }) #If the to email address is to the customer then it must be a staff member if msg_dict.get('to') == self.email: change_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_staff_replied') else: change_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_customer_replied') self.state = change_state.id return super(WebsiteSupportTicket, self).message_update(msg_dict, update_vals=update_vals) @api.one @api.depends('state') def _compute_unattend(self): #BACK COMPATABLITY Use open and customer reply as default unattended states opened_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_open') customer_replied_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_customer_replied') if self.state == opened_state or self.state == customer_replied_state or self.state.unattended == True: self.unattended = True @api.multi def request_approval(self): approval_email = self.env['ir.model.data'].get_object( 'website_support', 'support_ticket_approval') values = self.env['mail.compose.message'].generate_email_for_composer( approval_email.id, [self.id])[self.id] request_message = values['body'] return { 'name': "Request Approval", 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'website.support.ticket.compose', 'context': { 'default_ticket_id': self.id, 'default_email': self.email, 'default_subject': self.subject, 'default_approval': True, 'default_body': request_message }, 'target': 'new' } @api.multi def open_close_ticket_wizard(self): return { 'name': "Close Support Ticket", 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'website.support.ticket.close', 'context': { 'default_ticket_id': self.id }, 'target': 'new' } @api.model def _needaction_domain_get(self): open_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_open') custom_replied_state = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_customer_replied') return [ '|', ('state', '=', open_state.id), ('state', '=', custom_replied_state.id) ] #assigns ticket number def set_ticket_number(self, vals): print("vals", vals) tag_obj = self.env['sunfire.ticket.tag'] sun_tag_ids = tag_obj.search([('id', '=', vals['new_tag_ids'])]) vals['time_open'] = datetime.datetime.now() if sun_tag_ids.name == "Incident": print("Incident") vals['ticket_number'] = self.env['ir.sequence'].next_by_code( 'website.support.ticket.incident') elif sun_tag_ids.name == "Request": print("Request") vals['ticket_number'] = self.env['ir.sequence'].next_by_code( 'website.support.ticket.request') else: print("else") vals['ticket_number'] = self.env['ir.sequence'].next_by_code( 'website.support.ticket') @api.model def create(self, vals): # Get next ticket number from the sequence # vals['ticket_number'] = self.env['ir.sequence'].next_by_code('website.support.ticket') #call the function which assigns the ticket number self.set_ticket_number(vals) new_id = super(WebsiteSupportTicket, self).create(vals) new_id.portal_access_key = randint(1000000000, 2000000000) ticket_open_email_template = self.env['ir.model.data'].get_object( 'website_support', 'website_ticket_state_open').mail_template_id ticket_open_email_template.send_mail(new_id.id, True) #Check if this contact has a SLA assigned if new_id.partner_id.sla_id: #Check if this category has a SLA response time category_response = self.env[ 'website.support.sla.response'].search([ ('vsa_id', '=', new_id.partner_id.sla_id.id), ('category_id', '=', new_id.category.id) ]) if category_response: new_id.sla_id = new_id.partner_id.sla_id.id new_id.sla_active = True new_id.sla_timer = category_response.response_time new_id.sla_response_category_id = category_response.id #Send an email out to everyone in the category notification_template = self.env['ir.model.data'].sudo().get_object( 'website_support', 'new_support_ticket_category') support_ticket_menu = self.env['ir.model.data'].sudo().get_object( 'website_support', 'website_support_ticket_menu') support_ticket_action = self.env['ir.model.data'].sudo().get_object( 'website_support', 'website_support_ticket_action') for my_user in new_id.category.cat_user_ids: values = notification_template.generate_email(new_id.id) values['body_html'] = values['body_html'].replace( "_ticket_url_", "web#id=" + str(new_id.id) + "&view_type=form&model=website.support.ticket&menu_id=" + str(support_ticket_menu.id) + "&action=" + str(support_ticket_action.id)).replace("_user_name_", my_user.partner_id.name) values['email_to'] = my_user.partner_id.email send_mail = self.env['mail.mail'].create(values) #send_mail.send() #Remove the message from the chatter since this would bloat the communication history by a lot send_mail.mail_message_id.res_id = 0 return new_id @api.multi def write(self, values, context=None): update_rec = super(WebsiteSupportTicket, self).write(values) if 'state' in values: if self.state.mail_template_id: self.state.mail_template_id.send_mail(self.id, True) #Email user if category has changed if 'category' in values: change_category_email = self.env['ir.model.data'].sudo( ).get_object('website_support', 'new_support_ticket_category_change') change_category_email.send_mail(self.id, True) if 'user_id' in values: setting_change_user_email_template_id = self.env['ir.default'].get( 'website.support.settings', 'change_user_email_template_id') if setting_change_user_email_template_id: email_template = self.env['mail.template'].browse( setting_change_user_email_template_id) else: #Default email template email_template = self.env['ir.model.data'].get_object( 'website_support', 'support_ticket_user_change') email_values = email_template.generate_email([self.id])[self.id] email_values['model'] = "website.support.ticket" email_values['res_id'] = self.id assigned_user = self.env['res.users'].browse(int( values['user_id'])) email_values['email_to'] = assigned_user.partner_id.email email_values['body_html'] = email_values['body_html'].replace( "_user_name_", assigned_user.name) email_values['body'] = email_values['body'].replace( "_user_name_", assigned_user.name) send_mail = self.env['mail.mail'].create(email_values) #send_mail.send() return update_rec def send_survey(self): notification_template = self.env['ir.model.data'].sudo().get_object( 'website_support', 'support_ticket_survey') values = notification_template.generate_email(self.id) surevey_url = "support/survey/" + str(self.portal_access_key) values['body_html'] = values['body_html'].replace( "_survey_url_", surevey_url) send_mail = self.env['mail.mail'].create(values) send_mail.send(True)
class RequestGroupAction(models.Model): _name = "hc.request.group.action" _description = "Request Group Action" request_group_id = fields.Many2one( comodel_name="hc.res.request.group", string="Request Group", help="Request Group associated with this Request Group Action.") action_identifier_id = fields.Many2one( comodel_name="hc.request.group.action.action.identifier", string="Action Identifier", help="Unique identifier.") label = fields.Char( string="Label", help="User-visible label for the action (e.g. 1. or A.).") title = fields.Char(string="Title", help="User-visible title.") description = fields.Text(string="Description", help="Short description of the action.") text_equivalent = fields.Text( string="Text Equivalent", help= "Static text equivalent of the action, used if the dynamic aspects cannot be interpreted by the receiving system." ) code_ids = fields.Many2many( comodel_name="hc.vs.action.code", relation="request_group_action_code_rel", string="Codes", help="The meaning of the action or its sub-actions.") documentation_ids = fields.One2many( comodel_name="hc.request.group.action.documentation", inverse_name="action_id", string="Documentation", help= "Supporting documentation for the intended performer of the action.") timing_type = fields.Selection( string="Timing Type", selection=[("dateTime", "Datetime"), ("Period", "Period"), ("Duration", "Duration"), ("Range", "Range"), ("Timing", "Timing")], help="Type of when the action should take place.") timing_name = fields.Char(string="Timing", compute="_compute_timing_name", store="True", help="When the action should take place.") timing_datetime = fields.Datetime( string="Timing Datetime", help="When the action should take place.") timing_start_date = fields.Datetime( string="Timing Start Date", help="Start of when the action should take place.") timing_end_date = fields.Datetime( string="Timing End Date", help="End of when the action should take place.") timing_duration = fields.Float( string="Timing Duration", help="Duration when the action should take place.") timing_duration_uom_id = fields.Many2one( comodel_name="product.uom", string="Timing Duration UOM", domain="[('category_id','=','Time (UCUM)')]", help="Timing Duration unit of measure.") timing_range_low = fields.Float( string="Timing Range Low", help="Low limit of when the action should take place.") timing_range_high = fields.Float( string="Timing Range High", help="High limit of when the action should take place.") timing_range_uom_id = fields.Many2one(comodel_name="product.uom", string="Timing Range UOM", help="Timing Range unit of measure.") timing_id = fields.Many2one(comodel_name="hc.request.group.action.timing", string="Timing", help="When the action should take place.") participant_ids = fields.One2many( comodel_name="hc.request.group.action.participant", inverse_name="action_id", string="Participants", help="Participant.") type = fields.Selection( string="Type", selection=[("create", "Create"), ("update", "Update"), ("remove", "Remove"), ("fire-event", "Fire-Event")], help="The type of action to perform (create, update, remove).") grouping_behavior = fields.Selection( string="Grouping Behavior", selection=[("visual-group", "Visual-Group"), ("logical-group", "Logical-Group"), ("sentence-group", "Sentence-Group")], help="Defines the grouping behavior for the action and its children.") selection_behavior = fields.Selection( string="Selection Behavior", selection=[("any", "Any"), ("all", "All"), ("all-or-none", "All-Or-None"), ("exactly-one", "Exactly-One"), ("at-most-one", "At-Most-One"), ("one-or-more", "One-Or-More")], help="Defines the selection behavior for the action and its children.") required_behavior = fields.Selection( string="Required Behavior", selection=[("must", "Must"), ("could", "Could"), ("must-unless-documented", "Must-Unless-Documented")], help="Defines the requiredness behavior for the action.") precheck_behavior = fields.Selection( string="Precheck Behavior", selection=[("yes", "Yes"), ("no", "No")], help="Defines whether the action should usually be preselected.") cardinality_behavior = fields.Selection( string="Cardinality Behavior", selection=[("single", "Single"), ("multiple", "Multiple")], help="Defines whether the action can be selected multiple times.") resource_string = fields.Char(string="Resource String", help="String of the target of the action.") resource_code_id = fields.Many2one( comodel_name="hc.vs.resource.type", string="Resource Code", help="Code of the target of the action.") condition_ids = fields.One2many( comodel_name="hc.request.group.action.condition", inverse_name="action_id", string="Conditions", help="Whether or not the action is applicable.") related_action_ids = fields.One2many( comodel_name="hc.request.group.action.related.action", inverse_name="action_id", string="Related Actions", help="Relationship to another action.")
class project_task(models.Model): _inherit = "project.task" _order = "sequence" @api.model def create(self, vals): vals['reference'] = self.env['ir.sequence'].get('project.Task') return super(project_task, self).create(vals) user_id = fields.Many2one('res.users', 'Assigned to', select=True, track_visibility='onchange', default="") actor_ids = fields.Many2many(comodel_name='project.scrum.actors', string='Actor') sprint_id = fields.Many2one(comodel_name='project.scrum.sprint', string='Sprint', store=True) us_id = fields.Many2one(comodel_name='project.scrum.us', string='User Stories') date_start = fields.Datetime(string='Starting Date', required=False, default=fields.Datetime.now()) date_end = fields.Datetime(string='Ending Date', required=False) use_scrum = fields.Boolean(related='project_id.use_scrum') description = fields.Html('Description') current_sprint = fields.Boolean(compute='_current_sprint', string='Current Sprint', search='_search_current_sprint') moscow = fields.Selection([ (1, 'must'), (2, 'should'), (3, 'could'), (4, 'wont'), ('not_set', 'Not Set'), ], string='Moscow') value = fields.Selection([ (0, '0'), (0.5, '0.5'), (1, '1'), (2, '2'), (3, '3'), (5, '5'), (8, '8'), (13, '13'), \ (20, '20'), (40, '40'), (100, '100'), (00, 'Not Set'), ], string='Value') risk = fields.Selection([ (0, '0'), (1, '1'), (2, '2'), (3, '3'), (5, '5'), (8, '8'), (13, '13'), (20, '20'), \ (40, '40'), (100, '100'), (00, 'Not Set'), ], string='Risk') kano = fields.Selection([ ('excitement', 'Excitement'), ('indifferent', 'Indifferent'), ('mandatory', 'Mandatory'), \ ('performance', 'Performance'), ('questionable', 'Questionable'), ('reverse', 'Reverse'), ('not_set', 'Not Set'), ], string='Kano') color = fields.Integer(related='project_id.color') reference = fields.Char('Number', select=True, readonly=True, copy=False, default=':') @api.depends('sprint_id') @api.one def _current_sprint(self): sprint = self.env['project.scrum.sprint'].get_current_sprint(self.project_id.id) #~ _logger.error('Task computed %r' % self) if sprint: self.current_sprint = sprint.id == self.sprint_id.id else: self.current_sprint = False def _search_current_sprint(self, operator, value): #~ raise Warning('operator %s value %s' % (operator, value)) project_id = self.env.context.get('default_project_id', None) sprint = self.env['project.scrum.sprint'].get_current_sprint(project_id) #~ raise Warning('sprint %s csprint %s context %s' % (self.sprint_id, sprint, self.env.context)) _logger.error('Task %r' % self) return [('sprint_id', '=', sprint and sprint.id or None)] @api.multi def write(self, vals): if vals.get('stage_id') == self.env.ref('project.project_stage_data_2').id: vals['date_end'] = fields.datetime.now() return super(project_task, self).write(vals) @api.model def _read_group_sprint_id(self, present_ids, domain, **kwargs): project = self.env['project.project'].browse(self._resolve_project_id_from_context()) if project.use_scrum: sprints = self.env['project.scrum.sprint'].search([('project_id', '=', project.id)], order='sequence').name_get() return sprints, None else: return [], None @api.model def _read_group_us_id(self, present_ids, domain, **kwargs): project = self.env['project.project'].browse(self._resolve_project_id_from_context()) if project.use_scrum: user_stories = self.env['project.scrum.us'].search([('project_id', '=', project.id)], order='sequence').name_get() return user_stories, None else: return [], None
class ShiftShift(models.Model): _inherit = 'event.event' _name = 'shift.shift' _description = 'Shift Template' @api.model def _default_shift_mail_ids(self): return [(0, 0, { 'interval_unit': 'now', 'interval_type': 'after_sub', 'template_id': self.env.ref('coop_shift.shift_subscription') })] name = fields.Char(string="Shift Name") event_mail_ids = fields.One2many(default=None) shift_mail_ids = fields.One2many( 'shift.mail', 'shift_id', string='Mail Schedule', default=lambda self: self._default_shift_mail_ids()) shift_type_id = fields.Many2one('shift.type', string='Category', required=False, readonly=False, states={'done': [('readonly', True)]}) week_number = fields.Selection(WEEK_NUMBERS, string='Week', compute="_compute_week_number", store=True) week_list = fields.Selection([('MO', 'Monday'), ('TU', 'Tuesday'), ('WE', 'Wednesday'), ('TH', 'Thursday'), ('FR', 'Friday'), ('SA', 'Saturday'), ('SU', 'Sunday')], 'Weekday') registration_ids = fields.One2many('shift.registration', 'shift_id', string='Attendees', readonly=False, states={'done': [('readonly', True)]}) shift_template_id = fields.Many2one('shift.template', string='Template', ondelete='restrict') seats_reserved = fields.Integer(compute='_compute_seats_shift') seats_available = fields.Integer(compute='_compute_seats_shift') seats_unconfirmed = fields.Integer(compute='_compute_seats_shift') seats_used = fields.Integer(compute='_compute_seats_shift') seats_expected = fields.Integer(compute='_compute_seats_shift') auto_confirm = fields.Boolean(string='Confirmation not required', compute='_compute_auto_confirm') event_ticket_ids = fields.One2many( default=lambda rec: rec._default_tickets()) shift_ticket_ids = fields.One2many( 'shift.ticket', 'shift_id', string='Shift Ticket', default=lambda rec: rec._default_shift_tickets(), copy=True) date_tz = fields.Selection('_tz_get', string='Timezone', default=False) date_begin = fields.Datetime(compute="_compute_date_begin", store=True, required=False) date_begin_tz = fields.Datetime(string='Begin Date Time') date_end = fields.Datetime(compute="_compute_date_end", store=True, required=False) date_end_tz = fields.Datetime(string='End Date Time') date_without_time = fields.Date(string='Date', compute='_compute_begin_date_fields', store=True, multi="begin_date") begin_date_string = fields.Char(string='Begin Date', compute='_compute_begin_date_fields', store=True, multi="begin_date") end_date_for_mail = fields.Char(string='End Date for mail', compute='_compute_end_date_fields', store=True, multi="end_date") begin_date_without_time_string = fields.Char( string='Begin Date for mail without time', multi="begin_date", compute='_compute_begin_date_fields') begin_time = fields.Float(string='Start Time', compute='_compute_begin_date_fields', store=True, multi="begin_date") begin_time_string = fields.Char(string='Start Time', compute='_compute_begin_date_fields', multi="begin_date") end_time = fields.Float(string='Start Time', compute='_compute_end_date_fields', store=True, multi="end_date") end_time_for_mail = fields.Char(string='End Time', compute='_compute_end_date_fields', multi="end_date") user_ids = fields.Many2many('res.partner', 'res_partner_shift_shift_rel', 'shift_template_id', 'partner_id', string='Shift Leaders') user_id = fields.Many2one(comodel_name='res.partner', default=False) seats_max = fields.Integer() _sql_constraints = [ ('template_date_uniq', 'unique (shift_template_id, date_begin, company_id)', 'The same template cannot be planned several time at the same date !' ), ] @api.multi @api.depends('date_without_time') def _compute_week_number(self): for shift in self: if not shift.date_without_time: shift.week_number = False else: weekA_date = fields.Date.from_string( self.env.ref('coop_shift.config_parameter_weekA').value) start_date = fields.Date.from_string(shift.date_without_time) shift.week_number =\ 1 + (((start_date - weekA_date).days // 7) % 4) @api.model def name_search(self, name, args=None, operator='ilike', limit=100): args = args or [] domain = [] if name: domain = [ '|', ('begin_date_string', operator, name), ('name', operator, name) ] if operator in expression.NEGATIVE_TERM_OPERATORS: domain = ['&', '!'] + domain[1:] shifts = self.search(domain + args, limit=limit) return shifts.name_get() @api.multi @api.depends('name', 'date_begin') def name_get(self): result = [] for shift in self: name = shift.name + (shift.begin_date_string and (' ' + shift.begin_date_string) or '') result.append((shift.id, name)) return result @api.model def _default_tickets(self): return None @api.model def _default_shift_tickets(self): try: product = self.env.ref('coop_shift.product_product_shift_standard') product2 = self.env.ref('coop_shift.product_product_shift_ftop') return [{ 'name': _('Standard'), 'product_id': product.id, 'price': 0, }, { 'name': _('FTOP'), 'product_id': product2.id, 'price': 0, }] except ValueError: return self.env['shift.ticket'] @api.multi def _compute_auto_confirm(self): for shift in self: shift.auto_confirm = False @api.model def _default_event_mail_ids(self): return None @api.multi @api.depends('seats_max', 'registration_ids.state') def _compute_seats_shift(self): """ Determine reserved, available, reserved but unconfirmed and used seats. """ # initialize fields to 0 for shift in self: shift.seats_unconfirmed = shift.seats_reserved =\ shift.seats_used = shift.seats_available = 0 # aggregate registrations by shift and by state if self.ids: state_field = { 'draft': 'seats_reserved', 'open': 'seats_reserved', 'replacing': 'seats_reserved', 'done': 'seats_used', } query = """ SELECT shift_id, state, count(shift_id) FROM shift_registration WHERE shift_id IN %s AND state IN ('draft', 'open', 'done', 'replacing') GROUP BY shift_id, state """ self._cr.execute(query, (tuple(self.ids), )) for shift_id, state, num in self._cr.fetchall(): shift = self.browse(shift_id) shift[state_field[state]] += num # compute seats_available for shift in self: if shift.seats_max > 0: shift.seats_available = shift.seats_max - ( shift.seats_reserved + shift.seats_used) shift.seats_expected = shift.seats_unconfirmed +\ shift.seats_reserved + shift.seats_used @api.multi def write(self, vals, special=[]): if any(shift.state == "done" for shift in self): raise UserError( _('You can only repercute changes on draft shifts.')) res = super(ShiftShift, self).write(vals) for field in special: if field == 'shift_ticket_ids': for shift in self: template = shift.shift_template_id ftop_ticket = template.shift_ticket_ids.filtered( lambda t: t.shift_type == 'ftop') standard_ticket = template.shift_ticket_ids.filtered( lambda t: t.shift_type == 'standard') ftop_seats_max = ftop_ticket and ftop_ticket[0].seats_max\ or False standard_seats_max = standard_ticket and\ standard_ticket[0].seats_max or False for ticket in shift.shift_ticket_ids: if ticket.shift_type == 'ftop': ticket.seats_max = ftop_seats_max if ticket.shift_type == 'standard': ticket.seats_max = standard_seats_max return res @api.onchange('shift_template_id') def _onchange_template_id(self): if self.shift_template_id: self.name = self.shift_template_id.name self.user_ids = self.shift_template_id.user_ids self.shift_type_id = self.shift_template_id.shift_type_id self.week_number = self.shift_template_id.week_number cur_date = self.date_begin and datetime.strptime( self.date_begin, "%Y-%m-%d %H:%M:%S").date() or\ datetime.strptime( self.shift_template_id.start_date, "%Y-%m-%d") self.date_begin = datetime.strftime( cur_date + timedelta(hours=self.shift_template_id.start_time), "%Y-%m-%d %H:%M:%S") self.date_end = datetime.strftime( cur_date + timedelta(hours=self.shift_template_id.end_time), "%Y-%m-%d %H:%M:%S") cur_attendees = [r.partner_id.id for r in self.registration_ids] vals = [] for attendee in self.shift_template_id.registration_ids: if attendee.id not in cur_attendees: vals.append((0, 0, { 'partner_id': attendee.id, 'state': 'draft', 'email': attendee.email, 'phone': attendee.phone, 'name': attendee.name, 'shift_id': self.id, })) self.registration_ids = vals @api.depends('date_begin_tz') @api.multi def _compute_date_begin(self): tz_name = self._context.get('tz') or self.env.user.tz if not tz_name: raise UserError( _("You can not create Shift if your timezone is not defined.")) context_tz = pytz.timezone(tz_name) for shift in self: if shift.date_begin_tz: start_date_object_tz = fields.Datetime.from_string( shift.date_begin_tz) utc_timestamp = pytz.utc.localize(start_date_object_tz, is_dst=False) start_date_object = utc_timestamp.astimezone(context_tz) start_date = start_date_object_tz + timedelta( hours=start_date_object_tz.hour - start_date_object.hour) shift.date_begin = "%s-%02d-%02d %02d:%02d:%02d" % ( start_date.year, start_date.month, start_date.day, start_date.hour, start_date.minute, start_date.second, ) @api.depends('date_end_tz') @api.multi def _compute_date_end(self): tz_name = self._context.get('tz') or self.env.user.tz if not tz_name: raise UserError( _("You can not create Shift if your timezone is not defined.")) context_tz = pytz.timezone(tz_name) for shift in self: if shift.date_end_tz: end_date_object_tz = fields.Datetime.from_string( shift.date_end_tz) utc_timestamp = pytz.utc.localize(end_date_object_tz, is_dst=False) end_date_object = utc_timestamp.astimezone(context_tz) end_date = end_date_object_tz + timedelta( hours=end_date_object_tz.hour - end_date_object.hour) shift.date_end = "%s-%02d-%02d %02d:%02d:%02d" % ( end_date.year, end_date.month, end_date.day, end_date.hour, end_date.minute, end_date.second, ) @api.multi @api.depends('date_begin_tz') def _compute_begin_date_fields(self): for shift in self: if shift.date_begin_tz: start_date_object_tz = datetime.strptime( shift.date_begin_tz, '%Y-%m-%d %H:%M:%S') shift.begin_time = (start_date_object_tz.hour + (start_date_object_tz.minute / 60.0)) shift.begin_time_string = "%02d:%02d" % ( start_date_object_tz.hour, start_date_object_tz.minute, ) shift.begin_date_string = "%02d/%02d/%s %02d:%02d" % ( start_date_object_tz.day, start_date_object_tz.month, start_date_object_tz.year, start_date_object_tz.hour, start_date_object_tz.minute, ) shift.begin_date_without_time_string = "%02d/%02d/%s" % ( start_date_object_tz.day, start_date_object_tz.month, start_date_object_tz.year, ) shift.date_without_time = "%s-%02d-%02d" % ( start_date_object_tz.year, start_date_object_tz.month, start_date_object_tz.day, ) @api.multi @api.depends('date_end') def _compute_end_date_fields(self): tz_name = self._context.get('tz') or self.env.user.tz if not tz_name: raise UserError( _("You can not create Shift if your timezone is not defined.")) for shift in self: shift.end_date_for_mail = datetime.strftime( fields.Datetime.from_string(shift.date_end), "%d/%m/%Y %H:%M") shift.end_time_for_mail = datetime.strftime( fields.Datetime.from_string(shift.date_end), "%H:%M") if shift.date_end: start_date_object = datetime.strptime(shift.date_end, '%Y-%m-%d %H:%M:%S') utc_timestamp = pytz.utc.localize(start_date_object, is_dst=False) context_tz = pytz.timezone(tz_name) start_date_object_tz = utc_timestamp.astimezone(context_tz) shift.end_time = (start_date_object_tz.hour + (start_date_object_tz.minute / 60.0)) @api.multi def button_confirm(self): super(ShiftShift, self).button_confirm() @api.model def run_shift_confirmation(self): # This method is called by the cron task compare_date = fields.Date.to_string(datetime.today() + timedelta( days=SHIFT_CONFIRMATION_DAYS)) shifts = self.env['shift.shift'].search([('state', '=', 'draft'), ('date_begin', '<=', compare_date)]) shifts.button_confirm() @api.one @api.constrains('seats_max', 'seats_available') def _check_seats_limit(self): return True
class Edocument(models.AbstractModel): _name = 'account.edocument' _FIELDS = { 'account.invoice': 'invoice_number', 'account.retention': 'name' } SriServiceObj = SriService() clave_acceso = fields.Char('Clave de Acceso', size=49, readonly=True) numero_autorizacion = fields.Char('Número de Autorización', size=37, readonly=True) estado_autorizacion = fields.Char('Estado de Autorización', size=64, readonly=True) fecha_autorizacion = fields.Datetime('Fecha Autorización', readonly=True) ambiente = fields.Char('Ambiente', size=64, readonly=True) autorizado_sri = fields.Boolean('¿Autorizado SRI?', readonly=True) security_code = fields.Char('Código de Seguridad', size=8, readonly=True) emission_code = fields.Char('Tipo de Emisión', size=1, readonly=True) epayment_id = fields.Many2one('account.epayment', 'Forma de Pago') sent = fields.Boolean('Enviado?') def get_auth(self, document): partner = document.company_id.partner_id if document._name == 'account.invoice': return document.auth_inv_id elif document._name == 'account.retention': return partner.get_authorisation('ret_in_invoice') def get_secuencial(self): return getattr(self, self._FIELDS[self._name])[6:] def _info_tributaria(self, document, access_key, emission_code): """ """ company = document.company_id auth = self.get_auth(document) infoTributaria = { 'ambiente': self.env.user.company_id.env_service, 'tipoEmision': emission_code, 'razonSocial': company.name, 'nombreComercial': company.name, 'ruc': company.partner_id.identifier, 'claveAcceso': access_key, 'codDoc': utils.tipoDocumento[auth.type_id.code], 'estab': auth.serie_entidad, 'ptoEmi': auth.serie_emision, 'secuencial': self.get_secuencial(), 'dirMatriz': company.street } return infoTributaria def get_code(self): code = self.env['ir.sequence'].next_by_code('edocuments.code') return code def get_access_key(self, name): if name == 'account.invoice': auth = self.company_id.partner_id.get_authorisation('out_invoice') ld = self.date_invoice.split('-') numero = getattr(self, 'invoice_number') elif name == 'account.retention': auth = self.company_id.partner_id.get_authorisation( 'ret_in_invoice') # noqa ld = self.date.split('-') numero = getattr(self, 'name') numero = numero[6:15] ld.reverse() fecha = ''.join(ld) tcomp = utils.tipoDocumento[auth.type_id.code] ruc = self.company_id.partner_id.identifier codigo_numero = self.get_code() tipo_emision = self.company_id.emission_code access_key = ([fecha, tcomp, ruc], [numero, codigo_numero, tipo_emision]) return access_key @api.multi def _get_codes(self, name='account.invoice'): ak_temp = self.get_access_key(name) self.SriServiceObj.set_active_env(self.env.user.company_id.env_service) access_key = self.SriServiceObj.create_access_key(ak_temp) emission_code = self.company_id.emission_code return access_key, emission_code @api.multi def check_before_sent(self): """ """ MESSAGE_SEQUENCIAL = ' '.join([ u'Los comprobantes electrónicos deberán ser', u'enviados al SRI para su autorización en orden cronológico', 'y secuencial. Por favor enviar primero el', ' comprobante inmediatamente anterior.' ]) FIELD = { 'account.invoice': 'invoice_number', 'account.retention': 'name' } number = getattr(self, FIELD[self._name]) sql = ' '.join([ "SELECT autorizado_sri, %s FROM %s" % (FIELD[self._name], self._table), # noqa "WHERE state='open' AND %s < '%s'" % (FIELD[self._name], number), # noqa self._name == 'account.invoice' and "AND type = 'out_invoice'" or '', # noqa "ORDER BY %s DESC LIMIT 1" % FIELD[self._name] ]) self.env.cr.execute(sql) res = self.env.cr.fetchone() if not res: return True auth, number = res if auth is None and number: raise UserError(MESSAGE_SEQUENCIAL) return True def check_date(self, date_invoice): """ Validar que el envío del comprobante electrónico se realice dentro de las 24 horas posteriores a su emisión """ LIMIT_TO_SEND = 5 MESSAGE_TIME_LIMIT = u' '.join([ u'Los comprobantes electrónicos deben', u'enviarse con máximo 24h desde su emisión.' ]) dt = datetime.strptime(date_invoice, '%Y-%m-%d') days = (datetime.now() - dt).days if days > LIMIT_TO_SEND: raise UserError(MESSAGE_TIME_LIMIT) @api.multi def update_document(self, auth, codes): fecha = auth.fechaAutorizacion.strftime(DEFAULT_SERVER_DATETIME_FORMAT) self.write({ 'numero_autorizacion': auth.numeroAutorizacion, 'estado_autorizacion': auth.estado, 'ambiente': auth.ambiente, 'fecha_autorizacion': fecha, # noqa 'autorizado_sri': True, 'clave_acceso': codes[0], 'emission_code': codes[1] }) @api.one def add_attachment(self, xml_element, auth): buf = StringIO.StringIO() buf.write(xml_element.encode('utf-8')) document = base64.encodestring(buf.getvalue()) buf.close() attach = self.env['ir.attachment'].create( { 'name': '{0}.xml'.format(self.clave_acceso), 'datas': document, 'datas_fname': '{0}.xml'.format(self.clave_acceso), 'res_model': self._name, 'res_id': self.id, 'type': 'binary' }, ) return attach @api.multi def send_document(self, attachments=None, tmpl=False): self.ensure_one() self._logger.info('Enviando documento electronico por correo') tmpl = self.env.ref(tmpl) tmpl.send_mail( # noqa self.id, email_values={'attachment_ids': attachments}) self.sent = True return True def render_document(self, document, access_key, emission_code): pass
class WizEventDeleteAssistant(models.TransientModel): _name = 'wiz.event.delete.assistant' from_date = fields.Date(string='From date', required=True) to_date = fields.Date(string='To date', required=True) registration = fields.Many2one(comodel_name='event.registration', string='Partner registration') partner = fields.Many2one(comodel_name='res.partner', string='Partner', required=True) min_event = fields.Many2one(comodel_name='event.event', string='Min. event') min_from_date = fields.Datetime(string='Min. from date', required=True) max_event = fields.Many2one(comodel_name='event.event', string='Max. event') max_to_date = fields.Datetime(string='Max. to date', required=True) past_sessions = fields.Boolean(string='Past Sessions', compute='_compute_past_later_sessions') later_sessions = fields.Boolean(string='Later Sessions', compute='_compute_past_later_sessions') message = fields.Char(string='Message', readonly=True, compute='_compute_past_later_sessions') notes = fields.Text(string='Notes') removal_date = fields.Date( string='Removal date', default=lambda self: fields.Date.context_today(self)) @api.model def default_get(self, var_fields): tz = self.env.user.tz res = super(WizEventDeleteAssistant, self).default_get(var_fields) events = self.env['event.event'].browse( self.env.context.get('active_ids')) if events: from_date = _convert_to_local_date( min(events.mapped('date_begin')), tz) to_date = _convert_to_local_date(max(events.mapped('date_end')), tz) min_event = events.sorted(key=lambda e: e.date_begin)[:1] max_event = events.sorted(key=lambda e: e.date_end, reverse=True)[:1] res.update({ 'from_date': date2str(from_date.date()), 'to_date': date2str(to_date.date()), 'min_from_date': datetime2str(from_date), 'max_to_date': datetime2str(to_date), 'min_event': min_event.id, 'max_event': max_event.id, }) return res @api.depends('from_date', 'to_date', 'partner') def _compute_past_later_sessions(self): event_track_obj = self.env['event.track'] if self.from_date and self.to_date and self.partner: if self.registration: sessions = self.partner.mapped( 'presence_ids.session').filtered( lambda x: x.event_id.id == self.registration.event_id. id) else: sessions = self.partner.mapped( 'presence_ids.session').filtered( lambda x: x.event_id.id in self.env.context.get( 'active_ids')) cond = self._prepare_track_condition_from_date(sessions) self.past_sessions = bool(event_track_obj.search(cond, limit=1)) cond = self._prepare_track_condition_to_date(sessions) self.later_sessions = bool(event_track_obj.search(cond, limit=1)) if self.past_sessions and self.later_sessions: self.message = _('This person has sessions with dates before' ' and after') elif self.past_sessions: self.message = _('This person has sessions with dates before') elif self.later_sessions: self.message = _('This person has sessions with dates after') @api.multi @api.onchange('from_date', 'to_date') def onchange_dates(self): self.ensure_one() res = {} from_date, to_date =\ self._prepare_dates_for_search_registrations() min_from_date = self._prepare_date_for_control(self.min_from_date, time=0.0) max_to_date = self._prepare_date_for_control(self.max_to_date, time=24.0) if from_date and to_date and from_date > to_date: self.revert_dates() return { 'warning': { 'title': _('Error in from date'), 'message': (_('From date greater than date to')) } } if from_date and from_date < min_from_date: self.revert_dates() return { 'warning': { 'title': _('Error in from date'), 'message': (_('From date less than start date of the event %s') % self.min_event.name) } } if to_date and to_date > max_to_date: self.revert_dates() return { 'warning': { 'title': _('Error in to date'), 'message': (_('To date greater than end date of the event %s') % self.max_event.name) } } return res def _prepare_date_for_control(self, date, time=0.0): date = str2datetime(date) if isinstance(date, str) else date new_date = datetime2str( _convert_to_utc_date(date.date(), time=time, tz=self.env.user.tz)) return new_date def _prepare_track_condition_from_date(self, sessions): from_date, to_date = self._prepare_dates_for_search_registrations() cond = [('id', 'in', sessions.ids), ('date', '!=', False), ('date', '<', from_date)] return cond def _prepare_track_condition_to_date(self, sessions): from_date, to_date = self._prepare_dates_for_search_registrations() cond = [('id', 'in', sessions.ids), ('date', '!=', False), ('date', '>', to_date)] return cond @api.multi def action_delete(self): self.ensure_one() cond = [('event_id', 'in', self.env.context.get('active_ids')), ('partner_id', '=', self.partner.id), ('state', '=', 'open')] registrations = self.env['event.registration'].search(cond)\ if not self.registration else self.registration registrations._cancel_registration(self.from_date, self.to_date, self.removal_date, self.notes) return self._open_event_tree_form() def _prepare_dates_for_search_registrations(self): from_date = self._prepare_date_for_control(self.from_date, time=0.0) to_date = self._prepare_date_for_control(self.to_date, time=24.0) return from_date, to_date def revert_dates(self): tz = self.env.user.tz self.from_date = _convert_to_local_date(self.min_from_date, tz=tz).date() self.to_date = _convert_to_local_date(self.max_to_date, tz=tz).date() def _open_event_tree_form(self): active_ids = self.env.context.get('active_ids', []) view_mode = 'kanban,calendar,tree,form' if len(active_ids) > 1 else\ 'form,kanban,calendar,tree' result = { 'name': _('Event'), 'type': 'ir.actions.act_window', 'res_model': 'event.event', 'view_type': 'form', 'view_mode': view_mode, 'res_id': active_ids[0], 'target': 'current', 'context': self.env.context } return result
class eq_shipcloud(models.Model): _name = "eq.shipcloud" _description = "This module helps to integrate Odoo with shipcloud api" _rec_name = "eq_id" _order = "create_date desc" create_date = fields.Datetime(string="Creation Date") eq_id = fields.Char(string="Shipment ID", copy=False, help="Shipcloud shipments ID", required=True) eq_carrier_tracking_no = fields.Char(string="Carrier tracking nos", copy=False, help="shipments tracking nos") eq_tracking_url = fields.Text(string="Tracking URL", copy=False, help="shipments tracking URL") eq_label_url = fields.Text(string="Label URL", copy=False, help="Label URL") eq_price = fields.Float(string="Price", help="Price") eq_package = fields.Many2one('stock.quant.package', string="Package", help="Denote the shipment related package") _sql_constraints = [ ('eq_id_package_unique', 'unique(eq_id, eq_package)', 'Shipments ID and Package must be unique!'), ] @api.multi def eq_opentrack_url(self): if self.eq_tracking_url: webbrowser.open(self.eq_tracking_url) @api.multi def eq_openlabel_url(self): if self.eq_label_url: webbrowser.open(self.eq_label_url) @api.v7 def eq_check_pack_valid(self, cr, uid, pack_operation_data, context): if pack_operation_data.result_package_id.ul_id.height <=0 or pack_operation_data.result_package_id.ul_id.length <=0 or \ pack_operation_data.result_package_id.ul_id.width <=0 or pack_operation_data.eq_gross_weight <= 0: return False return True @api.v7 def eq_create_shipcloud(self, cr, uid, result, context=None): if result: """ Converting unicode string dictionary into dictionary in python """ for res in result: d = ast.literal_eval(res.get('response').text) if d.get('id') == None: return False data = { 'eq_id': d.get('id') or None, 'eq_carrier_tracking_no': d.get('carrier_tracking_no') or None, 'eq_tracking_url': d.get('tracking_url') or None, 'eq_label_url': d.get('label_url') or None, 'eq_price': d.get('price') or None, 'eq_package': res.get('package_id') or None } eq_shipcloud_id = self.create(cr, uid, data, context=None) return True @api.v7 def eq_shipcloud_service_url(self, cr, uid, context=None): """ Get the shipcloud service url """ url = self.pool.get('ir.config_parameter').get_param( cr, uid, "eq.shipcloud.service.url", False) or None return url @api.v7 def eq_shipcloud_api_key(self, cr, uid, context=None): """ Get the shipcloud apikey """ config_obj = self.pool.get('ir.config_parameter') if config_obj.get_param(cr, uid, "eq.is.sandbox.apikey", False) == 'True': key = config_obj.get_param(cr, uid, "eq.shipcloud.sandbox.apikey", False) else: key = config_obj.get_param(cr, uid, "eq.shipcloud.apikey", False) return key @api.v7 def _get_to_data(self, cr, uid, picking_data): res = {} partner = picking_data.partner_id if not partner.eq_house_no: raise (_('Error!'), _('The house no. for the delivery address is not defined.')) if partner.type in ('default', 'delivery', 'pobox', 'other'): if partner.eq_name2: res["to[company]"] = partner.name res["to[last_name]"] = partner.eq_name2 else: res["to[last_name]"] = partner.name elif partner.type == "contact": if partner.eq_name2: res["to[company]"] = partner.eq_name2 res["to[first_name]"] = partner.eq_firstname res["to[last_name]"] = partner.name if partner.use_parent_address: res["to[street]"] = partner.street or None, res["to[street_no]"] = partner.eq_house_no or None, res["to[city]"] = partner.city or None, res["to[zip_code]"] = partner.zip or None, res["to[country]"] = partner.country_id.name or None, else: res["to[street]"] = partner.parent_id.street or None, res["to[street_no]"] = partner.parent_id.eq_house_no or None, res["to[city]"] = partner.parent_id.city or None, res["to[zip_code]"] = partner.parent_id.zip or None, res["to[country]"] = partner.parent_id.country_id.name or None, return res @api.v7 def _get_from_data(self, cr, uid, picking_data): company = picking_data.company_id if not company.eq_house_no: raise Warning(_('The house no. for the company is not defined.')) res = { "from[last_name]": company.name or None, "from[street]": company.street or None, "from[street_no]": company.eq_house_no or None, "from[city]": company.city or None, "from[zip_code]": company.zip or None, "from[country]": company.country_id.name or None, } return res @api.v7 def eq_create_shipments(self, cr, uid, picking_id, context=None): """ If Delivery order has no package, then shipments will not be created. """ data = {} result = {} final_result = [] count = 0 if picking_id: # Get the shipcloud apikey api_key = self.eq_shipcloud_api_key(cr, uid, context=None) if api_key == None: raise osv.except_osv(_('Error!'), _('Please provide shipcloud apikey.')) stock_pick_obj = self.pool.get("stock.picking") stock_quant_package_obj = self.pool.get('stock.quant.package') shipcloud_deliverymethod_obj = self.pool.get( 'eq.shipcloud.deliverymethod') picking_data = stock_pick_obj.browse(cr, uid, picking_id, context=None) delivery_ids = shipcloud_deliverymethod_obj.search( cr, uid, [('eq_deliverymethod_id', '=', picking_data.carrier_id.id)], context=None) if delivery_ids: delivery_data = shipcloud_deliverymethod_obj.browse( cr, uid, delivery_ids, context=None)[0] if (not delivery_data.eq_sc_carrier) or ( not delivery_data.eq_sc_service_id): raise osv.except_osv( _('Error!'), _(' Only when a delivery method is connected with shipcloud carrier and Service a shipment at shipcloud is created.' )) else: raise osv.except_osv( _('Error!'), _(' Only when a delivery method is connected with shipcloud carrier and Service a shipment at shipcloud is created.' )) if picking_data.pack_operation_ids: for pack_operation_data in picking_data.pack_operation_ids: # If the Delivery Order has no destination package - throws exception if not pack_operation_data.result_package_id: raise osv.except_osv( _('Error!'), _('Please provide Destination packages for Shipments.' )) # Check valid package dimensions is_package_valid = self.eq_check_pack_valid( cr, uid, pack_operation_data, context=None) if not is_package_valid: raise osv.except_osv( _('Error!'), _('Please provide valid dimensions values for packages.' )) # Avoid creating duplicate entries if stock_quant_package_obj.browse( cr, uid, pack_operation_data.result_package_id.id, context=None).eq_is_processed: continue data = { "carrier": delivery_data.eq_sc_carrier or None, "package[weight]": pack_operation_data.result_package_id. eq_gross_weight_changed or pack_operation_data.result_package_id.eq_gross_weight, "package[length]": pack_operation_data.result_package_id.ul_id.length, "package[width]": pack_operation_data.result_package_id.ul_id.width, "package[height]": pack_operation_data.result_package_id.ul_id.height, "service": delivery_data.eq_sc_service_id.eq_name or None, "create_shipping_label": 'true', } to_data = self._get_to_data(cr, uid, picking_data) from_data = self._get_from_data(cr, uid, picking_data) data.update(to_data) data.update(from_data) #Creating a shipment try: #Get the shipcloud serice url service_url = self.eq_shipcloud_service_url( cr, uid, context=None) res = requests.post(service_url + '/v1/shipments', data=data, auth=(api_key, '')) count += 1 #adding package id to the result result = { 'package_id': pack_operation_data.result_package_id.id, 'response': res, 'picking_id': picking_id, } final_result.append(result) stock_quant_package_obj.write( cr, uid, pack_operation_data.result_package_id.id, {'eq_is_processed': True}, context=context) except Exception, e: _logger.exception(e) stock_pick_obj.write(cr, uid, picking_id, { 'eq_is_shipped': True, 'eq_is_processed': True }, context=context) return final_result return False
class CenitDataTypeTrigger(models.Model): _name = "cenit.data_type.trigger" data_type = fields.Many2one("cenit.data_type", "Data Type") name = fields.Selection([ ("on_create", "On creation"), ("on_write", "On update"), ("on_create_or_write", "On creation or update"), ("interval", "On interval"), ("only_manual", "Only manually"), ], required=True) cron = fields.Many2one('ir.cron', string='Cron rules') cron_lapse = fields.Integer("Interval number", default=10) cron_units = fields.Selection([('minutes', 'Minutes'), ('hours', 'Hours'), ('work_days', 'Work Days'), ('days', 'Days'), ('weeks', 'Weeks'), ('months', 'Months')], string="Interval units", default='minutes') cron_restrictions = fields.Selection([("create", "Newly created"), ("update", "Newly updated"), ("all", "All")], string="Restrictions", default="all") base_action_rules = fields.Many2many('base.action.rule', string='Action Rules') last_execution = fields.Datetime() @api.one def unlink(self): if self.cron: self.cron.unlink() if self.base_action_rules: for bar in self.base_action_rules: bar.server_action_ids.unlink() self.base_action_rules.unlink() return super(CenitDataTypeTrigger, self).unlink() @api.one def sync(self): if not self.data_type.enabled: if self.cron: self.cron.unlink() if self.base_action_rules: for bar in self.base_action_rules: bar.server_action_ids.unlink() self.base_action_rules.unlink() if self.name == 'only_manual': if self.base_action_rules: for bar in self.base_action_rules: bar.server_action_ids.unlink() self.base_action_rules.unlink() elif self.cron: self.cron.unlink() if self.name == 'interval': ic_obj = self.env['ir.cron'] if self.cron: vals_ic = { 'name': 'send_%s_%s' % (self.cron_restrictions, self.data_type.model.model), 'interval_number': self.cron_lapse, 'interval_type': self.cron_units, } _logger.info("\n\nWRITE IC: %s\n", vals_ic) self.cron.write(vals_ic) else: vals_ic = { 'name': 'send_%s_%s' % (self.cron_restrictions, self.data_type.model.model), 'interval_number': self.cron_lapse, 'interval_type': self.cron_units, 'numbercall': -1, 'model': 'cenit.data_type', 'function': 'perform_scheduled_action', 'args': '(%s,)' % str(self.data_type.id) } _logger.info("\n\nCREATE IC: %s\n", vals_ic) ic = ic_obj.create(vals_ic) self.with_context(local=True).write({'cron': ic.id}) if self.base_action_rules: for bar in self.base_action_rules: bar.server_action_ids.unlink() self.base_action_rules.unlink() elif self.name in ('on_create', 'on_write', 'on_create_or_write'): ias_obj = self.env['ir.actions.server'] bar_obj = self.env['base.action.rule'] if self.base_action_rules: for bar in self.base_action_rules: bar.server_action_ids.unlink() self.base_action_rules.unlink() rules = [] action_name = 'send_one_%s_as_%s' % (self.data_type.model.model, self.data_type.cenit_root) cd = "self.pool.get('{}').browse(cr, uid, {}).trigger_flows(obj)".format( self.data_type._name, self.data_type.id) vals_ias = { 'name': action_name, 'model_id': self.data_type.model.id, 'state': 'code', 'code': cd } ias = ias_obj.create(vals_ias) vals_bar = { 'name': action_name, 'active': True, 'kind': self.name, 'model_id': self.data_type.model.id, 'server_action_ids': [(6, False, [ias.id])] } bar = bar_obj.create(vals_bar) rules.append((4, bar.id, False)) self.with_context(local=True).write({'base_action_rules': rules}) if self.cron: self.cron.unlink() return True
class MgmtSystemAction(models.Model): """Model class that manage action.""" _name = "mgmtsystem.action" _description = "Action" _inherit = ['mail.thread', 'ir.needaction_mixin'] def _default_company(self): """Return the user company id.""" return self.env.user.company_id def _default_owner(self): """Return the user.""" return self.env.user def _default_stage(self): """Return the default stage.""" return self.env['mgmtsystem.action.stage'].search( [('is_starting', '=', True)], limit=1) @api.model def _elapsed_days(self, dt1_text, dt2_text): res = 0 if dt1_text and dt2_text: dt1 = fields.Datetime.from_string(dt1_text) dt2 = fields.Datetime.from_string(dt2_text) res = (dt2 - dt1).days return res @api.depends('opening_date', 'create_date') def _compute_number_of_days_to_open(self): for action in self: action.number_of_days_to_close_open = action._elapsed_days( action.create_date, action.opening_date) @api.depends('date_closed', 'create_date') def _compute_number_of_days_to_close(self): for action in self: action.number_of_days_to_close_open = action._elapsed_days( action.create_date, action.date_closed) name = fields.Char('Subject', required=True) active = fields.Boolean('Active', default=True) date_deadline = fields.Date('Deadline') create_date = fields.Datetime('Create Date', readonly=True, default=fields.datetime.now()) cancel_date = fields.Datetime('Cancel Date', readonly=True) opening_date = fields.Datetime('Opening Date', readonly=True) date_closed = fields.Datetime('Closed Date', readonly=True) number_of_days_to_open = fields.Integer( '# of days to open', compute=_compute_number_of_days_to_open, store=True) number_of_days_to_close = fields.Integer( '# of days to close', compute=_compute_number_of_days_to_close, store=True) reference = fields.Char('Reference', required=True, readonly=True, default="NEW") user_id = fields.Many2one('res.users', 'Responsible', default=_default_owner, required=True) description = fields.Text('Description') type_action = fields.Selection( [('immediate', 'Immediate Action'), ('correction', 'Corrective Action'), ('prevention', 'Preventive Action'), ('improvement', 'Improvement Opportunity')], 'Response Type', required=True) system_id = fields.Many2one('mgmtsystem.system', 'System') company_id = fields.Many2one('res.company', 'Company', default=_default_company) stage_id = fields.Many2one('mgmtsystem.action.stage', 'Stage', default=_default_stage) @api.model def _stage_groups(self, present_ids, domain, **kwargs): """This method is used by Kanban view to show empty stages.""" # perform search # We search here only stage ids stage_ids = self.env['mgmtsystem.action.stage']._search([]) # We search here stages objects result = self.env['mgmtsystem.action.stage'].search([]).name_get() # restore order of the search result.sort( lambda x, y: cmp(stage_ids.index(x[0]), stage_ids.index(y[0]))) return result, None _group_by_full = {'stage_id': _stage_groups} @api.model def _get_stage_new(self): return self.env['mgmtsystem.action.stage'].search( [('is_starting', '=', True)], limit=1) @api.model def _get_stage_open(self): return self.env.ref('mgmtsystem_action.stage_open') @api.model def _get_stage_close(self): return self.env.ref('mgmtsystem_action.stage_close') @api.model def _get_stage_cancel(self): return self.env.ref('mgmtsystem_action.stage_cancel') @api.multi def case_open(self): """ Opens case """ for case in self: case.write({'active': True, 'stage_id': case._get_stage_open().id}) return True
class MrpSegment(models.Model): _name = "mrp.segment" _description = "MRP Segment" _rec_name = 'name' def _default_stock_location(self): try: warehouse = self.env['ir.model.data'].get_object( 'stock', 'warehouse0') return warehouse.lot_stock_id.id except: return False name = fields.Char(string=_('Segment Reference'), required=True, readonly=True, states={'draft': [('readonly', False)]}, help=_('Segment Name.')) date = fields.Datetime( string=_('Segment Date'), required=True, readonly=True, default=fields.Datetime.now, help=_('The date that will be used for the segment.')) state = fields.Selection([('draft', 'Draft'), ('cancel', 'Cancelled'), ('confirm', 'In Progress'), ('done', 'Validated')], string=_('Status'), readonly=True, select=True, default='draft', copy=False) location_id = fields.Many2one('stock.location', string=_('Segment Location'), required=True, readonly=True, states={'draft': [('readonly', False)]}, default=_default_stock_location) company_id = fields.Many2one('res.company', string=_('Company'), required=True, select=True, readonly=True, default=lambda self: self.env.user.company_id, states={'draft': [('readonly', False)]}) line_ids = fields.One2many('mrp.segment.line', 'segment_id', string=_('Manufacturing Order Line'), readonly=False, states={'done': [('readonly', True)]}, help=_("Segment Lines."), copy=True) @api.multi def prepare_segment(self): for segment in self: line_ids = [line.id for line in segment.line_ids] if not line_ids: vals = self._get_segment_lines() for production_line in vals: self.env['mrp.segment.line'].create(production_line) return self.write({'state': 'confirm'}) def _get_segment_lines(self): domain = [('missing_qty', '>', 0), ('production_id.location_dest_id', '=', self.location_id.id), ('production_id.state', 'in', ["confirmed", "ready"])] segment_lines = self.env['mrp.production.product.line'].search(domain) vals = [] for line in segment_lines: product_line = dict((fn, 0.0) for fn in [ 'segment_id', 'mrp_production_id', 'product_id', 'quantity', 'sale_name', 'mrp_production_line_id' ]) product_line['segment_id'] = self.id product_line['mrp_production_id'] = line.production_id.id product_line['product_id'] = line.product_id.id product_line['quantity'] = line.missing_qty product_line['sale_name'] = line.production_id.sale_name product_line['mrp_production_line_id'] = line.id vals.append(product_line) return vals
class TestScript(models.Model): _name = "hc.res.test.script" _description = "Test Script" url = fields.Char( string="URI", required="True", help="Logical uri to reference this test script (globally unique).") identifier_id = fields.Many2one( comodel_name="hc.test.script.identifier", string="Identifier", help="Additional identifier for the test script.") version = fields.Char(string="Version", help="Business version of the test script.") name = fields.Char(string="Name", required="True", help="Name for this test script (Computer friendly).") title = fields.Text(string="Title", help="Name for this test script (Human friendly).") status = fields.Selection( string="Test Script Status", required="True", selection=[("draft", "Draft"), ("active", "Active"), ("retired", "Retired")], help= "The status of this test script. Enables tracking the life-cycle of the content." ) is_experimental = fields.Boolean( string="Experimental", help="If for testing purposes, not real usage.") publisher = fields.Char( string="Publisher", help="Name of the publisher (Organization or individual).") contact_ids = fields.One2many(comodel_name="hc.test.script.contact", inverse_name="test_script_id", string="Contacts", help="Contact details for the publisher.") date = fields.Datetime(string="Date", help="Date this was last changed.") description = fields.Text( string="Description", help="Natural language description of the test script.") use_context_ids = fields.One2many( comodel_name="hc.test.script.use.context", inverse_name="test_script_id", string="Use Contexts", help="Content intends to support these contexts.") jurisdiction_ids = fields.Many2many( comodel_name="hc.vs.jurisdiction", relation="test_script_jurisdiction_rel", string="Jurisdictions", help="Intended jurisdiction for test script (if applicable).") purpose = fields.Text(string="Purpose", help="Why this test script is defined.") copyright = fields.Text(string="Copyright", help="Use and/or publishing restrictions.") profile_ids = fields.One2many(comodel_name="hc.test.script.profile", inverse_name="test_script_id", string="Profiles", help="Reference of the validation profile.") origin_ids = fields.One2many( comodel_name="hc.test.script.origin", inverse_name="test_script_id", string="Origins", help= "An abstract server representing a client or sender in a message exchange." ) destination_ids = fields.One2many( comodel_name="hc.test.script.destination", inverse_name="test_script_id", string="Destinations", help= "An abstract server representing a destination or receiver in a message exchange." ) metadata_ids = fields.One2many( comodel_name="hc.test.script.metadata", inverse_name="test_script_id", string="Metadata", help= "Required capability that is assumed to function correctly on the FHIR server being tested." ) fixture_ids = fields.One2many( comodel_name="hc.test.script.fixture", inverse_name="test_script_id", string="Fixtures", help= "Fixture in the test script - either by reference (uri) or embedded (Resource)." ) variable_ids = fields.One2many(comodel_name="hc.test.script.variable", inverse_name="test_script_id", string="Variables", help="Placeholder for evaluated elements.") rule_ids = fields.One2many(comodel_name="hc.test.script.rule", inverse_name="test_script_id", string="Rules", required="True", help="The referenced rule within the ruleset.") ruleset_ids = fields.One2many( comodel_name="hc.test.script.ruleset", inverse_name="test_script_id", string="Rulesets", help="Assert ruleset used within the test script.") setup_ids = fields.One2many( comodel_name="hc.test.script.setup", inverse_name="test_script_id", string="Setups", help="A series of required setup operations before tests are executed." ) test_ids = fields.One2many(comodel_name="hc.test.script.test", inverse_name="test_script_id", string="Tests", help="A test in this script.") teardown_ids = fields.One2many(comodel_name="hc.test.script.teardown", inverse_name="test_script_id", string="Teardowns", help="A series of required clean up steps.")
class AccountInvoicePresentation(models.Model): _name = 'account.invoice.presentation' def get_period(self): """ Genera un string con el periodo seleccionado. :return: string con periodo ej : '201708' """ split_from = self.date_from.split('-') return split_from[0] + split_from[1] def get_invoices(self): return self.env['account.invoice'].search([ ('state', 'not in', ('cancel', 'draft')), ('date', '>=', self.date_from), ('date', '<=', self.date_to), ('company_id', '=', self.company_id.id), ]) @staticmethod def get_total_notTaxed_taxes(invoice, data): not_taxed_taxes = invoice.tax_line_ids.filtered( lambda t: t.tax_id in [data.tax_sale_ng, data.tax_purchase_ng]) return sum(not_taxed_taxes.mapped('amount')) def validate_invoices(self, data): """ Validamos que las facturas tengan los datos necesarios. """ foreign_fiscal_positions = [ self.env.ref( 'l10n_ar_afip_tables.account_fiscal_position_cliente_ext'), self.env.ref( 'l10n_ar_afip_tables.account_fiscal_position_prov_ext'), ] errors = [] for partner in self.invoices.mapped('partner_id'): if not partner.property_account_position_id: errors.append("El partner {} no posee posicion fiscal.".format( partner.name)) if not partner.partner_document_type_id: errors.append( "El partner {} no posee tipo de documento.".format( partner.name)) if not partner.vat and partner.property_account_position_id not in foreign_fiscal_positions: errors.append( "El partner {} no posee numero de documento.".format( partner.name)) if partner.property_account_position_id in foreign_fiscal_positions and not \ (partner.country_id and partner.country_id.vat): errors.append( "El partner {} no posee pais con documento.".format( partner.name)) for invoice in self.invoices: if not invoice.move_id.line_ids.filtered( lambda x: x.account_id == invoice.account_id): errors.append( "La cuenta de la factura {} no se encuentra en el asiento de la misma." .format(invoice.name_get()[0][1])) if invoice.amount_total == 0: errors.append("El total de la factura {} es cero.".format( invoice.name)) if not invoice.move_id.line_ids: errors.append( "La factura {} no posee lineas de asientos.".format( invoice.name)) if self.get_total_notTaxed_taxes(invoice, data): errors.append( "La factura {} posee montos en los impuestos no gravados.". format(invoice.name)) if errors: raise Warning( "ERROR\nLa presentacion no pudo ser generada por los siguientes motivos:\n{}" .format("\n".join(errors))) def generate_header_file(self): raise NotImplementedError def generate_presentations(self, data): purchase_builder = presentation.Presentation('ventasCompras', 'comprasCbte') purchase_iva_builder = presentation.Presentation( 'ventasCompras', 'comprasAlicuotas') purchase_import_builder = presentation.Presentation( 'ventasCompras', 'comprasImportaciones') sale_builder = presentation.Presentation('ventasCompras', 'ventasCbte') sale_iva_builder = presentation.Presentation('ventasCompras', 'ventasAlicuotas') self.purchase_presentation = PurchaseInvoicePresentation( data=data, builder=purchase_builder, with_prorate=self.with_prorate) self.purchase_iva_presentation = PurchaseIvaPresentation( data=data, builder=purchase_iva_builder) self.purchase_import_presentation = PurchaseImportationPresentation( data=data, builder=purchase_import_builder) self.sale_presentation = SaleInvoicePresentation(data=data, builder=sale_builder) self.sale_iva_presentation = SaleVatInvoicePresentation( data=data, builder=sale_iva_builder) def generate_files(self): """ Genera todas las presentaciones. A cada archivo generado le pone un nombre que se usa para crear el nombre del fichero. Luego llama a la funcion que colocara todos los archivos en un fichero zip. """ # Traemos datos generales invoice_proxy = self.env['account.invoice'] data = GeneralData(invoice_proxy) # Traemos y validamos todas las facturas del periodo seleccionado self.invoices = self.get_invoices() self.validate_invoices(data) # Instanciamos presentaciones self.generate_presentations(data) # Creamos nombre base para los archivos base_name = "REGINFO_CV_{}" + self.get_period() + ".{}" header_file = self.generate_header_file() header_file.file_name = base_name.format("CABECERA_", "txt") sale_file = self.sale_presentation.generate(self.invoices) sale_file.file_name = base_name.format("VENTAS_CBTE_", "txt") sale_vat_file = self.sale_iva_presentation.generate(self.invoices) sale_vat_file.file_name = base_name.format("VENTAS_ALICUOTAS_", "txt") purchase_file = self.purchase_presentation.generate(self.invoices) purchase_file.file_name = base_name.format("COMPRAS_CBTE_", "txt") purchase_vat_file = self.purchase_iva_presentation.generate( self.invoices) purchase_vat_file.file_name = base_name.format("COMPRAS_ALICUOTAS_", "txt") purchase_imports_file = self.purchase_import_presentation.generate( self.invoices) purchase_imports_file.file_name = base_name.format( "COMPRAS_IMPORTACION_", "txt") fiscal_credit_service_import_file = self.generate_fiscal_credit_service_import_file( ) fiscal_credit_service_import_file.file_name = base_name.format( "CREDITO_FISCAL_SERVICIOS_", "txt") # Se genera el archivo zip que contendra los archivos reginfo_zip_file = self.generate_reginfo_zip_file([ header_file, sale_file, sale_vat_file, purchase_file, purchase_vat_file, purchase_imports_file, fiscal_credit_service_import_file ]) #Se escriben en la presentacion los datos generados self.write({ 'generation_time': datetime.now(), 'header_filename': header_file.file_name, 'header_file': header_file.get_encoded_string(), 'sale_filename': sale_file.file_name, 'sale_file': sale_file.get_encoded_string(), 'sale_vat_filename': sale_vat_file.file_name, 'sale_vat_file': sale_vat_file.get_encoded_string(), 'purchase_filename': purchase_file.file_name, 'purchase_file': purchase_file.get_encoded_string(), 'purchase_vat_filename': purchase_vat_file.file_name, 'purchase_vat_file': purchase_vat_file.get_encoded_string(), 'purchase_imports_filename': purchase_imports_file.file_name, 'purchase_imports_file': purchase_imports_file.get_encoded_string(), 'fiscal_credit_service_import_filename': fiscal_credit_service_import_file.file_name, 'fiscal_credit_service_import_file': fiscal_credit_service_import_file.get_encoded_string(), 'reginfo_zip_filename': base_name.format("", "zip"), 'reginfo_zip_file': reginfo_zip_file, }) name = fields.Char( string="Nombre", required=True, ) generation_time = fields.Datetime(string="Fecha y hora de generacion", ) date_from = fields.Date( string="Desde", required=True, ) date_to = fields.Date( string="Hasta", required=True, ) sequence = fields.Char( string="Secuencia", size=2, required=True, default='00', ) with_prorate = fields.Boolean( string="Con prorrateo", default=True, ) header_file = fields.Binary( string="Cabecera", filename="header_filename", ) header_filename = fields.Char(string="Nombre de archivo de cabecera", ) sale_file = fields.Binary( string="Ventas", filename="sale_filename", ) sale_filename = fields.Char(string="Nombre de archivo de ventas", ) sale_vat_file = fields.Binary( string="Ventas alicuotas", filename="sale_vat_filename", ) sale_vat_filename = fields.Char( string="Nombre de archivo de ventas alicuotas", ) purchase_file = fields.Binary( string="Compras", filename="purchase_filename", ) purchase_filename = fields.Char(string="Nombre de archivo de compras", ) purchase_vat_file = fields.Binary( string="Compras alicuotas", filename="purchase_vat_filename", ) purchase_vat_filename = fields.Char( string="Nombre de archivo de compras alicuotas", ) purchase_imports_file = fields.Binary( string="Compras importaciones", filename="purchase_imports_filename", ) purchase_imports_filename = fields.Char( string="Nombre de archivo de compras importaciones", ) fiscal_credit_service_import_file = fields.Binary( string="Credito fiscal de importacion de servicios", filename="fiscal_credit_service_import_filename", ) fiscal_credit_service_import_filename = fields.Char( string= "Nombre de archivo de credito fiscal de importacion de servicios", ) reginfo_zip_file = fields.Binary( string="ZIP de regimen de informacion", filename="reginfo_zip_filename", ) reginfo_zip_filename = fields.Char( string="Nombre de archivo ZIP de regimen de informacion", ) company_id = fields.Many2one( string="Compania", comodel_name="res.company", required=True, default=lambda self: self.pool['res.company']._company_default_get( self.env.user.company_id), ) @staticmethod def generate_fiscal_credit_service_import_file(): """ Esta presentacion no se utiliza actualmente """ raise NotImplementedError @staticmethod def generate_reginfo_zip_file(files): """ Instancia el exportador en zip de ficheros de la API, y exporta todas las presentaciones. :param files: generators de las presentaciones :return: archivo zip """ exporter = presentation.PresentationZipExporter() map(lambda file: exporter.add_element(file), files) return exporter.export_elements() @api.constrains('date_from', 'date_to') def check_dates(self): if self.date_from > self.date_to: raise ValidationError( "La fecha 'desde' no puede ser mayor a la fecha 'hasta'.")
class maintenance_project(models.Model): _inherit = 'maintenance.project' state = fields.Selection( selection=[('draft', 'Draft'), ( 'quotation_todo', 'Quote To Do'), ('quotation_done', 'Quote Done'), ('active', 'Active'), ('disabled', 'Disabled')]) quotation_todo_date = fields.Datetime('Ask Date', readonly=True, translate=True) quotation_done_date = fields.Datetime('Date Done', readonly=True, translate=True) quotation_prices = fields.One2many('maintenance.project.quotation.price', 'project_id', 'Quotation prices') @api.one def _get_mail_users(self): #TODO: Add filter in another module to filter Project Warehouse with user warehouse - In order to extend it easily, created function _get_mail_users """ @return users:A recordset with users """ users = self.env['res.users'].search([ ('receive_project_quotation_request', '=', True) ]) return users # Send a mail to people that belongs to the same sale shop and # whom have checked that they want to be warned @api.one def _send_todo_mail(self): res = False if (not self.sale_order_id): return False body = _( 'A new maintenance quotation(Project : %s) has just been asked by %s<br/>' ) % (self.code, self.env.user.name) for user in self._get_mail_users(): self.env['mail.mail'].create({ 'email_from': self.env.user.partner_id.email, 'email_to': user.partner_id.email, 'subject': _('New maintenance quotation asked: %s') % (self.code), 'body_html': body, 'res_id': self.id, 'model': 'maintenance.project' }) res = True return res # Send a confirmation mail to the salesman linked to the sale @api.one def _send_done_mail(self): res = False if (not self.sale_order_id): return False body = _('A maintenance quotation(%s) has just been done by %s<br/>' ) % (self.code, self.env.user.name) for user in self._get_mail_users(): self.env['mail.mail'].create({ 'email_from': self.env.user, 'email_to': user.partner_id.email, 'subject': _('Maintenance quotation done: %s') % (self.code), 'body_html': body, 'res_id': self.id, 'model': 'maintenance.project' }) res = True return res @api.one def draft(self): self.state = 'draft' @api.one def quotation_todo(self): self.state = 'quotation_todo' self.quotation_todo_date = datetime.now() self._send_todo_mail() return True @api.one def quotation_done(self): self.state = 'quotation_done' self.quotation_done_date = datetime.now() self._send_done_mail() @api.one def active(self): self.state = 'active' @api.one def disabled(self): self.state = 'disabled' ''' UNUSED def _get_status(self,cr,uid,ids): return False ''' @api.one def generate_quotation_prices(self): for project_type in self.env['maintenance.project.type'].search([]): #find contract type and associated budget rules budget_rules = self.env['maintenance.project.budget.rule'].search([ ('project_type_id', '=', project_type.id) ]) total_cost_price = 0 total_sale_price = 0 for budget_line in self.budget_lines: budget = budget_rules.filtered( lambda r: r.intervention_type_id == budget_line. intervention_type_id) if not budget_line.intervention_type_id or not budget.mapped( 'budget_line_type_id'): raise Warning( _('Please configure budget rule for project type "%s", intervention type "%s" and budget line type "%s".' ) % (project_type.name, budget_line.intervention_type_id.name, budget_line.budget_line_type_id.name)) if budget.filtered( lambda r: r.budget_line_type_id == budget_line. budget_line_type_id and r.included): total_cost_price = total_cost_price + budget_line.cost_price * budget_line.quantity total_sale_price = total_sale_price + budget_line.sale_price * budget_line.quantity self.env['maintenance.project.quotation.price'].create({ 'project_id': self.id, 'project_type_id': project_type.id, 'brut_sale_price': total_sale_price, 'cost_price': total_cost_price }) return True
class StockDdT(models.Model): _inherit = 'stock.ddt' #imposta l'ora di creazione del ddt sempre a 00:00:00 indipendentemente dal timezone def _getDefaultDate(self): src_tstamp_str = tools.datetime.now().strftime('%Y-%m-%d') dst_format = "%Y-%m-%d %H:%M:%S" #format you want to get time in. dst_tz_name = self.env.user.tz to_date_time = (datetime.datetime.combine(datetime.datetime.now(), datetime.time(0, 0))) return to_date_time def _get_company_default(self): if self.partner_id and self.partner_id.company_id: return self.partner_id.company_id return self.env['res.users'].browse(self._uid).company_id weight = fields.Float(string='Peso', copy=False) weight_net = fields.Float(string='Peso Netto', copy=False) date_done = fields.Date(string='Data consegna') carrier_id = fields.Many2one('delivery.carrier', string='Carrier') company_id = fields.Many2one('res.company', string='Company', default=_get_company_default) incoterm_id = fields.Many2one( 'stock.incoterms', string='Condizione di Consegna (Incoterm)', help= "International Commercial Terms are a series of predefined commercial terms used in international transactions." ) user_id = fields.Many2one('res.users', string='Commerciale') payment_term = fields.Many2one('account.payment.term', string='Termine di Pagamento') invoice_id = fields.Many2one('account.invoice', string='Fattura') to_be_invoiced = fields.Boolean(string='Da Fatturare', compute='_get_to_be_invoiced', store=True) picking_ids_return = fields.One2many('stock.picking', 'ddt_id', string='Returned Pickings', readonly=True, compute='_get_pickings_return') ddt_lines_return = fields.One2many('stock.move', 'ddt_id', string='Returned DdT Line', readonly=True, compute='_get_lines_return') total_value = fields.Float(string='Imponibile Totale', compute='_get_total_value', store=False, copy=False) note2 = fields.Text('Note') ddt_date = fields.Date('Data DDT', required=False, store=True, compute='_compute_ddt_date') date = fields.Datetime(required=True, default=_getDefaultDate) @api.depends('date') def _compute_ddt_date(self): for record in self: if not record.date: return date_obj = datetime.datetime.strptime(self.date, '%Y-%m-%d %H:%M:%S') record.ddt_date = date_obj.date() @api.multi #@api.depends('picking_ids', 'picking_ids.state') def _get_total_value(self): for ddt in self: tot = 0.0 for ddt_line in ddt.ddt_lines: if ddt_line.procurement_id and ddt_line.procurement_id.sale_line_id: line = ddt_line.procurement_id.sale_line_id tot += line.price_subtotal * (ddt_line.product_uom_qty / line.product_uom_qty) elif ddt_line.procurement_id and ddt_line.procurement_id.purchase_line_id: line = ddt_line.procurement_id.purchase_line_id tot += line.price_subtotal * (ddt_line.product_uom_qty / line.product_qty) elif ddt_line.purchase_line_id: line = ddt_line.purchase_line_id tot += line.price_subtotal * (ddt_line.product_uom_qty / line.product_qty) for ddt_line in ddt.ddt_lines_return: if ddt_line.procurement_id and ddt_line.procurement_id.sale_line_id: line = ddt_line.procurement_id.sale_line_id tot -= line.price_subtotal * (ddt_line.product_uom_qty / line.product_uom_qty) elif ddt_line.procurement_id and ddt_line.procurement_id.purchase_line_id: line = ddt_line.procurement_id.purchase_line_id tot -= line.price_subtotal * (ddt_line.product_uom_qty / line.product_qty) elif ddt_line.purchase_line_id: line = ddt_line.purchase_line_id tot -= line.price_subtotal * (ddt_line.product_uom_qty / line.product_qty) ddt.total_value = tot @api.multi @api.depends('picking_ids', 'picking_ids.invoice_state') def _get_to_be_invoiced(self): for ddt in self: ddt.to_be_invoiced = False for picking in ddt.picking_ids: if picking.invoice_state == '2binvoiced': ddt.to_be_invoiced = True break @api.multi def _get_pickings_return(self): for ddt in self: for picking in ddt.picking_ids: back_ids = self.pool.get('stock.picking').search( self._cr, self._uid, [('origin', '=', picking.name)], context=self._context) if back_ids: ddt.picking_ids_return |= self.pool.get( 'stock.picking').browse(self._cr, self._uid, back_ids) for ddt in self: for picking in ddt.picking_ids_return: ddt.ddt_lines_return |= picking.move_lines @api.multi def _get_lines_return(self): for ddt in self: for picking in ddt.picking_ids: ddt.ddt_lines |= picking.move_lines @api.onchange('partner_id') def onchange_partner_id(self): self.delivery_address_id = None @api.multi def set_number(self): for ddt in self: if not ddt.name: for pick in ddt.picking_ids: if pick.picking_type_id.ddt_sequence_id: ddt_number = self.pool.get('ir.sequence').next_by_id( self._cr, self._uid, pick.picking_type_id.ddt_sequence_id.id) if ddt_number: ddt.name = ddt_number break @api.multi def action_confirm(self): for ddt in self: if not ddt.ddt_lines: raise except_orm(_('Errore!'), _('Non puoi confermare un DDT senza righe!')) self.write({ 'state': 'confirmed', 'delivery_date': time.strftime('%Y-%m-%dT%H:%M:%S') }) @api.one def copy(self, default=None): default = dict(default or {}) default.update(name=None) return super(StockDdT, self).copy(default) def view_partner_pickings(self, cr, uid, ids, context=None): if context is None: context = {} if isinstance(ids, (int, long)): ids = [ids] t_partner_list = [] for ddt_data in self.browse(cr, uid, ids, context): if ddt_data.partner_id: t_partner_list.append(ddt_data.partner_id.id) if t_partner_list: mod_obj = self.pool.get('ir.model.data') result = mod_obj.get_object_reference( cr, uid, 'l10n_it_ddt_makeover', 'view_picking_makeover_form') view_id = result and result[1] or False return { 'domain': "[('picking_type_id.code','=','outgoing'),('invoice_state','in', ['2binvoiced','none']),('ddt_id','not in', [" + ','.join(map(str, ids)) + "]),('partner_id','in', [" + ','.join(map(str, t_partner_list)) + "]),'|',('ddt_id','=', None),('ddt_id','=', False)]", 'name': _("Picking del Cliente"), 'view_type': 'form', 'view_mode': 'tree,form', 'res_model': 'stock.picking', 'type': 'ir.actions.act_window', 'context': context, 'views': [(False, 'tree'), (view_id, 'form')], } return True @api.multi def write(self, values): ''' if 'ddt_date' in values and values['ddt_date']: values.update({'date': values.get('ddt_date')}) ''' return super(StockDdT, self).write(values) @api.model def create(self, values): return super(StockDdT, self).create(values)
class event_registration(models.Model): _name = 'event.registration' _description = 'Attendee' _inherit = ['mail.thread', 'ir.needaction_mixin'] _order = 'name, create_date desc' origin = fields.Char( string='Source Document', readonly=True, help= "Reference of the document that created the registration, for example a sale order" ) event_id = fields.Many2one('event.event', string='Event', required=True, readonly=True, states={'draft': [('readonly', False)]}) partner_id = fields.Many2one('res.partner', string='Contact', states={'done': [('readonly', True)]}) date_open = fields.Datetime(string='Registration Date', readonly=True, default=lambda self: fields.datetime.now() ) # weird crash is directly now date_closed = fields.Datetime(string='Attended Date', readonly=True) event_begin_date = fields.Datetime(string="Event Start Date", related='event_id.date_begin', readonly=True) event_end_date = fields.Datetime(string="Event End Date", related='event_id.date_end', readonly=True) company_id = fields.Many2one('res.company', string='Company', related='event_id.company_id', store=True, readonly=True, states={'draft': [('readonly', False)]}) state = fields.Selection([('draft', 'Unconfirmed'), ('cancel', 'Cancelled'), ('open', 'Confirmed'), ('done', 'Attended')], string='Status', default='draft', readonly=True, copy=False, track_visibility='onchange') email = fields.Char(string='Email') phone = fields.Char(string='Phone') name = fields.Char(string='Attendee Name', select=True) @api.one @api.constrains('event_id', 'state') def _check_seats_limit(self): if self.event_id.seats_availability == 'limited' and self.event_id.seats_max and self.event_id.seats_available < ( 1 if self.state == 'draft' else 0): raise ValidationError(_('No more seats available for this event.')) @api.multi def _check_auto_confirmation(self): if self._context.get('registration_force_draft'): return False if any(registration.event_id.state != 'confirm' or not registration.event_id.auto_confirm or ( not registration.event_id.seats_available and registration.event_id.seats_availability == 'limited') for registration in self): return False return True @api.model def create(self, vals): registration = super(event_registration, self).create(vals) if registration._check_auto_confirmation(): registration.sudo().confirm_registration() return registration @api.model def _prepare_attendee_values(self, registration): """ Method preparing the values to create new attendees based on a sale order line. It takes some registration data (dict-based) that are optional values coming from an external input like a web page. This method is meant to be inherited in various addons that sell events. """ partner_id = registration.pop('partner_id', self.env.user.partner_id) event_id = registration.pop('event_id', False) data = { 'name': registration.get('name', partner_id.name), 'phone': registration.get('phone', partner_id.phone), 'email': registration.get('email', partner_id.email), 'partner_id': partner_id.id, 'event_id': event_id and event_id.id or False, } data.update({ key: registration[key] for key in registration.keys() if key in self._fields }) return data @api.one def do_draft(self): self.state = 'draft' @api.one def confirm_registration(self): self.state = 'open' # auto-trigger after_sub (on subscribe) mail schedulers, if needed onsubscribe_schedulers = self.event_id.event_mail_ids.filtered( lambda s: s.interval_type == 'after_sub') onsubscribe_schedulers.execute() @api.one def button_reg_close(self): """ Close Registration """ today = fields.Datetime.now() if self.event_id.date_begin <= today: self.write({'state': 'done', 'date_closed': today}) else: raise UserError( _("You must wait for the starting day of the event to do this action." )) @api.one def button_reg_cancel(self): self.state = 'cancel' @api.onchange('partner_id') def _onchange_partner(self): if self.partner_id: contact_id = self.partner_id.address_get().get('contact', False) if contact_id: contact = self.env['res.partner'].browse(contact_id) self.name = self.name or contact.name self.email = self.email or contact.email self.phone = self.phone or contact.phone @api.multi def message_get_suggested_recipients(self): recipients = super(event_registration, self).message_get_suggested_recipients() try: for attendee in self: if attendee.partner_id: attendee._message_add_suggested_recipient( recipients, partner=attendee.partner_id, reason=_('Customer')) elif attendee.email: attendee._message_add_suggested_recipient( recipients, email=attendee.email, reason=_('Customer Email')) except AccessError: # no read access rights -> ignore suggested recipients pass return recipients @api.multi def action_send_badge_email(self): """ Open a window to compose an email, with the template - 'event_badge' message loaded by default """ self.ensure_one() template = self.env.ref('event.event_registration_mail_template_badge') compose_form = self.env.ref('mail.email_compose_message_wizard_form') ctx = dict( default_model='event.registration', default_res_id=self.id, default_use_template=bool(template), default_template_id=template.id, default_composition_mode='comment', ) return { 'name': _('Compose Email'), 'type': 'ir.actions.act_window', 'view_type': 'form', 'view_mode': 'form', 'res_model': 'mail.compose.message', 'views': [(compose_form.id, 'form')], 'view_id': compose_form.id, 'target': 'new', 'context': ctx, }
class BuktiPotongTaxform1721A1(models.Model): _name = "l10n_id.bukti_potong_taxform_1721a1" _inherit = [ "mail.thread", "tier.validation", "base.sequence_document", "base.workflow_policy_object", "base.cancel.reason_common", "custom.info.mixin", ] _description = "Bukti Potong Taxform 1721 A1" _state_from = ["draft", "confirm"] _state_to = ["done"] @api.model def _default_company_id(self): return self.env.user.company_id.id @api.model def _default_pemotong_pajak_id(self): return self.env.user.company_id.partner_id.id @api.model def _default_date(self): return datetime.now().strftime("%Y-%m-%d") @api.depends( "penghasilan_01", "penghasilan_02", "penghasilan_03", "penghasilan_04", "penghasilan_05", "penghasilan_06", "penghasilan_07", ) @api.multi def _compute_penghasilan(self): for penghasilan in self: penghasilan.penghasilan_08 = 0.0 penghasilan.penghasilan_08 = ( penghasilan.penghasilan_01 + penghasilan.penghasilan_02 + penghasilan.penghasilan_03 + penghasilan.penghasilan_04 + penghasilan.penghasilan_05 + penghasilan.penghasilan_06 + penghasilan.penghasilan_07 ) @api.depends("penghasilan_08") @api.multi def _compute_jabatan(self): for jabatan in self: obj_biaya_jabatan = self.env["l10n_id.pph_21_biaya_jabatan"] perhitungan_biaya_jabatan = obj_biaya_jabatan.find( jabatan.date ).get_biaya_jabatan( 0.0, jabatan.penghasilan_08, 0, True, ) jabatan.pengurang_09 = perhitungan_biaya_jabatan["biaya_jabatan_setahun"] @api.depends("pengurang_09", "pengurang_10") @api.multi def _compute_pengurang(self): for pengurang in self: pengurang.pengurang_11 = 0.0 pengurang.pengurang_11 = pengurang.pengurang_09 + pengurang.pengurang_10 @api.depends("penghasilan_08", "pengurang_11") @api.multi def _compute_penghasilan_netto(self): for pn in self: pn.perhitungan_12 = 0.0 pn.perhitungan_12 = pn.penghasilan_08 - pn.pengurang_11 @api.depends("perhitungan_12", "perhitungan_13") @api.multi def _compute_penghasilan_netto_setahun(self): for pns in self: pns.perhitungan_14 = 0.0 pns.perhitungan_14 = pns.perhitungan_12 + pns.perhitungan_13 @api.depends("wajib_pajak_ptkp_category_id", "date") @api.multi def _compute_ptkp(self): for getptkp in self: getptkp.perhitungan_15 = 0.0 ptkp_category = getptkp.wajib_pajak_ptkp_category_id if ptkp_category: ptkp = ptkp_category.get_rate(getptkp.date) getptkp.perhitungan_15 = ptkp @api.depends( "perhitungan_14", "perhitungan_15", ) @api.multi def _compute_pkp(self): for pkp in self: pkp.perhitungan_16 = 0.0 if pkp.perhitungan_14 > pkp.perhitungan_15: pkp.perhitungan_16 = float( int((pkp.perhitungan_14 - pkp.perhitungan_15) / 1000) * 1000 ) @api.depends( "perhitungan_16", ) @api.multi def _compute_pph21(self): for pph in self: pph_21 = 0.0 if pph.perhitungan_16 > 0: tunj_lain = ( pph.penghasilan_03 + pph.penghasilan_04 + pph.penghasilan_05 + pph.penghasilan_06 ) perhitungan_pph = pph.wajib_pajak_id.compute_pph_21_2110001( 1, pph.end_tax_period_id.date_end, pph.penghasilan_01, pph.penghasilan_02, tunj_lain, pph.penghasilan_07, pph.pengurang_10, 0, 0, 0, 0, 0, 0, True, not pph.wajib_pajak_karyawan_asing, ) pph_21 = perhitungan_pph["pph"] pph.perhitungan_17 = pph_21 @api.depends( "perhitungan_17", "perhitungan_18", ) @api.multi def _compute_hutang_pph(self): for hutpph in self: hutpph.perhitungan_19 = hutpph.perhitungan_17 + hutpph.perhitungan_18 name = fields.Char( string="# Form A1721 A1", required=True, default="/", copy=False, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) company_id = fields.Many2one( string="Company", comodel_name="res.company", required=True, default=lambda self: self._default_company_id(), ondelete="restrict", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) kode_objek_pajak_id = fields.Many2one( string="Kode Objek Pajak", comodel_name="l10n_id.taxform_objek_pajak", ondelete="restrict", required=True, ) date = fields.Date( string="Date", required=True, default=lambda self: self._default_date(), readonly=True, states={ "draft": [ ("readonly", False), ], }, ) tax_year_id = fields.Many2one( string="Tax Year", comodel_name="l10n_id.tax_year", compute=False, readonly=True, required=True, states={ "draft": [ ("readonly", False), ], }, ) start_tax_period_id = fields.Many2one( string="Period Awal", comodel_name="l10n_id.tax_period", required=True, readonly=True, ondelete="restrict", states={ "draft": [ ("readonly", False), ], }, ) end_tax_period_id = fields.Many2one( string="Period Akhir", comodel_name="l10n_id.tax_period", compute=False, required=True, readonly=True, ondelete="restrict", states={ "draft": [ ("readonly", False), ], }, ) pemotong_pajak_id = fields.Many2one( string="Pemotong Pajak", comodel_name="res.partner", required=True, ondelete="restrict", default=lambda self: self._default_pemotong_pajak_id(), readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_id = fields.Many2one( string="Wajib Pajak", comodel_name="res.partner", required=True, ondelete="restrict", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_npwp = fields.Char( string="NPWP", required=True, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_alamat = fields.Char( string="Alamat", readonly=True, required=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_alamat2 = fields.Char( string="Alamat2", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_zip = fields.Char( string="ZIP", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_kota = fields.Char( string="Kota", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_state_id = fields.Many2one( string="State", comodel_name="res.country.state", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_country_id = fields.Many2one( string="Negara", comodel_name="res.country", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_nik = fields.Char( string="NIK", required=True, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_jenis_kelamin = fields.Selection( [ ("male", "Male"), ("female", "Female"), ("other", "Other"), ], string="Jenis Kelamin", related="wajib_pajak_id.gender", store=False, readonly=True, ) wajib_pajak_ptkp_category_id = fields.Many2one( string="PTKP Kategori", comodel_name="l10n_id.ptkp_category", readonly=True, required=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_job_position = fields.Char( string="Jabatan", readonly=True, required=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_karyawan_asing = fields.Boolean( string="Karyawan Asing", default=False, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) wajib_pajak_kode_negara = fields.Char( string="Kode Negara Domisili", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_01 = fields.Float( string="GAJI/PENSIUN ATAU THT/JHT", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_02 = fields.Float( string="TUNJANGAN PPh", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_03 = fields.Float( string="TUNJANGAN LAINNYA, UANG LEMBUR DAN SEBAGAINYA", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_04 = fields.Float( string="HONORARIUM DAN IMBALAN LAIN SEJENISNYA", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_05 = fields.Float( string="PREMI ASURANSI YANG DIBAYAR PEMBERI KERJA", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_06 = fields.Float( string="PENERIMAAN DALAM BENTUK NATURA DAN KENIKMATAN \ LAINNYA YANG DIKENAKAN PEMOTONGAN PPh PASAL 21", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_07 = fields.Float( string="TANTIEM, BONUS, GRATIFIKASI, JASA PRODUKSI DAN THR", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) penghasilan_08 = fields.Float( string="JUMLAH PENGHASILAN BRUTO (1 S.D. 7)", compute="_compute_penghasilan", store=True, readonly=True, ) pengurang_09 = fields.Float( string="BIAYA JABATAN/BIAYA PENSIUN", compute="_compute_jabatan", store=True, readonly=True, ) pengurang_10 = fields.Float( string="IURAN PENSIUN ATAU IURAN THT/JHT", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) pengurang_11 = fields.Float( string="JUMLAH PENGURANGAN (9 S.D. 10)", compute="_compute_pengurang", store=True, readonly=True, ) perhitungan_12 = fields.Float( string="JUMLAH PENGHASILAN NETO (8 11)", compute="_compute_penghasilan_netto", store=True, readonly=True, ) perhitungan_13 = fields.Float( string="PENGHASILAN NETO MASA SEBELUMNYA", default=0.0, readonly=True, states={ "draft": [ ("readonly", False), ], }, ) perhitungan_14 = fields.Float( string="JUMLAH PENGHASILAN NETO UNTUK PENGHITUNGAN PPh \ PASAL 21 (SETAHUN/DISETAHUNKAN)", compute="_compute_penghasilan_netto_setahun", store=True, readonly=True, ) perhitungan_15 = fields.Float( string="PENGHASILAN TIDAK KENA PAJAK (PTKP)", compute="_compute_ptkp", store=True, readonly=True, ) perhitungan_16 = fields.Float( string="PENGHASILAN KENA PAJAK SETAHUN/DISETAHUNKAN", compute="_compute_pkp", store=True, readonly=True, ) perhitungan_17 = fields.Float( string="PPh PASAL 21 ATAS PENGHASILAN KENA PAJAK SETAHUN/DISETAHUNKAN", compute="_compute_pph21", store=True, readonly=True, ) perhitungan_18 = fields.Float( string="PPh PASAL 21 YANG TELAH DIPOTONG MASA SEBELUMNYA", readonly=True, default=0.0, states={ "draft": [ ("readonly", False), ], }, ) perhitungan_19 = fields.Float( string="PPh PASAL 21 TERUTANG", compute="_compute_hutang_pph", store=True, readonly=True, ) perhitungan_20 = fields.Float( string="PPh PASAL 21 DAN PPh PASAL 26 YANG TELAH DIPOTONG DAN DILUNASI", readonly=True, states={ "draft": [ ("readonly", False), ], }, ) company_partner_id = fields.Many2one( string="Company Partner", comodel_name="res.partner", store=True, readonly=True, related="company_id.partner_id", ) ttd_id = fields.Many2one( string="TTD", comodel_name="res.partner", readonly=True, required=True, ondelete="restrict", states={ "draft": [ ("readonly", False), ], }, ) state = fields.Selection( string="State", selection=[ ("draft", "Draft"), ("confirm", "Waiting for Approval"), ("done", "Done"), ("cancel", "Cancelled"), ], default="draft", required=True, readonly=True, ) confirm_date = fields.Datetime( string="Confirmation Date", readonly=True, copy=False, ) confirm_user_id = fields.Many2one( string="Confirmed By", comodel_name="res.users", readonly=True, copy=False, ) done_date = fields.Datetime( string="Finish Date", readonly=True, copy=False, ) done_user_id = fields.Many2one( string="Finished By", comodel_name="res.users", readonly=True, copy=False, ) cancel_date = fields.Datetime( string="Cancel Date", readonly=True, copy=False, ) cancel_user_id = fields.Many2one( string="Cancelled By", comodel_name="res.users", readonly=True, copy=False, ) confirm_ok = fields.Boolean( string="Can Confirm", compute="_compute_policy", ) restart_approval_ok = fields.Boolean( string="Can Restart Approval", compute="_compute_policy", ) cancel_ok = fields.Boolean( string="Can Cancel", compute="_compute_policy", ) restart_ok = fields.Boolean( string="Can Restart", compute="_compute_policy", ) @api.multi def action_confirm(self): for record in self: record.write(record._prepare_confirm_data()) record.request_validation() @api.multi def action_approve(self): for record in self: record.write(record._prepare_approve_data()) @api.multi def action_cancel(self): for record in self: record.write(record._prepare_cancel_data()) @api.multi def action_restart(self): for record in self: record.write(record._prepare_restart_data()) @api.multi def _prepare_confirm_data(self): self.ensure_one() return { "state": "confirm", "confirm_date": fields.Datetime.now(), "confirm_user_id": self.env.user.id, } @api.multi def _prepare_approve_data(self): self.ensure_one() sequence = self._create_sequence() return { "state": "done", "done_date": fields.Datetime.now(), "done_user_id": self.env.user.id, "name": sequence, } @api.multi def _prepare_cancel_data(self): self.ensure_one() return { "state": "cancel", "cancel_date": fields.Datetime.now(), "cancel_user_id": self.env.user.id, } @api.multi def _prepare_restart_data(self): self.ensure_one() return { "state": "draft", "confirm_date": False, "confirm_user_id": False, "done_date": False, "done_user_id": False, "cancel_date": False, "cancel_user_id": False, } @api.multi def unlink(self): strWarning = _("You can only delete data on draft state") for record in self: if record.state != "draft": if not self.env.context.get("force_unlink", False): raise UserError(strWarning) _super = super(BuktiPotongTaxform1721A1, self) _super.unlink() @api.multi def validate_tier(self): _super = super(BuktiPotongTaxform1721A1, self) _super.validate_tier() for record in self: if record.validated: record.action_approve() @api.multi def restart_validation(self): _super = super(BuktiPotongTaxform1721A1, self) _super.restart_validation() for record in self: record.request_validation() def _get_localdict(self): self.ensure_one() return { "env": self.env, "document": self, } @api.onchange("wajib_pajak_id") def onchange_wajib_pajak_id(self): if self.wajib_pajak_id: self.wajib_pajak_nik = self.wajib_pajak_id.ektp_number self.wajib_pajak_npwp = self.wajib_pajak_id.vat self.wajib_pajak_alamat = self.wajib_pajak_id.street self.wajib_pajak_alamat2 = self.wajib_pajak_id.street2 self.wajib_pajak_zip = self.wajib_pajak_id.zip self.wajib_pajak_kota = self.wajib_pajak_id.city self.wajib_pajak_state_id = self.wajib_pajak_id.state_id self.wajib_pajak_country_id = self.wajib_pajak_id.country_id self.wajib_pajak_ptkp_category_id = self.wajib_pajak_id.ptkp_category_id self.wajib_pajak_job_position = self.wajib_pajak_id.function @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_01(self): self.penghasilan_01 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_01, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_01 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_02(self): self.penghasilan_02 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_02, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_02 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_03(self): self.penghasilan_03 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_03, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_03 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_04(self): self.penghasilan_04 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_04, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_04 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_05(self): self.penghasilan_05 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_05, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_05 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_06(self): self.penghasilan_06 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_06, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_06 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_penghasilan_07(self): self.penghasilan_07 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_penghasilan_07, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.penghasilan_07 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_pengurang_10(self): self.pengurang_10 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_pengurang_10, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.pengurang_10 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_perhitungan_13(self): self.perhitungan_13 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_perhitungan_13, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.perhitungan_13 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_perhitungan_18(self): self.perhitungan_18 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_perhitungan_18, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.perhitungan_18 = result @api.onchange( "company_id", "wajib_pajak_id", "start_tax_period_id", "end_tax_period_id", ) def onchange_perhitungan_20(self): self.perhitungan_20 = 0.0 if self.company_id: localdict = self._get_localdict() try: eval( self.company_id.python_code_1721a1_perhitungan_20, localdict, mode="exec", nocopy=True, ) result = localdict["result"] except Exception: result = 0.0 self.perhitungan_20 = result @api.onchange("tax_year_id") def onchange_tax_year_id(self): self.start_tax_period_id = False self.end_tax_period_id = False
class Specimen(models.Model): _name = "hc.res.specimen" _description = "Specimen" name = fields.Char( string="Event Name", compute="_compute_name", store="True", help= "Text representation of the specimen event. Subject Name + Accession Identifier + Received Time." ) identifier_ids = fields.One2many(comodel_name="hc.specimen.identifier", inverse_name="specimen_id", string="Identifiers", help="External Identifier.") accession_identifier_id = fields.Many2one( comodel_name="hc.specimen.accession.identifier", string="Accession Identifier", help="Identifier assigned by the lab.") status = fields.Selection(string="Status", selection=[("available", "Available"), ("unavailable", "Unavailable"), ("unsatisfactory", "Unsatisfactory"), ("entered-in-error", "Entered-In-Error")], help="The availability of the specimen.") type_id = fields.Many2one(comodel_name="hc.vs.v2.specimen.type", string="Type", help="Kind of material that forms the specimen.") subject_type = fields.Selection(string="Subject Type", required="True", selection=[("patient", "Patient"), ("group", "Group"), ("device", "Device"), ("substance", "Substance")], help="Type of who has the condition.") subject_name = fields.Char( string="Subject", compute="_compute_subject_name", required="True", help= "Where the specimen came from. This may be from the patient(s) or from the environment or a device." ) subject_patient_id = fields.Many2one( comodel_name="hc.res.patient", string="Subject Patient", help="Patient where the specimen came from.") subject_group_id = fields.Many2one( comodel_name="hc.res.group", string="Subject Group", help="Group where the specimen came from.") subject_device_id = fields.Many2one( comodel_name="hc.res.device", string="Subject Device", help="Device where the specimen came from.") subject_substance_id = fields.Many2one( comodel_name="hc.res.substance", string="Subject Substance", help="Substance where the specimen came from.") received_time = fields.Datetime( string="Received Time", help="The time when specimen was received for processing.") parent_specimen_ids = fields.Many2many( comodel_name="hc.specimen.parent", string="Parent Specimens", help="Specimen from which this specimen originated.") request_ids = fields.One2many(comodel_name="hc.specimen.request", inverse_name="specimen_id", string="Requests", help="Why the specimen was collected.") note_ids = fields.One2many(comodel_name="hc.specimen.note", inverse_name="specimen_id", string="Notes", help="Comments.") collection_ids = fields.One2many(comodel_name="hc.specimen.collection", inverse_name="specimen_id", string="Collections", help="Collection details.") treatment_ids = fields.One2many( comodel_name="hc.specimen.treatment", inverse_name="specimen_id", string="Treatments", help="Treatment and processing step details.") container_ids = fields.One2many( comodel_name="hc.specimen.container", inverse_name="specimen_id", string="Containers", help="Direct container of specimen (tube/slide, etc).")
class dym_cancel_kwitansi(models.Model): _name = "dym.cancel.kwitansi" _description = "Cancel Kwitansi" STATE_SELECTION = [('draft', 'Draft'), ('validate', 'Posted'), ('cancel', 'Cancelled')] @api.cr_uid_ids_context def _get_default_branch(self, cr, uid, ids, context=None): user_obj = self.pool.get('res.users') user_browse = user_obj.browse(cr, uid, uid) branch_ids = False branch_ids = user_browse.branch_ids and len( user_browse.branch_ids ) == 1 and user_browse.branch_ids[0].id or False return branch_ids name = fields.Char(string="Name", readonly=True, default='') branch_id = fields.Many2one('dym.branch', string='Branch', required=True, default=_get_default_branch) state = fields.Selection(STATE_SELECTION, string='State', readonly=True, default='draft') date = fields.Date(string="Date", required=True, readonly=True, default=fields.Date.context_today) reason = fields.Char(string="Reason") division = fields.Selection([('Unit', 'Showroom'), ('Sparepart', 'Workshop'), ('Umum', 'General'), ('Finance', 'Finance')], string='Division', default='Unit', required=True, change_default=True, select=True) voucher_id = fields.Many2one(related='kwitansi_id.payment_id', string='Payment No') kwitansi_id = fields.Many2one( 'dym.register.kwitansi.line', string="Kwitansi No", domain= "[('state','=','cancel'),('branch_id','=',branch_id),('payment_id','!=',False)]" ) confirm_uid = fields.Many2one('res.users', string="Validated by") confirm_date = fields.Datetime('Validated on') cancel_uid = fields.Many2one('res.users', string="Cancelled by") cancel_date = fields.Datetime('Cancelled on') voucher_id_show = fields.Many2one('account.voucher', string="Payment No") @api.onchange('voucher_id') def changekwitansi(self): self.voucher_id_show = self.voucher_id.id @api.model def create(self, vals, context=None): vals['name'] = self.env['ir.sequence'].get_per_branch( vals['branch_id'], 'CKW', division=vals['division']) vals['date'] = time.strftime('%Y-%m-%d') kwitansi_id = super(dym_cancel_kwitansi, self).create(vals) return kwitansi_id @api.cr_uid_ids_context def unlink(self, cr, uid, ids, context=None): for item in self.browse(cr, uid, ids, context=context): if item.state != 'draft': raise osv.except_osv(('Perhatian !'), ( "Form Cancel Kwitansi tidak bisa didelete karena sudah di validate !" )) return super(dym_cancel_kwitansi, self).unlink(cr, uid, ids, context=context) @api.multi def validate_kwitansi(self): voucher = self.env['account.voucher'] kwitansi = self.env['dym.register.kwitansi.line'] kwitansi_id = kwitansi.search([('id', '=', self.kwitansi_id.id)]) if not kwitansi_id: raise osv.except_osv(('Perhatian !'), ("Nomor Kwitansi sudah dihapus !")) kwitansi_id.write({ 'state': 'open', 'payment_id': False, 'reason': False }) self.state = 'validate' self.confirm_uid = self._uid self.confirm_date = datetime.now() self.voucher_id_show = self.voucher_id.id self.date = datetime.today()