def post(self): # OVERRIDE # On the validation of an invoice, send the different corrected fields to iap to improve the ocr algorithm. res = super(AccountMove, self).post() for record in self.filtered(lambda move: move.is_invoice()): if record.extract_state == 'waiting_validation': endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com' ) + '/iap/invoice_extract/validate' values = { 'total': record.get_validation('total'), 'subtotal': record.get_validation('subtotal'), 'global_taxes': record.get_validation('global_taxes'), 'global_taxes_amount': record.get_validation('global_taxes_amount'), 'date': record.get_validation('date'), 'due_date': record.get_validation('due_date'), 'invoice_id': record.get_validation('invoice_id'), 'partner': record.get_validation('supplier'), 'VAT_Number': record.get_validation('VAT_Number'), 'currency': record.get_validation('currency'), 'merged_lines': self.env.company.extract_single_line_per_tax, 'invoice_lines': record.get_validation('invoice_lines') } params = { 'document_id': record.extract_remote_id, 'version': CLIENT_OCR_VERSION, 'values': values } try: jsonrpc(endpoint, params=params) record.extract_state = 'done' except AccessError: pass # we don't need word data anymore, we can delete them self.mapped('extract_word_ids').unlink() return res
def _get_twitter_oauth_signature_from_iap(self, method, url, params, oauth_token_secret=''): params['oauth_nonce'] = str(params['oauth_nonce']) json_params = { 'method': method, 'url': url, 'params': params, 'oauth_token_secret': oauth_token_secret, 'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid') } social_iap_endpoint = self.env['ir.config_parameter'].sudo().get_param( 'social.social_iap_endpoint', self.env['social.media']._DEFAULT_SOCIAL_IAP_ENDPOINT) try: return jsonrpc(url_join(social_iap_endpoint, 'iap/social_twitter/get_signature'), params=json_params) except AccessError: return None
def _snailmail_estimate_from_documents(self, res_model, res_ids, partner_field=None): endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) docs = self.env[res_model].browse(res_ids) doc_list = [] for doc in docs: if partner_field: country_code = doc[partner_field].country_id.code else: country_code = doc.country_id.code val = { 'pages': 1, 'address': { 'country_code': country_code, }, } doc_list.append(val) params = { 'account_token': "", 'documents': doc_list, 'options': { 'color': self.env.user.company_id.snailmail_color, 'duplex': self.env.user.company_id.snailmail_duplex, 'currency_name': 'EUR', }, } req = jsonrpc(endpoint + '/iap/snailmail/1/estimate', params=params) return req['total_cost']
def _snailmail_print(self): """ get response { 'request_code': RESPONSE_OK, # because we receive 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ self.write({'state': 'pending'}) endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print') response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) for doc in response['request']['documents']: letter = self.browse(doc['letter_id']) record = self.env[doc['res_model']].browse(doc['res_id']) if doc.get('sent') and response['request_code'] == 200: if hasattr(record, '_message_log'): message = _('The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) record._message_log(body=message) letter.write({'info_msg': message, 'state': 'sent'}) else: # look for existing activities related to snailmail to update or create a new one. # TODO: in following versions, Add a link to a specifc activity on the letter note = _('An error occured when sending the document by post.<br>Error: %s' % \ self._get_error_message(doc['error'] if response['request_code'] == 200 else response['reason'])) domain = [ ('summary', 'ilike', '[SNAILMAIL]'), ('res_id', '=', letter.res_id), ('res_model_id', '=', self.env['ir.model']._get(letter.model).id), ('activity_type_id', '=', self.env.ref('mail.mail_activity_data_warning').id), ] MailActivity = self.env['mail.activity'] activity = MailActivity.search(domain, limit=1) activity_data = { 'activity_type_id': self.env.ref('mail.mail_activity_data_warning').id, 'summary': '[SNAILMAIL] ' + _('Post letter: an error occured.'), 'note': note, 'date_deadline': fields.Date.today() } if activity: activity.update(activity_data) else: activity_data.update({ 'user_id': letter.user_id.id, 'res_id': letter.res_id, 'res_model_id': self.env['ir.model']._get(letter.model).id, }) MailActivity.create(activity_data) letter.write({'info_msg': note, 'state': 'error'}) self.env.cr.commit()
def _snailmail_estimate(self): """ Send a request to estimate the cost of sending all the documents with the differents options. The JSON object sent is the one generated from self._snailmail_create() arguments sent: { "documents":[{ pages: int, res_id: int (client_side, optional), res_model: int (client_side, optional), address: { country_code: char (country name) } }], 'color': # color on the letter, 'duplex': # one/two side printing, } The answer of the server is the same JSON object with some additionnal fields: { "total_cost": integer, //The cost of sending ALL the documents body: JSON object (same as body param except new param 'cost' in each documents) } """ endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('estimate') req = jsonrpc(endpoint + '/iap/snailmail/1/estimate', params=params) return req['total_cost']
def _snailmail_estimate(self): """ Send a request to estimate the cost of sending all the documents with the differents options. The JSON object sent is the one generated from self._snailmail_create() arguments sent: { "documents":[{ pages: int, res_id: int (client_side, optional), res_model: int (client_side, optional), address: { country_code: char (country name) } }], 'color': # color on the letter, 'duplex': # one/two side printing, } The answer of the server is the same JSON object with some additionnal fields: { "total_cost": integer, //The cost of sending ALL the documents body: JSON object (same as body param except new param 'cost' in each documents) } """ endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('estimate') req = jsonrpc(endpoint + '/iap/snailmail/1/estimate', params=params) # The cost is sent in hunderth of eurocents, we change it to euros and then convert it to the company currency cost = int(req['total_cost'])/10000.0 currency_eur = self.env.ref('base.EUR') return currency_eur._convert(cost, self[0].company_id.currency_id, self[0].company_id, fields.Datetime.now())
def _snailmail_print_valid_address(self): """ get response { 'request_code': RESPONSE_OK, # because we receive 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print') response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) for doc in response['request']['documents']: if doc.get('sent') and response['request_code'] == 200: note = _('The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) letter_data = {'info_msg': note, 'state': 'sent', 'error_code': False} else: error = doc['error'] if response['request_code'] == 200 else response['reason'] note = _('An error occured when sending the document by post.<br>Error: %s' % self._get_error_message(error)) letter_data = { 'info_msg': note, 'state': 'error', 'error_code': error if error in ERROR_CODES else 'UNKNOWN_ERROR' } letter = self.browse(doc['letter_id']) letter.write(letter_data) self.send_snailmail_update()
def convert(self, binary, mimetype=None, filename=None, export="binary", doctype="document", format="pdf"): """ Converts a binary value to the given format. :param binary: The binary value. :param mimetype: The mimetype of the binary value. :param filename: The filename of the binary value. :param export: The output format (binary, file, base64). :param doctype: Specify the document type (document, graphics, presentation, spreadsheet). :param format: Specify the output format for the document. :return: Returns the output depending on the given format. :raises ValueError: The file extension could not be determined or the format is invalid. """ params = { 'format': format, 'doctype': doctype, 'mimetype': mimetype, 'filename': filename, 'content': base64.b64encode(binary), } result = jsonrpc(self.endpoint(CONVERTER_ENDPOINT_CONVERT), params=self.payload(params)) if export == 'base64': return result if export == 'file': output = io.BytesIO() output.write(base64.b64decode(result)) output.close() return output else: return base64.b64decode(result)
def _snailmail_estimate_from_documents(self, res_model, res_ids, partner_field=None): endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) docs = self.env[res_model].browse(res_ids) doc_list = [] for doc in docs: if partner_field: country_code = doc[partner_field].country_id.code else: country_code = doc.country_id.code val = { 'pages': 1, 'address': { 'country_code': country_code, }, } doc_list.append(val) params = { 'account_token': "", 'documents': doc_list, 'options': { 'color': self.env.company_id.snailmail_color, 'duplex': self.env.company_id.snailmail_duplex, 'currency_name': 'EUR', }, } req = jsonrpc(endpoint + '/iap/snailmail/1/estimate', params=params) return req['total_cost']
def message_post(self, **kwargs): """When a message is posted on an account.invoice, send the attachment to iap-ocr if the res_config is on "auto_send" and if this is the first attachment.""" res = super(AccountInvoice, self).message_post(**kwargs) if self.env.user.company_id.extract_show_ocr_option_selection == 'auto_send': account_token = self.env['iap.account'].get('invoice_ocr') for record in self: if record.type in ["out_invoice", "out_refund"]: return res if record.extract_state == "no_extract_requested": attachments = res.attachment_ids if attachments: endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com') + '/iap/invoice_extract/parse' params = { 'account_token': account_token.account_token, 'version': CLIENT_OCR_VERSION, 'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), 'documents': [x.datas.decode('utf-8') for x in attachments], 'file_names': [x.datas_fname for x in attachments], } try: result = jsonrpc(endpoint, params=params) if result[1] == "Not enough credits": record.extract_state = 'not_enough_credit' elif result[0] == -1: record.extract_state = 'error_status' else: record.extract_remoteid = result[0] record.extract_state = 'waiting_extraction' except AccessError: record.extract_state = 'error_status' for record in self: record._compute_show_resend_button() return res
def retry_ocr(self): """Retry to contact iap to submit the first attachment in the chatter""" if self.env.user.company_id.extract_show_ocr_option_selection == 'no_send': return False attachments = self.message_main_attachment_id if attachments and attachments.exists() and self.extract_state in ['no_extract_requested', 'not_enough_credit', 'error_status', 'module_not_up_to_date']: account_token = self.env['iap.account'].get('invoice_ocr') endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com') + '/iap/invoice_extract/parse' params = { 'account_token': account_token.account_token, 'version': CLIENT_OCR_VERSION, 'dbuuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), 'documents': [x.datas.decode('utf-8') for x in attachments], 'file_names': [x.datas_fname for x in attachments], } try: result = jsonrpc(endpoint, params=params) if result[1] == "Not enough credits": self.extract_state = 'not_enough_credit' elif result[0] == -1: self.extract_state = 'error_status' _logger.warning('There was an issue while doing the OCR operation on this file. Error: -1') else: self.extract_state = 'waiting_extraction' self.extract_remoteid = result[0] except AccessError: self.extract_state = 'error_status'
def invoice_validate(self): """On the validation of an invoice, send the differents corrected fields to iap to improve the ocr algorithm""" res = super(AccountInvoice, self).invoice_validate() for record in self: if record.type in ["out_invoice", "out_refund"]: return if record.extract_state == 'waiting_validation': endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com') + '/iap/invoice_extract/validate' values = { 'total': record.get_validation('total'), 'date': record.get_validation('date'), 'due_date': record.get_validation('due_date'), 'invoice_id': record.get_validation('invoice_id'), 'partner': record.get_validation('supplier'), 'VAT_Number': record.get_validation('VAT_Number'), 'currency': record.get_validation('currency') } params = { 'document_id': record.extract_remoteid, 'version': CLIENT_OCR_VERSION, 'values': values } try: _logger.warning(params) #TODO remove result = jsonrpc(endpoint, params=params) record.extract_state = 'done' except AccessError: pass #we don't need word data anymore, we can delete them self.extract_word_ids.unlink() return res
def _create_supplier_from_vat(self, vat_number_ocr): url = '%s/check_vat' % PARTNER_REMOTE_URL params = { 'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), 'vat': vat_number_ocr, } try: response = jsonrpc(url=url, params=params) except Exception as exception: _logger.error('Check VAT error: %s' % str(exception)) return False if response and response.get('name'): country_id = self.env['res.country'].search([ ('code', '=', response.pop('country_code', '')) ]) values = { field: response.get(field, None) for field in ['name', 'vat', 'street', 'city', 'zip'] } values.update({ 'is_company': True, 'country_id': country_id and country_id.id, }) new_partner = self.env["res.partner"].with_context( clean_context(self.env.context)).create(values) return new_partner return False
def _snailmail_print(self): """ get response { 'request_code': RESPONSE_OK, # because we receive 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ self.write({'state': 'pending'}) endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print') response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) for doc in response['request']['documents']: letter = self.browse(doc['letter_id']) record = self.env[doc['res_model']].browse(doc['res_id']) if doc.get('sent') and response['request_code'] == 200: if hasattr(record, '_message_log'): message = _('The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) record._message_log(body=message) letter.write({'info_msg': message, 'state': 'sent'}) else: # look for existing activities related to snailmail to update or create a new one. # TODO: in following versions, Add a link to a specifc activity on the letter note = _('An error occured when sending the document by post.<br>Error: %s <br>Go to \'Configuration > Management > Snailmail Letters\' to see all letters awaiting dispatch to Snailmail.' % \ self._get_error_message(doc['error'] if response['request_code'] == 200 else response['reason'])) domain = [ ('summary', 'ilike', '[SNAILMAIL]'), ('res_id', '=', letter.res_id), ('res_model_id', '=', self.env['ir.model']._get(letter.model).id), ('activity_type_id', '=', self.env.ref('mail.mail_activity_data_warning').id), ] activity = letter.activity_id activity_data = { 'activity_type_id': self.env.ref('mail.mail_activity_data_warning').id, 'summary': '[SNAILMAIL] ' + _('Post letter: an error occured.'), 'note': note, 'date_deadline': fields.Date.today() } if activity: activity.update(activity_data) else: activity_data.update({ 'user_id': letter.user_id.id, 'res_id': letter.res_id, 'res_model_id': self.env['ir.model']._get(letter.model).id, }) activity = self.env['mail.activity'].create(activity_data) letter.write({'activity_id': activity.id}) letter.write({'info_msg': note, 'state': 'error'}) self.env.cr.commit()
def _rpc_remote_api(self, action, params, timeout=15): if self.env.registry.in_test_mode(): return False, 'Insufficient Credit' url = '%s/%s' % (self.get_endpoint(), action) account = self.env['iap.account'].get('partner_autocomplete') params.update({ 'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), 'account_token': account.account_token, 'country_code': self.env.user.company_id.country_id.code, 'zip': self.env.user.company_id.zip, }) try: return jsonrpc(url=url, params=params, timeout=timeout), False except (ConnectionError, HTTPError, exceptions.AccessError) as exception: _logger.error('Autocomplete API error: %s' % str(exception)) return False, str(exception) except InsufficientCreditError as exception: _logger.warning( 'Insufficient Credits for Autocomplete Service: %s' % str(exception)) return False, 'Insufficient Credit'
def _perform_reveal_service(self, server_payload): result = False account_token = self.env['iap.account'].get('reveal') endpoint = self.env['ir.config_parameter'].sudo().get_param( 'reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/reveal' params = { 'account_token': account_token.account_token, 'data': server_payload } result = jsonrpc(endpoint, params=params, timeout=300) for res in result.get('reveal_data', []): if not res.get('not_found'): lead = self._create_lead_from_response(res) self.env['crm.reveal.view'].search([('reveal_ip', '=', res['ip'])]).unlink() else: self.env['crm.reveal.view'].search([ ('reveal_ip', '=', res['ip']) ]).write({'reveal_state': 'not_found'}) if result.get('credit_error'): self.env['crm.iap.lead.helpers'].notify_no_more_credit( 'reveal', self._name, 'reveal.already_notified') return False else: self.env['ir.config_parameter'].sudo().set_param( 'reveal.already_notified', False) return True
def _perform_request(self): """ This will perform the request and create the corresponding leads. The user will be notified if he hasn't enough credits. """ server_payload = self._prepare_iap_payload() reveal_account = self.env['iap.account'].get('reveal') dbuuid = self.env['ir.config_parameter'].sudo().get_param( 'database.uuid') endpoint = self.env['ir.config_parameter'].sudo().get_param( 'reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/lead_mining_request' params = { 'account_token': reveal_account.account_token, 'dbuuid': dbuuid, 'data': server_payload } try: response = jsonrpc(endpoint, params=params, timeout=300) return response['data'] except InsufficientCreditError as e: self.error = 'Insufficient credits. Recharge your account and retry.' self.state = 'error' self._cr.commit() raise e
def _l10n_in_edi_connect_to_server(self, company, url_path, params): user_token = self.env["iap.account"].get("l10n_in_edi") params.update({ "account_token": user_token.account_token, "dbuuid": self.env["ir.config_parameter"].sudo().get_param("database.uuid"), "username": company.sudo().l10n_in_edi_username, "gstin": company.vat, }) if company.sudo().l10n_in_edi_production_env: default_endpoint = DEFAULT_IAP_ENDPOINT else: default_endpoint = DEFAULT_IAP_TEST_ENDPOINT endpoint = self.env["ir.config_parameter"].sudo().get_param("l10n_in_edi.endpoint", default_endpoint) url = "%s%s" % (endpoint, url_path) try: return jsonrpc(url, params=params, timeout=25) except AccessError as e: _logger.warning("Connection error: %s", e.args[0]) return { "error": [{ "code": "404", "message": _("Unable to connect to the online E-invoice service." "The web service may be temporary down. Please try again in a moment.") }] }
def _rpc_remote_api(self, action, params=None, timeout=15): url = '%s/%s' % ('http://127.0.0.1:5001', action) try: return jsonrpc(url=url, params=params, timeout=timeout), False except (ConnectionError, HTTPError) as exception: _logger.error('API error: %s' % str(exception)) return False, str(exception)
def _firebase_send_message_from_iap(self, data, visitors): social_iap_endpoint = self.env['ir.config_parameter'].sudo().get_param( 'social.social_iap_endpoint', self.env['social.media']._DEFAULT_SOCIAL_IAP_ENDPOINT ) batch_size = 100 tokens = visitors.mapped('push_token') data.update({'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid')}) for i in range(int((len(visitors) / batch_size)) + 1): tokens_batch = tokens[(i * batch_size):((i + 1) * batch_size)] batch_data = dict(data) batch_data['tokens'] = tokens_batch jsonrpc(url_join(social_iap_endpoint, '/iap/social_push_notifications/firebase_send_message'), params=batch_data) return []
def _send_notification_to_partners(self, pids, message, msg_vals): """ Send the notification to a list of partners :param pids: list of partners :param message: current mail.message record :param msg_vals: dict values for current notification """ if pids: receiver_ids = self.env['res.partner'].sudo().search([ ('id', 'in', list(pids)), ('ocn_token', '!=', False) ]) if receiver_ids: endpoint = self.env['res.config.settings']._get_endpoint() chunks = self._ocn_prepare_payload(receiver_ids, message, msg_vals) for chunk in chunks: jsonrpc(endpoint + '/iap/ocn/send', params=chunk)
def _contact_iap(self, local_endpoint, params): account = self.env['iap.account'].get('reveal') dbuuid = self.env['ir.config_parameter'].sudo().get_param( 'database.uuid') params['account_token'] = account.account_token params['dbuuid'] = dbuuid return iap.jsonrpc(self._DEFAULT_ENDPOINT + local_endpoint, params=params, timeout=300)
def _notify_recipients(self, rdata, record, msg_vals, **kwargs): """ We want to send a Cloud notification for every mentions of a partner and every direct message. We have to take into account the risk of duplicated notifications in case of a mention in a channel of `chat` type. """ super(MailMessage, self)._notify_recipients(rdata, record, msg_vals, **kwargs) notif_pids = [r['id'] for r in rdata['partners']] chat_cids = [r['id'] for r in rdata['channels'] if r['type'] == 'chat'] if not notif_pids and not chat_cids: return self_sudo = self.sudo() msg_type = msg_vals.get('message_type') or self_sudo.message_type if msg_type == 'comment': # Create Cloud messages for needactions, but ignore the needaction if it is a result # of a mention in a chat. In this case the previously created Cloud message is enough. if chat_cids: channel_partner_ids = self.env['mail.channel'].sudo().search([ ('id', 'in', chat_cids), ]).mapped("channel_partner_ids").ids else: channel_partner_ids = [] pids = (set(notif_pids) | set(channel_partner_ids)) - set( self_sudo.author_id.ids) if pids: receiver_ids = self.env['res.partner'].sudo().search([ ('id', 'in', list(pids)) ]) identities = receiver_ids.filtered( lambda receiver: receiver.ocn_token).mapped('ocn_token') if identities: endpoint = self.env['res.config.settings']._get_endpoint() params = { 'ocn_tokens': identities, 'data': self._ocn_prepare_payload(self) } jsonrpc(endpoint + '/iap/ocn/send', params=params)
def action_snailmail_print(self): """ get response { 'request_code': RESPONSE_OK, # 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ self.ensure_one() endpoint = self.env['ir.config_parameter'].sudo().get_param( 'snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print', batch=True) response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) error = False doc = response['request']['documents'][0] record = self.env[self.model].browse(self.res_id) if doc.get('sent') and response['request_code'] == 200: if hasattr(record, '_message_log'): message = _( 'The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) record._message_log(body=message) else: activity_data = { 'res_id': self.res_id, 'res_model_id': self.env['ir.model']._get(self.model).id, 'activity_type_id': self.env.ref('snailmail.mail_activity_data_snailmail').id, 'summary': _('Post letter: an error occured.'), 'note': _('An error occured when sending the document by post.<br>Error: %s' % \ self._get_error_message(doc['error'] if response['request_code'] == 200 else response['reason'])), 'user_id': self.env.user.id, } self.env['mail.activity'].create(activity_data) error = True if not error: notification = _('Post letter: document sent.') else: notification = _( 'Post letter: an error occured. Please check the document for more information.' ) # as we interact with the exterior world, we commit self.env.cr.commit() self._update_company() return { 'error': error, 'message': notification, }
def register_device(self, device_key, device_name): if self.env['ir.config_parameter'].sudo().get_param('ocn.ocn_push_notification', False): values = { 'ocn_uuid': self._get_ocn_uuid(), 'user_name': self.env.user.partner_id.name, 'user_login': self.env.user.login, 'device_name': device_name, 'device_key': device_key } result = jsonrpc(self._get_endpoint() + '/iap/ocn/register_device', params=values) if result: self.env.user.partner_id.ocn_token = result return False
def _snailmail_print(self): """ get response { 'request_code': RESPONSE_OK, # because we receive 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ self.write({'state': 'pending'}) endpoint = self.env['ir.config_parameter'].sudo().get_param( 'snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print') response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) for doc in response['request']['documents']: letter = self.browse(doc['letter_id']) record = self.env[doc['res_model']].browse(doc['res_id']) if doc.get('sent') and response['request_code'] == 200: if hasattr(record, '_message_log'): message = _( 'The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) record._message_log(body=message) letter.write({'info_msg': message, 'state': 'sent'}) else: note = _('An error occured when sending the document by post.<br>Error: %s' % \ self._get_error_message(doc['error'] if response['request_code'] == 200 else response['reason'])) activity_data = { 'res_id': letter.res_id, 'res_model_id': self.env['ir.model']._get(letter.model).id, 'activity_type_id': self.env.ref('snailmail.mail_activity_data_snailmail').id, 'summary': _('Post letter: an error occured.'), 'note': note, 'user_id': letter.user_id.id, } self.env['mail.activity'].create(activity_data) letter.write({'info_msg': note}) self.env.cr.commit()
def retry_ocr(self): """Retry to contact iap to submit the first attachment in the chatter""" if self.env.company.extract_show_ocr_option_selection == 'no_send': return False attachments = self.message_main_attachment_id if attachments and attachments.exists() and self.extract_state in [ 'no_extract_requested', 'not_enough_credit', 'error_status', 'module_not_up_to_date' ]: account_token = self.env['iap.account'].get('invoice_ocr') endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com') + '/iap/invoice_extract/parse' user_infos = { 'user_company_VAT': self.company_id.vat, 'user_company_name': self.company_id.name, 'user_company_country_code': self.company_id.country_id.code, 'user_lang': self.env.user.lang, 'user_email': self.env.user.email, } params = { 'account_token': account_token.account_token, 'version': CLIENT_OCR_VERSION, 'dbuuid': self.env['ir.config_parameter'].sudo().get_param( 'database.uuid'), 'documents': [x.datas.decode('utf-8') for x in attachments], 'file_names': [x.name for x in attachments], 'user_infos': user_infos, } try: result = jsonrpc(endpoint, params=params) self.extract_status_code = result['status_code'] if result['status_code'] == SUCCESS: self.extract_state = 'waiting_extraction' self.extract_remote_id = result['document_id'] elif result['status_code'] == ERROR_NOT_ENOUGH_CREDIT: self.extract_state = 'not_enough_credit' else: self.extract_state = 'error_status' _logger.warning( 'There was an issue while doing the OCR operation on this file. Error: -1' ) except AccessError: self.extract_state = 'error_status' self.extract_status_code = ERROR_NO_CONNECTION
def register_device(self, device_key, device_name): values = { 'ocn_uuid': self._get_ocn_uuid(), 'user_name': self.env.user.partner_id.name, 'user_login': self.env.user.login, 'device_name': device_name, 'device_key': device_key, } result = jsonrpc(self._get_endpoint() + '/iap/ocn/register_device', params=values) if result: self.env.user.partner_id.ocn_token = result return result return False
def action_snailmail_print(self): """ get response { 'request_code': RESPONSE_OK, # 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ self.ensure_one() endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print', batch=True) response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) error = False doc = response['request']['documents'][0] record = self.env[self.model].browse(self.res_id) if doc.get('sent') and response['request_code'] == 200: if hasattr(record, '_message_log'): message = _('The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) record._message_log(body=message) else: activity_data = { 'res_id': self.res_id, 'res_model_id': self.env['ir.model']._get(self.model).id, 'activity_type_id': self.env.ref('snailmail.mail_activity_data_snailmail').id, 'summary': _('Post letter: an error occured.'), 'note': _('An error occured when sending the document by post.<br>Error: %s' % \ self._get_error_message(doc['error'] if response['request_code'] == 200 else response['reason'])), 'user_id': self.env.user.id, } self.env['mail.activity'].create(activity_data) error = True if not error: notification = _('Post letter: document sent.') else: notification = _('Post letter: an error occured. Please check the document for more information.') # as we interact with the exterior world, we commit self.env.cr.commit() self._update_company() return { 'error': error, 'message': notification, }
def fetch_book_data(self): self.ensure_one() if not self.isbn: raise UserError("Please add ISBN number") user_token = self.env['iap.account'].get('book_isbn') params = { 'account_token': user_token.account_token, 'isbn_number': self.isbn } service_endpoint = 'http://localhost:8070' result = jsonrpc(service_endpoint + '/get_book_data', params=params) if result.get('status') == 'found': self.write(self.process_result(result['data'])) return True
def create(self, vals): ir_params = self.env['ir.config_parameter'].sudo() if vals.get('ocn_push_notification') and not ir_params.get_param('odoo_ocn.project_id'): # Every time when user change setting, we need to validate ocn service params = { 'ocnuuid': self._get_ocn_uuid(), 'server_version': odoo.release.version, 'db': self.env.cr.dbname, 'company_name': self.env.user.company_id.name, 'url': ir_params.get_param('web.base.url') } # Register instance to ocn service. Unique with ocn.uuid project_id = jsonrpc(self._get_endpoint() + '/iap/ocn/enable_service', params=params) # Storing project id for generate token ir_params.set_param('odoo_ocn.project_id', project_id) return super(ResConfigSettings, self).create(vals)
def get_fcm_project_id(self): ir_params_sudo = self.env['ir.config_parameter'].sudo() project_id = ir_params_sudo.get_param('odoo_ocn.project_id') if not project_id: params = { 'ocnuuid': self._get_ocn_uuid(), 'server_version': odoo.release.version, 'db': self.env.cr.dbname, 'company_name': self.env.company.name, 'url': ir_params_sudo.get_param('web.base.url') } # Register instance to ocn service. Unique with ocn.uuid project_id = jsonrpc(self._get_endpoint() + '/iap/ocn/enable_service', params=params) # Storing project id for generate token ir_params_sudo.set_param('odoo_ocn.project_id', project_id) return project_id
def _rpc_remote_api(self, action, params, timeout=15): if self.env.registry.in_test_mode() : return False, 'Insufficient Credit' url = '%s/%s' % (self.get_endpoint(), action) account = self.env['iap.account'].get('partner_autocomplete') params.update({ 'db_uuid': self.env['ir.config_parameter'].sudo().get_param('database.uuid'), 'account_token': account.account_token, 'country_code': self.env.company.country_id.code, 'zip': self.env.company.zip, }) try: return jsonrpc(url=url, params=params, timeout=timeout), False except (ConnectionError, HTTPError, exceptions.AccessError) as exception: _logger.error('Autocomplete API error: %s' % str(exception)) return False, str(exception) except InsufficientCreditError as exception: _logger.warning('Insufficient Credits for Autocomplete Service: %s' % str(exception)) return False, 'Insufficient Credit'
def _snailmail_print(self): """ get response { 'request_code': RESPONSE_OK, # because we receive 200 if good or fail 'total_cost': total_cost, 'credit_error': credit_error, 'request': { 'documents': documents, 'options': options } } } """ self.write({'state': 'pending'}) endpoint = self.env['ir.config_parameter'].sudo().get_param('snailmail.endpoint', DEFAULT_ENDPOINT) params = self._snailmail_create('print') response = jsonrpc(endpoint + PRINT_ENDPOINT, params=params) for doc in response['request']['documents']: letter = self.browse(doc['letter_id']) record = self.env[doc['res_model']].browse(doc['res_id']) if doc.get('sent') and response['request_code'] == 200: if hasattr(record, '_message_log'): message = _('The document was correctly sent by post.<br>The tracking id is %s' % doc['send_id']) record._message_log(body=message) letter.write({'info_msg': message, 'state': 'sent'}) else: note = _('An error occured when sending the document by post.<br>Error: %s' % \ self._get_error_message(doc['error'] if response['request_code'] == 200 else response['reason'])) activity_data = { 'res_id': letter.res_id, 'res_model_id': self.env['ir.model']._get(letter.model).id, 'activity_type_id': self.env.ref('snailmail.mail_activity_data_snailmail').id, 'summary': _('Post letter: an error occured.'), 'note': note, 'user_id': letter.user_id.id, } self.env['mail.activity'].create(activity_data) letter.write({'info_msg': note}) self.env.cr.commit()
def _perform_request(self): """ This will perform the request and create the corresponding leads. The user will be notified if he hasn't enough credits. """ server_payload = self._prepare_iap_payload() reveal_account = self.env['iap.account'].get('reveal') dbuuid = self.env['ir.config_parameter'].sudo().get_param('database.uuid') endpoint = self.env['ir.config_parameter'].sudo().get_param('reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/lead_mining_request' params = { 'account_token': reveal_account.account_token, 'dbuuid': dbuuid, 'data': server_payload } try: response = jsonrpc(endpoint, params=params, timeout=300) return response['data'] except InsufficientCreditError as e: self.error = 'Insufficient credits. Recharge your account and retry.' self.state = 'error' self._cr.commit() raise e
def check_status(self): """contact iap to get the actual status of the ocr request""" for record in self: if record.extract_state not in ["waiting_extraction", "extract_not_ready"]: continue endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com') + '/iap/invoice_extract/get_result' params = { 'version': CLIENT_OCR_VERSION, 'document_id': record.extract_remoteid } result = jsonrpc(endpoint, params=params) if result == "Not ready": record.extract_state = "extract_not_ready" elif result == "An error occured": record.extract_state = "error_status" else: record.extract_state = "waiting_validation" self.extract_word_ids.unlink() if "supplier" in result: #be sure to execut supplier in first as it set some other values in invoice self.set_field_with_text("supplier", result["supplier"]["selected_text"][0]) for feature, value in result.items(): if feature != "supplier": self.set_field_with_text(feature, value["selected_text"][0]) data = [] for word in value["words"]: data.append((0, 0, { "field": feature, "selected_status": 1 if value["selected_text"] == word else 0, "word_text": word[0], "word_page": word[1], "word_box_midX": word[2][0], "word_box_midY": word[2][1], "word_box_width": word[2][2], "word_box_height": word[2][3], "word_box_angle": word[2][4], })) self.write({'extract_word_ids': data})
def _perform_reveal_service(self, server_payload): result = False account_token = self.env['iap.account'].get('reveal') endpoint = self.env['ir.config_parameter'].sudo().get_param('reveal.endpoint', DEFAULT_ENDPOINT) + '/iap/clearbit/1/reveal' params = { 'account_token': account_token.account_token, 'data': server_payload } result = jsonrpc(endpoint, params=params) for res in result.get('reveal_data', []): if not res.get('not_found'): lead = self._create_lead_from_response(res) self.env['crm.reveal.view'].search([('reveal_ip', '=', res['ip'])]).unlink() else: self.env['crm.reveal.view'].search([('reveal_ip', '=', res['ip'])]).write({ 'reveal_state': 'not_found' }) if result.get('credit_error'): self._notify_no_more_credit() return False else: self.env['ir.config_parameter'].sudo().set_param('reveal.already_notified', False) return True
def _check_status(self): self.ensure_one() endpoint = self.env['ir.config_parameter'].sudo().get_param( 'account_invoice_extract_endpoint', 'https://iap-extract.odoo.com') + '/iap/invoice_extract/get_result' params = { 'version': CLIENT_OCR_VERSION, 'document_id': self.extract_remote_id } result = jsonrpc(endpoint, params=params) self.extract_status_code = result['status_code'] if result['status_code'] == SUCCESS: self.extract_state = "waiting_validation" ocr_results = result['results'][0] self.extract_word_ids.unlink() # We still want to save all other fields when there is a duplicate vendor reference try: # Savepoint so the transactions don't go through if the save raises an exception with self.env.cr.savepoint(): self._save_form(ocr_results) # Retry saving without the ref, then set the error status to show the user a warning except ValidationError as e: self._save_form(ocr_results, no_ref=True) self.extract_status_code = WARNING_DUPLICATE_VENDOR_REFERENCE self.duplicated_vendor_ref = ocr_results['invoice_id'][ 'selected_value'][ 'content'] if 'invoice_id' in ocr_results else "" fields_with_boxes = [ 'supplier', 'date', 'due_date', 'invoice_id', 'currency', 'VAT_Number' ] for field in fields_with_boxes: if field in ocr_results: value = ocr_results[field] data = [] for word in value["words"]: data.append((0, 0, { "field": field, "selected_status": 1 if value["selected_value"] == word else 0, "word_text": word['content'], "word_page": word['page'], "word_box_midX": word['coords'][0], "word_box_midY": word['coords'][1], "word_box_width": word['coords'][2], "word_box_height": word['coords'][3], "word_box_angle": word['coords'][4], })) self.write({'extract_word_ids': data}) elif result['status_code'] == NOT_READY: self.extract_state = 'extract_not_ready' else: self.extract_state = 'error_status'