fix: invoice picker skips review-shadow rows for service_type/pricing

Review-shadow submissions are type=initial with blank service_type; the
picker grabbed the first initial found, hitting a shadow -> null service ->
$0 price. New pickInitialServiceType() skips shadows and prefers a real
service_type. Fixes Harlingen sites showing $0 on invoice.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Krao Hasanee
2026-06-11 22:29:42 -04:00
parent 4ef73d193d
commit 1784af909d
4 changed files with 25 additions and 13 deletions
+13
View File
@@ -35,6 +35,19 @@ export function getVisibleTaskSubmissions(submissions = []) {
return (submissions || []).filter(submission => !isReviewShadowSubmission(submission));
}
// Picks the representative service_type for a task's initial work for pricing.
// Skips review-shadow rows and blank service_types (those break price lookups),
// preferring a real initial submission, then any submission with a service_type.
export function pickInitialServiceType(submissions = [], fallback = '') {
const visible = getVisibleTaskSubmissions(submissions);
const initialWithSvc = visible.find(s => s?.type === 'initial' && s?.service_type);
if (initialWithSvc?.service_type) return initialWithSvc.service_type;
const anyInitial = visible.find(s => s?.type === 'initial');
if (anyInitial?.service_type) return anyInitial.service_type;
const anyWithSvc = visible.find(s => s?.service_type);
return anyWithSvc?.service_type || fallback;
}
export function getLatestVisibleSubmissionForVersion(taskId, submissions = [], versionNumber = 0) {
return getVisibleTaskSubmissions(submissions)
.filter(submission => submission?.task_id === taskId && (submission?.version_number || 0) === versionNumber)