def check_report(self): """.""" query = self.offering church = ('church_id', '=', self.env.user.company_id.id) services = self.env['ng_church.offering'].search([('service_id', '=', query.id), church]) offering_line = self.env['ng_church.offering_line'] for offering in services: offering_line += offering_line.search([('offering_id', '=', offering.id), church]) offerings = self._report_range(offering_line, self.date_from, self.date_to) if len(offerings) > 0: return self.env['report'].get_action( offerings, 'ng_church.church_offering_report') raise MissingError('Record not found')
def _prepare_claim(self, params): categ = self.env['crm.case.categ'].search([('id', '=', params['subject_id'])]) claim_type = self.env.ref('crm_claim_type.crm_claim_type_customer').id backend_id = self.backend_record.id vals = { 'categ_id': params['subject_id'], 'name': categ.name, 'description': params['message'], 'partner_id': self.partner.id, 'claim_type': claim_type, 'shopinvader_backend_id': backend_id, 'claim_line_ids': [] } vals = self.env['crm.claim'].play_onchanges(vals, ['partner_id']) order = False for line in params['sale_order_line']: if not line['qty']: continue so_line = self.env['sale.order.line'].search([ ('id', '=', line['id']), ('order_id.partner_id', '=', self.partner.id), ('order_id.shopinvader_backend_id', '=', backend_id) ]) if not so_line: raise MissingError( _('The sale order line %s does not exist') % line['id']) if not order: order = so_line.order_id vals['ref'] = 'sale.order,%s' % order.id elif order != so_line.order_id: raise UserError( _('All sale order lines must' 'come from the same sale order')) if order.invoice_ids and not vals.get('invoice_id', False): vals['invoice_id'] = order.invoice_ids[0].id vals['claim_line_ids'].append((0, 0, { 'product_id': so_line.product_id.id, 'product_returned_quantity': line['qty'], 'claim_origin': 'none' })) if not vals['claim_line_ids']: raise UserError(_('You have to select an item')) return vals
def _get_report_values(self, docids, data=None): partner_obj = self.env["res.partner"] student_ids = self.env.context.get("active_ids", []) students = partner_obj.browse(student_ids or docids) template = self.env.company.school_leaving_template if not template: raise MissingError("School Leaving Report Template is empty.") contents = {} for student in students: vals = { "date_today": fields.Date.context_today(self), } student_vals = student.read()[0] for key, value in student_vals.items(): vals["student_" + key] = value parent = student.family_ids.member_ids.filtered( lambda m: m.person_type == "parent") if parent: parent_vals = parent[0].read()[0] for key, value in parent_vals.items(): vals["parent_" + key] = value if student.grade_level_id: grade_level_vals = student.grade_level_id.read()[0] for key, value in grade_level_vals.items(): vals["grade_level_" + key] = value for key, value in vals.items(): new_value = str(value) if isinstance(value, date): new_value = format_date(self.env, value) elif isinstance(value, datetime): new_value = format_datetime(self.env, value) vals[key] = new_value try: contents[student.id] = template % vals except: raise ValidationError( "An error has occurred while formatting the school leaving report template." ) return { "doc_ids": student_ids, "doc_model": "res.partner", "docs": students, "contents": contents, }
def _ticket_check_access(self, model_name, document_id, access_token=None): document_search = request.env[model_name].sudo().search([ ('id', '=', document_id), ('partner_id.id', '=', request.env.user.partner_id.id) ]) document = request.env[model_name].sudo().browse([document_id]) document_sudo = document.sudo().exists() if not document_sudo or not document_search: raise MissingError("This document does not exist.") try: document.check_access_rights('read') document.check_access_rule('read') except AccessError: if not access_token or not consteq(document_sudo.access_token, access_token): raise return document_sudo
def find(self, env, path, model=None): if model: return self._find(env, path, model) else: result = [] try: result.append(self._find(env, path, 'muk_dms.directory')) except MissingError: pass try: result.append(self._find(env, path, 'muk_dms.file')) except MissingError: pass if result: return result else: raise MissingError(_("The record is missing!"))
def _read_file(self, file_path): with opened_w_error(file_path, "rb") as (file_handler, exception): if exception: _logger.error("Failed to read the file (%s): %s" % (file_path, str(exception))) raise MissingError( _("Something went wrong! Seems that the file (%s) is missing or broken.") % os.path.basename(file_path)) else: file = file_handler.read() encode_file = base64.b64encode(file) if self._check_file(file, self.checksum): return encode_file else: _logger.error( "Failed to read the file (%s): The file has been altered outside of the system." % os.path.basename(file_path)) raise ValidationError(_("The file (%s) is corrupted.") % os.path.basename(file_path))
def _document_check_access(self, model_name, document_id, access_token=None): document = request.env[model_name].browse([document_id]) _logger.info("document: " + str(document)) document_sudo = document.sudo().exists() if not document_sudo: raise MissingError("This document does not exist.") try: document.check_access_rights('read') document.check_access_rule('read') except AccessError: if not access_token or not consteq(document_sudo.access_token, access_token): raise return document_sudo
def _find_from_reference(self, reference): """Find a task from the given reference. :param reference: the task reference for which to find a task. :return: a project.task record if any found, otherwise None """ if not reference.task_id: return None task = self.browse(reference.task_id) if not task.exists(): raise MissingError( _('The task referenced by {ref} does not exist. ' 'No task found for the database ID {id}.').format( ref=reference, id=reference.task_id)) return task
def _prepare_second_account_move_line(self, move_id): if self.journal_id.default_debit_account_id.id == False: raise MissingError( '{} default debit and credit are not set.'.format( self.journal_id.name)) payload = { 'name': self.description, 'account_id': self.journal_id.default_debit_account_id.id, 'move_id': move_id, 'partner_id': parish(self), 'quantity': 1, 'debit': abs(self.amount), 'credit': 0.0, 'date': self.date, } account_move_line = self.env['account.move.line'].with_context( check_move_validity=False) account_move_line.create(payload)
def get(self, _id, size): """ Get partner's image """ field = "image" if size == "small": field = "image_small" elif size == "medium": field = "image_medium" status, headers, content = self.env["ir.http"].binary_content( model="res.partner", id=_id, field=field, env=self.env) if not content: raise MissingError(_("No image found for partner %s") % _id) image_base64 = base64.b64decode(content) headers.append(("Content-Length", len(image_base64))) response = request.make_response(image_base64, headers) response.status_code = status return response
def update_checksum(self): missing = [] for record in self: file_path = record._build_path() with opened_w_error(file_path, "rb") as (file_handler, exception): if exception: missing.append(file_path) _logger.error("Failed to read the file (%s): %s" % (file_path, str(exception))) else: file = file_handler.read() record.checksum = record._compute_checksum(file) if missing: message = _( "Something went wrong! Seems that some files are missing.\n") for path in missing: message += "\n - %s" % path raise MissingError(message)
def get(self, _id, size): """ Get partner's image """ field = 'image' if size == 'small': field = 'image_small' elif size == 'medium': field = 'image_medium' status, headers, content = self.env['ir.http'].binary_content( model='res.partner', id=_id, field=field, env=self.env) if not content: raise MissingError(_('No image found for partner %s') % _id) image_base64 = base64.b64decode(content) headers.append(('Content-Length', len(image_base64))) response = request.make_response(image_base64, headers) response.status_code = status return response
def aeroo_report(self, docids, data): self.name = self._context.get('report_name') report = self.env['ir.actions.report']._get_report_from_name(self.name) # TODO #_logger.info("Start Aeroo Reports %s (%s)" % (name, ctx.get('active_model')), logging.INFO) # debug mode if 'tz' not in self._context: self = self.with_context(tz=self.env.user.tz) # TODO we should propagate context in the proper way, just with self # agregamos el process_sep aca ya que necesitamos el doc convertido # para poder unirlos if report.process_sep and len(docids) > 1: # por ahora solo soportamos process_sep para pdf, en version # anterior tambien soportaba algun otro code = report.out_format.code if code != 'oo-pdf': raise MissingError( _('Process_sep not compatible with selected output format') ) results = [] for docid in docids: results.append( self.assemble_tasks([docid], data, report, self._context)) output = PdfFileWriter() for r in results: reader = PdfFileReader(BytesIO(r[0])) for page in range(reader.getNumPages()): output.addPage(reader.getPage(page)) s = BytesIO() output.write(s) data = s.getvalue() res = self._context.get('return_filename') and\ (data, results[0][1], results[0][2]) or (data, results[0][1]) else: res = self.assemble_tasks(docids, data, report, self._context) # TODO #_logger.info("End Aeroo Reports %s (%s), total elapsed time: %s" % (name, model), time() - aeroo_print.start_total_time), logging.INFO) # debug mode return res
def apply_discount(self): for order_id in self: write_lines = [] partner_id = order_id.student_id if order_id.student_id else order_id.partner_id discount_ids = partner_id.discount_ids for order_line_id in order_id.order_line: # If there is a student, our priority is the student invoice_line_categories = get_parent_category( order_line_id.product_id.categ_id) discount_applicable = discount_ids.filtered( lambda discount: discount.category_id in invoice_line_categories) for discount in discount_applicable: percent = discount.percent discount_count = -order_line_id.price_subtotal * (percent / 100) if not discount.product_id: raise MissingError( "There is no product set for the discount %s" % discount.name) order_line_create = { "product_id": discount.product_id.get_single_product_variant().get( "product_id", False), "price_unit": discount_count, # "analytic_account_id": discount.analytic_account_id.id, } if order_line_id.tax_id: order_line_create.update( {"tax_id": [(6, 0, order_line_id.tax_id.ids)]}) write_lines.append((0, 0, order_line_create)) order_id.write({"order_line": write_lines})
def _get_partner_from_headers(cls, headers): partner_model = request.env["shopinvader.partner"] partner_email = headers.get("HTTP_PARTNER_EMAIL") backend = cls._get_shopinvader_backend_from_request() if partner_email: partner = cls._find_partner(backend, partner_email) if len(partner) == 1: cls._validate_partner(backend, partner) return partner.record_id else: _logger.warning("Wrong HTTP_PARTNER_EMAIL, header ignored") if len(partner) > 1: _logger.warning( "More than one shopinvader.partner found for:" " backend_id={} email={}".format( backend.id, partner_email)) # Could be because the email is not related to a partner or # because the partner is inactive raise MissingError(_("The given partner is not found!")) return partner_model.browse([]).record_id
def _get_commerce_partner(self): if self._jwt_payload: partner_email = self._jwt_payload.get("email") backend = self._get_backend() if partner_email: commerce_partner = self._find_partner(backend, partner_email) if len(commerce_partner) == 1: self._validate_partner(backend, commerce_partner) return commerce_partner else: _logger.warning("Wrong email, jwt payload ignored") if len(commerce_partner) > 1: _logger.warning( "More than one commerce.partner found for:" " backend_id={} email={}".format( backend.id, partner_email)) # Could be because the email is not related to a partner or # because the partner is inactive raise MissingError(_("The given partner is not found!")) return super()._get_commerce_partner()
def action_print_report_xlsx(self): self.create_report_view() self._cr.execute("SELECT * FROM hotel_report") docs = self._cr.fetchall() if not docs: raise MissingError("Record does not exist or has been deleted.") return { 'type': 'ir.actions.report', 'data': { 'model': 'report.hotel_management.report_xlsx', 'options': json.dumps(self.get_data(), default=date_utils.json_default), 'output_format': 'xlsx', 'report_name': 'Hotel Management Report', }, 'report_type': 'xlsx', }
def _get_commerce_partner(self): headers = self.request.httprequest.environ partner_model = self.env["commerce.partner"] partner_email = headers.get("HTTP_PARTNER_EMAIL") backend = self._get_backend() if partner_email: partner = self._find_partner(backend, partner_email) if len(partner) == 1: self._validate_partner(backend, partner) return partner else: _logger.warning("Wrong HTTP_PARTNER_EMAIL, header ignored") if len(partner) > 1: _logger.warning( "More than one commerce.partner found for:" " backend_id={} email={}".format(backend.id, partner_email) ) # Could be because the email is not related to a partner or # because the partner is inactive raise MissingError(_("The given partner is not found!")) return partner_model.browse([])
def validate_counter_header(self): # extract the data lines from the specified absolute path data = self.read_file(self.counter_file_path) # read the header attributes file_header = self.sanitize_row(data[0]).split(';') # validate header attributes for key in self.counter_header: if key not in file_header: raise MissingError("Missing attribute counter_header %s" % key) # remove the header data.pop(0) # store the data in object attribute self.counter_data = [self.sanitize_row(row).split(';') for row in data] record_id = self.env['file.compteur'].search([]) if record_id: record_id.unlink() for rec in self.counter_data: vals = { 'CodeConcession': rec[self.counter_header.index('CodeConcession')], 'NomConcession': rec[self.counter_header.index('NomConcession')], 'CodeClient': rec[self.counter_header.index('CodeClient')], 'NumeroSerie': rec[self.counter_header.index('NuméroSérie')], 'DateLimite': rec[self.counter_header.index('DateLimite')], 'CodeCompteur1': rec[self.counter_header.index('CodeCompteur1')], 'CodeCompteur2': rec[self.counter_header.index('CodeCompteur2')], 'DernierCompteur1': rec[self.counter_header.index('DernierCompteur1')], 'DernierCompteur2': rec[self.counter_header.index('DernierCompteur2')], } self.env['file.compteur'].create(vals)
def _get_deduction_lines(self): self.ensure_one() res = [] if not self.employee_id.address_home_id: raise MissingError("Private address of {} is not set. Set the private address in the employee form.".format(employee.name)) partner = self.employee_id.address_home_id results, total, amls = self.env["report.account.report_agedpartnerbalance"].with_context( partner_ids=partner)._get_partner_move_lines( ["receivable"], fields.Date.context_today(self), "posted", 30) remaining_wage = self.net_wage for aml in amls.get(partner.id, []): if aml["amount"] <= 0 or (self.struct_id.type_id.invoice_payment_scope == "overdue" and aml["period"] >= 6): continue residual_amount = min(aml["amount"], remaining_wage) deduction_vals = { "move_line_id": aml["line"].id, "amount": residual_amount, } res.append(deduction_vals) remaining_wage -= residual_amount if not remaining_wage: break return res
def get_facebook_access_token(self): self.execute() get_param = self.env['ir.config_parameter'].sudo().get_param base_url = 'http://localhost' # get_param('web.base.url', 'http://localhost') https_url = base_url.replace("http://", "https://") canvas_url = https_url + "/config-save-token" perms = get_param('omi.fb_permission', '').split(',') app_id = self.fb_app_id if app_id and canvas_url and perms: graph = facebook.GraphAPI(version=3.1) auth_url = "%s&response_type=token" % graph.get_auth_url( app_id, canvas_url, perms) return { 'type': 'ir.actions.act_url', 'url': auth_url, 'target': 'self', 'target_type': 'public', } raise MissingError(_('Require "Facebook App ID" and "Permissions"'))
def _get_report_values(self, docids, data=None): payment_obj = self.env["pos_pr.invoice.payment"] pos_session_id = data["form"]["pos_session_id"][0] grouping = data["form"]["grouping"] payments = payment_obj.search([("pos_session_id", "=", pos_session_id) ]) if not payments: raise MissingError( "There are no invoice payments related to this session.") if grouping == "method": groups = payments.mapped("payment_method_id") else: groups = payments.mapped("payment_group_id") return { "doc_ids": payments.ids, "doc_model": "pos_pr.invoice.payment", "docs": payments, "groups": groups, "grouping": grouping, "session": self.env["pos.session"].browse(pos_session_id), "getattr": getattr, }
def _get_partner_from_headers(cls, headers): partner_model = request.env["shopinvader.partner"] partner_email = headers.get("HTTP_PARTNER_EMAIL") backend = cls._get_shopinvader_backend_from_request() if partner_email: partner_domain = [ ("partner_email", "=", partner_email), ("backend_id", "=", backend.id), ] partner = partner_model.search(partner_domain) if len(partner) == 1: return partner.record_id else: _logger.warning("Wrong HTTP_PARTNER_EMAIL, header ignored") if len(partner) > 1: _logger.warning( "More than one shopinvader.partner found for domain:" " %s", partner_domain, ) # Could be because the email is not related to a partner or # because the partner is inactive raise MissingError("The given partner is not found!") return partner_model.browse([]).record_id
def init_postgis(cr): """ Initialize postgis Add PostGIS support to the database. PostGIS is a spatial database extender for PostgreSQL object-relational database. It adds support for geographic objects allowing location queries to be run in SQL. """ cr.execute(""" SELECT tablename FROM pg_tables WHERE tablename='spatial_ref_sys'; """) check = cr.fetchone() if check: return {} try: cr.execute(""" CREATE EXTENSION postgis; CREATE EXTENSION postgis_topology; """) except Exception: raise MissingError( _( "Error, can not automatically initialize spatial postgis" " support. Database user may have to be superuser and" " postgres/postgis extensions with their devel header have" " to be installed. If you do not want Odoo to connect with a" " super user you can manually prepare your database. To do" " this, open a client to your database using a super user and" " run:\n" "CREATE EXTENSION postgis;\n" "CREATE EXTENSION postgis_topology;\n" ) )
def _find_record( self, xmlid=None, res_model='ir.attachment', res_id=None, access_token=None, ): """ Find and return a record either using an xmlid either a model+id pair. This method is an helper for the ``/web/content`` and ``/web/image`` controllers and should not be used in other contextes. :param Optional[str] xmlid: xmlid of the record :param Optional[str] res_model: model of the record, ir.attachment by default. :param Optional[id] res_id: id of the record :param Optional[str] access_token: access token to use instead of the access rights and access rules. :returns: single record :raises MissingError: when no record was found. """ record = None if xmlid: record = self.env.ref(xmlid, False) elif res_id is not None and res_model in self.env: record = self.env[res_model].browse(res_id).exists() if not record: raise MissingError( f"No record found for xmlid={xmlid}, res_model={res_model}, id={res_id}" ) if record._name == 'ir.attachment': record = record.validate_access(access_token) return record
def validate_statement_header(self): # extract the data lines from the specified absolute path data = self.read_file(self.statement_file_path) # read the header attributes file_header = self.sanitize_row(data[0]).split(';') # validate header attributes for key in self.statement_header: if key not in file_header: raise MissingError("Missing attribute statement_header %s" % key) # remove the header data.pop(0) # store the data in object attribute self.statement_data = [ self.sanitize_row(row).split(';') for row in data ] record_id = self.env['file.releve'].search([]) if record_id: record_id.unlink() for rec in self.statement_data: vals = { 'TypeReleve': rec[1], 'TypeCompteur': rec[2], 'NumeroSerie': rec[3], 'NumContrat': rec[4], 'NumeroFacture': rec[5], 'NumeroReleve': rec[6], 'DateReleve': rec[7], 'DateDebutPeriode': rec[8], 'DateFinPeriode': rec[9], 'CompteurReleve': rec[10], 'Consommation': rec[11], 'VolumeDepassement': rec[12], } self.env['file.releve'].create(vals)
def _check_name_within_range(self): for move in self.filtered(lambda m: m.journal_id.is_honduras_invoice and m.state == "posted" and m.type == "out_invoice"): if not all([move.journal_id.cai, move.journal_id.prefix, move.journal_id.authorized_range_from, move.journal_id.authorized_range_to, move.journal_id.issue_limit_date]): raise MissingError("CAI, Prefix, Issue Limit Date, or Authorized Range fields are not set in Journal") if fields.Date.context_today(self) > move.journal_id.issue_limit_date: raise ValidationError("Invoice issue limit date of %s is exceeded!" % move.journal_id.issue_limit_date) prefix = move.journal_id.prefix padding = move.journal_id.sequence_id.padding lower_limit = prefix + str(move.journal_id.authorized_range_from).zfill(padding) upper_limit = prefix + str(move.journal_id.authorized_range_to).zfill(padding) current_number = int(move.name.replace(prefix, "")) if move.journal_id.authorized_range_from > current_number or current_number > move.journal_id.authorized_range_to: raise ValidationError("Invoice number %s is outside of range (%s, %s)" % (move.name, lower_limit, upper_limit)) move.cai = move.journal_id.cai move.authorized_range_from = lower_limit move.authorized_range_to = upper_limit move.issue_limit_date = move.journal_id.issue_limit_date warning_limit = prefix + str(move.journal_id.authorized_range_warning).zfill(padding) if move.name == warning_limit: self.env.ref("honduras_invoices.account_journal_mail_template_authorized_range_warn").send_mail(move.journal_id.id)
def _update_records(self, model_name, website): """ This method: - Find and update existing records. For each model, overwrite the fields that are defined in the template (except few cases such as active) but keep inherited models to not lose customizations. - Create new records from templates for those that didn't exist. - Remove the models that existed before but are not in the template anymore. See _theme_cleanup for more information. There is a special 'while' loop around the 'for' to be able queue back models at the end of the iteration when they have unmet dependencies. Hopefully the dependency will be found after all models have been processed, but if it's not the case an error message will be shown. :param model_name: string with the technical name of the model to handle (the name must be one of the keys present in ``_theme_model_names``) :param website: ``website`` model for which the records have to be updated :raise MissingError: if there is a missing dependency. """ self.ensure_one() remaining = self._get_module_data(model_name) last_len = -1 while (len(remaining) != last_len): last_len = len(remaining) for rec in remaining: rec_data = rec._convert_to_base_model(website) if not rec_data: _logger.info('Record queued: %s' % rec.display_name) continue find = rec.with_context(active_test=False).mapped( 'copy_ids').filtered(lambda m: m.website_id == website) # special case for attachment # if module B override attachment from dependence A, we update it if not find and model_name == 'ir.attachment': # In master, a unique constraint over (theme_template_id, website_id) # will be introduced, thus ensuring unicity of 'find' find = rec.copy_ids.search([('key', '=', rec.key), ('website_id', '=', website.id), ("original_id", "=", False)]) if find: imd = self.env['ir.model.data'].search([ ('model', '=', find._name), ('res_id', '=', find.id) ]) if imd and imd.noupdate: _logger.info('Noupdate set for %s (%s)' % (find, imd)) else: # at update, ignore active field if 'active' in rec_data: rec_data.pop('active') if model_name == 'ir.ui.view' and ( find.arch_updated or find.arch == rec_data['arch']): rec_data.pop('arch') find.update(rec_data) self._post_copy(rec, find) else: new_rec = self.env[model_name].create(rec_data) self._post_copy(rec, new_rec) remaining -= rec if len(remaining): error = 'Error - Remaining: %s' % remaining.mapped('display_name') _logger.error(error) raise MissingError(error) self._theme_cleanup(model_name, website)
def test_missing_error_http(self, **kwargs): raise MissingError("This is a missing http test")
def test_missing_error_json(self, **kwargs): raise MissingError("This is a missing rpc test")