03d01d4c4e
on:
pull_request:
branches:
- production
types:
- closed
jobs:
backend-build-and-deploy:
name: Build & Deploy ERP Core Backend
runs-on: linux
if: github.event.pull_request.merged == true
steps:
- name: Checkout code
run: |
git clone \
--depth 1 \
--branch production \
https://oauth2:${{ secrets.ERPCORE }}@gitea.hexdive.com/New_REP_SYSTEM/ERP-core.git \
.
- name: Restore backend
run: dotnet restore Backend/ERPCore.sln
- name: Publish backend
run: |
rm -rf /tmp/erpcore-deploy
mkdir -p /tmp/erpcore-deploy
dotnet publish Backend/ERPCore/ERPCore.csproj \
-c Release \
-r linux-x64 \
--self-contained true \
-o /tmp/erpcore-deploy
- name: Stop backend service
run: systemctl stop erpcore.service
- name: Copy backend to deploy folder
run: |
mkdir -p /home/erp/core/publish
rm -rf /home/erp/core/publish/*
cp -r /tmp/erpcore-deploy/* /home/erp/core/publish/
- name: Fix backend ownership and permissions
run: |
chown -R erpuser:erpuser /home/erp/core/publish
find /home/erp/core/publish -type d -exec chmod 755 {} +
find /home/erp/core/publish -type f -exec chmod 644 {} +
chmod +x /home/erp/core/publish/ERPCore
- name: Restart backend service
run: systemctl restart erpcore.service
- name: Verify backend
run: |
systemctl is-active erpcore.service && echo "Backend service running" || echo "Backend service failed"
frontend-build-and-deploy:
name: Build & Deploy ERP Core Frontend
runs-on: linux
needs: backend-build-and-deploy
if: github.event.pull_request.merged == true
steps:
- name: Checkout code
run: |
git clone \
--depth 1 \
--branch Production \
https://oauth2:${{ secrets.ERPCORE }}@gitea.hexdive.com/New_REP_SYSTEM/ERP-core.git \
.
- name: Build frontend Docker image
run: docker build -t erpcore-frontend:latest Frontend/erp-system
- name: Stop & remove existing frontend container
run: |
docker stop erpcore-frontend 2>/dev/null || true
docker rm erpcore-frontend 2>/dev/null || true
- name: Start frontend container
run: |
docker run -d \
--name erpcore-frontend \
-p 6702:6702 \
--add-host=host.docker.internal:host-gateway \
-e BACKEND_ORIGIN=http://host.docker.internal:6701 \
--restart unless-stopped \
--memory="512m" \
--cpus="1.0" \
--cap-drop ALL \
--security-opt no-new-privileges \
erpcore-frontend:latest
- name: Remove old frontend images
run: docker image prune -f
- name: Verify frontend
run: |
docker ps --filter name=erpcore-frontend --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}" \
| grep erpcore-frontend && echo "Frontend container running" || echo "Frontend container failed"
167 lines
8.0 KiB
TypeScript
167 lines
8.0 KiB
TypeScript
import type { IconSvgElement } from '@hugeicons/react'
|
|
import {
|
|
DashboardSquare01Icon,
|
|
Location01Icon,
|
|
Route01Icon,
|
|
Car01Icon,
|
|
Building02Icon,
|
|
Package01Icon,
|
|
CatalogueIcon,
|
|
BarCode01Icon,
|
|
Layers01Icon,
|
|
Discount01Icon,
|
|
DiscountTag01Icon,
|
|
UserGroupIcon,
|
|
Store01Icon,
|
|
UserShield01Icon,
|
|
ShieldUserIcon,
|
|
LicenseDraftIcon,
|
|
LicenseIcon,
|
|
ShoppingCart01Icon,
|
|
PackageReceiveIcon,
|
|
TruckIcon,
|
|
DeliveryBox01Icon,
|
|
DeliveryTruck01Icon,
|
|
DollarSquareIcon,
|
|
ClipboardListIcon,
|
|
BankIcon,
|
|
PackageMoving01Icon,
|
|
} from '@hugeicons/core-free-icons'
|
|
|
|
export interface NavItem {
|
|
title: string
|
|
href: string
|
|
icon: IconSvgElement
|
|
description?: string
|
|
permission?: string
|
|
}
|
|
|
|
export interface NavGroup {
|
|
title: string
|
|
icon: IconSvgElement
|
|
items: NavItem[]
|
|
}
|
|
|
|
// Standalone item rendered at top — not inside any collapsible group
|
|
export const DASHBOARD_ITEM: NavItem = {
|
|
title: 'Dashboard',
|
|
href: '/',
|
|
icon: DashboardSquare01Icon,
|
|
}
|
|
|
|
export const NAV_GROUPS: NavGroup[] = [
|
|
{
|
|
title: 'Operations',
|
|
icon: TruckIcon,
|
|
items: [
|
|
{ title: 'Rides', href: '/operations/rides', icon: TruckIcon, description: 'Delivery/Sales runs assigned to a driver and vehicle', permission: 'rides.view' },
|
|
{ title: 'Loading Sheets', href: '/operations/loading', icon: DeliveryBox01Icon, description: 'Track goods loaded onto a vehicle before dispatch', permission: 'loading.view' },
|
|
{ title: 'Delivery Tasks', href: '/operations/deliveries', icon: DeliveryTruck01Icon, description: 'Individual store drop-offs within a ride', permission: 'rides.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Shop POs & Invoices',
|
|
icon: DollarSquareIcon,
|
|
items: [
|
|
{ title: 'Shop POs', href: '/sales', icon: ClipboardListIcon, description: 'Purchase orders raised by sales agents on behalf of stores', permission: 'orders.view' },
|
|
{ title: 'Invoices', href: '/sales/orders', icon: DollarSquareIcon, description: 'Billing documents generated from confirmed Shop POs', permission: 'orders.view' },
|
|
{ title: 'Payments', href: '/sales/payments', icon: BankIcon, description: 'Cash and credit payments collected against invoices', permission: 'orders.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Stores',
|
|
icon: Store01Icon,
|
|
items: [
|
|
{ title: 'Stores', href: '/stores', icon: Store01Icon, description: 'Retail store accounts, credit limits, and KYC status', permission: 'stores.view' },
|
|
{ title: 'Sales Visits', href: '/sales-visits', icon: Location01Icon, description: 'Check in and out of scheduled store visits', permission: 'sales_visits.checkin' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Catalogue',
|
|
icon: CatalogueIcon,
|
|
items: [
|
|
{ title: 'Items', href: '/catalogue/items', icon: Package01Icon, description: 'Products available for sale and distribution', permission: 'items.view' },
|
|
{ title: 'Categories', href: '/catalogue/categories', icon: CatalogueIcon, description: 'Product groupings and sub-categories', permission: 'categories.view' },
|
|
{ title: 'Brands', href: '/catalogue/brands', icon: BarCode01Icon, description: 'Brands associated with catalogue items', permission: 'categories.view' },
|
|
// { title: 'UOMs', href: '/catalogue/uoms', icon: Layers01Icon, description: 'Units of measure and conversion factors between units', permission: 'categories.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Stock',
|
|
icon: PackageMoving01Icon,
|
|
items: [
|
|
{ title: 'Stock Balances', href: '/stock', icon: Package01Icon, description: 'Current quantity of each item across warehouses and vehicles', permission: 'warehouses.view' },
|
|
{ title: 'Stock Movements', href: '/stock/movements', icon: PackageMoving01Icon, description: 'Full history of stock in and out across all locations', permission: 'warehouses.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Procurement',
|
|
icon: ShoppingCart01Icon,
|
|
items: [
|
|
{ title: 'Purchase Orders', href: '/procurement/orders', icon: ShoppingCart01Icon, description: 'Orders placed with suppliers to restock inventory', permission: 'purchase_orders.view' },
|
|
{ title: 'Goods Receipt', href: '/procurement/grn', icon: PackageReceiveIcon, description: 'Record stock received into a warehouse against a purchase order', permission: 'purchase_orders.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Pricing',
|
|
icon: Discount01Icon,
|
|
items: [
|
|
{ title: 'Price Lists', href: '/pricing/price-lists', icon: Discount01Icon, description: 'Item prices scoped by region and active date range', permission: 'pricelists.view' },
|
|
{ title: 'Schemes', href: '/pricing/schemes', icon: DiscountTag01Icon, description: 'Promotions, bundle deals, and slab discounts applied at sale', permission: 'schemes.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Suppliers',
|
|
icon: UserGroupIcon,
|
|
items: [
|
|
{ title: 'Suppliers', href: '/suppliers', icon: UserGroupIcon, description: 'Supplier accounts used for raising purchase orders', permission: 'suppliers.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Returns & Claims',
|
|
icon: ClipboardListIcon,
|
|
items: [
|
|
{ title: 'Order Returns', href: '/returns-claims/order-returns', icon: ClipboardListIcon, description: 'Items a store returned during a sale visit', permission: 'orders.view' },
|
|
{ title: 'Agency Claims', href: '/returns-claims/claims', icon: ClipboardListIcon, description: 'Claims raised against a regional agency and their settlement', permission: 'orders.view' },
|
|
{ title: 'Supplier Claims', href: '/returns-claims/supplier-claims', icon: ClipboardListIcon, description: 'Claims raised against a supplier for damaged, short, or wrong stock', permission: 'purchase_orders.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Drivers',
|
|
icon: LicenseDraftIcon,
|
|
items: [
|
|
{ title: 'Driver Profiles', href: '/drivers', icon: LicenseDraftIcon, description: 'Driver records including license and medical clearance dates', permission: 'driver_profiles.view' },
|
|
{ title: 'Compliance', href: '/drivers/compliance', icon: LicenseIcon, description: 'Rules that enforce license and medical clearance before a ride starts', permission: 'compliance.manage' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Users & Access',
|
|
icon: UserShield01Icon,
|
|
items: [
|
|
{ title: 'Users', href: '/users', icon: UserShield01Icon, description: 'Staff accounts and their role assignments', permission: 'users.view' },
|
|
{ title: 'Roles', href: '/users/roles', icon: ShieldUserIcon, description: 'Permission sets that control what each role can see and do', permission: 'roles.view' },
|
|
],
|
|
},
|
|
{
|
|
title: 'Network',
|
|
icon: Building02Icon,
|
|
items: [
|
|
{ title: 'Regions', href: '/network/regions', icon: Location01Icon, description: 'Geographic territories the distribution network operates in', permission: 'regions.view' },
|
|
{ title: 'Region Manage', href: '/network/region-manage', icon: ClipboardListIcon, description: 'Targets, budgets, tax rules, and agency mapping per region', permission: 'regions.view' },
|
|
{ title: 'Routes', href: '/network/routes', icon: Route01Icon, description: 'Delivery paths within a region that rides are assigned to', permission: 'routes.view' },
|
|
{ title: 'Vehicles', href: '/network/vehicles', icon: Car01Icon, description: 'Fleet vehicles available for delivery rides', permission: 'vehicles.view' },
|
|
{ title: 'Warehouses', href: '/network/warehouses', icon: Building02Icon, description: 'Storage locations where stock is held and loaded from', permission: 'warehouses.view' },
|
|
],
|
|
},
|
|
]
|
|
|
|
// Ordered candidates for mobile bottom nav — first 5 visible are shown
|
|
export const BOTTOM_NAV_CANDIDATES: NavItem[] = [
|
|
{ title: 'Home', href: '/', icon: DashboardSquare01Icon },
|
|
{ title: 'Stores', href: '/stores', icon: Store01Icon, permission: 'stores.view' },
|
|
{ title: 'Rides', href: '/operations/rides', icon: TruckIcon, permission: 'rides.view' },
|
|
{ title: 'Loading', href: '/operations/loading', icon: DeliveryBox01Icon, permission: 'loading.view' },
|
|
{ title: 'Shop POs', href: '/sales', icon: ClipboardListIcon, permission: 'orders.view' },
|
|
{ title: 'Items', href: '/catalogue/items', icon: Package01Icon, permission: 'items.view' },
|
|
]
|