Skip to content

Conversation

@EdgarRetes
Copy link
Contributor

@max3903 max3903 added this to the 18.0 milestone Oct 16, 2024
@max3903 max3903 self-assigned this Oct 16, 2024
@max3903
Copy link
Member

max3903 commented Oct 16, 2024

/ocabot migration fieldservice_account_analytic

@OCA-git-bot OCA-git-bot mentioned this pull request Oct 16, 2024
33 tasks
@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch from d3e562e to d48f879 Compare November 5, 2024 20:16
@max3903
Copy link
Member

max3903 commented Nov 15, 2024

/ocabot migration fieldservice_account_analytic

@max3903 max3903 changed the title [18.0][MIG]fieldservice_account_analytic [18.0][MIG] fieldservice_account_analytic Nov 15, 2024
@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch 5 times, most recently from 6a59d33 to 50d20bf Compare November 22, 2024 22:11
@EdgarRetes
Copy link
Contributor Author

@brian10048 @max3903

@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch from 50d20bf to 4a17d52 Compare November 22, 2024 22:42
@max3903
Copy link
Member

max3903 commented Nov 23, 2024

@EdgarRetes We need to create 3 analytic plans:

  • FSM Orders
  • FSM Locations
  • FSM Routes

and:

  • Create a new account in the FSM Orders plan for each order
  • Create a new account in the FSM Locations plan for each location
  • CReate a new account in the FSM Routes plan for each route

When creating the customer invoice, vendor bill line or timesheet entry, we need to set the corresponding analytic account in each plan.

We also need to activate the following settings/groups:

  • Technical/Analytic Accounting
  • Technical/Show Full Accounting Features --> Add a dependency on account_usability

@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch 2 times, most recently from f0ef587 to 062bb59 Compare November 27, 2024 20:19
@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch 8 times, most recently from 52ad51f to 40d4df5 Compare November 29, 2024 19:51
@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch from e7f8bb5 to 849fdc4 Compare December 2, 2024 19:08
@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch from 849fdc4 to 5c93b75 Compare December 2, 2024 20:19
@EdgarRetes EdgarRetes requested a review from max3903 December 2, 2024 20:22
@EdgarRetes EdgarRetes force-pushed the 18.0-mig-fieldservice_account_analytic branch from 4181c76 to b7ce772 Compare December 5, 2024 17:05
@max3903
Copy link
Member

max3903 commented Dec 6, 2024

@EdgarRetes

I think all the features around route can be moved to fieldservice and hidden with a group (activated in the settings).

All the analytic features can be moved to fieldservice_account and hidden with the existing group/setting.

@EdgarRetes
Copy link
Contributor Author

@EdgarRetes

I think all the features around route can be moved to fieldservice and hidden with a group (activated in the settings).

All the analytic features can be moved to fieldservice_account and hidden with the existing group/setting.

Do you have any example of a repository that does this?

@are-agilebg
Copy link

@max3903 since the changes you're proposing are, if I'm not mistaken, refactoring of the actual logic and this PR is stale for a long time, don't you think we can postpone the refactoring to a later PR and prioritize the pure migration of the logic as-is? Also, this module not migrated 'blocks' the migration of fieldservice_isp_account.

Do you think this could be feasible? Thanks

@max3903
Copy link
Member

max3903 commented Mar 10, 2025

Let me discuss it with @santiagordz and give it higher priority.

@are-agilebg
Copy link

Let me discuss it with @santiagordz and give it higher priority.

Sorry if I bother you: have you had a chance to discuss it?

@max3903
Copy link
Member

max3903 commented Apr 28, 2025

Sorry if I bother you: have you had a chance to discuss it?

Nope. @SMaciasOSI Can you get this in the todo list of @dcamacho20?

@are-agilebg
Copy link

Sorry if I bother you: have you had a chance to discuss it?

Nope. @SMaciasOSI Can you get this in the todo list of @dcamacho20?

Thanks for looking into it! We'll probably start anyway to migrate fieldservice_isp_account internally to 18.0 using this open PR as a dependency.

@vvrossem
Copy link
Contributor

Hello 👋
I'm migrating fieldservice_isp_account (#1442) but several unit tests are failing because of required fields introduced in fieldservice_account_analytic.
Example: fieldservice_crm (which doesn't depend on fieldservice_account_analytic) fails to create a fsm.location because the required field customer_id is not present.

@EdgarRetes would you mind rebasing this PR? I suspect the CI will fail too: some modules have been merged meanwhile.

Copy link
Contributor

@ivantodorovich ivantodorovich left a comment

Choose a reason for hiding this comment

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

Hello 👋🏻 !

I just did a review commit by commit.
Some of my comments may be outdated, as the code is overwritten by following commits. However, the content is still valid in most cases.

Can you clean up a bit the commits, please?
I believe the changes are not atomic and well organized. If not possible, then it's better to squash everything into the migration commit and write a nice message describing the main changes.

Some things are blocking for me, like the addition of the new dependency, and the new init_hook.

vals["account_id"] = order.location_id.analytic_account_id.id
else:
raise ValidationError(
_("No analytic account set " "on the order's Location.")
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use self.env._

return super().create(vals)
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
Copy link
Contributor

Choose a reason for hiding this comment

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

I know it was like this before, but please lets only loop if vals.get("fsm_order_id"), as it makes no sense to get into this iteration otherwise



class AnalyticAccount(models.Model):
_inherit = "account.analytic.account"
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we split this into two files: account_analytic_line.py and account_analytic_account.py ?

_inherit = "account.analytic.account"

fsm_order_id = fields.One2many("fsm.order", "analytic_account_id", copy=False)
# route_id = fields.One2many("tms.route", "analytic_account_id", copy=False)
Copy link
Contributor

Choose a reason for hiding this comment

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

What's with this commented out line?

Copy link
Contributor

Choose a reason for hiding this comment

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

NOTE: This line is overwriten in a following commit.
Still: clearly commits are not atomic and require some cleaning

Comment on lines 48 to 54
{
"name": vals.get("name"),
"plan_id": self.env.ref(
"fieldservice_account_analytic.fsm_order_analytic_plan"
).id,
"fsm_order_id": record,
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Please move the vals preparation to a separate method. This makes it possible to easily override in other modules if needed. e.g: _prepare_analytic_account_vals

"plan_id": self.env.ref(
"fieldservice_account_analytic.fsm_order_analytic_plan"
).id,
"fsm_order_id": record,
Copy link
Contributor

Choose a reason for hiding this comment

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

set also the company_id and partner_id

@api.model
def create(self, vals):
record = super().create(vals)
analytic_account = self.env["account.analytic.account"].create(
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comments than the fsm.order model:

  • use model_create_multi
  • separate method for vals preparation
  • create only if not explicitly set in vals

# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl).

from odoo import api, fields, models
from odoo import _, api, fields, models
Copy link
Contributor

Choose a reason for hiding this comment

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

Use self.env._ instead, everywhere

"analytic",
"product",
"fieldservice_route",
"account_usability",
Copy link
Contributor

Choose a reason for hiding this comment

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

What's with this new dependency?

users = env["res.users"].search([])

for user in users:
user.write({"groups_id": [(4, group_analytic_accounting.id)]})
Copy link
Contributor

Choose a reason for hiding this comment

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

This is not correct.

You can't just give this group to every user in the db

<field name="name">account.analytic.line.fsm.manager</field>
<field name="model_id" ref="model_account_analytic_line" />
<field name="global" eval="False" />
<field name="domain_force">[(1, '=', 1)]</field>
Copy link
Contributor

Choose a reason for hiding this comment

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

This is coming from previous versions, but it's not correct.
It grants too much power.

It should only grant access to lines having a fsm_order_id, IMO:

Suggested change
<field name="domain_force">[(1, '=', 1)]</field>
<field name="domain_force">[('fsm_order_id', '!=', False)]</field>

Comment on lines +17 to +22
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('fieldservice.group_fsm_dispatcher'))]" />
<field name="perm_read" eval="True" />
<field name="perm_write" eval="True" />
<field name="perm_create" eval="True" />
<field name="perm_unlink" eval="True" />
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as before, but it's also giving too much power.
The dispatcher should probably only see them, but I'm not sure if it should modify them 🤔
TBD

Suggested change
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('fieldservice.group_fsm_dispatcher'))]" />
<field name="perm_read" eval="True" />
<field name="perm_write" eval="True" />
<field name="perm_create" eval="True" />
<field name="perm_unlink" eval="True" />
<field name="domain_force">[('fsm_order_id', '!=', False)]</field>
<field name="groups" eval="[(4, ref('fieldservice.group_fsm_dispatcher'))]" />
<field name="perm_read" eval="True" />
<field name="perm_write" eval="False" />
<field name="perm_create" eval="False" />
<field name="perm_unlink" eval="False" />

<field name="perm_create" eval="True" />
<field name="perm_unlink" eval="True" />
</record>
</odoo>
Copy link
Contributor

Choose a reason for hiding this comment

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

Moreover, the user should be able to see and record his own timesheets

Suggested change
</odoo>
<record id="analytic_account_fsm_user" model="ir.rule">
<field name="name">account.analytic.line.fsm.user</field>
<field name="model_id" ref="model_account_analytic_line" />
<field name="domain_force">[('fsm_order_id', '!=', False), ('user_id', '=', user.id)]</field>
<field name="groups" eval="[Command.link(ref('fieldservice.group_fsm_user'))]" />
</record>
</odoo>

Copy link
Contributor

Choose a reason for hiding this comment

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

This file should be moved to security/

Comment on lines +11 to +25
@api.model_create_multi
def create(self, vals_list):
for vals in vals_list:
if vals.get("fsm_order_ids") and len(vals.get("fsm_order_ids")[0]) > 2:
fsm_orders = vals.get("fsm_order_ids")[0][2]
for order in self.env["fsm.order"].browse(fsm_orders).exists():
if order.location_id.analytic_account_id:
vals["analytic_distribution"] = {
order.location_id.analytic_account_id.id: 100
}
else:
raise ValidationError(
_("No analytic account " "set on the order's Location.")
)
return super().create(vals_list)
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be done in an override of _compute_analytic_distribution, instead of a create override.

Comment on lines +27 to +29
@api.onchange("product_id")
def onchange_product_id(self):
self.name = self.product_id.name if self.product_id else False
Copy link
Contributor

Choose a reason for hiding this comment

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

This is too invasive for other modules adding their own analytic lines.

I'm not sure we want this, anyway.

My recommendation would be to remove it.
And if we really want it, it shuold be limited only on those analytic.lines that have a fsm_order_id

Suggested change
@api.onchange("product_id")
def onchange_product_id(self):
self.name = self.product_id.name if self.product_id else False

@api.model_create_multi
def create(self, vals_list):
record = super().create(vals_list)
if self.env.user.has_group("analytic.group_analytic_accounting"):
Copy link
Contributor

Choose a reason for hiding this comment

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

It shouldn't matter if the user creating the FSM order has access to accounting or not.
The behavior should be the same.

Moreover, the account should be created only if it's not already provided in the vals. Otherwise we'd be overwriting it.

Comment on lines +62 to +72
for vals in vals_list:
analytic_account = self.env["account.analytic.account"].create(
{
"name": vals.get("name"),
"plan_id": self.env.ref(
"fieldservice_account_analytic.fsm_location_analytic_plan"
).id,
"fsm_location_id": record,
}
)
record.analytic_account_id = analytic_account
Copy link
Contributor

Choose a reason for hiding this comment

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

This for..loop is totally wrong.

It's looping through all the vals in vals_list, but for each iteration it's assigning the created analytic account to record (which in fact should be spelled records [plural]).

So, all the created records will end up with the same analytic account --> the one created for the last of them

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.