fix: guard task status updates on invoice lifecycle transitions
Prevent overwriting task status when task has moved to a new revision
cycle after being invoiced. Now uses .eq('status', guardStatus) to only
update tasks still at the expected prior state:
- invoice creation: only update tasks at client_approved → invoiced
- mark sent: only client_approved → invoiced
- mark paid: only invoiced → paid
- reopen: only paid → client_approved
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -24,7 +24,8 @@
|
||||
"mcp__plugin_supabase_supabase__execute_sql",
|
||||
"Bash(sed -n '88,100p' src/pages/Tasks.jsx)",
|
||||
"Bash(sed -n '570,600p' src/pages/Tasks.jsx)",
|
||||
"Bash(git commit -q -m 'fix: hide counter on All tab in projects table *)"
|
||||
"Bash(git commit -q -m 'fix: hide counter on All tab in projects table *)",
|
||||
"Bash(git commit -q -m 'fix: guard task status updates on invoice lifecycle transitions *)"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ export default function CreateInvoice() {
|
||||
|
||||
const taskIds = [...new Set(validItems.filter(i => i.task_id && !i.submission_id).map(i => i.task_id))];
|
||||
if (taskIds.length > 0) {
|
||||
const { error: taskError } = await supabase.from('tasks').update({ invoiced: true, status: 'invoiced' }).in('id', taskIds);
|
||||
const { error: taskError } = await supabase.from('tasks').update({ invoiced: true, status: 'invoiced' }).in('id', taskIds).eq('status', 'client_approved');
|
||||
if (taskError) throw taskError;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,10 @@ export function TeamInvoiceDetailPanel({
|
||||
const taskIds = (freshItems || []).filter(i => i.task_id && !i.submission_id).map(i => i.task_id);
|
||||
if (taskIds.length > 0) {
|
||||
const newTaskStatus = status === 'paid' ? 'paid' : status === 'sent' ? 'invoiced' : 'client_approved';
|
||||
await supabase.from('tasks').update({ status: newTaskStatus }).in('id', taskIds);
|
||||
// Guard: only update tasks still at the expected prior status so tasks
|
||||
// that have moved on to a new revision cycle aren't overwritten.
|
||||
const guardStatus = status === 'paid' ? 'invoiced' : status === 'sent' ? 'client_approved' : 'paid';
|
||||
await supabase.from('tasks').update({ status: newTaskStatus }).in('id', taskIds).eq('status', guardStatus);
|
||||
}
|
||||
if (status === 'paid') {
|
||||
try {
|
||||
|
||||
@@ -410,7 +410,7 @@ export default function Invoices() {
|
||||
const validItems = invItems.filter(i => i.description);
|
||||
if (validItems.length > 0) await supabase.from('invoice_items').insert(validItems.map(it => ({ invoice_id: invoice.id, task_id: it.task_id || null, submission_id: it.submission_id || null, description: it.description, quantity: Number(it.quantity) || 1, unit_price: Number(it.unit_price) || 0 })));
|
||||
const taskIds = [...new Set(validItems.filter(i => i.task_id && !i.submission_id).map(i => i.task_id))];
|
||||
if (taskIds.length > 0) await supabase.from('tasks').update({ invoiced: true, status: 'invoiced' }).in('id', taskIds);
|
||||
if (taskIds.length > 0) await supabase.from('tasks').update({ invoiced: true, status: 'invoiced' }).in('id', taskIds).eq('status', 'client_approved');
|
||||
const subIds = [...new Set(validItems.filter(i => i.submission_id).map(i => i.submission_id))];
|
||||
if (subIds.length > 0) await supabase.from('submissions').update({ invoiced: true }).in('id', subIds);
|
||||
if (status === 'sent') {
|
||||
|
||||
Reference in New Issue
Block a user