chnages
This commit is contained in:
@@ -26,7 +26,7 @@ _SNAPSHOT_FIELDS = [
|
||||
'parallel_start',
|
||||
'triggers_workflow_state_id', # Sub 14 — workflow milestone trigger
|
||||
'requires_rack_assignment', 'requires_transition_form',
|
||||
'default_kind',
|
||||
'kind_id', # Sub 14b — replaces default_kind (now a related Char)
|
||||
]
|
||||
|
||||
# Fields on fp.step.template.input that copy 1:1 into
|
||||
@@ -90,6 +90,8 @@ class SimpleRecipeController(http.Controller):
|
||||
'sequence': step.sequence,
|
||||
'icon': step.icon,
|
||||
'default_kind': step.default_kind,
|
||||
'kind_id': step.kind_id.id if step.kind_id else False,
|
||||
'kind_name': step.kind_id.name if step.kind_id else '',
|
||||
'requires_signoff': step.requires_signoff,
|
||||
'requires_rack_assignment': step.requires_rack_assignment,
|
||||
'requires_transition_form': step.requires_transition_form,
|
||||
@@ -150,6 +152,8 @@ class SimpleRecipeController(http.Controller):
|
||||
'code': t.code,
|
||||
'icon': t.icon,
|
||||
'default_kind': t.default_kind,
|
||||
'kind_id': t.kind_id.id if t.kind_id else False,
|
||||
'kind_name': t.kind_id.name if t.kind_id else '',
|
||||
'station_count': len(t.tank_ids),
|
||||
}
|
||||
for t in records
|
||||
@@ -201,6 +205,8 @@ class SimpleRecipeController(http.Controller):
|
||||
'code': tpl.code or '',
|
||||
'icon': tpl.icon or 'fa-cog',
|
||||
'default_kind': tpl.default_kind or '',
|
||||
'kind_id': tpl.kind_id.id if tpl.kind_id else False,
|
||||
'kind_name': tpl.kind_id.name if tpl.kind_id else '',
|
||||
'description': tpl.description or '',
|
||||
'requires_signoff': tpl.requires_signoff,
|
||||
'requires_predecessor_done': tpl.requires_predecessor_done,
|
||||
@@ -245,8 +251,11 @@ class SimpleRecipeController(http.Controller):
|
||||
"""
|
||||
Tpl = request.env['fp.step.template']
|
||||
# Whitelist — never trust client-provided write_uid / id / etc.
|
||||
# Sub 14b: `default_kind` is now a related read-only Char. The
|
||||
# client may still send it as a string code for back-compat — we
|
||||
# translate it to kind_id below.
|
||||
allowed = {
|
||||
'name', 'code', 'icon', 'default_kind', 'description',
|
||||
'name', 'code', 'icon', 'kind_id', 'description',
|
||||
'requires_signoff', 'requires_predecessor_done',
|
||||
'parallel_start',
|
||||
'triggers_workflow_state_id', # Sub 14
|
||||
@@ -254,6 +263,11 @@ class SimpleRecipeController(http.Controller):
|
||||
'tank_ids',
|
||||
}
|
||||
clean = {k: v for k, v in (vals or {}).items() if k in allowed}
|
||||
# Back-compat: accept default_kind (string code) and resolve to kind_id.
|
||||
if 'kind_id' not in clean and (vals or {}).get('default_kind'):
|
||||
clean['kind_id'] = self._resolve_kind_id_from_code(
|
||||
vals['default_kind'],
|
||||
)
|
||||
# tank_ids comes in as a plain list of ids from the OWL form;
|
||||
# translate into the Odoo (6, 0, ids) command form.
|
||||
if 'tank_ids' in clean:
|
||||
@@ -266,6 +280,15 @@ class SimpleRecipeController(http.Controller):
|
||||
tpl = Tpl.create(clean)
|
||||
return {'ok': True, 'template': self._library_payload(tpl)}
|
||||
|
||||
def _resolve_kind_id_from_code(self, code):
|
||||
"""Look up fp.step.kind id by code. Empty string → False."""
|
||||
if not code:
|
||||
return False
|
||||
rec = request.env['fp.step.kind'].search(
|
||||
[('code', '=', code)], limit=1,
|
||||
)
|
||||
return rec.id or False
|
||||
|
||||
@http.route('/fp/simple_recipe/library/seed_defaults', type='jsonrpc', auth='user')
|
||||
def library_seed_defaults(self, template_id):
|
||||
"""Run action_seed_default_inputs on this template. Idempotent —
|
||||
@@ -340,6 +363,55 @@ class SimpleRecipeController(http.Controller):
|
||||
],
|
||||
}
|
||||
|
||||
@http.route('/fp/simple_recipe/kinds/list',
|
||||
type='jsonrpc', auth='user')
|
||||
def kinds_list(self):
|
||||
"""Sub 14b — Step Kind dropdown options for the inline library
|
||||
form. User-extensible via /fp/simple_recipe/kinds/create."""
|
||||
Kind = request.env['fp.step.kind']
|
||||
return {
|
||||
'kinds': [
|
||||
{
|
||||
'id': k.id,
|
||||
'code': k.code or '',
|
||||
'name': k.name or '',
|
||||
'icon': k.icon or '',
|
||||
'sequence': k.sequence,
|
||||
}
|
||||
for k in Kind.search(
|
||||
[('active', '=', True)], order='sequence, name',
|
||||
)
|
||||
],
|
||||
}
|
||||
|
||||
@http.route('/fp/simple_recipe/kinds/create',
|
||||
type='jsonrpc', auth='user')
|
||||
def kinds_create(self, name, code=''):
|
||||
"""Sub 14b — Inline create for "+ New kind…" in the library
|
||||
form. Auto-derives a code from the name if blank."""
|
||||
Kind = request.env['fp.step.kind']
|
||||
if not name or not name.strip():
|
||||
return {'ok': False, 'error': 'name_required'}
|
||||
# check_access via create attempt — supervisors+ allowed (ACL).
|
||||
if not code:
|
||||
code = name.strip().lower().replace(' ', '_').replace('/', '_')
|
||||
existing = Kind.search([('code', '=', code)], limit=1)
|
||||
if existing:
|
||||
return {
|
||||
'ok': True, 'id': existing.id,
|
||||
'name': existing.name, 'code': existing.code,
|
||||
'duplicate': True,
|
||||
}
|
||||
rec = Kind.create({
|
||||
'name': name.strip(),
|
||||
'code': code,
|
||||
})
|
||||
return {
|
||||
'ok': True, 'id': rec.id,
|
||||
'name': rec.name, 'code': rec.code,
|
||||
'duplicate': False,
|
||||
}
|
||||
|
||||
@http.route('/fp/simple_recipe/workflow_states/list',
|
||||
type='jsonrpc', auth='user')
|
||||
def workflow_states_list(self):
|
||||
@@ -457,7 +529,7 @@ class SimpleRecipeController(http.Controller):
|
||||
node.check_access('write')
|
||||
allowed = {
|
||||
'name', 'description', 'icon',
|
||||
'default_kind',
|
||||
'kind_id', # Sub 14b — replaces default_kind
|
||||
'requires_signoff', 'requires_predecessor_done',
|
||||
'parallel_start', # Sub 13
|
||||
'triggers_workflow_state_id', # Sub 14
|
||||
@@ -467,6 +539,11 @@ class SimpleRecipeController(http.Controller):
|
||||
'collect_measurements',
|
||||
}
|
||||
clean = {k: v for k, v in (vals or {}).items() if k in allowed}
|
||||
# Back-compat: accept default_kind (string code) and resolve.
|
||||
if 'kind_id' not in clean and (vals or {}).get('default_kind'):
|
||||
clean['kind_id'] = self._resolve_kind_id_from_code(
|
||||
vals['default_kind'],
|
||||
)
|
||||
if clean:
|
||||
node.write(clean)
|
||||
return {'ok': True}
|
||||
|
||||
Reference in New Issue
Block a user