Bug #11771
openSynchronize Token Renewal & Expiration Behavior for Product Quote Resend and Customer Acceptance
0%
Description
While commit 39f27b74 unblocked administrators from approving product quotes older than 30 days, customer-facing acceptance in
acceptQuote
still invokes canAcceptQuote(quote), which rejects quotes created >30 days ago (now > createdAt + 30 days).
When
resendQuoteEmail
or
sendQuoteEmail
is called on an older product quotation, it does not renew acceptanceTokenExpires or acceptanceToken (unlike Landscaping Quotes in QuotationController.js). As a result, resending an old quote sends an expired link that the customer cannot accept.
2. Acceptance Criteria
AC 2.1 (Token Renewal on Resend): Given an existing product quotation where acceptanceTokenExpires <= Date.now() or is missing, When resendQuoteEmail or sendAcceptanceLink is called, Then the backend MUST generate a fresh acceptanceToken = uuidv4() and set acceptanceTokenExpires = new Date(Date.now() + 30 * 24 * 60 * 60 * 1000) before sending the email/SMS.
AC 2.2 (Customer Acceptance Grace Period): Given an older product quotation that was explicitly resent by an admin, When the customer clicks the new link within the newly granted 30-day window, Then canAcceptQuote MUST evaluate validity based on acceptanceTokenExpires rather than strictly createdAt + 30 days.
AC 2.3 (Action History Logging): Every token renewal on resend MUST append a "token_renewed" or "resent" entry into actionHistory with timestamp and user ID.
Subtasks
Related issues
No data to display