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.

227 lines
8.5 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.parse_expr("debp[400A%]")
  75. self.aep.parse_expr("crdp[700I%]")
  76. self.aep.parse_expr("bal_700IN") # deprecated
  77. self.aep.parse_expr("bals[700IN]") # deprecated
  78. self.aep.done_parsing(self.company)
  79. def _create_move(self, date, amount, debit_acc, credit_acc):
  80. move = self.move_model.create({
  81. 'journal_id': self.journal.id,
  82. 'date': fields.Date.to_string(date),
  83. 'line_ids': [(0, 0, {
  84. 'name': '/',
  85. 'debit': amount,
  86. 'account_id': debit_acc.id,
  87. }), (0, 0, {
  88. 'name': '/',
  89. 'credit': amount,
  90. 'account_id': credit_acc.id,
  91. })]})
  92. move.post()
  93. return move
  94. def _do_queries(self, date_from, date_to):
  95. self.aep.do_queries(
  96. date_from=fields.Date.to_string(date_from),
  97. date_to=fields.Date.to_string(date_to),
  98. target_move='posted',
  99. company=self.company)
  100. def _eval(self, expr):
  101. eval_dict = {'AccountingNone': AccountingNone}
  102. return safe_eval(self.aep.replace_expr(expr), eval_dict)
  103. def _eval_by_account_id(self, expr):
  104. res = {}
  105. eval_dict = {'AccountingNone': AccountingNone}
  106. for account_id, replaced_exprs in \
  107. self.aep.replace_exprs_by_account_id([expr]):
  108. res[account_id] = safe_eval(replaced_exprs[0], eval_dict)
  109. return res
  110. def test_sanity_check(self):
  111. self.assertEquals(self.company.fiscalyear_last_day, 31)
  112. self.assertEquals(self.company.fiscalyear_last_month, 12)
  113. def test_aep_basic(self):
  114. # let's query for december
  115. self._do_queries(
  116. datetime.date(self.prev_year, 12, 1),
  117. datetime.date(self.prev_year, 12, 31))
  118. # initial balance must be None
  119. self.assertIs(self._eval('bali[400AR]'), AccountingNone)
  120. self.assertIs(self._eval('bali[700IN]'), AccountingNone)
  121. # check variation
  122. self.assertEquals(self._eval('balp[400AR]'), 100)
  123. self.assertEquals(self._eval('balp[700IN]'), -100)
  124. # check ending balance
  125. self.assertEquals(self._eval('bale[400AR]'), 100)
  126. self.assertEquals(self._eval('bale[700IN]'), -100)
  127. # let's query for January
  128. self._do_queries(
  129. datetime.date(self.curr_year, 1, 1),
  130. datetime.date(self.curr_year, 1, 31))
  131. # initial balance is None for income account (it's not carried over)
  132. self.assertEquals(self._eval('bali[400AR]'), 100)
  133. self.assertIs(self._eval('bali[700IN]'), AccountingNone)
  134. # check variation
  135. self.assertEquals(self._eval('balp[400AR]'), 300)
  136. self.assertEquals(self._eval('balp[700IN]'), -300)
  137. # check ending balance
  138. self.assertEquals(self._eval('bale[400AR]'), 400)
  139. self.assertEquals(self._eval('bale[700IN]'), -300)
  140. # let's query for March
  141. self._do_queries(
  142. datetime.date(self.curr_year, 3, 1),
  143. datetime.date(self.curr_year, 3, 31))
  144. # initial balance is the ending balance fo January
  145. self.assertEquals(self._eval('bali[400AR]'), 400)
  146. self.assertEquals(self._eval('bali[700IN]'), -300)
  147. # check variation
  148. self.assertEquals(self._eval('balp[400AR]'), 500)
  149. self.assertEquals(self._eval('balp[700IN]'), -500)
  150. # check ending balance
  151. self.assertEquals(self._eval('bale[400AR]'), 900)
  152. self.assertEquals(self._eval('bale[700IN]'), -800)
  153. # check some variant expressions, for coverage
  154. self.assertEquals(self._eval('crdp[700I%]'), 500)
  155. self.assertEquals(self._eval('debp[400A%]'), 500)
  156. self.assertEquals(self._eval('bal_700IN'), -500)
  157. self.assertEquals(self._eval('bals[700IN]'), -800)
  158. # unallocated p&l from previous year
  159. self.assertEquals(self._eval('balu[]'), -100)
  160. # TODO allocate profits, and then...
  161. def test_aep_by_account(self):
  162. self._do_queries(
  163. datetime.date(self.curr_year, 3, 1),
  164. datetime.date(self.curr_year, 3, 31))
  165. variation = self._eval_by_account_id('balp[]')
  166. self.assertEquals(variation, {
  167. self.account_ar.id: 500,
  168. self.account_in.id: -500,
  169. })
  170. variation = self._eval_by_account_id('balp[700IN]')
  171. self.assertEquals(variation, {
  172. self.account_in.id: -500,
  173. })
  174. end = self._eval_by_account_id('bale[]')
  175. self.assertEquals(end, {
  176. self.account_ar.id: 900,
  177. self.account_in.id: -800,
  178. })
  179. def test_aep_convenience_methods(self):
  180. initial = AEP.get_balances_initial(
  181. self.company,
  182. time.strftime('%Y') + '-03-01',
  183. 'posted')
  184. self.assertEquals(initial, {
  185. self.account_ar.id: (400, 0),
  186. self.account_in.id: (0, 300),
  187. })
  188. variation = AEP.get_balances_variation(
  189. self.company,
  190. time.strftime('%Y') + '-03-01',
  191. time.strftime('%Y') + '-03-31',
  192. 'posted')
  193. self.assertEquals(variation, {
  194. self.account_ar.id: (500, 0),
  195. self.account_in.id: (0, 500),
  196. })
  197. end = AEP.get_balances_end(
  198. self.company,
  199. time.strftime('%Y') + '-03-31',
  200. 'posted')
  201. self.assertEquals(end, {
  202. self.account_ar.id: (900, 0),
  203. self.account_in.id: (0, 800),
  204. })
  205. unallocated = AEP.get_unallocated_pl(
  206. self.company,
  207. time.strftime('%Y') + '-03-15',
  208. 'posted')
  209. self.assertEquals(unallocated, (0, 100))