def name_get(self): result = [] for attendance in self: if not attendance.check_out: result.append( (attendance.id, _("%(empl_name)s from %(check_in)s") % { 'empl_name': attendance.employee_id.name, 'check_in': format_datetime( self.env, attendance.check_in, dt_format=False), })) else: result.append( (attendance.id, _("%(empl_name)s from %(check_in)s to %(check_out)s") % { 'empl_name': attendance.employee_id.name, 'check_in': format_datetime( self.env, attendance.check_in, dt_format=False), 'check_out': format_datetime( self.env, attendance.check_out, dt_format=False), })) return result
def _compute_date_end_tz(self): for event in self: if event.date_end: event.date_end_located = format_datetime(self.env, event.date_end, tz=event.date_tz, dt_format='medium') else: event.date_end_located = False
def format_datetime(env, dt, tz=False, dt_format='medium', lang_code=False): try: return tools.format_datetime(env, dt, tz=tz, dt_format=dt_format, lang_code=lang_code) except babel.core.UnknownLocaleError: return dt
def _prepare_report_line(self, quantity, move_out=None, move_in=None, replenishment_filled=True, product=False, reservation=False): timezone = self._context.get('tz') product = product or (move_out.product_id if move_out else move_in.product_id) is_late = move_out.date < move_in.date if (move_out and move_in) else False return { 'document_in': move_in._get_source_document() if move_in else False, 'document_out': move_out._get_source_document() if move_out else False, 'product': { 'id': product.id, 'display_name': product.display_name }, 'replenishment_filled': replenishment_filled, 'uom_id': product.uom_id, 'receipt_date': format_datetime(self.env, move_in.date, timezone, dt_format=False) if move_in else False, 'delivery_date': format_datetime(self.env, move_out.date, timezone, dt_format=False) if move_out else False, 'is_late': is_late, 'quantity': float_round(quantity, precision_rounding=product.uom_id.rounding), 'move_out': move_out, 'move_in': move_in, 'reservation': reservation, }
def _final_vals_to_lines(self, final_vals, level): lines = [] for data in final_vals: lines.append({ 'id': autoIncrement(), 'model': data['model'], 'model_id': data['model_id'], 'parent_id': data['parent_id'], 'usage': data.get('usage', False), 'is_used': data.get('is_used', False), 'lot_name': data.get('lot_name', False), 'lot_id': data.get('lot_id', False), 'reference': data.get('reference_id', False), 'res_id': data.get('res_id', False), 'res_model': data.get('res_model', False), 'columns': [ data.get('reference_id', False), data.get('product_id', False), format_datetime(self.env, data.get('date', False), tz=False, dt_format=False), data.get('lot_name', False), data.get('location_source', False), data.get('location_destination', False), data.get('product_qty_uom', 0) ], 'level': level, 'unfoldable': data['unfoldable'], }) return lines
def survey_print(self, survey_token, review=False, answer_token=None, **post): '''Display an survey in printable view; if <answer_token> is set, it will grab the answers of the user_input_id that has <answer_token>.''' access_data = self._get_access_data(survey_token, answer_token, ensure_token=False, check_partner=False) if access_data['validity_code'] is not True and ( access_data['has_survey_access'] or access_data['validity_code'] not in ['token_required', 'survey_closed', 'survey_void']): return self._redirect_with_error(access_data, access_data['validity_code']) survey_sudo, answer_sudo = access_data['survey_sudo'], access_data[ 'answer_sudo'] return request.render( 'survey.survey_page_print', { 'is_html_empty': is_html_empty, 'review': review, 'survey': survey_sudo, 'answer': answer_sudo if survey_sudo.scoring_type != 'scoring_without_answers' else answer_sudo.browse(), 'questions_to_display': answer_sudo._get_print_questions(), 'scoring_display_correction': survey_sudo.scoring_type == 'scoring_with_answers' and answer_sudo, 'format_datetime': lambda dt: format_datetime(request.env, dt, dt_format=False), 'format_date': lambda date: format_date(request.env, date), })
def get_date_range_str(self): self.ensure_one() today = fields.Datetime.now() event_date = self.event_begin_date diff = (event_date.date() - today.date()) if diff.days <= 0: return _('today') elif diff.days == 1: return _('tomorrow') elif (diff.days < 7): return _('in %d days') % (diff.days, ) elif (diff.days < 14): return _('next week') elif event_date.month == (today + relativedelta(months=+1)).month: return _('next month') else: return _('on %(date)s', date=format_datetime(self.env, self.event_begin_date, tz=self.event_id.date_tz, dt_format='medium'))
def _prepare_statistics_email_values(self): """Return some statistics that will be displayed in the mailing statistics email. Each item in the returned list will be displayed as a table, with a title and 1, 2 or 3 columns. """ self.ensure_one() random_tip = self.env['digest.tip'].search([ ('group_id.category_id', '=', self.env.ref('base.module_category_marketing_email_marketing').id) ]) if random_tip: random_tip = random.choice(random_tip).tip_description formatted_date = tools.format_datetime( self.env, self.sent_date, self.user_id.tz, 'MMM dd, YYYY', self.user_id.lang) if self.sent_date else False web_base_url = self.env['ir.config_parameter'].sudo().get_param( 'web.base.url') return { 'title': _('24H Stats of mailing'), 'sub_title': '"%s"' % self.subject, 'top_button_label': _('More Info'), 'top_button_url': url_join( web_base_url, f'/web#id={self.id}&model=mailing.mailing&view_type=form'), 'kpi_data': [ { 'kpi_fullname': _('Engagement on %i Emails Sent') % self.sent, 'kpi_action': None, 'kpi_col1': { 'value': f'{self.received_ratio}%', 'col_subtitle': '%s (%i)' % (_('RECEIVED'), self.delivered), }, 'kpi_col2': { 'value': f'{self.opened_ratio}%', 'col_subtitle': '%s (%i)' % (_('OPENED'), self.opened), }, 'kpi_col3': { 'value': f'{self.replied_ratio}%', 'col_subtitle': '%s (%i)' % (_('REPLIED'), self.replied), }, }, { 'kpi_fullname': _('Business Benefits on %i Emails Sent') % self.sent, 'kpi_action': None, 'kpi_col1': {}, 'kpi_col2': {}, 'kpi_col3': {}, }, ], 'tips': [random_tip] if random_tip else False, 'formatted_date': formatted_date, }
def _check_validity(self): """ Verifies the validity of the attendance record compared to the others from the same employee. For the same employee we must have : * maximum 1 "open" attendance record (without check_out) * no overlapping time slices with previous employee records """ for attendance in self: # we take the latest attendance before our check_in time and check it doesn't overlap with ours last_attendance_before_check_in = self.env['hr.attendance'].search( [ ('employee_id', '=', attendance.employee_id.id), ('check_in', '<=', attendance.check_in), ('id', '!=', attendance.id), ], order='check_in desc', limit=1) if last_attendance_before_check_in and last_attendance_before_check_in.check_out and last_attendance_before_check_in.check_out > attendance.check_in: raise exceptions.ValidationError( _("Cannot create new attendance record for %(empl_name)s, the employee was already checked in on %(datetime)s" ) % { 'empl_name': attendance.employee_id.name, 'datetime': format_datetime( self.env, attendance.check_in, dt_format=False), }) if not attendance.check_out: # if our attendance is "open" (no check_out), we verify there is no other "open" attendance no_check_out_attendances = self.env['hr.attendance'].search( [ ('employee_id', '=', attendance.employee_id.id), ('check_out', '=', False), ('id', '!=', attendance.id), ], order='check_in desc', limit=1) if no_check_out_attendances: raise exceptions.ValidationError( _("Cannot create new attendance record for %(empl_name)s, the employee hasn't checked out since %(datetime)s" ) % { 'empl_name': attendance.employee_id.name, 'datetime': format_datetime(self.env, no_check_out_attendances.check_in, dt_format=False), }) else: # we verify that the latest attendance with check_in time before our check_out time # is the same as the one before our check_in time computed before, otherwise it overlaps last_attendance_before_check_out = self.env[ 'hr.attendance'].search([ ('employee_id', '=', attendance.employee_id.id), ('check_in', '<', attendance.check_out), ('id', '!=', attendance.id), ], order='check_in desc', limit=1) if last_attendance_before_check_out and last_attendance_before_check_in != last_attendance_before_check_out: raise exceptions.ValidationError( _("Cannot create new attendance record for %(empl_name)s, the employee was already checked in on %(datetime)s" ) % { 'empl_name': attendance.employee_id.name, 'datetime': format_datetime( self.env, last_attendance_before_check_out.check_in, dt_format=False), })
def _compute_json_popover(self): previous_wo_data = self.env['mrp.workorder'].read_group( [('next_work_order_id', 'in', self.ids)], [ 'ids:array_agg(id)', 'date_planned_start:max', 'date_planned_finished:max' ], ['next_work_order_id']) previous_wo_dict = dict([(x['next_work_order_id'][0], { 'id': x['ids'][0], 'date_planned_start': x['date_planned_start'], 'date_planned_finished': x['date_planned_finished'] }) for x in previous_wo_data]) if self.ids: conflicted_dict = self._get_conflicted_workorder_ids() for wo in self: infos = [] if not wo.date_planned_start or not wo.date_planned_finished or not wo.ids: wo.show_json_popover = False wo.json_popover = False continue if wo.state in ['pending', 'ready']: previous_wo = previous_wo_dict.get(wo.id) prev_start = previous_wo and previous_wo[ 'date_planned_start'] or False prev_finished = previous_wo and previous_wo[ 'date_planned_finished'] or False if wo.state == 'pending' and prev_start and not ( prev_start > wo.date_planned_start): infos.append({ 'color': 'text-primary', 'msg': _("Waiting the previous work order, planned from %(start)s to %(end)s", start=format_datetime(self.env, prev_start, dt_format=False), end=format_datetime(self.env, prev_finished, dt_format=False)) }) if wo.date_planned_finished < fields.Datetime.now(): infos.append({ 'color': 'text-warning', 'msg': _("The work order should have already been processed.") }) if prev_start and prev_start > wo.date_planned_start: infos.append({ 'color': 'text-danger', 'msg': _("Scheduled before the previous work order, planned from %(start)s to %(end)s", start=format_datetime(self.env, prev_start, dt_format=False), end=format_datetime(self.env, prev_finished, dt_format=False)) }) if conflicted_dict.get(wo.id): infos.append({ 'color': 'text-danger', 'msg': _( "Planned at the same time as other workorder(s) at %s", wo.workcenter_id.display_name) }) color_icon = infos and infos[-1]['color'] or False wo.show_json_popover = bool(color_icon) wo.json_popover = json.dumps({ 'infos': infos, 'color': color_icon, 'icon': 'fa-exclamation-triangle' if color_icon in ['text-warning', 'text-danger'] else 'fa-info-circle', 'replan': color_icon not in [False, 'text-primary'] })
def _prepare_survey_data(self, survey_sudo, answer_sudo, **post): """ This method prepares all the data needed for template rendering, in function of the survey user input state. :param post: - previous_page_id : come from the breadcrumb or the back button and force the next questions to load to be the previous ones. """ data = { 'is_html_empty': is_html_empty, 'survey': survey_sudo, 'answer': answer_sudo, 'breadcrumb_pages': [{ 'id': page.id, 'title': page.title, } for page in survey_sudo.page_ids], 'format_datetime': lambda dt: format_datetime(request.env, dt, dt_format=False), 'format_date': lambda date: format_date(request.env, date) } if survey_sudo.questions_layout != 'page_per_question': triggering_answer_by_question, triggered_questions_by_answer, selected_answers = answer_sudo._get_conditional_values( ) data.update({ 'triggering_answer_by_question': { question.id: triggering_answer_by_question[question].id for question in triggering_answer_by_question.keys() if triggering_answer_by_question[question] }, 'triggered_questions_by_answer': { answer.id: triggered_questions_by_answer[answer].ids for answer in triggered_questions_by_answer.keys() }, 'selected_answers': selected_answers.ids }) if not answer_sudo.is_session_answer and survey_sudo.is_time_limited and answer_sudo.start_datetime: data.update({ 'server_time': fields.Datetime.now(), 'timer_start': answer_sudo.start_datetime.isoformat(), 'time_limit_minutes': survey_sudo.time_limit }) page_or_question_key = 'question' if survey_sudo.questions_layout == 'page_per_question' else 'page' # Bypass all if page_id is specified (comes from breadcrumb or previous button) if 'previous_page_id' in post: previous_page_or_question_id = int(post['previous_page_id']) new_previous_id = survey_sudo._get_next_page_or_question( answer_sudo, previous_page_or_question_id, go_back=True).id page_or_question = request.env['survey.question'].sudo().browse( previous_page_or_question_id) data.update({ page_or_question_key: page_or_question, 'previous_page_id': new_previous_id, 'has_answered': answer_sudo.user_input_line_ids.filtered( lambda line: line.question_id.id == new_previous_id), 'can_go_back': survey_sudo._can_go_back(answer_sudo, page_or_question), }) return data if answer_sudo.state == 'in_progress': if answer_sudo.is_session_answer: next_page_or_question = survey_sudo.session_question_id else: next_page_or_question = survey_sudo._get_next_page_or_question( answer_sudo, answer_sudo.last_displayed_page_id.id if answer_sudo.last_displayed_page_id else 0) if next_page_or_question: data.update({ 'survey_last': survey_sudo._is_last_page_or_question( answer_sudo, next_page_or_question) }) if answer_sudo.is_session_answer and next_page_or_question.is_time_limited: data.update({ 'timer_start': survey_sudo.session_question_start_time.isoformat(), 'time_limit_minutes': next_page_or_question.time_limit / 60 }) data.update({ page_or_question_key: next_page_or_question, 'has_answered': answer_sudo.user_input_line_ids.filtered( lambda line: line.question_id == next_page_or_question), 'can_go_back': survey_sudo._can_go_back(answer_sudo, next_page_or_question), }) if survey_sudo.questions_layout != 'one_page': data.update({ 'previous_page_id': survey_sudo._get_next_page_or_question( answer_sudo, next_page_or_question.id, go_back=True).id }) elif answer_sudo.state == 'done' or answer_sudo.survey_time_limit_reached: # Display success message return self._prepare_survey_finished_values( survey_sudo, answer_sudo) return data