File size: 2,470 Bytes
c14ceee
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
"""Feedback module — feature requests / feedback / bug reports from every user.

Sits OUTSIDE the Dashboards/Workflows nav groups (its own sidebar entry). Submissions accumulate
in the platform's writable HF Dataset store (core/store.py, key 'feedback') so they survive
restarts and are shared across users/instances. The record shape is deliberately structured so an
AI staging pass can later triage items into the build workflow (type/module/importance/status +
free-text details). No Odoo involvement at all — this module never touches ERP data.

Statuses: New (just submitted) -> Staged (AI/owner queued it for a build cycle) -> Planned ->
Done | Declined. Triage is admin-only; submitting is open to every signed-in user.
"""
import time
import datetime as dt

import core.store as store

KEY = 'feedback'
TYPES = ['Feature request', 'Feedback', 'Bug']
IMPORTANCE = ['Must have', 'Nice to have', 'Idea']
STATUSES = ['New', 'Staged', 'Planned', 'Done', 'Declined']


def available():
    return store.available()


def items(fresh=True):
    """All submissions, newest first. Lenient read (display only)."""
    data = store.get(KEY, fresh=fresh) or {}
    out = list(data.get('items', []))
    out.sort(key=lambda r: r.get('ts', ''), reverse=True)
    return out


def add(user, name, ftype, module, title, details, importance):
    """Append one submission (strict read-modify-write — a transient read error aborts,
    never clobbers). Returns the new id."""
    rec = {
        'id': f'fb-{int(time.time() * 1000)}-{user}',
        'ts': dt.datetime.now().strftime('%Y-%m-%d %H:%M'),
        'user': user, 'name': name,
        'type': ftype, 'module': module,
        'title': (title or '').strip(),
        'details': (details or '').strip(),
        'importance': importance,
        'status': 'New', 'note': '',
    }
    store.update(KEY, lambda d: {**d, 'items': d.get('items', []) + [rec]})
    return rec['id']


def set_fields(fid, **fields):
    """Update triage fields (status / note) on one submission by id."""
    def _fn(d):
        for it in d.get('items', []):
            if it.get('id') == fid:
                it.update(fields)
        return d
    store.update(KEY, _fn)


def counts(rows=None):
    """Status -> count, for the header KPIs."""
    rows = items() if rows is None else rows
    out = {s: 0 for s in STATUSES}
    for r in rows:
        out[r.get('status', 'New')] = out.get(r.get('status', 'New'), 0) + 1
    return out