Add PostProductStock component and integrate posting functionality for product stocks. Update NewProductStock to set default state to 'draft'. Enhance ProductStockInfo with modal for posting stocks and update action visibility based on stock state.
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
Some checks failed
farmcontrol/farmcontrol-ui/pipeline/head There was a failure building this commit
This commit is contained in:
parent
04d26600fd
commit
5ec394cbc0
@ -8,7 +8,7 @@ const NewProductStock = ({ onOk, reset, defaultValues }) => {
|
|||||||
<NewObjectForm
|
<NewObjectForm
|
||||||
type={'productStock'}
|
type={'productStock'}
|
||||||
reset={reset}
|
reset={reset}
|
||||||
defaultValues={{ state: { type: 'new' }, ...defaultValues }}
|
defaultValues={{ state: { type: 'draft' }, ...defaultValues }}
|
||||||
>
|
>
|
||||||
{({ handleSubmit, submitLoading, objectData, formValid }) => {
|
{({ handleSubmit, submitLoading, objectData, formValid }) => {
|
||||||
const steps = [
|
const steps = [
|
||||||
|
|||||||
@ -0,0 +1,46 @@
|
|||||||
|
import { useState, useContext } from 'react'
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import { ApiServerContext } from '../../context/ApiServerContext'
|
||||||
|
import { message } from 'antd'
|
||||||
|
import MessageDialogView from '../../common/MessageDialogView.jsx'
|
||||||
|
|
||||||
|
const PostProductStock = ({ onOk, objectData }) => {
|
||||||
|
const [postLoading, setPostLoading] = useState(false)
|
||||||
|
const { sendObjectFunction } = useContext(ApiServerContext)
|
||||||
|
|
||||||
|
const handlePost = async () => {
|
||||||
|
setPostLoading(true)
|
||||||
|
try {
|
||||||
|
const result = await sendObjectFunction(
|
||||||
|
objectData._id,
|
||||||
|
'ProductStock',
|
||||||
|
'post'
|
||||||
|
)
|
||||||
|
if (result) {
|
||||||
|
message.success('Product stock posted successfully')
|
||||||
|
onOk(result)
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error posting product stock:', error)
|
||||||
|
} finally {
|
||||||
|
setPostLoading(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MessageDialogView
|
||||||
|
title={'Are you sure you want to post this product stock?'}
|
||||||
|
description={`Posting product stock ${objectData?.name || objectData?._reference || objectData?._id} will finalize it and make it read-only.`}
|
||||||
|
onOk={handlePost}
|
||||||
|
okText='Post'
|
||||||
|
okLoading={postLoading}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
PostProductStock.propTypes = {
|
||||||
|
onOk: PropTypes.func.isRequired,
|
||||||
|
objectData: PropTypes.object
|
||||||
|
}
|
||||||
|
|
||||||
|
export default PostProductStock
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import { useRef, useState } from 'react'
|
import { useRef, useState } from 'react'
|
||||||
import { useLocation } from 'react-router-dom'
|
import { useLocation } from 'react-router-dom'
|
||||||
import { Space, Flex, Card } from 'antd'
|
import { Space, Flex, Card, Modal } from 'antd'
|
||||||
import { LoadingOutlined } from '@ant-design/icons'
|
import { LoadingOutlined } from '@ant-design/icons'
|
||||||
import loglevel from 'loglevel'
|
import loglevel from 'loglevel'
|
||||||
import config from '../../../../config.js'
|
import config from '../../../../config.js'
|
||||||
@ -10,7 +10,8 @@ import InfoCollapse from '../../common/InfoCollapse.jsx'
|
|||||||
import ObjectInfo from '../../common/ObjectInfo.jsx'
|
import ObjectInfo from '../../common/ObjectInfo.jsx'
|
||||||
import ObjectProperty from '../../common/ObjectProperty.jsx'
|
import ObjectProperty from '../../common/ObjectProperty.jsx'
|
||||||
import ViewButton from '../../common/ViewButton.jsx'
|
import ViewButton from '../../common/ViewButton.jsx'
|
||||||
import { getModelProperty } from '../../../../database/ObjectModels.js'
|
import { getModelProperty, getModelByName } from '../../../../database/ObjectModels.js'
|
||||||
|
import PostProductStock from './PostProductStock.jsx'
|
||||||
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
|
import InfoCircleIcon from '../../../Icons/InfoCircleIcon.jsx'
|
||||||
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
import NoteIcon from '../../../Icons/NoteIcon.jsx'
|
||||||
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
|
import AuditLogIcon from '../../../Icons/AuditLogIcon.jsx'
|
||||||
@ -36,6 +37,7 @@ const ProductStockInfo = () => {
|
|||||||
const productStockId = new URLSearchParams(location.search).get(
|
const productStockId = new URLSearchParams(location.search).get(
|
||||||
'productStockId'
|
'productStockId'
|
||||||
)
|
)
|
||||||
|
const [postProductStockOpen, setPostProductStockOpen] = useState(false)
|
||||||
const [collapseState, updateCollapseState] = useCollapseState(
|
const [collapseState, updateCollapseState] = useCollapseState(
|
||||||
'ProductStockInfo',
|
'ProductStockInfo',
|
||||||
{
|
{
|
||||||
@ -71,9 +73,22 @@ const ProductStockInfo = () => {
|
|||||||
finishEdit: () => {
|
finishEdit: () => {
|
||||||
objectFormRef?.current.handleUpdate()
|
objectFormRef?.current.handleUpdate()
|
||||||
return true
|
return true
|
||||||
|
},
|
||||||
|
delete: () => {
|
||||||
|
objectFormRef?.current.handleDelete?.()
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
post: () => {
|
||||||
|
setPostProductStockOpen(true)
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const editDisabled =
|
||||||
|
getModelByName('productStock')
|
||||||
|
?.actions?.find((action) => action.name === 'edit')
|
||||||
|
?.disabled(objectFormState.objectData) ?? false
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Flex
|
<Flex
|
||||||
@ -131,7 +146,11 @@ const ProductStockInfo = () => {
|
|||||||
}}
|
}}
|
||||||
editLoading={objectFormState.editLoading}
|
editLoading={objectFormState.editLoading}
|
||||||
formValid={objectFormState.formValid}
|
formValid={objectFormState.formValid}
|
||||||
disabled={objectFormState.lock?.locked || objectFormState.loading}
|
disabled={
|
||||||
|
objectFormState.lock?.locked ||
|
||||||
|
objectFormState.loading ||
|
||||||
|
editDisabled
|
||||||
|
}
|
||||||
loading={objectFormState.editLoading}
|
loading={objectFormState.editLoading}
|
||||||
/>
|
/>
|
||||||
</Space>
|
</Space>
|
||||||
@ -230,6 +249,24 @@ const ProductStockInfo = () => {
|
|||||||
</Flex>
|
</Flex>
|
||||||
</ScrollBox>
|
</ScrollBox>
|
||||||
</Flex>
|
</Flex>
|
||||||
|
<Modal
|
||||||
|
open={postProductStockOpen}
|
||||||
|
onCancel={() => {
|
||||||
|
setPostProductStockOpen(false)
|
||||||
|
}}
|
||||||
|
width={500}
|
||||||
|
footer={null}
|
||||||
|
destroyOnHidden={true}
|
||||||
|
centered={true}
|
||||||
|
>
|
||||||
|
<PostProductStock
|
||||||
|
onOk={() => {
|
||||||
|
setPostProductStockOpen(false)
|
||||||
|
actions.reload()
|
||||||
|
}}
|
||||||
|
objectData={objectFormState.objectData}
|
||||||
|
/>
|
||||||
|
</Modal>
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
import ProductStockIcon from '../../components/Icons/ProductStockIcon'
|
import ProductStockIcon from '../../components/Icons/ProductStockIcon'
|
||||||
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
|
import InfoCircleIcon from '../../components/Icons/InfoCircleIcon'
|
||||||
|
import EditIcon from '../../components/Icons/EditIcon'
|
||||||
|
import CheckIcon from '../../components/Icons/CheckIcon'
|
||||||
|
import XMarkIcon from '../../components/Icons/XMarkIcon'
|
||||||
|
import BinIcon from '../../components/Icons/BinIcon'
|
||||||
|
|
||||||
export const ProductStock = {
|
export const ProductStock = {
|
||||||
name: 'productStock',
|
name: 'productStock',
|
||||||
@ -15,6 +19,69 @@ export const ProductStock = {
|
|||||||
icon: InfoCircleIcon,
|
icon: InfoCircleIcon,
|
||||||
url: (_id) =>
|
url: (_id) =>
|
||||||
`/dashboard/inventory/productstocks/info?productStockId=${_id}`
|
`/dashboard/inventory/productstocks/info?productStockId=${_id}`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'edit',
|
||||||
|
label: 'Edit',
|
||||||
|
type: 'button',
|
||||||
|
icon: EditIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/inventory/productstocks/info?productStockId=${_id}&action=edit`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return !(objectData?._isEditing && objectData?._isEditing == true)
|
||||||
|
},
|
||||||
|
disabled: (objectData) => {
|
||||||
|
return objectData?.state?.type != 'draft'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'cancelEdit',
|
||||||
|
label: 'Cancel Edit',
|
||||||
|
type: 'button',
|
||||||
|
icon: XMarkIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/inventory/productstocks/info?productStockId=${_id}&action=cancelEdit`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return objectData?._isEditing && objectData?._isEditing == true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'finishEdit',
|
||||||
|
label: 'Finish Edit',
|
||||||
|
type: 'button',
|
||||||
|
icon: CheckIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/inventory/productstocks/info?productStockId=${_id}&action=finishEdit`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return objectData?._isEditing && objectData?._isEditing == true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'delete',
|
||||||
|
label: 'Delete',
|
||||||
|
type: 'button',
|
||||||
|
icon: BinIcon,
|
||||||
|
danger: true,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/inventory/productstocks/info?productStockId=${_id}&action=delete`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return !(objectData?._isEditing && objectData?._isEditing == true)
|
||||||
|
},
|
||||||
|
disabled: (objectData) => {
|
||||||
|
return objectData?.state?.type != 'draft'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ type: 'divider' },
|
||||||
|
{
|
||||||
|
name: 'post',
|
||||||
|
label: 'Post',
|
||||||
|
type: 'button',
|
||||||
|
icon: CheckIcon,
|
||||||
|
url: (_id) =>
|
||||||
|
`/dashboard/inventory/productstocks/info?productStockId=${_id}&action=post`,
|
||||||
|
visible: (objectData) => {
|
||||||
|
return objectData?.state?.type == 'draft'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
url: (id) => `/dashboard/inventory/productstocks/info?productStockId=${id}`,
|
url: (id) => `/dashboard/inventory/productstocks/info?productStockId=${id}`,
|
||||||
@ -50,6 +117,12 @@ export const ProductStock = {
|
|||||||
readOnly: true,
|
readOnly: true,
|
||||||
columnWidth: 120
|
columnWidth: 120
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'postedAt',
|
||||||
|
label: 'Posted At',
|
||||||
|
type: 'dateTime',
|
||||||
|
readOnly: true
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'updatedAt',
|
name: 'updatedAt',
|
||||||
label: 'Updated At',
|
label: 'Updated At',
|
||||||
@ -109,6 +182,18 @@ export const ProductStock = {
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
stats: [
|
stats: [
|
||||||
|
{
|
||||||
|
name: 'draft.count',
|
||||||
|
label: 'Draft',
|
||||||
|
type: 'number',
|
||||||
|
color: 'default'
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'posted.count',
|
||||||
|
label: 'Posted',
|
||||||
|
type: 'number',
|
||||||
|
color: 'success'
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'totalCurrentQuantity.sum',
|
name: 'totalCurrentQuantity.sum',
|
||||||
label: 'Total Current Quantity',
|
label: 'Total Current Quantity',
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user