diff --git a/website_sale_signifyd/__manifest__.py b/website_sale_signifyd/__manifest__.py
index 5906d751..eba24d0d 100644
--- a/website_sale_signifyd/__manifest__.py
+++ b/website_sale_signifyd/__manifest__.py
@@ -9,15 +9,17 @@ Automate Order Fraud Detection with the Signifyd API.
'website': 'https://hibou.io/',
'depends': [
'website_sale',
+ 'stock',
+ 'delivery',
],
'data': [
'security/ir.model.access.csv',
- 'views/company_views.xml',
'views/partner_views.xml',
'views/sale_views.xml',
'views/signifyd_views.xml',
'views/stock_views.xml',
'views/web_assets.xml',
+ 'views/website_views.xml',
],
'installable': True,
'application': False,
diff --git a/website_sale_signifyd/controllers/__init__.py b/website_sale_signifyd/controllers/__init__.py
index 3b63458e..387cb370 100644
--- a/website_sale_signifyd/controllers/__init__.py
+++ b/website_sale_signifyd/controllers/__init__.py
@@ -1,2 +1 @@
-from . import main
from . import signifyd
diff --git a/website_sale_signifyd/controllers/main.py b/website_sale_signifyd/controllers/main.py
deleted file mode 100644
index 85d9c3be..00000000
--- a/website_sale_signifyd/controllers/main.py
+++ /dev/null
@@ -1,27 +0,0 @@
-from odoo.http import request, route
-from odoo.addons.website_sale.controllers.main import WebsiteSale
-
-import logging
-_logger = logging.getLogger(__name__)
-
-
-class WebsiteSale(WebsiteSale):
-
- @route(['/shop/confirmation'], type='http', auth="public", website=True, sitemap=False)
- def payment_confirmation(self, **post):
- res = super(WebsiteSale, self).payment_confirmation()
- # order_session_id = request.session.session_token
- checkout_token = request.session.session_token
- order_session_id = checkout_token # TODO what is the appropriate variable?
- _logger.warn(str(request.session))
- browser_ip_address = request.httprequest.environ['REMOTE_ADDR']
- sale_order_id = request.session.get('sale_last_order_id')
- if sale_order_id:
- order = request.env['sale.order'].sudo().browse(sale_order_id)
- # Post completed order to Signifyd
- signifyd = request.env.company.signifyd_connector_id
- if signifyd:
- # TODO should the signifyd variable be used?
- order.post_signifyd_case(order_session_id, checkout_token, browser_ip_address)
-
- return res
diff --git a/website_sale_signifyd/controllers/signifyd.py b/website_sale_signifyd/controllers/signifyd.py
index 30b6fd16..aba30ab2 100644
--- a/website_sale_signifyd/controllers/signifyd.py
+++ b/website_sale_signifyd/controllers/signifyd.py
@@ -4,36 +4,19 @@ from odoo.http import Response
class SignifydWebhooks(Controller):
- @route(['/cases/creation'], type='json', auth='public', methods=['POST'], csrf=False)
- def case_creation(self, *args, **post):
- data = json.loads(request.httprequest.data)
- vals = request.env['signifyd.connector'].process_post_values(data)
- # Update case with info
- case = request.env['signifyd.case'].sudo().search([('case_id', '=', vals['case_id'])])
- if case:
- case.sudo().update_case_info(vals)
- # Request guarantee for case if eligible
- try:
- case.request_guarantee()
- if case.guarantee_requested and not case.guarantee_eligible:
- # Only alert Signifyd to stop trying if we have at least tried once already
- return Response({'response': 'success'}, status=200, mimetype='application/json')
- # TODO what would the return case be here?
- except:
- # Signifyd API will try again up to 15 times if a non-2** code is returned
- return Response({'response': 'failed'}, status=500, mimetype='application/json')
- # TODO what would the return case be here?
- @route(['/cases/update'], type='json', auth='public', methods=['POST'], csrf=False)
+ @route(['/signifyd/cases/update'], type='json', auth='public', methods=['POST'], csrf=False, website=True)
def case_update(self, *args, **post):
+ return self._case_update()
+
+ def _case_update(self):
data = json.loads(request.httprequest.data)
vals = request.env['signifyd.connector'].process_post_values(data)
- case = request.env['signifyd.case'].sudo().search([('case_id', '=', vals['case_id'])])
+ case = self._get_case(vals.get('case_id'))
if case:
case.update_case_info(vals)
+ return Response({'response': 'success'}, status=200, mimetype='application/json')
+ return Response({'response': 'failed'}, status=500, mimetype='application/json')
- outcome = vals.get('guarantee_disposition')
- if case and outcome == 'DECLINED':
- for user in request.env.company.signifyd_connector_id.notify_user_ids:
- case.sudo().create_notification(user, outcome)
- # TODO any return result?
+ def _get_case(self, case_id):
+ return request.env['signifyd.case'].sudo().search([('case_id', '=', case_id)], limit=1)
diff --git a/website_sale_signifyd/models/__init__.py b/website_sale_signifyd/models/__init__.py
index 7aacfb24..5408481e 100644
--- a/website_sale_signifyd/models/__init__.py
+++ b/website_sale_signifyd/models/__init__.py
@@ -1,6 +1,6 @@
-from . import company
from . import partner
from . import sale_order
from . import signifyd
from . import signifyd_connector
from . import stock
+from . import website
diff --git a/website_sale_signifyd/models/company.py b/website_sale_signifyd/models/company.py
deleted file mode 100644
index b51a6748..00000000
--- a/website_sale_signifyd/models/company.py
+++ /dev/null
@@ -1,8 +0,0 @@
-from odoo import fields, models
-
-
-class ResCompany(models.Model):
- _inherit = 'res.company'
-
- # TODO move to website
- signifyd_connector_id = fields.Many2one('signifyd.connector')
diff --git a/website_sale_signifyd/models/partner.py b/website_sale_signifyd/models/partner.py
index 536ed814..63ae2b6b 100644
--- a/website_sale_signifyd/models/partner.py
+++ b/website_sale_signifyd/models/partner.py
@@ -8,6 +8,7 @@ class ResPartner(models.Model):
signifyd_case_count = fields.Integer(compute='_compute_signifyd_stats', string='Signifyd Cases')
signifyd_average_score = fields.Float(compute='_compute_signifyd_stats', string='Signifyd Score')
+ @api.depends('signifyd_case_ids')
def _compute_signifyd_stats(self):
for record in self:
cases = record.signifyd_case_ids
diff --git a/website_sale_signifyd/models/sale_order.py b/website_sale_signifyd/models/sale_order.py
index e5412c11..b57d5abc 100644
--- a/website_sale_signifyd/models/sale_order.py
+++ b/website_sale_signifyd/models/sale_order.py
@@ -1,15 +1,19 @@
from odoo import api, fields, models
+from odoo.exceptions import UserError
+from odoo.http import request
class SaleOrder(models.Model):
_inherit = 'sale.order'
- signifyd_case_id = fields.Many2one('signifyd.case', readonly=1)
+ signifyd_case_id = fields.Many2one('signifyd.case', readonly=1, copy=False)
singifyd_score = fields.Float(related='signifyd_case_id.score')
signifyd_disposition_status = fields.Selection(related='signifyd_case_id.guarantee_disposition')
def action_view_signifyd_case(self):
self.ensure_one()
+ if not self.signifyd_case_id:
+ raise UserError('This order has no Signifyd Case')
form_id = self.env.ref('website_sale_signifyd.signifyd_case_form_view').id
context = {'create': False, 'delete': False}
return {
@@ -22,128 +26,126 @@ class SaleOrder(models.Model):
'context': context,
}
- def post_signifyd_case(self, order_session_id, checkout_token, browser_ip_address):
+ def action_confirm(self):
+ res = super().action_confirm()
+ for sale in self.filtered(lambda so: so.state in ('sale', 'done') and not so.signifyd_case_id):
+ _case = sale.post_signifyd_case()
+ return res
+
+ def post_signifyd_case(self):
+ if not self.website_id.signifyd_connector_id:
+ return
+ browser_ip_address = request.httprequest.environ['REMOTE_ADDR']
+ if request.session:
+ checkout_token = request.session.session_token
+ order_session_id = checkout_token
+ else:
+ checkout_token = ''
# Session values for Signifyd post
- data = {
- 'order_session_id': order_session_id,
- 'checkout_token': checkout_token,
- 'browser_ip_address': browser_ip_address,
- }
- sig_vals = self.prepare_signifyd_case_values(data)
+ sig_vals = self._prepare_signifyd_case_values(order_session_id, checkout_token, browser_ip_address)
- case_res = self.env['signifyd.case'].post_case(sig_vals)
+ case = self.env['signifyd.case'].post_case(self.website_id.signifyd_connector_id, sig_vals)
- success_response = case_res.get('investigationId')
+ success_response = case.get('investigationId')
if success_response:
new_case = self.env['signifyd.case'].create({
'order_id': self.id,
'case_id': success_response,
'name': success_response,
+ 'partner_id': self.partner_id.id,
})
self.write({'signifyd_case_id': new_case.id})
- self.partner_id.write({
- 'signifyd_case_ids': [(4, new_case.id)],
- })
return new_case
+ # TODO do we need to raise an exception?
+ return None
@api.model
- def prepare_signifyd_case_values(self, data):
- order_session_id = data.get('order_session_id')
- checkout_token = data.get('checkout_token')
- browser_ip_address = data.get('browser_ip_address')
-
- new_case_vals = {}
-
- new_case_vals['purchase'] = {
- "orderSessionId": order_session_id,
- "orderId": self.id,
- "checkoutToken": checkout_token,
- "browserIpAddress": browser_ip_address,
- "currency": self.partner_id.currency_id.name,
- "orderChannel": "WEB",
- "totalPrice": self.amount_total,
+ def _prepare_signifyd_case_values(self, order_session_id, checkout_token, browser_ip_address):
+ tx_status_type = {
+ 'draft': 'FAILURE',
+ 'pending': 'PENDING',
+ 'authorized': 'SUCCESS',
+ 'done': 'SUCCESS',
+ 'cancel': 'FAILURE',
+ 'error': 'ERROR',
}
-
- new_case_vals['purchase']['products'] = []
- for line in self.order_line:
- product = line.product_id
- vals = {
- "itemId": product.id,
- "itemName": product.name,
- "itemIsDigital": False,
- "itemCategory": product.categ_id.name,
- "itemUrl": product.website_url,
- "itemQuantity": line.product_uom_qty,
- "itemPrice": line.price_unit,
- "itemWeight": product.weight,
- }
- new_case_vals['purchase']['products'].append(vals)
-
- new_case_vals['purchase']['shipments'] = []
- if self.carrier_id:
- vals = {
- "shipper": self.carrier_id.name,
- "shippingMethod": "ground",
- "shippingPrice": self.amount_delivery,
- }
- new_case_vals['purchase']['shipments'].append(vals)
-
- new_case_vals['recipients'] = []
- recipients = [self.partner_invoice_id, self.partner_shipping_id]
- for partner in recipients:
- vals = {
- "fullName": partner.name,
- "confirmationEmail": partner.email,
- "confirmationPhone": partner.phone,
- "organization": partner.company_id.name,
- "deliveryAddress": {
- "streetAddress": partner.street,
- "unit": partner.street2,
- "city": partner.city,
- "provinceCode": partner.state_id.code,
- "postalCode": partner.zip,
- "countryCode": partner.country_id.code,
- }
- }
- new_case_vals['recipients'].append(vals)
-
- new_case_vals['transactions'] = []
- # payment.transaction
- for tx in self.transaction_ids:
- tx_status_type = {
- 'draft': 'FAILURE',
- 'pending': 'PENDING',
- 'authorized': 'SUCCESS',
- 'done': 'SUCCESS',
- 'cancel': 'FAILURE',
- 'error': 'ERROR',
- }
-
- tx_status = tx_status_type[tx.state]
-
- vals = {
- "parentTransactionId": None,
- "transactionId": tx.id,
- "gateway": tx.acquirer_id.name,
- "paymentMethod": "CREDIT_CARD",
- "gatewayStatusCode": tx_status,
- "type": "AUTHORIZATION",
+ recipients = self.partner_invoice_id + self.partner_shipping_id
+ new_case_vals = {
+ 'decisionRequest': {
+ 'paymentFraud': 'GUARANTEE',
+ },
+ 'purchase': {
+ "orderSessionId": order_session_id,
+ "orderId": self.id,
+ "checkoutToken": checkout_token,
+ "browserIpAddress": browser_ip_address,
"currency": self.partner_id.currency_id.name,
- "amount": tx.amount,
- "avsResponseCode": "Y",
- "cvvResponseCode": "N",
- "checkoutPaymentDetails": {
- "holderName": tx.partner_id.name,
- "billingAddress": {
- "streetAddress": tx.partner_id.street,
- "unit": tx.partner_id.street2,
- "city": tx.partner_id.city,
- "provinceCode": tx.partner_id.state_id.code,
- "postalCode": tx.partner_id.zip,
- "countryCode": tx.partner_id.country_id.code,
+ "orderChannel": "WEB",
+ "totalPrice": self.amount_total,
+ 'products': [
+ {
+ "itemId": line.product_id.id,
+ "itemName": line.product_id.name,
+ "itemIsDigital": False,
+ "itemCategory": line.product_id.categ_id.name,
+ "itemUrl": line.product_id.website_url or '',
+ "itemQuantity": line.product_uom_qty,
+ "itemPrice": line.price_unit,
+ "itemWeight": line.product_id.weight or 0.1,
+ }
+ for line in self.order_line if line.product_id
+ ],
+ 'shipments': [{
+ "shipper": carrier.name,
+ "shippingMethod": "ground",
+ "shippingPrice": self.amount_delivery,
+ }
+ for carrier in self.carrier_id
+ ],
+ },
+ 'recipients': [
+ {
+ "fullName": partner.name,
+ "confirmationEmail": partner.email,
+ "confirmationPhone": partner.phone,
+ "organization": partner.company_id.name,
+ "deliveryAddress": {
+ "streetAddress": partner.street,
+ "unit": partner.street2,
+ "city": partner.city,
+ "provinceCode": partner.state_id.code,
+ "postalCode": partner.zip,
+ "countryCode": partner.country_id.code,
}
}
- }
- new_case_vals['transactions'].append(vals)
+ for partner in recipients
+ ],
+ 'transactions': [
+ {
+ "parentTransactionId": None,
+ "transactionId": tx.id,
+ "gateway": tx.acquirer_id.name,
+ "paymentMethod": "CREDIT_CARD",
+ "gatewayStatusCode": tx_status_type.get(tx.state, 'PENDING'),
+ "type": "AUTHORIZATION",
+ "currency": self.partner_id.currency_id.name,
+ "amount": tx.amount,
+ # "avsResponseCode": "Y",
+ # "cvvResponseCode": "N",
+ "checkoutPaymentDetails": {
+ "holderName": tx.partner_id.name,
+ "billingAddress": {
+ "streetAddress": tx.partner_id.street,
+ "unit": tx.partner_id.street2,
+ "city": tx.partner_id.city,
+ "provinceCode": tx.partner_id.state_id.code,
+ "postalCode": tx.partner_id.zip,
+ "countryCode": tx.partner_id.country_id.code,
+ }
+ }
+ }
+ for tx in self.transaction_ids
+ ],
+ }
return new_case_vals
diff --git a/website_sale_signifyd/models/signifyd.py b/website_sale_signifyd/models/signifyd.py
index 46ddadec..6138a2fb 100644
--- a/website_sale_signifyd/models/signifyd.py
+++ b/website_sale_signifyd/models/signifyd.py
@@ -42,97 +42,77 @@ class SignifydCase(models.Model):
('CANCELED', 'Canceled'),
], string='Guarantee Status')
disposition_reason = fields.Char('Disposition Reason')
- guarantee_eligible = fields.Boolean('Eligible for Guarantee')
- guarantee_requested = fields.Boolean('Requested Guarantee')
score = fields.Float(string='Transaction Score')
adjusted_score = fields.Float(string='Adjusted Score')
signifyd_url = fields.Char('Signifyd.com', compute='_compute_signifyd_url')
+ def _get_connector(self):
+ return self.order_id.website_id.signifyd_connector_id
+
@api.model
def _compute_signifyd_url(self):
for record in self:
if record.case_id:
- self.signifyd_url = 'https://app.signifyd.com/cases/%s' % record.case_id
+ self.signifyd_url = 'https://app.signifyd.com/cases/%s' % (record.case_id, )
else:
self.signifyd_url = ''
def write(self, vals):
original_disposition = {c: c.guarantee_disposition for c in self}
res = super(SignifydCase, self).write(vals)
- disposition = vals.get('guarantee_disposition')
- for case in self:
- if case.order_id and original_disposition[case] != disposition:
- self.order_id.message_post(body=_('Signifyd Updated Record to %s' % vals['guarantee_disposition']),
- subtype='website_sale_signifyd.disposition_change')
+ disposition = vals.get('guarantee_disposition', False)
+ for case in self.filtered(lambda c: c.order_id and original_disposition[c] != disposition):
+ case.order_id.message_post(body=_('Signifyd Updated Record to %s' % disposition),
+ subtype='website_sale_signifyd.disposition_change')
return res
@api.model
- def post_case(self, values):
- signifyd = self.env['signifyd.connector'] # TODO HOW, this shouldn't be a singleton
- headers = signifyd.get_headers()
+ def post_case(self, connector, values):
+ headers = connector.get_headers()
data = json.dumps(values, indent=4, sort_keys=True, default=str)
# TODO this should be in `signifyd.connector`
r = requests.post(
- signifyd.API_URL + '/cases',
+ connector.API_URL + '/cases',
headers=headers,
data=data,
)
return r.json()
- @api.model
def get_case(self):
- # TODO See above....
- signifyd = self.env['signifyd.connector']
- headers = signifyd.get_headers()
+ self.ensure_one()
+ if not self.case_id:
+ raise UserError('Case not represented in Signifyd.')
+ connector = self._get_connector()
+ headers = connector.get_headers()
r = requests.get(
- signifyd.API_URL + '/cases/' + str(self.case_id),
+ connector.API_URL + '/cases/' + str(self.case_id),
headers=headers
)
return r.json()
- @api.model
- def request_guarantee(self, *args):
- # TODO See above....
- signifyd = self.env['signifyd.connector']
- headers = signifyd.get_headers()
- values = json.dumps({"caseId": self.case_id})
- r = requests.post(
- signifyd.API_URL + '/async/guarantees',
- headers=headers,
- data=values,
- )
-
- if 200 <= r.status_code < 300:
- self.write({'guarantee_requested': True})
- else:
- msg = r.content.decode("utf-8")
- raise UserError(_(msg))
-
- def action_request_guarantee(self):
- for record in self:
- record.request_guarantee()
-
def action_force_update_case(self):
for record in self:
record.update_case_info()
- @api.model
def update_case_info(self, vals=None):
+ self.ensure_one()
+ if not self.case_id:
+ raise UserError('Case not represented in Signifyd.')
if not vals:
case = self.get_case()
case_id = case.get('caseId')
- team_id = case.get('teamId')
- team_name = case.get('teamName')
- uuid = case.get('uuid')
- status = case.get('status')
- review_disposition = case.get('reviewDisposition')
- order_outcome = case.get('orderOutcome')
- guarantee_disposition = case.get('guaranteeDisposition')
- adjusted_score = case.get('adjustedScore')
- score = case.get('score')
- guarantee_eligible = case.get('guaranteeEligible')
- # order_id = case.get('orderId')
+ if not case_id:
+ raise ValueError('Signifyd Case has no ID?')
+ team_id = case.get('teamId', self.team_id)
+ team_name = case.get('teamName', self.team_name)
+ uuid = case.get('uuid', self.uuid)
+ status = case.get('status', self.status)
+ review_disposition = case.get('reviewDisposition', self.review_disposition)
+ order_outcome = case.get('orderOutcome', self.order_outcome)
+ guarantee_disposition = case.get('guaranteeDisposition', self.guarantee_disposition)
+ adjusted_score = case.get('adjustedScore', self.adjusted_score)
+ score = case.get('score', self.score)
vals = {
'case_id': case_id,
@@ -145,13 +125,13 @@ class SignifydCase(models.Model):
'adjusted_score': adjusted_score,
'guarantee_disposition': guarantee_disposition,
'score': score,
- 'guarantee_eligible': guarantee_eligible,
- 'last_update': dt.now(),
+ 'last_update': dt.now(), # why not just use
}
outcome = vals.get('guarantee_disposition')
if outcome == 'DECLINED':
- for user in self.env.company.signifyd_connector_id.notify_user_ids:
+ connector = self._get_connector()
+ for user in connector.notify_user_ids:
self.create_notification(user, outcome)
self.write(vals)
@@ -163,6 +143,6 @@ class SignifydCase(models.Model):
'activity_type_id': self.env.ref('mail.mail_activity_data_todo').id,
'user_id': user.id,
'res_id': self.order_id.id,
- 'res_model_id': self.env['ir.model']._get('sale.order').id,
+ 'res_model_id': self.env['ir.model']._get(self.order_id._name).id,
}
self.env['mail.activity'].create(vals)
diff --git a/website_sale_signifyd/models/signifyd_connector.py b/website_sale_signifyd/models/signifyd_connector.py
index 24bb44b5..696d6e59 100644
--- a/website_sale_signifyd/models/signifyd_connector.py
+++ b/website_sale_signifyd/models/signifyd_connector.py
@@ -12,56 +12,65 @@ class SignifydConnector(models.Model):
name = fields.Char(string='Connector Name')
test_mode = fields.Boolean(string='Test Mode')
- user_key = fields.Char(string='Username')
+ user_key = fields.Char(string='Team/Username')
secret_key = fields.Char(string='API Key')
- user_key_test = fields.Char(string='TEST Username')
+ user_key_test = fields.Char(string='TEST Team/Username')
secret_key_test = fields.Char(string='TEST API Key')
- open_so_cap = fields.Integer(string='Cap requests at:')
webhooks_registered = fields.Boolean(string='Successfully Registered Webhooks')
- notify_user_ids = fields.Many2many('res.users', string='Receive event notifications')
+ notify_user_ids = fields.Many2many('res.users', string='Receive decline notifications')
+ # TODO ideally this would be a regular constant
+ # however other entities currently use this by reference
API_URL = 'https://api.signifyd.com/v2'
def get_headers(self):
+ self.ensure_one()
# Check for prod or test mode
- signifyd = self.env.company.signifyd_connector_id
- if not signifyd:
- return False
-
- if signifyd.test_mode:
- api_key = signifyd.secret_key_test
+ if self.test_mode:
+ api_key = self.secret_key_test
else:
- api_key = signifyd.secret_key
+ api_key = self.secret_key
- b64_auth_key = b64encode(api_key.encode('utf-8'))
+ b64_auth_key = b64encode(api_key.encode()).decode().replace('=', '')
headers = {
- 'Authorization': 'Basic ' + str(b64_auth_key, 'utf-8').replace('=', ''),
+ 'Authorization': 'Basic ' + b64_auth_key,
'Content-Type': 'application/json',
}
return headers
def register_webhooks(self):
+ self.ensure_one()
headers = self.get_headers()
- base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
+ # This should come from the website...
+ # we may need a better way to link the connector to the website.
+ base_url = None
+ website = self.env['website'].search([('signifyd_connector_id', '=', self.id)], limit=1)
+ if website and website.domain:
+ base_url = website.domain
+ if base_url.find('://') <= 0: # documentation says if no protocol use http
+ base_url = 'http://' + base_url
+ if not base_url:
+ base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
values = {
"webhooks": [
- {
- "event": "CASE_CREATION",
- "url": base_url + "/cases/creation"
- },
+ # Given we are creating the cases, we do not need to know about it
+ # {
+ # "event": "CASE_CREATION",
+ # "url": base_url + "/signifyd/cases/update"
+ # },
{
"event": "CASE_RESCORE",
- "url": base_url + "/cases/update"
+ "url": base_url + "/signifyd/cases/update"
},
{
"event": "CASE_REVIEW",
- "url": base_url + "/cases/update"
+ "url": base_url + "/signifyd/cases/update"
},
{
"event": "GUARANTEE_COMPLETION",
- "url": base_url + "/cases/update"
+ "url": base_url + "/signifyd/cases/update"
},
]
}
@@ -75,7 +84,6 @@ class SignifydConnector(models.Model):
return r
def action_register_webhooks(self):
-
notification = {
'type': 'ir.actions.client',
'tag': 'display_notification',
@@ -96,11 +104,11 @@ class SignifydConnector(models.Model):
else:
notification['params']['type'] = 'danger'
notification['params']['message'] = res.content.decode('utf-8')
+ self.webhooks_registered = False
return notification
def process_post_values(self, post):
# Construct dict from request data for endpoints
- guarantee_eligible = post.get('guaranteeEligible')
uuid = post.get('uuid')
case_id = post.get('caseId')
team_name = post.get('teamName')
@@ -117,7 +125,6 @@ class SignifydConnector(models.Model):
values = {}
# Validate that the order and case match the request
- values.update({'guarantee_eligible': guarantee_eligible}) if guarantee_eligible else ''
values.update({'uuid': uuid}) if uuid else ''
values.update({'team_name': team_name}) if team_name else ''
values.update({'team_id': team_id}) if team_id else ''
diff --git a/website_sale_signifyd/models/stock.py b/website_sale_signifyd/models/stock.py
index a2cae1e8..c3dea3db 100644
--- a/website_sale_signifyd/models/stock.py
+++ b/website_sale_signifyd/models/stock.py
@@ -1,5 +1,5 @@
from odoo import fields, models
-
+from odoo.exceptions import UserError
class StockPicking(models.Model):
_inherit = 'stock.picking'
@@ -9,6 +9,8 @@ class StockPicking(models.Model):
def action_view_signifyd_case(self):
self.ensure_one()
+ if not self.singifyd_case_id:
+ raise UserError('No Signifyd Case')
form_id = self.env.ref('website_sale_signifyd.signifyd_case_form_view').id
context = {'create': False, 'delete': False, 'id': self.sale_id.signifyd_case_id.id}
return {
diff --git a/website_sale_signifyd/models/website.py b/website_sale_signifyd/models/website.py
new file mode 100644
index 00000000..2cb78188
--- /dev/null
+++ b/website_sale_signifyd/models/website.py
@@ -0,0 +1,7 @@
+from odoo import api, fields, models
+
+
+class Website(models.Model):
+ _inherit = 'website'
+
+ signifyd_connector_id = fields.Many2one('signifyd.connector')
diff --git a/website_sale_signifyd/security/ir.model.access.csv b/website_sale_signifyd/security/ir.model.access.csv
index c537a258..dbebf821 100644
--- a/website_sale_signifyd/security/ir.model.access.csv
+++ b/website_sale_signifyd/security/ir.model.access.csv
@@ -1,9 +1,9 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
manage_signifyd_connector,manage_signifyd_connector,model_signifyd_connector,base.group_erp_manager,1,1,1,1
-access_signifyd_connector,access_signifyd_connector,model_signifyd_connector,base.group_user,1,1,1,0
-public_signifyd_connector,public_signifyd_connector,model_signifyd_connector,base.group_public,1,1,1,0
-portal_signifyd_connector,portal_signifyd_connector,model_signifyd_connector,base.group_portal,1,1,1,0
+access_signifyd_connector,access_signifyd_connector,model_signifyd_connector,base.group_user,1,0,0,0
+public_signifyd_connector,public_signifyd_connector,model_signifyd_connector,base.group_public,1,0,0,0
+portal_signifyd_connector,portal_signifyd_connector,model_signifyd_connector,base.group_portal,1,0,0,0
manage_signifyd_case,manage_signifyd_case,model_signifyd_case,base.group_erp_manager,1,1,1,1
-access_signifyd_case,access_signifyd_case,model_signifyd_case,base.group_user,1,1,1,0
-public_signifyd_case,public_signifyd_case,model_signifyd_case,base.group_public,1,1,1,0
-portal_signifyd_case,portal_signifyd_case,model_signifyd_case,base.group_portal,1,1,1,0
\ No newline at end of file
+access_signifyd_case,access_signifyd_case,model_signifyd_case,base.group_user,1,0,0,0
+public_signifyd_case,public_signifyd_case,model_signifyd_case,base.group_public,1,0,0,0
+portal_signifyd_case,portal_signifyd_case,model_signifyd_case,base.group_portal,1,0,0,0
\ No newline at end of file
diff --git a/website_sale_signifyd/views/company_views.xml b/website_sale_signifyd/views/company_views.xml
deleted file mode 100644
index 1f217b4d..00000000
--- a/website_sale_signifyd/views/company_views.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
- Connector
-
-