Files
Kalana B. Thilakarathna 03d01d4c4e name: CI/CD - ERP Core Monorepo
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"
2026-09-17 13:59:05 +05:30

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' },
]