summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Trigaux <mat@odoo.com>2019-07-22 11:17:40 +0000
committerMartin Trigaux <mat@odoo.com>2019-07-22 11:43:54 +0000
commit324d3fc93a00a919d4a561f713ec2c5dd0d6b51c (patch)
tree3487e89e219b6d3357635c7ed620447dadfab443
parentf58fa65c2bb1f6ec65b3b9ed7227975ce2799e83 (diff)
parent06f8f0469915f6686d9f5f6f1ab5feff18722ffd (diff)
[MERGE] Forward port of saas-11.3 to 12.0 up to 06f8f046991
closes odoo/odoo#35064 Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
-rw-r--r--addons/account/models/account_payment.py17
-rw-r--r--addons/account_payment/views/account_portal_templates.xml2
-rw-r--r--addons/delivery/__manifest__.py1
-rw-r--r--addons/delivery/static/src/js/delivery_translations.js16
-rw-r--r--addons/delivery/views/assets.xml10
-rw-r--r--addons/fleet/views/fleet_vehicle_cost_views.xml2
-rw-r--r--addons/payment/static/src/js/payment_translations.js10
-rw-r--r--addons/payment/views/assets.xml7
-rw-r--r--addons/payment_authorize/models/payment.py30
-rw-r--r--addons/payment_authorize/views/payment_views.xml1
-rw-r--r--addons/stock/models/product.py20
-rw-r--r--addons/stock_account/models/stock.py2
-rw-r--r--addons/stock_account/tests/test_stockvaluation.py48
-rw-r--r--addons/website_sale/views/templates.xml1
-rw-r--r--doc/reference/qweb.rst5
15 files changed, 155 insertions, 17 deletions
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 @@
<div t-if="pms or acquirers" id="payment_method" class="text-left col-md-13">
<t t-call="payment.payment_tokens_list">
<t t-set="mode" t-value="'payment'"/>
- <t t-set="partner_id" t-value="request.env.user.partner_id.id"/>
+ <t t-set="partner_id" t-value="invoice.partner_id.id if request.env.user._is_public() else request.env.user.partner_id.id"/>
<t t-set="success_url" t-value="invoice.get_portal_url()"/>
<t t-set="error_url" t-value="invoice.get_portal_url()"/>
<t t-set="access_token" t-value="access_token or ''"/>
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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<odoo>
+
+ <template id="assets_backend" name="delivery_assets_backend" inherit_id="web.assets_backend">
+ <xpath expr="." position="inside">
+ <script type="text/javascript" src="/delivery/static/src/js/delivery_translations.js"></script>
+ </xpath>
+ </template>
+
+</odoo>
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 @@
<group>
<field name="date" string="Invoice Date"/>
<field name="start_date"/>
- <field name="expiration_date" />
+ <field name="expiration_date" attrs="{'required': [('cost_frequency', '!=', 'no')]}"/>
</group>
<group>
<field name="insurer_id" context="{'default_supplier': True}"/>
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 @@
<script type="text/javascript" src="/payment/static/src/js/payment_processing.js"></script>
</xpath>
</template>
+
+ <template id="assets_backend" name="payment_assets_backend" inherit_id="web.assets_backend">
+ <xpath expr="." position="inside">
+ <script type="text/javascript" src="/payment/static/src/js/payment_translations.js"></script>
+ </xpath>
+ </template>
+
</odoo>
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 @@
<group attrs="{'invisible': [('provider', '!=', 'authorize')]}">
<field name="authorize_login"/>
<field name="authorize_transaction_key" password="True"/>
+ <field name="authorize_signature_key" password="True"/>
<a colspan="2" href="https://www.odoo.com/documentation/user/online/ecommerce/shopper_experience/authorize.html" target="_blank">How to get paid with Authorize.Net</a>
</group>
</xpath>
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 @@
<template id="products_attributes" inherit_id="website_sale.products" active="False" customize_show="True" name="Product Attribute's Filters">
<xpath expr="//div[@id='products_grid_before']" position="inside">
<form class="js_attributes" method="get">
+ <input t-if="category" type="hidden" name="category" t-att-value="category.id" />
<input type="hidden" name="search" t-att-value="search" />
<ul class="nav nav-pills flex-column mt16">
<t t-foreach="attributes" t-as="a">
diff --git a/doc/reference/qweb.rst b/doc/reference/qweb.rst
index 2954d0bf167..f4f464f7aa9 100644
--- a/doc/reference/qweb.rst
+++ b/doc/reference/qweb.rst
@@ -490,6 +490,11 @@ on the extended template to select *context nodes* to which the specified
the node's body replaces the context node's children
``replace``
the node's body is used to replace the context node itself
+``attributes``
+ the nodes's body should be any number of ``attribute`` elements,
+ each with a ``name`` attribute and some textual content, the named
+ attribute of the context node will be set to the specified value
+ (either replaced if it already existed or added if not)
No operation
if no ``t-operation`` is specified, the template body is interpreted as
javascript code and executed with the context node as ``this``