Repository: GeorgeKalash/ArgusFE
Pull request #1039: Ar 2864
Author: login: omarZrayka23
Created: 2025-03-03T08:35:29Z | Merged: 2025-04-04T14:24:55Z

new screen :  undelivered-items in asp


Diff:
diff --git a/src/components/Inputs/CustomCheckBox.js b/src/components/Inputs/CustomCheckBox.js
index 2a46a6c505..b07ac1ac64 100644
--- a/src/components/Inputs/CustomCheckBox.js
+++ b/src/components/Inputs/CustomCheckBox.js
@@ -36,11 +36,13 @@ const CustomCheckBox = ({
           disabled={_disabled}
           inputProps={{ 'aria-label': label }}
           sx={{ ml: 2, '& .MuiSvgIcon-root': { fontSize: 15 }, '&.aria-label': { fontSize: 15 } }}
+          {...props}
         />
       }
       label={label}
       dir={dir}
       componentsProps={{ typography: { sx: { fontSize: 15 } } }}
+      {...props}
     />
   )
 }
diff --git a/src/components/Shared/Buttons.js b/src/components/Shared/Buttons.js
index 9463162a0b..942b9c67ea 100644
--- a/src/components/Shared/Buttons.js
+++ b/src/components/Shared/Buttons.js
@@ -555,5 +555,11 @@ export const getButtons = platformLabels => [
     color: '#1f78b4',
     image: '3d-printer.png',
     main: false
+  },
+  {
+    key: 'ORD',
+    label: platformLabels.ord,
+    color: '#231f20',
+    main: false
   }
 ]
diff --git a/src/components/Shared/DataGrid/components/numberfield/index.js b/src/components/Shared/DataGrid/components/numberfield/index.js
index a8f52a59fd..1df6e2d151 100644
--- a/src/components/Shared/DataGrid/components/numberfield/index.js
+++ b/src/components/Shared/DataGrid/components/numberfield/index.js
@@ -9,7 +9,7 @@ export function View({ value }) {
   const viewDecimals = systemChecks.some(check => check.checkId === SystemChecks.HIDE_LEADING_ZERO_DECIMALS)
 
   const formatValue = val => {
-    if (!val) return ''
+    if (!val && val !== 0) return ''
     if (isNaN(val)) return val
 
     return String(val)
diff --git a/src/components/Shared/DataGrid/index.js b/src/components/Shared/DataGrid/index.js
index 991f48c4c7..b70e4faed0 100644
--- a/src/components/Shared/DataGrid/index.js
+++ b/src/components/Shared/DataGrid/index.js
@@ -1,6 +1,6 @@
 import React, { useContext, useEffect, useRef, useState } from 'react'
 import { AgGridReact } from 'ag-grid-react'
-import { Box, IconButton } from '@mui/material'
+import { Box, Checkbox, Grid, IconButton } from '@mui/material'
 import components from './components'
 import { CacheStoreProvider } from 'src/providers/CacheStoreContext'
 import { GridDeleteIcon } from '@mui/x-data-grid'
@@ -9,6 +9,7 @@ import { useWindow } from 'src/windows'
 import DeleteDialog from '../DeleteDialog'
 import ConfirmationDialog from 'src/components/ConfirmationDialog'
 import { ControlContext } from 'src/providers/ControlContext'
+import CustomCheckBox from 'src/components/Inputs/CustomCheckBox'
 
 export function DataGrid({
   name, // maxAccess
@@ -199,15 +200,6 @@ export function DataGrid({
     }
   }, [rowSelectionModel])
 
-  useEffect(() => {
-    if (gridApiRef.current && rowSelectionModel) {
-      const rowNode = gridApiRef.current.getRowNode(rowSelectionModel)
-      if (rowNode) {
-        rowNode.setSelected(true)
-      }
-    }
-  }, [rowSelectionModel])
-
   const addNewRow = () => {
     const highestIndex = Math.max(...value?.map(item => item.id), 0) + 1
 
@@ -273,7 +265,8 @@ export function DataGrid({
         (allColumns?.[i]?.props?.readOnly &&
           (accessLevel({ maxAccess, name: `${name}.${allColumns?.[i]?.name}` }) === FORCE_ENABLED ||
             accessLevel({ maxAccess, name: `${name}.${allColumns?.[i]?.name}` }) === MANDATORY))) &&
-      (typeof allColumns?.[i]?.props?.disableCondition !== 'function' || !allColumns?.[i]?.props?.disableCondition(data))
+      (typeof allColumns?.[i]?.props?.disableCondition !== 'function' ||
+        !allColumns?.[i]?.props?.disableCondition(data))
     )
   }
 
@@ -560,6 +553,32 @@ export function DataGrid({
       sortable: false,
       cellRenderer: CustomCellRenderer,
       cellEditor: CustomCellEditor,
+      ...(column?.checkAll?.visible && {
+        headerComponent: params => {
+          const selectAll = e => {
+            if (column?.checkAll?.onChange) {
+              column?.checkAll?.onChange({ checked: e.target?.checked })
+            }
+          }
+
+          return (
+            <Grid container justifyContent='center' alignItems='center'>
+              <CustomCheckBox
+                checked={column?.checkAll?.value}
+                onChange={e => {
+                  selectAll(e)
+                }}
+                sx={{
+                  width: '20%',
+                  height: '20%',
+                  marginLeft: '0px !important'
+                }}
+                disabled={column.checkAll?.disabled}
+              />
+            </Grid>
+          )
+        }
+      }),
       cellEditorParams: { maxAccess },
       cellStyle: getCellStyle,
       suppressKeyboardEvent: params => {
@@ -615,11 +634,12 @@ export function DataGrid({
   useEffect(() => {
     function handleBlur(event) {
       if (
-        gridContainerRef.current &&
-        !gridContainerRef.current.contains(event.target) &&
-        gridApiRef.current?.getEditingCells()?.length > 0 &&
-        !event.target.classList.contains('MuiBox-root') &&
-        !event.target.classList.contains('MuiAutocomplete-option')
+        (gridContainerRef.current &&
+          !gridContainerRef.current.contains(event.target) &&
+          gridApiRef.current?.getEditingCells()?.length > 0 &&
+          !event.target.classList.contains('MuiBox-root') &&
+          !event.target.classList.contains('MuiAutocomplete-option')) ||
+        event.target.closest('.ag-header-row')
       ) {
         gridApiRef.current?.stopEditing()
       } else {
diff --git a/src/components/Shared/WindowToolbar.js b/src/components/Shared/WindowToolbar.js
index 10e627ec66..31e53d4c5a 100644
--- a/src/components/Shared/WindowToolbar.js
+++ b/src/components/Shared/WindowToolbar.js
@@ -16,6 +16,7 @@ const WindowToolbar = ({
   isSavedClear,
   isInfo,
   isCleared,
+  onORD,
   onGenerateReport,
   disabledSubmit,
   disabledSavedClear,
@@ -105,6 +106,7 @@ const WindowToolbar = ({
     isClosed,
     editMode,
     onSave,
+    onORD,
     onSaveClear,
     onClear,
     onInfo
diff --git a/src/pages/delivery-orders/Forms/DeliveryOrdersForm.js b/src/pages/delivery-orders/Forms/DeliveryOrdersForm.js
index 0db8dfc28b..15a54eb58d 100644
--- a/src/pages/delivery-orders/Forms/DeliveryOrdersForm.js
+++ b/src/pages/delivery-orders/Forms/DeliveryOrdersForm.js
@@ -31,7 +31,7 @@ import AddressFilterForm from 'src/components/Shared/AddressFilterForm'
 import GenerateInvoiceForm from './GenerateInvoiceForm'
 import CustomCheckBox from 'src/components/Inputs/CustomCheckBox'
 
-export default function DeliveriesOrdersForm({ labels, maxAccess: access, recordId }) {
+export default function DeliveriesOrdersForm({ labels, maxAccess: access, recordId, refresh = true, ...props }) {
   const { getRequest, postRequest } = useContext(RequestsContext)
   const { platformLabels, userDefaultsData } = useContext(ControlContext)
   const { stack } = useWindow()
@@ -43,24 +43,14 @@ export default function DeliveriesOrdersForm({ labels, maxAccess: access, record
     enabled: !recordId
   })
 
-  async function getDefaultData() {
-    const userKeys = ['plantId', 'siteId']
+  const defPId = parseInt(userDefaultsData?.list?.find(obj => obj.key === 'plantId')?.value)
+  const defSiteId = parseInt(userDefaultsData?.list?.find(obj => obj.key === 'siteId')?.value)
 
-    const userDefault = (userDefaultsData?.list || []).reduce((acc, { key, value }) => {
-      if (userKeys.includes(key)) {
-        acc[key] = value ? parseInt(value) : null
-      }
-
-      return acc
-    }, {})
-
-    formik.setFieldValue('plantId', parseInt(userDefault?.plantId))
-    formik.setFieldValue('siteId', parseInt(userDefault?.siteId))
-  }
-
-  const invalidate = useInvalidate({
-    endpointId: DeliveryRepository.DeliveriesOrders.qry
-  })
+  const invalidate = useInvalidate(
+    refresh && {
+      endpointId: DeliveryRepository.DeliveriesOrders.qry
+    }
+  )
 
   const ordersInitialValues = [
     {
@@ -78,7 +68,6 @@ export default function DeliveriesOrdersForm({ labels, maxAccess: access, record
       qty: null,
       pendingQty: null,
       placeHolder: null,
-      soRef: null,
       siteId: null,
       siteName: '',
       isEditMode: false,
@@ -96,7 +85,7 @@ export default function DeliveriesOrdersForm({ labels, maxAccess: access, record
     initialValues: {
       recordId: null,
       reference: '',
-      plantId: null,
+      plantId: defPId,
       saleOrderId: null,
       clientRef: '',
       clientName: '',
@@ -123,7 +112,7 @@ export default function DeliveriesOrdersForm({ labels, maxAccess: access, record
       spId: null,
       volume: null,
       qty: null,
-      siteId: null,
+      siteId: defSiteId,
       address: '',
       orders: ordersInitialValues
     },
@@ -235,6 +224,8 @@ export default function DeliveriesOrdersForm({ labels, maxAccess: access, record
 
     formik.setValues({
       ...doHeader?.record,
+      plantId: props.plantId || doHeader?.record.plantId,
+      dtId: props.dtId || doHeader?.record.dtId,
       address: address,
       orders: ordersList
     })
@@ -278,7 +269,6 @@ export default function DeliveriesOrdersForm({ labels, maxAccess: access, record
 
   useEffect(() => {
     ;(async function () {
-      getDefaultData()
       if (recordId) {
         await refetchForm(recordId)
       }
diff --git a/src/pages/undelivered-items/index.js b/src/pages/undelivered-items/index.js
new file mode 100644
index 0000000000..874a9f705f
--- /dev/null
+++ b/src/pages/undelivered-items/index.js
@@ -0,0 +1,459 @@
+import { useContext, useEffect } from 'react'
+import toast from 'react-hot-toast'
+import { RequestsContext } from 'src/providers/RequestsContext'
+import { useResourceQuery } from 'src/hooks/resource'
+import { ResourceIds } from 'src/resources/ResourceIds'
+import { VertLayout } from 'src/components/Shared/Layouts/VertLayout'
+import { Fixed } from 'src/components/Shared/Layouts/Fixed'
+import { Grow } from 'src/components/Shared/Layouts/Grow'
+import { ControlContext } from 'src/providers/ControlContext'
+import { InventoryRepository } from 'src/repositories/InventoryRepository'
+import { Grid } from '@mui/material'
+import { ResourceLookup } from 'src/components/Shared/ResourceLookup'
+import { useForm } from 'src/hooks/form'
+import { SystemRepository } from 'src/repositories/SystemRepository'
+import { SaleRepository } from 'src/repositories/SaleRepository'
+import ResourceComboBox from 'src/components/Shared/ResourceComboBox'
+import { SystemFunction } from 'src/resources/SystemFunction'
+import { DataGrid } from 'src/components/Shared/DataGrid'
+import { RGSaleRepository } from 'src/repositories/RGSaleRepository'
+import { formatDateFromApi } from 'src/lib/date-helper'
+import WindowToolbar from 'src/components/Shared/WindowToolbar'
+import { DeliveryRepository } from 'src/repositories/DeliveryRepository'
+import CustomButton from 'src/components/Inputs/CustomButton'
+import CustomTextArea from 'src/components/Inputs/CustomTextArea'
+import { useWindow } from 'src/windows'
+import DeliveriesOrdersForm from '../delivery-orders/Forms/DeliveryOrdersForm'
+import { useError } from 'src/error'
+
+const UndeliveredItems = () => {
+  const { getRequest, postRequest } = useContext(RequestsContext)
+  const { platformLabels, defaultsData } = useContext(ControlContext)
+  const { stack } = useWindow()
+  const { stack: stackError } = useError()
+
+  const { labels, access } = useResourceQuery({
+    datasetId: ResourceIds.UndeliveredItems
+  })
+
+  const { labels: _labels, access: maxAccess } = useResourceQuery({
+    datasetId: ResourceIds.DeliveriesOrders
+  })
+
+  const defaultVat = defaultsData?.list?.find(({ key }) => key === 'DEORDMaxVarPct')
+
+  const { formik } = useForm({
+    maxAccess: access,
+    initialValues: {
+      recordId: null,
+      dtId: null,
+      groupId: 0,
+      plantId: 0,
+      siteId: 0,
+      categoryId: 0,
+      clientId: 0,
+      clientRef: '',
+      clientName: '',
+      soId: 0,
+      items: [],
+      marginDefault: defaultVat?.value,
+      notes: ''
+    },
+    validateOnChange: true,
+    onSubmit: async obj => {
+      const { clientId, siteId, notes, items, dtId, plantId } = obj
+
+      const itemValues = items
+        .filter(item => item.isChecked)
+        .map(({ scheduledDate, functionId, id, isChecked, ...item }) => item)
+
+      if (itemValues?.length < 1) {
+        stackError({
+          message: labels.checkItemsBeforeAppend
+        })
+
+        return
+      }
+
+      postRequest({
+        extension: DeliveryRepository.DeliveriesOrders.gen,
+        record: JSON.stringify({ clientId, siteId, notes, items: itemValues })
+      }).then(res => {
+        if (res.recordId) {
+          const items = obj.items.map(({ isChecked, ...item }) => ({
+            ...item,
+            isChecked: false,
+            deliverNow: 0
+          }))
+
+          formik.setFieldValue('items', items)
+
+          stack({
+            Component: DeliveriesOrdersForm,
+            props: {
+              labels: _labels,
+              recordId: res.recordId,
+              maxAccess,
+              refresh: false,
+              plantId,
+              dtId
+            },
+            width: 1300,
+            height: 700,
+            title: _labels.deliveryOrder
+          })
+
+          toast.success(platformLabels.Generated)
+        }
+      })
+    }
+  })
+
+  const { groupId, plantId, siteId, categoryId, clientId, soId, marginDefault } = formik.values
+
+  useEffect(() => {
+    getData()
+  }, [clientId, categoryId, groupId])
+
+  async function getData() {
+    const result = await getRequest({
+      extension: RGSaleRepository.SaSaleOrder.open,
+      parameters: `_categoryId=${categoryId}&_siteId=${siteId}&_groupId=${groupId}&_clientId=${clientId}&_soId=${soId}&_plantId=${plantId}`
+    })
+
+    const res = result?.list?.map((item, index) => ({
+      ...item,
+      id: index + 1,
+      date: formatDateFromApi(item.date),
+      balance: item.qty - item.deliveredQty
+    }))
+
+    formik.setFieldValue('items', res)
+  }
+
+  const isCheckedAll = formik.values.items?.length > 0 && formik.values.items?.every(item => item?.isChecked)
+
+  const columns = [
+    {
+      component: 'checkbox',
+      name: 'isChecked',
+      flex: 0.3,
+      checkAll: {
+        value: isCheckedAll,
+        visible: true,
+        onChange({ checked }) {
+          const items = formik.values.items.map(({ isChecked, ...item }) => ({
+            ...item,
+            isChecked: checked,
+            deliverNow: checked ? item.balance : 0
+          }))
+
+          formik.setFieldValue('items', items)
+        }
+      },
+
+      async onChange({ row: { update, newRow } }) {
+        update({ deliverNow: newRow.isChecked ? newRow.balance : 0 })
+      }
+    },
+    {
+      component: 'textfield',
+      label: labels.reference,
+      name: 'reference',
+      props: { readOnly: true }
+    },
+    {
+      component: 'date',
+      label: labels.date,
+      name: 'date',
+      props: { readOnly: true }
+    },
+    {
+      component: 'textfield',
+      label: labels.clientRef,
+      name: 'clientRef',
+      props: { readOnly: true }
+    },
+    {
+      component: 'textfield',
+      label: labels.client,
+      name: 'clientName',
+      props: { readOnly: true }
+    },
+    {
+      component: 'textfield',
+      label: labels.sku,
+      name: 'sku',
+      props: { readOnly: true }
+    },
+    {
+      component: 'textfield',
+      label: labels.item,
+      name: 'itemName',
+      props: { readOnly: true }
+    },
+    {
+      component: 'numberfield',
+      label: labels.qty,
+      name: 'qty',
+      props: { readOnly: true }
+    },
+    {
+      component: 'numberfield',
+      label: labels.deliveredQty,
+      name: 'deliveredQty',
+      props: { readOnly: true }
+    },
+    {
+      component: 'numberfield',
+      label: labels.balance,
+      name: 'balance',
+      props: { readOnly: true }
+    },
+    {
+      component: 'numberfield',
+      label: labels.genQty,
+      name: 'deliverNow',
+      updateOn: 'blur',
+      propsReducer({ row, props }) {
+        return { ...props, readOnly: !row.isChecked }
+      },
+      async onChange({ row: { update, newRow } }) {
+        const { deliverNow, balance, qty } = newRow
+
+        let value = deliverNow
+
+        if (deliverNow > balance) {
+          const margin = (100 * (deliverNow - balance)) / qty
+          if (marginDefault && marginDefault == 0) value = balance
+          else if (marginDefault && margin < marginDefault) value = deliverNow
+        } else if (deliverNow < 0) value = 0
+
+        update({ deliverNow: value })
+      }
+    }
+  ]
+
+  const actions = [
+    {
+      key: 'ORD',
+      condition: true,
+      onClick: () => formik.handleSubmit(),
+      disabled: !clientId || !siteId
+    }
+  ]
+
+  return (
+    <VertLayout>
+      <Fixed>
+        <Grid container spacing={2} padding={2}>
+          <Grid item xs={3}>
+            <Grid container spacing={2}>
+              <Grid item xs={12}>
+                <ResourceComboBox
+                  endpointId={SystemRepository.DocumentType.qry}
+                  parameters={`_dgId=${SystemFunction.DeliveryOrder}&_startAt=${0}&_pageSize=${1000}`}
+                  name='dtId'
+                  label={labels.documentType}
+                  valueField='recordId'
+                  displayField='name'
+                  values={formik.values}
+                  onChange={(event, newValue) => {
+                    formik.setFieldValue('dtId', newValue?.recordId || null)
+                  }}
+                  error={formik.touched.dtId && Boolean(formik.errors.dtId)}
+                  maxAccess={access}
+                />
+              </Grid>
+              <Grid item xs={12}>
+                <ResourceComboBox
+                  endpointId={InventoryRepository.Category.qry}
+                  parameters='_pagesize=30&_startAt=0&_name='
+                  name='categoryId'
+                  label={labels.category}
+                  valueField='recordId'
+                  displayField={'name'}
+                  displayFieldWidth={1}
+                  values={formik?.values}
+                  maxAccess={access}
+                  onChange={(event, newValue) => {
+                    formik.setFieldValue('categoryId', newValue?.recordId || 0)
+                  }}
+                  error={formik.touched.categoryId && Boolean(formik.errors.categoryId)}
+                />
+              </Grid>
+              <Grid item xs={12}>
+                <ResourceComboBox
+                  endpointId={InventoryRepository.Group.qry}
+                  parameters='_startAt=0&_pageSize=1000'
+                  name='groupId'
+                  label={labels.group}
+                  valueField='recordId'
+                  displayField={['reference', 'name']}
+                  columnsInDropDown={[
+                    { key: 'reference', value: 'Reference' },
+                    { key: 'name', value: 'Name' }
+                  ]}
+                  values={formik.values}
+                  onChange={(event, newValue) => {
+                    formik.setFieldValue('groupId', newValue?.recordId || 0)
+                  }}
+                  error={formik.touched.groupId && Boolean(formik.errors.groupId)}
+                  maxAccess={access}
+                />
+              </Grid>
+            </Grid>
+          </Grid>
+          <Grid item xs={3}>
+            <Grid container spacing={2}>
+              <Grid item xs={12}>
+                <ResourceLookup
+                  endpointId={SaleRepository.Client.snapshot}
+                  parameters={{
+                    _category: 0
+                  }}
+                  valueField='reference'
+                  displayField='name'
+                  name='clientId'
+                  label={labels.client}
+                  form={formik}
+                  displayFieldWidth={2}
+                  valueShow='clientRef'
+                  secondValueShow='clientName'
+                  maxAccess={access}
+                  columnsInDropDown={[
+                    { key: 'reference', value: 'Ref.' },
+                    { key: 'name', value: 'Name' }
+                  ]}
+                  onChange={async (event, newValue) => {
+                    formik.setFieldValue('clientId', newValue?.recordId || 0)
+                    formik.setFieldValue('clientName', newValue?.name || '')
+                    formik.setFieldValue('clientRef', newValue?.reference || '')
+                  }}
+                  errorCheck={'clientId'}
+                />
+              </Grid>
+              <Grid item xs={12}>
+                <ResourceComboBox
+                  endpointId={InventoryRepository.Site.qry}
+                  name='siteId'
+                  label={labels.site}
+                  valueField='recordId'
+                  displayField={['reference', 'name']}
+                  maxAccess={access}
+                  columnsInDropDown={[
+                    { key: 'reference', value: 'Reference' },
+                    { key: 'name', value: 'Name' }
+                  ]}
+                  values={formik.values}
+                  onChange={(event, newValue) => {
+                    formik.setFieldValue('siteId', newValue?.recordId || 0)
+                    formik.setFieldValue('siteRef', newValue?.reference || '')
+                    formik.setFieldValue('siteName', newValue?.name || '')
+                  }}
+                  required={formik.values.clientId}
+                  error={(formik.touched.sitId && Boolean(formik.errors.sitId)) || (clientId && !siteId)}
+                />
+              </Grid>
+              <Grid item xs={12}>
+                <ResourceComboBox
+                  endpointId={SystemRepository.Plant.qry}
+                  name='plantId'
+                  label={labels.plant}
+                  valueField='recordId'
+                  displayField={['reference', 'name']}
+                  columnsInDropDown={[
+                    { key: 'reference', value: 'Reference' },
+                    { key: 'name', value: 'Name' }
+                  ]}
+                  values={formik.values}
+                  onChange={(event, newValue) => {
+                    formik.setFieldValue('plantId', newValue?.recordId || 0)
+                  }}
+                  error={formik.touched.plantId && Boolean(formik.errors.plantId)}
+                  maxAccess={access}
+                />
+              </Grid>
+            </Grid>
+          </Grid>
+          <Grid item xs={3}>
+            <Grid container spacing={2}>
+              <Grid item xs={12}>
+                <ResourceLookup
+                  endpointId={SaleRepository.SalesOrder.snapshot}
+                  parameters={{
+                    _size: 30,
+                    _startAt: 0
+                  }}
+                  valueField='reference'
+                  displayField='name'
+                  name='soId'
+                  label={labels.salesOrder}
+                  form={formik}
+                  required={formik.values.type === '2' || formik.values.type === 2}
+                  valueShow='soRef'
+                  secondDisplayField={false}
+                  maxAccess={access}
+                  onChange={async (event, newValue) => {
+                    formik.setFieldValue('soId', newValue?.recordId || 0)
+                    formik.setFieldValue('soRef', newValue?.reference || '')
+                  }}
+                  errorCheck={'soId'}
+                />
+              </Grid>
+              <Grid item xs={12}>
+                <CustomTextArea
+                  name='notes'
+                  label={labels.notes}
+                  value={formik.values.notes}
+                  maxLength='100'
+                  rows={2.5}
+                  maxAccess={access}
+                  onChange={formik.handleChange}
+                  onClear={() => formik.setFieldValue('notes', '')}
+                  error={formik.touched.notes && Boolean(formik.errors.notes)}
+                />
+              </Grid>
+            </Grid>
+          </Grid>
+
+          <Grid item xs={3}>
+            <Grid container spacing={2}>
+              <Grid item xs={12}></Grid>
+              <Grid item xs={12}></Grid>
+              <Grid item xs={12}></Grid>
+              <Grid item xs={12}></Grid>
+              <Grid item xs={12}></Grid>
+              <Grid item xs={12}>
+                <CustomButton
+                  variant='contained'
+                  image={'preview.png'}
+                  label={platformLabels.Preview}
+                  onClick={() => getData()}
+                  color='#231f20'
+                />
+              </Grid>
+            </Grid>
+          </Grid>
+        </Grid>
+      </Fixed>
+      <Grow>
+        <DataGrid
+          onChange={value => formik.setFieldValue('items', value)}
+          value={formik.values.items}
+          error={formik.errors.items}
+          columns={columns}
+          name='items'
+          allowDelete={false}
+          allowAddNewLine={false}
+          maxAccess={access}
+        />
+      </Grow>
+      <Fixed>
+        <WindowToolbar smallBox={true} actions={actions} />
+      </Fixed>
+    </VertLayout>
+  )
+}
+
+export default UndeliveredItems
diff --git a/src/repositories/DeliveryRepository.js b/src/repositories/DeliveryRepository.js
index b5f82cd59b..4fbae6088a 100644
--- a/src/repositories/DeliveryRepository.js
+++ b/src/repositories/DeliveryRepository.js
@@ -54,6 +54,7 @@ export const DeliveryRepository = {
     get: service + 'getORD',
     snapshot: service + 'snapshotORD',
     unpost: service + 'unpostORD',
+    gen: service + 'genORD',
     post: service + 'postORD',
     del: service + 'delORD',
     cancel: service + 'cancelORD',
diff --git a/src/repositories/RGSaleRepository.js b/src/repositories/RGSaleRepository.js
new file mode 100644
index 0000000000..8d6113f2f2
--- /dev/null
+++ b/src/repositories/RGSaleRepository.js
@@ -0,0 +1,7 @@
+const service = 'RG.SA.asmx/'
+
+export const RGSaleRepository = {
+  SaSaleOrder: {
+    open: service + 'openSO'
+  }
+}
diff --git a/src/resources/ResourceIds.js b/src/resources/ResourceIds.js
index bcfd779708..373de8c8e1 100644
--- a/src/resources/ResourceIds.js
+++ b/src/resources/ResourceIds.js
@@ -365,6 +365,7 @@ export const ResourceIds = {
   WaxDocTypeDefaults: 42601,
   JobWaxInquiry: 47313,
   PostDraftSerials: 51315,
+  UndeliveredItems: 52304,
   AvailabilitiesCrossTab: 41227,
   Collections: 41119,
   Designer: 48100,


Reviews:
user: login: imtithalhalalo
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-01T08:17:56Z
user: login: omarZrayka23
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-01T13:21:40Z
user: login: imtithalhalalo
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-04T10:38:17Z

Review comments:
diff_hunk: @@ -0,0 +1,452 @@
+import { useContext, useEffect } from 'react'
+import toast from 'react-hot-toast'
+import { RequestsContext } from 'src/providers/RequestsContext'
+import { useResourceQuery } from 'src/hooks/resource'
+import { ResourceIds } from 'src/resources/ResourceIds'
+import { VertLayout } from 'src/components/Shared/Layouts/VertLayout'
+import { Fixed } from 'src/components/Shared/Layouts/Fixed'
+import { Grow } from 'src/components/Shared/Layouts/Grow'
+import { ControlContext } from 'src/providers/ControlContext'
+import { InventoryRepository } from 'src/repositories/InventoryRepository'
+import { Grid } from '@mui/material'
+import { ResourceLookup } from 'src/components/Shared/ResourceLookup'
+import { useForm } from 'src/hooks/form'
+import { SystemRepository } from 'src/repositories/SystemRepository'
+import { SaleRepository } from 'src/repositories/SaleRepository'
+import ResourceComboBox from 'src/components/Shared/ResourceComboBox'
+import { SystemFunction } from 'src/resources/SystemFunction'
+import { DataGrid } from 'src/components/Shared/DataGrid'
+import { RGSaleRepository } from 'src/repositories/RGSaleRepository'
+import { formatDateFromApi } from 'src/lib/date-helper'
+import WindowToolbar from 'src/components/Shared/WindowToolbar'
+import { DeliveryRepository } from 'src/repositories/DeliveryRepository'
+import CustomButton from 'src/components/Inputs/CustomButton'
+import CustomTextArea from 'src/components/Inputs/CustomTextArea'
+import { useWindow } from 'src/windows'
+import DeliveriesOrdersForm from '../delivery-orders/Forms/DeliveryOrdersForm'
+
+const UndeliveredItems = () => {
+  const { getRequest, postRequest } = useContext(RequestsContext)
+  const { platformLabels, defaultsData } = useContext(ControlContext)
+  const { stack } = useWindow()
+
+  const { labels, access } = useResourceQuery({
+    datasetId: ResourceIds.UndeliveredItems
+  })
+
+  const { labels: _labels, access: maxAccess } = useResourceQuery({
+    datasetId: ResourceIds.DeliveriesOrders
+  })
+
+  const defaultVat = defaultsData?.list?.find(({ key }) => key === 'DEORDMaxVarPct')
+
+  const { formik } = useForm({
+    maxAccess: access,
+    initialValues: {
+      recordId: null,
+      dtId: null,
+      groupId: 0,
+      plantId: 0,
+      siteId: 0,
+      categoryId: 0,
+      clientId: 0,
path: src/pages/undelivered-items/index.js
user: login: imtithalhalalo
body: why are these defaults zeros?
created_at: 2025-04-01T07:44:22Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,452 @@
+import { useContext, useEffect } from 'react'
+import toast from 'react-hot-toast'
+import { RequestsContext } from 'src/providers/RequestsContext'
+import { useResourceQuery } from 'src/hooks/resource'
+import { ResourceIds } from 'src/resources/ResourceIds'
+import { VertLayout } from 'src/components/Shared/Layouts/VertLayout'
+import { Fixed } from 'src/components/Shared/Layouts/Fixed'
+import { Grow } from 'src/components/Shared/Layouts/Grow'
+import { ControlContext } from 'src/providers/ControlContext'
+import { InventoryRepository } from 'src/repositories/InventoryRepository'
+import { Grid } from '@mui/material'
+import { ResourceLookup } from 'src/components/Shared/ResourceLookup'
+import { useForm } from 'src/hooks/form'
+import { SystemRepository } from 'src/repositories/SystemRepository'
+import { SaleRepository } from 'src/repositories/SaleRepository'
+import ResourceComboBox from 'src/components/Shared/ResourceComboBox'
+import { SystemFunction } from 'src/resources/SystemFunction'
+import { DataGrid } from 'src/components/Shared/DataGrid'
+import { RGSaleRepository } from 'src/repositories/RGSaleRepository'
+import { formatDateFromApi } from 'src/lib/date-helper'
+import WindowToolbar from 'src/components/Shared/WindowToolbar'
+import { DeliveryRepository } from 'src/repositories/DeliveryRepository'
+import CustomButton from 'src/components/Inputs/CustomButton'
+import CustomTextArea from 'src/components/Inputs/CustomTextArea'
+import { useWindow } from 'src/windows'
+import DeliveriesOrdersForm from '../delivery-orders/Forms/DeliveryOrdersForm'
+
+const UndeliveredItems = () => {
+  const { getRequest, postRequest } = useContext(RequestsContext)
+  const { platformLabels, defaultsData } = useContext(ControlContext)
+  const { stack } = useWindow()
+
+  const { labels, access } = useResourceQuery({
+    datasetId: ResourceIds.UndeliveredItems
+  })
+
+  const { labels: _labels, access: maxAccess } = useResourceQuery({
+    datasetId: ResourceIds.DeliveriesOrders
+  })
+
+  const defaultVat = defaultsData?.list?.find(({ key }) => key === 'DEORDMaxVarPct')
+
+  const { formik } = useForm({
+    maxAccess: access,
+    initialValues: {
+      recordId: null,
+      dtId: null,
+      groupId: 0,
+      plantId: 0,
+      siteId: 0,
+      categoryId: 0,
+      clientId: 0,
+      clientRef: '',
+      clientName: '',
+      soId: 0,
+      items: [],
+      marginDefault: defaultVat?.value,
+      notes: ''
+    },
+    validateOnChange: true,
+    onSubmit: async obj => {
+      const { clientId, siteId, notes, items, dtId, plantId } = obj
+
+      const itemValues = items
+        .filter(item => item.isChecked)
+        .map(({ scheduledDate, functionId, id, isChecked, ...item }) => item)
+
+      postRequest({
+        extension: DeliveryRepository.DeliveriesOrders.gen,
+        record: JSON.stringify({ clientId, siteId, notes, items: itemValues })
+      }).then(res => {
+        toast.success(platformLabels.Generated)
path: src/pages/undelivered-items/index.js
user: login: imtithalhalalo
body: toast might be shown after the form is opened
created_at: 2025-04-01T07:45:38Z
author_association: COLLABORATOR
diff_hunk: @@ -105,317 +105,321 @@ export default function FormShell({
     }
   }, [loading, editMode])
 
-  actions?.filter(Boolean)?.forEach(action => {
-    if (typeof action?.onClick !== 'function') {
-      switch (action?.onClick) {
-        case 'onRecordRemarks':
-          action.onClick = () => {
-            stack({
-              Component: ResourceRecordRemarks,
-              props: {
-                recordId: form.values?.recordId,
-                resourceId: resourceId
-              },
-              width: 800,
-              height: 500,
-              title: platformLabels.ResourceRecordRemarks
-            })
-          }
-          break
-        case 'onApproval':
-          action.onClick = () => {
-            stack({
-              Component: Approvals,
-              props: {
-                recordId: form.values.remittanceRecordId ?? form.values.recordId,
-                functionId: form.values.functionId ?? functionId
-              },
-              width: 1000,
-              height: 500,
-              title: platformLabels.Approvals
-            })
-          }
-          break
-        case 'transactionClicked':
-          action.onClick = () => {
-            stack({
-              Component: CashTransaction,
-              props: {
-                recordId: form.values?.recordId,
-                functionId: functionId
-              },
-              width: 1200,
-              height: 670,
-              title: platformLabels.CashTransaction
-            })
-          }
-          break
-        case 'onClientSalesTransaction':
-          action.onClick = () => {
-            stack({
-              Component: ClientSalesTransaction,
-              props: {
-                functionId: functionId,
-                clientId: form?.values?.header?.clientId
-              },
-              width: 600,
-              height: 450,
-              title: platformLabels.ClientSalesTransaction
-            })
-          }
+  useEffect(() => {
path: src/components/Shared/FormShell.js
user: login: imtithalhalalo
body: why did you return the useEffect?
created_at: 2025-04-01T08:16:43Z
author_association: COLLABORATOR
diff_hunk: @@ -555,6 +546,31 @@ export function DataGrid({
       sortable: false,
       cellRenderer: CustomCellRenderer,
       cellEditor: CustomCellEditor,
+      ...(column?.checkAll?.visible && {
+        headerComponent: params => {
+          const selectAll = e => {
+            if (column?.checkAll?.onChange) {
+              column?.checkAll?.onChange({ checked: e.target?.checked })
+            }
+          }
+
+          return (
+            <Grid container justifyContent='center' alignItems='center'>
+              <Checkbox
path: src/components/Shared/DataGrid/index.js
user: login: imtithalhalalo
body: you cannot use custom checkbox here?
created_at: 2025-04-01T08:17:19Z
author_association: COLLABORATOR
diff_hunk: @@ -0,0 +1,452 @@
+import { useContext, useEffect } from 'react'
+import toast from 'react-hot-toast'
+import { RequestsContext } from 'src/providers/RequestsContext'
+import { useResourceQuery } from 'src/hooks/resource'
+import { ResourceIds } from 'src/resources/ResourceIds'
+import { VertLayout } from 'src/components/Shared/Layouts/VertLayout'
+import { Fixed } from 'src/components/Shared/Layouts/Fixed'
+import { Grow } from 'src/components/Shared/Layouts/Grow'
+import { ControlContext } from 'src/providers/ControlContext'
+import { InventoryRepository } from 'src/repositories/InventoryRepository'
+import { Grid } from '@mui/material'
+import { ResourceLookup } from 'src/components/Shared/ResourceLookup'
+import { useForm } from 'src/hooks/form'
+import { SystemRepository } from 'src/repositories/SystemRepository'
+import { SaleRepository } from 'src/repositories/SaleRepository'
+import ResourceComboBox from 'src/components/Shared/ResourceComboBox'
+import { SystemFunction } from 'src/resources/SystemFunction'
+import { DataGrid } from 'src/components/Shared/DataGrid'
+import { RGSaleRepository } from 'src/repositories/RGSaleRepository'
+import { formatDateFromApi } from 'src/lib/date-helper'
+import WindowToolbar from 'src/components/Shared/WindowToolbar'
+import { DeliveryRepository } from 'src/repositories/DeliveryRepository'
+import CustomButton from 'src/components/Inputs/CustomButton'
+import CustomTextArea from 'src/components/Inputs/CustomTextArea'
+import { useWindow } from 'src/windows'
+import DeliveriesOrdersForm from '../delivery-orders/Forms/DeliveryOrdersForm'
+
+const UndeliveredItems = () => {
+  const { getRequest, postRequest } = useContext(RequestsContext)
+  const { platformLabels, defaultsData } = useContext(ControlContext)
+  const { stack } = useWindow()
+
+  const { labels, access } = useResourceQuery({
+    datasetId: ResourceIds.UndeliveredItems
+  })
+
+  const { labels: _labels, access: maxAccess } = useResourceQuery({
+    datasetId: ResourceIds.DeliveriesOrders
+  })
+
+  const defaultVat = defaultsData?.list?.find(({ key }) => key === 'DEORDMaxVarPct')
+
+  const { formik } = useForm({
+    maxAccess: access,
+    initialValues: {
+      recordId: null,
+      dtId: null,
+      groupId: 0,
+      plantId: 0,
+      siteId: 0,
+      categoryId: 0,
+      clientId: 0,
path: src/pages/undelivered-items/index.js
user: login: omarZrayka23
body: These are solely used for filtering, and the API requires zero if there are no values.
created_at: 2025-04-01T13:21:40Z
author_association: CONTRIBUTOR

PR comments:
user: login: vercel[bot]
created_at: 2025-03-03T08:35:34Z
body: [vc]: #ydgoPBS92qBtZGh4BYJfMgCUd33ep8eyL1pcXYmQBdE=:eyJpc01vbm9yZXBvIjp0cnVlLCJ0eXBlIjoiZ2l0aHViIiwicHJvamVjdHMiOlt7Im5hbWUiOiJhcmd1cy1mZSIsImxpdmVGZWVkYmFjayI6eyJyZXNvbHZlZCI6MCwidW5yZXNvbHZlZCI6MCwidG90YWwiOjAsImxpbmsiOiJhcmd1cy1mZS1naXQtYXItMjg2NC1nZW9yZ2Uta2FsYXNocy1wcm9qZWN0cy52ZXJjZWwuYXBwIn0sImluc3BlY3RvclVybCI6Imh0dHBzOi8vdmVyY2VsLmNvbS9nZW9yZ2Uta2FsYXNocy1wcm9qZWN0cy9hcmd1cy1mZS9GNDYzMXpodUM1ZmptQlREczREdExRczFhQ0FUIiwicHJldmlld1VybCI6ImFyZ3VzLWZlLWdpdC1hci0yODY0LWdlb3JnZS1rYWxhc2hzLXByb2plY3RzLnZlcmNlbC5hcHAiLCJuZXh0Q29tbWl0U3RhdHVzIjoiREVQTE9ZRUQiLCJyb290RGlyZWN0b3J5IjpudWxsfV19
**The latest updates on your projects**. Learn more about [Vercel for Git ↗︎](https://vercel.link/github-learn-more)

| Name | Status | Preview | Comments | Updated (UTC) |
| :--- | :----- | :------ | :------- | :------ |
| **argus-fe** | ✅ Ready ([Inspect](https://vercel.com/george-kalashs-projects/argus-fe/F4631zhuC5fjmBTDs4DtLQs1aCAT)) | [Visit Preview](https://argus-fe-git-ar-2864-george-kalashs-projects.vercel.app) | 💬 [**Add feedback**](https://vercel.live/open-feedback/argus-fe-git-ar-2864-george-kalashs-projects.vercel.app?via=pr-comment-feedback-link) | Apr 4, 2025 8:22am |


author_association: NONE
user: login: imtithalhalalo
created_at: 2025-04-01T07:28:49Z
body: ![Screenshot 2025-04-01 102648](https://github.com/user-attachments/assets/1585336c-f42a-4004-9eff-ee3cce1c1fb9)
![Screenshot 2025-04-01 102748](https://github.com/user-attachments/assets/58a27689-8114-40c3-b857-61c4d11f700d) 
I am trying to change the gen. qty but in react it is returning to old one however in asp it is getting the changed number 
try to add number and click outside the cell
author_association: COLLABORATOR
user: login: imtithalhalalo
created_at: 2025-04-01T07:32:24Z
body: ![Screenshot 2025-04-01 103137](https://github.com/user-attachments/assets/b7803a68-c4a7-4bcc-a5ac-4d86d623e9f2)
![Screenshot 2025-04-01 103144](https://github.com/user-attachments/assets/3f164f80-4fcd-41c2-9e42-3cfccf07fcc0)
try to create sales person is always empty in react
author_association: COLLABORATOR
user: login: imtithalhalalo
created_at: 2025-04-02T12:24:11Z
body: ![Screenshot 2025-04-02 152343](https://github.com/user-attachments/assets/6ac427bc-80ad-4a4a-8172-4d4660c1b26e)
checkbox in the header has different padding than the rows it wasn't like that before
author_association: COLLABORATOR
user: login: imtithalhalalo
created_at: 2025-04-04T06:07:45Z
body: ![Screenshot 2025-04-04 090641](https://github.com/user-attachments/assets/94f562ec-de45-4c69-87ad-8a7471cba319)
![Screenshot 2025-04-04 090702](https://github.com/user-attachments/assets/3c4d4adf-95fd-46d6-bb41-8afa6d72224f)
same data in the header 
no data in react but it is showing in asp
author_association: COLLABORATOR
user: login: omarZrayka23
created_at: 2025-04-04T07:57:02Z
body: > ![Screenshot 2025-04-04 090641](https://private-user-images.githubusercontent.com/109606167/430247602-94f562ec-de45-4c69-87ad-8a7471cba319.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDM3NTI5NzQsIm5iZiI6MTc0Mzc1MjY3NCwicGF0aCI6Ii8xMDk2MDYxNjcvNDMwMjQ3NjAyLTk0ZjU2MmVjLWRlNDUtNGM2OS04N2FkLThhNzQ3MWNiYTMxOS5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwNDA0JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDQwNFQwNzQ0MzRaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT1lY2ZjOTNiODQ2MDdiODYyOWRlMDMzY2Q3N2Q0NTM2YmFjZjFkMTIyZjRiMTA1NzI1Zjg4NDAzZTBmMzM4MmIxJlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.og45l1tpBfRbWJZb-Y1YfogMSxaqFbemxdj0XwWa630) ![Screenshot 2025-04-04 090702](https://private-user-images.githubusercontent.com/109606167/430247656-3c4d4adf-95fd-46d6-bb41-8afa6d72224f.png?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NDM3NTI5NzQsIm5iZiI6MTc0Mzc1MjY3NCwicGF0aCI6Ii8xMDk2MDYxNjcvNDMwMjQ3NjU2LTNjNGQ0YWRmLTk1ZmQtNDZkNi1iYjQxLThhZmE2ZDcyMjI0Zi5wbmc_WC1BbXotQWxnb3JpdGhtPUFXUzQtSE1BQy1TSEEyNTYmWC1BbXotQ3JlZGVudGlhbD1BS0lBVkNPRFlMU0E1M1BRSzRaQSUyRjIwMjUwNDA0JTJGdXMtZWFzdC0xJTJGczMlMkZhd3M0X3JlcXVlc3QmWC1BbXotRGF0ZT0yMDI1MDQwNFQwNzQ0MzRaJlgtQW16LUV4cGlyZXM9MzAwJlgtQW16LVNpZ25hdHVyZT04Y2QzZWExMTAyZjZmMGRkYzI0ZDc3YmY4OTNmMWYyYjJhMDg4MzFiNzcwOWYzNDc1Y2NhYTVmY2UwYjkxOGI0JlgtQW16LVNpZ25lZEhlYWRlcnM9aG9zdCJ9.3nnWusFUhD31TzBC4grnT3SY8XTT7Sqj2vja2b3r9a0) same data in the header no data in react but it is showing in asp

But they are not the same accounts. 
author_association: CONTRIBUTOR
user: login: imtithalhalalo
created_at: 2025-04-04T07:58:00Z
body: ![Screenshot 2025-04-04 105623](https://github.com/user-attachments/assets/b8ca7365-4b3c-465a-8ce4-2b076dee1aaa)
![Screenshot 2025-04-04 105739](https://github.com/user-attachments/assets/d16bb548-e56e-4251-a67e-cc29c50ec07b)
different message same scenario
author_association: COLLABORATOR