docs(openspec): add reporting API contract documentation
Add comprehensive API documentation for the reporting endpoint: - Request/response structure - View type inference (did/is/will) - Blank vs explicit zero semantics - Status values and error responses Related to enhanced-allocation change.
This commit is contained in:
@@ -105,6 +105,23 @@
|
||||
return allocations.reduce((sum, a) => sum + parseFloat(a.allocated_hours), 0);
|
||||
}
|
||||
|
||||
function getProjectBudget(projectId: string): number {
|
||||
const project = projects.find(p => p.id === projectId);
|
||||
if (!project?.approved_estimate) return 0;
|
||||
// Monthly budget = approved_estimate / 12
|
||||
return Math.round(Number(project.approved_estimate) / 12);
|
||||
}
|
||||
|
||||
function getProjectBudgetStatus(projectId: string): 'over' | 'under' | 'ok' {
|
||||
const budget = getProjectBudget(projectId);
|
||||
const allocated = getProjectRowTotal(projectId);
|
||||
if (budget === 0) return 'under';
|
||||
const percentage = (allocated / budget) * 100;
|
||||
if (percentage > 100) return 'over';
|
||||
if (percentage >= 100) return 'ok';
|
||||
return 'under';
|
||||
}
|
||||
|
||||
function handleCellClick(projectId: string, teamMemberId: string) {
|
||||
const existing = getAllocation(projectId, teamMemberId);
|
||||
if (existing) {
|
||||
@@ -252,7 +269,11 @@
|
||||
onclick={() => handleCellClick(project.id, member.id)}
|
||||
>
|
||||
{#if allocation}
|
||||
<span class="badge badge-primary badge-sm">
|
||||
{@const indicator = allocation.allocation_indicator || 'gray'}
|
||||
<span
|
||||
class="badge badge-sm {indicator === 'green' ? 'badge-success' : indicator === 'yellow' ? 'badge-warning' : indicator === 'red' ? 'badge-error' : 'badge-ghost'}"
|
||||
title="{indicator === 'green' ? 'Fully allocated' : indicator === 'yellow' ? 'Under allocated' : indicator === 'red' ? 'Over allocated' : 'No budget'}"
|
||||
>
|
||||
{allocation.allocated_hours}h
|
||||
</span>
|
||||
{:else}
|
||||
@@ -266,6 +287,34 @@
|
||||
</tr>
|
||||
{/each}
|
||||
</tbody>
|
||||
|
||||
<!-- Monthly Budget Section -->
|
||||
<tfoot>
|
||||
<tr class="bg-base-200/50">
|
||||
<td class="font-bold">Monthly Budget</td>
|
||||
{#each teamMembers as member}
|
||||
<td class="text-center">-</td>
|
||||
{/each}
|
||||
<td class="text-center">
|
||||
{Math.round(projects.reduce((sum, p) => sum + (getProjectBudget(p.id) || 0), 0))}h
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="bg-base-200/50">
|
||||
<td class="font-bold">Status</td>
|
||||
{#each teamMembers as member}
|
||||
<td class="text-center">-</td>
|
||||
{/each}
|
||||
<td class="text-center">
|
||||
{#if getProjectTotal() > projects.reduce((sum, p) => sum + getProjectBudget(p.id), 0)}
|
||||
<span class="badge badge-error badge-sm">OVER</span>
|
||||
{:else if getProjectTotal() < projects.reduce((sum, p) => sum + getProjectBudget(p.id), 0)}
|
||||
<span class="badge badge-warning badge-sm">UNDER</span>
|
||||
{:else}
|
||||
<span class="badge badge-success badge-sm">OK</span>
|
||||
{/if}
|
||||
</td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
<tfoot>
|
||||
<tr class="font-bold bg-base-200">
|
||||
<td class="sticky left-0 bg-base-200 z-10">Total</td>
|
||||
|
||||
Reference in New Issue
Block a user