summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Simonis <chs@odoo.com>2018-07-10 12:22:55 +0200
committerChristophe Simonis <chs@odoo.com>2018-07-10 12:22:55 +0200
commitc22e479246e7c6fc22d50a6b0813f11795ba2e27 (patch)
treed9a179ff294e8a7ddd5d4689cf30541a8b7a5a65
parentb06c09db604a580acc85eb75ce68f42880ba9b73 (diff)
parent5d8076c842f62d23e7ebcbbf73f57ef263833b0b (diff)
[MERGE] forward port branch saas-14 up to 5d8076c842f
-rw-r--r--addons/account/models/account_move.py6
-rw-r--r--addons/account/tests/test_reconciliation.py68
-rw-r--r--addons/auth_oauth/controllers/main.py4
-rw-r--r--addons/calendar/models/calendar.py8
-rw-r--r--addons/point_of_sale/static/src/js/models.js8
-rw-r--r--addons/sale_stock/tests/test_sale_stock.py4
-rw-r--r--addons/stock/models/stock_picking.py2
-rw-r--r--addons/web/models/ir_http.py4
-rw-r--r--odoo/addons/base/ir/ir_autovacuum.py3
9 files changed, 99 insertions, 8 deletions
diff --git a/addons/account/models/account_move.py b/addons/account/models/account_move.py
index 877ad3cd0d2..da1641854ac 100644
--- a/addons/account/models/account_move.py
+++ b/addons/account/models/account_move.py
@@ -244,6 +244,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
@@ -290,7 +293,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
@@ -1760,7 +1763,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 deeba898ce9..d4dfac560a5 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 a5a888f51a2..0e8270d7eed 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 a8b51aec442..bdf4c2dd329 100644
--- a/addons/calendar/models/calendar.py
+++ b/addons/calendar/models/calendar.py
@@ -872,6 +872,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 7cbef6c99dc..8b938738e85 100644
--- a/addons/point_of_sale/static/src/js/models.js
+++ b/addons/point_of_sale/static/src/js/models.js
@@ -221,7 +221,7 @@ exports.PosModel = Backbone.Model.extend({
fields: ['id', 'journal_ids','name','user_id','config_id','start_at','stop_at','sequence_number','login_number'],
domain: function(self){ return [['state','=','opened'],['user_id','=',session.uid]]; },
loaded: function(self,pos_sessions){
- self.pos_session = pos_sessions[0];
+ self.pos_session = pos_sessions[0];
},
},{
model: 'pos.config',
@@ -241,6 +241,8 @@ exports.PosModel = Backbone.Model.extend({
self.db.set_uuid(self.config.uuid);
self.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++) {
@@ -577,6 +579,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.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 1544c78288c..ab39a0d2129 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.pack_operation_product_ids.write({'qty_done': 1})
- self.assertTrue(pick_2.do_new_transfer(), 'Sale Stock: second picking should be final without need for a backorder')
+ self.assertIsNone(pick_2.do_new_transfer(), '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]
@@ -100,7 +100,7 @@ class TestSaleStock(TestSale):
pick = self.so.picking_ids
pick.force_assign()
pick.pack_operation_product_ids.write({'qty_done': 2})
- self.assertTrue(pick.do_new_transfer(), 'Sale Stock: complete delivery should not need a backorder')
+ self.assertIsNone(pick.do_new_transfer(), '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 2661915b303..0fae5076d7c 100644
--- a/addons/stock/models/stock_picking.py
+++ b/addons/stock/models/stock_picking.py
@@ -842,7 +842,7 @@ class Picking(models.Model):
if pack_operations_delete:
pack_operations_delete.unlink()
self.do_transfer()
- return True
+ return
def check_backorder(self):
need_rereserve, all_op_processed = self.picking_recompute_remaining_quantities(done_qtys=True)
diff --git a/addons/web/models/ir_http.py b/addons/web/models/ir_http.py
index a1fa58ef81d..8d73db777ec 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 {},
}
def get_currencies(self):
diff --git a/odoo/addons/base/ir/ir_autovacuum.py b/odoo/addons/base/ir/ir_autovacuum.py
index a85f82af6a9..67880e72e23 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):
+ if not self.env.user._is_admin():
+ raise AccessDenied()
self.env['ir.attachment']._file_gc()
self._gc_transient_models()
self._gc_user_logs()