forked from mollie/mollie-odoo
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[ADD] added new module for v14 to manage mollie terminal with Odoo pos
- Loading branch information
Showing
36 changed files
with
1,075 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
from . import models | ||
from . import wizard | ||
from . import controllers |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
{ | ||
'name': 'Mollie Pos Terminal', | ||
'version': '14.0.0.0', | ||
'description': '', | ||
'summary': 'Connect your pos with mollie terminal', | ||
'author': 'Mollie', | ||
'maintainer': 'Applix', | ||
'license': 'LGPL-3', | ||
'category': '', | ||
'depends': [ | ||
'point_of_sale', | ||
], | ||
'data': [ | ||
'security/ir.model.access.csv', | ||
'views/assets.xml', | ||
'views/mollie_pos_terminal_views.xml', | ||
'views/mollie_pos_terminal_payments_views.xml', | ||
'views/res_config_settings_views.xml', | ||
'views/pos_payment_method_views.xml', | ||
'wizard/mollie_sync_terminal.xml', | ||
], | ||
'qweb': [ | ||
'static/src/views/*.xml', | ||
], | ||
'images': [ | ||
'static/description/cover.png', | ||
], | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
# coding: utf-8 | ||
from . import main |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
# coding: utf-8 | ||
import logging | ||
import json | ||
from odoo import fields, http | ||
from odoo.http import request | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class PosMollieController(http.Controller): | ||
|
||
@http.route('/pos_mollie/webhook', type='http', methods=['POST'], auth='public', csrf=False) | ||
def webhook(self, **post): | ||
if not post.get('id'): | ||
return | ||
request.env['mollie.pos.terminal.payments']._mollie_process_webhook(post) | ||
return "" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
from . import res_company | ||
from . import res_config_settings | ||
from . import pos_payment_method | ||
from . import mollie_pos_terminal | ||
from . import mollie_pos_terminal_payments |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
import logging | ||
import requests | ||
from werkzeug import urls | ||
|
||
from odoo import fields, models, _ | ||
from odoo.exceptions import ValidationError | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class MolliePosTerminal(models.Model): | ||
_name = 'mollie.pos.terminal' | ||
_description = 'Mollie Pos Terminal' | ||
|
||
name = fields.Char() | ||
terminal_id = fields.Char('Terminal ID') | ||
profile_id = fields.Char('Profile ID') | ||
serial_number = fields.Char('Serial Number') | ||
status = fields.Selection([ | ||
('pending', 'Pending'), | ||
('active', 'Active'), | ||
('inactive', 'Inactive') | ||
]) | ||
currency_id = fields.Many2one('res.currency', string='Currency') | ||
company_id = fields.Many2one('res.company', required=True, default=lambda self: self.env.company) | ||
|
||
def _sync_mollie_terminals(self): | ||
existing_terminals = self.search([]) | ||
terminals_data = self._api_get_terminals() # TODO: manage pager for 250+ terminals | ||
|
||
if not terminals_data.get('count'): | ||
return | ||
|
||
for terminal in terminals_data['_embedded']['terminals']: | ||
terminal_found = existing_terminals.filtered(lambda x: x.terminal_id == terminal['id']) | ||
currency = self.env['res.currency'].search([('name', '=', terminal['currency'])]) | ||
|
||
if not currency: | ||
raise ValidationError(_('Currency ') + terminal['currency'] + _(' is not active. Please activate it first.')) | ||
|
||
terminal_data = { | ||
'name': terminal['description'], | ||
'terminal_id': terminal['id'], | ||
'profile_id': terminal['profileId'], | ||
'serial_number': terminal['serialNumber'], | ||
'status': terminal['status'], | ||
'currency_id': currency.id | ||
} | ||
if terminal_found: | ||
terminal_found.write(terminal_data) | ||
else: | ||
self.create(terminal_data) | ||
|
||
# ================= | ||
# API CALLS METHODS | ||
# ================= | ||
|
||
def _api_get_terminals(self): | ||
""" Fetch terminals data from mollie api """ | ||
return self._mollie_api_call('/terminals', method='GET') | ||
|
||
def _api_make_payment_request(self, data): | ||
payment_payload = self._prepare_payment_payload(data) | ||
result = self._mollie_api_call('/payments', data=payment_payload, method='POST', silent=True) | ||
self.env['mollie.pos.terminal.payments']._create_mollie_payment_request(result, {**data, 'terminal_id': self.id}) | ||
return result | ||
|
||
def _api_cancel_mollie_payment(self, transaction_id): | ||
return self.sudo()._mollie_api_call(f'/payments/{transaction_id}', method='DELETE', silent=True) | ||
|
||
def _api_get_mollie_payment_status(self, transaction_id): | ||
return self.sudo()._mollie_api_call(f'/payments/{transaction_id}', method='GET', silent=True) | ||
|
||
def _prepare_payment_payload(self, data): | ||
base_url = self.get_base_url() | ||
webhook_url = urls.url_join(base_url, '/pos_mollie/webhook/') | ||
return { | ||
"amount": { | ||
"currency": data['curruncy'], | ||
"value": f"{data['amount']:.2f}" | ||
}, | ||
"description": data['description'], | ||
"webhookUrl": webhook_url, | ||
"redirectUrl": webhook_url, | ||
"method": "pointofsale", | ||
"terminalId": self.terminal_id, | ||
"metadata": { | ||
"mollie_uid": data['mollie_uid'], | ||
"order_id": data['order_id'], | ||
} | ||
} | ||
|
||
# ===================== | ||
# GENERIC TOOLS METHODS | ||
# ===================== | ||
|
||
def _mollie_api_call(self, endpoint, data=None, method='POST', silent=False): | ||
company = self.company_id or self.env.company | ||
|
||
headers = { | ||
'content-type': 'application/json', | ||
"Authorization": f'Bearer {company.mollie_terminal_api_key}', | ||
} | ||
|
||
endpoint = f'/v2/{endpoint.strip("/")}' | ||
url = urls.url_join('https://api.mollie.com/', endpoint) | ||
|
||
_logger.info('Mollie POS Terminal CALL on: %s', url) | ||
|
||
try: | ||
response = requests.request(method, url, json=data, headers=headers, timeout=60) | ||
response.raise_for_status() | ||
except requests.exceptions.HTTPError: | ||
error_details = response.json() | ||
_logger.exception("MOLLIE-POS-ERROR \n %s", error_details) | ||
if silent: | ||
return error_details | ||
else: | ||
raise ValidationError("MOLLIE: \n %s" % error_details) | ||
except requests.exceptions.RequestException as e: | ||
_logger.exception("unable to communicate with Mollie: %s \n %s", url, e) | ||
if silent: | ||
return {'error': "Some thing went wrong"} | ||
else: | ||
raise ValidationError("Mollie: " + _("Some thing went wrong.")) | ||
return response.json() | ||
|
||
def show_form_and_tree(self): | ||
action = self.env['ir.actions.actions']._for_xml_id('mollie_pos_terminal.mollie_pos_terminal_payments_action') | ||
action.update({ | ||
'domain': [('terminal_id', '=', self.id)], | ||
'views': [(self.env.ref('mollie_pos_terminal.mollie_pos_terminal_payments_view_tree').id, 'tree'), (self.env.ref('mollie_pos_terminal.mollie_pos_terminal_payments_view_form').id, 'form')], | ||
'res_id': self.id, | ||
}) | ||
return action |
75 changes: 75 additions & 0 deletions
75
mollie_pos_terminal/models/mollie_pos_terminal_payments.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import json | ||
import logging | ||
import requests | ||
from werkzeug import urls | ||
|
||
from odoo import fields, models, api, _ | ||
from odoo.exceptions import ValidationError | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class MolliePosTerminal(models.Model): | ||
_name = 'mollie.pos.terminal.payments' | ||
_description = 'Mollie Pos Terminal' | ||
|
||
name = fields.Char("Transaction ID") | ||
mollie_uid = fields.Char("Mollie UID") | ||
terminal_id = fields.Many2one('mollie.pos.terminal') | ||
mollie_latest_response = fields.Text('Response', default="{}") | ||
status = fields.Selection([ | ||
('open', 'Open'), | ||
('paid', 'Paid'), | ||
('failed', 'Failed'), | ||
('expired', 'Expired'), | ||
('canceled', 'Canceled'), | ||
('pending', 'Pending'), | ||
], default='open') | ||
|
||
def _create_mollie_payment_request(self, response, data): | ||
if response and response.get('status') == 'open': | ||
self.create({ | ||
'name': response.get('id'), | ||
'mollie_uid': data.get('mollie_uid'), | ||
'terminal_id': data.get('terminal_id'), | ||
'mollie_latest_response': json.dumps(response or {}), | ||
'status': response.get('status') | ||
}) | ||
|
||
@api.model | ||
def get_mollie_payment_status(self, transaction_id=None, mollie_uid=None): | ||
domain = [] | ||
if transaction_id: | ||
domain.append(('name', '=', transaction_id)) | ||
elif mollie_uid: | ||
domain.append(('mollie_uid', '=', mollie_uid)) | ||
else: | ||
return {} | ||
mollie_payment = self.search(domain, limit=1) | ||
if mollie_payment: | ||
return json.loads(mollie_payment.mollie_latest_response or '{}') | ||
return {} | ||
|
||
@api.model | ||
def mollie_cancel_payment_request(self, transaction_id=None, mollie_uid=None): | ||
domain = [] | ||
if transaction_id: | ||
domain.append(('name', '=', transaction_id)) | ||
elif mollie_uid: | ||
domain.append(('mollie_uid', '=', mollie_uid)) | ||
else: | ||
return {} | ||
mollie_payment = self.search(domain, limit=1) | ||
if mollie_payment and mollie_payment.status == 'open': | ||
return mollie_payment.terminal_id._api_cancel_mollie_payment(mollie_payment.name) | ||
return {} | ||
|
||
def _mollie_process_webhook(self, webhook_data): | ||
mollie_payment = self.sudo().search([('name', '=', webhook_data.get('id'))], limit=1) | ||
if mollie_payment: | ||
payment_status = mollie_payment.terminal_id._api_get_mollie_payment_status(webhook_data.get('id')) | ||
if payment_status and payment_status.get('status'): | ||
mollie_payment.write({ | ||
'mollie_latest_response': json.dumps(payment_status or {}), | ||
'status': payment_status.get('status') | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
from odoo import fields, models | ||
|
||
|
||
class PosPaymentMethod(models.Model): | ||
_inherit = 'pos.payment.method' | ||
|
||
mollie_pos_terminal_id = fields.Many2one('mollie.pos.terminal', string='Mollie Pos Terminal', domain="[('status', '=', 'active')]") | ||
|
||
def _get_payment_terminal_selection(self): | ||
return super(PosPaymentMethod, self)._get_payment_terminal_selection() + [('mollie', 'Mollie')] | ||
|
||
def mollie_payment_request(self, data): | ||
return self.mollie_pos_terminal_id._api_make_payment_request(data) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from odoo import models, fields, _ | ||
|
||
|
||
class Company(models.Model): | ||
_inherit = 'res.company' | ||
|
||
mollie_terminal_api_key = fields.Char(string="Mollie Terminal Api Key") |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
from odoo import models, fields | ||
|
||
|
||
class ResConfigSettings(models.TransientModel): | ||
_inherit = 'res.config.settings' | ||
|
||
mollie_terminal_api_key = fields.Char(related='company_id.mollie_terminal_api_key', string='Mollie Terminal Api Key', readonly=False) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink | ||
access_mollie_pos_terminal,access_mollie_pos_terminal,model_mollie_pos_terminal,point_of_sale.group_pos_manager,1,1,1,1 | ||
access_mollie_wiz_sync_terminal,access_mollie_wiz_sync_terminal,model_sync_mollie_terminal,point_of_sale.group_pos_manager,1,1,1,1 | ||
access_mollie_pos_terminal_payments_user,access_mollie_pos_terminal_payments_user,model_mollie_pos_terminal_payments,point_of_sale.group_pos_user,1,1,1,0 | ||
access_mollie_pos_terminal_payments_manager,access_mollie_pos_terminal_payments_manager,model_mollie_pos_terminal_payments,point_of_sale.group_pos_manager,1,1,1,1 |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added
BIN
+51 KB
mollie_pos_terminal/static/description/img/odoo-mollie-pos-terminals.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Oops, something went wrong.