feat(workforce): keep the hourly rate off the workers roster
The Rate / hr column put every worker's wage on a wide table that is glanceable, projected and exported. The rate already lives on the worker detail page, where it is a deliberate lookup. Drop the column from the roster and the rate from its CSV export — the export is the wider accidental leak, since that file gets emailed and opened on shared machines. Site managers can still see a worker's rate by opening the worker, which stays deliberate access.
This commit is contained in:
parent
34017d8630
commit
88a3a1e1be
3 changed files with 3 additions and 10 deletions
|
|
@ -7,7 +7,7 @@ import { EmployeesView } from "./employees-view";
|
|||
it("keeps worker assignments read-only until the edit sheet is opened", () => {
|
||||
const html = renderToStaticMarkup(<EmployeesView rows={[{
|
||||
id: "worker000000001", name: "Test worker", employeeNo: "01", workerType: "casual",
|
||||
position: "Labourer", ratePerHour: 40, projectCode: "ONE", siteId: "site00000000001",
|
||||
position: "Labourer", projectCode: "ONE", siteId: "site00000000001",
|
||||
employerId: "broker000000001", employerName: "Labour broker",
|
||||
}]} showSiteColumn={false} positions={[]} employers={[{ id: "broker000000001", name: "Labour broker", site: "site00000000001" }]} />);
|
||||
expect(html).toContain("Labour broker");
|
||||
|
|
@ -20,4 +20,6 @@ it("keeps worker assignments read-only until the edit sheet is opened", () => {
|
|||
const roster = html.slice(html.indexOf("<tbody"), html.indexOf("</tbody>"));
|
||||
expect(roster).not.toContain("<select");
|
||||
expect(html).not.toContain("Save changes");
|
||||
// The hourly rate lives on the worker detail page only — never in the roster.
|
||||
expect(html).not.toContain("Rate / hr");
|
||||
});
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ import {
|
|||
SelectValue,
|
||||
} from "@/components/ui/select";
|
||||
import { Pagination } from "@/components/ui/pagination";
|
||||
import { formatCurrency } from "@/lib/utils";
|
||||
import { DropdownMenu, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from "@/components/ui/dropdown-menu";
|
||||
import { AddWorkerDialog } from "@/components/add-worker-dialog";
|
||||
import { WorkerQrBatchDialog } from "@/components/worker-qr-batch-dialog";
|
||||
|
|
@ -47,7 +46,6 @@ export interface EmployeeRow {
|
|||
weekActivity?: ActivityDay[];
|
||||
position: string;
|
||||
workerType: "permanent" | "casual";
|
||||
ratePerHour: number;
|
||||
projectCode: string;
|
||||
}
|
||||
|
||||
|
|
@ -214,7 +212,6 @@ export function EmployeesView({
|
|||
<TableHead>Position / type</TableHead>
|
||||
{showSiteColumn && <TableHead>Project</TableHead>}
|
||||
<TableHead>Employer/Broker</TableHead>
|
||||
<TableHead className="text-right">Rate / hr</TableHead>
|
||||
<TableHead className="w-10 px-1"><span className="sr-only">Worker actions</span></TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
|
|
@ -266,9 +263,6 @@ export function EmployeesView({
|
|||
</TableCell>
|
||||
)}
|
||||
<TableCell className="text-sm">{r.employerName || "Unassigned"}</TableCell>
|
||||
<TableCell className="text-right tabular-nums">
|
||||
{formatCurrency(r.ratePerHour)}
|
||||
</TableCell>
|
||||
<TableCell className="w-10 px-1 text-right" onClick={event => event.stopPropagation()}>
|
||||
<WorkerActions iconOnly worker={{ ...r, siteId: r.siteId ?? "" }} employers={employers}
|
||||
history={assignments.filter(a => a.employee === r.id && a.site === r.siteId)} />
|
||||
|
|
@ -348,7 +342,6 @@ function exportCsv(rows: EmployeeRow[]) {
|
|||
"worker_type",
|
||||
"position",
|
||||
"project_code",
|
||||
"rate_per_hour",
|
||||
"employer_broker",
|
||||
];
|
||||
const lines = [headers.join(",")];
|
||||
|
|
@ -360,7 +353,6 @@ function exportCsv(rows: EmployeeRow[]) {
|
|||
r.workerType,
|
||||
csvCell(r.position),
|
||||
csvCell(r.projectCode),
|
||||
r.ratePerHour.toFixed(2),
|
||||
csvCell(r.employerName || "Unassigned"),
|
||||
].join(","),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -67,7 +67,6 @@ export default async function EmployeesPage({
|
|||
duplicateBadge: (badgeCounts.get(String(e.employee_no||"").trim().toUpperCase())||0)>1,
|
||||
position: e.position,
|
||||
workerType: e.worker_type,
|
||||
ratePerHour: e.rate_per_hour || 0,
|
||||
projectCode: e.expand?.site?.project_code ?? siteById.get(e.site)?.project_code ?? "",
|
||||
}));
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue