price adjustment and stock adjustments

This commit is contained in:
2026-10-12 14:08:23 +05:30
committed by ImanThiyanga
parent a788349138
commit d0354ed169
166 changed files with 98818 additions and 252 deletions
@@ -25,7 +25,10 @@ import {
HelpCircle,
IdCard,
Inbox,
ClipboardCheck,
Landmark,
PiggyBank,
Tag,
LayoutGrid,
LayoutList,
LayoutTemplate,
@@ -38,7 +41,6 @@ import {
PackageCheck,
PackageSearch,
PackageX,
Percent,
PlayCircle,
PieChart,
Receipt,
@@ -50,6 +52,7 @@ import {
ShieldCheck,
ShoppingCart,
SlidersHorizontal,
Tags,
Truck,
Undo2,
Users,
@@ -59,6 +62,7 @@ import {
type LucideIcon,
} from "lucide-react"
import { approvalsApi } from "@/lib/api/approvals"
import { cn } from "@/lib/utils"
import { useAuth } from "@/components/auth/AuthProvider"
import { useTrackingSettings } from "@/hooks/use-tracking-settings"
@@ -102,9 +106,11 @@ const navItems: {
icon: ListTree,
altCodes: ["products.brand", "products.uom"],
},
{ title: "Tax Rates", code: "products.tax-rates", href: "/dashboard/products/tax-rates", icon: Percent },
{ title: "Price Adjustments", code: "products.price-adjustments", href: "/dashboard/products/price-adjustments", icon: Tag },
],
},
// Open to everyone signed in: the inbox only lists what the user may approve and their own requests.
{ title: "Approvals", code: "approvals", href: "/dashboard/approvals", icon: ClipboardCheck },
{
title: "Procurement",
code: "procurement",
@@ -135,7 +141,8 @@ const navItems: {
{ title: "Customers", code: "sales.invoices", href: "/dashboard/customers", icon: Users },
{ title: "Bundle Templates", code: "sales.bundle-templates", href: "/dashboard/sales/bundles/templates", icon: LayoutList },
{ title: "Free Issues", code: "sales.free-issues", href: "/dashboard/sales/free-issues", icon: PackageX },
{ title: "Day End", code: "sales.day-end", href: "/dashboard/sales/day-end", icon: Lock },
{ title: "Approved Invoices", code: "sales.day-end", href: "/dashboard/sales/day-end", icon: Lock },
{ title: "Day-End Report", code: "sales.day-end-report", href: "/dashboard/sales/day-end-report", icon: LineChart },
// { title: "Reports", code: "sales.reports", href: "/dashboard/sales/reports", icon: FileBarChart },
],
},
@@ -215,6 +222,9 @@ const navItems: {
{ title: "Cash / Bank Accounts", code: "accounts.bank-accounts", href: "/dashboard/accounts/bank-accounts", icon: Wallet },
{ title: "Cheque Books", code: "accounts.cheque-books", href: "/dashboard/accounts/cheque-books", icon: BookText },
{ title: "Received Cheques", code: "accounts.received-cheques", href: "/dashboard/accounts/received-cheques", icon: Inbox },
{ title: "Expenses", code: "accounts.expenses", href: "/dashboard/accounts/expenses", icon: ReceiptText },
{ title: "Expense Setup", code: "accounts.expense-setup", href: "/dashboard/accounts/expense-setup", icon: Tags },
{ title: "Bank Deposits", code: "accounts.bank-deposits", href: "/dashboard/accounts/bank-deposits", icon: PiggyBank },
],
},
{
@@ -226,6 +236,7 @@ const navItems: {
{ title: "Branches", code: "settings.branches", href: "/dashboard/settings/branches", icon: MapPin },
{ title: "Roles", code: "settings.roles", href: "/dashboard/settings/roles", icon: ShieldCheck },
{ title: "Users", code: "settings.users", href: "/dashboard/settings/users", icon: Users },
{ title: "Approvals", code: "settings.approvals", href: "/dashboard/settings/approvals", icon: ClipboardCheck },
{ title: "Configuration", code: "products.configuration", href: "/dashboard/settings/configuration", icon: SlidersHorizontal },
],
},
@@ -239,6 +250,7 @@ function SidebarContent({
onClose,
pathname,
isMobile,
approvalCount,
}: {
items: typeof navItems
collapsed: boolean
@@ -246,6 +258,8 @@ function SidebarContent({
onClose?: () => void
pathname: string
isMobile: boolean
/** Requests the user can approve — the badge on Approvals. */
approvalCount: number
}) {
const iconOnly = !isMobile && collapsed
@@ -367,6 +381,11 @@ function SidebarContent({
className={cn("size-3.5 shrink-0", isActive ? "text-primary" : "text-muted-foreground")}
/>
{!iconOnly && <span className="flex-1">{item.title}</span>}
{item.code === "approvals" && approvalCount > 0 && (
<span className="ml-auto rounded-full bg-primary px-1.5 text-[10px] font-semibold leading-4 text-primary-foreground tabular-nums">
{approvalCount}
</span>
)}
</Link>
)}
</div>
@@ -449,7 +468,16 @@ export function AppSidebar() {
// seed grants it. This is also flagged in 02-SECURITY.md as the AR-09 sidebar-visibility
// stopgap for HRM's salary/PII data — it hides HRM from the UI but doesn't enforce
// anything server-side.
const bypassCodes = new Set(["procurement", "sales", "sales-returns", "hrm", "production", "stock"])
// "approvals" is not a permission at all — the inbox is for everyone (see its nav entry).
const bypassCodes = new Set(["procurement", "sales", "sales-returns", "hrm", "production", "stock", "approvals"])
// Requests waiting for this user — the Approvals badge. Refreshed on navigation, which is when
// someone has most likely just approved or submitted something.
const [approvalCount, setApprovalCount] = useState(0)
useEffect(() => {
if (loading) return
approvalsApi.pending().then((p) => setApprovalCount(p.actionableCount)).catch(() => setApprovalCount(0))
}, [loading, pathname])
const visibleItems = loading
? []
: navItems
@@ -489,6 +517,7 @@ export function AppSidebar() {
onCollapse={() => setCollapsed((v) => !v)}
pathname={pathname}
isMobile={false}
approvalCount={approvalCount}
/>
</div>
@@ -525,6 +554,7 @@ export function AppSidebar() {
onClose={() => setMobileOpen(false)}
pathname={pathname}
isMobile={true}
approvalCount={approvalCount}
/>
</div>
</>
@@ -72,6 +72,9 @@ const ACCOUNTS_TITLES: Record<string, string> = {
"/dashboard/accounts/cheque-books/new": "New Cheque Book",
"/dashboard/accounts/received-cheques": "Received Cheques",
"/dashboard/accounts/received-cheques/new": "New Received Cheque",
"/dashboard/accounts/expenses": "Expenses",
"/dashboard/accounts/expenses/new": "New Expense",
"/dashboard/accounts/expense-setup": "Expense Setup",
}
const STOCK_TITLES: Record<string, string> = {
@@ -104,6 +107,7 @@ function titleFromPath(pathname: string) {
if (pathname === "/dashboard/sales/invoices") return "Sales"
if (pathname === "/dashboard/sales/invoices/new") return "New Sale"
if (pathname === "/dashboard/sales/warranties") return "Warranties"
if (pathname === "/dashboard/sales/day-end-report") return "Day-End Report"
if (pathname === "/dashboard/receiving/grn") return "Goods Receipt Notes"
if (pathname === "/dashboard/receiving/grn/new") return "Create Goods Receipt Note"
@@ -113,6 +117,8 @@ function titleFromPath(pathname: string) {
if (ACCOUNTS_TITLES[pathname]) return ACCOUNTS_TITLES[pathname]
if (/^\/dashboard\/accounts\/cheque-books\/[^/]+$/.test(pathname)) return "Cheque Book"
if (/^\/dashboard\/accounts\/expenses\/[^/]+\/edit$/.test(pathname)) return "Edit Expense"
if (/^\/dashboard\/accounts\/expenses\/[^/]+$/.test(pathname)) return "Expense"
if (STOCK_TITLES[pathname]) return STOCK_TITLES[pathname]
if (/^\/dashboard\/stock\/transfers\/[^/]+$/.test(pathname)) return "Stock Transfer"