mirror of
https://gitlab.com/mbugroup/lti-web-client.git
synced 2026-05-20 13:32:00 +00:00
feat(FE-218,212,213): implement PurchaseOrderDetail component and update related types
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useRouter, useSearchParams } from 'next/navigation';
|
||||
import useSWR from 'swr';
|
||||
import PurchaseRequestForm from '@/components/pages/purchase/form/request/PurchaseRequestForm';
|
||||
import PurchaseOrderDetail from '@/components/pages/purchase/order/PurchaseOrderDetail';
|
||||
import { PurchaseRequestApi } from '@/services/api/purchase';
|
||||
import { isResponseSuccess, isResponseError } from '@/lib/api-helper';
|
||||
|
||||
@@ -33,12 +33,14 @@ const PurchaseDetail = () => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div className='w-full p-4 flex flex-row justify-center'>
|
||||
<div className='w-full p-4'>
|
||||
{isLoadingPurchase && (
|
||||
<span className='loading loading-spinner loading-xl' />
|
||||
<div className='w-full flex flex-row justify-center items-center'>
|
||||
<span className='loading loading-spinner loading-xl' />
|
||||
</div>
|
||||
)}
|
||||
{!isLoadingPurchase && isResponseSuccess(purchase) && (
|
||||
<PurchaseRequestForm type='detail' initialValues={purchase.data} />
|
||||
<PurchaseOrderDetail type='detail' data={purchase.data} />
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -206,15 +206,13 @@ const PurchaseOrderAcceptApprovalForm = ({
|
||||
if (initialValues?.items) {
|
||||
return initialValues.items.map((item) => ({
|
||||
value: item.id,
|
||||
label: `${item.product.name} (${item.quantity} ${item.product.uom.name})`,
|
||||
label: `${item.product.name} (${item.quantity} ${item.product.uom?.name || 'unit'})`,
|
||||
id: item.id,
|
||||
quantity: item.quantity,
|
||||
product: {
|
||||
name: item.product.name,
|
||||
product_category: item.product.product_category,
|
||||
uom: {
|
||||
name: item.product.uom.name,
|
||||
},
|
||||
uom: item.product.uom,
|
||||
},
|
||||
warehouse: {
|
||||
name: item.warehouse?.name || '',
|
||||
|
||||
@@ -44,7 +44,7 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
product: {
|
||||
name: string;
|
||||
type?: string;
|
||||
uom: {
|
||||
uom?: {
|
||||
name: string;
|
||||
};
|
||||
};
|
||||
@@ -170,15 +170,13 @@ const PurchaseOrderStaffApprovalForm = ({
|
||||
if (initialValues?.items) {
|
||||
return initialValues.items.map((item) => ({
|
||||
value: item.id,
|
||||
label: `${item.product.name} (${item.quantity} ${item.product.uom.name})`,
|
||||
label: `${item.product.name} (${item.quantity} ${item.product.uom?.name || 'unit'})`,
|
||||
id: item.id,
|
||||
quantity: item.quantity,
|
||||
product: {
|
||||
name: item.product.name,
|
||||
product_category: item.product.product_category,
|
||||
uom: {
|
||||
name: item.product.uom.name,
|
||||
},
|
||||
uom: item.product.uom,
|
||||
},
|
||||
warehouse: {
|
||||
name: item.warehouse?.name || '',
|
||||
|
||||
@@ -3,9 +3,7 @@
|
||||
import { useCallback, useMemo, useState } from 'react';
|
||||
import { ColumnDef, SortingState } from '@tanstack/react-table';
|
||||
|
||||
import ApprovalSteps, {
|
||||
formatGroupedApprovalsToApprovalSteps,
|
||||
} from '@/components/pages/ApprovalSteps';
|
||||
import ApprovalSteps from '@/components/pages/ApprovalSteps';
|
||||
import Table from '@/components/Table';
|
||||
import Button from '@/components/Button';
|
||||
import { Icon } from '@iconify/react';
|
||||
@@ -20,21 +18,13 @@ import PurchaseOrderStaffApprovalForm from '@/components/pages/purchase/form/ord
|
||||
import PurchaseOrderAcceptApprovalForm from '@/components/pages/purchase/form/order/PurchaseOrderAcceptApprovalForm';
|
||||
import PurchaseOrderInvoice from '@/components/pages/purchase/order/PurchaseOrderInvoice';
|
||||
|
||||
import { BaseGroupedApproval } from '@/types/api/api-general';
|
||||
import { PURCHASE_ORDER_APPROVAL_LINE } from '@/config/approval-line';
|
||||
import { ApprovalStepStatus } from '@/components/pages/ApprovalSteps';
|
||||
import Card from '@/components/Card';
|
||||
import {
|
||||
CreateManagerApprovalRequestPayload,
|
||||
Purchase,
|
||||
PurchaseItem,
|
||||
} from '@/types/api/purchase/purchase';
|
||||
import {
|
||||
createdUser,
|
||||
dummyAreas,
|
||||
dummyLocations,
|
||||
dummyProductWarehouses,
|
||||
dummyWarehouses,
|
||||
} from '@/dummy/marketing.dummy';
|
||||
import {
|
||||
ManagerApprovalApi,
|
||||
PurchaseDeleteItemsApi,
|
||||
@@ -81,321 +71,8 @@ interface PurchaseOrderDetailProps {
|
||||
data?: Purchase;
|
||||
}
|
||||
|
||||
const dummyPurchaseData: Purchase = {
|
||||
id: 1,
|
||||
pr_number: 'PR-MBU-01837',
|
||||
po_number: 'PO-MBU-01837',
|
||||
po_document_path: '/documents/po-mbu-01837.pdf',
|
||||
po_date: '2025-01-10T00:00:00Z',
|
||||
supplier: {
|
||||
id: 1,
|
||||
name: 'PT. CHAROEN POKPHAND JAYA FARM',
|
||||
alias: 'CP JAYA FARM',
|
||||
pic: 'Budi Santoso',
|
||||
type: 'Supplier',
|
||||
category: 'Feed',
|
||||
hatchery: 'Jawa Barat',
|
||||
phone: '+62-22-7563850',
|
||||
email: 'info@cp.co.id',
|
||||
address:
|
||||
'Jl. Raya Bandung - Sumedang Km. 28, Desa Cisantana, Kec. Cigendel, Kabupaten Sumedang, Jawa Barat 45363',
|
||||
npwp: '01.938.451.6-433.000',
|
||||
account_number: '123-456-7890',
|
||||
due_date: 30,
|
||||
balance: 0,
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
created_user: createdUser,
|
||||
},
|
||||
credit_term: 30,
|
||||
due_date: '2025-11-13T00:00:00Z',
|
||||
grand_total: 65000000,
|
||||
notes: null,
|
||||
area: dummyAreas[0],
|
||||
location: dummyLocations[0],
|
||||
items: [
|
||||
{
|
||||
id: 1,
|
||||
purchase_id: 1,
|
||||
product: {
|
||||
id: 1,
|
||||
name: 'CP Vaksin',
|
||||
brand: '',
|
||||
sku: '',
|
||||
product_price: 0,
|
||||
selling_price: 0,
|
||||
tax: 0,
|
||||
expiry_period: 0,
|
||||
uom: {
|
||||
id: 1,
|
||||
name: 'Ekor',
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
product_category: {
|
||||
id: 1,
|
||||
code: 'DOC',
|
||||
name: 'DOC',
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
suppliers: [],
|
||||
flags: [],
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
product_warehouse: dummyProductWarehouses[0],
|
||||
quantity: 10000,
|
||||
sub_qty: 10000,
|
||||
total_qty: 10000,
|
||||
total_used: 0,
|
||||
price: 6500,
|
||||
total_price: 65000000,
|
||||
received_date: null,
|
||||
travel_number: null,
|
||||
travel_number_docs: null,
|
||||
vehicle_number: null,
|
||||
warehouse: dummyWarehouses[0],
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
purchase_id: 2,
|
||||
product: {
|
||||
id: 1,
|
||||
name: 'CP Vaksin',
|
||||
brand: '',
|
||||
sku: '',
|
||||
product_price: 0,
|
||||
selling_price: 0,
|
||||
tax: 0,
|
||||
expiry_period: 0,
|
||||
uom: {
|
||||
id: 1,
|
||||
name: 'Ekor',
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
product_category: {
|
||||
id: 1,
|
||||
code: 'DOC',
|
||||
name: 'DOC',
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
suppliers: [],
|
||||
flags: [],
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
product_warehouse: dummyProductWarehouses[0],
|
||||
quantity: 10000,
|
||||
sub_qty: 10000,
|
||||
total_qty: 10000,
|
||||
total_used: 0,
|
||||
price: 6500,
|
||||
total_price: 65000000,
|
||||
received_date: null,
|
||||
travel_number: null,
|
||||
travel_number_docs: null,
|
||||
vehicle_number: null,
|
||||
warehouse: dummyWarehouses[0],
|
||||
},
|
||||
],
|
||||
created_at: '2025-01-10T00:00:00Z',
|
||||
updated_at: '2025-01-10T00:00:00Z',
|
||||
created_by: 1,
|
||||
deleted_at: null,
|
||||
created_user: createdUser,
|
||||
warehouse: dummyWarehouses[0],
|
||||
};
|
||||
|
||||
const dummyGoodsReceiptItems: PurchaseItem[] = [
|
||||
{
|
||||
id: 1,
|
||||
purchase_id: 1,
|
||||
product: {
|
||||
id: 1,
|
||||
product_category: {
|
||||
id: 1,
|
||||
code: 'DOC',
|
||||
name: 'DOC',
|
||||
created_user: createdUser,
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
name: 'CP Vaksin',
|
||||
brand: '',
|
||||
sku: '',
|
||||
product_price: 0,
|
||||
selling_price: 0,
|
||||
tax: 0,
|
||||
expiry_period: 0,
|
||||
uom: {
|
||||
id: 1,
|
||||
name: 'Ekor',
|
||||
created_user: createdUser,
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
suppliers: [],
|
||||
flags: [],
|
||||
created_user: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'hello@gmail.com',
|
||||
name: 'Admin',
|
||||
},
|
||||
created_at: '2025-01-01T00:00:00Z',
|
||||
updated_at: '2025-01-01T00:00:00Z',
|
||||
},
|
||||
product_warehouse: dummyProductWarehouses[0],
|
||||
quantity: 10000,
|
||||
sub_qty: 10000,
|
||||
total_qty: 10000,
|
||||
total_used: 0,
|
||||
price: 6500,
|
||||
total_price: 65000000,
|
||||
received_date: '2025-01-15T00:00:00Z',
|
||||
travel_number: 'NSJ-1',
|
||||
travel_number_docs: '/documents/nsj-1.pdf',
|
||||
vehicle_number: 'NAP-1',
|
||||
warehouse: dummyWarehouses[0],
|
||||
},
|
||||
];
|
||||
|
||||
const dummyGroupedApprovals: BaseGroupedApproval[] = [
|
||||
{
|
||||
step_number: 1,
|
||||
step_name: 'Pengajuan',
|
||||
approvals: [
|
||||
{
|
||||
step_number: 1,
|
||||
step_name: 'Pengajuan',
|
||||
action: 'submit',
|
||||
notes: 'Pengajuan purchase order dibuat',
|
||||
action_by: {
|
||||
id: 1,
|
||||
id_user: 1,
|
||||
email: 'user@company.com',
|
||||
name: 'User Pengajuan',
|
||||
},
|
||||
action_at: '2025-01-10T08:00:00Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
step_number: 2,
|
||||
step_name: 'Approval Purchasing',
|
||||
approvals: [
|
||||
{
|
||||
step_number: 2,
|
||||
step_name: 'Approval Purchasing',
|
||||
action: 'approve',
|
||||
notes: 'Purchase order disetujui oleh purchasing',
|
||||
action_by: {
|
||||
id: 2,
|
||||
id_user: 2,
|
||||
email: 'purchasing@company.com',
|
||||
name: 'Staff Purchasing',
|
||||
},
|
||||
action_at: '2025-01-10T10:30:00Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
step_number: 3,
|
||||
step_name: 'Approval Manager Purchasing',
|
||||
approvals: [
|
||||
{
|
||||
step_number: 3,
|
||||
step_name: 'Approval Manager Purchasing',
|
||||
action: 'approve',
|
||||
notes: 'Purchase order disetujui oleh manager purchasing',
|
||||
action_by: {
|
||||
id: 3,
|
||||
id_user: 3,
|
||||
email: 'manager.purchasing@company.com',
|
||||
name: 'Manager Purchasing',
|
||||
},
|
||||
action_at: '2025-01-10T14:15:00Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
step_number: 4,
|
||||
step_name: 'Produk Diterima',
|
||||
approvals: [
|
||||
{
|
||||
step_number: 4,
|
||||
step_name: 'Produk Diterima',
|
||||
action: 'receive',
|
||||
notes: 'Produk telah diterima sesuai pesanan',
|
||||
action_by: {
|
||||
id: 4,
|
||||
id_user: 4,
|
||||
email: 'user@company.com',
|
||||
name: 'User Pengajuan',
|
||||
},
|
||||
action_at: '2025-01-12T09:00:00Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
step_number: 5,
|
||||
step_name: 'Selesai',
|
||||
approvals: [
|
||||
{
|
||||
step_number: 5,
|
||||
step_name: 'Selesai',
|
||||
action: 'complete',
|
||||
notes: 'Purchase order telah selesai diproses',
|
||||
action_by: {
|
||||
id: 5,
|
||||
id_user: 5,
|
||||
email: 'user@company.com',
|
||||
name: 'User Pengajuan',
|
||||
},
|
||||
action_at: '2025-01-12T16:00:00Z',
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
const PurchaseOrderDetail = ({
|
||||
type = 'detail',
|
||||
@@ -420,23 +97,49 @@ const PurchaseOrderDetail = ({
|
||||
parseInt(item)
|
||||
);
|
||||
|
||||
// ===== STATIC DATA =====
|
||||
const purchaseData = data || dummyPurchaseData;
|
||||
// ===== COMPUTED VALUES =====
|
||||
const purchaseOrderItems = useMemo(
|
||||
() => purchaseData.items || [],
|
||||
[purchaseData.items]
|
||||
() => data?.items || [],
|
||||
[data?.items]
|
||||
);
|
||||
const goodsReceiptItems = dummyGoodsReceiptItems;
|
||||
const groupedApprovals = dummyGroupedApprovals;
|
||||
const latestApproval =
|
||||
groupedApprovals[groupedApprovals.length - 1]?.approvals[0];
|
||||
|
||||
// Create goods receipt items from received items
|
||||
const goodsReceiptItems = useMemo(() => {
|
||||
return purchaseOrderItems.filter(item => item.received_date);
|
||||
}, [purchaseOrderItems]);
|
||||
|
||||
// Create simple approval steps from single approval data
|
||||
const approvalSteps = useMemo(() => {
|
||||
if (!data?.approval) return [];
|
||||
|
||||
// Create a simple approval step based on the single approval data
|
||||
const status = data.approval.action === 'APPROVED' ? 'APPROVED' :
|
||||
data.approval.action === 'REJECTED' ? 'REJECTED' : 'WAITING';
|
||||
|
||||
return [{
|
||||
name: data.approval.step_name,
|
||||
status: status as ApprovalStepStatus,
|
||||
logs: [{
|
||||
action_by: data.approval.action_by?.name,
|
||||
date: data.approval.action_at,
|
||||
notes: data.approval.notes,
|
||||
}],
|
||||
}];
|
||||
}, [data?.approval]);
|
||||
|
||||
const totalBeforeTax = useMemo(() => {
|
||||
return purchaseOrderItems.reduce(
|
||||
(sum, item) => sum + (item.total_price || 0),
|
||||
0
|
||||
);
|
||||
}, [purchaseOrderItems]);
|
||||
|
||||
// ===== SUBMISSION HANDLER =====
|
||||
const createManagerApprovalHandler = useCallback(
|
||||
async (payload: CreateManagerApprovalRequestPayload) => {
|
||||
const purchaseRequestId = searchParams.get('purchaseId')
|
||||
? parseInt(searchParams.get('purchaseId')!)
|
||||
: purchaseData?.id || 1;
|
||||
: data?.id || 1;
|
||||
|
||||
if (!purchaseRequestId) {
|
||||
toast.error('Purchase Request ID is required');
|
||||
@@ -454,14 +157,14 @@ const PurchaseOrderDetail = ({
|
||||
}
|
||||
toast.success(res?.message as string);
|
||||
},
|
||||
[purchaseData?.id, searchParams]
|
||||
[data?.id, searchParams]
|
||||
);
|
||||
|
||||
// ===== DELETE HANDLER =====
|
||||
const deleteItemsHandler = useCallback(async () => {
|
||||
const purchaseRequestId = searchParams.get('purchaseId')
|
||||
? parseInt(searchParams.get('purchaseId')!)
|
||||
: purchaseData?.id || 1;
|
||||
: data?.id || 1;
|
||||
|
||||
if (!purchaseRequestId) {
|
||||
toast.error('Purchase Request ID is required');
|
||||
@@ -501,30 +204,14 @@ const PurchaseOrderDetail = ({
|
||||
} finally {
|
||||
setIsDeleteLoading(false);
|
||||
}
|
||||
}, [purchaseData?.id, searchParams, selectedItem, selectedRowIds]);
|
||||
}, [data?.id, searchParams, selectedItem, selectedRowIds]);
|
||||
|
||||
// ===== COMPUTED VALUES =====
|
||||
const approvalSteps = useMemo(() => {
|
||||
if (!groupedApprovals.length || !latestApproval) return [];
|
||||
// Return null if no data provided
|
||||
if (!data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return formatGroupedApprovalsToApprovalSteps(
|
||||
PURCHASE_ORDER_APPROVAL_LINE,
|
||||
groupedApprovals,
|
||||
latestApproval
|
||||
);
|
||||
} catch (error) {
|
||||
console.error('Error formatting approval steps:', error);
|
||||
return [];
|
||||
}
|
||||
}, [groupedApprovals, latestApproval]);
|
||||
|
||||
const totalBeforeTax = useMemo(() => {
|
||||
return purchaseOrderItems.reduce(
|
||||
(sum, item) => sum + (item.total_price || 0),
|
||||
0
|
||||
);
|
||||
}, [purchaseOrderItems]);
|
||||
const purchaseData = data;
|
||||
|
||||
const purchaseOrderColumns: ColumnDef<PurchaseItem>[] = [
|
||||
{
|
||||
@@ -563,10 +250,15 @@ const PurchaseOrderDetail = ({
|
||||
cell: (props) => props.row.original.product?.name || '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'product.product_category.name',
|
||||
accessorKey: 'product.product_category',
|
||||
header: 'Jenis Produk',
|
||||
cell: (props) =>
|
||||
props.row.original.product?.product_category?.name || '-',
|
||||
cell: (props) => {
|
||||
const category = props.row.original.product?.product_category;
|
||||
if (typeof category === 'string') {
|
||||
return category;
|
||||
}
|
||||
return category?.name || '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'quantity',
|
||||
@@ -576,7 +268,13 @@ const PurchaseOrderDetail = ({
|
||||
{
|
||||
accessorKey: 'product.uom.name',
|
||||
header: 'Satuan',
|
||||
cell: (props) => props.row.original.product?.uom?.name || '-',
|
||||
cell: (props) => {
|
||||
const uom = props.row.original.product?.uom;
|
||||
if (uom && typeof uom === 'object' && uom.name) {
|
||||
return uom.name;
|
||||
}
|
||||
return uom || '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'price',
|
||||
@@ -628,10 +326,12 @@ const PurchaseOrderDetail = ({
|
||||
: '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'product_warehouse.warehouse.name',
|
||||
accessorKey: 'warehouse.name',
|
||||
header: 'Gudang Tujuan',
|
||||
cell: (props) =>
|
||||
props.row.original.product_warehouse?.warehouse?.name || '-',
|
||||
cell: (props) => {
|
||||
const warehouse = props.row.original.warehouse;
|
||||
return warehouse?.name || '-';
|
||||
},
|
||||
},
|
||||
{
|
||||
accessorKey: 'travel_number',
|
||||
@@ -639,10 +339,10 @@ const PurchaseOrderDetail = ({
|
||||
cell: (props) => props.row.original.travel_number || '-',
|
||||
},
|
||||
{
|
||||
accessorKey: 'travel_number_docs',
|
||||
accessorKey: 'travel_document_path',
|
||||
header: 'Dokumen Surat Jalan',
|
||||
cell: (props) => {
|
||||
const documentPath = props.row.original.travel_number_docs;
|
||||
const documentPath = props.row.original.travel_document_path;
|
||||
return documentPath ? (
|
||||
<Button
|
||||
color='primary'
|
||||
@@ -807,7 +507,7 @@ const PurchaseOrderDetail = ({
|
||||
Area
|
||||
</span>
|
||||
<span className='text-gray-900 ml-3 break-all'>
|
||||
: {purchaseData.area?.name || '-'}
|
||||
: {purchaseData.items?.[0]?.warehouse?.area?.name || '-'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -817,7 +517,7 @@ const PurchaseOrderDetail = ({
|
||||
Lokasi
|
||||
</span>
|
||||
<span className='text-gray-900 ml-3 break-all'>
|
||||
: {purchaseData.location?.name || '-'}
|
||||
: {purchaseData.items?.[0]?.warehouse?.type !== 'AREA' && purchaseData.items?.[0]?.warehouse?.location?.name ? purchaseData.items[0].warehouse.location.name : '-'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -827,7 +527,7 @@ const PurchaseOrderDetail = ({
|
||||
Gudang
|
||||
</span>
|
||||
<span className='text-gray-900 ml-3 break-all'>
|
||||
: {purchaseData.warehouse?.name || '-'}
|
||||
: {purchaseData.items?.[0]?.warehouse?.name || '-'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
@@ -848,10 +548,10 @@ const PurchaseOrderDetail = ({
|
||||
<div className='group'>
|
||||
<div className='flex items-start'>
|
||||
<span className='font-medium text-gray-600 min-w-[140px] flex-shrink-0'>
|
||||
Alamat Supplier
|
||||
Kategori Supplier
|
||||
</span>
|
||||
<span className='text-gray-900 ml-3 break-all'>
|
||||
: {purchaseData.supplier?.address || '-'}
|
||||
: {purchaseData.supplier?.category || '-'}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Vendored
+19
-3
@@ -1,4 +1,4 @@
|
||||
import { BaseMetadata } from '@/types/api/api-general';
|
||||
import { BaseApproval, BaseMetadata } from '@/types/api/api-general';
|
||||
import { Supplier } from '@/types/api/master-data/supplier';
|
||||
import { Warehouse } from '@/types/api/master-data/warehouse';
|
||||
import { Product } from '@/types/api/master-data/product';
|
||||
@@ -6,11 +6,25 @@ import { ProductWarehouse } from '@/types/api/inventory/product-warehouse';
|
||||
import { Area } from '@/types/api/master-data/area';
|
||||
import { Location } from '@/types/api/master-data/location';
|
||||
|
||||
export type PurchaseItemProduct = {
|
||||
id: number;
|
||||
name: string;
|
||||
flags?: string[];
|
||||
uom?: {
|
||||
name: string;
|
||||
};
|
||||
product_category?:
|
||||
| {
|
||||
name: string;
|
||||
}
|
||||
| string;
|
||||
};
|
||||
|
||||
export type PurchaseItem = {
|
||||
id: number;
|
||||
purchase_id?: number;
|
||||
product_id: number;
|
||||
warehouse: Warehouse;
|
||||
product: Product;
|
||||
product: PurchaseItemProduct | Product;
|
||||
product_warehouse: ProductWarehouse;
|
||||
quantity: number;
|
||||
qty: number;
|
||||
@@ -22,6 +36,7 @@ export type PurchaseItem = {
|
||||
received_date?: string | null;
|
||||
travel_number?: string | null;
|
||||
travel_number_docs?: string | null;
|
||||
travel_document_path?: string | null;
|
||||
vehicle_number?: string | null;
|
||||
};
|
||||
|
||||
@@ -42,6 +57,7 @@ export type BasePurchase = {
|
||||
location?: Location;
|
||||
warehouse?: Warehouse;
|
||||
items?: PurchaseItem[];
|
||||
approval?: BaseApproval;
|
||||
};
|
||||
|
||||
export type Purchase = BaseMetadata & BasePurchase;
|
||||
|
||||
Reference in New Issue
Block a user