diff options
| author | Martin Trigaux <mat@odoo.com> | 2019-07-22 11:17:40 +0000 |
|---|---|---|
| committer | Martin Trigaux <mat@odoo.com> | 2019-07-22 11:43:54 +0000 |
| commit | 324d3fc93a00a919d4a561f713ec2c5dd0d6b51c (patch) | |
| tree | 3487e89e219b6d3357635c7ed620447dadfab443 | |
| parent | f58fa65c2bb1f6ec65b3b9ed7227975ce2799e83 (diff) | |
| parent | 06f8f0469915f6686d9f5f6f1ab5feff18722ffd (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.py | 17 | ||||
| -rw-r--r-- | addons/account_payment/views/account_portal_templates.xml | 2 | ||||
| -rw-r--r-- | addons/delivery/__manifest__.py | 1 | ||||
| -rw-r--r-- | addons/delivery/static/src/js/delivery_translations.js | 16 | ||||
| -rw-r--r-- | addons/delivery/views/assets.xml | 10 | ||||
| -rw-r--r-- | addons/fleet/views/fleet_vehicle_cost_views.xml | 2 | ||||
| -rw-r--r-- | addons/payment/static/src/js/payment_translations.js | 10 | ||||
| -rw-r--r-- | addons/payment/views/assets.xml | 7 | ||||
| -rw-r--r-- | addons/payment_authorize/models/payment.py | 30 | ||||
| -rw-r--r-- | addons/payment_authorize/views/payment_views.xml | 1 | ||||
| -rw-r--r-- | addons/stock/models/product.py | 20 | ||||
| -rw-r--r-- | addons/stock_account/models/stock.py | 2 | ||||
| -rw-r--r-- | addons/stock_account/tests/test_stockvaluation.py | 48 | ||||
| -rw-r--r-- | addons/website_sale/views/templates.xml | 1 | ||||
| -rw-r--r-- | doc/reference/qweb.rst | 5 |
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`` |
