Skip to content

Commit

Permalink
TA#73803 [14.0][IMP] project_wip: MultiCo and Readme (#500)
Browse files Browse the repository at this point in the history
  • Loading branch information
majouda authored Jan 27, 2025
1 parent 29b3df4 commit 1a7850b
Show file tree
Hide file tree
Showing 34 changed files with 97 additions and 88 deletions.
141 changes: 71 additions & 70 deletions project_wip/README.rst
Original file line number Diff line number Diff line change
@@ -1,148 +1,149 @@
Project Work In Progress
========================
This module enables to manage `Work In Progress` (WIP) accounting.
This module enables to manage ``Work In Progress`` (WIP) accounting.

.. contents:: Table of Contents

Work In Progress
----------------
`Work In Progress` is an account of the general ledger.
``Work In Progress`` is an account of the general ledger.

It includes consumed products, direct labour costs and factory overhead costs
related to an unfinished manufacturing project.

Once a project is delivered, the costs associated to this project are transfered
to the `Cost of Finished Goods` (CFG) or to the `Cost of Goods Sold` (CGS).
to the ``Cost of Finished Goods`` (CFG) or to the ``Cost of Goods Sold`` (CGS).

Cost of Finished Goods
----------------------
`Cost of Finished Goods` (CFG) is a step between WIP and CGS.
``Cost of Finished Goods`` (CFG) is a step between WIP and CGS.

It represents finished products that are still in inventory.
Not all companies maintain a CFG account, depending on their business requirements.

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.
Configuration
-------------

An action on the project allows to transfer all WIP entries into CGS.
As member of the group ``Invoicing/Billing Administrator`` and has technical group ``Show Full Accounting Features`` checked:

Each WIP entry is reconciled with its related CGS entry.
New WIP entries can be identified easily and transfered into CGS.
.. image:: static/description/invoicing_access.png

Anlytic Entries
---------------
When transfering WIP into CFG, you get the following account move:
- I go to ``Invoicing/Configuration/Chart of Accounts``:

.. image:: static/description/account_move_wip_to_cgs.png
* I create a new account for *WIP* with ``Àllow Reconciliation`` 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.

To use this feature, the field `No Analytic Lines` can be checked before posting the account move.
* I create a new account fot *CGS* with ``Àllow Reconciliation`` checked:

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

.. image:: static/description/account_move_line_form_with_no_analytic_lines.png
- I go to ``Invoicing/Configuration/Journals``:

The analytic account field is still used to filter the general ledger by project/job.
* 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``:

In the field `Type`, I click on `Create and Edit`.
- I create a new type that can be applied for projects.

.. image:: static/description/project_type_field.png
.. image:: static/description/project_type.png

I create a new `Project Type` named `Manufacturing`.
- 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.

.. image:: static/description/project_type_form.png
*WIP To CGS Journal* : This journal will be used when transfering WIP journal items into CGS.

In the `Accounting` tab, I fill the following fields:
*WIP Account* : This account will be used to cumulate Work In Progress.

* 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.
*CGS Account* : This account will be used to cumulate Costs of Goods Sold.

Back to the project form, I click on `Save`.
.. image:: static/description/project_type_accounting.png

.. image:: static/description/project_form_save.png

Now, In the `Accounting` application, we are going to post three accounting entries.
How The Module Works
--------------------
As member of the group ``Project/Manager``, I create a project and give it a ``Type`` with configured accounts and an ``Analytic Account``:

One entry for raw materials.
.. image:: static/description/project_with_type.png

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

One entry for direct labour.
- I go to ``Invoicing/Accounting/Journal Entries``,

.. image:: static/description/direct_labour_entry.png
- 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 outsourcing.
* One entry for raw materials.

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

In the general ledger, I filter for the WIP account. The balance of the account is $ 300.00.
* One entry for direct labour.

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

Back to the form view of my project, I click on `Transfer WIP To CGS`.
* One entry for outsourcing.

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

A wizard is appears.

It allows me to select a specific accounting date for the transfer.
By default, the current date is selected.
- In the general ledger, I filter for the WIP account. The balance of the account is $ 300.00.

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

I click on `Validate`.

Back to the general ledger, I notice that the balance of the WIP account is null.
- Back to the form view of my project, I click on ``Transfer WIP To CGS``.

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

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

In the `Cost of Goods Sold` account, I notice 3 journal items.
- 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/general_ledger_cgs_account.png
.. image:: static/description/wip_to_cgs_wizard.png

Repeating the Operation
-----------------------
The operation can be repeated multiple times. Each time, only the new WIP entries will be transfered to CGS.

If I go back to the project form and click on the button. The wizard will show $ 0.00 to transfer.
- I click on ``Validate``.

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

Analytic Entries
----------------
I go to `Accounting / Adviser / Analytic Entries`.
- 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

I see 3 analytic entries. These are the analytic entries of my initial WIP journal entries.
Every debit in the WIP account is reconciled with its related credit.

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

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

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

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

Transfer WIP to CGS Group
-------------------------

Repeating the Operation
-----------------------
The operation can be repeated multiple times. Each time, only the new WIP entries will be transfered to CGS.

If I go back to the project form and click on the button. The wizard will show $ 0.00 to transfer.

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


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'.

.. image:: static/description/wip_to_cgs_group.png
.. image:: static/description/wip_to_cgs_group.png

Users do not need to be members of Project / Manager to transfer the journal entries.

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 modified project_wip/static/description/wip_to_cgs_group.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/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 1a7850b

Please sign in to comment.