-
-
Notifications
You must be signed in to change notification settings - Fork 59
[16.0][ADD] hr_personal_equipment_request_sign_oca: new module #127
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
base: 16.0
Are you sure you want to change the base?
[16.0][ADD] hr_personal_equipment_request_sign_oca: new module #127
Conversation
78020a4 to
0b98f6d
Compare
aleuffre
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Partial code review
| @@ -0,0 +1,34 @@ | |||
| <?xml version="1.0" encoding="UTF-8" ?> | |||
| <odoo> | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (non-blocking):
I think it could be useful to have these as actual data, not just demo data, maybe with a noupdate, what do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not, it helps save time in configuration. Applied changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Both files are still in the demo key in the manifest (and also still in the demo folder)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Moved files correctly, thank you.
| def _compute_personal_equipment_request_id(self): | ||
| for item in self.filtered( | ||
| lambda x: x.record_ref | ||
| and x.record_ref._name == "hr.personal.equipment.request" | ||
| ): | ||
| item.personal_equipment_request_id = item.record_ref.id | ||
|
|
||
| @api.depends("record_ref") | ||
| def _compute_employee_id(self): | ||
| for item in self.filtered( | ||
| lambda x: x.record_ref | ||
| and x.record_ref._name == "hr.personal.equipment.request" | ||
| ): | ||
| equipment_request = self.env["hr.personal.equipment.request"].browse( | ||
| item.record_ref.id | ||
| ) | ||
| item.employee_id = equipment_request.employee_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: since these are so similar and so strictly linked, they could be merged into a single compute for both fields
| compute_sudo=True, | ||
| readonly=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore: fields that are computed are also readonly by default. If they are stored, they are also compute_sudo by default
| old_employee_id = self.employee_id | ||
| new_employee_id = vals.get("employee_id") | ||
| res = super().write(vals) | ||
| if new_employee_id and new_employee_id != old_employee_id.id: | ||
| self._generate_sign_oca_request() | ||
| return res |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: Careful! self can be a recordset with multiple records
suggestion:
| old_employee_id = self.employee_id | |
| new_employee_id = vals.get("employee_id") | |
| res = super().write(vals) | |
| if new_employee_id and new_employee_id != old_employee_id.id: | |
| self._generate_sign_oca_request() | |
| return res | |
| if employee_id in vals: | |
| old_employees = {rec.id: rec.employee_id for rec in self} | |
| res = super().write(vals) | |
| if employee_id in vals: | |
| for rec in self: | |
| if rec.employee_id and rec.employee_id != old_employees.get(rec.id): | |
| rec._generate_sign_oca_request() | |
| return res |
0b98f6d to
9f12bae
Compare
aleuffre
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review
| personal_equipment_request_sign_oca_template_id = fields.Many2one( | ||
| comodel_name="sign.oca.template", | ||
| related="company_id.personal_equipment_request_sign_oca_template_id", | ||
| string="Personal Equipment Request Sign Oca Template", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore: In a related field, there's no need to re-declare any fields that are the same as the original field (like this string here)
| ) | ||
|
|
||
| @api.depends("record_ref") | ||
| def _compute_fields(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
issue: let's use a more descriptive name.
suggestion: Maybe employee_id could simply be a related field personal_equipment_request_id.employee_id, so this compute could be even simpler?
Also, maybe it could be called ppe_employee_id to make it clear it's linked to the ppe request? (I'm imagining a scenario with multiple sign related modules
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Renamed employee_id in ppe_employee_id (now it's a related field) and _compute_fields in _compute_personal_equipment_request_id.
| for item in self.filtered( | ||
| lambda x: x.record_ref | ||
| and x.record_ref._name == "hr.personal.equipment.request" | ||
| ): | ||
| item.personal_equipment_request_id = item.record_ref.id | ||
| equipment_request = self.env["hr.personal.equipment.request"].browse( | ||
| item.record_ref.id | ||
| ) | ||
| item.employee_id = equipment_request.employee_id |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: Should we explicitly set personal_requipment_request_id to False if record_ref is not a ppe request?
| for item in self.filtered( | |
| lambda x: x.record_ref | |
| and x.record_ref._name == "hr.personal.equipment.request" | |
| ): | |
| item.personal_equipment_request_id = item.record_ref.id | |
| equipment_request = self.env["hr.personal.equipment.request"].browse( | |
| item.record_ref.id | |
| ) | |
| item.employee_id = equipment_request.employee_id | |
| for item in self: | |
| if item.record_ref and item._record_ref._name == "hr.personal.equipment.request": | |
| item.personal_equipment_request_id = item.record_ref.id | |
| equipment_request = self.env["hr.personal.equipment.request"].browse( | |
| item.record_ref.id | |
| ) | |
| item.employee_id = equipment_request.employee_id | |
| else: | |
| item.personal_equipment_request_id = False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know but is okay to explicit (code is also more readable).
| for item in res: | ||
| item._generate_sign_oca_request() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore: _generate_sign_oca_request is safe for recordsets
| for item in res: | |
| item._generate_sign_oca_request() | |
| res._generate_sign_oca_request() |
| sign_request_count = fields.Integer( | ||
| string="Sign request count", | ||
| compute="_compute_sign_request_count", | ||
| compute_sudo=True, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (non-blocking):
| compute_sudo=True, | |
| store=True, |
| <table class="table table-condensed"> | ||
| <tbody> | ||
| <div> | ||
| <t> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore: empty <t> can be removed
| <tr> | ||
| <th> | ||
| Product | ||
| </th> | ||
| <th> | ||
| Quantity | ||
| </th> | ||
| <th> | ||
| Indications | ||
| </th> | ||
| </tr> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore: please fix the indentation here
| requests = self.request_1 + self.request_2 | ||
| wizard_form = Form( | ||
| self.env["sign.oca.template.generate.multi"].with_context( | ||
| default_model="hr.personal.equipment.request", active_ids=requests.ids | ||
| ) | ||
| ) | ||
| wizard_form.template_id = self.template | ||
| action = wizard_form.save().generate() | ||
| requests = self.env[action["res_model"]].search(action["domain"]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
chore (non-blocking): it's somewhat confusing to reuse the variable requests for two different objects. Also below we have request_1 which is not quite the same thing as self.request_1.
I would be grateful for more descriptive and distinct variable names.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just did some refactoring
| self.assertIn(self.partner_1, request_1.mapped("signer_ids.partner_id")) | ||
| self.assertIn(self.partner_2, request_2.mapped("signer_ids.partner_id")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question: shouldn't this be
| self.assertIn(self.partner_1, request_1.mapped("signer_ids.partner_id")) | |
| self.assertIn(self.partner_2, request_2.mapped("signer_ids.partner_id")) | |
| self.assertEqual(self.partner_1, request_1.mapped("signer_ids.partner_id")) | |
| self.assertEqual(self.partner_2, request_2.mapped("signer_ids.partner_id")) |
| def test_personal_equipment_request_write(self): | ||
| # flake8: noqa: B950 | ||
| self.company_id.personal_equipment_request_sign_oca_template_id = self.template | ||
| self.request_1.write({"employee_id": False}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion (non-blocking):
I personally prefer using object-oriented assignments whenever possible. Seems easier to read and to write
| self.request_1.write({"employee_id": False}) | |
| self.request_1.employee_id = False |
9f12bae to
06148e7
Compare
06148e7 to
9fe93b3
Compare
aleuffre
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code review, LGTM
New module to allow to generate manual and automatic signature requests from Personal Equipment Request.
Instead of a "static" template, every time a new Personal Equipment Request is created, PPE receipt document is generated and attached in the signature request.
Also, the PPE receipt report template in this module is overwritten, in order to keep the space for signature always in the same position.