def _send_sms_notification(self, params, send_mode='direct'): uuid = 'uid-1232389' params.update({ 'instance': 'test', 'sender': '+41414104141', 'operator': 'orange', 'command': 'FORWARD', 'date': Datetime.now(), 'uuid': uuid, }) if send_mode != 'direct': params.update({ 'receptionDate': Datetime.now(), 'requestUid': uuid, }) url_params = urllib.urlencode(params) response = self.url_open('/sms/mnc/?' + url_params) response_str = response.read() return response_str notification = self.env['sms.notification'].create(params) self.assertEqual(notification.state, 'new') response = notification.run_service() response_str = response.data self.assertEqual(notification.answer, response_str) return notification
def test_in_date_5(self): """ Receive the same lot at different times, once they're in the same location, the quants are merged and only the earliest incoming date is kept. """ lot1 = self.env['stock.production.lot'].create({ 'name': 'lot1', 'product_id': self.product_lot.id, }) from odoo.fields import Datetime in_date1 = Datetime.now() self.env['stock.quant']._update_available_quantity(self.product_lot, self.stock_location, 1.0, lot_id=lot1, in_date=in_date1) quant = self.env['stock.quant'].search([ ('product_id', '=', self.product_lot.id), ('location_id', '=', self.stock_location.id), ]) self.assertEqual(len(quant), 1) self.assertEqual(quant.quantity, 1) self.assertEqual(quant.lot_id.id, lot1.id) self.assertEqual(quant.in_date, in_date1) in_date2 = Datetime.now() - timedelta(days=5) self.env['stock.quant']._update_available_quantity(self.product_lot, self.stock_location, 1.0, lot_id=lot1, in_date=in_date2) quant = self.env['stock.quant'].search([ ('product_id', '=', self.product_lot.id), ('location_id', '=', self.stock_location.id), ]) self.assertEqual(len(quant), 1) self.assertEqual(quant.quantity, 2) self.assertEqual(quant.lot_id.id, lot1.id) self.assertEqual(quant.in_date, in_date2)
def _get_car_atn(self, acquisition_date, car_value, fuel_type, co2): # Compute the correction coefficient from the age of the car now = Datetime.from_string(Datetime.now()) start = Datetime.from_string(acquisition_date) if start: number_of_month = (now.year - start.year) * 12.0 + now.month - start.month + int(bool(now.day - start.day + 1)) if number_of_month <= 12: age_coefficient = 1.00 elif number_of_month <= 24: age_coefficient = 0.94 elif number_of_month <= 36: age_coefficient = 0.88 elif number_of_month <= 48: age_coefficient = 0.82 elif number_of_month <= 60: age_coefficient = 0.76 else: age_coefficient = 0.70 car_value = car_value * age_coefficient # Compute atn value from corrected car_value magic_coeff = 6.0 / 7.0 # Don't ask me why if fuel_type == 'electric': atn = 0.0 else: if fuel_type in ['diesel', 'hybrid']: reference = 87.0 else: reference = 105.0 if co2 <= reference: atn = car_value * max(0.04, (0.055 - 0.001 * (reference - co2))) * magic_coeff else: atn = car_value * min(0.18, (0.055 + 0.001 * (co2 - reference))) * magic_coeff return max(1280, atn) / 12.0
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): res = super(StockHistory, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy) if 'inventory_value' in fields: date = self._context.get('history_date', fieldsDatetime.now()) stock_history = self.env['stock.history'] group_lines = {} for line in res: domain = line.get('__domain', domain) group_lines.setdefault(str(domain), self.search(domain)) stock_history |= group_lines[str(domain)] histories_dict = {} not_real_cost_method_products = stock_history.mapped('product_id').filtered(lambda product: product.cost_method != 'real') if not_real_cost_method_products: self._cr.execute("""SELECT DISTINCT ON (product_id, company_id) product_id, company_id, cost FROM product_price_history WHERE product_id in %s AND datetime <= %s ORDER BY product_id, company_id, datetime DESC, id DESC""", (tuple(not_real_cost_method_products.ids), date)) for history in self._cr.dictfetchall(): histories_dict[(history['product_id'], history['company_id'])] = history['cost'] for line in res: inv_value = 0.0 for stock_history in group_lines.get(str(line.get('__domain', domain))): product = stock_history.product_id if product.cost_method == 'real': price = stock_history.price_unit_on_quant else: price = histories_dict.get((product.id, stock_history.company_id.id), 0.0) inv_value += price * stock_history.quantity line['inventory_value'] = inv_value return res
def _check_presence(self): company = self.env.company if not company.hr_presence_last_compute_date or \ company.hr_presence_last_compute_date.day != Datetime.now().day: self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id) ]).write({'hr_presence_state': 'to_define'}) employees = self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id), ('user_id', '!=', False), ('hr_presence_state', '=', 'to_define')]) # Remove employees on holidays leaves = self.env['hr.leave'].search([ ('state', '=', 'validate'), ('date_from', '<=', Datetime.to_string(Datetime.now())), ('date_to', '>=', Datetime.to_string(Datetime.now()))]) employees_on_holiday = leaves.mapped('employee_id') employees_on_holiday.write({'hr_presence_state': 'absent'}) employees = employees - employees_on_holiday # Check on system login if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_login'): online_employees = employees.filtered(lambda employee: employee.user_id.im_status in ['away', 'online']) online_employees.write({'hr_presence_state': 'present'}) employees = employees - online_employees # Check on IP if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_ip'): ip_list = company.hr_presence_control_ip_list ip_list = ip_list.split(',') if ip_list else [] ip_employees = self.env['hr.employee'] for employee in employees: employee_ips = self.env['res.users.log'].search([ ('create_uid', '=', employee.user_id.id), ('ip', '!=', False), ('create_date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)))] ).mapped('ip') if any([ip in ip_list for ip in employee_ips]): ip_employees |= employee ip_employees.write({'hr_presence_state': 'present'}) employees = employees - ip_employees # Check on sent emails if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_email'): email_employees = self.env['hr.employee'] threshold = company.hr_presence_control_email_amount for employee in employees: sent_emails = self.env['mail.message'].search_count([ ('author_id', '=', employee.user_id.partner_id.id), ('date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))), ('date', '<=', Datetime.to_string(Datetime.now()))]) if sent_emails >= threshold: email_employees |= employee email_employees.write({'hr_presence_state': 'present'}) employees = employees - email_employees company.hr_presence_last_compute_date = Datetime.now()
def poll(self, channels, last, options=None): if request.env.user.has_group('base.group_user'): ip_address = request.httprequest.remote_addr users_log = request.env['res.users.log'].search_count([ ('create_uid', '=', request.env.user.id), ('ip', '=', ip_address), ('create_date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)))]) if not users_log: with registry(request.env.cr.dbname).cursor() as cr: env = Environment(cr, request.env.user.id, {}) env['res.users.log'].create({'ip': ip_address}) return super(BusController, self).poll(channels, last, options=options)
def setUp(self): super(TestTheoreticalAmount, self).setUp() #create the budgetary position user_type_id = self.ref('account.data_account_type_revenue') tag_id = self.ref('account.account_tag_operating') account_rev = self.env['account.account'].create({ 'code': 'Y2020', 'name': 'Budget - Test Revenue Account', 'user_type_id': user_type_id, 'tag_ids': [(4, tag_id, 0)] }) buget_post = self.env['account.budget.post'].create({ 'name': 'Sales', 'account_ids': [(4, account_rev.id, 0)], }) #create the budget and budget lines first_january = Datetime.now().replace(day=1, month=1) self.last_day_of_budget = first_january + timedelta(days=364) # will be 30th of December or 31th in case of leap year date_from = first_january.date() date_to = self.last_day_of_budget.date() crossovered_budget = self.env['crossovered.budget'].create({ 'name': 'test budget name', 'date_from': date_from, 'date_to': date_to, }) crossovered_budget_line_obj = self.env['crossovered.budget.lines'] self.line = crossovered_budget_line_obj.create({ 'crossovered_budget_id': crossovered_budget.id, 'general_budget_id': buget_post.id, 'date_from': date_from, 'date_to': date_to, 'planned_amount': -364, }) self.paid_date_line = crossovered_budget_line_obj.create({ 'crossovered_budget_id': crossovered_budget.id, 'general_budget_id': buget_post.id, 'date_from': date_from, 'date_to': date_to, 'planned_amount': -364, 'paid_date': Date.today().replace(day=9, month=9), }) self.patcher = patch('odoo.addons.account_budget.models.account_budget.fields.Date', wraps=Date) self.mock_date = self.patcher.start()
def _download_attendance_queue(self, zk_id=None): zk = self.env['zk.machine'].search([], limit=1) if len(zk) > 0: time_zone = zk.time_zone date_now = Datetime.now().astimezone( timezone(time_zone)).strftime("%d/%m/%Y") zk_need_pull = self.env['zk.machine'].search([('last_date_pull', '!=', date_now), ('id', '=', zk_id)]) zk_attendance = self.env['zk.machine.attendance'] att_obj = self.env['hr.attendance'] if len(zk_need_pull) > 0: for info in zk_need_pull: if info.state != 'in_process': self.env.cr.execute( """update zk_machine set state = 'in_process' WHERE id=%s""", (info.id, )) self.env.cr.commit() conn = None try: conn = info.connect() except Exception as e: self.env.cr.execute( """update zk_machine set state = 'ready' WHERE id=%s""", (info.id, )) self.env.cr.commit() try: attendances = None if conn: attendances = conn.get_attendance() if attendances: for each in attendances: atten_time = each.timestamp local_tz = pytz.timezone(time_zone) local_dt = local_tz.localize( atten_time, is_dst=None) utc_dt = local_dt.astimezone(pytz.utc) utc_dt = utc_dt.strftime( "%Y-%m-%d %H:%M:%S") atten_time = each.timestamp.strptime( utc_dt, "%Y-%m-%d %H:%M:%S") atten_time = fields.Datetime.to_string( atten_time) get_user_id = info.env[ 'hr.employee'].search([ ('device_id', '=', str(each.user_id)), ('zk_id', '=', info.id) ]) if each.punch not in [ 0, 1, 2, 3, 4, 5 ]: each.punch = 255 if get_user_id: duplicate_atten_ids = zk_attendance.search( [('device_id', '=', str(each.user_id)), ('punching_time', '=', atten_time), ('zk_id', '=', info.id)]) if duplicate_atten_ids: continue else: try: zk_attendance.create({ 'employee_id': get_user_id.id, 'device_id': each.user_id, 'attendance_type': "1", 'punch_type': str(each.punch), 'punching_time': atten_time, 'address_id': info.address_id.id, 'zk_id': info.id }) date = each.timestamp.strftime( "%d/%m/%Y") att_var = att_obj.search([ ('employee_id', '=', get_user_id.id), ('date_check_in', '=', date) ]) if not att_var: try: att_obj.create({ 'employee_id': get_user_id.id, 'check_in': atten_time, 'date_check_in': date }) except Exception as e: 'print(" Error " + str(e))' else: att_var.write({ 'check_out': atten_time }) # if each.punch not in [0, 1]: # "print('Wrong Code' + str(each.punch))" except Exception as e: print("Error" + str(e)) else: pass # create new employee else: if info.auto_create_new_emp: users = None try: users = conn.get_users() except Exception as e: "print('Error:' + str(e))" new_emp = None if users: for user in users: if user.user_id == str( each.user_id): new_emp = user break employee = info.env[ 'hr.employee'].create({ 'device_id': str(each.user_id), 'name': new_emp.name, 'zk_id': info.id }) zk_attendance.create({ 'employee_id': employee.id, 'device_id': each.user_id, 'attendance_type': "1", 'punch_type': str(each.punch), 'punching_time': atten_time, 'zk_id': info.id, }) try: att_obj.create({ 'employee_id': employee.id, 'check_in': atten_time }) except Exception as e: 'print(" Error " + str(e))' # Write Date Pull date_now = Datetime.now().astimezone( timezone(info.time_zone)).strftime( "%d/%m/%Y") try: # info.write({'last_date_pull': date_now}) self.env.cr.execute( """update zk_machine set state = 'ready',last_date_pull = %s WHERE id=%s""", ( date_now, info.id, )) self.env.cr.commit() except Exception as e: self.env.cr.execute( """update zk_machine set state = 'ready' WHERE id=%s""", (info.id, )) self.env.cr.commit() else: self.env.cr.execute( """update zk_machine set state = 'ready' WHERE id=%s""", (info.id, )) self.env.cr.commit() except Exception as e: "print(e)" finally: self.env.cr.execute( """update zk_machine set state = 'ready' WHERE id=%s""", (info.id, )) self.env.cr.commit()
def download_attendance(self): _logger.info("++++++++++++Cron Executed++++++++++++++++++++++") zk_attendance = self.env['zk.machine.attendance'] att_obj = self.env['hr.attendance'] if self.state != 'in_process': # mark in process for this record self.env.cr.execute( """update zk_machine set state = 'in_process' WHERE id=%s""", (self.id, )) self.env.cr.commit() for info in self: try: conn = info.connect() except Exception as e: raise UserError(str(e)) attendances = None try: if conn: attendances = conn.get_attendance() if attendances: for each in attendances: atten_time = each.timestamp local_tz = pytz.timezone( self.env.user.partner_id.tz or 'GMT') local_dt = local_tz.localize(atten_time, is_dst=None) utc_dt = local_dt.astimezone(pytz.utc) utc_dt = utc_dt.strftime("%Y-%m-%d %H:%M:%S") atten_time = each.timestamp.strptime( utc_dt, "%Y-%m-%d %H:%M:%S") atten_time = fields.Datetime.to_string( atten_time) get_user_id = self.env['hr.employee'].search([ ('device_id', '=', str(each.user_id)), ('zk_id', '=', self.id) ]) # if each.user_id == 3: # print('vi') # print(atten_time) if each.punch not in [0, 1, 2, 3, 4, 5]: each.punch = 255 if get_user_id: duplicate_atten_ids = zk_attendance.search( [('device_id', '=', str(each.user_id)), ('punching_time', '=', atten_time), ('zk_id', '=', self.id)]) if duplicate_atten_ids: continue else: try: zk_attendance.create({ 'employee_id': get_user_id.id, 'device_id': each.user_id, 'attendance_type': "1", 'punch_type': str(each.punch), 'punching_time': atten_time, 'address_id': info.address_id.id, 'zk_id': self.id }) date = each.timestamp.strftime( "%d/%m/%Y") att_var = att_obj.search([ ('employee_id', '=', get_user_id.id), ('date_check_in', '=', date) ]) if not att_var: try: att_obj.create({ 'employee_id': get_user_id.id, 'check_in': atten_time, 'date_check_in': date }) except Exception as e: 'print(" Error " + str(e))' else: att_var.write( {'check_out': atten_time}) # if each.punch not in [0, 1]: # "print('Wrong Code' + str(each.punch))" except Exception as e: print("Error" + str(e)) else: pass # create new employee else: if self.auto_create_new_emp: users = None try: users = conn.get_users() except Exception as e: "print('Error:' + str(e))" new_emp = None if users: for user in users: if user.user_id == str( each.user_id): new_emp = user break employee = self.env[ 'hr.employee'].create({ 'device_id': str(each.user_id), 'name': new_emp.name, 'zk_id': self.id }) zk_attendance.create({ 'employee_id': employee.id, 'device_id': each.user_id, 'attendance_type': '1', 'punch_type': str(each.punch), 'punching_time': atten_time, 'zk_id': self.id }) try: att_obj.create({ 'employee_id': employee.id, 'check_in': atten_time }) except Exception as e: 'print(" Error " + str(e))' # Write Date Pull date_now = Datetime.now().astimezone( timezone(self.time_zone)).strftime("%d/%m/%Y") try: self.env.cr.execute( """update zk_machine set state = 'ready' WHERE id=%s""", (self.id, )) self.env.cr.execute( """update zk_machine set last_date_pull = %s WHERE id=%s""", ( date_now, self.id, )) self.env.cr.commit() except Exception as e: """print(e)""" self.env.cr.execute( """update zk_machine set state = 'ready' WHERE id=%s""", (self.id, )) self.env.cr.commit() return { 'name': 'Message', 'type': 'ir.actions.act_window', 'view_mode': 'form', 'res_model': 'custom.pop.message', 'target': 'new', 'context': { 'default_name': "Download Data Complete!" } } else: raise UserError( _('Unable to get the attendance log, please try again later.' )) else: raise UserError( _('Unable to connect, please check the parameters and network connections.' )) except Exception as e: raise ValueError("Process terminate : {}".format(e)) finally: if attendances: if info.auto_clear_log: if conn: conn.clear_attendance() if conn: conn.disconnect()
def web_login(self, redirect=None, **kw): ensure_db() request.params['login_success'] = False if request.httprequest.method == 'GET' and redirect and request.session.uid: return http.redirect_with_hash(redirect) if not request.uid: request.uid = odoo.SUPERUSER_ID values = request.params.copy() try: values['databases'] = http.db_list() except odoo.exceptions.AccessDenied: values['databases'] = None if request.httprequest.method == 'POST': # fix login = request.params['login'] user = request.env['res.users'].sudo().search([('login', '=', login)]) block_config = request.env['limit_login.block.config'].sudo( ).search([('is_active', '=', True)]) is_limit_attempts = len(user) > 0 and len(block_config) > 0 if is_limit_attempts: user = user[0] block_config = block_config[0] block_user = request.env['limit_login.block'].sudo().search([ ('user_id', '=', user.id) ]) now = Datetime.now() last_login_fail = user.last_login_fail delta = Datetime.from_string(now) - Datetime.from_string( last_login_fail) remaining_time = datetime.timedelta( hours=block_config.block_time) - delta remaining_time = remaining_time.total_seconds( ) if remaining_time.total_seconds() > 0 else 0 # if user is blocked if len(block_user) > 0 and remaining_time: values['error'] = _(block_config.message_block) values['remaining_time'] = remaining_time values['unblock_message'] = _(block_config.message_unblock) # base if 'login' not in values and request.session.get( 'auth_login'): values['login'] = request.session.get('auth_login') if not odoo.tools.config['list_db']: values['disable_database_manager'] = True response = request.render('web.login', values) response.headers['X-Frame-Options'] = 'DENY' return response # if user is unblocked elif len(block_user) > 0: block_user[0].unlink() # base old_uid = request.uid uid = request.session.authenticate(request.session.db, request.params['login'], request.params['password']) if uid is not False: request.params['login_success'] = True return http.redirect_with_hash( self._login_redirect(uid, redirect=redirect)) request.uid = old_uid # if login fail last_count_attempts = user.count_attempts # update last_login_fail user.write({'last_login_fail': now}) if delta <= datetime.timedelta(hours=block_config.interval): current_count_attempts = last_count_attempts + 1 if current_count_attempts >= block_config.attempts: # add user to block list request.env['limit_login.block'].sudo().create( {'user_id': user.id}) values['error'] = _(block_config.message_block) values['remaining_time'] = remaining_time values['unblock_message'] = _( block_config.message_unblock) else: values['error'] = _("Wrong password" + ' - ' + str(current_count_attempts) + '/' + str(block_config.attempts)) # update count_attempts user.write({'count_attempts': current_count_attempts}) else: # reset count_attempts user.write({'count_attempts': 1}) values['error'] = _("Wrong password" + ' - ' + '1/' + str(block_config.attempts)) else: # base old_uid = request.uid uid = request.session.authenticate(request.session.db, request.params['login'], request.params['password']) if uid is not False: request.params['login_success'] = True return http.redirect_with_hash( self._login_redirect(uid, redirect=redirect)) request.uid = old_uid values['error'] = _("Wrong login/password") else: if 'error' in request.params and request.params.get( 'error') == 'access': values['error'] = _( 'Only employee can access this database. Please contact the administrator.' ) if 'login' not in values and request.session.get('auth_login'): values['login'] = request.session.get('auth_login') if not odoo.tools.config['list_db']: values['disable_database_manager'] = True response = request.render('web.login', values) response.headers['X-Frame-Options'] = 'DENY' return response
def action_set_synchronized(self): self.write({'last_sync_date': Datetime.now()}) self.mapped('marketing_activity_ids').write({'require_sync': False})
def _action_open_presence_view(self): # Compute the presence/absence for the employees on the same # company than the HR/manager. Then opens the kanban view # of the employees with an undefined presence/absence _logger.info("Employees presence checked by: %s" % self.env.user.name) company = self.env.user.company_id if not company.hr_presence_last_compute_date or \ company.hr_presence_last_compute_date.day != Datetime.now().day: self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id) ]).write({'hr_presence_state': 'to_define'}) employees = self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id), ('user_id', '!=', False), ('hr_presence_state', '=', 'to_define') ]) # Remove employees on holidays leaves = self.env['hr.leave'].search([ ('state', '=', 'validate'), ('date_from', '<=', Datetime.to_string(Datetime.now())), ('date_to', '>=', Datetime.to_string(Datetime.now())) ]) employees_on_holiday = leaves.mapped('employee_id') employees_on_holiday.write({'hr_presence_state': 'absent'}) employees = employees - employees_on_holiday # Check on system login if self.env['ir.config_parameter'].sudo().get_param( 'hr_presence.hr_presence_control_login'): online_employees = employees.filtered( lambda employee: employee.user_id.im_status in ['away', 'online']) online_employees.write({'hr_presence_state': 'present'}) employees = employees - online_employees # Check on IP if self.env['ir.config_parameter'].sudo().get_param( 'hr_presence.hr_presence_control_ip'): ip_list = company.hr_presence_control_ip_list ip_list = ip_list.split(',') if ip_list else [] ip_employees = self.env['hr.employee'] for employee in employees: employee_ips = self.env['res.users.log'].search([ ('create_uid', '=', employee.user_id.id), ('ip', '!=', False), ('create_date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))) ]).mapped('ip') if any([ip in ip_list for ip in employee_ips]): ip_employees |= employee ip_employees.write({'hr_presence_state': 'present'}) employees = employees - ip_employees # Check on sent emails if self.env['ir.config_parameter'].sudo().get_param( 'hr_presence.hr_presence_control_email'): email_employees = self.env['hr.employee'] threshold = company.hr_presence_control_email_amount for employee in employees: sent_emails = self.env['mail.message'].search_count([ ('author_id', '=', employee.user_id.partner_id.id), ('date', '>=', Datetime.to_string(Datetime.now().replace( hour=0, minute=0, second=0, microsecond=0))), ('date', '<=', Datetime.to_string(Datetime.now())) ]) if sent_emails >= threshold: email_employees |= employee email_employees.write({'hr_presence_state': 'present'}) employees = employees - email_employees company.hr_presence_last_compute_date = Datetime.now() return { "type": "ir.actions.act_window", "res_model": "hr.employee", "views": [[ self.env.ref('hr_presence.hr_employee_view_kanban').id, "kanban" ], [False, "tree"], [False, "form"]], 'view_mode': 'kanban,tree,form', "domain": [], "name": "Employee's Presence to Define", "context": { 'search_default_group_hr_presence_state': 1 }, }
def setUp(self): super(TestPurchaseOpenQty, self).setUp() self.purchase_order_model = self.env['purchase.order'] purchase_order_line_model = self.env['purchase.order.line'] partner_model = self.env['res.partner'] prod_model = self.env['product.product'] analytic_account_model = self.env['account.analytic.account'] # partners pa_dict = { 'name': 'Partner 1', 'supplier': True, } self.partner = partner_model.sudo().create(pa_dict) pa_dict2 = { 'name': 'Partner 2', 'supplier': True, } self.partner2 = partner_model.sudo().create(pa_dict2) # account ac_dict = { 'name': 'analytic account 1', } self.analytic_account_1 = \ analytic_account_model.sudo().create(ac_dict) # Purchase Order Num 1 po_dict = { 'partner_id': self.partner.id, } self.purchase_order_1 = self.purchase_order_model.create(po_dict) uom_id = prod_model.uom_id.search([('name', '=', 'Unit(s)')], limit=1).id pr_dict = { 'name': 'Product Test', 'uom_id': uom_id, 'purchase_method': 'purchase', } self.product = prod_model.sudo().create(pr_dict) pl_dict1 = { 'date_planned': Datetime.now(), 'name': 'PO01', 'order_id': self.purchase_order_1.id, 'product_id': self.product.id, 'product_uom': uom_id, 'price_unit': 1.0, 'product_qty': 5.0, 'account_analytic_id': self.analytic_account_1.id, } self.purchase_order_line_1 = \ purchase_order_line_model.sudo().create(pl_dict1) self.purchase_order_1.button_confirm() # Purchase Order Num 2 po_dict2 = { 'partner_id': self.partner2.id, } self.purchase_order_2 = self.purchase_order_model.create(po_dict2) pr_dict2 = { 'name': 'Product Test 2', 'uom_id': uom_id, 'purchase_method': 'receive', } self.product2 = prod_model.sudo().create(pr_dict2) pl_dict2 = { 'date_planned': Datetime.now(), 'name': 'PO02', 'order_id': self.purchase_order_2.id, 'product_id': self.product2.id, 'product_uom': uom_id, 'price_unit': 1.0, 'product_qty': 5.0, 'account_analytic_id': self.analytic_account_1.id, } self.purchase_order_line_2 = \ purchase_order_line_model.sudo().create(pl_dict2) self.purchase_order_2.button_confirm()
def _test_work_entries(self): work_entry_type = self.create_work_entry_type( user=self.hr_payroll_manager, name='bla', code='TYPE100', ) work_entry_type_leave = self.create_work_entry_type( user=self.hr_payroll_manager, name='bla bla', code='TYPE200', is_leave=True, ) self.link_leave_work_entry_type( user=self.hr_payroll_manager, work_entry_type=work_entry_type_leave, leave_type=self.leave_type_1, ) # Request a leave but don't approve it non_approved_leave = self.create_leave( user=self.user, leave_type=self.leave_type_1, start=Datetime.now() + relativedelta(days=12), end=Datetime.now() + relativedelta(days=13)) self.user.employee_id.with_user( self.hr_payroll_user).generate_work_entries( Datetime.today().replace(day=1), Datetime.today() + relativedelta(months=1, day=1, days=-1, hour=23, minute=59)) work_entries = self.env['hr.work.entry'].with_user( self.hr_payroll_user).search([('employee_id', '=', self.user.employee_id.id)]) # should not be able to validate self.assertFalse( work_entries.with_user(self.hr_payroll_user).action_validate()) work_entries_with_error = work_entries.filtered( lambda b: b.state == 'conflict') self.env['hr.leave'].search([('employee_id', "=", self.user.employee_id.id)]) # Check work_entries without a type undefined_type = work_entries_with_error.filtered( lambda b: not b.work_entry_type_id) self.assertTrue( undefined_type ) # some leave types we created earlier are not linked to any work entry type undefined_type.write({'work_entry_type_id': work_entry_type_leave.id}) # Check work_entries conflicting with a leave, approve them as payroll manager conflicting_leave = work_entries_with_error.filtered( lambda b: b.leave_id and b.leave_id.state != 'validate') # this user need "group_hr_timesheet_approver" to access timesheets of other user with additional_groups(self.hr_payroll_user, 'hr_timesheet.group_hr_timesheet_approver'): conflicting_leave.mapped('leave_id').with_user( self.hr_payroll_user).action_approve() # Reload work_entries (some might have been deleted/created when approving leaves) work_entries = self.env['hr.work.entry'].with_user( self.hr_payroll_user).search([('employee_id', '=', self.user.employee_id.id)]) # Some work entries are still conflicting (if not completely included in a leave) self.assertFalse( work_entries.with_user(self.hr_payroll_user).action_validate()) work_entries.filtered(lambda w: w.state == 'conflict').write( {'state': 'cancelled'}) self.assertTrue( work_entries.with_user(self.hr_payroll_user).action_validate())
def test_basic(self): """ Basic order test: no routing (thus no workorders), no lot """ self.product_1.type = 'product' self.product_2.type = 'product' inventory = self.env['stock.inventory'].create({ 'name': 'Initial inventory', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': self.product_1.id, 'product_uom_id': self.product_1.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id }), (0, 0, { 'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id })] }) inventory.action_validate() test_date_planned = Dt.now() - timedelta(days=1) test_quantity = 2.0 self.bom_1.routing_id = False man_order = self.env['mrp.production'].sudo(self.user_mrp_user).create( { 'name': 'Stick-0', 'product_id': self.product_4.id, 'product_uom_id': self.product_4.uom_id.id, 'product_qty': test_quantity, 'bom_id': self.bom_1.id, 'date_planned_start': test_date_planned, 'location_src_id': self.location_1.id, 'location_dest_id': self.warehouse_1.wh_output_stock_loc_id.id, }) self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.") # check production move production_move = man_order.move_finished_ids self.assertEqual(production_move.date, test_date_planned) self.assertEqual(production_move.product_id, self.product_4) self.assertEqual(production_move.product_uom, man_order.product_uom_id) self.assertEqual(production_move.product_qty, man_order.product_qty) self.assertEqual(production_move.location_id, self.product_4.property_stock_production) self.assertEqual(production_move.location_dest_id, man_order.location_dest_id) # check consumption moves for move in man_order.move_raw_ids: self.assertEqual(move.date, test_date_planned) first_move = man_order.move_raw_ids.filtered( lambda move: move.product_id == self.product_2) self.assertEqual( first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2) first_move = man_order.move_raw_ids.filtered( lambda move: move.product_id == self.product_1) self.assertEqual( first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4) # waste some material, create a scrap # scrap = self.env['stock.scrap'].with_context( # active_model='mrp.production', active_id=man_order.id # ).create({}) # scrap = self.env['stock.scrap'].create({ # 'production_id': man_order.id, # 'product_id': first_move.product_id.id, # 'product_uom_id': first_move.product_uom.id, # 'scrap_qty': 5.0, # }) # check created scrap # procurements = self.env['procurement.order'].search([('move_dest_id', 'in', man_order.move_raw_ids.ids)]) # print procurements # procurements = self.env['procurement.order'].search([('production_id', '=', man_order.id)]) # print procurements # for proc in self.env['procurement.order'].browse(procurements): # date_planned = self.mrp_production_test1.date_planned # if proc.product_id.type not in ('product', 'consu'): # continue # if proc.product_id.id == order_line.product_id.id: # self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond") # # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which # # case it could already be in `running` or `exception` state (not enough stock) # expected_states = ('confirmed', 'running', 'exception') # self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states)) # Change production quantity qty_wizard = self.env['change.production.qty'].create({ 'mo_id': man_order.id, 'product_qty': 3.0, }) # qty_wizard.change_prod_qty() # # I check qty after changed in production order. # #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.") # move = self.mrp_production_test1.move_finished_ids[0] # self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.") # # I run scheduler. # self.env['procurement.order'].run_scheduler() # # The production order is Waiting Goods, will force production which should set consume lines as available # self.mrp_production_test1.button_plan() # # I check that production order in ready state after forcing production. # #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available') # produce product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': man_order.id, 'active_ids': [man_order.id], })) produce_form.product_qty = 1.0 produce_wizard = produce_form.save() produce_wizard.do_produce() # man_order.button_mark_done() man_order.button_mark_done() self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
def test_basic(self): """ Checks a basic manufacturing order: no routing (thus no workorders), no lot and consume strictly what's needed. """ self.product_1.type = 'product' self.product_2.type = 'product' inventory = self.env['stock.inventory'].create({ 'name': 'Initial inventory', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': self.product_1.id, 'product_uom_id': self.product_1.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id }), (0, 0, { 'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id })] }) inventory.action_validate() test_date_planned = Dt.now() - timedelta(days=1) test_quantity = 2.0 self.bom_1.routing_id = False man_order_form = Form(self.env['mrp.production'].sudo( self.user_mrp_user)) man_order_form.product_id = self.product_4 man_order_form.bom_id = self.bom_1 man_order_form.product_uom_id = self.product_4.uom_id man_order_form.product_qty = test_quantity man_order_form.date_planned_start = test_date_planned man_order_form.location_src_id = self.location_1 man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id man_order = man_order_form.save() self.assertEqual(man_order.state, 'draft', "Production order should be in draft state.") man_order.action_confirm() self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.") # check production move production_move = man_order.move_finished_ids self.assertEqual(production_move.date, test_date_planned) self.assertEqual(production_move.product_id, self.product_4) self.assertEqual(production_move.product_uom, man_order.product_uom_id) self.assertEqual(production_move.product_qty, man_order.product_qty) self.assertEqual(production_move.location_id, self.product_4.property_stock_production) self.assertEqual(production_move.location_dest_id, man_order.location_dest_id) # check consumption moves for move in man_order.move_raw_ids: self.assertEqual(move.date, test_date_planned) first_move = man_order.move_raw_ids.filtered( lambda move: move.product_id == self.product_2) self.assertEqual( first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2) first_move = man_order.move_raw_ids.filtered( lambda move: move.product_id == self.product_1) self.assertEqual( first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4) # produce product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': man_order.id, 'active_ids': [man_order.id], })) produce_form.qty_producing = 1.0 produce_wizard = produce_form.save() produce_wizard.do_produce() man_order.button_mark_done() self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
def setUp(self): super(TestUICommon, self).setUp() # Load pdf and img contents pdf_path = get_module_resource('website_slides', 'static', 'src', 'img', 'presentation.pdf') pdf_content = base64.b64encode(open(pdf_path, "rb").read()) img_path = get_module_resource('website_slides', 'static', 'src', 'img', 'slide_demo_gardening_1.jpg') img_content = base64.b64encode(open(img_path, "rb").read()) self.env['slide.channel'].create({ 'name': 'Basics of Gardening - Test', 'user_id': self.env.ref('base.user_admin').id, 'enroll': 'public', 'channel_type': 'training', 'allow_comment': True, 'promote_strategy': 'most_voted', 'is_published': True, 'description': 'Learn the basics of gardening !', 'create_date': Datetime.now() - relativedelta(days=8), 'slide_ids': [(0, 0, { 'name': 'Gardening: The Know-How', 'sequence': 1, 'binary_content': pdf_content, 'slide_category': 'document', 'is_published': True, 'is_preview': True, }), (0, 0, { 'name': 'Home Gardening', 'sequence': 2, 'image_1920': img_content, 'slide_category': 'infographic', 'is_published': True, }), (0, 0, { 'name': 'Mighty Carrots', 'sequence': 3, 'image_1920': img_content, 'slide_category': 'infographic', 'is_published': True, }), (0, 0, { 'name': 'How to Grow and Harvest The Best Strawberries | Basics', 'sequence': 4, 'binary_content': pdf_content, 'slide_category': 'document', 'is_published': True, }), (0, 0, { 'name': 'Test your knowledge', 'sequence': 5, 'slide_category': 'quiz', 'is_published': True, 'question_ids': [ (0, 0, { 'question': 'What is a strawberry ?', 'answer_ids': [ (0, 0, { 'text_value': 'A fruit', 'is_correct': True, 'sequence': 1, }), (0, 0, { 'text_value': 'A vegetable', 'sequence': 2, }), (0, 0, { 'text_value': 'A table', 'sequence': 3, }) ] }), (0, 0, { 'question': 'What is the best tool to dig a hole for your plants ?', 'answer_ids': [(0, 0, { 'text_value': 'A shovel', 'is_correct': True, 'sequence': 1, }), (0, 0, { 'text_value': 'A spoon', 'sequence': 2, })] }) ] })] })
def setUp(self): super(TestMailActivityTeam, self).setUp() self.env["mail.activity.team"].search([]).unlink() self.employee = self.env['res.users'].create({ 'company_id': self.env.ref("base.main_company").id, 'name': "Employee", 'login': "******", 'email': "*****@*****.**", 'groups_id': [(6, 0, [ self.env.ref('base.group_user').id, self.env.ref('base.group_partner_manager').id ])] }) self.employee2 = self.env['res.users'].create({ 'company_id': self.env.ref("base.main_company").id, 'name': "Employee 2", 'login': "******", 'email': "*****@*****.**", 'groups_id': [(6, 0, [self.env.ref('base.group_user').id])] }) self.partner_ir_model = self.env['ir.model']._get('res.partner') activity_type_model = self.env['mail.activity.type'] self.activity1 = activity_type_model.create({ 'name': 'Initial Contact', 'days': 5, 'summary': 'ACT 1 : Presentation, barbecue, ... ', 'res_model_id': self.partner_ir_model.id, }) self.activity2 = activity_type_model.create({ 'name': 'Call for Demo', 'days': 6, 'summary': 'ACT 2 : I want to show you my ERP !', 'res_model_id': self.partner_ir_model.id, }) self.partner_client = self.env.ref("base.res_partner_1") self.act1 = self.env['mail.activity'].sudo(self.employee).create({ 'activity_type_id': self.activity1.id, 'note': 'Partner activity 1.', 'res_id': self.partner_client.id, 'res_model_id': self.partner_ir_model.id, 'user_id': self.employee.id, }) self.team1 = self.env['mail.activity.team'].sudo().create({ 'name': 'Team 1', 'res_model_ids': [(6, 0, [self.partner_ir_model.id])], 'member_ids': [(6, 0, [self.employee.id])], }) self.team2 = self.env['mail.activity.team'].sudo().create({ 'name': 'Team 2', 'res_model_ids': [(6, 0, [self.partner_ir_model.id])], 'member_ids': [(6, 0, [self.employee.id, self.employee2.id])], }) self.act2 = self.env['mail.activity'].sudo(self.employee).create({ 'activity_type_id': self.activity2.id, 'note': 'Partner activity 2.', 'res_id': self.partner_client.id, 'res_model_id': self.partner_ir_model.id, 'user_id': self.employee.id, }) self.act3 = self.env['mail.activity'].sudo(self.employee).create({ 'activity_type_id': self.browse_ref('mail.mail_activity_data_meeting').id, 'note': 'Meeting activity 3.', 'res_id': self.partner_client.id, 'res_model_id': self.partner_ir_model.id, 'user_id': self.employee.id, 'team_id': self.team1.id, 'summary': 'Metting activity' }) self.start = Datetime.now() self.stop = Datetime.to_string( Datetime.from_string(self.start) + timedelta(hours=1))
def _execute_email(self, traces): res_ids = [r for r in set(traces.mapped('res_id'))] mailing = self.mass_mailing_id.with_context( default_marketing_activity_id=self.ids[0], active_ids=res_ids, ) # we only allow to continue if the user has sufficient rights, as a sudo() follows if not self.env.is_superuser() and not self.user_has_groups( 'marketing_automation.group_marketing_automation_user'): raise AccessError( _('To use this feature you should be an administrator or belong to the marketing automation group.' )) try: mailing.sudo().action_send_mail(res_ids) except Exception as e: _logger.warning( 'Marketing Automation: activity <%s> encountered mass mailing issue %s', self.id, str(e), exc_info=True) traces.write({ 'state': 'error', 'schedule_date': Datetime.now(), 'state_msg': _('Exception in mass mailing: %s', str)(e), }) else: failed_stats = self.env['mailing.trace'].sudo().search([ ('marketing_trace_id', 'in', traces.ids), '|', ('exception', '!=', False), ('ignored', '!=', False) ]) ignored_doc_ids = [ stat.res_id for stat in failed_stats if stat.exception ] error_doc_ids = [ stat.res_id for stat in failed_stats if stat.ignored ] processed_traces = traces ignored_traces = traces.filtered( lambda trace: trace.res_id in ignored_doc_ids) error_traces = traces.filtered( lambda trace: trace.res_id in error_doc_ids) if ignored_traces: ignored_traces.write({ 'state': 'canceled', 'schedule_date': Datetime.now(), 'state_msg': _('Email ignored') }) processed_traces = processed_traces - ignored_traces if error_traces: error_traces.write({ 'state': 'error', 'schedule_date': Datetime.now(), 'state_msg': _('Email failed') }) processed_traces = processed_traces - error_traces if processed_traces: processed_traces.write({ 'state': 'processed', 'schedule_date': Datetime.now(), }) return True
def action_cancel(self, message=None): values = {'state': 'canceled', 'schedule_date': Datetime.now()} if message: values['state_msg'] = message self.write(values) self.mapped('participant_id').check_completed()
def _get_report_data(self, data): year = data['year'] employees = self.env['hr.employee'].browse(data['employee_ids']) payslips = self.env['hr.payslip'].search([ ('employee_id', 'in', employees.ids), ('state', '=', 'done'), ('date_from', '>=', Datetime.now().replace(month=1, day=1, year=year)), ('date_from', '<=', Datetime.now().replace(month=12, day=31, year=year)), '|', ('struct_id.country_id', '=', False), ('struct_id.country_id', '=', self.env.ref('base.be').id), ]) lines = payslips.mapped('line_ids') payslip_rules = [(rule.code, rule.sequence) for rule in lines.mapped('salary_rule_id')] payslip_rules = sorted(payslip_rules, key=lambda x: x[1]) worked_days = payslips.mapped('worked_days_line_ids') result = { employee: { 'rules': OrderedDict( (rule[0], { 'year': {'name': False, 'total': 0}, 'month': {m: {'name': False, 'total': 0} for m in range(12)}, 'quarter': {q: {'name': False, 'total': 0} for q in range(4)} }) for rule in payslip_rules), 'worked_days': { code: { 'year': {'name': False, 'number_of_days': 0, 'number_of_hours': 0}, 'month': {m: {'name': False, 'number_of_days': 0, 'number_of_hours': 0} for m in range(12)}, 'quarter': {q: {'name': False, 'number_of_days': 0, 'number_of_hours': 0} for q in range(4)} } for code in worked_days.mapped('code') } } for employee in employees } for line in lines: rule = result[line.employee_id]['rules'][line.salary_rule_id.code] month = line.slip_id.date_from.month - 1 rule['month'][month]['name'] = line.name rule['month'][month]['total'] += line.total rule['quarter'][(month) // 3]['name'] = line.name rule['quarter'][(month) // 3]['total'] += line.total rule['year']['name'] = line.name rule['year']['total'] += line.total rule['month'][month]['total'] = round(rule['month'][month]['total'], 2) rule['quarter'][(month) // 3]['total'] = round(rule['quarter'][(month) // 3]['total'], 2) rule['year']['total'] = round(rule['year']['total'], 2) for worked_day in worked_days: work = result[worked_day.payslip_id.employee_id]['worked_days'][worked_day.code] month = worked_day.payslip_id.date_from.month - 1 work['month'][month]['name'] = worked_day.name work['month'][month]['number_of_days'] += worked_day.number_of_days work['month'][month]['number_of_hours'] += worked_day.number_of_hours work['quarter'][(month) // 3]['name'] = worked_day.name work['quarter'][(month) // 3]['number_of_days'] += worked_day.number_of_days work['quarter'][(month) // 3]['number_of_hours'] += worked_day.number_of_hours work['year']['name'] = worked_day.name work['year']['number_of_days'] += worked_day.number_of_days work['year']['number_of_hours'] += worked_day.number_of_hours return { 'year': year, 'employee_data': result }
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): res = super(StockHistory, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy) if 'inventory_value' in fields: date = self._context.get('history_date', fieldsDatetime.now()) stock_history = self.env['stock.history'] group_lines = {} for line in res: domain = line.get('__domain', domain) group_lines.setdefault(str(domain), self.search(domain)) stock_history |= group_lines[str(domain)] # get data of stock_history in one shot to speed things up (the view can be very slow) stock_history_data = {} if stock_history: self._cr.execute( """SELECT id, product_id, price_unit_on_quant, company_id, quantity FROM stock_history WHERE id in %s""", (tuple(stock_history.ids), )) stock_history_data = { line['id']: line for line in self._cr.dictfetchall() } histories_dict = {} not_real_cost_method_products = self.env['product.product'].browse( record['product_id'] for record in stock_history_data.values()).filtered( lambda product: product.cost_method != 'real') if not_real_cost_method_products: self._cr.execute( """SELECT DISTINCT ON (product_id, company_id) product_id, company_id, cost FROM product_price_history WHERE product_id in %s AND datetime <= %s ORDER BY product_id, company_id, datetime DESC, id DESC""", (tuple(not_real_cost_method_products.ids), date)) for history in self._cr.dictfetchall(): histories_dict[(history['product_id'], history['company_id'])] = history['cost'] for line in res: inv_value = 0.0 for stock_history in group_lines.get( str(line.get('__domain', domain))): history_data = stock_history_data[stock_history.id] product_id = history_data['product_id'] if self.env['product.product'].browse( product_id).cost_method == 'real': price = history_data['price_unit_on_quant'] else: price = histories_dict.get( (product_id, history_data['company_id']), 0.0) inv_value += price * history_data['quantity'] line['inventory_value'] = inv_value return res
def _action_open_presence_view(self): # Compute the presence/absence for the employees on the same # company than the HR/manager. Then opens the kanban view # of the employees with an undefined presence/absence _logger.info("Employees presence checked by: %s" % self.env.user.name) company = self.env.user.company_id if not company.hr_presence_last_compute_date or \ company.hr_presence_last_compute_date.day != Datetime.now().day: self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id) ]).write({'hr_presence_state': 'to_define'}) employees = self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id), ('user_id', '!=', False), ('hr_presence_state', '=', 'to_define')]) # Remove employees on holidays leaves = self.env['hr.leave'].search([ ('state', '=', 'validate'), ('date_from', '<=', Datetime.to_string(Datetime.now())), ('date_to', '>=', Datetime.to_string(Datetime.now()))]) employees_on_holiday = leaves.mapped('employee_id') employees_on_holiday.write({'hr_presence_state': 'absent'}) employees = employees - employees_on_holiday # Check on system login if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_login'): online_employees = employees.filtered(lambda employee: employee.user_id.im_status in ['away', 'online']) online_employees.write({'hr_presence_state': 'present'}) employees = employees - online_employees # Check on IP if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_ip'): ip_list = company.hr_presence_control_ip_list ip_list = ip_list.split(',') if ip_list else [] ip_employees = self.env['hr.employee'] for employee in employees: employee_ips = self.env['res.users.log'].search([ ('create_uid', '=', employee.user_id.id), ('ip', '!=', False), ('create_date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)))] ).mapped('ip') if any([ip in ip_list for ip in employee_ips]): ip_employees |= employee ip_employees.write({'hr_presence_state': 'present'}) employees = employees - ip_employees # Check on sent emails if self.env['ir.config_parameter'].sudo().get_param('hr_presence.hr_presence_control_email'): email_employees = self.env['hr.employee'] threshold = company.hr_presence_control_email_amount for employee in employees: sent_emails = self.env['mail.message'].search_count([ ('author_id', '=', employee.user_id.partner_id.id), ('date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))), ('date', '<=', Datetime.to_string(Datetime.now()))]) if sent_emails >= threshold: email_employees |= employee email_employees.write({'hr_presence_state': 'present'}) employees = employees - email_employees company.hr_presence_last_compute_date = Datetime.now() return { "type": "ir.actions.act_window", "res_model": "hr.employee", "views": [[self.env.ref('hr_presence.hr_employee_view_kanban').id, "kanban"], [False, "tree"], [False, "form"]], 'view_mode': 'kanban,tree,form', "domain": [], "name": "Employee's Presence to Define", "context": {'search_default_group_hr_presence_state': 1}, }
def test_merge_method_followers(self): """ Test that the followers of the leads are added in the destination lead. They should be added if: - The related partner was active on the lead (posted a message in the last 30 days) - The related partner is not already following the destination lead Leads Followers Info --------------------------------------------------------------------------------- lead_w_contact contact_1 OK (destination lead) lead_w_email contact_1 KO (already following the destination lead) contact_2 OK (active on lead_w_email) contact_company KO (most recent message on lead_w_email is 35 days ago, message on lead_w_partner is not counted as he doesn't follow it) lead_w_partner contact_2 KO (already added with lead_w_email) lead_w_partner_company """ self.leads.message_follower_ids.unlink() self.leads.message_ids.unlink() self.lead_w_contact.message_subscribe([self.contact_1.id]) self.lead_w_email.message_subscribe( [self.contact_1.id, self.contact_2.id, self.contact_company.id]) self.lead_w_partner.message_subscribe([self.contact_2.id]) self.env['mail.message'].create([{ 'author_id': self.contact_1.id, 'model': 'crm.lead', 'res_id': self.lead_w_contact.id, 'date': Datetime.now() - timedelta(days=1), 'subtype_id': self.ref('mail.mt_comment'), 'reply_to': False, 'body': 'Test follower', }, { 'author_id': self.contact_1.id, 'model': 'crm.lead', 'res_id': self.lead_w_email.id, 'date': Datetime.now() - timedelta(days=20), 'subtype_id': self.ref('mail.mt_comment'), 'reply_to': False, 'body': 'Test follower', }, { 'author_id': self.contact_2.id, 'model': 'crm.lead', 'res_id': self.lead_w_email.id, 'date': Datetime.now() - timedelta(days=15), 'subtype_id': self.ref('mail.mt_comment'), 'reply_to': False, 'body': 'Test follower', }, { 'author_id': self.contact_2.id, 'model': 'crm.lead', 'res_id': self.lead_w_partner.id, 'date': Datetime.now() - timedelta(days=29), 'subtype_id': self.ref('mail.mt_comment'), 'reply_to': False, 'body': 'Test follower', }, { 'author_id': self.contact_company.id, 'model': 'crm.lead', 'res_id': self.lead_w_email.id, 'date': Datetime.now() - timedelta(days=35), 'subtype_id': self.ref('mail.mt_comment'), 'reply_to': False, 'body': 'Test follower', }, { 'author_id': self.contact_company.id, 'model': 'crm.lead', 'res_id': self.lead_w_partner.id, 'date': Datetime.now(), 'subtype_id': self.ref('mail.mt_comment'), 'reply_to': False, 'body': 'Test follower', }]) initial_followers = self.lead_w_contact.message_follower_ids leads = self.env['crm.lead'].browse( self.leads.ids)._sort_by_confidence_level(reverse=True) master_lead = leads._merge_opportunity(max_length=None) self.assertEqual(master_lead, self.lead_w_contact) # Check followers of the destination lead new_partner_followers = (master_lead.message_follower_ids - initial_followers).partner_id self.assertIn(self.contact_2, new_partner_followers, 'The partner must follow the destination lead') # "contact_company" posted a message 35 days ago on lead_2, so it's considered as inactive # "contact_company" posted a message now on lead_3, but he doesn't follow lead_3 # so this message is just ignored self.assertNotIn(self.contact_company, new_partner_followers, 'The partner was not active on the lead') self.assertIn( self.contact_1, master_lead.message_follower_ids.partner_id, 'Should not have removed follower of the destination lead')
def _test_leave(self): # -------------------------------------------------- # Holiday manager: creates leave types # -------------------------------------------------- self.leave_type_1 = self.create_leave_type( user=self.hr_holidays_manager, name='Leave Type (no allocation, validation HR, day)', allocation='no', request_unit='day', validation='hr', ) self.leave_type_2 = self.create_leave_type( user=self.hr_holidays_manager, name='Leave Type (allocation by HR, no validation, half day)', allocation='fixed', request_unit='half_day', validation='no_validation', ) self.leave_type_3 = self.create_leave_type( user=self.hr_holidays_manager, name='Leave Type (allocation request, validation both, hour)', allocation='fixed_allocation', request_unit='hour', validation='both', allocation_validation='both', ) # -------------------------------------------------- # Holiday user: Allocation # -------------------------------------------------- allocation_no_validation = self.create_allocation( user=self.hr_holidays_user, employee=self.user.employee_id, leave_type=self.leave_type_2, ) # Holiday user refuse allocation allocation_no_validation.action_refuse() self.assertEqual(allocation_no_validation.state, 'refuse') # Holiday manager reset to draft allocation_no_validation.with_user( self.hr_holidays_manager).action_draft() self.assertEqual(allocation_no_validation.state, 'draft') # Holiday user approve allocation allocation_no_validation.action_confirm() allocation_no_validation.action_approve() self.assertEqual(allocation_no_validation.state, 'validate') self.assertEqual(allocation_no_validation.first_approver_id, self.hr_holidays_user.employee_id) # -------------------------------------------------- # User: Allocation request # -------------------------------------------------- # User request an allocation allocation = self.create_allocation( user=self.user, employee=self.user.employee_id, leave_type=self.leave_type_3, ) self.assertEqual(allocation.state, 'confirm') # Employee's manager approves allocation.with_user(self.user_leave_team_leader).action_approve() self.assertEqual(allocation.state, 'validate1') self.assertEqual(allocation.first_approver_id, self.user_leave_team_leader.employee_id) # Holiday Manager validates allocation.with_user(self.hr_holidays_manager).action_validate() self.assertEqual(allocation.state, 'validate') self.assertEqual(allocation.second_approver_id, self.hr_holidays_manager.employee_id) # -------------------------------------------------- # User: Leave request # -------------------------------------------------- # User request a leave which does not require validation leave_form = Form(self.env['hr.leave'].with_user(self.user)) leave_form.holiday_status_id = allocation_no_validation.holiday_status_id leave_form.request_unit_half = True leave_form.request_date_from = Date.today() + relativedelta(days=1) leave_form.request_date_from_period = 'am' self.assertEqual(leave_form.number_of_days, 0.5, "Onchange should have computed 0.5 days") leave = leave_form.save() self.assertEqual(leave.state, 'validate', "Should be automatically validated") # User request a leave that doesn't require allocation leave = self.create_leave(user=self.user, leave_type=self.leave_type_1, start=Datetime.now() + relativedelta(days=2), end=Datetime.now() + relativedelta(days=3)) # User request a leave that require validation leave = self.create_leave(user=self.user, leave_type=allocation.holiday_status_id, start=Datetime.now() + relativedelta(days=6), end=Datetime.now() + relativedelta(days=8)) self.assertEqual(leave.state, 'confirm', "Should be in `confirm` state") # Team leader approves leave.with_user(self.user_leave_team_leader).action_approve() self.assertEqual(leave.state, 'validate1') self.assertEqual(leave.first_approver_id, self.user_leave_team_leader.employee_id) # Holiday manager applies second approval # the "hr_holidays_manager" user need this group to access timesheets of other users with additional_groups(self.hr_holidays_manager, 'hr_timesheet.group_hr_timesheet_approver'): leave.with_user(self.hr_holidays_manager).action_validate() self.assertEqual(leave.state, 'validate') self.assertEqual(leave.second_approver_id, self.hr_holidays_manager.employee_id)
def _get_report_data(self, data): year = data['year'] employees = self.env['hr.employee'].browse(data['employee_ids']) payslips = self.env['hr.payslip'].search([ ('employee_id', 'in', employees.ids), ('state', '=', 'done'), ('date_from', '>=', Datetime.now().replace(month=1, day=1, year=year)), ('date_from', '<=', Datetime.now().replace(month=12, day=31, year=year)), '|', ('struct_id.country_id', '=', False), ('struct_id.country_id', '=', self.env.ref('base.be').id), ]) lines = payslips.mapped('line_ids') payslip_rules = [(rule.code, rule.sequence) for rule in lines.mapped('salary_rule_id')] payslip_rules = sorted(payslip_rules, key=lambda x: x[1]) worked_days = payslips.mapped('worked_days_line_ids') result = { employee: { 'rules': OrderedDict((rule[0], { 'year': { 'name': False, 'total': 0 }, 'month': {m: { 'name': False, 'total': 0 } for m in range(12)}, 'quarter': {q: { 'name': False, 'total': 0 } for q in range(4)} }) for rule in payslip_rules), 'worked_days': { code: { 'year': { 'name': False, 'number_of_days': 0, 'number_of_hours': 0 }, 'month': { m: { 'name': False, 'number_of_days': 0, 'number_of_hours': 0 } for m in range(12) }, 'quarter': { q: { 'name': False, 'number_of_days': 0, 'number_of_hours': 0 } for q in range(4) } } for code in worked_days.mapped('code') } } for employee in employees } for line in lines: rule = result[line.employee_id]['rules'][line.salary_rule_id.code] month = line.slip_id.date_from.month - 1 rule['month'][month]['name'] = line.name rule['month'][month]['total'] += line.total rule['quarter'][(month) // 3]['name'] = line.name rule['quarter'][(month) // 3]['total'] += line.total rule['year']['name'] = line.name rule['year']['total'] += line.total rule['month'][month]['total'] = round( rule['month'][month]['total'], 2) rule['quarter'][(month) // 3]['total'] = round( rule['quarter'][(month) // 3]['total'], 2) rule['year']['total'] = round(rule['year']['total'], 2) for worked_day in worked_days: work = result[worked_day.payslip_id.employee_id]['worked_days'][ worked_day.code] month = worked_day.payslip_id.date_from.month - 1 work['month'][month]['name'] = worked_day.name work['month'][month]['number_of_days'] += worked_day.number_of_days work['month'][month][ 'number_of_hours'] += worked_day.number_of_hours work['quarter'][(month) // 3]['name'] = worked_day.name work['quarter'][(month) // 3]['number_of_days'] += worked_day.number_of_days work['quarter'][(month) // 3]['number_of_hours'] += worked_day.number_of_hours work['year']['name'] = worked_day.name work['year']['number_of_days'] += worked_day.number_of_days work['year']['number_of_hours'] += worked_day.number_of_hours return {'year': year, 'employee_data': result}
def read_group(self, domain, fields, groupby, offset=0, limit=None, orderby=False, lazy=True): # Step 1: retrieve the standard read_group output. In case of inventory valuation, this # will be mostly used as a 'skeleton' since the inventory value needs to be computed based # on the individual lines. res = super(StockHistory, self).read_group(domain, fields, groupby, offset=offset, limit=limit, orderby=orderby, lazy=lazy) if "inventory_value" in fields: groupby_list = groupby[:1] if lazy else groupby date = self._context.get("history_date", fieldsDatetime.now()) # Step 2: retrieve the stock history lines. The result contains the 'expanded' # version of the read_group. We build the query manually for performance reason # (and avoid a costly 'WHERE id IN ...'). fields_2 = set([ "id", "product_id", "price_unit_on_quant", "company_id", "quantity" ] + groupby_list) query = self._where_calc(domain) self._apply_ir_rules(query, "read") tables, where_clause, where_clause_params = query.get_sql() select = "SELECT %s FROM %s WHERE %s " query = select % (",".join(fields_2), tables, where_clause) self._cr.execute(query, where_clause_params) # Step 3: match the lines retrieved at step 2 with the aggregated results of step 1. # In other words, we link each item of the read_group result with the corresponding # lines. stock_history_data = {} stock_histories_by_group = {} for line in self._cr.dictfetchall(): stock_history_data[line["id"]] = line key = tuple(line.get(g) or False for g in groupby_list) stock_histories_by_group.setdefault(key, []) stock_histories_by_group[key] += [line["id"]] histories_dict = {} # sudo() added here (QRTL) not_real_cost_method_products = ( self.env["product.product"].sudo().browse( record["product_id"] for record in stock_history_data.values()).filtered( lambda product: product.cost_method != "real")) if not_real_cost_method_products: self._cr.execute( """SELECT DISTINCT ON (product_id, company_id) product_id, company_id, cost FROM product_price_history WHERE product_id in %s AND datetime <= %s ORDER BY product_id, company_id, datetime DESC, id DESC""", (tuple(not_real_cost_method_products.ids), date), ) for history in self._cr.dictfetchall(): histories_dict[(history["product_id"], history["company_id"])] = history["cost"] for line in res: inv_value = 0.0 # Build the same keys than above, but need to take into account Many2one are tuples key = tuple(line[g] if g in line else False for g in groupby_list) key = tuple(k[0] if isinstance(k, tuple) else k for k in key) for stock_history in self.env["stock.history"].browse( stock_histories_by_group[key]): history_data = stock_history_data[stock_history.id] product_id = history_data["product_id"] if self.env["product.product"].browse( product_id).cost_method == "real": price = history_data["price_unit_on_quant"] else: price = histories_dict.get( (product_id, history_data["company_id"]), 0.0) inv_value += price * history_data["quantity"] line["inventory_value"] = inv_value return res
def sync_participants(self): """ Creates new participants, taking into account already-existing ones as well as campaign filter and unique field. """ def _uniquify_list(seq): seen = set() return [x for x in seq if x not in seen and not seen.add(x)] participants = self.env['marketing.participant'] # auto-commit except in testing mode auto_commit = not getattr(threading.currentThread(), 'testing', False) for campaign in self.filtered(lambda c: c.marketing_activity_ids): now = Datetime.now() if not campaign.last_sync_date: campaign.last_sync_date = now RecordModel = self.env[campaign.model_name] # Fetch existing participants participants_data = participants.search_read( [('campaign_id', '=', campaign.id)], ['res_id']) existing_rec_ids = _uniquify_list([ live_participant['res_id'] for live_participant in participants_data ]) record_domain = literal_eval(campaign.domain or "[]") db_rec_ids = _uniquify_list(RecordModel.search(record_domain).ids) to_create = [ rid for rid in db_rec_ids if rid not in existing_rec_ids ] # keep ordered IDs to_remove = set(existing_rec_ids) - set(db_rec_ids) if campaign.unique_field_id and campaign.unique_field_id.name != 'id': without_duplicates = [] existing_records = RecordModel.with_context( prefetch_fields=False).browse(existing_rec_ids).exists() # Split the read in batch of 1000 to avoid the prefetch # crawling the cache for the next 1000 records to fetch unique_field_vals = { rec[campaign.unique_field_id.name] for index in range(0, len(existing_records), 1000) for rec in existing_records[index:index + 1000] } for rec in RecordModel.with_context( prefetch_fields=False).browse(to_create): field_val = rec[campaign.unique_field_id.name] # we exclude the empty recordset with the first condition if (not campaign.unique_field_id.relation or field_val) and field_val not in unique_field_vals: without_duplicates.append(rec.id) unique_field_vals.add(field_val) to_create = without_duplicates BATCH_SIZE = 100 for index, rec_id in enumerate(to_create, start=1): participants |= participants.create({ 'campaign_id': campaign.id, 'res_id': rec_id, }) if not index % BATCH_SIZE and auto_commit: self.env.cr.commit() if to_remove: participants_to_unlink = participants.search([ ('res_id', 'in', list(to_remove)), ('campaign_id', '=', campaign.id), ('state', '!=', 'unlinked'), ]) for index in range(0, len(participants_to_unlink), 1000): participants_to_unlink[index:index + 1000].action_set_unlink() # Commit only every 100 operation to avoid committing to often # this mean every 10k record. It should be ok, it takes 1sec second to process 10k if not index % (BATCH_SIZE * 100): self.env.cr.commit() return participants
def _check_presence(self): company = self.env.company if not company.hr_presence_last_compute_date or \ company.hr_presence_last_compute_date.day != Datetime.now().day: self.env['hr.employee'].search([('company_id', '=', company.id) ]).write({ 'email_sent': False, 'ip_connected': False, 'manually_set_present': False }) employees = self.env['hr.employee'].search([('company_id', '=', company.id)]) all_employees = employees # Check on IP if literal_eval(self.env['ir.config_parameter'].sudo().get_param( 'hr.hr_presence_control_ip', 'False')): ip_list = company.hr_presence_control_ip_list ip_list = ip_list.split(',') if ip_list else [] ip_employees = self.env['hr.employee'] for employee in employees: employee_ips = self.env['res.users.log'].search([ ('create_uid', '=', employee.user_id.id), ('ip', '!=', False), ('create_date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))) ]).mapped('ip') if any(ip in ip_list for ip in employee_ips): ip_employees |= employee ip_employees.write({'ip_connected': True}) employees = employees - ip_employees # Check on sent emails if literal_eval(self.env['ir.config_parameter'].sudo().get_param( 'hr.hr_presence_control_email', 'False')): email_employees = self.env['hr.employee'] threshold = company.hr_presence_control_email_amount for employee in employees: sent_emails = self.env['mail.message'].search_count([ ('author_id', '=', employee.user_id.partner_id.id), ('date', '>=', Datetime.to_string(Datetime.now().replace( hour=0, minute=0, second=0, microsecond=0))), ('date', '<=', Datetime.to_string(Datetime.now())) ]) if sent_emails >= threshold: email_employees |= employee email_employees.write({'email_sent': True}) employees = employees - email_employees company.sudo().hr_presence_last_compute_date = Datetime.now() for employee in all_employees: employee.hr_presence_state_display = employee.hr_presence_state
def test_course_certification_employee(self): user_demo = self.user_demo user_demo.flush() # Avoid Billing/Shipping address page user_demo.write({ 'groups_id': [(5, 0), (4, self.env.ref('base.group_user').id)], 'street': '215 Vine St', 'city': 'Scranton', 'zip': '18503', 'country_id': self.env.ref('base.us').id, 'state_id': self.env.ref('base.state_us_39').id, 'phone': '+1 555-555-5555', 'email': '*****@*****.**', }) # Specify Accounting Data cash_journal = self.env['account.journal'].create({ 'name': 'Cash - Test', 'type': 'cash', 'code': 'CASH - Test' }) self.env['payment.acquirer'].search([('journal_id', '=', False) ]).journal_id = cash_journal a_recv = self.env['account.account'].create({ 'code': 'X1012', 'name': 'Debtors - (test)', 'reconcile': True, 'user_type_id': self.env.ref('account.data_account_type_receivable').id, }) a_pay = self.env['account.account'].create({ 'code': 'X1111', 'name': 'Creditors - (test)', 'user_type_id': self.env.ref('account.data_account_type_payable').id, 'reconcile': True, }) self.env['ir.property'].create([{ 'name': 'property_account_receivable_id', 'fields_id': self.env['ir.model.fields'].search( [('model', '=', 'res.partner'), ('name', '=', 'property_account_receivable_id')], limit=1).id, 'value': 'account.account,%s' % (a_recv.id), 'company_id': self.env.company.id, }, { 'name': 'property_account_payable_id', 'fields_id': self.env['ir.model.fields'].search( [('model', '=', 'res.partner'), ('name', '=', 'property_account_payable_id')], limit=1).id, 'value': 'account.account,%s' % (a_pay.id), 'company_id': self.env.company.id, }]) product_course_channel_6 = self.env['product.product'].create({ 'name': 'DIY Furniture Course', 'list_price': 100.0, 'type': 'service', 'is_published': True, }) furniture_survey = self.env['survey.survey'].create({ 'title': 'Furniture Creation Certification', 'access_token': '5632a4d7-48cf-aaaa-8c52-2174d58cf50b', 'state': 'open', 'access_mode': 'public', 'users_can_go_back': True, 'users_login_required': True, 'scoring_type': 'scoring_with_answers', 'certificate': True, 'certification_mail_template_id': self.env.ref('survey.mail_template_certification').id, 'is_attempts_limited': True, 'attempts_limit': 3, 'description': "<p>Test your furniture knowledge!</p>", 'thank_you_message': "<p></p>", 'question_and_page_ids': [(0, 0, { 'title': 'Furniture', 'sequence': 1, 'is_page': True, 'description': "<p>Test your furniture knowledge!</p>", }), (0, 0, { 'title': 'What type of wood is the best for furniture?', 'sequence': 2, 'question_type': 'simple_choice', 'display_mode': 'dropdown', 'constr_mandatory': True, 'labels_ids': [(0, 0, { 'value': 'Fir', 'sequence': 1, }), (0, 0, { 'value': 'Oak', 'sequence': 2, 'is_correct': True, 'answer_score': 2.0, }), (0, 0, { 'value': 'Ash', 'sequence': 3, }), (0, 0, { 'value': 'Beech', 'sequence': 4, })] }), (0, 0, { 'title': 'Select all the furniture shown in the video', 'sequence': 3, 'question_type': 'multiple_choice', 'column_nb': '4', 'labels_ids': [(0, 0, { 'value': 'Chair', 'sequence': 1, 'is_correct': True, 'answer_score': 1.0, }), (0, 0, { 'value': 'Table', 'sequence': 2, 'answer_score': -1.0, }), (0, 0, { 'value': 'Desk', 'sequence': 3, 'is_correct': True, 'answer_score': 1.0, }), (0, 0, { 'value': 'Shelve', 'sequence': 4, 'is_correct': True, 'answer_score': 1.0, }), (0, 0, { 'value': 'Bed', 'sequence': 5, 'answer_score': -1.0, })] }), (0, 0, { 'title': 'What do you think about the content of the course? (not rated)', 'sequence': 4, 'question_type': 'free_text', })] }) slide_channel_demo_6_furn3 = self.env['slide.channel'].create({ 'name': 'DIY Furniture - TEST', 'user_id': self.env.ref('base.user_admin').id, 'enroll': 'payment', 'product_id': product_course_channel_6.id, 'channel_type': 'training', 'allow_comment': True, 'promote_strategy': 'most_voted', 'is_published': True, 'description': 'So much amazing certification.', 'create_date': Datetime.now() - relativedelta(days=2), 'slide_ids': [(0, 0, { 'name': 'DIY Furniture Certification', 'sequence': 1, 'slide_type': 'certification', 'category_id': False, 'is_published': True, 'is_preview': False, 'description': "It's time to test your knowledge!", 'survey_id': furniture_survey.id, })] }) self.browser_js( '/slides', 'odoo.__DEBUG__.services["web_tour.tour"].run("certification_member")', 'odoo.__DEBUG__.services["web_tour.tour"].tours.certification_member.ready', login=user_demo.login)
def action_update_participants(self): """ Synchronizes all participants based campaign activities demanding synchronization It is done in 2 part: * update traces related to updated activities. This means basically recomputing the schedule date * creating new traces for activities recently added in the workflow : * 'begin' activities simple create new traces for all running participants; * other activities: create child for traces linked to the parent of the newly created activity * we consider scheduling to be done after parent processing, independently of other time considerations * for 'not' triggers take into account brother traces that could be already processed """ for campaign in self: # Action 1: On activity modification modified_activities = campaign.marketing_activity_ids.filtered( lambda activity: activity.require_sync) traces_to_reschedule = self.env['marketing.trace'].search([ ('state', '=', 'scheduled'), ('activity_id', 'in', modified_activities.ids) ]) for trace in traces_to_reschedule: trace_offset = relativedelta( **{ trace.activity_id.interval_type: trace.activity_id.interval_number }) trigger_type = trace.activity_id.trigger_type if trigger_type == 'begin': trace.schedule_date = Datetime.from_string( trace.participant_id.create_date) + trace_offset elif trigger_type in [ 'act', 'mail_not_open', 'mail_not_click', 'mail_not_reply' ] and trace.parent_id: trace.schedule_date = Datetime.from_string( trace.parent_id.schedule_date) + trace_offset elif trace.parent_id: process_dt = trace.parent_id.mail_statistics_ids.state_update trace.schedule_date = Datetime.from_string( process_dt) + trace_offset # Action 2: On activity creation created_activities = campaign.marketing_activity_ids.filtered( lambda a: a.create_date >= campaign.last_sync_date) for activity in created_activities: activity_offset = relativedelta( **{activity.interval_type: activity.interval_number}) # Case 1: Trigger = begin # Create new root traces for all running participants -> consider campaign begin date is now to avoid spamming participants if activity.trigger_type == 'begin': participants = self.env['marketing.participant'].search([ ('state', '=', 'running'), ('campaign_id', '=', campaign.id) ]) for participant in participants: schedule_date = Datetime.from_string( Datetime.now()) + activity_offset self.env['marketing.trace'].create({ 'activity_id': activity.id, 'participant_id': participant.id, 'schedule_date': schedule_date, }) else: valid_parent_traces = self.env['marketing.trace'].search([ ('state', '=', 'processed'), ('activity_id', '=', activity.parent_id.id) ]) # avoid creating new traces that would have processed brother traces already processed # example: do not create a mail_not_click trace if mail_click is already processed if activity.trigger_type in [ 'mail_not_open', 'mail_not_click', 'mail_not_reply' ]: opposite_trigger = activity.trigger_type.replace( '_not_', '_') brother_traces = self.env['marketing.trace'].search([ ('parent_id', 'in', valid_parent_traces.ids), ('trigger_type', '=', opposite_trigger), ('state', '=', 'processed'), ]) valid_parent_traces = valid_parent_traces - brother_traces.mapped( 'parent_id') valid_parent_traces.mapped('participant_id').filtered( lambda participant: participant.state == 'completed' ).action_set_running() for parent_trace in valid_parent_traces: self.env['marketing.trace'].create({ 'activity_id': activity.id, 'participant_id': parent_trace.participant_id.id, 'parent_id': parent_trace.id, 'schedule_date': Datetime.from_string(parent_trace.schedule_date) + activity_offset, }) self.action_set_synchronized()
def _check_presence(self): company = self.env.company if not company.hr_presence_last_compute_date or \ company.hr_presence_last_compute_date.day != Datetime.now().day: self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id) ]).write({'hr_presence_state': 'to_define'}) employees = self.env['hr.employee'].search([ ('department_id.company_id', '=', company.id), ('user_id', '!=', False), ('hr_presence_state', '=', 'to_define') ]) # Remove employees on holidays leaves = self.env['hr.leave'].search([ ('state', '=', 'validate'), ('date_from', '<=', Datetime.to_string(Datetime.now())), ('date_to', '>=', Datetime.to_string(Datetime.now())) ]) employees_on_holiday = leaves.mapped('employee_id') employees_on_holiday.write({'hr_presence_state': 'absent'}) employees = employees - employees_on_holiday # Check on system login if self.env['ir.config_parameter'].sudo().get_param( 'hr_presence.hr_presence_control_login'): online_employees = employees.filtered( lambda employee: employee.user_id.im_status in ['away', 'online']) online_employees.write({'hr_presence_state': 'present'}) employees = employees - online_employees # Check on IP if self.env['ir.config_parameter'].sudo().get_param( 'hr_presence.hr_presence_control_ip'): ip_list = company.hr_presence_control_ip_list ip_list = ip_list.split(',') if ip_list else [] ip_employees = self.env['hr.employee'] for employee in employees: employee_ips = self.env['res.users.log'].search([ ('create_uid', '=', employee.user_id.id), ('ip', '!=', False), ('create_date', '>=', Datetime.to_string(Datetime.now().replace(hour=0, minute=0, second=0, microsecond=0))) ]).mapped('ip') if any([ip in ip_list for ip in employee_ips]): ip_employees |= employee ip_employees.write({'hr_presence_state': 'present'}) employees = employees - ip_employees # Check on sent emails if self.env['ir.config_parameter'].sudo().get_param( 'hr_presence.hr_presence_control_email'): email_employees = self.env['hr.employee'] threshold = company.hr_presence_control_email_amount for employee in employees: sent_emails = self.env['mail.message'].search_count([ ('author_id', '=', employee.user_id.partner_id.id), ('date', '>=', Datetime.to_string(Datetime.now().replace( hour=0, minute=0, second=0, microsecond=0))), ('date', '<=', Datetime.to_string(Datetime.now())) ]) if sent_emails >= threshold: email_employees |= employee email_employees.write({'hr_presence_state': 'present'}) employees = employees - email_employees company.hr_presence_last_compute_date = Datetime.now()
def available_shift_irregular_worker(self, irregular_enable_sign_up=False, nexturl=""): """ Return template variables for 'beesdoo_website_shift.available_shift_irregular_worker_grid' """ # Get current user cur_user = request.env["res.users"].browse(request.uid) # Get all the shifts in the future with no worker shifts = (request.env["beesdoo.shift.shift"].sudo().search( [ ("start_time", ">", Datetime.now()), ("worker_id", "=", False), ("state", "=", "open"), ], order="task_template_id, start_time, task_type_id", )) # Get shifts where user is subscribed subscribed_shifts = (request.env["beesdoo.shift.shift"].sudo().search( [ ("start_time", ">", Datetime.now()), ("worker_id", "=", cur_user.partner_id.id), ], order="task_template_id, start_time, task_type_id", )) # Get config highlight_rule_pc = request.website.highlight_rule_pc hide_rule = request.website.hide_rule / 100.0 groupby_iter = groupby( shifts, lambda s: (s.task_template_id, s.start_time, s.task_type_id), ) displayed_shifts = [] for keys, grouped_shifts in groupby_iter: task_template, start_time, task_type = keys shift_list = list(grouped_shifts) # Compute available space free_space = len(shift_list) # Is the current user subscribed to this task_template is_subscribed = any((sub_shift.task_template_id == task_template and sub_shift.start_time == start_time and sub_shift.task_type_id == task_type) for sub_shift in subscribed_shifts) # Check the necessary number of worker based on the # highlight_rule_pc has_enough_workers = ( free_space <= (task_template.worker_nb * highlight_rule_pc) / 100) if free_space >= task_template.worker_nb * hide_rule: displayed_shifts.append( DisplayedShift( shift_list[0], free_space, is_subscribed, has_enough_workers, )) shift_weeks = build_shift_grid(displayed_shifts) return { "shift_weeks": shift_weeks, "nexturl": nexturl, "irregular_enable_sign_up": irregular_enable_sign_up, }
def setUpClass(cls): super(TestMailActivityTeam, cls).setUpClass() cls.env = cls.env(context=dict( cls.env.context, tracking_disable=True, no_reset_password=True)) cls.env["mail.activity.team"].search([]).unlink() cls.employee = cls.env['res.users'].create({ 'company_id': cls.env.ref("base.main_company").id, 'name': "Employee", 'login': "******", 'email': "*****@*****.**", 'groups_id': [(6, 0, [ cls.env.ref('base.group_user').id, cls.env.ref('base.group_partner_manager').id ])] }) cls.employee2 = cls.env['res.users'].create({ 'company_id': cls.env.ref("base.main_company").id, 'name': "Employee 2", 'login': "******", 'email': "*****@*****.**", 'groups_id': [(6, 0, [cls.env.ref('base.group_user').id])] }) cls.partner_ir_model = cls.env['ir.model']._get('res.partner') activity_type_model = cls.env['mail.activity.type'] cls.activity1 = activity_type_model.create({ 'name': 'Initial Contact', 'summary': 'ACT 1 : Presentation, barbecue, ... ', 'res_model_id': cls.partner_ir_model.id, }) cls.activity2 = activity_type_model.create({ 'name': 'Call for Demo', 'summary': 'ACT 2 : I want to show you my ERP !', 'res_model_id': cls.partner_ir_model.id, }) cls.partner_client = cls.env.ref("base.res_partner_1") cls.act1 = cls.env['mail.activity'].sudo(cls.employee).create({ 'activity_type_id': cls.activity1.id, 'note': 'Partner activity 1.', 'res_id': cls.partner_client.id, 'res_model_id': cls.partner_ir_model.id, 'user_id': cls.employee.id, }) cls.team1 = cls.env['mail.activity.team'].sudo().create({ 'name': 'Team 1', 'res_model_ids': [(6, 0, [cls.partner_ir_model.id])], 'member_ids': [(6, 0, [cls.employee.id])], }) cls.team2 = cls.env['mail.activity.team'].sudo().create({ 'name': 'Team 2', 'res_model_ids': [(6, 0, [cls.partner_ir_model.id])], 'member_ids': [(6, 0, [cls.employee.id, cls.employee2.id])], }) cls.act2 = cls.env['mail.activity'].sudo(cls.employee).create({ 'activity_type_id': cls.activity2.id, 'note': 'Partner activity 2.', 'res_id': cls.partner_client.id, 'res_model_id': cls.partner_ir_model.id, 'user_id': cls.employee.id, }) cls.act3 = cls.env['mail.activity'].sudo(cls.employee).create({ 'activity_type_id': cls.env.ref('mail.mail_activity_data_meeting').id, 'note': 'Meeting activity 3.', 'res_id': cls.partner_client.id, 'res_model_id': cls.partner_ir_model.id, 'user_id': cls.employee.id, 'team_id': cls.team1.id, 'summary': 'Metting activity' }) cls.start = Datetime.now() cls.stop = Datetime.to_string( Datetime.from_string(cls.start) + timedelta(hours=1))
def _compute_atn(self): now = Datetime.now() for model in self: model.default_atn = self.env['fleet.vehicle']._get_car_atn( now, model.default_car_value, model.default_fuel_type, model.default_co2)
def setUpClass(cls): super(TestAnalyticSearch, cls).setUpClass() cls.purchase_order_model = cls.env['purchase.order'] partner_model = cls.env['res.partner'] prod_model = cls.env['product.product'] analytic_account_model = cls.env['account.analytic.account'] cls.product_uom_model = cls.env['product.uom'] pa_dict = { 'name': 'Partner 1', 'supplier': True, } cls.partner = partner_model.create(pa_dict) uom_id = cls.product_uom_model.search([('name', '=', 'Unit(s)')])[0].id pr_dict = { 'name': 'Product Test', 'uom_id': uom_id, } cls.product = prod_model.create(pr_dict) ac_dict = { 'name': 'account 1', } cls.analytic_account_1 = \ analytic_account_model.create(ac_dict) ac_dict = { 'name': 'dummyname', } cls.analytic_account_2 = \ analytic_account_model.create(ac_dict) # PURCHASE ORDER NUM 1 => account 1 po_dict = { 'partner_id': cls.partner.id, 'order_line': [(0, 0, { 'date_planned': Datetime.now(), 'name': 'PO01', 'product_id': cls.product.id, 'product_uom': uom_id, 'price_unit': 1, 'product_qty': 5.0, 'account_analytic_id': cls.analytic_account_1.id, }), (0, 0, { 'date_planned': Datetime.now(), 'name': 'PO01', 'product_id': cls.product.id, 'product_uom': uom_id, 'price_unit': 1, 'product_qty': 5.0, 'account_analytic_id': cls.analytic_account_1.id, })], } cls.purchase_order_1 = cls.purchase_order_model.create(po_dict) # PURCHASE ORDER NUM 2 => account 1 and 2 pa_dict2 = { 'name': 'Partner 2', 'supplier': True, } cls.partner2 = partner_model.create(pa_dict2) po_dict2 = { 'partner_id': cls.partner2.id, 'order_line': [ (0, 0, { 'date_planned': Datetime.now(), 'name': 'PO01', 'product_id': cls.product.id, 'product_uom': uom_id, 'price_unit': 1, 'product_qty': 5.0, 'account_analytic_id': cls.analytic_account_1.id, }), (0, 0, { 'date_planned': Datetime.now(), 'name': 'PO01', 'product_id': cls.product.id, 'product_uom': uom_id, 'price_unit': 1, 'product_qty': 5.0, 'account_analytic_id': cls.analytic_account_2.id, }), ] } cls.purchase_order_2 = cls.purchase_order_model.create(po_dict2) # PURCHASE ORDER NUM 3 => account 2 po_dict3 = { 'partner_id': cls.partner2.id, 'order_line': [ (0, 0, { 'date_planned': Datetime.now(), 'name': 'PO01', 'product_id': cls.product.id, 'product_uom': uom_id, 'price_unit': 1, 'product_qty': 5.0, 'account_analytic_id': cls.analytic_account_2.id, }), (0, 0, { 'date_planned': Datetime.now(), 'name': 'PO01', 'product_id': cls.product.id, 'product_uom': uom_id, 'price_unit': 1, 'product_qty': 5.0, 'account_analytic_id': cls.analytic_account_2.id, }), ] } cls.purchase_order_3 = cls.purchase_order_model.create(po_dict3)
def _compute_atn(self): now = Datetime.now() for model in self: model.default_atn = self.env['fleet.vehicle']._get_car_atn(now, model.default_car_value, model.default_fuel_type, model.default_co2)
def setUp(self): super(TestPurchaseOpenQty, self).setUp() self.purchase_order_model = self.env["purchase.order"] purchase_order_line_model = self.env["purchase.order.line"] partner_model = self.env["res.partner"] prod_model = self.env["product.product"] analytic_account_model = self.env["account.analytic.account"] # partners pa_dict = {"name": "Partner 1"} self.partner = partner_model.sudo().create(pa_dict) pa_dict2 = {"name": "Partner 2"} self.partner2 = partner_model.sudo().create(pa_dict2) # account ac_dict = {"name": "analytic account 1"} self.analytic_account_1 = analytic_account_model.sudo().create(ac_dict) # Purchase Order Num 1 po_dict = {"partner_id": self.partner.id} self.purchase_order_1 = self.purchase_order_model.create(po_dict) uom_id = prod_model.uom_id.search([("name", "=", "Units")], limit=1).id pr_dict = { "name": "Product Test", "uom_id": uom_id, "purchase_method": "purchase", } self.product = prod_model.sudo().create(pr_dict) pl_dict1 = { "date_planned": Datetime.now(), "name": "PO01", "order_id": self.purchase_order_1.id, "product_id": self.product.id, "product_uom": uom_id, "price_unit": 1.0, "product_qty": 5.0, "account_analytic_id": self.analytic_account_1.id, } self.purchase_order_line_1 = purchase_order_line_model.sudo().create( pl_dict1) self.purchase_order_1.button_confirm() # Purchase Order Num 2 po_dict2 = {"partner_id": self.partner2.id} self.purchase_order_2 = self.purchase_order_model.create(po_dict2) pr_dict2 = { "name": "Product Test 2", "uom_id": uom_id, "purchase_method": "receive", } self.product2 = prod_model.sudo().create(pr_dict2) pl_dict2 = { "date_planned": Datetime.now(), "name": "PO02", "order_id": self.purchase_order_2.id, "product_id": self.product2.id, "product_uom": uom_id, "price_unit": 1.0, "product_qty": 5.0, "account_analytic_id": self.analytic_account_1.id, } self.purchase_order_line_2 = purchase_order_line_model.sudo().create( pl_dict2) self.purchase_order_2.button_confirm()
def test_basic(self): """ Basic order test: no routing (thus no workorders), no lot """ self.product_1.type = 'product' self.product_2.type = 'product' inventory = self.env['stock.inventory'].create({ 'name': 'Initial inventory', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': self.product_1.id, 'product_uom_id': self.product_1.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id }), (0, 0, { 'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id })] }) inventory.action_validate() test_date_planned = Dt.now() - timedelta(days=1) test_quantity = 2.0 self.bom_1.routing_id = False man_order_form = Form(self.env['mrp.production'].sudo(self.user_mrp_user)) man_order_form.product_id = self.product_4 man_order_form.bom_id = self.bom_1 man_order_form.product_uom_id = self.product_4.uom_id man_order_form.product_qty = test_quantity man_order_form.date_planned_start = test_date_planned man_order_form.location_src_id = self.location_1 man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id man_order = man_order_form.save() self.assertEqual(man_order.state, 'draft', "Production order should be in draft state.") man_order.action_confirm() self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.") # check production move production_move = man_order.move_finished_ids self.assertEqual(production_move.date, test_date_planned) self.assertEqual(production_move.product_id, self.product_4) self.assertEqual(production_move.product_uom, man_order.product_uom_id) self.assertEqual(production_move.product_qty, man_order.product_qty) self.assertEqual(production_move.location_id, self.product_4.property_stock_production) self.assertEqual(production_move.location_dest_id, man_order.location_dest_id) # check consumption moves for move in man_order.move_raw_ids: self.assertEqual(move.date, test_date_planned) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4) # waste some material, create a scrap # scrap = self.env['stock.scrap'].with_context( # active_model='mrp.production', active_id=man_order.id # ).create({}) # scrap = self.env['stock.scrap'].create({ # 'production_id': man_order.id, # 'product_id': first_move.product_id.id, # 'product_uom_id': first_move.product_uom.id, # 'scrap_qty': 5.0, # }) # check created scrap # procurements = self.env['procurement.order'].search([('move_dest_id', 'in', man_order.move_raw_ids.ids)]) # print procurements # procurements = self.env['procurement.order'].search([('production_id', '=', man_order.id)]) # print procurements # for proc in self.env['procurement.order'].browse(procurements): # date_planned = self.mrp_production_test1.date_planned # if proc.product_id.type not in ('product', 'consu'): # continue # if proc.product_id.id == order_line.product_id.id: # self.assertEqual(proc.date_planned, date_planned, "Planned date does not correspond") # # procurement state should be `confirmed` at this stage, except if procurement_jit is installed, in which # # case it could already be in `running` or `exception` state (not enough stock) # expected_states = ('confirmed', 'running', 'exception') # self.assertEqual(proc.state in expected_states, 'Procurement state is `%s` for %s, expected one of %s' % (proc.state, proc.product_id.name, expected_states)) # Change production quantity qty_wizard = self.env['change.production.qty'].create({ 'mo_id': man_order.id, 'product_qty': 3.0, }) # qty_wizard.change_prod_qty() # # I check qty after changed in production order. # #self.assertEqual(self.mrp_production_test1.product_qty, 3, "Qty is not changed in order.") # move = self.mrp_production_test1.move_finished_ids[0] # self.assertEqual(move.product_qty, self.mrp_production_test1.product_qty, "Qty is not changed in move line.") # # I run scheduler. # self.env['procurement.order'].run_scheduler() # # The production order is Waiting Goods, will force production which should set consume lines as available # self.mrp_production_test1.button_plan() # # I check that production order in ready state after forcing production. # #self.assertEqual(self.mrp_production_test1.availability, 'assigned', 'Production order availability should be set as available') # produce product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': man_order.id, 'active_ids': [man_order.id], })) produce_form.qty_producing = 1.0 produce_wizard = produce_form.save() produce_wizard.do_produce() # man_order.button_mark_done() man_order.button_mark_done() self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
def _compute_presence_state(self): super()._compute_presence_state() employees = self.filtered(lambda employee: employee.hr_presence_state != 'present' and not employee.is_absent) company = self.env.company for employee in employees: if not employee.is_absent and company.hr_presence_last_compute_date and company.hr_presence_last_compute_date.day == Datetime.now().day and \ (employee.email_sent or employee.ip_connected or employee.manually_set_present): employee.hr_presence_state = 'present'
def test_basic(self): """ Checks a basic manufacturing order: no routing (thus no workorders), no lot and consume strictly what's needed. """ self.product_1.type = 'product' self.product_2.type = 'product' inventory = self.env['stock.inventory'].create({ 'name': 'Initial inventory', 'filter': 'partial', 'line_ids': [(0, 0, { 'product_id': self.product_1.id, 'product_uom_id': self.product_1.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id }), (0, 0, { 'product_id': self.product_2.id, 'product_uom_id': self.product_2.uom_id.id, 'product_qty': 500, 'location_id': self.warehouse_1.lot_stock_id.id })] }) inventory.action_validate() test_date_planned = Dt.now() - timedelta(days=1) test_quantity = 2.0 self.bom_1.routing_id = False man_order_form = Form(self.env['mrp.production'].sudo(self.user_mrp_user)) man_order_form.product_id = self.product_4 man_order_form.bom_id = self.bom_1 man_order_form.product_uom_id = self.product_4.uom_id man_order_form.product_qty = test_quantity man_order_form.date_planned_start = test_date_planned man_order_form.location_src_id = self.location_1 man_order_form.location_dest_id = self.warehouse_1.wh_output_stock_loc_id man_order = man_order_form.save() self.assertEqual(man_order.state, 'draft', "Production order should be in draft state.") man_order.action_confirm() self.assertEqual(man_order.state, 'confirmed', "Production order should be in confirmed state.") # check production move production_move = man_order.move_finished_ids self.assertEqual(production_move.date, test_date_planned) self.assertEqual(production_move.product_id, self.product_4) self.assertEqual(production_move.product_uom, man_order.product_uom_id) self.assertEqual(production_move.product_qty, man_order.product_qty) self.assertEqual(production_move.location_id, self.product_4.property_stock_production) self.assertEqual(production_move.location_dest_id, man_order.location_dest_id) # check consumption moves for move in man_order.move_raw_ids: self.assertEqual(move.date, test_date_planned) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_2) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 2) first_move = man_order.move_raw_ids.filtered(lambda move: move.product_id == self.product_1) self.assertEqual(first_move.product_qty, test_quantity / self.bom_1.product_qty * self.product_4.uom_id.factor_inv * 4) # produce product produce_form = Form(self.env['mrp.product.produce'].with_context({ 'active_id': man_order.id, 'active_ids': [man_order.id], })) produce_form.qty_producing = 1.0 produce_wizard = produce_form.save() produce_wizard.do_produce() man_order.button_mark_done() self.assertEqual(man_order.state, 'done', "Production order should be in done state.")
def get_meeting_this_week( self, employee, index): # meeting_today = [id(int), [name, start, stop]] # tim tat ca cac leave cua nhan vien trong tuan nay # tim tat ca cac event duoc tao ra sau khi approve # tim tat ca cac meeting trong tuan nay khong nam trong nhung meeting trong buoc tren # , ('id', 'not in', leave_ids) leaves = request.env['hr.leave'].sudo().search([('state', '=', 'validate')]) leave_ids = [] for e in leaves: leave_ids.append(e.meeting_id.id) today = Datetime.now() start = today - timedelta(days=today.weekday()) end = start + timedelta(days=6) meetings = request.env['calendar.event'].sudo().search([ ('stop', '>=', str(start)), ('start', '<=', str(end)), ('id', 'not in', leave_ids) ]) meeting_this_week_ids = [] for e in meetings.ids: if isinstance(e, int): meeting_this_week_ids.append(e) # tim tat ca cac meeting employee nay tham gia trong khoang thoi gian tuan nay calendar_attendee_this_week = request.env['calendar.attendee'].sudo( ).search([('event_id', 'in', meeting_this_week_ids), ('partner_id', '=', employee.user_id.partner_id.id), ('state', '=', 'accepted')]) # set quyen truy cap tat ca meeting cho admin # admin = request.env['res.groups'].sudo().search([('name', '=', "Settings")]) # set_admin = admin.users # loc va return check_meeting = [] meeting_this_week = {} for calendar_attendee_this_week_item in calendar_attendee_this_week: meeting_today_am = [] meeting_today_pm = [] meeting_today = [] index += 1 meeting = calendar_attendee_this_week_item.event_id if self.user_has_groups('employee_time_table.group_admin_timetable' ) or self._uid == employee.user_id.id: meeting_reason = meeting.name else: meeting_reason = "Meeting Occupied" # fix time zone current_meeting_start = meeting.start.astimezone( timezone(self.get_timezone())) current_meeting_stop = meeting.stop.astimezone( timezone(self.get_timezone())) meeting_start_standard_visual = current_meeting_start.strftime( "%d/%m/%Y %H:%M") meeting_stop_standard_visual = current_meeting_stop.strftime( "%d/%m/%Y %H:%M") # if meeting not all day if not meeting.allday: # if no, check if meeting occurs in the morning, if yes, update data check_meeting.append( meeting.start.astimezone(timezone( self.get_timezone())).weekday()) meeting_day = current_meeting_start.strftime("%A") if int(current_meeting_start.strftime("%H")) < 13 and int( current_meeting_stop.strftime("%H")) < 13: # meeting_day += "_AM" infos = [ meeting_reason, meeting_start_standard_visual, meeting_stop_standard_visual ] meeting_today_am.append(True) meeting_today_am.append(False) meeting_today_am.append(meeting.id) meeting_today_am.append(infos) if not meeting_this_week.get(meeting_day): meeting_this_week.update({ meeting_day: [True, False, index, [meeting_today_am]] }) else: new_meeting_today_data_am = meeting_this_week.get( meeting_day)[3] new_meeting_today_data_am.append(meeting_today_am) meeting_this_week.update({ meeting_day: [ True, meeting_this_week.get(meeting_day)[1], index, new_meeting_today_data_am ] }) elif int(current_meeting_start.strftime("%H")) >= 13 and int( current_meeting_stop.strftime("%H")) >= 13: # meeting_day += "_PM" infos = [ meeting_reason, meeting_start_standard_visual, meeting_stop_standard_visual ] meeting_today_pm.append(False) meeting_today_pm.append(True) meeting_today_pm.append(meeting.id) meeting_today_pm.append(infos) if not meeting_this_week.get(meeting_day): meeting_this_week.update({ meeting_day: [False, True, index, [meeting_today_pm]] }) else: new_meeting_today_data_pm = meeting_this_week.get( meeting_day)[3] new_meeting_today_data_pm.append(meeting_today_pm) meeting_this_week.update({ meeting_day: [ meeting_this_week.get(meeting_day)[0], True, index, new_meeting_today_data_pm ] }) else: infos = [ meeting_reason, meeting_start_standard_visual, meeting_stop_standard_visual ] meeting_today.append(True) meeting_today.append(True) meeting_today.append(meeting.id) meeting_today.append(infos) if not meeting_this_week.get(meeting_day): meeting_this_week.update({ meeting_day: [True, True, index, [meeting_today]] }) else: new_meeting_today_data = meeting_this_week.get( meeting_day)[3] new_meeting_today_data.append(meeting_today) meeting_this_week.update({ meeting_day: [ meeting_this_week.get(meeting_day)[0], True, index, new_meeting_today_data ] }) else: current_meeting_start_tmp = meeting.start if datetime.strftime(current_meeting_start_tmp, '%Y/%m/%d') < datetime.strftime( start, '%Y/%m/%d'): current_meeting_start_tmp = start # if not sunday monday_first_time = True while monday_first_time and current_meeting_start_tmp.weekday( ) < 7 and datetime.strftime(current_meeting_start_tmp, '%Y/%m/%d') <= datetime.strftime( meeting.stop, '%Y/%m/%d'): current_meeting_day = current_meeting_start_tmp.strftime( "%A") check_meeting.append(current_meeting_start_tmp.weekday()) if not meeting_this_week.get(current_meeting_day): meeting_this_week.update({ current_meeting_day: [ True, True, index, [[ True, True, meeting.id, [ meeting_reason, meeting.start.strftime("%d/%m/%Y") + ' 00:00', meeting.stop.strftime("%d/%m/%Y") + ' 23:59' ] ]] ] }) else: meeting_this_week.get(current_meeting_day)[0] = True meeting_this_week.get(current_meeting_day)[1] = True meeting_this_week.get(current_meeting_day)[3].append([ True, True, index, [ meeting_reason, meeting.start.strftime("%d/%m/%Y") + ' 00:00', meeting.stop.strftime("%d/%m/%Y") + ' 23:59' ] ]) index += 1 current_meeting_start_tmp += timedelta(days=1) if current_meeting_start_tmp.weekday() == 0: monday_first_time = False # if not having meeting, return false day_off = 'None' for i in range(6): if i not in check_meeting: if i == 0: day_off = 'Monday' if i == 1: day_off = 'Tuesday' if i == 2: day_off = 'Wednesday' if i == 3: day_off = 'Thursday' if i == 4: day_off = 'Friday' if i == 5: day_off = 'Saturday' meeting_today = [] meeting_this_week.update( {day_off: [False, False, False, [meeting_today]]}) return meeting_this_week, index