def poll(self, dbname, channels, last, options=None, timeout=TIMEOUT): if options is None: options = {} # Dont hang ctrl-c for a poll request, we need to bypass private # attribute access because we dont know before starting the thread that # it will handle a longpolling request if not swerp.evented: current = threading.current_thread() current._Thread__daemonic = True # PY2 current._daemonic = True # PY3 # rename the thread to avoid tests waiting for a longpolling current.setName("openerp.longpolling.request.%s" % current.ident) registry = swerp.registry(dbname) # immediatly returns if past notifications exist with registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) notifications = env['bus.bus'].poll(channels, last, options) # immediatly returns in peek mode if options.get('peek'): return dict(notifications=notifications, channels=channels) # or wait for future ones if not notifications: if not self.started: # Lazy start of events listener self.start() event = self.Event() for channel in channels: self.channels.setdefault(hashable(channel), set()).add(event) try: event.wait(timeout=timeout) with registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) notifications = env['bus.bus'].poll(channels, last, options, force_status=True) except Exception: # timeout pass finally: # gc pointers to event for channel in channels: channel_events = self.channels.get(hashable(channel)) if channel_events and event in channel_events: channel_events.remove(event) return notifications
def oea(self, **kw): """login user via Swerp Account provider""" dbname = kw.pop('db', None) if not dbname: dbname = db_monodb() if not dbname: return BadRequest() if not http.db_filter([dbname]): return BadRequest() registry = registry_get(dbname) with registry.cursor() as cr: try: env = api.Environment(cr, SUPERUSER_ID, {}) provider = env.ref('auth_oauth.provider_openerp') except ValueError: return set_cookie_and_redirect('/web?db=%s' % dbname) assert provider._name == 'auth.oauth.provider' state = { 'd': dbname, 'p': provider.id, 'c': {'no_user_creation': True}, } kw['state'] = json.dumps(state) return self.signin(**kw)
def test_02_demo_address_and_company(self): ''' This test ensure that the company_id of the address (partner) is correctly set and also, is not wrongly changed. eg: new shipping should use the company of the website and not the one from the admin, and editing a billing should not change its company. ''' self._setUp_multicompany_env() so = self._create_so(self.demo_partner.id) env = api.Environment(self.env.cr, self.demo_user.id, {}) # change also website env for `sale_get_order` to not change order partner_id with MockRequest(env, website=self.website.with_env(env), sale_order_id=so.id): # 1. Logged in user, new shipping self.WebsiteSaleController.address(**self.default_address_values) new_shipping = self._get_last_address(self.demo_partner) self.assertTrue( new_shipping.company_id != self.env.user.company_id, "Logged in user new shipping should not get the company of the sudo() neither the one from it's partner.." ) self.assertEqual(new_shipping.company_id, self.website.company_id, ".. but the one from the website.") # 2. Logged in user, edit billing self.default_address_values['partner_id'] = self.demo_partner.id self.WebsiteSaleController.address(**self.default_address_values) self.assertEqual( self.demo_partner.company_id, self.company_c, "Logged in user edited billing (the partner itself) should not get its company modified." )
def test_03_public_user_address_and_company(self): ''' Same as test_02 but with public user ''' self._setUp_multicompany_env() so = self._create_so(self.website.user_id.partner_id.id) env = api.Environment(self.env.cr, self.website.user_id.id, {}) # change also website env for `sale_get_order` to not change order partner_id with MockRequest(env, website=self.website.with_env(env), sale_order_id=so.id): # 1. Public user, new billing self.default_address_values['partner_id'] = -1 self.WebsiteSaleController.address(**self.default_address_values) new_partner = so.partner_id self.assertNotEqual( new_partner, self.website.user_id.partner_id, "New billing should have created a new partner and assign it on the SO" ) self.assertEqual( new_partner.company_id, self.website.company_id, "The new partner should get the company of the website") # 2. Public user, edit billing self.default_address_values['partner_id'] = new_partner.id self.WebsiteSaleController.address(**self.default_address_values) self.assertEqual( new_partner.company_id, self.website.company_id, "Public user edited billing (the partner itself) should not get its company modified." )
def _serve_attachment(cls): env = api.Environment(request.cr, SUPERUSER_ID, request.context) attach = env['ir.attachment'].get_serve_attachment(request.httprequest.path, extra_fields=['name', 'checksum']) if attach: wdate = attach[0]['__last_update'] datas = attach[0]['datas'] or b'' name = attach[0]['name'] checksum = attach[0]['checksum'] or hashlib.sha1(datas).hexdigest() if (not datas and name != request.httprequest.path and name.startswith(('http://', 'https://', '/'))): return werkzeug.utils.redirect(name, 301) response = werkzeug.wrappers.Response() response.last_modified = wdate response.set_etag(checksum) response.make_conditional(request.httprequest) if response.status_code == 304: return response response.mimetype = attach[0]['mimetype'] or 'application/octet-stream' response.data = base64.b64decode(datas) return response
def _button_immediate_function(self, function): try: # This is done because the installation/uninstallation/upgrade can modify a currently # running cron job and prevent it from finishing, and since the ir_cron table is locked # during execution, the lock won't be released until timeout. self._cr.execute("SELECT * FROM ir_cron FOR UPDATE NOWAIT") except psycopg2.OperationalError: raise UserError(_("The server is busy right now, module operations are not possible at" " this time, please try again later.")) function(self) self._cr.commit() api.Environment.reset() modules.registry.Registry.new(self._cr.dbname, update_module=True) self._cr.commit() env = api.Environment(self._cr, self._uid, self._context) # pylint: disable=next-method-called config = env['ir.module.module'].next() or {} if config.get('type') not in ('ir.actions.act_window_close',): return config # reload the client; open the first available root menu menu = env['ir.ui.menu'].search([('parent_id', '=', False)])[:1] return { 'type': 'ir.actions.client', 'tag': 'reload', 'params': {'menu_id': menu.id}, }
def environment(): """ Return an environment with a new cursor for the current database; the cursor is committed and closed after the context block. """ reg = registry(common.get_db_name()) with reg.cursor() as cr: yield api.Environment(cr, SUPERUSER_ID, {})
def load_demo(cr, package, idref, mode, report=None): """ Loads demo data for the specified package. """ if not package.should_have_demo(): return False try: _logger.info("Module %s: loading demo", package.name) with cr.savepoint(): load_data(cr, idref, mode, kind='demo', package=package, report=report) return True except Exception as e: # If we could not install demo data for this module _logger.warning( "Module %s demo data failed to install, installed without demo data", package.name, exc_info=True) env = api.Environment(cr, SUPERUSER_ID, {}) todo = env.ref('base.demo_failure_todo', raise_if_not_found=False) Failure = env.get('ir.demo_failure') if todo and Failure is not None: todo.state = 'open' Failure.create({'module_id': package.id, 'error': str(e)}) return False
def rem_website_id_null(dbname): db_registry = swerp.modules.registry.Registry.new(dbname) with api.Environment.manage(), db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) env['ir.model.fields'].search([ ('name', '=', 'website_id'), ('model', '=', 'res.config.settings'), ]).unlink()
def update_dashboard_graph_model(dbname): db_registry = swerp.modules.registry.Registry.new(dbname) with api.Environment.manage(), db_registry.cursor() as cr: env = api.Environment(cr, SUPERUSER_ID, {}) if 'crm.team' in env: recs = env['crm.team'].search([]) for rec in recs: rec._onchange_team_type()
def uninstall_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) env['product.template'].search([ ('service_type', '=', 'timesheet') ]).write({'service_type': 'manual'}) env['product.product'].search([ ('service_type', '=', 'timesheet') ]).write({'service_type': 'manual'})
def reset_payment_provider(cr, registry, provider): env = api.Environment(cr, SUPERUSER_ID, {}) acquirers = env['payment.acquirer'].search([('provider', '=', provider)]) acquirers.write({ 'view_template_id': acquirers._get_default_view_template_id().id, 'provider': 'manual', })
def uninstall_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) code_taxes = env['account.tax'].search([('amount_type', '=', 'code')]) code_taxes.write({'amount_type': 'percent', 'active': False}) _logger.warning( "The following taxes have been archived following 'account_tax_python' module uninstallation: %s" % code_taxes.ids)
def _setup_inalterability(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) # enable ping for this module env['publisher_warranty.contract'].update_notification(cron_mode=True) fr_companies = env['res.company'].search([('partner_id.country_id.code', 'in', UNALTERABLE_COUNTRIES)]) if fr_companies: # create the securisation sequence per company fr_companies._create_secure_sequence(['l10n_fr_closing_sequence_id'])
def _create_buy_rules(cr, registry): """ This hook is used to add a default buy_pull_id on every warehouse. It is necessary if the purchase_stock module is installed after some warehouses were already created. """ env = api.Environment(cr, SUPERUSER_ID, {}) warehouse_ids = env['stock.warehouse'].search([('buy_pull_id', '=', False) ]) for warehouse_id in warehouse_ids: warehouse_id._create_or_update_global_routes_rules()
def to_python(self, value): matching = re.match(self.regex, value) _uid = RequestUID(value=value, match=matching, converter=self) record_id = int(matching.group(2)) env = api.Environment(request.cr, _uid, request.context) if record_id < 0: # limited support for negative IDs due to our slug pattern, assume abs() if not found if not env[self.model].browse(record_id).exists(): record_id = abs(record_id) return env[self.model].browse(record_id)
def _create_warehouse_data(cr, registry): """ This hook is used to add a default manufacture_pull_id, manufacture picking_type on every warehouse. It is necessary if the mrp module is installed after some warehouses were already created. """ env = api.Environment(cr, SUPERUSER_ID, {}) warehouse_ids = env['stock.warehouse'].search([('manufacture_pull_id', '=', False)]) for warehouse_id in warehouse_ids: warehouse_id.write({'manufacture_to_resupply': True})
def _auto_install_l10n(cr, registry): #check the country of the main company (only) and eventually load some module needed in that country env = api.Environment(cr, SUPERUSER_ID, {}) country_code = env.user.company_id.country_id.code if country_code: #auto install localization module(s) if available module_list = [] if country_code in SYSCOHADA_LIST: #countries using OHADA Chart of Accounts module_list.append('l10n_syscohada') elif country_code == 'GB': module_list.append('l10n_uk') elif country_code == 'DE': module_list.append('l10n_de_skr03') module_list.append('l10n_de_skr04') elif country_code == 'CN': module_list.append('l10n_cn_small_business') module_list.append('l10n_cn_standard') else: if env['ir.module.module'].search([ ('name', '=', 'l10n_' + country_code.lower()) ]): module_list.append('l10n_' + country_code.lower()) else: module_list.append('l10n_generic_coa') if country_code == 'US': module_list.append('account_plaid') module_list.append('l10n_us_check_printing') if country_code == 'CA': module_list.append('l10n_ca_check_printing') if country_code in [ 'US', 'AU', 'NZ', 'CA', 'CO', 'EC', 'ES', 'FR', 'IN', 'MX', 'UK' ]: module_list.append('account_yodlee') if country_code in SYSCOHADA_LIST + [ 'AT', 'BE', 'CA', 'CO', 'DE', 'EC', 'ES', 'ET', 'FR', 'GR', 'IT', 'LU', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'SI', 'TR', 'UK', 'VE', 'VN' ]: module_list.append('base_vat') if country_code == 'MX': module_list.append('l10n_mx_edi') # European countries will be using SEPA europe = env.ref('base.europe', raise_if_not_found=False) if europe: europe_country_codes = [x.code for x in europe.country_ids] if country_code in europe_country_codes: module_list.append('account_sepa') module_list.append('account_bank_statement_import_camt') module_ids = env['ir.module.module'].search([ ('name', 'in', module_list), ('state', '=', 'uninstalled') ]) module_ids.sudo().button_install()
def _assign_default_nomeclature_id(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) company_ids_without_default_nomenclature_id = env['res.company'].search([ ('nomenclature_id', '=', False) ]) default_nomenclature_id = env.ref('barcodes.default_barcode_nomenclature', raise_if_not_found=False) if default_nomenclature_id: company_ids_without_default_nomenclature_id.write({ 'nomenclature_id': default_nomenclature_id.id, })
def uninstall_hook(cr, registry): ''' Need to reenable the `product` pricelist multi-company rule that were disabled to be 'overriden' for multi-website purpose ''' env = api.Environment(cr, SUPERUSER_ID, {}) pl_rule = env.ref('product.product_pricelist_comp_rule', raise_if_not_found=False) pl_item_rule = env.ref('product.product_pricelist_item_comp_rule', raise_if_not_found=False) multi_company_rules = pl_rule or env['ir.rule'] multi_company_rules += pl_item_rule or env['ir.rule'] multi_company_rules.write({'active': True})
def _set_accounts(cr, registry): #write the default debit account on salary rule having xml_id like 'l10n_be_hr_payroll.1' up to 'l10n_be_hr_payroll.1409' env = api.Environment(cr, SUPERUSER_ID, {}) names = [str(x) for x in range(1, 1410)] data = env['ir.model.data'].search([('model', '=', 'hr.salary.rule'), ('module', '=', 'l10n_be_hr_payroll'), ('name', 'in', names)]) account = env['account.account'].search([('code', 'like', '4530%')], limit=1) if account and data: rule_ids = [x['res_id'] for x in data.read(['res_id'])] env['hr.salary.rule'].browse(rule_ids).write( {'account_debit': account.id})
def _auth_method_public(cls): """ If no user logged, set the public user of current website, or default public user as request uid. After this method `request.env` can be called, since the `request.uid` is set. The `env` lazy property of `request` will be correct. """ if not request.session.uid: env = api.Environment(request.cr, SUPERUSER_ID, request.context) website = env['website'].get_current_website() if website and website.user_id: request.uid = website.user_id.id if not request.uid: super(Http, cls)._auth_method_public()
def _setup_inalterability(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) # enable ping for this module env['publisher_warranty.contract'].update_notification(cron_mode=True) fr_companies = env['res.company'].search([('partner_id.country_id.code', 'in', UNALTERABLE_COUNTRIES)]) if fr_companies: # create the securisation sequence per company fr_companies._create_secure_sequence(['l10n_fr_secure_sequence_id']) #reset the update_posted field on journals journals = env['account.journal'].search([('company_id', 'in', fr_companies.ids)]) journals.write({'update_posted': False})
def uninstall_hook(cr, registry): env = api.Environment(cr, SUPERUSER_ID, {}) default = env['product.template']._fields['type'].default( env['product.template']) def _reset_product_template_type(): # stock introduces an option on the `type` Selection field of `product.template` # if this module is uninstalled and any `product.template` record still points to this option # the registry will find itself in an unstable state and will most likely crash (eventually) cr.execute("UPDATE product_template SET type = %s WHERE type = %s", (default, 'product')) cr.after('commit', _reset_product_template_type)
def force_demo(cr): """ Forces the `demo` flag on all modules, and installs demo data for all installed modules. """ graph = swerp.modules.graph.Graph() cr.execute('UPDATE ir_module_module SET demo=True') cr.execute( "SELECT name FROM ir_module_module WHERE state IN ('installed', 'to upgrade', 'to remove')" ) module_list = [name for (name, ) in cr.fetchall()] graph.add_modules(cr, module_list, ['demo']) for package in graph: load_demo(cr, package, {}, 'init') env = api.Environment(cr, SUPERUSER_ID, {}) env['ir.module.module'].invalidate_cache(['demo'])
def _create_warehouse(cr, registry): """ This hook is used to add a warehouse on existing companies when module stock is installed. """ env = api.Environment(cr, SUPERUSER_ID, {}) company_ids = env['res.company'].search([]) company_with_warehouse = env['stock.warehouse'].search( []).mapped('company_id') company_without_warehouse = company_ids - company_with_warehouse for company in company_without_warehouse: company.create_transit_location() env['stock.warehouse'].create({ 'name': company.name, 'code': company.name[:5], 'company_id': company.id, 'partner_id': company.partner_id.id })
def signin(self, **kw): state = json.loads(kw['state']) dbname = state['d'] if not http.db_filter([dbname]): return BadRequest() provider = state['p'] context = state.get('c', {}) registry = registry_get(dbname) with registry.cursor() as cr: try: env = api.Environment(cr, SUPERUSER_ID, context) credentials = env['res.users'].sudo().auth_oauth(provider, kw) cr.commit() action = state.get('a') menu = state.get('m') redirect = werkzeug.url_unquote_plus(state['r']) if state.get('r') else False url = '/web' if redirect: url = redirect elif action: url = '/web#action=%s' % action elif menu: url = '/web#menu_id=%s' % menu resp = login_and_redirect(*credentials, redirect_url=url) # Since /web is hardcoded, verify user has right to land on it if werkzeug.urls.url_parse(resp.location).path == '/web' and not request.env.user.has_group('base.group_user'): resp.location = '/' return resp except AttributeError: # auth_signup is not installed _logger.error("auth_signup not installed on database %s: oauth sign up cancelled." % (dbname,)) url = "/web/login?oauth_error=1" except AccessDenied: # oauth credentials not valid, user could be on a temporary session _logger.info('OAuth2: access denied, redirect to main page in case a valid session exists, without setting cookies') url = "/web/login?oauth_error=3" redirect = werkzeug.utils.redirect(url, 303) redirect.autocorrect_location_header = False return redirect except Exception as e: # signup error _logger.exception("OAuth2: %s" % str(e)) url = "/web/login?oauth_error=2" return set_cookie_and_redirect(url)
def _login(cls, db, login, password): try: return super(Users, cls)._login(db, login, password) except AccessDenied as e: with registry(db).cursor() as cr: cr.execute("SELECT id FROM res_users WHERE lower(login)=%s", (login, )) res = cr.fetchone() if res: raise e env = api.Environment(cr, SUPERUSER_ID, {}) Ldap = env['res.company.ldap'] for conf in Ldap._get_ldap_dicts(): entry = Ldap._authenticate(conf, login, password) if entry: return Ldap._get_or_create_user(conf, login, entry) raise e
def post_init(cr, registry): """ Set the timesheet project and task on existing leave type. Do it in post_init to be sure the internal project/task of res.company are set. (Since timesheet_generate field is true by default, those 2 fields are required on the leave type). """ from swerp import api, SUPERUSER_ID env = api.Environment(cr, SUPERUSER_ID, {}) for hr_leave_type in env['hr.leave.type'].search([ ('timesheet_generate', '=', True), ('timesheet_project_id', '=', False) ]): company = hr_leave_type.company_id or env.user.company_id hr_leave_type.write({ 'timesheet_project_id': company.leave_timesheet_project_id.id, 'timesheet_task_id': company.leave_timesheet_task_id.id, })
def _process_job(cls, job_cr, job, cron_cr): """ Run a given job taking care of the repetition. :param job_cr: cursor to use to execute the job, safe to commit/rollback :param job: job to be run (as a dictionary). :param cron_cr: cursor holding lock on the cron job row, to use to update the next exec date, must not be committed/rolled back! """ try: with api.Environment.manage(): cron = api.Environment(job_cr, job['user_id'], {})[cls._name] # Use the user's timezone to compare and compute datetimes, # otherwise unexpected results may appear. For instance, adding # 1 month in UTC to July 1st at midnight in GMT+2 gives July 30 # instead of August 1st! now = fields.Datetime.context_timestamp(cron, datetime.now()) nextcall = fields.Datetime.context_timestamp(cron, fields.Datetime.from_string(job['nextcall'])) numbercall = job['numbercall'] ok = False while nextcall < now and numbercall: if numbercall > 0: numbercall -= 1 if not ok or job['doall']: cron._callback(job['cron_name'], job['ir_actions_server_id'], job['id']) if numbercall: nextcall += _intervalTypes[job['interval_type']](job['interval_number']) ok = True addsql = '' if not numbercall: addsql = ', active=False' cron_cr.execute("UPDATE ir_cron SET nextcall=%s, numbercall=%s"+addsql+" WHERE id=%s", (fields.Datetime.to_string(nextcall.astimezone(pytz.UTC)), numbercall, job['id'])) cron.invalidate_cache() finally: job_cr.commit() cron_cr.commit()