diff --git a/addons/account/models/account_payment.py b/addons/account/models/account_payment.py
index adca204ce3e..ebd507f1aae 100644
--- a/addons/account/models/account_payment.py
+++ b/addons/account/models/account_payment.py
@@ -560,20 +560,25 @@ class account_payment(models.Model):
@api.multi
def button_invoices(self):
- if self.partner_type == 'supplier':
- views = [(self.env.ref('account.invoice_supplier_tree').id, 'tree'), (self.env.ref('account.invoice_supplier_form').id, 'form')]
- else:
- views = [(self.env.ref('account.invoice_tree').id, 'tree'), (self.env.ref('account.invoice_form').id, 'form')]
- return {
+ action = {
'name': _('Paid Invoices'),
'view_type': 'form',
'view_mode': 'tree,form',
'res_model': 'account.invoice',
'view_id': False,
- 'views': views,
'type': 'ir.actions.act_window',
'domain': [('id', 'in', [x.id for x in self.reconciled_invoice_ids])],
}
+ if self.partner_type == 'supplier':
+ action['views'] = [(self.env.ref('account.invoice_supplier_tree').id, 'tree'), (self.env.ref('account.invoice_supplier_form').id, 'form')]
+ action['context'] = {
+ 'journal_type': 'purchase',
+ 'type': 'in_invoice',
+ 'default_type': 'in_invoice',
+ }
+ else:
+ action['views'] = [(self.env.ref('account.invoice_tree').id, 'tree'), (self.env.ref('account.invoice_form').id, 'form')]
+ return action
@api.multi
def button_dummy(self):
diff --git a/addons/account_payment/views/account_portal_templates.xml b/addons/account_payment/views/account_portal_templates.xml
index bdc9c9da488..4945eb9b5bc 100644
--- a/addons/account_payment/views/account_portal_templates.xml
+++ b/addons/account_payment/views/account_portal_templates.xml
@@ -48,7 +48,7 @@
-
+
diff --git a/addons/delivery/__manifest__.py b/addons/delivery/__manifest__.py
index 17583ac4324..7c06e139b1d 100644
--- a/addons/delivery/__manifest__.py
+++ b/addons/delivery/__manifest__.py
@@ -27,6 +27,7 @@ invoices from picking, the system is able to add and compute the shipping line.
'views/report_package_barcode.xml',
'views/res_config_settings_views.xml',
'wizard/choose_delivery_package_views.xml',
+ 'views/assets.xml',
],
'demo': ['data/delivery_demo.xml'],
'installable': True,
diff --git a/addons/delivery/static/src/js/delivery_translations.js b/addons/delivery/static/src/js/delivery_translations.js
new file mode 100644
index 00000000000..565adbcb69f
--- /dev/null
+++ b/addons/delivery/static/src/js/delivery_translations.js
@@ -0,0 +1,16 @@
+// TODO Remove me >=saas-12.5, this is a disgrace
+// This is an hack to get the string_* and hover_* options translated on the
+// boolean_button terminology widget. The terms are translated through
+// _t(opt_terms.string_true) which will only work if the terms are already
+// present in the translation map.
+// This code does nothing but marks the strings as translatable
+var _t = function(x) { return x; };
+
+_t("Production Environment");
+_t("Switch to test environment");
+_t("Test Environment");
+_t("Switch to production environment");
+_t("Debug requests");
+_t("Disable debug");
+_t("No debug");
+_t("Enable debug");
diff --git a/addons/delivery/views/assets.xml b/addons/delivery/views/assets.xml
new file mode 100644
index 00000000000..851aaca55c9
--- /dev/null
+++ b/addons/delivery/views/assets.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/addons/fleet/views/fleet_vehicle_cost_views.xml b/addons/fleet/views/fleet_vehicle_cost_views.xml
index a3df5e74e33..e7f30238762 100644
--- a/addons/fleet/views/fleet_vehicle_cost_views.xml
+++ b/addons/fleet/views/fleet_vehicle_cost_views.xml
@@ -206,7 +206,7 @@
-
+
diff --git a/addons/payment/static/src/js/payment_translations.js b/addons/payment/static/src/js/payment_translations.js
new file mode 100644
index 00000000000..199dcc2a276
--- /dev/null
+++ b/addons/payment/static/src/js/payment_translations.js
@@ -0,0 +1,10 @@
+// TODO Remove me >=saas-12.5, this is a disgrace
+// This is an hack to get the string_true and hover_false options translated on
+// the boolean_button terminology widget. The terms are translated through
+// _t(opt_terms.string_true) which will only work if the terms are already
+// present in the translation map.
+// This code does nothing but marks the strings as translatable
+var _t = function(x) { return x; };
+
+_t("Published");
+_t("Publish");
diff --git a/addons/payment/views/assets.xml b/addons/payment/views/assets.xml
index 62fe9d2455f..49cc88c5536 100644
--- a/addons/payment/views/assets.xml
+++ b/addons/payment/views/assets.xml
@@ -13,4 +13,11 @@
+
+
+
+
+
+
+
diff --git a/addons/payment_authorize/models/payment.py b/addons/payment_authorize/models/payment.py
index 6361a211f16..b1d9a2e6a1e 100644
--- a/addons/payment_authorize/models/payment.py
+++ b/addons/payment_authorize/models/payment.py
@@ -25,6 +25,7 @@ class PaymentAcquirerAuthorize(models.Model):
provider = fields.Selection(selection_add=[('authorize', 'Authorize.Net')])
authorize_login = fields.Char(string='API Login Id', required_if_provider='authorize', groups='base.group_user')
authorize_transaction_key = fields.Char(string='API Transaction Key', required_if_provider='authorize', groups='base.group_user')
+ authorize_signature_key = fields.Char(string='API Signature Key', groups='base.group_user', compute="_compute_auth_signature_key", inverse="_inverse_auth_signature_key")
def _get_feature_support(self):
"""Get advanced feature support by provider.
@@ -42,6 +43,16 @@ class PaymentAcquirerAuthorize(models.Model):
res['tokenize'].append('authorize')
return res
+ def _compute_auth_signature_key(self):
+ ICP = self.env['ir.config_parameter'].sudo()
+ for acquirer in self.filtered(lambda a: a.provider == 'authorize'):
+ acquirer.authorize_signature_key = ICP.get_param('payment_authorize.signature_key_%s' % acquirer.id)
+
+ def _inverse_auth_signature_key(self):
+ ICP = self.env['ir.config_parameter'].sudo()
+ for acquirer in self.filtered(lambda a: a.provider == 'authorize'):
+ ICP.set_param('payment_authorize.signature_key_%s' % acquirer.id, acquirer.authorize_signature_key)
+
def _get_authorize_urls(self, environment):
""" Authorize URLs """
if environment == 'prod':
@@ -57,13 +68,22 @@ class PaymentAcquirerAuthorize(models.Model):
values['x_amount'],
values['x_currency_code']]).encode('utf-8')
- # [BACKWARD COMPATIBILITY] Check that the merchant did update his transaction
- # key to signature key (end of MD5 support from Authorize.net)
+ # [BACKWARD COMPATIBILITY, 2nd edition]
# The signature key is now '128-character hexadecimal format', while the
# transaction key was only 16-character.
- if len(values['x_trans_key']) == 128:
- key = bytes.fromhex(values['x_trans_key'])
- return hmac.new(key, data, hashlib.sha512).hexdigest().upper()
+ # One of 2 things should have happened:
+ # 1/ the Transaction Key has been replaced with the Signature Key value (patch from March 2019)
+ # => Use that to sign, but server-to-server won't work since it uses transaction key
+ # as its credentials
+ # 2/ the Signature key is a new field (patch from July 2019)
+ # => Use that field for the signature
+
+ # FORWARD-PORT NOTE: forward part to saas-12.4 but no further
+ if len(values['x_trans_key']) == 128 and not self.authorize_signature_key:
+ self.authorize_signature_key = values['x_trans_key'] # store in the correct field
+ return hmac.new(bytes.fromhex(values['x_trans_key']), data, hashlib.sha512).hexdigest().upper()
+ elif self.authorize_signature_key:
+ return hmac.new(bytes.fromhex(self.authorize_signature_key), data, hashlib.sha512).hexdigest().upper()
else:
return hmac.new(values['x_trans_key'].encode('utf-8'), data, hashlib.md5).hexdigest()
diff --git a/addons/payment_authorize/views/payment_views.xml b/addons/payment_authorize/views/payment_views.xml
index 0237325e0c2..b60385ed9f0 100644
--- a/addons/payment_authorize/views/payment_views.xml
+++ b/addons/payment_authorize/views/payment_views.xml
@@ -9,6 +9,7 @@
+
How to get paid with Authorize.Net
diff --git a/addons/stock/models/product.py b/addons/stock/models/product.py
index dd0269d81ff..bbb6f301834 100644
--- a/addons/stock/models/product.py
+++ b/addons/stock/models/product.py
@@ -162,9 +162,23 @@ class Product(models.Model):
company_id = self.env.user.company_id.id
return (
[('location_id.company_id', '=', company_id), ('location_id.usage', 'in', ['internal', 'transit'])],
- [('location_id.company_id', '=', False), ('location_dest_id.company_id', '=', company_id)],
- [('location_id.company_id', '=', company_id), ('location_dest_id.company_id', '=', False),
- ])
+ ['&',
+ ('location_dest_id.company_id', '=', company_id),
+ '|',
+ ('location_id.company_id', '=', False),
+ '&',
+ ('location_id.usage', 'in', ['inventory', 'production']),
+ ('location_id.company_id', '=', company_id),
+ ],
+ ['&',
+ ('location_id.company_id', '=', company_id),
+ '|',
+ ('location_dest_id.company_id', '=', False),
+ '&',
+ ('location_dest_id.usage', 'in', ['inventory', 'production']),
+ ('location_dest_id.company_id', '=', company_id),
+ ]
+ )
location_ids = []
if self.env.context.get('location', False):
if isinstance(self.env.context['location'], pycompat.integer_types):
diff --git a/addons/stock_account/models/stock.py b/addons/stock_account/models/stock.py
index 889fa9d7863..c744638bcff 100644
--- a/addons/stock_account/models/stock.py
+++ b/addons/stock_account/models/stock.py
@@ -201,7 +201,7 @@ class StockMove(models.Model):
'|',
('location_dest_id.company_id', '=', False),
'&',
- ('location_dest_id.usage', '=', 'inventory'),
+ ('location_dest_id.usage', 'in', ['inventory', 'production']),
('location_dest_id.company_id', '=', company_id or self.env.user.company_id.id),
]
return domain
diff --git a/addons/stock_account/tests/test_stockvaluation.py b/addons/stock_account/tests/test_stockvaluation.py
index 5efd5ca5bbc..d7097fe10d7 100644
--- a/addons/stock_account/tests/test_stockvaluation.py
+++ b/addons/stock_account/tests/test_stockvaluation.py
@@ -3944,3 +3944,51 @@ class TestStockValuation(TransactionCase):
self.assertAlmostEqual(move1.remaining_qty, 0.0)
self.assertAlmostEqual(self.product1.stock_value, 0.0)
+
+ def test_at_date_average_1(self):
+ """ Set a company on the inventory loss, take items from there then put items there, check
+ the values and quantities at date.
+ """
+ now = Datetime.from_string(Date.today())
+ date1 = now - timedelta(days=8)
+ date2 = now - timedelta(days=7)
+
+ self.product1.standard_price = 10
+ self.env['product.price.history'].search([
+ ('product_id', '=', self.product1.id)
+ ], order='datetime desc, id DESC', limit=1).datetime = date1
+ self.product1.product_tmpl_id.cost_method = 'average'
+ self.inventory_location.company_id = self.env.user.company_id.id
+
+ move1 = self.env['stock.move'].create({
+ 'name': 'Adjustment of 10 units',
+ 'location_id': self.inventory_location.id,
+ 'location_dest_id': self.stock_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 10.0,
+ })
+ move1._action_confirm()
+ move1._action_assign()
+ move1.move_line_ids.qty_done = 10.0
+ move1._action_done()
+ move1.date = date1
+
+ move2 = self.env['stock.move'].create({
+ 'name': 'Sell 5 units',
+ 'location_id': self.stock_location.id,
+ 'location_dest_id': self.inventory_location.id,
+ 'product_id': self.product1.id,
+ 'product_uom': self.uom_unit.id,
+ 'product_uom_qty': 5.0,
+ })
+ move2._action_confirm()
+ move2._action_assign()
+ move2.move_line_ids.qty_done = 5.0
+ move2._action_done()
+ move2.date = date2
+
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).qty_at_date, 10)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date1)).stock_value, 100)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).qty_at_date, 5)
+ self.assertEqual(self.product1.with_context(to_date=Date.to_string(date2)).stock_value, 50)
diff --git a/addons/website_sale/views/templates.xml b/addons/website_sale/views/templates.xml
index 47dd679ba31..306186b841f 100644
--- a/addons/website_sale/views/templates.xml
+++ b/addons/website_sale/views/templates.xml
@@ -346,6 +346,7 @@