Skip to content

Commit

Permalink
Merge pull request #64 from CompassionCH/devel
Browse files Browse the repository at this point in the history
Devel to prod
  • Loading branch information
ecino authored Sep 4, 2018
2 parents 94ca916 + a678ddb commit 5e8a8a9
Show file tree
Hide file tree
Showing 35 changed files with 1,286 additions and 45 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ virtualenv:


install:
- pip install -r requirements.txt
- git clone --depth=1 https://github.com/OCA/maintainer-quality-tools.git ${HOME}/maintainer-quality-tools
- export PATH=${HOME}/maintainer-quality-tools/travis:${PATH}
- travis_install_nightly
Expand Down
90 changes: 49 additions & 41 deletions account_analytic_attribution/models/account_analytic_attribution.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,14 +40,6 @@ class AccountAttribution(models.Model):
sequence = fields.Integer()
next_fiscal_year = fields.Date(compute='_compute_next_fy')

@api.model
def next_fiscal_year(self):
today = datetime.today()
fy = self.env.user.company_id.compute_fiscalyear_dates(today)
next_fy = fy['date_to'] + relativedelta(days=1)
next_fy.hour = 20
return fields.Datetime.to_string(next_fy)

@api.model
def get_attribution(self, account_tag_ids, analytic_tag_ids, date):
""" Find a valid distribution rule given some data. """
Expand All @@ -72,52 +64,25 @@ def perform_distribution(self, date_start=None, date_stop=None):
The attribution is done for each general account.
By default it takes the last fiscal year for the computation.
"""
if not date_start or not date_stop:
# Select the last year period
year = datetime.today()
year = year - relativedelta(years=1)
fy = self.env.user.company_id.compute_fiscalyear_dates(year)
date_start = fields.Date.to_string(fy['date_from'])
date_stop = fields.Date.to_string(fy['date_to'])

date_start, date_stop = self._compute_dates(date_start, date_stop)
analytic_line_obj = self.env['account.analytic.line']
tag_id = self.env.ref(
'account_analytic_attribution.tag_attribution').id

# Remove old attributions for avoiding duplicates
old_lines = analytic_line_obj.search([
('tag_ids', '=', tag_id),
('date', '>=', date_start),
('date', '<=', date_stop)])
old_lines.unlink()

# Perform the attribution for each analytic line
analytic_lines = analytic_line_obj.search([
('date', '>=', date_start),
('date', '<=', date_stop),
])
analytic_lines = self._filter_analytic_lines_and_removed_old_ones(
date_start, date_stop, tag_id)
generated_lines = analytic_line_obj

# Get the total amount to attribute for each analytic account
# -> {analytic_id: {general_account_id: total}}
attribution_amounts = dict()
for line in analytic_lines:
analytic_id = line.account_id.id
account_id = line.general_account_id.id
analytic_attribution = attribution_amounts.get(analytic_id, {
account_id: 0.0})
total = analytic_attribution.get(account_id, 0.0) + line.amount
analytic_attribution[account_id] = total
attribution_amounts[analytic_id] = analytic_attribution
attribution_amounts = self._aggregate_by_account(analytic_lines)

# Attribute the amounts
analytic_obj = self.env['account.analytic.account']
analytic_account_obj = self.env['account.analytic.account']
account_obj = self.env['account.account']
for analytic_id, attribution in attribution_amounts.iteritems():
for account_id, amount_total in attribution.iteritems():
account = account_obj.browse(account_id)
account_tag_ids = account.tag_ids.ids
analytic = analytic_obj.browse(analytic_id)
analytic = analytic_account_obj.browse(analytic_id)
analytic_tag_ids = analytic.tag_ids.ids
attribution_rule = self.get_attribution(
account_tag_ids, analytic_tag_ids, date_stop)
Expand All @@ -138,3 +103,46 @@ def perform_distribution(self, date_start=None, date_stop=None):
generated_lines += line

return generated_lines

def _compute_dates(self, date_start=None, date_stop=None):
if not date_start or not date_stop:
# Select the last year period
year = datetime.today()
year = year - relativedelta(years=1)
fy = self.env.user.company_id.compute_fiscalyear_dates(year)
date_start = fields.Date.to_string(fy['date_from'])
date_stop = fields.Date.to_string(fy['date_to'])
return date_start, date_stop

def _filter_analytic_lines_and_removed_old_ones(self, date_start,
date_stop, tag_id):
analytic_line_obj = self.env['account.analytic.line']
# Remove old attributions for avoiding duplicates
old_lines = analytic_line_obj.search([
('tag_ids', '=', tag_id),
('date', '>=', date_start),
('date', '<=', date_stop)])
old_lines.unlink()

# Perform the attribution for each analytic line
return analytic_line_obj.search([
('date', '>=', date_start),
('date', '<=', date_stop),
])

@staticmethod
def _aggregate_by_account(analytic_lines):
"""
# Get the total amount to attribute for each analytic account
# -> {analytic_id: {general_account_id: total}}
"""
attribution_amounts = dict()
for line in analytic_lines:
analytic_id = line.account_id.id
account_id = line.general_account_id.id
analytic_attribution = attribution_amounts.get(analytic_id, {
account_id: 0.0})
total = analytic_attribution.get(account_id, 0.0) + line.amount
analytic_attribution[account_id] = total
attribution_amounts[analytic_id] = analytic_attribution
return attribution_amounts
12 changes: 12 additions & 0 deletions account_analytic_attribution/tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2018 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Nicolas Bornand
#
# The licence is in the file __manifest__.py
#
##############################################################################

from . import test_analytic_attribution
109 changes: 109 additions & 0 deletions account_analytic_attribution/tests/test_analytic_attribution.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2018 Compassion CH (http://www.compassion.ch)
# Releasing children from poverty in Jesus' name
# @author: Nicolas Bornand
#
# The licence is in the file __manifest__.py
#
##############################################################################
import logging
from datetime import datetime, timedelta
from odoo import fields
from odoo.tests.common import TransactionCase

_logger = logging.getLogger(__name__)


class TestAnalyticAttribution(TransactionCase):

def setUp(self):
super(TestAnalyticAttribution, self).setUp()
self.analytic_account = self.env["account.analytic.account"] \
.create({"name": "Test Account"})
self.account = self.env["account.account"] \
.search([('code', '=', '1050')])
self.tag = self.env.ref('account_analytic_attribution.tag_attribution')
self.Attribution = self.env['account.analytic.attribution']

def test_perform_distribution__line_generation(self):
self._create_line_with_amount_twelve(self.analytic_account)
self._create_line_with_amount_twelve(self.analytic_account)
attribution = self.Attribution.create({})
self.env['account.analytic.distribution.line'].create({
'rate': 40,
'account_analytic_id': self.analytic_account.id,
'attribution_id': attribution.id
})

self._assert_analytic_lines_count(2)
line = attribution.perform_distribution()
self._assert_analytic_lines_count(3)

self.assertEqual(len(line), 1)
self.assertAlmostEqual(line.amount, 9.6) # 40% of (2*12)
self.assertEqual(line.account_id.id, self.analytic_account.id)
self.assertTrue('Analytic attribution for' in line.name)

def test_perform_distribution__should_evict_old_analytic_lines(self):
line = self._create_line_with_amount_twelve(self.analytic_account)
line.tag_ids += self.env \
.ref('account_analytic_attribution.tag_attribution')
attribution = self.Attribution.create({})

self._assert_analytic_lines_count(1)
attribution.perform_distribution()
self._assert_analytic_lines_count(0)

def test_get_attribution__match_if_filters_are_not_set(self):
attribution = self.Attribution.create({})
self.env['account.analytic.distribution.line'].create({
'rate': 40,
'account_analytic_id': self.analytic_account.id,
'attribution_id': attribution.id
})

matched = attribution.get_attribution(False, False, datetime.now())
self.assertEqual(len(matched), 1)

def test_get_attribution__matching_by_date(self):
attribution = self.Attribution.create({
'rate': 40,
'date_start': datetime.now(),
'date_stop': datetime.now()
})

yesterday = datetime.now() - timedelta(days=-1)
rules = attribution.get_attribution(False, False, yesterday)
self.assertEqual(len(rules), 0)

matched = attribution.get_attribution(False, False, datetime.now())
self.assertEqual(len(matched), 1)

def test_get_attribution__matching_by_tag(self):
attribution = self.Attribution.create({
'rate': 40
})
attribution.analytic_tag_id += self.tag

now = datetime.now()
unknown_tag = 99
rules = attribution.get_attribution(False, [unknown_tag], now)
self.assertEqual(len(rules), 0)

matched = attribution.get_attribution(False, [self.tag.id], now)
self.assertEqual(len(matched), 1)

def _create_line_with_amount_twelve(self, account):
return self.env['account.analytic.line'].create({
'name': 'test line',
'amount': 12.0,
'account_id': account.id,
'general_account_id': 1,
'date': fields.Datetime.from_string('2017-05-05')
})

def _assert_analytic_lines_count(self, count):
lines_after = self.env['account.analytic.line'].search([])
self.assertEqual(len(lines_after), count)
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
<sheet>
<group>
<field name="sequence"/>
<field name="analytic_tag_id"/>
</group>
<group colspan="2">
<field name="account_distribution_line_ids" required="1">
Expand All @@ -36,6 +35,7 @@
</group>
<group string="Conditions">
<field name="account_tag_id"/>
<field name="analytic_tag_id"/>
<field name="date_start"/>
<field name="date_stop"/>
</group>
Expand Down
70 changes: 70 additions & 0 deletions account_move_fiscalyear/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
===========================================
Account move open bills to next fiscal year
===========================================

.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!! This file is generated by oca-gen-addon-readme !!
!! changes will be overwritten. !!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png
:target: https://odoo-community.org/page/development-status
:alt: Beta
.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png
:target: http://www.gnu.org/licenses/agpl-3.0-standalone.html
:alt: License: AGPL-3
.. |badge3| image:: https://img.shields.io/badge/github-CompassionCH%2Fcompassion--accounting-lightgray.png?logo=github
:target: https://github.com/CompassionCH/compassion-accounting/tree/10.0/account_move_fiscalyear
:alt: CompassionCH/compassion-accounting

|badge1| |badge2| |badge3|

This module adds an option to automatically move open customer invoice moves to the next fiscal year during the fiscal year closing.

**Table of contents**

.. contents::
:local:

Configuration
=============

In the Accounting Settings menu, in the Fiscal Year section, enable the option "Move unclosed bills to next fiscal year" to enable the feature.

Bug Tracker
===========

Bugs are tracked on `GitHub Issues <https://github.com/CompassionCH/compassion-accounting/issues>`_.
In case of trouble, please check there if your issue has already been reported.
If you spotted it first, help us smashing it by providing a detailed and welcomed
`feedback <https://github.com/CompassionCH/compassion-accounting/issues/new?body=module:%20account_move_fiscalyear%0Aversion:%2010.0%0A%0A**Steps%20to%20reproduce**%0A-%20...%0A%0A**Current%20behavior**%0A%0A**Expected%20behavior**>`_.

Do not contact contributors directly about support or help with technical issues.

Credits
=======

Authors
~~~~~~~

* Compassion CH

Contributors
~~~~~~~~~~~~

* Quentin Gigon <[email protected]>
* Emanuel Cino <[email protected]>

Maintainers
~~~~~~~~~~~

This module is maintained by Compassion Switzerland.

.. image:: https://upload.wikimedia.org/wikipedia/en/8/83/CompassionInternationalLogo.png
:alt: Compassion Switzerland
:target: https://www.compassion.ch

Compassion Switzerland is a nonprofit organization whose
mission is to release children from extreme poverty in Jesus name.

This module is part of the `CompassionCH/compassion-accounting <https://github.com/CompassionCH/compassion-accounting/tree/10.0/account_move_fiscalyear>`_ project on GitHub.
10 changes: 10 additions & 0 deletions account_move_fiscalyear/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2018 Compassion CH (http://www.compassion.ch)
# @author: Quentin Gigon <[email protected]>
#
# The licence is in the file __manifest__.py
#
##############################################################################
from . import models
23 changes: 23 additions & 0 deletions account_move_fiscalyear/__manifest__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2018 Compassion CH (http://www.compassion.ch)
# @author: Quentin Gigon <[email protected]>
#
# The licence is in the file __manifest__.py
#
##############################################################################
# pylint: disable=C8101
{
'name': 'Account move open bills to next fiscal year',
'version': '10.0.0.0.0',
'license': 'AGPL-3',
'author': 'Compassion CH',
'website': 'http://www.compassion.ch',
'category': 'Accounting',
'depends': ['account'],
'external_dependencies': {},
'data': ['views/res_config_bills_view.xml'],
'demo': [],
'installable': True,
}
12 changes: 12 additions & 0 deletions account_move_fiscalyear/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
##############################################################################
#
# Copyright (C) 2018 Compassion CH (http://www.compassion.ch)
# @author: Quentin Gigon <[email protected]>
#
# The licence is in the file __manifest__.py
#
##############################################################################

from . import account_config_settings
from . import res_company
Loading

0 comments on commit 5e8a8a9

Please sign in to comment.