Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Multi company support #16

Conversation

Martronic-SA
Copy link

Could you check this?
I've added company_ids and currency_id in MIS report instance.
For the moment, the rate calcuation is not implemented (will be soon).

Copy link
Member

@sbidoul sbidoul left a comment

Choose a reason for hiding this comment

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

Thanks for this contrib!

def __init__(self, company):
self.company = company
self.dp = company.currency_id.decimal_places
def __init__(self, company_ids=None, currency_id=None):
Copy link
Member

Choose a reason for hiding this comment

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

Can you name that companies instead of company_ids.

else:
aml_model = self.company.env[aml_model]
aml_model = self.company_ids[0].env[aml_model]
Copy link
Member

Choose a reason for hiding this comment

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

self.companies.env[aml_model] : [0] is not needed

[self.env.user.company_id]
self.currency_id = currency_id and currency_id or \
self.env.user.company_id.currency_id
self.dp = self.currency_id.decimal_places
Copy link
Member

Choose a reason for hiding this comment

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

Could you keep the currency stuff in separate commits? So we different commit(s) for multi company and multi currency and a clean commit history.

@@ -238,7 +241,7 @@ def get_aml_domain_for_dates(self, date_from, date_to,
elif mode == self.MODE_UNALLOCATED:
date_from_date = fields.Date.from_string(date_from)
fy_date_from = \
self.company.\
self.company_ids[0].\
Copy link
Member

Choose a reason for hiding this comment

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

Hm. Here it's a special treatment for the first company. This could lead to surprises.

Could you extract the fy_date_from computation in a separate method and add a check (raise UserError) that all companies have the same fy_date_from? Later we can add logic to handle companies with different fiscal years.

Copy link
Author

Choose a reason for hiding this comment

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

I can see some border effects when company is located in Australia with GMT +12, but this can be fixed.
However don't you think that for this particular case (at least) the main company (or user.company_id) is useful?

Copy link
Member

Choose a reason for hiding this comment

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

It could be useful to have a main company but not in AEP. Perhaps in mis_report_instance. But even that I'm not sure and I certainly have not studied the impact of having different fiscal years on the computation of consolidated initial balances... Until that is clarified I prefer to raise an error if the various companies have different fiscal year dates.

help='Select companies for which data will be searched. \
User\'s company if empty.',
default=_default_company_ids,
required=False)
Copy link
Member

Choose a reason for hiding this comment

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

Could you use this style for new/modified fields?

company_ids = fields.Many2many(
        comodel_name='res.company',
        string='Company',
        help='Select companies for which data will  be searched. '
                 'User\'s company if empty.',
        default=_default_company_ids,
        required=False,
)

Copy link
Member

Choose a reason for hiding this comment

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

A migration script is needed.

default=_default_company_ids,
required=False)
currency_id = fields.Many2one('res.currency', 'Currency',
required=False)
Copy link
Member

Choose a reason for hiding this comment

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

Could you please do multi currency in another PR?

_company_default_get('mis.report.instance')
def _default_company_ids(self):
return [(6,0,[self.env['res.company'].\
_company_default_get('mis.report.instance').id])]
Copy link
Member

Choose a reason for hiding this comment

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

flake8 will complain here

Copy link
Member

Choose a reason for hiding this comment

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

I'm wondering if return _company_default_get('mis.report.instance') would work too?

Copy link
Author

Choose a reason for hiding this comment

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

I'm wondering if return _company_default_get('mis.report.instance') would work too?

That's what I was using first, but there were a json complaint about res.company not serialisable.
Why flake8 will complain?

Copy link
Member

Choose a reason for hiding this comment

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

flake8 requires a space after commas

@sbidoul
Copy link
Member

sbidoul commented Jun 19, 2017

Can you add a new test for multi-company AEP?

time.strftime('%Y') + '-03-31',
'posted')
self.assertEquals(end, {
self.account_ar.id: (900, 0),
self.account_in.id: (0, 800),
})
unallocated = AEP.get_unallocated_pl(
self.company,
self.company_ids,
Copy link
Member

Choose a reason for hiding this comment

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

test_aep.py should be unchanged: existing tests in this file should continue to work without change.

Copy link
Author

Choose a reason for hiding this comment

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

So you the the AEP init method shoud accept company and companies as first argument and I shoud add check whether theare are one or many companies passed?

Copy link
Member

Choose a reason for hiding this comment

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

What I mean is that for Odoo, a recordset of 1 is still a recordset, and create returns a recordset of 1. So these tests can remain unmodified and work normally even if AEP.__init__ accept companies as argument.

@Martronic-SA
Copy link
Author

Martronic-SA commented Jun 21, 2017

Even if currency support is in a separate request, we still need to choose a main currency for total amounts calculation as account.move.lines might be in different currencies.
Do you see a way to output the main currency in the report?
What do you think about having a cell of type "Monetary" that would format the number as Monetary field according to the main currency in report? or a new checkbox in the style for "Monetary" ?

EDITED : This PR

@sbidoul
Copy link
Member

sbidoul commented Jun 21, 2017

Regarding this PR, a few things remain todo before merging;

Regarding multi-currency I would not worry too much with the display issue: we currently do it with a suffix/prefix in the styles, it does the job. Doing the currency conversion in an efficient manner is the key problem to resolve.

@sbidoul
Copy link
Member

sbidoul commented Jun 21, 2017

Please please do the currency conversion in another pull request so this one remains reasonably small and easy to review.

@Martronic-SA
Copy link
Author

I've added a basic currency conversion of amounts to the main currency.
(For now, the main currency is the user's company currency.)
This will at least avoid having amounts in different currencies mixed together.
This does not support choosing currency rates at a particular date..

# in initial mode, ignore accounts with 0 balance
continue
self._data[key][acc['account_id'][0]] = (debit, credit)
if company.currency_id != self.currency_id:
rate = self.currency_id.rate / company.currency_id.rate
Copy link
Author

Choose a reason for hiding this comment

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

The basic implementation is quite simple.
Get the account for the line, get its company. If account company currency is not the same as APE currency, do the conversion (using current rate for now)

@@ -281,14 +284,20 @@ def do_queries(self, date_from, date_to,
['debit', 'credit', 'account_id'],
['account_id'])
for acc in accs:
company = account_model.browse(acc['account_id'][0]).company_id
Copy link
Member

Choose a reason for hiding this comment

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

This browse inside the loop is bad for performance.

I suggest:

  1. fetching and computing currency rates by company at the beginning of the method, outside of the loops, store that in a dictionary
  2. adding company_id in the read_group

Copy link
Author

Choose a reason for hiding this comment

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

Yes good idea!

Copy link
Author

Choose a reason for hiding this comment

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

What do you think about the precision rounding in float_is_zero method ? should it be company currency rounding or AEP currency rounding?

Copy link
Member

Choose a reason for hiding this comment

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

Use self.dp, which should come from the target currency.

Copy link
Author

Choose a reason for hiding this comment

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

But if target currency is CHF which is 0.5 rounding and we're getting amounts in EUR which rounding is 0.1, won't we miss some amounts? That could be problematic especially if there are many amounts with 0.1 or 0.2 ?

Copy link
Member

Choose a reason for hiding this comment

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

Hm. Indeed this float_compare occurs before currency conversion, so you are probably right, yes.

def __init__(self, companies, currency_id=None):
self.companies = companies
self.currency_id = currency_id and currency_id or \
self.companies.env.user.company_id.currency_id
Copy link
Member

@sbidoul sbidoul Jun 22, 2017

Choose a reason for hiding this comment

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

here, raise UserError if currency_id is not set and companies don't have all the same currency

Copy link
Author

Choose a reason for hiding this comment

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

Ok, but we might also consider that user wants to see the amounts in his own currency by default. But then we would need the Monetary cell as if not set, the traget currency depends on user

Copy link
Member

Choose a reason for hiding this comment

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

In that case the user will specify the currency explicitly in mis_report_instance.
AEP is a low level API, and I want it to have as little implicit behaviour as possible.

Copy link
Author

Choose a reason for hiding this comment

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

Ok, that's a good reason.

@Martronic-SA
Copy link
Author

Martronic-SA commented Jun 23, 2017

TODO:
Testing
test the tests, I've added an test for multi company. I've not been able to setup a testing environment and I've not been able to test those test files.
There is missing a proper test for currency conversion (set a currency rate and check the final results).
(But I've tested on a dev DB and it's working fine.)

Migration

  • Write the migration script to convert from company to company_ids in mis.report.instance

There is missing some functionalities to have this 100% usable, at least:

  • Add currency field in the mis.report.instance (separate PR)
  • Display a number as a monetary field and format it according to the target currency. Might be done either with a new type of cell "Monetary" or a checkbox in the style "Monetary formatting".
  • Add a selection field with options to tell the AEP how to choose the right date for currency rate conversion. That could be now, start/end of the report, start/end of each period or an average on the report/period, or..?

@Martronic-SA
Copy link
Author

I think we are ready to add the currency_id field to mis report instance?
It's not a big change, I've done it in a sapearate branch here and it's working fine:
10.0-mis_builder-3-currency

@sbidoul
Copy link
Member

sbidoul commented Jun 23, 2017

Yes, now that all the multi-currency logic in AEP is in this branch, it's a small change to add curency_id in mis_report_instance in this PR.

SELECT id as mis_report_instance_id,
company_id as res_company_id
FROM mis_report_instance;
""")
Copy link
Member

Choose a reason for hiding this comment

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

Hm that's a lot of code.

Better use openupgradelib for this: https://github.com/OCA/openupgradelib/blob/master/openupgradelib/openupgrade.py#L789

Also bump version to 10.0.3.1.0 and make a different migration directory for that.

Copy link
Author

Choose a reason for hiding this comment

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

So much simpler, thank you for remind me the openupgrade

@Martronic-SA
Copy link
Author

Martronic-SA commented Jun 28, 2017

I think we should add company_ids to mis.report.instance.period and if not null, add the company filter to
_get_additional_move_line_filter and _get_additional_query_filter methods.
This is useful if you want to make a comparision between companies in a table with a company per column.

We might better add company_ids filter field to sub kpi filter

@sbidoul
Copy link
Member

sbidoul commented Jun 30, 2017

Thanks a lot for your work! I've too little time to finalize the review and merge now, but I keep an eye on this and will do as soon as I can.

@Martronic-SA
Copy link
Author

Please check also this PR
It's the Monetary type of value which takes the currency set in report instance or user's currency to format the values automatically.

@sbidoul sbidoul force-pushed the 10.0-mis_builder-3-sbi branch 2 times, most recently from 2803bb3 to 14b7f5e Compare September 1, 2017 15:51
@sbidoul
Copy link
Member

sbidoul commented Sep 3, 2017

@Martronic-SA Thanks for your contributions and patience.

I'm now back working on this and I'm planning to do a release with as many new features as possible before end of september.

I'll now flesh out the tests a little bit and merge at least some parts of this multi company PR.

Could you rebase it on OCA#275 ?

@Martronic-SA
Copy link
Author

@sbidoul I'm back from holidays.
Unfortunately I'm having trouble with rebasing. I'm not very used to git in fact.
Any advice?
Thank you

@sbidoul
Copy link
Member

sbidoul commented Sep 24, 2017

Here is a rough rebasing procedure:

  • make sure you have a git remote named acsone: git remote add acsone https://github.com/acsone/account-financial-reporting.git
  • git fetch --all
  • git rebase acsone/10.0-mis_builder-3-sbi
  • in case of conflict, edit the conflicting files to resolve the conflict (look for === in the files), then git add the corrected files, the git rebase --continue
  • the git push -f

@sbidoul
Copy link
Member

sbidoul commented Sep 24, 2017

@Martronic-SA will you be at the OCA code sprint in Louvain-la-Neuve?

@sbidoul sbidoul force-pushed the 10.0-mis_builder-3-sbi branch from b77bcb5 to d38052e Compare September 26, 2017 08:30
@Martronic-SA
Copy link
Author

Thank you very much for the procedure.
I think it's ok now with the rebase.
Unfortunately I can't be there in Louvain-La-Neuve next week but I will be there remotely if possible.

@sbidoul
Copy link
Member

sbidoul commented Sep 27, 2017

@Martronic-SA could you review OCA#275 ?

We'll merge that first then move on with your other PRs.

@Martronic-SA
Copy link
Author

I think everything is fine with OCA#275. ok for me!

@sbidoul
Copy link
Member

sbidoul commented Sep 27, 2017

Can write your approval there?

@sbidoul
Copy link
Member

sbidoul commented Oct 2, 2017

I'm currently moving this PR to OCA/mis-builder.

@sbidoul
Copy link
Member

sbidoul commented Oct 2, 2017

Moved to OCA/mis-builder#23

@sbidoul sbidoul closed this Oct 2, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants