diff options
| author | Christophe Simonis <chs@odoo.com> | 2018-07-10 13:21:06 +0200 |
|---|---|---|
| committer | Christophe Simonis <chs@odoo.com> | 2018-07-10 13:21:06 +0200 |
| commit | e354142ce742a96f8e7ba1d86a847a009d3fdfe6 (patch) | |
| tree | 30debd9e770f687f7af60677b24c0db4e64fc825 | |
| parent | 7384401e6365b9b00080154491cbbcc321d9719e (diff) | |
| parent | c22e479246e7c6fc22d50a6b0813f11795ba2e27 (diff) | |
[MERGE] forward port branch saas-15 up to c22e479246e
| -rw-r--r-- | addons/account/models/account_move.py | 6 | ||||
| -rw-r--r-- | addons/account/tests/test_reconciliation.py | 68 | ||||
| -rw-r--r-- | addons/auth_oauth/controllers/main.py | 4 | ||||
| -rw-r--r-- | addons/calendar/models/calendar.py | 8 | ||||
| -rw-r--r-- | addons/point_of_sale/static/src/js/models.js | 6 | ||||
| -rw-r--r-- | addons/sale_stock/tests/test_sale_stock.py | 4 | ||||
| -rw-r--r-- | addons/stock/models/stock_picking.py | 2 | ||||
| -rw-r--r-- | addons/web/models/ir_http.py | 4 | ||||
| -rw-r--r-- | odoo/addons/base/ir/ir_autovacuum.py | 3 |
9 files changed, 98 insertions, 7 deletions
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py index 36bc522d5d5..47798406a25 100644 --- a/addons/account/models/account_move.py +++ b/addons/account/models/account_move.py @@ -249,6 +249,9 @@ class AccountMove(models.Model): date = date or fields.Date.today() reversed_moves = self.env['account.move'] for ac_move in self: + #unreconcile all lines reversed + aml = ac_move.line_ids.filtered(lambda x: x.account_id.reconcile or x.account_id.internal_type == 'liquidity') + aml.remove_move_reconcile() reversed_move = ac_move._reverse_move(date=date, journal_id=journal_id) reversed_moves |= reversed_move @@ -297,7 +300,7 @@ class AccountMoveLine(models.Model): for unreconciled lines, and something in-between for partially reconciled lines. """ for line in self: - if not line.account_id.reconcile: + if not line.account_id.reconcile and line.account_id.internal_type != 'liquidity': line.reconciled = False line.amount_residual = 0 line.amount_residual_currency = 0 @@ -1838,7 +1841,6 @@ class AccountPartialReconcile(models.Model): """ When removing a partial reconciliation, also unlink its full reconciliation if it exists """ full_to_unlink = self.env['account.full.reconcile'] for rec in self: - #without the deleted partial reconciliations, the full reconciliation won't be full anymore if rec.full_reconcile_id: full_to_unlink |= rec.full_reconcile_id #reverse the tax basis move created at the reconciliation time diff --git a/addons/account/tests/test_reconciliation.py b/addons/account/tests/test_reconciliation.py index d40c2937a8c..a1133d72bb1 100644 --- a/addons/account/tests/test_reconciliation.py +++ b/addons/account/tests/test_reconciliation.py @@ -811,3 +811,71 @@ class TestReconciliation(AccountingTestCase): self.assertEqual(positive_line[0]['amount'], 50.0, 'The amount of the amls should be 50') self.assertEqual(negative_line[0]['amount'], -50.0, 'The amount of the amls should be -50') + + def test_revert_payment_and_reconcile_exchange(self): + + # A reversal of a reconciled payment which created a currency exchange entry, should create reversal moves + # which move lines should be reconciled two by two with the original move's lines + + def _determine_debit_credit_line(move): + line_ids_reconciliable = move.line_ids.filtered(lambda l: l.account_id.reconcile or l.account_id.internal_type == 'liquidity') + return line_ids_reconciliable.filtered(lambda l: l.debit), line_ids_reconciliable.filtered(lambda l: l.credit) + + def _move_revert_test_pair(move, revert): + self.assertTrue(move.line_ids) + self.assertTrue(revert.line_ids) + + move_lines = _determine_debit_credit_line(move) + revert_lines = _determine_debit_credit_line(revert) + + # in the case of the exchange entry, only one pair of lines will be found + if move_lines[0] and revert_lines[1]: + self.assertTrue(move_lines[0].full_reconcile_id.exists()) + self.assertEqual(move_lines[0].full_reconcile_id.id, revert_lines[1].full_reconcile_id.id) + + if move_lines[1] and revert_lines[0]: + self.assertTrue(move_lines[1].full_reconcile_id.exists()) + self.assertEqual(move_lines[1].full_reconcile_id.id, revert_lines[0].full_reconcile_id.id) + + self.env['res.currency.rate'].create({ + 'name': time.strftime('%Y') + '-07-01', + 'rate': 1.0, + 'currency_id': self.currency_usd_id, + 'company_id': self.env.ref('base.main_company').id + }) + self.env['res.currency.rate'].create({ + 'name': time.strftime('%Y') + '-08-01', + 'rate': 0.5, + 'currency_id': self.currency_usd_id, + 'company_id': self.env.ref('base.main_company').id + }) + inv = self.create_invoice(invoice_amount=111, currency_id=self.currency_usd_id) + payment = self.env['account.payment'].create({ + 'payment_type': 'inbound', + 'payment_method_id': self.env.ref('account.account_payment_method_manual_in').id, + 'partner_type': 'customer', + 'partner_id': self.partner_agrolait_id, + 'amount': 111, + 'currency_id': self.currency_usd_id, + 'journal_id': self.bank_journal_usd.id, + 'payment_date': time.strftime('%Y') + '-08-01', + }) + payment.post() + + credit_aml = payment.move_line_ids.filtered('credit') + inv.assign_outstanding_credit(credit_aml.id) + self.assertTrue(inv.state == 'paid', 'The invoice should be paid') + + exchange_reconcile = payment.move_line_ids.mapped('full_reconcile_id') + exchange_move = exchange_reconcile.exchange_move_id + payment_move = payment.move_line_ids[0].move_id + + reverted_payment_move = self.env['account.move'].browse(payment_move.reverse_moves(time.strftime('%Y') + '-08-01')) + + # After reversal of payment, the invoice should be open + self.assertTrue(inv.state == 'open', 'The invoice should be open again') + self.assertFalse(exchange_reconcile.exists()) + + reverted_exchange_move = self.env['account.move'].search([('journal_id', '=', exchange_move.journal_id.id), ('ref', 'ilike', exchange_move.name)], limit=1) + _move_revert_test_pair(payment_move, reverted_payment_move) + _move_revert_test_pair(exchange_move, reverted_exchange_move) diff --git a/addons/auth_oauth/controllers/main.py b/addons/auth_oauth/controllers/main.py index e231cd0f6d0..3b300070929 100644 --- a/addons/auth_oauth/controllers/main.py +++ b/addons/auth_oauth/controllers/main.py @@ -131,6 +131,8 @@ class OAuthController(http.Controller): def signin(self, **kw): state = json.loads(kw['state']) dbname = state['d'] + if not http.db_filter([dbname]): + return BadRequest() provider = state['p'] context = state.get('c', {}) registry = registry_get(dbname) @@ -180,6 +182,8 @@ class OAuthController(http.Controller): dbname = db_monodb() if not dbname: return BadRequest() + if not http.db_filter([dbname]): + return BadRequest() registry = registry_get(dbname) with registry.cursor() as cr: diff --git a/addons/calendar/models/calendar.py b/addons/calendar/models/calendar.py index e5a006088be..7e67db98496 100644 --- a/addons/calendar/models/calendar.py +++ b/addons/calendar/models/calendar.py @@ -944,6 +944,14 @@ class Meeting(models.Model): self.start = self.start_datetime self.stop = fields.Datetime.to_string(start + timedelta(hours=self.duration)) + @api.onchange('start_date') + def _onchange_start_date(self): + self.start = self.start_date + + @api.onchange('stop_date') + def _onchange_stop_date(self): + self.stop = self.stop_date + #################################################### # Calendar Business, Reccurency, ... #################################################### diff --git a/addons/point_of_sale/static/src/js/models.js b/addons/point_of_sale/static/src/js/models.js index 6394df4921c..942559bb8bf 100644 --- a/addons/point_of_sale/static/src/js/models.js +++ b/addons/point_of_sale/static/src/js/models.js @@ -245,6 +245,8 @@ exports.PosModel = Backbone.Model.extend({ self.db.set_uuid(self.config.uuid); self.set_cashier(self.get_cashier()); + // We need to do it here, since only then the local storage has the correct uuid + self.db.save('pos_session_id', self.pos_session.id); var orders = self.db.get_orders(); for (var i = 0; i < orders.length; i++) { @@ -627,6 +629,10 @@ exports.PosModel = Backbone.Model.extend({ // returns the user who is currently the cashier for this point of sale get_cashier: function(){ + // reset the cashier to the current user if session is new + if (this.db.load('pos_session_id') !== this.pos_session.id) { + this.set_cashier(this.user); + } return this.db.get_cashier() || this.get('cashier') || this.user; }, // changes the current cashier diff --git a/addons/sale_stock/tests/test_sale_stock.py b/addons/sale_stock/tests/test_sale_stock.py index 517d1dbdd70..c99f211ce50 100644 --- a/addons/sale_stock/tests/test_sale_stock.py +++ b/addons/sale_stock/tests/test_sale_stock.py @@ -52,7 +52,7 @@ class TestSaleStock(TestSale): pick_2 = self.so.picking_ids[0] pick_2.force_assign() pick_2.move_lines.write({'quantity_done': 1}) - self.assertTrue(pick_2.button_validate(), 'Sale Stock: second picking should be final without need for a backorder') + self.assertIsNone(pick_2.button_validate(), 'Sale Stock: second picking should be final without need for a backorder') self.assertEqual(self.so.invoice_status, 'to invoice', 'Sale Stock: so invoice_status should be "to invoice" after complete delivery') del_qties = [sol.qty_delivered for sol in self.so.order_line] del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line] @@ -104,7 +104,7 @@ class TestSaleStock(TestSale): pick = self.so.picking_ids pick.force_assign() pick.move_lines.write({'quantity_done': 2}) - self.assertTrue(pick.button_validate(), 'Sale Stock: complete delivery should not need a backorder') + self.assertIsNone(pick.button_validate(), 'Sale Stock: complete delivery should not need a backorder') del_qties = [sol.qty_delivered for sol in self.so.order_line] del_qties_truth = [2.0 if sol.product_id.type in ['product', 'consu'] else 0.0 for sol in self.so.order_line] self.assertEqual(del_qties, del_qties_truth, 'Sale Stock: delivered quantities are wrong after partial delivery') diff --git a/addons/stock/models/stock_picking.py b/addons/stock/models/stock_picking.py index 0017e805dd2..314fee31e06 100644 --- a/addons/stock/models/stock_picking.py +++ b/addons/stock/models/stock_picking.py @@ -757,7 +757,7 @@ class Picking(models.Model): if self._check_backorder(): return self.action_generate_backorder_wizard() self.action_done() - return True + return def action_generate_backorder_wizard(self): view = self.env.ref('stock.view_backorder_confirmation') diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py index 23a87f4cd02..e17baa55077 100644 --- a/addons/web/models/ir_http.py +++ b/addons/web/models/ir_http.py @@ -26,7 +26,7 @@ class Http(models.AbstractModel): "session_id": request.session.sid, "uid": request.session.uid, "is_system": request.env.user._is_system(), - "is_superuser": request.env.user._is_superuser(), + "is_superuser": request.env.user._is_superuser() if request.session.uid else False, "user_context": request.session.get_context() if request.session.uid else {}, "db": request.session.db, "server_version": version_info.get('server_version'), @@ -36,7 +36,7 @@ class Http(models.AbstractModel): "company_id": request.env.user.company_id.id if request.session.uid else None, "partner_id": request.env.user.partner_id.id if request.session.uid and request.env.user.partner_id else None, "user_companies": {'current_company': (user.company_id.id, user.company_id.name), 'allowed_companies': [(comp.id, comp.name) for comp in user.company_ids]} if display_switch_company_menu else False, - "currencies": self.get_currencies(), + "currencies": self.get_currencies() if request.session.uid else {}, "web.base.url": self.env['ir.config_parameter'].sudo().get_param('web.base.url', default=''), } diff --git a/odoo/addons/base/ir/ir_autovacuum.py b/odoo/addons/base/ir/ir_autovacuum.py index 8ffdb0b1b3e..8cef88e7c20 100644 --- a/odoo/addons/base/ir/ir_autovacuum.py +++ b/odoo/addons/base/ir/ir_autovacuum.py @@ -4,6 +4,7 @@ import logging from odoo import api, models +from odoo.exceptions import AccessDenied _logger = logging.getLogger(__name__) @@ -36,6 +37,8 @@ class AutoVacuum(models.AbstractModel): @api.model def power_on(self, *args, **kwargs): + if not self.env.user._is_admin(): + raise AccessDenied() self.env['ir.attachment']._file_gc() self._gc_transient_models() self._gc_user_logs() |
