class LeaveReportCalendar(models.Model): _name = "hr.leave.report.calendar" _description = 'Time Off Calendar' _auto = False _order = "start_datetime DESC, employee_id" name = fields.Char(string='Name', readonly=True) start_datetime = fields.Datetime(string='From', readonly=True) stop_datetime = fields.Datetime(string='To', readonly=True) tz = fields.Selection(_tz_get, string="Timezone", readonly=True) duration = fields.Float(string='Duration', readonly=True) employee_id = fields.Many2one('hr.employee', readonly=True) company_id = fields.Many2one('res.company', readonly=True) def init(self): tools.drop_view_if_exists(self._cr, 'hr_leave_report_calendar') self._cr.execute("""CREATE OR REPLACE VIEW hr_leave_report_calendar AS (SELECT row_number() OVER() AS id, ce.name AS name, ce.start_datetime AS start_datetime, ce.stop_datetime AS stop_datetime, ce.event_tz AS tz, ce.duration AS duration, hl.employee_id AS employee_id, em.company_id AS company_id FROM hr_leave hl LEFT JOIN calendar_event ce ON ce.id = hl.meeting_id LEFT JOIN hr_employee em ON em.id = hl.employee_id WHERE hl.state = 'validate'); """)
class MixedModel(models.Model): _name = 'test_new_api.mixed' _description = 'Test New API Mixed' number = fields.Float(digits=(10, 2), default=3.14) number2 = fields.Float(digits='New API Precision') date = fields.Date() moment = fields.Datetime() now = fields.Datetime(compute='_compute_now') lang = fields.Selection(string='Language', selection='_get_lang') reference = fields.Reference(string='Related Document', selection='_reference_models') comment1 = fields.Html(sanitize=False) comment2 = fields.Html(sanitize_attributes=True, strip_classes=False) comment3 = fields.Html(sanitize_attributes=True, strip_classes=True) comment4 = fields.Html(sanitize_attributes=True, strip_style=True) currency_id = fields.Many2one('res.currency', default=lambda self: self.env.ref('base.EUR')) amount = fields.Monetary() def _compute_now(self): # this is a non-stored computed field without dependencies for message in self: message.now = fields.Datetime.now() @api.model def _get_lang(self): return self.env['res.lang'].get_installed() @api.model def _reference_models(self): models = self.env['ir.model'].sudo().search([('state', '!=', 'manual')]) return [(model.model, model.name) for model in models if not model.model.startswith('ir.')]
class User(models.Model): _inherit = ['res.users'] hours_last_month = fields.Float(related='employee_id.hours_last_month') hours_last_month_display = fields.Char( related='employee_id.hours_last_month_display') attendance_state = fields.Selection(related='employee_id.attendance_state') last_check_in = fields.Datetime( related='employee_id.last_attendance_id.check_in') last_check_out = fields.Datetime( related='employee_id.last_attendance_id.check_out') def __init__(self, pool, cr): """ Override of __init__ to add access rights. Access rights are disabled by default, but allowed on some specific fields defined in self.SELF_{READ/WRITE}ABLE_FIELDS. """ attendance_readable_fields = [ 'hours_last_month', 'hours_last_month_display', 'attendance_state', 'last_check_in', 'last_check_out' ] super(User, self).__init__(pool, cr) # duplicate list to avoid modifying the original reference type(self).SELF_READABLE_FIELDS = type( self).SELF_READABLE_FIELDS + attendance_readable_fields
class User(models.Model): _inherit = 'res.users' google_calendar_rtoken = fields.Char('Refresh Token', copy=False) google_calendar_token = fields.Char('User token', copy=False) google_calendar_token_validity = fields.Datetime('Token Validity', copy=False) google_calendar_last_sync_date = fields.Datetime('Last synchro date', copy=False) google_calendar_cal_id = fields.Char('Calendar ID', copy=False, help='Last Calendar ID who has been synchronized. If it is changed, we remove all links between GoogleID and Harpiya Google Internal ID')
class BusPresence(models.Model): """ User Presence Its status is 'online', 'away' or 'offline'. This model should be a one2one, but is not attached to res_users to avoid database concurrence errors. Since the 'update' method is executed at each poll, if the user have multiple opened tabs, concurrence errors can happend, but are 'muted-logged'. """ _name = 'bus.presence' _description = 'User Presence' _log_access = False _sql_constraints = [('bus_user_presence_unique', 'unique(user_id)', 'A user can only have one IM status.')] user_id = fields.Many2one('res.users', 'Users', required=True, index=True, ondelete='cascade') last_poll = fields.Datetime('Last Poll', default=lambda self: fields.Datetime.now()) last_presence = fields.Datetime('Last Presence', default=lambda self: fields.Datetime.now()) status = fields.Selection([('online', 'Online'), ('away', 'Away'), ('offline', 'Offline')], 'IM Status', default='offline') @api.model def update(self, inactivity_period): """ Updates the last_poll and last_presence of the current user :param inactivity_period: duration in milliseconds """ presence = self.search([('user_id', '=', self._uid)], limit=1) # compute last_presence timestamp last_presence = datetime.datetime.now() - datetime.timedelta( milliseconds=inactivity_period) values = { 'last_poll': time.strftime(DEFAULT_SERVER_DATETIME_FORMAT), } # update the presence or a create a new one if not presence: # create a new presence for the user values['user_id'] = self._uid values['last_presence'] = last_presence self.create(values) else: # update the last_presence if necessary, and write values if presence.last_presence < last_presence: values['last_presence'] = last_presence # Hide transaction serialization errors, which can be ignored, the presence update is not essential with tools.mute_logger('harpiya.sql_db'): presence.write(values) # avoid TransactionRollbackError self.env.cr.commit() # TODO : check if still necessary
class PosDetails(models.TransientModel): _name = 'pos.details.wizard' _description = 'Point of Sale Details Report' def _default_start_date(self): """ Find the earliest start_date of the latests sessions """ # restrict to configs available to the user config_ids = self.env['pos.config'].search([]).ids # exclude configs has not been opened for 2 days self.env.cr.execute( """ SELECT max(start_at) as start, config_id FROM pos_session WHERE config_id = ANY(%s) AND start_at > (NOW() - INTERVAL '2 DAYS') GROUP BY config_id """, (config_ids, )) latest_start_dates = [ res['start'] for res in self.env.cr.dictfetchall() ] # earliest of the latest sessions return latest_start_dates and min( latest_start_dates) or fields.Datetime.now() start_date = fields.Datetime(required=True, default=_default_start_date) end_date = fields.Datetime(required=True, default=fields.Datetime.now) pos_config_ids = fields.Many2many( 'pos.config', 'pos_detail_configs', default=lambda s: s.env['pos.config'].search([])) @api.onchange('start_date') def _onchange_start_date(self): if self.start_date and self.end_date and self.end_date < self.start_date: self.end_date = self.start_date @api.onchange('end_date') def _onchange_end_date(self): if self.end_date and self.end_date < self.start_date: self.start_date = self.end_date def generate_report(self): data = { 'date_start': self.start_date, 'date_stop': self.end_date, 'config_ids': self.pos_config_ids.ids } return self.env.ref('point_of_sale.sale_details_report').report_action( [], data=data)
class Partner(models.Model): _inherit = 'res.partner' calendar_last_notif_ack = fields.Datetime( 'Last notification marked as read from base Calendar', default=fields.Datetime.now) def get_attendee_detail(self, meeting_id): """ Return a list of tuple (id, name, status) Used by base_calendar.js : Many2ManyAttendee """ datas = [] meeting = None if meeting_id: meeting = self.env['calendar.event'].browse( get_real_ids(meeting_id)) for partner in self: data = partner.name_get()[0] data = [data[0], data[1], False, partner.color] if meeting: for attendee in meeting.attendee_ids: if attendee.partner_id.id == partner.id: data[2] = attendee.state datas.append(data) return datas @api.model def _set_calendar_last_notif_ack(self): partner = self.env['res.users'].browse( self.env.context.get('uid', self.env.uid)).partner_id partner.write({'calendar_last_notif_ack': datetime.now()}) return
class ConverterTest(models.Model): _name = 'web_editor.converter.test' _description = 'Web Editor Converter Test' # disable translation export for those brilliant field labels and values _translate = False char = fields.Char() integer = fields.Integer() float = fields.Float() numeric = fields.Float(digits=(16, 2)) many2one = fields.Many2one('web_editor.converter.test.sub') binary = fields.Binary(attachment=False) date = fields.Date() datetime = fields.Datetime() selection_str = fields.Selection( [ ('A', "Qu'il n'est pas arrivé à Toronto"), ('B', "Qu'il était supposé arriver à Toronto"), ('C', "Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?"), ('D', "La réponse D"), ], string=u"Lorsqu'un pancake prend l'avion à destination de Toronto et " u"qu'il fait une escale technique à St Claude, on dit:") html = fields.Html() text = fields.Text()
class test_model(models.Model): _name = 'test_converter.test_model' _description = 'Test Converter Model' char = fields.Char() integer = fields.Integer() float = fields.Float() numeric = fields.Float(digits=(16, 2)) many2one = fields.Many2one('test_converter.test_model.sub', group_expand='_gbf_m2o') binary = fields.Binary(attachment=False) date = fields.Date() datetime = fields.Datetime() selection_str = fields.Selection( [ ('A', u"Qu'il n'est pas arrivé à Toronto"), ('B', u"Qu'il était supposé arriver à Toronto"), ('C', u"Qu'est-ce qu'il fout ce maudit pancake, tabernacle ?"), ('D', u"La réponse D"), ], string=u"Lorsqu'un pancake prend l'avion à destination de Toronto et " u"qu'il fait une escale technique à St Claude, on dit:") html = fields.Html() text = fields.Text() # `base` module does not contains any model that implement the functionality # `group_expand`; test this feature here... @api.model def _gbf_m2o(self, subs, domain, order): sub_ids = subs._search([], order=order, access_rights_uid=SUPERUSER_ID) return subs.browse(sub_ids)
class Rating(models.Model): _inherit = 'rating.rating' # Add this related field to mail.message for performance reason website_published = fields.Boolean(related='message_id.website_published', store=True, readonly=False) # Adding information for comment a rating message publisher_comment = fields.Text("Publisher Comment") publisher_id = fields.Many2one('res.partner', 'Commented by', ondelete='set null', readonly=True) publisher_datetime = fields.Datetime("Commented on", readonly=True) def write(self, values): if values.get('publisher_comment'): if not self.env.user.has_group("website.group_website_publisher"): raise exceptions.AccessError( _("Only the publisher of the website can change the rating comment" )) if not values.get('publisher_datetime'): values['publisher_datetime'] = fields.Datetime.now() if not values.get('publisher_id'): values['publisher_id'] = self.env.user.partner_id.id return super(Rating, self).write(values)
class FillTemporal(models.Model): _name = 'test_read_group.fill_temporal' _description = 'Group Test Fill Temporal' date = fields.Date() datetime = fields.Datetime() value = fields.Integer()
class Attendee(models.Model): _inherit = 'calendar.attendee' google_internal_event_id = fields.Char('Google Calendar Event Id') oe_synchro_date = fields.Datetime('Harpiya Synchro Date') _sql_constraints = [ ('google_id_uniq', 'unique(google_internal_event_id,partner_id,event_id)', 'Google ID should be unique!') ] def write(self, values): for attendee in self: meeting_id_to_update = values.get('event_id', attendee.event_id.id) # If attendees are updated, we need to specify that next synchro need an action # Except if it come from an update_from_google if not self._context.get('curr_attendee', False) and not self._context.get( 'NewMeeting', False): self.env['calendar.event'].browse(meeting_id_to_update).write( {'oe_update_date': fields.Datetime.now()}) return super(Attendee, self).write(values)
class StockQuantityHistory(models.TransientModel): _name = 'stock.quantity.history' _description = 'Stock Quantity History' inventory_datetime = fields.Datetime( 'Inventory at Date', help="Choose a date to get the inventory at that date", default=fields.Datetime.now) def open_at_date(self): tree_view_id = self.env.ref('stock.view_stock_product_tree').id form_view_id = self.env.ref( 'stock.product_form_view_procurement_button').id domain = [('type', '=', 'product')] product_id = self.env.context.get('product_id', False) product_tmpl_id = self.env.context.get('product_tmpl_id', False) if product_id: domain = expression.AND([domain, [('id', '=', product_id)]]) elif product_tmpl_id: domain = expression.AND( [domain, [('product_tmpl_id', '=', product_tmpl_id)]]) # We pass `to_date` in the context so that `qty_available` will be computed across # moves until date. action = { 'type': 'ir.actions.act_window', 'views': [(tree_view_id, 'tree'), (form_view_id, 'form')], 'view_mode': 'tree,form', 'name': _('Products'), 'res_model': 'product.product', 'domain': domain, 'context': dict(self.env.context, to_date=self.inventory_datetime), } return action
class CompanyDependent(models.Model): _name = 'test_new_api.company' _description = 'Test New API Company' foo = fields.Char(company_dependent=True) date = fields.Date(company_dependent=True) moment = fields.Datetime(company_dependent=True) tag_id = fields.Many2one('test_new_api.multi.tag', company_dependent=True)
class HrEmployeePublic(models.Model): _name = "hr.employee.public" _inherit = ["hr.employee.base"] _description = 'Public Employee' _order = 'name' _auto = False _log_access = True # Include magic fields # Fields coming from hr.employee.base create_date = fields.Datetime(readonly=True) name = fields.Char(readonly=True) active = fields.Boolean(readonly=True) department_id = fields.Many2one(readonly=True) job_id = fields.Many2one(readonly=True) job_title = fields.Char(readonly=True) company_id = fields.Many2one(readonly=True) address_id = fields.Many2one(readonly=True) mobile_phone = fields.Char(readonly=True) work_phone = fields.Char(readonly=True) work_email = fields.Char(readonly=True) work_location = fields.Char(readonly=True) user_id = fields.Many2one(readonly=True) resource_id = fields.Many2one(readonly=True) resource_calendar_id = fields.Many2one(readonly=True) tz = fields.Selection(readonly=True) color = fields.Integer(readonly=True) # hr.employee.public specific fields child_ids = fields.One2many('hr.employee.public', 'parent_id', string='Direct subordinates', readonly=True) image_1920 = fields.Image("Original Image", compute='_compute_image', compute_sudo=True) image_1024 = fields.Image("Image 1024", compute='_compute_image', compute_sudo=True) image_512 = fields.Image("Image 512", compute='_compute_image', compute_sudo=True) image_256 = fields.Image("Image 256", compute='_compute_image', compute_sudo=True) image_128 = fields.Image("Image 128", compute='_compute_image', compute_sudo=True) parent_id = fields.Many2one('hr.employee.public', 'Manager', readonly=True) coach_id = fields.Many2one('hr.employee.public', 'Coach', readonly=True) def _compute_image(self): for employee in self: # We have to be in sudo to have access to the images employee_id = self.sudo().env['hr.employee'].browse(employee.id) employee.image_1920 = employee_id.image_1920 employee.image_1024 = employee_id.image_1024 employee.image_512 = employee_id.image_512 employee.image_256 = employee_id.image_256 employee.image_128 = employee_id.image_128 @api.model def _get_fields(self): return ','.join('emp.%s' % name for name, field in self._fields.items() if field.store and field.type not in ['many2many', 'one2many']) def init(self): tools.drop_view_if_exists(self.env.cr, self._table) self.env.cr.execute("""CREATE or REPLACE VIEW %s as ( SELECT %s FROM hr_employee emp )""" % (self._table, self._get_fields()))
class IrLogging(models.Model): _name = 'ir.logging' _description = 'Logging' _order = 'id DESC' # The _log_access fields are defined manually for the following reasons: # # - The entries in ir_logging are filled in with sql queries bypassing the orm. As the --log-db # cli option allows to insert ir_logging entries into a remote database, the one2many *_uid # fields make no sense in the first place but we will keep it for backward compatibility. # # - Also, when an ir_logging entry is triggered by the orm (when using --log-db) at the moment # it is making changes to the res.users model, the ALTER TABLE will aquire an exclusive lock # on res_users, preventing the ir_logging INSERT to be processed, hence the ongoing module # install/update will hang forever as the orm is blocked by the ir_logging query that will # never occur. create_uid = fields.Integer(string='Created by', readonly=True) create_date = fields.Datetime(string='Created on', readonly=True) write_uid = fields.Integer(string='Last Updated by', readonly=True) write_date = fields.Datetime(string='Last Updated on', readonly=True) name = fields.Char(required=True) type = fields.Selection([('client', 'Client'), ('server', 'Server')], required=True, index=True) dbname = fields.Char(string='Database Name', index=True) level = fields.Char(index=True) message = fields.Text(required=True) path = fields.Char(required=True) func = fields.Char(string='Function', required=True) line = fields.Char(required=True) def init(self): super(IrLogging, self).init() self._cr.execute( "select 1 from information_schema.constraint_column_usage where table_name = 'ir_logging' and constraint_name = 'ir_logging_write_uid_fkey'" ) if self._cr.rowcount: # DROP CONSTRAINT unconditionally takes an ACCESS EXCLUSIVE lock # on the table, even "IF EXISTS" is set and not matching; disabling # the relevant trigger instead acquires SHARE ROW EXCLUSIVE, which # still conflicts with the ROW EXCLUSIVE needed for an insert self._cr.execute( "ALTER TABLE ir_logging DROP CONSTRAINT ir_logging_write_uid_fkey" )
class ComplexModel(models.Model): _name = model('complex') _description = 'Tests: Base Import Model Complex' f = fields.Float() m = fields.Monetary() c = fields.Char() currency_id = fields.Many2one('res.currency') d = fields.Date() dt = fields.Datetime()
class MailingTraceReport(models.Model): _name = 'mailing.trace.report' _auto = False _description = 'Mass Mailing Statistics' # mailing name = fields.Char(string='Mass Mail', readonly=True) mailing_type = fields.Selection([('mail', 'Mail')], string='Type', default='mail', required=True) campaign = fields.Char(string='Mass Mail Campaign', readonly=True) scheduled_date = fields.Datetime(string='Scheduled Date', readonly=True) state = fields.Selection([('draft', 'Draft'), ('test', 'Tested'), ('done', 'Sent')], string='Status', readonly=True) email_from = fields.Char('From', readonly=True) # traces sent = fields.Integer(readonly=True) delivered = fields.Integer(readonly=True) opened = fields.Integer(readonly=True) replied = fields.Integer(readonly=True) clicked = fields.Integer(readonly=True) bounced = fields.Integer(readonly=True) def init(self): """Mass Mail Statistical Report: based on mailing.trace that models the various statistics collected for each mailing, and mailing.mailing model that models the various mailing performed. """ tools.drop_view_if_exists(self.env.cr, 'mailing_trace_report') self.env.cr.execute(""" CREATE OR REPLACE VIEW mailing_trace_report AS ( SELECT min(trace.id) as id, utm_source.name as name, mailing.mailing_type, utm_campaign.name as campaign, trace.scheduled as scheduled_date, mailing.state, mailing.email_from, count(trace.sent) as sent, (count(trace.sent) - count(trace.bounced)) as delivered, count(trace.opened) as opened, count(trace.replied) as replied, count(trace.clicked) as clicked, count(trace.bounced) as bounced FROM mailing_trace as trace left join mailing_mailing as mailing ON (trace.mass_mailing_id=mailing.id) left join utm_campaign as utm_campaign ON (mailing.campaign_id = utm_campaign.id) left join utm_source as utm_source ON (mailing.source_id = utm_source.id) GROUP BY trace.scheduled, utm_source.name, utm_campaign.name, mailing.mailing_type, mailing.state, mailing.email_from )""")
class SaleCouponRule(models.Model): _name = 'sale.coupon.rule' _description = "Sales Coupon Rule" rule_date_from = fields.Datetime(string="Start Date", help="Coupon program start date") rule_date_to = fields.Datetime(string="End Date", help="Coupon program end date") rule_partners_domain = fields.Char(string="Based on Customers", help="Coupon program will work for selected customers only") rule_products_domain = fields.Char(string="Based on Products", default=[['sale_ok', '=', True]], help="On Purchase of selected product, reward will be given") rule_min_quantity = fields.Integer(string="Minimum Quantity", default=1, help="Minimum required product quantity to get the reward") rule_minimum_amount = fields.Float(default=0.0, help="Minimum required amount to get the reward") rule_maximum_amount = fields.Float(default=99999.0, help="Maxiumum required amount to get the reward") rule_minimum_amount_tax_inclusion = fields.Selection([ ('tax_included', 'Tax Included'), ('tax_excluded', 'Tax Excluded')], default="tax_excluded") rule_maximum_amount_tax_inclusion = fields.Selection([ ('tax_included', 'Tax Included'), ('tax_excluded', 'Tax Excluded')], default="tax_excluded") @api.constrains('rule_date_to', 'rule_date_from') def _check_rule_date_from(self): if any(applicability for applicability in self if applicability.rule_date_to and applicability.rule_date_from and applicability.rule_date_to < applicability.rule_date_from): raise ValidationError(_('The start date must be before the end date')) @api.constrains('rule_minimum_amount') def _check_rule_minimum_amount(self): if self.filtered(lambda applicability: applicability.rule_minimum_amount < 0): raise ValidationError(_('Minimum purchased amount should be greater than 0')) @api.constrains('rule_maximum_amount') def _check_rule_maximum_amount(self): if self.filtered(lambda applicability: applicability.rule_maximum_amount < 0): raise ValidationError(_('Maximum purchased amount should be greater than 0')) @api.constrains('rule_min_quantity') def _check_rule_min_quantity(self): if not self.rule_min_quantity > 0: raise ValidationError(_('Minimum quantity should be greater than 0'))
class StockQuant(models.Model): _inherit = 'stock.quant' removal_date = fields.Datetime(related='lot_id.removal_date', store=True, readonly=False) @api.model def _get_removal_strategy_order(self, removal_strategy): if removal_strategy == 'fefo': return 'removal_date, in_date, id' return super(StockQuant, self)._get_removal_strategy_order(removal_strategy)
class ResourceCalendarLeaves(models.Model): _name = "resource.calendar.leaves" _description = "Resource Time Off Detail" _order = "date_from" name = fields.Char('Reason') company_id = fields.Many2one('res.company', related='calendar_id.company_id', string="Company", readonly=True, store=True) calendar_id = fields.Many2one('resource.calendar', 'Working Hours') date_from = fields.Datetime('Start Date', required=True) date_to = fields.Datetime('End Date', required=True) resource_id = fields.Many2one( "resource.resource", 'Resource', help= "If empty, this is a generic time off for the company. If a resource is set, the time off is only for this resource" ) time_type = fields.Selection( [('leave', 'Time Off'), ('other', 'Other')], default='leave', help= "Whether this should be computed as a time off or as work time (eg: formation)" ) @api.constrains('date_from', 'date_to') def check_dates(self): if self.filtered(lambda leave: leave.date_from > leave.date_to): raise ValidationError( _('The start date of the time off must be earlier end date.')) @api.onchange('resource_id') def onchange_resource(self): if self.resource_id: self.calendar_id = self.resource_id.calendar_id
class MailingMailingScheduleDate(models.TransientModel): _name = 'mailing.mailing.schedule.date' _description = 'Mass Mailing Scheduling' schedule_date = fields.Datetime(string='Scheduled for') mass_mailing_id = fields.Many2one('mailing.mailing', required=True, ondelete='cascade') @api.constrains('schedule_date') def _check_schedule_date(self): for scheduler in self: if scheduler.schedule_date < fields.Datetime.now(): raise ValidationError(_('Please select a date equal/or greater than the current date.')) def set_schedule_date(self): self.mass_mailing_id.write({'schedule_date': self.schedule_date, 'state': 'in_queue'})
class pos_config(models.Model): _inherit = 'pos.config' @api.depends('cache_ids') def _get_oldest_cache_time(self): for cache in self: pos_cache = self.env['pos.cache'] oldest_cache = pos_cache.search([('config_id', '=', cache.id)], order='write_date', limit=1) cache.oldest_cache_time = oldest_cache.write_date # Use a related model to avoid the load of the cache when the pos load his config cache_ids = fields.One2many('pos.cache', 'config_id') oldest_cache_time = fields.Datetime(compute='_get_oldest_cache_time', string='Oldest cache time', readonly=True) def _get_cache_for_user(self): pos_cache = self.env['pos.cache'] cache_for_user = pos_cache.search([('id', 'in', self.cache_ids.ids), ('compute_user_id', '=', self.env.uid)]) if cache_for_user: return cache_for_user[0] else: return None def get_products_from_cache(self, fields, domain): cache_for_user = self._get_cache_for_user() if cache_for_user: return cache_for_user.get_cache(domain, fields) else: pos_cache = self.env['pos.cache'] pos_cache.create({ 'config_id': self.id, 'product_domain': str(domain), 'product_fields': str(fields), 'compute_user_id': self.env.uid }) new_cache = self._get_cache_for_user() return new_cache.get_cache(domain, fields) def delete_cache(self): # throw away the old caches self.cache_ids.unlink()
class MassMailingContactListRel(models.Model): """ Intermediate model between mass mailing list and mass mailing contact Indicates if a contact is opted out for a particular list """ _name = 'mailing.contact.subscription' _description = 'Mass Mailing Subscription Information' _table = 'mailing_contact_list_rel' _rec_name = 'contact_id' contact_id = fields.Many2one('mailing.contact', string='Contact', ondelete='cascade', required=True) list_id = fields.Many2one('mailing.list', string='Mailing List', ondelete='cascade', required=True) opt_out = fields.Boolean( string='Opt Out', help= 'The contact has chosen not to receive mails anymore from this list', default=False) unsubscription_date = fields.Datetime(string='Unsubscription Date') message_bounce = fields.Integer(related='contact_id.message_bounce', store=False, readonly=False) is_blacklisted = fields.Boolean(related='contact_id.is_blacklisted', store=False, readonly=False) _sql_constraints = [ ('unique_contact_list', 'unique (contact_id, list_id)', 'A contact cannot be subscribed multiple times to the same list!') ] @api.model def create(self, vals): if 'opt_out' in vals: vals['unsubscription_date'] = vals[ 'opt_out'] and fields.Datetime.now() return super(MassMailingContactListRel, self).create(vals) def write(self, vals): if 'opt_out' in vals: vals['unsubscription_date'] = vals[ 'opt_out'] and fields.Datetime.now() return super(MassMailingContactListRel, self).write(vals)
class WebsiteTrack(models.Model): _name = 'website.track' _description = 'Visited Pages' _order = 'visit_datetime DESC' _log_access = False visitor_id = fields.Many2one('website.visitor', ondelete="cascade", index=True, required=True, readonly=True) page_id = fields.Many2one('website.page', index=True, ondelete='cascade', readonly=True) url = fields.Text('Url', index=True) visit_datetime = fields.Datetime('Visit Date', default=fields.Datetime.now, required=True, readonly=True)
class EventMailRegistration(models.Model): _name = 'event.mail.registration' _description = 'Registration Mail Scheduler' _rec_name = 'scheduler_id' _order = 'scheduled_date DESC' scheduler_id = fields.Many2one('event.mail', 'Mail Scheduler', required=True, ondelete='cascade') registration_id = fields.Many2one('event.registration', 'Attendee', required=True, ondelete='cascade') scheduled_date = fields.Datetime('Scheduled Time', compute='_compute_scheduled_date', store=True) mail_sent = fields.Boolean('Mail Sent') def execute(self): for mail in self: if mail.registration_id.state in [ 'open', 'done' ] and not mail.mail_sent and mail.scheduler_id.notification_type == 'mail': mail.scheduler_id.template_id.send_mail( mail.registration_id.id) mail.write({'mail_sent': True}) @api.depends('registration_id', 'scheduler_id.interval_unit', 'scheduler_id.interval_type') def _compute_scheduled_date(self): for mail in self: if mail.registration_id: date_open = mail.registration_id.date_open date_open_datetime = date_open or fields.Datetime.now() mail.scheduled_date = date_open_datetime + _INTERVALS[ mail.scheduler_id.interval_unit]( mail.scheduler_id.interval_nbr) else: mail.scheduled_date = False
class LeadTest(models.Model): _name = "base.automation.lead.test" _description = "Automated Rule Test" name = fields.Char(string='Subject', required=True, index=True) user_id = fields.Many2one('res.users', string='Responsible') state = fields.Selection([('draft', 'New'), ('cancel', 'Cancelled'), ('open', 'In Progress'), ('pending', 'Pending'), ('done', 'Closed')], string="Status", readonly=True, default='draft') active = fields.Boolean(default=True) partner_id = fields.Many2one('res.partner', string='Partner') date_action_last = fields.Datetime(string='Last Action', readonly=True) employee = fields.Boolean(compute='_compute_employee_deadline', store=True) line_ids = fields.One2many('base.automation.line.test', 'lead_id') priority = fields.Boolean() deadline = fields.Boolean(compute='_compute_employee_deadline', store=True) is_assigned_to_admin = fields.Boolean(string='Assigned to admin user') @api.depends('partner_id.employee', 'priority') def _compute_employee_deadline(self): # this method computes two fields on purpose; don't split it for record in self: record.employee = record.partner_id.employee if not record.priority: record.deadline = False else: record.deadline = record.create_date + relativedelta.relativedelta( days=3) def write(self, vals): result = super().write(vals) # force recomputation of field 'deadline' via 'employee': the action # based on 'deadline' must be triggered self.mapped('employee') return result
class MailTestFull(models.Model): """ This model can be used in tests when complex chatter features are required like modeling tasks or tickets. """ _description = 'Full Chatter Model' _name = 'mail.test.full' _inherit = ['mail.thread'] name = fields.Char() email_from = fields.Char(tracking=True) count = fields.Integer(default=1) datetime = fields.Datetime(default=fields.Datetime.now) mail_template = fields.Many2one('mail.template', 'Template') customer_id = fields.Many2one('res.partner', 'Customer', tracking=2) user_id = fields.Many2one('res.users', 'Responsible', tracking=1) umbrella_id = fields.Many2one('mail.test', tracking=True) def _track_template(self, changes): res = super(MailTestFull, self)._track_template(changes) record = self[0] if 'customer_id' in changes and record.mail_template: res['customer_id'] = (record.mail_template, { 'composition_mode': 'mass_mail' }) elif 'datetime' in changes: res['datetime'] = ('test_mail.mail_test_full_tracking_view', { 'composition_mode': 'mass_mail' }) return res def _creation_subtype(self): if self.umbrella_id: return self.env.ref('test_mail.st_mail_test_full_umbrella_upd') return super(MailTestFull, self)._creation_subtype() def _track_subtype(self, init_values): self.ensure_one() if 'umbrella_id' in init_values and self.umbrella_id: return self.env.ref('test_mail.st_mail_test_full_umbrella_upd') return super(MailTestFull, self)._track_subtype(init_values)
class Meeting(models.Model): _inherit = "calendar.event" oe_update_date = fields.Datetime('Harpiya Update Date') @api.model def get_fields_need_update_google(self): recurrent_fields = self._get_recurrent_fields() return recurrent_fields + [ 'name', 'description', 'allday', 'start', 'date_end', 'stop', 'attendee_ids', 'alarm_ids', 'location', 'privacy', 'active', 'start_date', 'start_datetime', 'stop_date', 'stop_datetime' ] def write(self, values): sync_fields = set(self.get_fields_need_update_google()) if ( set(values) and sync_fields ) and 'oe_update_date' not in values and 'NewMeeting' not in self._context: if 'oe_update_date' in self._context: values['oe_update_date'] = self._context.get('oe_update_date') else: values['oe_update_date'] = fields.Datetime.now() return super(Meeting, self).write(values) @api.returns('self', lambda value: value.id) def copy(self, default=None): default = default or {} if default.get('write_type', False): del default['write_type'] elif default.get('recurrent_id', False): default['oe_update_date'] = fields.Datetime.now() else: default['oe_update_date'] = False return super(Meeting, self).copy(default) def unlink(self, can_be_deleted=False): return super(Meeting, self).unlink(can_be_deleted=can_be_deleted)
class Users(models.Model): _inherit = 'res.users' create_date = fields.Datetime('Create Date', readonly=True, index=True) forum_waiting_posts_count = fields.Integer( 'Waiting post', compute="_get_user_waiting_post") def _get_user_waiting_post(self): for user in self: Post = self.env['forum.post'] domain = [('parent_id', '=', False), ('state', '=', 'pending'), ('create_uid', '=', user.id)] user.forum_waiting_posts_count = Post.search_count(domain) # Wrapper for call_kw with inherits def open_website_url(self): return self.mapped('partner_id').open_website_url() def get_gamification_redirection_data(self): res = super(Users, self).get_gamification_redirection_data() res.append({'url': '/forum', 'label': 'See our Forum'}) return res