You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

218 lines
8.0 KiB

9 years ago
  1. # -*- coding: utf-8 -*-
  2. # © 2014-2015 ACSONE SA/NV (<http://acsone.eu>)
  3. # License AGPL-3.0 or later (https://www.gnu.org/licenses/agpl.html).
  4. import datetime
  5. import time
  6. from openerp import fields
  7. import openerp.tests.common as common
  8. from openerp.tools.safe_eval import safe_eval
  9. from ..models.aep import AccountingExpressionProcessor as AEP
  10. from ..models.accounting_none import AccountingNone
  11. class TestAEP(common.TransactionCase):
  12. def setUp(self):
  13. super(TestAEP, self).setUp()
  14. self.res_company = self.env['res.company']
  15. self.account_model = self.env['account.account']
  16. self.move_model = self.env['account.move']
  17. self.journal_model = self.env['account.journal']
  18. self.curr_year = datetime.date.today().year
  19. self.prev_year = self.curr_year - 1
  20. # create company
  21. self.company = self.res_company.create({
  22. 'name': 'AEP Company'})
  23. # create receivable bs account
  24. type_ar = self.browse_ref('account.data_account_type_receivable')
  25. self.account_ar = self.account_model.create({
  26. 'company_id': self.company.id,
  27. 'code': '400AR',
  28. 'name': 'Receivable',
  29. 'user_type_id': type_ar.id,
  30. 'reconcile': True})
  31. # create income pl account
  32. type_in = self.browse_ref('account.data_account_type_revenue')
  33. self.account_in = self.account_model.create({
  34. 'company_id': self.company.id,
  35. 'code': '700IN',
  36. 'name': 'Income',
  37. 'user_type_id': type_in.id})
  38. # create journal
  39. self.journal = self.journal_model.create({
  40. 'company_id': self.company.id,
  41. 'name': 'Sale journal',
  42. 'code': 'VEN',
  43. 'type': 'sale'})
  44. # create move in december last year
  45. self._create_move(
  46. date=datetime.date(self.prev_year, 12, 1),
  47. amount=100,
  48. debit_acc=self.account_ar,
  49. credit_acc=self.account_in)
  50. # create move in january this year
  51. self._create_move(
  52. date=datetime.date(self.curr_year, 1, 1),
  53. amount=300,
  54. debit_acc=self.account_ar,
  55. credit_acc=self.account_in)
  56. # create move in february this year
  57. self._create_move(
  58. date=datetime.date(self.curr_year, 3, 1),
  59. amount=500,
  60. debit_acc=self.account_ar,
  61. credit_acc=self.account_in)
  62. # create the AEP, and prepare the expressions we'll need
  63. self.aep = AEP(self.env)
  64. self.aep.parse_expr("bali[]")
  65. self.aep.parse_expr("bale[]")
  66. self.aep.parse_expr("balp[]")
  67. self.aep.parse_expr("balu[]")
  68. self.aep.parse_expr("bali[700IN]")
  69. self.aep.parse_expr("bale[700IN]")
  70. self.aep.parse_expr("balp[700IN]")
  71. self.aep.parse_expr("bali[400AR]")
  72. self.aep.parse_expr("bale[400AR]")
  73. self.aep.parse_expr("balp[400AR]")
  74. self.aep.done_parsing(self.company)
  75. def _create_move(self, date, amount, debit_acc, credit_acc):
  76. move = self.move_model.create({
  77. 'journal_id': self.journal.id,
  78. 'date': fields.Date.to_string(date),
  79. 'line_ids': [(0, 0, {
  80. 'name': '/',
  81. 'debit': amount,
  82. 'account_id': debit_acc.id,
  83. }), (0, 0, {
  84. 'name': '/',
  85. 'credit': amount,
  86. 'account_id': credit_acc.id,
  87. })]})
  88. move.post()
  89. return move
  90. def _do_queries(self, date_from, date_to):
  91. self.aep.do_queries(
  92. date_from=fields.Date.to_string(date_from),
  93. date_to=fields.Date.to_string(date_to),
  94. target_move='posted',
  95. company=self.company)
  96. def _eval(self, expr):
  97. eval_dict = {'AccountingNone': AccountingNone}
  98. return safe_eval(self.aep.replace_expr(expr), eval_dict)
  99. def _eval_by_account_id(self, expr):
  100. res = {}
  101. eval_dict = {'AccountingNone': AccountingNone}
  102. for account_id, replaced_expr in \
  103. self.aep.replace_expr_by_account_id(expr):
  104. res[account_id] = safe_eval(replaced_expr, eval_dict)
  105. return res
  106. def test_sanity_check(self):
  107. self.assertEquals(self.company.fiscalyear_last_day, 31)
  108. self.assertEquals(self.company.fiscalyear_last_month, 12)
  109. def test_aep_basic(self):
  110. # let's query for december
  111. self._do_queries(
  112. datetime.date(self.prev_year, 12, 1),
  113. datetime.date(self.prev_year, 12, 31))
  114. # initial balance must be None
  115. self.assertIs(self._eval('bali[400AR]'), AccountingNone)
  116. self.assertIs(self._eval('bali[700IN]'), AccountingNone)
  117. # check variation
  118. self.assertEquals(self._eval('balp[400AR]'), 100)
  119. self.assertEquals(self._eval('balp[700IN]'), -100)
  120. # check ending balance
  121. self.assertEquals(self._eval('bale[400AR]'), 100)
  122. self.assertEquals(self._eval('bale[700IN]'), -100)
  123. # let's query for January
  124. self._do_queries(
  125. datetime.date(self.curr_year, 1, 1),
  126. datetime.date(self.curr_year, 1, 31))
  127. # initial balance is None for income account (it's not carried over)
  128. self.assertEquals(self._eval('bali[400AR]'), 100)
  129. self.assertIs(self._eval('bali[700IN]'), AccountingNone)
  130. # check variation
  131. self.assertEquals(self._eval('balp[400AR]'), 300)
  132. self.assertEquals(self._eval('balp[700IN]'), -300)
  133. # check ending balance
  134. self.assertEquals(self._eval('bale[400AR]'), 400)
  135. self.assertEquals(self._eval('bale[700IN]'), -300)
  136. # let's query for March
  137. self._do_queries(
  138. datetime.date(self.curr_year, 3, 1),
  139. datetime.date(self.curr_year, 3, 31))
  140. # initial balance is the ending balance fo January
  141. self.assertEquals(self._eval('bali[400AR]'), 400)
  142. self.assertEquals(self._eval('bali[700IN]'), -300)
  143. # check variation
  144. self.assertEquals(self._eval('balp[400AR]'), 500)
  145. self.assertEquals(self._eval('balp[700IN]'), -500)
  146. # check ending balance
  147. self.assertEquals(self._eval('bale[400AR]'), 900)
  148. self.assertEquals(self._eval('bale[700IN]'), -800)
  149. # unallocated p&l from previous year
  150. self.assertEquals(self._eval('balu[]'), -100)
  151. # TODO allocate profits, and then...
  152. def test_aep_by_account(self):
  153. self._do_queries(
  154. datetime.date(self.curr_year, 3, 1),
  155. datetime.date(self.curr_year, 3, 31))
  156. variation = self._eval_by_account_id('balp[]')
  157. self.assertEquals(variation, {
  158. self.account_ar.id: 500,
  159. self.account_in.id: -500,
  160. })
  161. variation = self._eval_by_account_id('balp[700IN]')
  162. self.assertEquals(variation, {
  163. self.account_in.id: -500,
  164. })
  165. def test_aep_convenience_methods(self):
  166. initial = AEP.get_balances(
  167. AEP.MODE_INITIAL,
  168. time.strftime('%Y') + '-03-01',
  169. time.strftime('%Y') + '-03-31',
  170. 'posted',
  171. self.company)
  172. self.assertEquals(initial, {
  173. self.account_ar.id: (400, 0),
  174. self.account_in.id: (0, 300),
  175. })
  176. variation = AEP.get_balances(
  177. AEP.MODE_VARIATION,
  178. time.strftime('%Y') + '-03-01',
  179. time.strftime('%Y') + '-03-31',
  180. 'posted',
  181. self.company)
  182. self.assertEquals(variation, {
  183. self.account_ar.id: (500, 0),
  184. self.account_in.id: (0, 500),
  185. })
  186. end = AEP.get_balances(
  187. AEP.MODE_END,
  188. time.strftime('%Y') + '-03-01',
  189. time.strftime('%Y') + '-03-31',
  190. 'posted',
  191. self.company)
  192. self.assertEquals(end, {
  193. self.account_ar.id: (900, 0),
  194. self.account_in.id: (0, 800),
  195. })
  196. unallocated = AEP.get_unallocated_pl(
  197. time.strftime('%Y') + '-03-01',
  198. 'posted',
  199. self.company)
  200. self.assertEquals(unallocated, (0, 100))