Skip to content

Commit 92a7f8c

Browse files
qdp-odood-fence
authored andcommitted
[IMP] base, tests: use freezegun lib to mock dates and datetimes
closes odoo#54227 Related: odoo/enterprise#11742 Signed-off-by: Olivier Dony (odo) <odo@openerp.com>
1 parent da6c902 commit 92a7f8c

File tree

8 files changed

+155
-177
lines changed

8 files changed

+155
-177
lines changed

addons/account/tests/common.py

Lines changed: 0 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,7 @@
66

77
import time
88
import logging
9-
import datetime
109

11-
from contextlib import contextmanager
12-
from unittest.mock import patch
1310

1411
_logger = logging.getLogger(__name__)
1512

@@ -986,31 +983,6 @@ def setup_armageddon_tax(cls, tax_name, company_data):
986983
],
987984
})
988985

989-
@contextmanager
990-
def mocked_today(self, forced_today):
991-
''' Helper to make easily a python "with statement" mocking the "today" date.
992-
:param forced_today: The expected "today" date as a str or Date object.
993-
:return: An object to be used like 'with self.mocked_today(<today>):'.
994-
'''
995-
996-
if isinstance(forced_today, str):
997-
forced_today_date = fields.Date.from_string(forced_today)
998-
forced_today_datetime = fields.Datetime.from_string(forced_today)
999-
elif isinstance(forced_today, datetime.datetime):
1000-
forced_today_datetime = forced_today
1001-
forced_today_date = forced_today_datetime.date()
1002-
else:
1003-
forced_today_date = forced_today
1004-
forced_today_datetime = datetime.datetime.combine(forced_today_date, datetime.time())
1005-
1006-
def today(*args, **kwargs):
1007-
return forced_today_date
1008-
1009-
with patch.object(fields.Date, 'today', today):
1010-
with patch.object(fields.Date, 'context_today', today):
1011-
with patch.object(fields.Datetime, 'now', return_value=forced_today_datetime):
1012-
yield
1013-
1014986
@classmethod
1015987
def init_invoice(cls, move_type, partner=None, invoice_date=None):
1016988
move_form = Form(cls.env['account.move'].with_context(default_move_type=move_type))
Lines changed: 86 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,94 +1,94 @@
11
# -*- coding: utf-8 -*-
2+
from freezegun import freeze_time
3+
24
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
35
from odoo.tests import tagged
46

5-
67
@tagged('post_install', '-at_install')
78
class TestAccountJournalDashboard(AccountTestInvoicingCommon):
89

10+
@freeze_time("2019-01-22")
911
def test_customer_invoice_dashboard(self):
10-
with self.mocked_today('2019-01-22'):
11-
12-
journal = self.company_data['default_journal_sale']
13-
14-
invoice = self.env['account.move'].create({
15-
'move_type': 'out_invoice',
16-
'journal_id': journal.id,
17-
'partner_id': self.partner_a.id,
18-
'invoice_date': '2019-01-21',
19-
'date': '2019-01-21',
20-
'invoice_line_ids': [(0, 0, {
21-
'product_id': self.product_a.id,
22-
'quantity': 40.0,
23-
'name': 'product test 1',
24-
'discount': 10.00,
25-
'price_unit': 2.27,
26-
})]
27-
})
28-
refund = self.env['account.move'].create({
29-
'move_type': 'out_refund',
30-
'journal_id': journal.id,
31-
'partner_id': self.partner_a.id,
32-
'invoice_date': '2019-01-21',
33-
'date': '2019-01-21',
34-
'invoice_line_ids': [(0, 0, {
35-
'product_id': self.product_a.id,
36-
'quantity': 1.0,
37-
'name': 'product test 1',
38-
'price_unit': 13.3,
39-
})]
40-
})
41-
42-
# Check Draft
43-
dashboard_data = journal.get_journal_dashboard_datas()
44-
45-
self.assertEqual(dashboard_data['number_draft'], 2)
46-
self.assertIn('68.42', dashboard_data['sum_draft'])
47-
48-
self.assertEqual(dashboard_data['number_waiting'], 0)
49-
self.assertIn('0.00', dashboard_data['sum_waiting'])
50-
51-
# Check Both
52-
invoice.post()
53-
54-
dashboard_data = journal.get_journal_dashboard_datas()
55-
self.assertEqual(dashboard_data['number_draft'], 1)
56-
self.assertIn('-13.30', dashboard_data['sum_draft'])
57-
58-
self.assertEqual(dashboard_data['number_waiting'], 1)
59-
self.assertIn('81.72', dashboard_data['sum_waiting'])
60-
61-
# Check waiting payment
62-
refund.post()
63-
64-
dashboard_data = journal.get_journal_dashboard_datas()
65-
self.assertEqual(dashboard_data['number_draft'], 0)
66-
self.assertIn('0.00', dashboard_data['sum_draft'])
67-
68-
self.assertEqual(dashboard_data['number_waiting'], 2)
69-
self.assertIn('68.42', dashboard_data['sum_waiting'])
70-
71-
# Check partial
72-
receivable_account = refund.line_ids.mapped('account_id').filtered(lambda a: a.internal_type == 'receivable')
73-
payment = self.env['account.payment'].create({
74-
'amount': 10.0,
75-
'payment_type': 'outbound',
76-
'partner_type': 'customer',
77-
'partner_id': self.partner_a.id,
78-
})
79-
payment.action_post()
80-
81-
(refund + payment.move_id).line_ids\
82-
.filtered(lambda line: line.account_internal_type == 'receivable')\
83-
.reconcile()
84-
85-
dashboard_data = journal.get_journal_dashboard_datas()
86-
self.assertEqual(dashboard_data['number_draft'], 0)
87-
self.assertIn('0.00', dashboard_data['sum_draft'])
88-
89-
self.assertEqual(dashboard_data['number_waiting'], 2)
90-
self.assertIn('78.42', dashboard_data['sum_waiting'])
91-
92-
dashboard_data = journal.get_journal_dashboard_datas()
93-
self.assertEqual(dashboard_data['number_late'], 2)
94-
self.assertIn('78.42', dashboard_data['sum_late'])
12+
journal = self.company_data['default_journal_sale']
13+
14+
invoice = self.env['account.move'].create({
15+
'move_type': 'out_invoice',
16+
'journal_id': journal.id,
17+
'partner_id': self.partner_a.id,
18+
'invoice_date': '2019-01-21',
19+
'date': '2019-01-21',
20+
'invoice_line_ids': [(0, 0, {
21+
'product_id': self.product_a.id,
22+
'quantity': 40.0,
23+
'name': 'product test 1',
24+
'discount': 10.00,
25+
'price_unit': 2.27,
26+
})]
27+
})
28+
refund = self.env['account.move'].create({
29+
'move_type': 'out_refund',
30+
'journal_id': journal.id,
31+
'partner_id': self.partner_a.id,
32+
'invoice_date': '2019-01-21',
33+
'date': '2019-01-21',
34+
'invoice_line_ids': [(0, 0, {
35+
'product_id': self.product_a.id,
36+
'quantity': 1.0,
37+
'name': 'product test 1',
38+
'price_unit': 13.3,
39+
})]
40+
})
41+
42+
# Check Draft
43+
dashboard_data = journal.get_journal_dashboard_datas()
44+
45+
self.assertEqual(dashboard_data['number_draft'], 2)
46+
self.assertIn('68.42', dashboard_data['sum_draft'])
47+
48+
self.assertEqual(dashboard_data['number_waiting'], 0)
49+
self.assertIn('0.00', dashboard_data['sum_waiting'])
50+
51+
# Check Both
52+
invoice.post()
53+
54+
dashboard_data = journal.get_journal_dashboard_datas()
55+
self.assertEqual(dashboard_data['number_draft'], 1)
56+
self.assertIn('-13.30', dashboard_data['sum_draft'])
57+
58+
self.assertEqual(dashboard_data['number_waiting'], 1)
59+
self.assertIn('81.72', dashboard_data['sum_waiting'])
60+
61+
# Check waiting payment
62+
refund.post()
63+
64+
dashboard_data = journal.get_journal_dashboard_datas()
65+
self.assertEqual(dashboard_data['number_draft'], 0)
66+
self.assertIn('0.00', dashboard_data['sum_draft'])
67+
68+
self.assertEqual(dashboard_data['number_waiting'], 2)
69+
self.assertIn('68.42', dashboard_data['sum_waiting'])
70+
71+
# Check partial
72+
receivable_account = refund.line_ids.mapped('account_id').filtered(lambda a: a.internal_type == 'receivable')
73+
payment = self.env['account.payment'].create({
74+
'amount': 10.0,
75+
'payment_type': 'outbound',
76+
'partner_type': 'customer',
77+
'partner_id': self.partner_a.id,
78+
})
79+
payment.action_post()
80+
81+
(refund + payment.move_id).line_ids\
82+
.filtered(lambda line: line.account_internal_type == 'receivable')\
83+
.reconcile()
84+
85+
dashboard_data = journal.get_journal_dashboard_datas()
86+
self.assertEqual(dashboard_data['number_draft'], 0)
87+
self.assertIn('0.00', dashboard_data['sum_draft'])
88+
89+
self.assertEqual(dashboard_data['number_waiting'], 2)
90+
self.assertIn('78.42', dashboard_data['sum_waiting'])
91+
92+
dashboard_data = journal.get_journal_dashboard_datas()
93+
self.assertEqual(dashboard_data['number_late'], 2)
94+
self.assertIn('78.42', dashboard_data['sum_late'])

addons/account/tests/test_reconciliation_matching_rules.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# -*- coding: utf-8 -*-
2-
from odoo import fields
2+
from freezegun import freeze_time
3+
34
from odoo.addons.account.tests.common import AccountTestInvoicingCommon
45
from odoo.tests.common import Form
56
from odoo.tests import tagged
@@ -625,7 +626,7 @@ def test_match_multi_currencies(self):
625626

626627
self.env['account.reconcile.model'].flush()
627628

628-
with self.mocked_today('2017-01-01'):
629+
with freeze_time('2017-01-01'):
629630
self._check_statement_matching(matching_rule, {
630631
statement_line.id: {'aml_ids': (move_line_1 + move_line_2).ids, 'model': matching_rule}
631632
}, statements=statement)

addons/account_edi_facturx/tests/test_facturx.py

Lines changed: 62 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
# -*- coding: utf-8 -*-
2+
from freezegun import freeze_time
3+
24
from odoo.addons.account.tests.account_test_xml import AccountTestEdiCommon
35
from odoo.tests import tagged
46

@@ -151,74 +153,74 @@ def setUpClass(cls, chart_template_ref=None):
151153
</CrossIndustryInvoice>
152154
'''
153155

156+
@freeze_time('2017-02-01')
154157
def test_facturx(self):
155158
''' Test the generated Facturx Edi attachment without any modification of the invoice. '''
156159

157-
with self.mocked_today('2017-02-01'):
158-
self.invoice.post()
160+
self.invoice.post()
159161

160-
xml_content = self.facturx_edi_format._export_invoice_to_attachment(self.invoice)['datas']
161-
current_etree = self.get_xml_tree_from_string(xml_content)
162-
expected_etree = self.get_xml_tree_from_string(self.expected_invoice_facturx_values)
163-
self.assertXmlTreeEqual(current_etree, expected_etree)
162+
xml_content = self.facturx_edi_format._export_invoice_to_attachment(self.invoice)['datas']
163+
current_etree = self.get_xml_tree_from_string(xml_content)
164+
expected_etree = self.get_xml_tree_from_string(self.expected_invoice_facturx_values)
165+
self.assertXmlTreeEqual(current_etree, expected_etree)
164166

167+
@freeze_time('2017-02-01')
165168
def test_facturx_group_of_taxes(self):
166169
''' Same as above with a group of taxes. '''
167170
self.invoice.write({
168171
'invoice_line_ids': [(1, self.invoice.invoice_line_ids.id, {'tax_ids': [(6, 0, self.tax_group.ids)]})],
169172
})
170173

171-
with self.mocked_today('2017-02-01'):
172-
self.invoice.post()
173-
174-
xml_content = self.facturx_edi_format._export_invoice_to_attachment(self.invoice)['datas']
175-
current_etree = self.get_xml_tree_from_string(xml_content)
176-
expected_etree = self.with_applied_xpath(
177-
self.get_xml_tree_from_string(self.expected_invoice_facturx_values),
178-
'''
179-
<xpath expr="//GrossPriceProductTradePrice/ChargeAmount" position="replace">
180-
<ChargeAmount currencyID="Gol">275.000</ChargeAmount>
181-
</xpath>
182-
<xpath expr="//SpecifiedLineTradeSettlement" position="replace">
183-
<SpecifiedLineTradeSettlement>
184-
<ApplicableTradeTax>
185-
<RateApplicablePercent>10.0</RateApplicablePercent>
186-
</ApplicableTradeTax>
187-
<ApplicableTradeTax>
188-
<RateApplicablePercent>20.0</RateApplicablePercent>
189-
</ApplicableTradeTax>
190-
<SpecifiedTradeSettlementLineMonetarySummation>
191-
<LineTotalAmount currencyID="Gol">1000.000</LineTotalAmount>
192-
</SpecifiedTradeSettlementLineMonetarySummation>
193-
</SpecifiedLineTradeSettlement>
194-
</xpath>
195-
<xpath expr="//ApplicableHeaderTradeSettlement" position="replace">
196-
<ApplicableHeaderTradeSettlement>
197-
<ApplicableTradeTax>
198-
<CalculatedAmount currencyID="Gol">220.000</CalculatedAmount>
199-
<BasisAmount currencyID="Gol">1100.000</BasisAmount>
200-
<RateApplicablePercent>20.0</RateApplicablePercent>
201-
</ApplicableTradeTax>
202-
<ApplicableTradeTax>
203-
<CalculatedAmount currencyID="Gol">100.000</CalculatedAmount>
204-
<BasisAmount currencyID="Gol">1000.000</BasisAmount>
205-
<RateApplicablePercent>10.0</RateApplicablePercent>
206-
</ApplicableTradeTax>
207-
<SpecifiedTradePaymentTerms>
208-
<DueDateDateTime>
209-
<DateTimeString>20170101</DateTimeString>
210-
</DueDateDateTime>
211-
</SpecifiedTradePaymentTerms>
212-
<SpecifiedTradeSettlementHeaderMonetarySummation>
213-
<LineTotalAmount currencyID="Gol">1000.000</LineTotalAmount>
214-
<TaxBasisTotalAmount currencyID="Gol">1000.000</TaxBasisTotalAmount>
215-
<TaxTotalAmount currencyID="Gol">320.000</TaxTotalAmount>
216-
<GrandTotalAmount currencyID="Gol">1320.000</GrandTotalAmount>
217-
<TotalPrepaidAmount currencyID="Gol">0.000</TotalPrepaidAmount>
218-
<DuePayableAmount currencyID="Gol">1320.000</DuePayableAmount>
219-
</SpecifiedTradeSettlementHeaderMonetarySummation>
220-
</ApplicableHeaderTradeSettlement>
221-
</xpath>
222-
''',
223-
)
224-
self.assertXmlTreeEqual(current_etree, expected_etree)
174+
self.invoice.post()
175+
176+
xml_content = self.facturx_edi_format._export_invoice_to_attachment(self.invoice)['datas']
177+
current_etree = self.get_xml_tree_from_string(xml_content)
178+
expected_etree = self.with_applied_xpath(
179+
self.get_xml_tree_from_string(self.expected_invoice_facturx_values),
180+
'''
181+
<xpath expr="//GrossPriceProductTradePrice/ChargeAmount" position="replace">
182+
<ChargeAmount currencyID="Gol">275.000</ChargeAmount>
183+
</xpath>
184+
<xpath expr="//SpecifiedLineTradeSettlement" position="replace">
185+
<SpecifiedLineTradeSettlement>
186+
<ApplicableTradeTax>
187+
<RateApplicablePercent>10.0</RateApplicablePercent>
188+
</ApplicableTradeTax>
189+
<ApplicableTradeTax>
190+
<RateApplicablePercent>20.0</RateApplicablePercent>
191+
</ApplicableTradeTax>
192+
<SpecifiedTradeSettlementLineMonetarySummation>
193+
<LineTotalAmount currencyID="Gol">1000.000</LineTotalAmount>
194+
</SpecifiedTradeSettlementLineMonetarySummation>
195+
</SpecifiedLineTradeSettlement>
196+
</xpath>
197+
<xpath expr="//ApplicableHeaderTradeSettlement" position="replace">
198+
<ApplicableHeaderTradeSettlement>
199+
<ApplicableTradeTax>
200+
<CalculatedAmount currencyID="Gol">220.000</CalculatedAmount>
201+
<BasisAmount currencyID="Gol">1100.000</BasisAmount>
202+
<RateApplicablePercent>20.0</RateApplicablePercent>
203+
</ApplicableTradeTax>
204+
<ApplicableTradeTax>
205+
<CalculatedAmount currencyID="Gol">100.000</CalculatedAmount>
206+
<BasisAmount currencyID="Gol">1000.000</BasisAmount>
207+
<RateApplicablePercent>10.0</RateApplicablePercent>
208+
</ApplicableTradeTax>
209+
<SpecifiedTradePaymentTerms>
210+
<DueDateDateTime>
211+
<DateTimeString>20170101</DateTimeString>
212+
</DueDateDateTime>
213+
</SpecifiedTradePaymentTerms>
214+
<SpecifiedTradeSettlementHeaderMonetarySummation>
215+
<LineTotalAmount currencyID="Gol">1000.000</LineTotalAmount>
216+
<TaxBasisTotalAmount currencyID="Gol">1000.000</TaxBasisTotalAmount>
217+
<TaxTotalAmount currencyID="Gol">320.000</TaxTotalAmount>
218+
<GrandTotalAmount currencyID="Gol">1320.000</GrandTotalAmount>
219+
<TotalPrepaidAmount currencyID="Gol">0.000</TotalPrepaidAmount>
220+
<DuePayableAmount currencyID="Gol">1320.000</DuePayableAmount>
221+
</SpecifiedTradeSettlementHeaderMonetarySummation>
222+
</ApplicableHeaderTradeSettlement>
223+
</xpath>
224+
''',
225+
)
226+
self.assertXmlTreeEqual(current_etree, expected_etree)

debian/control

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Depends:
2222
python3-decorator,
2323
python3-docutils,
2424
python3-feedparser,
25+
python3-freezegun,
2526
python3-html2text,
2627
python3-pil,
2728
python3-jinja2,

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ decorator==4.3.0
44
docutils==0.14
55
ebaysdk==2.1.5
66
feedparser==5.2.1
7+
freezegun==0.3.11
78
gevent==1.1.2 ; sys_platform != 'win32' and python_version < '3.7'
89
gevent==1.3.7 ; sys_platform != 'win32' and python_version >= '3.7'
910
gevent==1.4.0 ; sys_platform == 'win32'

0 commit comments

Comments
 (0)