perfoma invoice
This commit is contained in:
@@ -1,3 +1,4 @@
|
|||||||
VITE_API_BASE_URL = 'http://10.86.60.88:4000'
|
VITE_API_BASE_URL = 'https://negareh-api.dev.danakcorp.com'
|
||||||
|
# VITE_API_BASE_URL = 'http://10.86.60.88:4000'
|
||||||
VITE_TOKEN_NAME = 'negareh_at'
|
VITE_TOKEN_NAME = 'negareh_at'
|
||||||
VITE_REFRESH_TOKEN_NAME = 'negareh_art'
|
VITE_REFRESH_TOKEN_NAME = 'negareh_art'
|
||||||
|
|||||||
@@ -1,30 +1,95 @@
|
|||||||
import Tabs from '@/components/Tabs'
|
import Tabs from '@/components/Tabs'
|
||||||
import { useState, type FC } from 'react'
|
import { useMemo, useState, type FC } from 'react'
|
||||||
import { ProformaInvoiceStatusEnum } from './enum/InvoiceEnum'
|
import { ProformaInvoiceStatusEnum } from './enum/InvoiceEnum'
|
||||||
import Filters from '@/components/Filters'
|
import Filters from '@/components/Filters'
|
||||||
import Table from '@/components/Table'
|
import Table from '@/components/Table'
|
||||||
import { Eye } from 'iconsax-react'
|
import { Eye } from 'iconsax-react'
|
||||||
import { Link } from 'react-router-dom'
|
import { Link } from 'react-router-dom'
|
||||||
import { Paths } from '@/config/Paths'
|
import { Paths } from '@/config/Paths'
|
||||||
|
import { useGetOrdersInvoiced } from '../order/hooks/useOrderData'
|
||||||
|
import moment from 'moment-jalaali'
|
||||||
|
import type { OrderType } from '../order/types/Types'
|
||||||
|
import type { FilterValues } from '@/components/Filters'
|
||||||
|
import { OrderStatusEnum } from '../order/enum/OrderEnum'
|
||||||
|
|
||||||
|
const isInvoiceConfirmed = (status: OrderStatusEnum) =>
|
||||||
|
status !== OrderStatusEnum.WAITING_to_CONFIRM_INVOICE &&
|
||||||
|
status !== OrderStatusEnum.CREATED &&
|
||||||
|
status !== OrderStatusEnum.CANCELED
|
||||||
|
|
||||||
const ProformaInvoice: FC = () => {
|
const ProformaInvoice: FC = () => {
|
||||||
|
const [activeTab, setActiveTab] = useState<ProformaInvoiceStatusEnum>(ProformaInvoiceStatusEnum.ALL)
|
||||||
|
const [page, setPage] = useState(1)
|
||||||
|
const [filters, setFilters] = useState<FilterValues>({})
|
||||||
|
|
||||||
const [activeTab, setactiveTab] = useState<ProformaInvoiceStatusEnum>(ProformaInvoiceStatusEnum.ALL)
|
const { data, isLoading } = useGetOrdersInvoiced(page)
|
||||||
|
|
||||||
|
const meta = data?.meta
|
||||||
|
|
||||||
|
const filteredData = useMemo(() => {
|
||||||
|
const list = data?.data ?? []
|
||||||
|
|
||||||
|
if (activeTab === ProformaInvoiceStatusEnum.CONFIRMED) {
|
||||||
|
return list.filter((o) => isInvoiceConfirmed(o.status))
|
||||||
|
}
|
||||||
|
if (activeTab === ProformaInvoiceStatusEnum.NOT_CONFIRMED) {
|
||||||
|
return list.filter((o) => o.status === OrderStatusEnum.WAITING_to_CONFIRM_INVOICE)
|
||||||
|
}
|
||||||
|
|
||||||
|
let result = list
|
||||||
|
|
||||||
|
const search = (filters.search ?? '').trim()
|
||||||
|
if (search) {
|
||||||
|
const lower = search.toLowerCase()
|
||||||
|
result = result.filter(
|
||||||
|
(o) =>
|
||||||
|
String(o.orderNumber).includes(search) ||
|
||||||
|
o.user?.firstName?.toLowerCase().includes(lower) ||
|
||||||
|
o.user?.lastName?.toLowerCase().includes(lower) ||
|
||||||
|
o.user?.phone?.includes(search)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dateFilter = filters.date
|
||||||
|
if (dateFilter) {
|
||||||
|
const filterDate = moment(dateFilter, 'jYYYY/jMM/jDD').format('YYYY-MM-DD')
|
||||||
|
result = result.filter((o) => {
|
||||||
|
const d = o.invoicedAt || o.createdAt
|
||||||
|
return d && moment(d).format('YYYY-MM-DD') === filterDate
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return result
|
||||||
|
}, [data?.data, activeTab, filters.search, filters.date])
|
||||||
|
|
||||||
|
const getPaymentStatus = (item: OrderType) => {
|
||||||
|
const total = Number(item.total) || 0
|
||||||
|
const paid = Number(item.paidAmount) || 0
|
||||||
|
if (total <= 0) return '-'
|
||||||
|
if (paid >= total) return 'پرداخت شده'
|
||||||
|
if (paid > 0) return 'پرداخت جزئی'
|
||||||
|
return 'پرداخت نشده'
|
||||||
|
}
|
||||||
|
|
||||||
|
const getServiceLabel = (item: OrderType) => {
|
||||||
|
if (!item.items?.length) return '-'
|
||||||
|
if (item.items.length === 1) return item.items[0].product?.title ?? '-'
|
||||||
|
return `${item.items.length} خدمت`
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className='mt-5'>
|
<div className='mt-5'>
|
||||||
<h1>
|
<h1 className='text-lg font-light'>پیش فاکتورها</h1>
|
||||||
پیش فاکتورها
|
|
||||||
</h1>
|
|
||||||
<div className='mt-8'>
|
<div className='mt-8'>
|
||||||
<Tabs
|
<Tabs
|
||||||
items={[
|
items={[
|
||||||
{ label: 'همه', value: 'all' },
|
{ label: 'همه', value: ProformaInvoiceStatusEnum.ALL },
|
||||||
{ label: 'تایید نشده', value: 'not_confirmed' },
|
{ label: 'تایید نشده', value: ProformaInvoiceStatusEnum.NOT_CONFIRMED },
|
||||||
{ label: 'تایید شده', value: 'confirmed' },
|
{ label: 'تایید شده', value: ProformaInvoiceStatusEnum.CONFIRMED },
|
||||||
]}
|
]}
|
||||||
activeTab={activeTab}
|
activeTab={activeTab}
|
||||||
onTabChange={(tab) => setactiveTab(tab as ProformaInvoiceStatusEnum)}
|
onTabChange={(tab) => setActiveTab(tab as ProformaInvoiceStatusEnum)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -34,7 +99,7 @@ const ProformaInvoice: FC = () => {
|
|||||||
{
|
{
|
||||||
type: 'input',
|
type: 'input',
|
||||||
name: 'search',
|
name: 'search',
|
||||||
placeholder: 'جستجو',
|
placeholder: 'جستجو (شماره سفارش / مشتری)',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
type: 'date',
|
type: 'date',
|
||||||
@@ -42,7 +107,7 @@ const ProformaInvoice: FC = () => {
|
|||||||
placeholder: 'تاریخ',
|
placeholder: 'تاریخ',
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
onChange={() => { }}
|
onChange={setFilters}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -50,65 +115,79 @@ const ProformaInvoice: FC = () => {
|
|||||||
<Table
|
<Table
|
||||||
columns={[
|
columns={[
|
||||||
{
|
{
|
||||||
key: 'id',
|
key: 'orderNumber',
|
||||||
title: 'شماره',
|
title: 'شماره',
|
||||||
|
render: (item) => item.orderNumber,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'service',
|
key: 'service',
|
||||||
title: 'خدمت',
|
title: 'خدمت',
|
||||||
|
render: (item) => getServiceLabel(item),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'issueDate',
|
key: 'issueDate',
|
||||||
title: 'تاریخ صدور',
|
title: 'تاریخ صدور',
|
||||||
|
render: (item) =>
|
||||||
|
item.invoicedAt
|
||||||
|
? moment(item.invoicedAt).format('jYYYY/jMM/jDD')
|
||||||
|
: moment(item.createdAt).format('jYYYY/jMM/jDD'),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'lastConfirmDate',
|
key: 'lastConfirmDate',
|
||||||
title: 'آخرین مهلت تایید',
|
title: 'آخرین مهلت تایید',
|
||||||
|
render: () => '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'total',
|
key: 'total',
|
||||||
title: 'مجموع',
|
title: 'مجموع',
|
||||||
|
render: (item) =>
|
||||||
|
item.total
|
||||||
|
? Number(item.total).toLocaleString('fa-IR') + ' ریال'
|
||||||
|
: '-',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'confirmStatus',
|
key: 'confirmStatus',
|
||||||
title: 'وضعیت تایید',
|
title: 'وضعیت تایید',
|
||||||
|
render: (item) => {
|
||||||
|
const confirmed = isInvoiceConfirmed(item.status)
|
||||||
|
return (
|
||||||
|
<span
|
||||||
|
className={`inline-flex h-6 items-center rounded-full px-2.5 text-xs ${
|
||||||
|
confirmed ? 'bg-green-100 text-green-800' : 'bg-amber-100 text-amber-800'
|
||||||
|
}`}
|
||||||
|
>
|
||||||
|
{confirmed ? 'تایید شده' : 'تایید نشده'}
|
||||||
|
</span>
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'paymentStatus',
|
key: 'paymentStatus',
|
||||||
title: 'وضعیت پرداخت',
|
title: 'وضعیت پرداخت',
|
||||||
|
render: (item) => getPaymentStatus(item),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'actions',
|
key: 'actions',
|
||||||
title: '',
|
title: '',
|
||||||
render: () => {
|
render: (item) => (
|
||||||
return (
|
<Link to={Paths.perfomaInvoice.detail + item.id}>
|
||||||
<Link to={Paths.perfomaInvoice.detail + '1'}>
|
|
||||||
<Eye size={20} color='#8C90A3' />
|
<Eye size={20} color='#8C90A3' />
|
||||||
</Link>
|
</Link>
|
||||||
)
|
),
|
||||||
}
|
|
||||||
}
|
|
||||||
]}
|
|
||||||
data={[
|
|
||||||
{
|
|
||||||
id: 1,
|
|
||||||
service: 'خدمت 1',
|
|
||||||
issueDate: '2021-01-01',
|
|
||||||
lastConfirmDate: '2021-01-01',
|
|
||||||
total: 100000,
|
|
||||||
confirmStatus: 'تایید شده',
|
|
||||||
paymentStatus: 'پرداخت شده',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
id: 2,
|
|
||||||
service: 'خدمت 2',
|
|
||||||
issueDate: '2021-01-01',
|
|
||||||
lastConfirmDate: '2021-01-01',
|
|
||||||
total: 100000,
|
|
||||||
confirmStatus: 'تایید شده',
|
|
||||||
paymentStatus: 'پرداخت شده',
|
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
|
data={filteredData}
|
||||||
|
isLoading={isLoading}
|
||||||
|
noDataMessage='پیش فاکتوری یافت نشد.'
|
||||||
|
pagination={
|
||||||
|
meta && meta.totalPages > 1
|
||||||
|
? {
|
||||||
|
currentPage: meta.page,
|
||||||
|
totalPages: meta.totalPages,
|
||||||
|
onPageChange: setPage,
|
||||||
|
}
|
||||||
|
: undefined
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,6 +9,13 @@ export const useGetOrders = () => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const useGetOrdersInvoiced = (page: number = 1) => {
|
||||||
|
return useQuery({
|
||||||
|
queryKey: ["orders-invoiced", page],
|
||||||
|
queryFn: () => api.getOrdersInvoiced(page),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const useGetRequests = () => {
|
export const useGetRequests = () => {
|
||||||
return useQuery({
|
return useQuery({
|
||||||
queryKey: ["requests"],
|
queryKey: ["requests"],
|
||||||
|
|||||||
@@ -17,6 +17,13 @@ export const getOrders = async () => {
|
|||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getOrdersInvoiced = async (page: number = 1) => {
|
||||||
|
const { data } = await axios.get<OrderResponseType>(
|
||||||
|
`/admin/orders/invoiced?page=${page}`,
|
||||||
|
);
|
||||||
|
return data;
|
||||||
|
};
|
||||||
|
|
||||||
export const getRequests = async () => {
|
export const getRequests = async () => {
|
||||||
const { data } = await axios.get<OrderResponseType>(`/admin/orders/request`);
|
const { data } = await axios.get<OrderResponseType>(`/admin/orders/request`);
|
||||||
return data;
|
return data;
|
||||||
@@ -24,14 +31,14 @@ export const getRequests = async () => {
|
|||||||
|
|
||||||
export const getOrderDetail = async (id: string) => {
|
export const getOrderDetail = async (id: string) => {
|
||||||
const { data } = await axios.get<OrderDetailResponseType>(
|
const { data } = await axios.get<OrderDetailResponseType>(
|
||||||
`/admin/orders/${id}`
|
`/admin/orders/${id}`,
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getTickets = async (orderId: string) => {
|
export const getTickets = async (orderId: string) => {
|
||||||
const { data } = await axios.get<TicketsResponseType>(
|
const { data } = await axios.get<TicketsResponseType>(
|
||||||
`/admin/ticket/order/${orderId}`
|
`/admin/ticket/order/${orderId}`,
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
@@ -39,7 +46,7 @@ export const getTickets = async (orderId: string) => {
|
|||||||
export const addTicket = async (ticketId: string, params: AddTicketType) => {
|
export const addTicket = async (ticketId: string, params: AddTicketType) => {
|
||||||
const { data } = await axios.post(
|
const { data } = await axios.post(
|
||||||
`/admin/ticket/order/item/${ticketId}`,
|
`/admin/ticket/order/item/${ticketId}`,
|
||||||
params
|
params,
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
@@ -51,7 +58,7 @@ export const submitOrder = async (params: CreateFinalOrderType) => {
|
|||||||
|
|
||||||
export const updateOrder = async (
|
export const updateOrder = async (
|
||||||
orderId: string,
|
orderId: string,
|
||||||
params: CreateFinalOrderType
|
params: CreateFinalOrderType,
|
||||||
) => {
|
) => {
|
||||||
const { data } = await axios.patch(`/admin/orders/${orderId}`, params);
|
const { data } = await axios.patch(`/admin/orders/${orderId}`, params);
|
||||||
return data;
|
return data;
|
||||||
@@ -64,14 +71,14 @@ export const getProducts = async () => {
|
|||||||
|
|
||||||
export const getAttributes = async (productId?: number) => {
|
export const getAttributes = async (productId?: number) => {
|
||||||
const { data } = await axios.get<FieldResponseType>(
|
const { data } = await axios.get<FieldResponseType>(
|
||||||
`/admin/entity/${productId}/field`
|
`/admin/entity/${productId}/field`,
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getOrderItem = async (itemId?: number) => {
|
export const getOrderItem = async (itemId?: number) => {
|
||||||
const { data } = await axios.get<OrderItemResponseType>(
|
const { data } = await axios.get<OrderItemResponseType>(
|
||||||
`/admin/orders/item/${itemId}`
|
`/admin/orders/item/${itemId}`,
|
||||||
);
|
);
|
||||||
return data;
|
return data;
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user