tickets: distinguer par département + technicien assigné ; réponse courriel = Received
- TicketCard : badge Département (issue_type) + technicien (assigned_staff) → distingue les tickets quasi identiques (ex. 3 « Cancellation » = Support/Facturation/Rétention). - migrate_tickets.py : importe assigned_staff (ticket.assign_to → nom du staff) — le rattrapage ne le posait pas. Backfill des ~7,5k tickets assignés en F mais sans technicien côté ERPNext. - logToLinkedTicket : direction Received si l'expéditeur = adresse destinataire du ticket (une réponse depuis un domaine interne @targo n'est plus mal classée « Sent »). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
417ef08f58
commit
27263d7766
|
|
@ -23,6 +23,8 @@
|
|||
</template>
|
||||
</InlineField>
|
||||
</span>
|
||||
<span v-if="ticket.issue_type" class="ops-badge tk-dept"><q-icon name="apartment" size="11px" class="q-mr-xs" />{{ ticket.issue_type }}</span>
|
||||
<span v-if="ticket.assigned_staff" class="tk-assignee"><q-icon name="person" size="12px" /> {{ ticket.assigned_staff }}</span>
|
||||
<span class="tk-id">#{{ ticket.legacy_ticket_id || ticket.name }}</span>
|
||||
<span v-if="ticket.opening_date" class="tk-date"><q-icon name="event" size="12px" /> {{ ticket.opening_date }}</span>
|
||||
<q-space />
|
||||
|
|
@ -64,6 +66,8 @@ defineEmits(['open'])
|
|||
.tk-badge { font-size: 10px; padding: 1px 8px; }
|
||||
.tk-meta { display: flex; align-items: center; flex-wrap: wrap; gap: 6px 10px; margin-top: 6px; padding-left: 0; }
|
||||
.tk-id { font-size: 11px; color: #94a3b8; font-variant-numeric: tabular-nums; }
|
||||
.tk-dept { background: #eef2ff; color: #4338ca; font-size: 10px; padding: 1px 8px; display: inline-flex; align-items: center; }
|
||||
.tk-assignee { font-size: 11px; color: #64748b; display: inline-flex; align-items: center; gap: 2px; white-space: nowrap; }
|
||||
.tk-date { font-size: 11px; color: #94a3b8; white-space: nowrap; display: inline-flex; align-items: center; gap: 2px; }
|
||||
.avatar-stack { display: flex; align-items: center; }
|
||||
.avatar-stack .avatar-chip { color: #fff; font-size: 9px; font-weight: 600; border: 1.5px solid #fff; margin-left: -8px; }
|
||||
|
|
|
|||
|
|
@ -115,10 +115,14 @@ def main():
|
|||
user_by_email = {r[1]: r[0] for r in pgc.fetchall() if r[1]}
|
||||
|
||||
staff_to_user = {}
|
||||
staff_name_by_id = {} # ticket.assign_to → « Prénom Nom » (custom field assigned_staff, cf update_assigned_staff.py)
|
||||
for s in staff_list:
|
||||
email = s.get("email", "")
|
||||
if email and email in user_by_email:
|
||||
staff_to_user[s["id"]] = user_by_email[email]
|
||||
nm = ((s.get("first_name") or "") + " " + (s.get("last_name") or "")).strip() or (s.get("username") or "")
|
||||
if nm:
|
||||
staff_name_by_id[s["id"]] = nm
|
||||
|
||||
# Existing Issue Types
|
||||
pgc.execute('SELECT name FROM "tabIssue Type"')
|
||||
|
|
@ -208,6 +212,7 @@ def main():
|
|||
dept_name = dept_map.get(t.get("dept_id"), None)
|
||||
cust_name = cust_map.get(t.get("account_id"))
|
||||
is_important = 1 if t.get("important") else 0
|
||||
assigned_staff = staff_name_by_id.get(t.get("assign_to")) if t.get("assign_to") else None
|
||||
|
||||
opening_date = ts_to_dateonly(t.get("date_create"))
|
||||
opening_time = None
|
||||
|
|
@ -233,17 +238,17 @@ def main():
|
|||
naming_series, subject, status, priority, issue_type,
|
||||
customer, company, opening_date, opening_time,
|
||||
legacy_ticket_id, is_incident, is_important,
|
||||
parent_incident, service_location
|
||||
parent_incident, service_location, assigned_staff
|
||||
) VALUES (
|
||||
%s, %s, %s, %s, %s, 0, 0,
|
||||
'ISS-.YYYY.-', %s, %s, %s, %s,
|
||||
%s, %s, %s, %s,
|
||||
%s, %s, %s, %s, %s
|
||||
%s, %s, %s, %s, %s, %s
|
||||
)
|
||||
""", (issue_name, ts, ts, ADMIN, ADMIN,
|
||||
subject[:255], status, priority, dept_name,
|
||||
cust_name, COMPANY, opening_date, opening_time,
|
||||
tid, 0, is_important, None, None))
|
||||
tid, 0, is_important, None, None, assigned_staff))
|
||||
|
||||
ticket_to_issue[tid] = issue_name
|
||||
i_ok += 1
|
||||
|
|
|
|||
|
|
@ -765,7 +765,11 @@ async function logToLinkedTicket (conv, msg, subject) {
|
|||
if (!conv || !conv.linkedTickets || !conv.linkedTickets.length) return
|
||||
const issue = conv.linkedTickets[conv.linkedTickets.length - 1] // le plus récent
|
||||
if (!issue || !issue.name) return
|
||||
const sent = msg.from === 'agent'
|
||||
// Sortant seulement si NOUS écrivons (from=agent) ET pas depuis l'adresse destinataire du ticket
|
||||
// (sinon une réponse depuis un domaine interne @targo — ex. test/employé destinataire — serait mal classée « Sent »).
|
||||
const custEmail = String(conv.email || '').toLowerCase()
|
||||
const fromEmail = String(msg.fromEmail || '').toLowerCase()
|
||||
const sent = msg.from === 'agent' && (!custEmail || fromEmail !== custEmail)
|
||||
try {
|
||||
await createCommunication({
|
||||
communication_type: 'Communication', communication_medium: 'Email',
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user