mirror of
https://github.com/bringout/oca-ocb-core.git
synced 2026-04-22 00:12:07 +02:00
19.0 vanilla
This commit is contained in:
parent
d1963a3c3a
commit
2d3ee4855a
7430 changed files with 2687981 additions and 2965473 deletions
|
|
@ -2,6 +2,6 @@
|
|||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from . import onboarding_onboarding
|
||||
from . import onboarding_step
|
||||
from . import onboarding_onboarding_step
|
||||
from . import onboarding_progress
|
||||
from . import onboarding_progress_step
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ from odoo import api, fields, models
|
|||
from odoo.addons.onboarding.models.onboarding_progress import ONBOARDING_PROGRESS_STATES
|
||||
|
||||
|
||||
class Onboarding(models.Model):
|
||||
class OnboardingOnboarding(models.Model):
|
||||
_name = 'onboarding.onboarding'
|
||||
_description = 'Onboarding'
|
||||
_order = 'sequence asc, id desc'
|
||||
|
|
@ -13,15 +13,15 @@ class Onboarding(models.Model):
|
|||
name = fields.Char('Name of the onboarding', translate=True)
|
||||
# One word identifier used to define the onboarding panel's route: `/onboarding/{route_name}`.
|
||||
route_name = fields.Char('One word name', required=True)
|
||||
step_ids = fields.One2many('onboarding.onboarding.step', 'onboarding_id', 'Onboarding steps')
|
||||
step_ids = fields.Many2many('onboarding.onboarding.step', string='Onboarding steps')
|
||||
|
||||
is_per_company = fields.Boolean('Should be done per company?', default=True)
|
||||
text_completed = fields.Char(
|
||||
'Message at completion', default=lambda s: s.env._('Nice work! Your configuration is done.'),
|
||||
help='Text shown on onboarding when completed')
|
||||
|
||||
panel_background_color = fields.Selection(
|
||||
[('orange', 'Orange'), ('blue', 'Blue'), ('violet', 'Violet'), ('none', 'None')],
|
||||
string="Panel's Background color", default='orange',
|
||||
help="Color gradient added to the panel's background.")
|
||||
panel_background_image = fields.Binary("Panel's background image")
|
||||
is_per_company = fields.Boolean(
|
||||
'Should be done per company?', compute='_compute_is_per_company', readonly=True, store=False,
|
||||
)
|
||||
panel_close_action_name = fields.Char(
|
||||
'Closing action', help='Name of the onboarding model action to execute when closing the panel.')
|
||||
|
||||
|
|
@ -37,19 +37,29 @@ class Onboarding(models.Model):
|
|||
help='All Onboarding Progress Records (across companies).')
|
||||
|
||||
sequence = fields.Integer(default=10)
|
||||
_sql_constraints = [
|
||||
('route_name_uniq', 'UNIQUE (route_name)', 'Onboarding alias must be unique.'),
|
||||
]
|
||||
_route_name_uniq = models.Constraint(
|
||||
'UNIQUE (route_name)',
|
||||
'Onboarding alias must be unique.',
|
||||
)
|
||||
|
||||
@api.depends('progress_ids', 'progress_ids.company_id', 'step_ids', 'step_ids.is_per_company')
|
||||
def _compute_is_per_company(self):
|
||||
# Once an onboarding is made "per-company", there is no drawback to simply still consider
|
||||
# it per-company even when if its last per-company step is unlinked. This allows to avoid
|
||||
# handling the merging of existing progress (step) records.
|
||||
|
||||
onboardings_with_per_company_steps_or_progress = self.filtered(
|
||||
lambda o: o.progress_ids.company_id or (True in o.step_ids.mapped('is_per_company')))
|
||||
onboardings_with_per_company_steps_or_progress.is_per_company = True
|
||||
(self - onboardings_with_per_company_steps_or_progress).is_per_company = False
|
||||
|
||||
@api.depends_context('company')
|
||||
@api.depends('progress_ids', 'progress_ids.is_onboarding_closed', 'progress_ids.onboarding_state')
|
||||
@api.depends('progress_ids', 'progress_ids.is_onboarding_closed', 'progress_ids.onboarding_state', 'progress_ids.company_id')
|
||||
def _compute_current_progress(self):
|
||||
for onboarding in self:
|
||||
current_progress_id = onboarding.progress_ids.filtered(
|
||||
lambda progress: progress.company_id.id in {False, self.env.company.id})
|
||||
if current_progress_id:
|
||||
if len(current_progress_id) > 1:
|
||||
current_progress_id = current_progress_id.sorted('create_date', reverse=True)[0]
|
||||
onboarding.current_onboarding_state = current_progress_id.onboarding_state
|
||||
onboarding.current_progress_id = current_progress_id
|
||||
onboarding.is_onboarding_closed = current_progress_id.is_onboarding_closed
|
||||
|
|
@ -58,28 +68,44 @@ class Onboarding(models.Model):
|
|||
onboarding.current_progress_id = False
|
||||
onboarding.is_onboarding_closed = False
|
||||
|
||||
def write(self, vals):
|
||||
"""Recompute progress step ids if new steps are added/removed."""
|
||||
already_linked_steps = self.step_ids
|
||||
res = super().write(vals)
|
||||
if self.step_ids != already_linked_steps:
|
||||
self.progress_ids._recompute_progress_step_ids()
|
||||
return res
|
||||
|
||||
def action_close(self):
|
||||
"""Close the onboarding panel."""
|
||||
self.current_progress_id.action_close()
|
||||
|
||||
@api.model
|
||||
def action_close_panel(self, xmlid):
|
||||
"""Close the onboarding panel identified by its `xmlid`.
|
||||
|
||||
If not found, quietly do nothing.
|
||||
"""
|
||||
if onboarding := self.env.ref(xmlid, raise_if_not_found=False):
|
||||
onboarding.action_close()
|
||||
|
||||
def action_refresh_progress_ids(self):
|
||||
"""Re-initialize onboarding progress records (after step is_per_company change).
|
||||
|
||||
Meant to be called when `is_per_company` of linked steps is modified (or per-company
|
||||
steps are added to an onboarding).
|
||||
"""
|
||||
onboardings_to_refresh_progress = self.filtered(
|
||||
lambda o: o.is_per_company and o.progress_ids and not o.progress_ids.company_id
|
||||
)
|
||||
onboardings_to_refresh_progress.progress_ids.unlink()
|
||||
onboardings_to_refresh_progress._create_progress()
|
||||
|
||||
def action_toggle_visibility(self):
|
||||
self.current_progress_id.action_toggle_visibility()
|
||||
|
||||
def write(self, values):
|
||||
if 'is_per_company' in values:
|
||||
onboardings_per_company_update = self.filtered(
|
||||
lambda onboarding: onboarding.is_per_company != values['is_per_company'])
|
||||
|
||||
res = super().write(values)
|
||||
|
||||
if 'is_per_company' in values:
|
||||
# When changing this parameter, all progress (onboarding and steps) is reset.
|
||||
onboardings_per_company_update.progress_ids.unlink()
|
||||
return res
|
||||
|
||||
def _search_or_create_progress(self):
|
||||
"""Create Progress record(s) as necessary for the context.
|
||||
"""
|
||||
"""Create Progress record(s) as necessary for the context."""
|
||||
onboardings_without_progress = self.filtered(lambda onboarding: not onboarding.current_progress_id)
|
||||
onboardings_without_progress._create_progress()
|
||||
return self.current_progress_id
|
||||
|
|
@ -88,20 +114,22 @@ class Onboarding(models.Model):
|
|||
return self.env['onboarding.progress'].create([
|
||||
{
|
||||
'company_id': self.env.company.id if onboarding.is_per_company else False,
|
||||
'onboarding_id': onboarding.id
|
||||
} for onboarding in self
|
||||
'onboarding_id': onboarding.id,
|
||||
'progress_step_ids': onboarding.step_ids.progress_ids.filtered(
|
||||
lambda p: p.company_id.id in [False, self.env.company.id]
|
||||
),
|
||||
}
|
||||
for onboarding in self
|
||||
])
|
||||
|
||||
def _prepare_rendering_values(self):
|
||||
self.ensure_one()
|
||||
values = {
|
||||
'bg_image': f'/web/image/onboarding.onboarding/{self.id}/panel_background_image',
|
||||
'classes': f'o_onboarding_{self.panel_background_color}'
|
||||
if self.panel_background_color not in {False, 'none'} else '',
|
||||
'close_method': self.panel_close_action_name,
|
||||
'close_model': 'onboarding.onboarding',
|
||||
'steps': self.step_ids,
|
||||
'state': self.current_progress_id._get_and_update_onboarding_state(),
|
||||
'text_completed': self.text_completed,
|
||||
}
|
||||
|
||||
return values
|
||||
|
|
|
|||
|
|
@ -0,0 +1,133 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, Command, fields, models
|
||||
from odoo.addons.onboarding.models.onboarding_progress import ONBOARDING_PROGRESS_STATES
|
||||
from odoo.exceptions import ValidationError
|
||||
|
||||
|
||||
class OnboardingOnboardingStep(models.Model):
|
||||
_name = 'onboarding.onboarding.step'
|
||||
_description = 'Onboarding Step'
|
||||
_order = 'sequence asc, id asc'
|
||||
_rec_name = 'title'
|
||||
|
||||
onboarding_ids = fields.Many2many('onboarding.onboarding', string='Onboardings')
|
||||
|
||||
title = fields.Char('Title', translate=True)
|
||||
description = fields.Char('Description', translate=True)
|
||||
button_text = fields.Char(
|
||||
'Button text', required=True, default=lambda s: s.env._("Let's do it"), translate=True,
|
||||
help="Text on the panel's button to start this step")
|
||||
done_icon = fields.Char('Font Awesome Icon when completed', default='fa-star')
|
||||
done_text = fields.Char(
|
||||
'Text to show when step is completed', default=lambda s: s.env._('Step Completed!'), translate=True)
|
||||
step_image = fields.Binary("Step Image")
|
||||
step_image_filename = fields.Char("Step Image Filename")
|
||||
step_image_alt = fields.Char(
|
||||
'Alt Text for the Step Image', default='Onboarding Step Image', translate=True,
|
||||
help='Show when impossible to load the image')
|
||||
panel_step_open_action_name = fields.Char(
|
||||
string='Opening action', required=False,
|
||||
help='Name of the onboarding step model action to execute when opening the step, '
|
||||
'e.g. action_open_onboarding_1_step_1')
|
||||
|
||||
current_progress_step_id = fields.Many2one(
|
||||
'onboarding.progress.step', string='Step Progress',
|
||||
compute='_compute_current_progress', help='Onboarding Progress Step for the current context (company).')
|
||||
current_step_state = fields.Selection(
|
||||
ONBOARDING_PROGRESS_STATES, string='Completion State', compute='_compute_current_progress')
|
||||
progress_ids = fields.One2many(
|
||||
'onboarding.progress.step', 'step_id', string='Onboarding Progress Step Records', readonly=True,
|
||||
help='All related Onboarding Progress Step Records (across companies)')
|
||||
|
||||
is_per_company = fields.Boolean('Is per company', default=True)
|
||||
sequence = fields.Integer(default=10)
|
||||
|
||||
@api.depends_context('company')
|
||||
@api.depends('progress_ids', 'progress_ids.step_state')
|
||||
def _compute_current_progress(self):
|
||||
# When `is_per_company` is changed, `progress_ids` is updated (see `write`) which triggers this `_compute`.
|
||||
existing_progress_steps = self.progress_ids.filtered_domain([
|
||||
('step_id', 'in', self.ids),
|
||||
('company_id', 'in', [False, self.env.company.id]),
|
||||
])
|
||||
for step in self:
|
||||
if step in existing_progress_steps.step_id:
|
||||
current_progress_step_id = existing_progress_steps.filtered(
|
||||
lambda progress_step: progress_step.step_id == step)
|
||||
step.current_progress_step_id = current_progress_step_id
|
||||
step.current_step_state = current_progress_step_id.step_state
|
||||
else:
|
||||
step.current_progress_step_id = False
|
||||
step.current_step_state = 'not_done'
|
||||
|
||||
@api.constrains('onboarding_ids')
|
||||
def check_step_on_onboarding_has_action(self):
|
||||
if steps_without_action := self.filtered(lambda step: step.onboarding_ids and not step.panel_step_open_action_name):
|
||||
raise ValidationError(_(
|
||||
'An "Opening Action" is required for the following steps to be '
|
||||
'linked to an onboarding panel: %(step_titles)s',
|
||||
step_titles=steps_without_action.mapped('title'),
|
||||
))
|
||||
|
||||
def write(self, vals):
|
||||
new_is_per_company = vals.get('is_per_company')
|
||||
steps_changing_is_per_company = (
|
||||
self.browse() if new_is_per_company is None
|
||||
else self.filtered(lambda step: step.is_per_company != new_is_per_company)
|
||||
)
|
||||
already_linked_onboardings = self.onboarding_ids
|
||||
|
||||
res = super().write(vals)
|
||||
|
||||
# Progress is reset (to be done per-company or, for steps, to have a single record)
|
||||
if steps_changing_is_per_company:
|
||||
steps_changing_is_per_company.progress_ids.unlink()
|
||||
self.onboarding_ids.action_refresh_progress_ids()
|
||||
|
||||
if self.onboarding_ids - already_linked_onboardings:
|
||||
self.onboarding_ids.progress_ids._recompute_progress_step_ids()
|
||||
|
||||
return res
|
||||
|
||||
def action_set_just_done(self):
|
||||
# Make sure progress records exist for the current context (company)
|
||||
steps_without_progress = self.filtered(lambda step: not step.current_progress_step_id)
|
||||
steps_without_progress._create_progress_steps()
|
||||
return self.current_progress_step_id.action_set_just_done().step_id
|
||||
|
||||
@api.model
|
||||
def action_validate_step(self, xml_id):
|
||||
step = self.env.ref(xml_id, raise_if_not_found=False)
|
||||
if not step:
|
||||
return "NOT_FOUND"
|
||||
return "JUST_DONE" if step.action_set_just_done() else "WAS_DONE"
|
||||
|
||||
@api.model
|
||||
def _get_placeholder_filename(self, field):
|
||||
if field == "step_image":
|
||||
return 'base/static/img/onboarding_default.png'
|
||||
return super()._get_placeholder_filename(field)
|
||||
|
||||
def _create_progress_steps(self):
|
||||
"""Create progress step records as necessary to validate steps.
|
||||
|
||||
Only considers existing `onboarding.progress` records for the current
|
||||
company or without company (depending on `is_per_company`).
|
||||
"""
|
||||
onboarding_progress_records = self.env['onboarding.progress'].search([
|
||||
('onboarding_id', 'in', self.onboarding_ids.ids),
|
||||
('company_id', 'in', [False, self.env.company.id])
|
||||
])
|
||||
progress_step_values = [
|
||||
{
|
||||
'step_id': step_id.id,
|
||||
'progress_ids': [
|
||||
Command.link(onboarding_progress_record.id)
|
||||
for onboarding_progress_record
|
||||
in onboarding_progress_records.filtered(lambda p: step_id in p.onboarding_id.step_ids)],
|
||||
'company_id': self.env.company.id if step_id.is_per_company else False,
|
||||
} for step_id in self
|
||||
]
|
||||
return self.env['onboarding.progress.step'].create(progress_step_values)
|
||||
|
|
@ -19,26 +19,29 @@ class OnboardingProgress(models.Model):
|
|||
onboarding_state = fields.Selection(
|
||||
ONBOARDING_PROGRESS_STATES, string='Onboarding progress', compute='_compute_onboarding_state', store=True)
|
||||
is_onboarding_closed = fields.Boolean('Was panel closed?')
|
||||
company_id = fields.Many2one('res.company')
|
||||
company_id = fields.Many2one('res.company', ondelete='cascade')
|
||||
onboarding_id = fields.Many2one(
|
||||
'onboarding.onboarding', 'Related onboarding tracked', required=True, ondelete='cascade')
|
||||
progress_step_ids = fields.One2many('onboarding.progress.step', 'progress_id', 'Progress Steps Trackers')
|
||||
_sql_constraints = [
|
||||
('onboarding_company_uniq', 'unique (onboarding_id,company_id)',
|
||||
'There cannot be multiple records of the same onboarding completion for the same company.'),
|
||||
]
|
||||
'onboarding.onboarding', 'Related onboarding tracked', required=True, index=True, ondelete='cascade')
|
||||
progress_step_ids = fields.Many2many('onboarding.progress.step', string='Progress Steps Trackers')
|
||||
|
||||
# not in _sql_constraint because COALESCE is not supported for PostgreSQL constraint
|
||||
_onboarding_company_uniq = models.UniqueIndex("(onboarding_id, COALESCE(company_id, 0))")
|
||||
|
||||
@api.depends('onboarding_id.step_ids', 'progress_step_ids', 'progress_step_ids.step_state')
|
||||
def _compute_onboarding_state(self):
|
||||
progress_steps_data = self.env['onboarding.progress.step'].read_group(
|
||||
[('progress_id', 'in', self.ids), ('step_state', 'in', ['just_done', 'done'])],
|
||||
['progress_id'], ['progress_id']
|
||||
)
|
||||
result = dict((data['progress_id'][0], data['progress_id_count']) for data in progress_steps_data)
|
||||
for progress in self:
|
||||
progress.onboarding_state = (
|
||||
'not_done' if result.get(progress.id, 0) != len(progress.onboarding_id.step_ids)
|
||||
else 'done')
|
||||
'not_done' if (
|
||||
len(progress.progress_step_ids.filtered(lambda p: p.step_state in {'just_done', 'done'}))
|
||||
!= len(progress.onboarding_id.step_ids)
|
||||
)
|
||||
else 'done'
|
||||
)
|
||||
|
||||
def _recompute_progress_step_ids(self):
|
||||
"""Update progress steps when a step (with existing progress) is added to an onboarding."""
|
||||
for progress in self:
|
||||
progress.progress_step_ids = progress.onboarding_id.step_ids.current_progress_step_id
|
||||
|
||||
def action_close(self):
|
||||
self.is_onboarding_closed = True
|
||||
|
|
@ -48,9 +51,11 @@ class OnboardingProgress(models.Model):
|
|||
progress.is_onboarding_closed = not progress.is_onboarding_closed
|
||||
|
||||
def _get_and_update_onboarding_state(self):
|
||||
"""Used to fetch the progress of an onboarding for rendering its panel and is expected to
|
||||
be called by the onboarding controller. It also has the responsibility of updating the
|
||||
'just_done' states into 'done' so that the 'just_done' states are only rendered once.
|
||||
"""Fetch the progress of an onboarding for rendering its panel.
|
||||
|
||||
This method is expected to only be called by the onboarding controller.
|
||||
It also has the responsibility of updating the 'just_done' state into
|
||||
'done' so that the 'just_done' states are only rendered once.
|
||||
"""
|
||||
self.ensure_one()
|
||||
onboarding_states_values = {}
|
||||
|
|
|
|||
|
|
@ -10,18 +10,15 @@ class OnboardingProgressStep(models.Model):
|
|||
_description = 'Onboarding Progress Step Tracker'
|
||||
_rec_name = 'step_id'
|
||||
|
||||
progress_id = fields.Many2one(
|
||||
'onboarding.progress', 'Related Onboarding Progress Tracker', required=True, ondelete='cascade')
|
||||
progress_ids = fields.Many2many('onboarding.progress', string='Related Onboarding Progress Tracker')
|
||||
step_state = fields.Selection(
|
||||
ONBOARDING_PROGRESS_STATES, string='Onboarding Step Progress', default='not_done')
|
||||
onboarding_id = fields.Many2one(related='progress_id.onboarding_id', string='Onboarding')
|
||||
step_id = fields.Many2one(
|
||||
'onboarding.onboarding.step', string='Onboarding Step', required=True, ondelete='cascade')
|
||||
'onboarding.onboarding.step', string='Onboarding Step', required=True, index=True, ondelete='cascade')
|
||||
|
||||
_sql_constraints = [
|
||||
('progress_step_uniq', 'unique (progress_id, step_id)',
|
||||
'There cannot be multiple records of the same onboarding step completion for the same Progress record.'),
|
||||
]
|
||||
company_id = fields.Many2one('res.company', ondelete='cascade')
|
||||
|
||||
_company_uniq = models.UniqueIndex('(step_id, COALESCE(company_id, 0))')
|
||||
|
||||
def action_consolidate_just_done(self):
|
||||
was_just_done = self.filtered(lambda progress: progress.step_state == 'just_done')
|
||||
|
|
|
|||
|
|
@ -1,84 +0,0 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
|
||||
from odoo import _, api, fields, models
|
||||
from odoo.addons.onboarding.models.onboarding_progress import ONBOARDING_PROGRESS_STATES
|
||||
|
||||
|
||||
class OnboardingStep(models.Model):
|
||||
_name = 'onboarding.onboarding.step'
|
||||
_description = 'Onboarding Step'
|
||||
_order = 'sequence asc, id asc'
|
||||
_rec_name = 'title'
|
||||
|
||||
onboarding_id = fields.Many2one(
|
||||
'onboarding.onboarding', string='Onboarding', readonly=True, required=True, ondelete='cascade')
|
||||
|
||||
title = fields.Char('Title', translate=True)
|
||||
description = fields.Char('Description', translate=True)
|
||||
button_text = fields.Char(
|
||||
'Button text', required=True, default=_("Let's do it"), translate=True,
|
||||
help="Text on the panel's button to start this step")
|
||||
done_icon = fields.Char('Font Awesome Icon when completed', default='fa-star')
|
||||
done_text = fields.Char(
|
||||
'Text to show when step is completed', default=_('Step Completed! - Click to review'), translate=True)
|
||||
panel_step_open_action_name = fields.Char(
|
||||
string='Opening action', required=True,
|
||||
help='Name of the onboarding step model action to execute when opening the step, '
|
||||
'e.g. action_open_onboarding_1_step_1')
|
||||
|
||||
current_progress_step_id = fields.Many2one(
|
||||
'onboarding.progress.step', string='Step Progress',
|
||||
compute='_compute_current_progress', help='Onboarding Progress Step for the current context (company).')
|
||||
current_step_state = fields.Selection(
|
||||
ONBOARDING_PROGRESS_STATES, string='Completion State', compute='_compute_current_progress')
|
||||
progress_ids = fields.One2many(
|
||||
'onboarding.progress.step', 'step_id', string='Onboarding Progress Step Records', readonly=True,
|
||||
help='All related Onboarding Progress Step Records (across companies)')
|
||||
|
||||
sequence = fields.Integer(default=10)
|
||||
|
||||
@api.depends_context('company')
|
||||
@api.depends('progress_ids', 'progress_ids.step_state')
|
||||
def _compute_current_progress(self):
|
||||
existing_progress_steps = self.progress_ids.filtered_domain([
|
||||
('step_id', 'in', self.ids),
|
||||
('progress_id.company_id', 'in', [False, self.env.company.id]),
|
||||
])
|
||||
for step in self:
|
||||
if step in existing_progress_steps.step_id:
|
||||
current_progress_step_id = existing_progress_steps.filtered(
|
||||
lambda progress_step: progress_step.step_id == step)
|
||||
if len(current_progress_step_id) > 1:
|
||||
current_progress_step_id = current_progress_step_id.sorted('create_date', reverse=True)[0]
|
||||
step.current_progress_step_id = current_progress_step_id
|
||||
step.current_step_state = current_progress_step_id.step_state
|
||||
else:
|
||||
step.current_progress_step_id = False
|
||||
step.current_step_state = 'not_done'
|
||||
|
||||
def action_set_just_done(self):
|
||||
# Make sure progress records exist for the current context (company)
|
||||
steps_without_progress = self.filtered(lambda step: not step.current_progress_step_id)
|
||||
steps_without_progress._create_progress_steps()
|
||||
return self.current_progress_step_id.action_set_just_done()
|
||||
|
||||
def _create_progress_steps(self):
|
||||
onboarding_progress_records = self.env['onboarding.progress'].search([
|
||||
('onboarding_id', 'in', self.onboarding_id.ids),
|
||||
('company_id', 'in', [False, self.env.company.id])
|
||||
])
|
||||
progress_step_values = []
|
||||
for onboarding_progress_record in onboarding_progress_records:
|
||||
progress_step_values += [
|
||||
{
|
||||
'onboarding_id': onboarding_progress_record.onboarding_id.id,
|
||||
'progress_id': onboarding_progress_record.id,
|
||||
'step_id': step_id.id,
|
||||
}
|
||||
for step_id
|
||||
in self.filtered(lambda step: self.onboarding_id == onboarding_progress_record.onboarding_id)
|
||||
if step_id not in onboarding_progress_record.progress_step_ids.step_id
|
||||
]
|
||||
|
||||
return self.env['onboarding.progress.step'].create(progress_step_values)
|
||||
Loading…
Add table
Add a link
Reference in a new issue