feat: update inventory columns to match legacy portal and grant admins all companies
Inventory summary table now shows Plant, Cust Part#, Vorteq Part#, Vorteq Desc, Warehouse, Qty LB, Rows with a blue View button for drill-down. Admins see all active companies in the company selector. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
cf9af94f7d
commit
87c1cdf8da
3 changed files with 45 additions and 24 deletions
|
|
@ -12,7 +12,7 @@ import {
|
|||
} from '@/components/ui/table';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Input } from '@/components/ui/input';
|
||||
import { Search, Download } from 'lucide-react';
|
||||
import { Search, Download, Eye } from 'lucide-react';
|
||||
import { InventorySummaryRow } from '@/services/inventory';
|
||||
|
||||
type InventorySummaryTableProps = {
|
||||
|
|
@ -30,31 +30,34 @@ export function InventorySummaryTable({
|
|||
(row) =>
|
||||
row.part_num.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
row.description?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
row.plant?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
row.plant?.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
||||
row.cust_part_num?.toLowerCase().includes(searchTerm.toLowerCase())
|
||||
);
|
||||
|
||||
const handleExportCSV = () => {
|
||||
// Create CSV content
|
||||
const headers = [
|
||||
'Part Number',
|
||||
'Description',
|
||||
'Plant',
|
||||
'Cust Part#',
|
||||
'Vorteq Part#',
|
||||
'Vorteq Desc',
|
||||
'Warehouse',
|
||||
'On Hand Qty',
|
||||
'Qty LB',
|
||||
'Rows',
|
||||
];
|
||||
const rows = filteredData.map((row) => [
|
||||
row.plant,
|
||||
row.cust_part_num || '',
|
||||
row.part_num,
|
||||
row.description || '',
|
||||
row.plant,
|
||||
row.warehouse,
|
||||
row.on_hand_qty,
|
||||
row.rows,
|
||||
]);
|
||||
|
||||
const csvContent = [headers, ...rows]
|
||||
.map((row) => row.join(','))
|
||||
.map((row) => row.map((cell) => `"${cell}"`).join(','))
|
||||
.join('\n');
|
||||
|
||||
// Download CSV
|
||||
const blob = new Blob([csvContent], { type: 'text/csv' });
|
||||
const url = window.URL.createObjectURL(blob);
|
||||
const a = document.createElement('a');
|
||||
|
|
@ -95,32 +98,39 @@ export function InventorySummaryTable({
|
|||
<Table>
|
||||
<TableHeader>
|
||||
<TableRow>
|
||||
<TableHead>Part Number</TableHead>
|
||||
<TableHead>Description</TableHead>
|
||||
<TableHead>Plant</TableHead>
|
||||
<TableHead>Cust Part#</TableHead>
|
||||
<TableHead>Vorteq Part#</TableHead>
|
||||
<TableHead>Vorteq Desc</TableHead>
|
||||
<TableHead>Warehouse</TableHead>
|
||||
<TableHead className="text-right">On Hand Qty</TableHead>
|
||||
<TableHead className="text-right">Qty LB</TableHead>
|
||||
<TableHead className="text-right">Rows</TableHead>
|
||||
<TableHead className="w-[70px]"></TableHead>
|
||||
</TableRow>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{filteredData.map((row, idx) => (
|
||||
<TableRow key={idx}>
|
||||
<TableCell>
|
||||
<Link
|
||||
href={`/inventory/${category}/detail?part=${encodeURIComponent(row.part_num)}&plant=${encodeURIComponent(row.plant_key || row.plant)}&warehouse=${encodeURIComponent(row.warehouse)}`}
|
||||
className="font-medium hover:underline"
|
||||
>
|
||||
{row.part_num}
|
||||
</Link>
|
||||
</TableCell>
|
||||
<TableCell className="max-w-xs truncate">
|
||||
{row.description || 'N/A'}
|
||||
</TableCell>
|
||||
<TableCell>{row.plant}</TableCell>
|
||||
<TableCell>{row.cust_part_num || '-'}</TableCell>
|
||||
<TableCell className="font-medium">{row.part_num}</TableCell>
|
||||
<TableCell className="max-w-xs truncate">
|
||||
{row.description || '-'}
|
||||
</TableCell>
|
||||
<TableCell>{row.warehouse}</TableCell>
|
||||
<TableCell className="text-right">
|
||||
{Number(row.on_hand_qty).toLocaleString()}
|
||||
</TableCell>
|
||||
<TableCell className="text-right">{row.rows}</TableCell>
|
||||
<TableCell>
|
||||
<Link
|
||||
href={`/inventory/${category}/detail?part=${encodeURIComponent(row.part_num)}&plant=${encodeURIComponent(row.plant_key || row.plant)}&warehouse=${encodeURIComponent(row.warehouse)}`}
|
||||
>
|
||||
<Button variant="ghost" size="icon" className="h-8 w-8 text-blue-600 hover:text-blue-800">
|
||||
<Eye className="h-4 w-4" />
|
||||
</Button>
|
||||
</Link>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
))}
|
||||
</TableBody>
|
||||
|
|
|
|||
|
|
@ -247,7 +247,8 @@ export async function getActiveCompany() {
|
|||
}
|
||||
|
||||
/**
|
||||
* Get all companies accessible by the current user
|
||||
* Get all companies accessible by the current user.
|
||||
* Admins and Super Admins can access all active companies.
|
||||
*/
|
||||
export async function getUserCompanies() {
|
||||
const session = await getQuestSession();
|
||||
|
|
@ -256,6 +257,14 @@ export async function getUserCompanies() {
|
|||
return [];
|
||||
}
|
||||
|
||||
// Admins see all active companies
|
||||
if (session.userType === 'Admin' || session.userType === 'Super Admin') {
|
||||
return await db.quest_company.findMany({
|
||||
where: { is_active: true },
|
||||
orderBy: { display_name: 'asc' },
|
||||
});
|
||||
}
|
||||
|
||||
const questUser = await db.quest_user.findUnique({
|
||||
where: { id: session.questUserId },
|
||||
include: {
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ export type InventorySummaryRow = {
|
|||
plant_key: string;
|
||||
warehouse: string;
|
||||
on_hand_qty: number;
|
||||
rows: number;
|
||||
paint_code?: string;
|
||||
cust_part_num?: string;
|
||||
};
|
||||
|
|
@ -50,6 +51,7 @@ function mapSummaryRow(raw: Record<string, unknown>): InventorySummaryRow {
|
|||
plant_key: String(raw.PlantKey ?? ''),
|
||||
warehouse: String(raw.Warehouse ?? ''),
|
||||
on_hand_qty: Number(raw.OnHandQty ?? 0),
|
||||
rows: Number(raw.Rows ?? 0),
|
||||
paint_code: raw.PaintCode ? String(raw.PaintCode) : undefined,
|
||||
cust_part_num: raw.CustPartNum ? String(raw.CustPartNum) : undefined,
|
||||
};
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue