Skip to content

Commit

Permalink
[REF] *: use native date/datetime for Date/Datetime fields
Browse files Browse the repository at this point in the history
From this commit onwards, Date fields will return datetime.date objects and Datetime fields will return datetime.datetime objects, this implies a number of things that are clearly explained both in the ORM API for master.

This commit also introduces a number of helper functions for dates and datetimes that are exposed in tools.date_utils and fields.Date[time], explained in the documentation as well.

Task-ID: 47189
  • Loading branch information
rco-odoo authored and Adrian Torres committed Aug 6, 2018
1 parent 09ba95b commit 960360a
Show file tree
Hide file tree
Showing 82 changed files with 770 additions and 454 deletions.
5 changes: 2 additions & 3 deletions addons/account/models/account_fiscal_year.py
Expand Up @@ -2,7 +2,6 @@

from odoo.exceptions import ValidationError
from odoo import api, fields, models, _
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT


from datetime import datetime
Expand Down Expand Up @@ -37,8 +36,8 @@ def _check_dates(self):
'''
for fy in self:
# Starting date must be prior to the ending date
date_from = datetime.strptime(fy.date_from, DEFAULT_SERVER_DATE_FORMAT)
date_to = datetime.strptime(fy.date_to, DEFAULT_SERVER_DATE_FORMAT)
date_from = fy.date_from
date_to = fy.date_to
if date_to < date_from:
raise ValidationError(_('The ending date must not be prior to the starting date.'))

Expand Down
5 changes: 3 additions & 2 deletions addons/account/models/account_invoice.py
Expand Up @@ -10,7 +10,8 @@
from werkzeug.urls import url_encode

from odoo import api, exceptions, fields, models, _
from odoo.tools import email_re, email_split, email_escape_char, float_is_zero, float_compare, pycompat
from odoo.tools import email_re, email_split, email_escape_char, float_is_zero, float_compare, \
pycompat, date_utils
from odoo.tools.misc import formatLang

from odoo.exceptions import AccessError, UserError, RedirectWarning, ValidationError, Warning
Expand Down Expand Up @@ -216,7 +217,7 @@ def _get_payment_info_JSON(self):
self.payments_widget = json.dumps(False)
if self.payment_move_line_ids:
info = {'title': _('Less Payment'), 'outstanding': False, 'content': self._get_payments_vals()}
self.payments_widget = json.dumps(info)
self.payments_widget = json.dumps(info, default=date_utils.json_default)

@api.one
@api.depends('move_id.line_ids.amount_residual')
Expand Down
4 changes: 2 additions & 2 deletions addons/account/models/account_journal_dashboard.py
Expand Up @@ -76,7 +76,7 @@ def build_graph_data(date, amount):
"""
self.env.cr.execute(query, (self.id, last_month, today))
for val in self.env.cr.dictfetchall():
date = datetime.strptime(val['date'], DF)
date = val['date']
if val['date'] != today.strftime(DF): # make sure the last point in the graph is today
data[:0] = [build_graph_data(date, amount)]
amount -= val['amount']
Expand All @@ -92,7 +92,7 @@ def build_graph_data(date, amount):
@api.multi
def get_bar_graph_datas(self):
data = []
today = datetime.strptime(fields.Date.context_today(self), DF)
today = fields.Date.context_today(self)
data.append({'label': _('Past'), 'value':0.0, 'type': 'past'})
day_of_week = int(format_datetime(today, 'e', locale=self._context.get('lang') or 'en_US'))
first_day_of_week = today + timedelta(days=-day_of_week+1)
Expand Down
17 changes: 9 additions & 8 deletions addons/account/models/account_move.py
@@ -1,6 +1,7 @@
# -*- coding: utf-8 -*-

import time
from datetime import date
from collections import OrderedDict
from odoo import api, fields, models, _
from odoo.osv import expression
Expand Down Expand Up @@ -345,10 +346,10 @@ def _post_validate(self):
@api.multi
def _check_lock_date(self):
for move in self:
lock_date = max(move.company_id.period_lock_date or '0000-00-00', move.company_id.fiscalyear_lock_date or '0000-00-00')
lock_date = max(move.company_id.period_lock_date or date.min, move.company_id.fiscalyear_lock_date or date.min)
if self.user_has_groups('account.group_account_manager'):
lock_date = move.company_id.fiscalyear_lock_date
if move.date <= (lock_date or '0000-00-00'):
if move.date <= (lock_date or date.min):
if self.user_has_groups('account.group_account_manager'):
message = _("You cannot add/modify entries prior to and inclusive of the lock date %s") % (lock_date)
else:
Expand Down Expand Up @@ -738,7 +739,7 @@ def check_full_reconcile(self):
total_debit = 0
total_credit = 0
total_amount_currency = 0
maxdate = '0000-00-00'
maxdate = date.min
to_balance = {}
for aml in amls:
total_debit += aml.debit
Expand Down Expand Up @@ -947,15 +948,15 @@ def compute_writeoff_counterpart_vals(values):
total = 0
total_currency = 0
writeoff_lines = []
date = time.strftime('%Y-%m-%d')
date = fields.Date.today()
for vals in lines:
# Check and complete vals
if 'account_id' not in vals or 'journal_id' not in vals:
raise UserError(_("It is mandatory to specify an account and a journal to create a write-off."))
if ('debit' in vals) ^ ('credit' in vals):
raise UserError(_("Either pass both debit and credit or none."))
if 'date' not in vals:
vals['date'] = self._context.get('date_p') or time.strftime('%Y-%m-%d')
vals['date'] = self._context.get('date_p') or fields.Date.today()
if vals['date'] < date:
date = vals['date']
if 'name' not in vals:
Expand Down Expand Up @@ -1369,8 +1370,8 @@ class AccountPartialReconcile(models.Model):
def _compute_max_date(self):
for rec in self:
rec.max_date = max(
fields.Datetime.from_string(rec.debit_move_id.date),
fields.Datetime.from_string(rec.credit_move_id.date)
rec.debit_move_id.date,
rec.credit_move_id.date
)

@api.model
Expand Down Expand Up @@ -1608,6 +1609,6 @@ def _prepare_exchange_diff_move(self, move_date, company):
# The move date should be the maximum date between payment and invoice
# (in case of payment in advance). However, we should make sure the
# move date is not recorded after the end of year closing.
if move_date > (company.fiscalyear_lock_date or '0000-00-00'):
if move_date > (company.fiscalyear_lock_date or date.min):
res['date'] = move_date
return res
23 changes: 11 additions & 12 deletions addons/account/models/company.py
Expand Up @@ -9,7 +9,7 @@
from odoo.exceptions import ValidationError, UserError, RedirectWarning
from odoo.tools.misc import DEFAULT_SERVER_DATE_FORMAT
from odoo.tools.float_utils import float_round, float_is_zero
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT, date_utils
from odoo.tools import date_utils


class ResCompany(models.Model):
Expand Down Expand Up @@ -110,16 +110,15 @@ def _check_lock_dates(self, vals):
: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)
fields.Date.from_string(vals['period_lock_date'])
fiscalyear_lock_date = vals.get('fiscalyear_lock_date') and\
time.strptime(vals['fiscalyear_lock_date'], DEFAULT_SERVER_DATE_FORMAT)
fields.Date.from_string(vals['fiscalyear_lock_date'])

previous_month = datetime.strptime(fields.Date.today(), DEFAULT_SERVER_DATE_FORMAT) + relativedelta(months=-1)
previous_month = fields.Date.today() + 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()
previous_month = previous_month.replace(day=days_previous_month[1])
for company in self:
old_fiscalyear_lock_date = company.fiscalyear_lock_date and\
time.strptime(company.fiscalyear_lock_date, DEFAULT_SERVER_DATE_FORMAT)
old_fiscalyear_lock_date = company.fiscalyear_lock_date

# 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:
Expand All @@ -143,7 +142,7 @@ def _check_lock_dates(self, vals):
# 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)
period_lock_date = company.period_lock_date
else:
continue

Expand Down Expand Up @@ -182,8 +181,8 @@ def compute_fiscalyear_dates(self, current_date):
], limit=1)
if fiscalyear:
return {
'date_from': datetime.strptime(fiscalyear.date_from, DEFAULT_SERVER_DATE_FORMAT).date(),
'date_to': datetime.strptime(fiscalyear.date_to, DEFAULT_SERVER_DATE_FORMAT).date(),
'date_from': fiscalyear.date_from,
'date_to': fiscalyear.date_to,
'record': fiscalyear,
}

Expand All @@ -204,15 +203,15 @@ def compute_fiscalyear_dates(self, current_date):
('date_to', '>=', date_from_str),
], limit=1)
if fiscalyear_from:
date_from = datetime.strptime(fiscalyear_from.date_to, DEFAULT_SERVER_DATE_FORMAT).date() + timedelta(days=1)
date_from = fiscalyear_from.date_to + timedelta(days=1)

fiscalyear_to = self.env['account.fiscal.year'].search([
('company_id', '=', self.id),
('date_from', '<=', date_to_str),
('date_to', '>=', date_to_str),
], limit=1)
if fiscalyear_to:
date_to = datetime.strptime(fiscalyear_to.date_from, DEFAULT_SERVER_DATE_FORMAT).date() - timedelta(days=1)
date_to = fiscalyear_to.date_from - timedelta(days=1)

return {'date_from': date_from, 'date_to': date_to}

Expand Down
7 changes: 4 additions & 3 deletions addons/account/report/account_aged_partner_balance.py
@@ -1,7 +1,7 @@
# -*- coding: utf-8 -*-

import time
from odoo import api, models, _
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools import float_is_zero
from datetime import datetime
Expand All @@ -19,7 +19,8 @@ def _get_partner_move_lines(self, account_type, date_from, target_move, period_l
# The context key allow it to appear
ctx = self._context
periods = {}
start = datetime.strptime(date_from, "%Y-%m-%d") - relativedelta(days=1)
date_from = fields.Date.from_string(date_from)
start = date_from - relativedelta(days=1)
for i in range(5)[::-1]:
stop = start - relativedelta(days=period_length)
periods[str(i)] = {
Expand Down Expand Up @@ -220,7 +221,7 @@ def _get_report_values(self, docids, data=None):
docs = self.env[model].browse(self.env.context.get('active_id'))

target_move = data['form'].get('target_move', 'all')
date_from = data['form'].get('date_from', time.strftime('%Y-%m-%d'))
date_from = fields.Date.from_string(data['form'].get('date_from')) or fields.Date.today()

if data['form']['result_selection'] == 'customer':
account_type = ['receivable']
Expand Down
2 changes: 0 additions & 2 deletions addons/account/report/account_partner_ledger.py
Expand Up @@ -4,7 +4,6 @@
import time
from odoo import api, models, _
from odoo.exceptions import UserError
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT


class ReportPartnerLedger(models.AbstractModel):
Expand Down Expand Up @@ -35,7 +34,6 @@ def _lines(self, data, partner):
lang_id = lang._lang_get(lang_code)
date_format = lang_id.date_format
for r in res:
r['date'] = datetime.strptime(r['date'], DEFAULT_SERVER_DATE_FORMAT).strftime(date_format)
r['displayed_name'] = '-'.join(
r[field_name] for field_name in ('move_name', 'ref', 'name')
if r[field_name] not in (None, '', '/')
Expand Down
8 changes: 4 additions & 4 deletions addons/account/tests/test_account_fiscal_year.py
@@ -1,8 +1,8 @@
# -*- coding: utf-8 -*-
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT

import odoo.tests
from odoo import fields

from datetime import datetime

Expand All @@ -19,10 +19,10 @@ def check_compute_fiscal_year(self, company, date, expected_date_from, expected_
:param expected_date_from: The expected date_from after computation.
:param expected_date_to: The expected date_to after computation.
'''
current_date = datetime.strptime(date, DEFAULT_SERVER_DATE_FORMAT)
current_date = fields.Date.from_string(date)
res = company.compute_fiscalyear_dates(current_date)
self.assertEqual(res['date_from'].strftime(DEFAULT_SERVER_DATE_FORMAT), expected_date_from)
self.assertEqual(res['date_to'].strftime(DEFAULT_SERVER_DATE_FORMAT), expected_date_to)
self.assertEqual(res['date_from'], fields.Date.from_string(expected_date_from))
self.assertEqual(res['date_to'], fields.Date.from_string(expected_date_to))

def test_default_fiscal_year(self):
'''Basic case with a fiscal year xxxx-01-01 - xxxx-12-31.'''
Expand Down
2 changes: 1 addition & 1 deletion addons/account/tests/test_reconciliation.py
@@ -1,4 +1,4 @@
from odoo import api
from odoo import api, fields
from odoo.addons.account.tests.account_test_classes import AccountingTestCase
from odoo.tests import tagged
import time
Expand Down
Expand Up @@ -27,7 +27,7 @@ def _print_report(self, data):
if not data['form']['date_from']:
raise UserError(_('You must set a start date.'))

start = datetime.strptime(data['form']['date_from'], "%Y-%m-%d")
start = fields.Date.from_string(data['form']['date_from'])

for i in range(5)[::-1]:
stop = start - relativedelta(days=period_length - 1)
Expand Down
18 changes: 7 additions & 11 deletions addons/account_asset/models/account_asset.py
Expand Up @@ -7,7 +7,6 @@

from odoo import api, fields, models, _
from odoo.exceptions import UserError, ValidationError
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF
from odoo.tools import float_compare, float_is_zero


Expand Down Expand Up @@ -164,7 +163,7 @@ def _compute_board_amount(self, sequence, residual_amount, amount_to_depr, undon
if self.prorata:
amount = amount_to_depr / self.method_number
if sequence == 1:
date = datetime.strptime(self.date, DF)
date = self.date
if self.method_period % 12 != 0:
month_days = calendar.monthrange(date.year, date.month)[1]
days = month_days - date.day + 1
Expand All @@ -176,7 +175,7 @@ def _compute_board_amount(self, sequence, residual_amount, amount_to_depr, undon
amount = residual_amount * self.method_progress_factor
if self.prorata:
if sequence == 1:
date = datetime.strptime(self.date, DF)
date = self.date
if self.method_period % 12 != 0:
month_days = calendar.monthrange(date.year, date.month)[1]
days = month_days - date.day + 1
Expand All @@ -189,7 +188,7 @@ def _compute_board_amount(self, sequence, residual_amount, amount_to_depr, undon
def _compute_board_undone_dotation_nb(self, depreciation_date, total_days):
undone_dotation_number = self.method_number
if self.method_time == 'end':
end_date = datetime.strptime(self.method_end, DF).date()
end_date = self.method_end
undone_dotation_number = 0
while depreciation_date <= end_date:
depreciation_date = date(depreciation_date.year, depreciation_date.month, depreciation_date.day) + relativedelta(months=+self.method_period)
Expand All @@ -213,27 +212,24 @@ def compute_depreciation_board(self):

# if we already have some previous validated entries, starting date is last entry + method period
if posted_depreciation_line_ids and posted_depreciation_line_ids[-1].depreciation_date:
last_depreciation_date = datetime.strptime(posted_depreciation_line_ids[-1].depreciation_date, DF).date()
last_depreciation_date = fields.Date.from_string(posted_depreciation_line_ids[-1].depreciation_date)
depreciation_date = last_depreciation_date + relativedelta(months=+self.method_period)
else:
# depreciation_date computed from the purchase date
depreciation_date = self.date
depreciation_date = datetime.strptime(depreciation_date, DF)
if self.date_first_depreciation == 'last_day_period':
# depreciation_date = the last day of the month
depreciation_date = depreciation_date + relativedelta(day=31)
# ... or fiscalyear depending the number of period
if self.method_period == 12:
depreciation_date = depreciation_date + relativedelta(month=self.company_id.fiscalyear_last_month)
depreciation_date = depreciation_date + relativedelta(day=self.company_id.fiscalyear_last_day)
if datetime.strftime(depreciation_date, DF) < self.date:
if depreciation_date < self.date:
depreciation_date = depreciation_date + relativedelta(years=1)
elif self.first_depreciation_manual_date and self.first_depreciation_manual_date != self.date:
# depreciation_date set manually from the 'first_depreciation_manual_date' field
depreciation_date = self.first_depreciation_manual_date
depreciation_date = datetime.strptime(depreciation_date, DF)

depreciation_date = depreciation_date.date()
total_days = (depreciation_date.year % 4) and 365 or 366
month_day = depreciation_date.day
undone_dotation_number = self._compute_board_undone_dotation_nb(depreciation_date, total_days)
Expand All @@ -252,7 +248,7 @@ def compute_depreciation_board(self):
'name': (self.code or '') + '/' + str(sequence),
'remaining_value': residual_amount,
'depreciated_value': self.value - (self.salvage_value + residual_amount),
'depreciation_date': depreciation_date.strftime(DF),
'depreciation_date': depreciation_date,
}
commands.append((0, False, vals))

Expand Down Expand Up @@ -327,7 +323,7 @@ def _get_disposal_moves(self):

# Create a new depr. line with the residual amount and post it
sequence = len(asset.depreciation_line_ids) - len(unposted_depreciation_line_ids) + 1
today = datetime.today().strftime(DF)
today = fields.Datetime.today()
vals = {
'amount': asset.value_residual,
'asset_id': asset.id,
Expand Down
7 changes: 3 additions & 4 deletions addons/account_asset/models/account_invoice.py
Expand Up @@ -5,7 +5,6 @@
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools import DEFAULT_SERVER_DATE_FORMAT as DF

from odoo.addons import decimal_precision as dp

Expand Down Expand Up @@ -65,10 +64,10 @@ def _get_asset_date(self):
if self.invoice_id.type in ['out_invoice', 'out_refund']:
self.asset_mrr = self.price_subtotal_signed / months
if self.invoice_id.date_invoice:
start_date = datetime.strptime(self.invoice_id.date_invoice, DF).replace(day=1)
start_date = self.invoice_id.date_invoice.replace(day=1)
end_date = (start_date + relativedelta(months=months, days=-1))
self.asset_start_date = start_date.strftime(DF)
self.asset_end_date = end_date.strftime(DF)
self.asset_start_date = start_date
self.asset_end_date = end_date

@api.one
def asset_create(self):
Expand Down

1 comment on commit 960360a

@rim-odoo
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sign in to comment.