Skip to content

Commit

Permalink
TA#73803 [14.0][IMP] project_wip: MultiCo and Readme
Browse files Browse the repository at this point in the history
  • Loading branch information
majouda committed Jan 27, 2025
1 parent 29b3df4 commit c90e608
Show file tree
Hide file tree
Showing 34 changed files with 78 additions and 82 deletions.
116 changes: 52 additions & 64 deletions project_wip/README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -24,101 +24,98 @@ Not all companies maintain a CFG account, depending on their business requiremen
The current module does not implement CFG.
The costs of a project are transfered directly to the CGS when the project is finished.

How The Module Works
--------------------
The module uses analytic accounts to dispatch WIP accounting entries per project.

An action on the project allows to transfer all WIP entries into CGS.

Each WIP entry is reconciled with its related CGS entry.
New WIP entries can be identified easily and transfered into CGS.

Anlytic Entries
---------------
When transfering WIP into CFG, you get the following account move:
Configuration
-------------

.. image:: static/description/account_move_wip_to_cgs.png
As member of the group `Invoicing/Billing Administrator` and has technical group `Show Full Accounting Features` checked:

At this point, creating 2 analytic entries for this move would only pollute the database.
One analytic entry would cancel the other.
.. image:: static/description/wip_account.png

A mecanism is added by the module to prevent creating analytic entries for an account move.
1- I go to `Invoicing/Configuration/Chart of Accounts`:
* I create a new account for *WIP* with `Àllow Reconciliation` checked:

To use this feature, the field `No Analytic Lines` can be checked before posting the account move.
.. image:: static/description/wip_account.png

.. image:: static/description/account_move_no_analytic_lines.png
* I create a new account fot *CGS* with `Àllow Reconciliation` checked:

.. image:: static/description/account_move_line_form_with_no_analytic_lines.png
.. image:: static/description/cgs_account.png

The analytic account field is still used to filter the general ledger by project/job.
2- I go to `Invoicing/Configuration/Journals`:
* I create a tranfert journal from *WIP* to *CGS*, I set journal type to `Miscellaneous` and give the journal a short code:

.. image:: static/description/general_ledger_filtered_by_analytic_lines.png
.. image:: static/description/transfert_journal.png

Transfering WIP To CGS
----------------------
As member of the group `Project / Manager`, I go to `Project / Configuration / Projects`, then I select my project.

.. image:: static/description/project_form.png
As member of the group `Project/Manager`, I go to `Project/Configuration/Project Types`
* I create a new type that can be applied for projects.

In the field `Type`, I click on `Create and Edit`.
.. image:: static/description/project_type.png

.. image:: static/description/project_type_field.png
* I can see a new page `Accounting` is added to the type form view.
* I fill the fields `WIP Account`, `WIP To CGS Journal` and `CGS Account` that already have been created.
- *WIP To CGS Journal*: This journal will be used when transfering WIP journal items into CGS.
- *WIP Account*: This account will be used to cumulate Work In Progress.
- *CGS Account*: This account will be used to cumulate Costs of Goods Sold.

I create a new `Project Type` named `Manufacturing`.
.. image:: static/description/project_type_accounting.png

.. image:: static/description/project_type_form.png

In the `Accounting` tab, I fill the following fields:
How The Module Works
--------------------
As member of the group `Project/Manager`, I create a project and give it a *Type* and an *Analytic Account*:

* WIP To CGS Journal: This journal will be used when transfering WIP journal items into CGS.
* WIP Account: This account will be used to cumulate Work In Progress.
* CGS Account: This account will be used to cumulate Costs of Goods Sold.
.. image:: static/description/project_with_type.png

Back to the project form, I click on `Save`.
As member of the group `Invoicing/Billing Administrator` and has technical groups `Show Full Accounting Features` and `Analytic Accounting` checked,

.. image:: static/description/project_form_save.png
1- I go to `Invoicing/Accounting/Journal Entries`,

Now, In the `Accounting` application, we are going to post three accounting entries.
2- I create 3 journal entries with `No Analytic Lines` checked:

A mecanism is added by the module to prevent creating analytic entries for an account move.
creating 2 analytic entries for this move would only pollute the database. One analytic entry would cancel the other.
To use this feature, the field `No Analytic Lines` can be checked before posting the account move.

One entry for raw materials.
* One entry for raw materials.

.. image:: static/description/raw_material_entry.png
.. image:: static/description/raw_material_entry.png

One entry for direct labour.
* One entry for direct labour.

.. image:: static/description/direct_labour_entry.png
.. image:: static/description/direct_labour_entry.png

One entry for outsourcing.
* One entry for outsourcing.

.. image:: static/description/outsourcing_entry.png
.. image:: static/description/outsourcing_entry.png

In the general ledger, I filter for the WIP account. The balance of the account is $ 300.00.
3- In the general ledger, I filter for the WIP account. The balance of the account is $ 300.00.

.. image:: static/description/general_ledger_before_wip_to_cgs.png

Back to the form view of my project, I click on `Transfer WIP To CGS`.
4- Back to the form view of my project, I click on `Transfer WIP To CGS`.

.. image:: static/description/project_wip_to_cgs_button.png

A wizard is appears.

It allows me to select a specific accounting date for the transfer.
By default, the current date is selected.
5- A wizard is appears. It allows to select a specific accounting date for the transfer.
By default, the current date is selected.

.. image:: static/description/wip_to_cgs_wizard.png

I click on `Validate`.
6- I click on `Validate`.

Back to the general ledger, I notice that the balance of the WIP account is null.
7- Back to the general ledger, I notice that the balance of the WIP account is null.

.. image:: static/description/general_ledger_after_wip_to_cgs.png

Every debit in the WIP account is reconciled with its related credit.
Every debit in the WIP account is reconciled with its related credit.

In the `Cost of Goods Sold` account, I notice 3 journal items.
8- In the `Cost of Goods Sold` account, I notice 3 journal items.

.. image:: static/description/general_ledger_cgs_account.png


The transfers from WIP to CGS did not create extra analytic entries.


Repeating the Operation
-----------------------
The operation can be repeated multiple times. Each time, only the new WIP entries will be transfered to CGS.
Expand All @@ -127,18 +124,9 @@ If I go back to the project form and click on the button. The wizard will show $

.. image:: static/description/wip_to_cgs_wizard_2nd_time.png

Analytic Entries
----------------
I go to `Accounting / Adviser / Analytic Entries`.

I see 3 analytic entries. These are the analytic entries of my initial WIP journal entries.

.. image:: static/description/project_analytic_entries.png

The transfers from WIP to CGS did not create extra analytic entries.

Transfer WIP to CGS Group
-------------------------
Releases
--------
Since the version 1.1.0 of the module, the button to open the wizard on a project is only visible to
a new group named 'Transfer WIP to CGS'.

Expand Down
2 changes: 1 addition & 1 deletion project_wip/__manifest__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

{
"name": "Project Work In Progress",
"version": "14.0.1.0.0",
"version": "14.0.1.1.0",
"author": "Numigi",
"maintainer": "Numigi",
"website": "https://bit.ly/numigi-com",
Expand Down
1 change: 0 additions & 1 deletion project_wip/models/account_analytic_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,4 @@ def _get_wip_timesheet_line_description(self):
return "{} {}".format(self.name, task) if self.name else task

def _get_wip_account(self):
self = self.with_company(self.company_id)
return self.project_id.type_id.wip_account_id
2 changes: 1 addition & 1 deletion project_wip/models/account_move_line.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class AccountMoveLine(models.Model):

def create_analytic_lines(self):
"""Prevent creating analytic lines for moves with no_analytic_lines checked."""
lines_with_no_analytic = self.filtered(lambda l: l.move_id.no_analytic_lines)
lines_with_no_analytic = self.filtered(lambda line: line.move_id.no_analytic_lines)
lines_with_analytic = self - lines_with_no_analytic

if lines_with_no_analytic:
Expand Down
10 changes: 5 additions & 5 deletions project_wip/models/project_project.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def action_wip_to_cgs_wizard(self):
"res_model": "project.wip.transfer",
"context": {
"default_project_id": self.id,
"default_company_id": self.env.user.company_id.id,
"default_company_id": self.company_id.id,
},
"target": "new",
}
Expand Down Expand Up @@ -60,7 +60,7 @@ def _action_wip_to_cgs_single(self, accounting_date=None):
move.date = accounting_date

wip_reversal_line = move.line_ids.filtered(
lambda l: l.account_id == self.type_id.wip_account_id
lambda line: line.account_id == self.type_id.wip_account_id
)

move.action_post()
Expand Down Expand Up @@ -137,13 +137,13 @@ def _get_posted_unreconciled_wip_lines(self):
:rtype: account.move.line recordset
"""
self = self.with_company(self.company_id)
return self.env["account.move.line"].search(
[
("analytic_account_id", "=", self.analytic_account_id.id),
("account_id", "=", self.type_id.wip_account_id.id),
("reconciled", "=", False),
("move_id.state", "=", "posted"),
("company_id", "=", self.company_id.id)
]
)

Expand All @@ -170,10 +170,10 @@ def _reconcile_wip_move_lines(self, wip_line, wip_reversal_line):

data = [
{
"id": None,
"id": wip_line.account_id.id,
"mv_line_ids": [wip_line.id, wip_reversal_line.id],
"new_mv_line_dicts": [],
"type": None,
"type": "account",
}
]
self.env["account.reconciliation.widget"].process_move_lines(data)
Expand Down
2 changes: 1 addition & 1 deletion project_wip/models/project_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class ProjectType(models.Model):
@api.constrains("wip_account_id")
def _check_wip_account_allows_reconcile(self):
"""Check that the wip account on project type allows reconciliation."""
self = self.with_company(self.env.user.company_id)
self = self.with_company(self.env.company)
project_types_with_wip_accounts = self.filtered(lambda t: t.wip_account_id)
for project_type in project_types_with_wip_accounts:
if not project_type.wip_account_id.reconcile:
Expand Down
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file added project_wip/static/description/cgs_account.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified project_wip/static/description/direct_labour_entry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified project_wip/static/description/general_ledger_cgs_account.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified project_wip/static/description/outsourcing_entry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file removed project_wip/static/description/project_form.png
Binary file not shown.
Binary file removed project_wip/static/description/project_form_save.png
Binary file not shown.
Binary file added project_wip/static/description/project_type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file not shown.
Binary file removed project_wip/static/description/project_type_form.png
Binary file not shown.
Binary file modified project_wip/static/description/project_wip_to_cgs_button.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified project_wip/static/description/raw_material_entry.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added project_wip/static/description/wip_account.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed project_wip/static/description/wip_to_cgs_group.png
Binary file not shown.
Binary file modified project_wip/static/description/wip_to_cgs_wizard.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
10 changes: 6 additions & 4 deletions project_wip/tests/test_account_move_no_analytic.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def setUpClass(cls):
"name": "Cost of Goods Sold",
"code": "510101",
"user_type_id": cls.env.ref("account.data_account_type_expenses").id,
"reconcile": True,
}
)
cls.account_wip = cls.env["account.account"].create(
Expand All @@ -29,6 +30,7 @@ def setUpClass(cls):
"user_type_id": cls.env.ref(
"account.data_account_type_non_current_assets"
).id,
"reconcile": True,
}
)

Expand Down Expand Up @@ -58,18 +60,18 @@ def setUpClass(cls):
}
)
cls.line_1_1 = cls.move_1.line_ids.filtered(
lambda l: l.account_id == cls.account_wip
lambda line: line.account_id == cls.account_wip
)
cls.line_1_2 = cls.move_1.line_ids.filtered(
lambda l: l.account_id == cls.account_expense
lambda line: line.account_id == cls.account_expense
)

cls.move_2 = cls.move_1.copy()
cls.line_2_1 = cls.move_2.line_ids.filtered(
lambda l: l.account_id == cls.account_wip
lambda line: line.account_id == cls.account_wip
)
cls.line_2_2 = cls.move_2.line_ids.filtered(
lambda l: l.account_id == cls.account_expense
lambda line: line.account_id == cls.account_expense
)

cls.moves = cls.move_1 | cls.move_2
Expand Down
17 changes: 12 additions & 5 deletions project_wip/wizard/project_wip_transfer.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@ class ProjectWipTransferWizard(models.TransientModel):

project_id = fields.Many2one("project.project", "Project")
cgs_journal_id = fields.Many2one(
related="project_id.type_id.cgs_journal_id", readonly=True
related="project_id.type_id.cgs_journal_id", readonly=True, company_check=True
)
wip_account_id = fields.Many2one(
related="project_id.type_id.wip_account_id", readonly=True
related="project_id.type_id.wip_account_id", readonly=True, company_check=True
)
cgs_account_id = fields.Many2one(
related="project_id.type_id.cgs_account_id", readonly=True
related="project_id.type_id.cgs_account_id", readonly=True, company_check=True
)
accounting_date = fields.Date(
default=fields.Date.context_today,
Expand All @@ -32,10 +32,17 @@ class ProjectWipTransferWizard(models.TransientModel):
related="project_id.company_id.currency_id",
readonly=True,
)
company_id = fields.Many2one(
"res.company",
"Company",
related="project_id.company_id",
readonly=True,
store=True,
)

@api.onchange("project_id")
def _onchange_project_compute_costs_to_transfer(self):
self = self.with_company(self.env.user.company_id)
self = self.with_company(self.company_id)
has_wip_account = bool(self.wip_account_id)
if has_wip_account:
self.costs_to_transfer = sum(
Expand All @@ -44,5 +51,5 @@ def _onchange_project_compute_costs_to_transfer(self):
)

def validate(self):
self = self.with_company(self.env.user.company_id)
self = self.with_company(self.company_id)
return self.project_id.action_wip_to_cgs(self.accounting_date)

0 comments on commit c90e608

Please sign in to comment.