[MERGE] forward port branch saas-15 up to c301122b5f

This commit is contained in:
Christophe Simonis
2018-06-05 15:10:45 +02:00
14 changed files with 180 additions and 15 deletions
+58 -1
View File
@@ -2,10 +2,12 @@
from datetime import timedelta, datetime
import calendar
import time
from dateutil.relativedelta import relativedelta
from odoo import fields, models, api, _
from odoo.exceptions import ValidationError, UserError
from odoo.exceptions import UserError
from odoo.tools.misc import DEFAULT_SERVER_DATE_FORMAT
from odoo.tools.float_utils import float_round, float_is_zero
@@ -62,6 +64,61 @@ Best Regards,'''))
account_setup_coa_done = fields.Boolean(string='Chart of Account Checked', help="Technical field holding the status of the chart of account setup step.")
account_setup_bar_closed = fields.Boolean(string='Setup Bar Closed', help="Technical field set to True when setup bar has been closed by the user.")
@api.multi
def _check_lock_dates(self, vals):
'''Check the lock dates for the current companies. This can't be done in a api.constrains because we need
to perform some comparison between new/old values. This method forces the lock dates to be irreversible.
* You cannot define stricter conditions on advisors than on users. Then, the lock date on advisor must be set
after the lock date for users.
* You cannot lock a period that is not finished yet. Then, the lock date for advisors must be set after the
last day of the previous month.
* The new lock date for advisors must be set after the previous lock date.
:param vals: The values passed to the write method.
'''
period_lock_date = vals.get('period_lock_date') and\
time.strptime(vals['period_lock_date'], DEFAULT_SERVER_DATE_FORMAT)
fiscalyear_lock_date = vals.get('fiscalyear_lock_date') and\
time.strptime(vals['fiscalyear_lock_date'], DEFAULT_SERVER_DATE_FORMAT)
previous_month = datetime.strptime(fields.Date.today(), DEFAULT_SERVER_DATE_FORMAT) + relativedelta(months=-1)
days_previous_month = calendar.monthrange(previous_month.year, previous_month.month)
previous_month = previous_month.replace(day=days_previous_month[1]).timetuple()
for company in self:
old_fiscalyear_lock_date = company.fiscalyear_lock_date and\
time.strptime(company.fiscalyear_lock_date, DEFAULT_SERVER_DATE_FORMAT)
# The user attempts to remove the lock date for advisors
if old_fiscalyear_lock_date and not fiscalyear_lock_date and 'fiscalyear_lock_date' in vals:
raise ValidationError(_('The lock date for advisors is irreversible and can\'t be removed.'))
# The user attempts to set a lock date for advisors prior to the previous one
if old_fiscalyear_lock_date and fiscalyear_lock_date and fiscalyear_lock_date < old_fiscalyear_lock_date:
raise ValidationError(_('The new lock date for advisors must be set after the previous lock date.'))
# In case of no new fiscal year in vals, fallback to the oldest
if not fiscalyear_lock_date:
if old_fiscalyear_lock_date:
fiscalyear_lock_date = old_fiscalyear_lock_date
else:
continue
# The user attempts to set a lock date for advisors prior to the last day of previous month
if fiscalyear_lock_date > previous_month:
raise ValidationError(_('You cannot lock a period that is not finished yet. Please make sure that the lock date for advisors is not set after the last day of the previous month.'))
# In case of no new period lock date in vals, fallback to the one defined in the company
if not period_lock_date:
if company.period_lock_date:
period_lock_date = time.strptime(company.period_lock_date, DEFAULT_SERVER_DATE_FORMAT)
else:
continue
# The user attempts to set a lock date for advisors prior to the lock date for users
if period_lock_date < fiscalyear_lock_date:
raise ValidationError(_('You cannot define stricter conditions on advisors than on users. Please make sure that the lock date on advisor is set before the lock date for users.'))
@api.model
def _verify_fiscalyear_last_day(self, company_id, last_day, last_month):
company = self.browse(company_id)
@@ -1,6 +1,8 @@
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
from odoo.osv.orm import except_orm
from datetime import datetime, timedelta
from datetime import datetime
from dateutil.relativedelta import relativedelta
from calendar import monthrange
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT
class TestPeriodState(AccountingTestCase):
@@ -11,14 +13,16 @@ class TestPeriodState(AccountingTestCase):
def setUp(self):
super(TestPeriodState, self).setUp()
self.user_id = self.env.user
self.day_before_yesterday = datetime.now() - timedelta(2)
self.yesterday = datetime.now() - timedelta(1)
self.yesterday_str = self.yesterday.strftime(DEFAULT_SERVER_DATE_FORMAT)
last_day_month = datetime.now() - relativedelta(months=1)
last_day_month = last_day_month.replace(day=monthrange(last_day_month.year, last_day_month.month)[1])
self.last_day_month_str = last_day_month.strftime(DEFAULT_SERVER_DATE_FORMAT)
#make sure there is no unposted entry
draft_entries = self.env['account.move'].search([('date', '<=', self.yesterday_str), ('state', '=', 'draft')])
draft_entries = self.env['account.move'].search([('date', '<=', self.last_day_month_str), ('state', '=', 'draft')])
if draft_entries:
draft_entries.post()
self.user_id.company_id.write({'fiscalyear_lock_date': self.yesterday_str})
self.user_id.company_id.fiscalyear_lock_date = self.last_day_month_str
self.sale_journal_id = self.env['account.journal'].search([('type', '=', 'sale')])[0]
self.account_id = self.env['account.account'].search([('internal_type', '=', 'receivable')])[0]
@@ -27,7 +31,7 @@ class TestPeriodState(AccountingTestCase):
move = self.env['account.move'].create({
'name': '/',
'journal_id': self.sale_journal_id.id,
'date': self.day_before_yesterday.strftime(DEFAULT_SERVER_DATE_FORMAT),
'date': self.last_day_month_str,
'line_ids': [(0, 0, {
'name': 'foo',
'debit': 10,
@@ -40,6 +40,12 @@ class TestReconciliation(AccountingTestCase):
self.diff_income_account = self.env['res.users'].browse(self.env.uid).company_id.income_currency_exchange_account_id
self.diff_expense_account = self.env['res.users'].browse(self.env.uid).company_id.expense_currency_exchange_account_id
self.inbound_payment_method = self.env['account.payment.method'].create({
'name': 'inbound',
'code': 'IN',
'payment_type': 'inbound',
})
def create_invoice(self, type='out_invoice', invoice_amount=50, currency_id=None):
#we create an invoice in given currency
invoice = self.account_invoice_model.create({'partner_id': self.partner_agrolait_id,
@@ -705,3 +711,46 @@ class TestReconciliation(AccountingTestCase):
# Unreconcile invoice and check residual
credit_aml.with_context(invoice_id=inv.id).remove_move_reconcile()
self.assertAlmostEquals(inv.residual, 111)
def test_revert_payment_and_reconcile(self):
payment = self.env['account.payment'].create({
'payment_method_id': self.inbound_payment_method.id,
'payment_type': 'inbound',
'partner_type': 'customer',
'partner_id': self.partner_agrolait_id,
'journal_id': self.bank_journal_usd.id,
'payment_date': '2018-06-04',
'amount': 666,
})
payment.post()
self.assertEqual(len(payment.move_line_ids), 2)
bank_line = payment.move_line_ids.filtered(lambda l: l.account_id.id == self.bank_journal_usd.default_debit_account_id.id)
customer_line = payment.move_line_ids - bank_line
self.assertEqual(len(bank_line), 1)
self.assertEqual(len(customer_line), 1)
self.assertNotEqual(bank_line.id, customer_line.id)
self.assertEqual(bank_line.move_id.id, customer_line.move_id.id)
move = bank_line.move_id
# Reversing the payment's move
reversed_move_list = move.reverse_moves('2018-06-04')
self.assertEqual(len(reversed_move_list), 1)
reversed_move = self.env['account.move'].browse(reversed_move_list[0])
self.assertEqual(len(reversed_move.line_ids), 2)
# Testing the reconciliation matching between the move lines and their reversed counterparts
reversed_bank_line = reversed_move.line_ids.filtered(lambda l: l.account_id.id == self.bank_journal_usd.default_debit_account_id.id)
reversed_customer_line = reversed_move.line_ids - reversed_bank_line
self.assertEqual(len(reversed_bank_line), 1)
self.assertEqual(len(reversed_customer_line), 1)
self.assertNotEqual(reversed_bank_line.id, reversed_customer_line.id)
self.assertEqual(reversed_bank_line.move_id.id, reversed_customer_line.move_id.id)
self.assertEqual(reversed_bank_line.full_reconcile_id.id, bank_line.full_reconcile_id.id)
self.assertEqual(reversed_customer_line.full_reconcile_id.id, customer_line.full_reconcile_id.id)
+3
View File
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models
+16
View File
@@ -0,0 +1,16 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
{
'name' : 'Irreversible Lock Date',
'version' : '1.0',
'category': 'Accounting',
'description': """
Make the lock date irreversible:
* You cannot define stricter conditions on advisors than on users. Then, the lock date on advisor must be set before the lock date for users.
* You cannot lock a period that is not finished yet. Then, the lock date for advisors must be set before the last day of the previous month.
* The new lock date for advisors must be set after the previous lock date.
""",
'depends' : ['account'],
'data': [],
}
+3
View File
@@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import res_company
+14
View File
@@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from odoo import models, api
class ResCompany(models.Model):
_inherit = 'res.company'
@api.multi
def write(self, vals):
# fiscalyear_lock_date can't be set to a prior date
if 'fiscalyear_lock_date' in vals or 'period_lock_date' in vals:
self._check_lock_dates(vals)
return super(ResCompany, self).write(vals)
@@ -842,7 +842,7 @@ class GoogleCalendar(models.AbstractModel):
try:
# if already deleted from gmail or never created
recs.delete_an_event(current_event[0])
except Exception as e:
except requests.exceptions.HTTPError as e:
if e.response.status_code in (401, 410,):
pass
else:
+4
View File
@@ -522,6 +522,10 @@ class Escpos:
# Print Code
if code:
self._raw(code)
# We are using type A commands
# So we need to add the 'NULL' character
# https://github.com/python-escpos/python-escpos/pull/98/files#diff-a0b1df12c7c67e38915adbe469051e2dR444
self._raw('\x00')
else:
raise exception.BarcodeCodeError()
@@ -30,6 +30,9 @@ class ResCompany(models.Model):
if company._is_accounting_unalterable():
sequence_fields = ['l10n_fr_secure_sequence_id']
company._create_secure_sequence(sequence_fields)
# fiscalyear_lock_date can't be set to a prior date
if 'fiscalyear_lock_date' in vals or 'period_lock_date' in vals:
self._check_lock_dates(vals)
return res
def _create_secure_sequence(self, sequence_fields):
+1 -1
View File
@@ -92,7 +92,7 @@ class MailMail(models.Model):
def send_get_email_dict(self, partner=None):
# TDE: temporary addition (mail was parameter) due to semi-new-API
res = super(MailMail, self).send_get_email_dict(partner)
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url')
base_url = self.env['ir.config_parameter'].sudo().get_param('web.base.url').rstrip('/')
if self.mailing_id and res.get('body') and res.get('email_to'):
emails = tools.email_split(res.get('email_to')[0])
email_to = emails and emails[0] or False
+1 -1
View File
@@ -24,7 +24,7 @@ class ProductTemplate(models.Model):
@api.depends('product_variant_ids.sales_count')
def _sales_count(self):
for product in self:
product.sales_count = sum([p.sales_count for p in product.product_variant_ids])
product.sales_count = sum([p.sales_count for p in product.with_context(active_test=False).product_variant_ids])
@api.multi
def action_view_sales(self):
@@ -456,6 +456,13 @@ msgstr ""
msgid "Photos of Past Events"
msgstr ""
#. module: website_event
#: code:addons/website_event/static/src/js/website_event.js:37
#, python-format
msgid "Please select at least one ticket."
msgstr ""
#. module: website_event
#: model:ir.ui.view,arch_db:website_event.ticket
msgid "Price"
@@ -20,8 +20,11 @@ return instance.appendTo($form).then(function () {
odoo.define('website_event.website_event', function (require) {
var ajax = require('web.ajax');
var core = require('web.core');
var Widget = require('web.Widget');
var _t = core._t;
// Catch registration form event, because of JS for attendee details
var EventRegistrationForm = Widget.extend({
start: function () {
@@ -31,7 +34,6 @@ var EventRegistrationForm = Widget.extend({
.off('click')
.removeClass('a-submit')
.click(function (ev) {
$(this).attr('disabled', true);
self.on_click(ev);
});
});
@@ -43,15 +45,18 @@ var EventRegistrationForm = Widget.extend({
var $form = $(ev.currentTarget).closest('form');
var $button = $(ev.currentTarget).closest('[type="submit"]');
var post = {};
$('#registration_form table').siblings('.alert').remove();
$('#registration_form select').each(function () {
post[$(this).attr('name')] = $(this).val();
});
var tickets_ordered = _.some(_.map(post, function (value, key) { return parseInt(value); }));
if (!tickets_ordered) {
return $('#registration_form table').after(
'<div class="alert alert-info">Please select at least one ticket.</div>'
);
$('<div class="alert alert-info"/>')
.text(_t('Please select at least one ticket.'))
.insertAfter('#registration_form table');
return $.Deferred();
} else {
$button.attr('disabled', true);
return ajax.jsonRpc($form.attr('action'), 'call', post).then(function (modal) {
var $modal = $(modal);
$modal.find('.modal-body > div').removeClass('container'); // retrocompatibility - REMOVE ME in master / saas-19