approval of transactions works, is also now requires a matching transaction if the bin selected also uses hybrid control, rejection still needs to be implemented
This commit is contained in:
parent
a083f7d8ed
commit
691b3be1f9
3 changed files with 85 additions and 26 deletions
|
|
@ -712,6 +712,8 @@ export default function BinSettings(props: Props) {
|
||||||
return "Auto (lidar)"
|
return "Auto (lidar)"
|
||||||
case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC:
|
case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_AUTOMATIC:
|
||||||
return "Auto (cable)"
|
return "Auto (cable)"
|
||||||
|
case pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR:
|
||||||
|
return "Hybrid (lidar)"
|
||||||
default:
|
default:
|
||||||
return "Manual"
|
return "Manual"
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,11 @@ export default function BinTransactions(props: Props){
|
||||||
const [tablePageSize, setTablePageSize] = useState(10)
|
const [tablePageSize, setTablePageSize] = useState(10)
|
||||||
const { openSnack } = useSnackbar();
|
const { openSnack } = useSnackbar();
|
||||||
const [total, setTotal] = useState(0)
|
const [total, setTotal] = useState(0)
|
||||||
|
const [grainMessage, setGrainMessage] = useState("")
|
||||||
|
|
||||||
|
//only need to do this for the bins since if a bin is picked for the secondary we need to check its inventory control type,
|
||||||
|
//if it is also hybrid a matching transaction must be selected
|
||||||
|
const [bins, setBins] = useState<Map<string, Bin>>(new Map())
|
||||||
const [binOptions, setBinOptions] = useState<Option[]>([])
|
const [binOptions, setBinOptions] = useState<Option[]>([])
|
||||||
|
|
||||||
const [grainBagOptions, setGrainBagOptions] = useState<Option[]>([])
|
const [grainBagOptions, setGrainBagOptions] = useState<Option[]>([])
|
||||||
|
|
@ -53,18 +57,21 @@ export default function BinTransactions(props: Props){
|
||||||
|
|
||||||
const [toType, setToType] = useState<pond.ObjectType>(pond.ObjectType.OBJECT_TYPE_UNKNOWN)
|
const [toType, setToType] = useState<pond.ObjectType>(pond.ObjectType.OBJECT_TYPE_UNKNOWN)
|
||||||
const [toOption, setToOption] = useState<Option | undefined>()
|
const [toOption, setToOption] = useState<Option | undefined>()
|
||||||
|
const [requiresMatch, setRequiresMatch] = useState(false)
|
||||||
//the following object loads are loading the objects for options when editing transactions to accept as well as build the name map for display
|
|
||||||
//these only happen when going to the transactions tab on the bin page
|
|
||||||
|
|
||||||
//load bins
|
//load bins
|
||||||
const loadBins = ()=>{
|
const loadBins = ()=>{
|
||||||
//limit of 0 will load them all but this load will only happen once regardless of how many times the dropdown for type is changed
|
//limit of 0 will load them all but this load will only happen once regardless of how many times the dropdown for type is changed
|
||||||
binAPI.listBins(0, 0, "asc", "name").then(resp => {
|
binAPI.listBins(0, 0, "asc", "name").then(resp => {
|
||||||
setBinOptions(resp.data.bins.map(b => {
|
let options: Option[] = []
|
||||||
|
let binMap: Map<string, Bin> = new Map()
|
||||||
|
resp.data.bins.map(b => {
|
||||||
let bin = Bin.create(b)
|
let bin = Bin.create(b)
|
||||||
return {label: bin.name(), value: bin.key()}
|
options.push({label: bin.name(), value: bin.key()})
|
||||||
}))
|
binMap.set(bin.key(), bin)
|
||||||
|
})
|
||||||
|
setBinOptions(options)
|
||||||
|
setBins(binMap)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -107,31 +114,41 @@ export default function BinTransactions(props: Props){
|
||||||
loadTransactionsFor()
|
loadTransactionsFor()
|
||||||
},[state, bin, loadTransactionsFor])
|
},[state, bin, loadTransactionsFor])
|
||||||
|
|
||||||
|
const closeDialog = () => {
|
||||||
|
setPossibleTransactionMatches([])
|
||||||
|
setselectedMatch(undefined)
|
||||||
|
setRequiresMatch(false)
|
||||||
|
setOpenDialog(false)
|
||||||
|
}
|
||||||
|
|
||||||
const submit = () => {
|
const submit = () => {
|
||||||
|
console.log("submitting transaction")
|
||||||
let transaction = cloneDeep(selectedTransaction)
|
let transaction = cloneDeep(selectedTransaction)
|
||||||
if(transaction){
|
if(transaction){
|
||||||
if(selectedMatch){
|
//use the dropdowns to update the from/to for the transaction, meaning if the user added another object it will adjust its inventory as well
|
||||||
if (transaction.transaction.fromKey === ""){
|
transaction.transaction.fromObject = fromType
|
||||||
transaction.transaction.fromObject = selectedMatch.transaction.fromObject
|
transaction.transaction.fromKey = fromOption?.value ?? ""
|
||||||
transaction.transaction.fromKey = selectedMatch.transaction.fromKey
|
transaction.transaction.toObject = toType
|
||||||
}
|
transaction.transaction.toKey = toOption?.value ?? ""
|
||||||
if (transaction.transaction.toKey === ""){
|
//need to do a check to make sure the transaction data contains a grain transaction
|
||||||
transaction.transaction.toObject = selectedMatch.transaction.toObject
|
if(transaction.transaction.transaction && transaction.transaction.transaction.grainTransaction) {
|
||||||
transaction.transaction.toKey = selectedMatch.transaction.toKey
|
transaction.transaction.transaction.grainTransaction.message = grainMessage
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//submit approval
|
//submit approval
|
||||||
transactionAPI.submitApproval(transaction.transaction.key, true, transaction.transaction).then(resp => {
|
transactionAPI.submitApproval(transaction.transaction.key, true, transaction.transaction).then(resp => {
|
||||||
//in the response if it succeeded remove (not reject but fully delete it) the matched transaction
|
//in the response if it succeeded remove (not reject but fully delete it) the matched transaction if one was selected
|
||||||
if(selectedMatch){
|
if(selectedMatch){
|
||||||
transactionAPI.removeTransaction(selectedMatch.transaction.key).then(resp => {
|
transactionAPI.removeTransaction(selectedMatch.transaction.key).then(resp => {
|
||||||
openSnack("Updated and matched transactions")
|
openSnack("Updated and matched transactions")
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
|
openSnack("Updated primary transaction but failed to remove matched transaction")
|
||||||
})
|
})
|
||||||
}else{
|
}else{
|
||||||
openSnack("Updated Transaction")
|
openSnack("Updated Transaction")
|
||||||
}
|
}
|
||||||
|
}).catch(err => {
|
||||||
|
openSnack("There was a problem submitting transaction approval")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -166,7 +183,7 @@ export default function BinTransactions(props: Props){
|
||||||
let fromDisabled = selectedTransaction?.transaction.fromKey !== ""
|
let fromDisabled = selectedTransaction?.transaction.fromKey !== ""
|
||||||
let toDisabled = selectedTransaction?.transaction.toKey !== ""
|
let toDisabled = selectedTransaction?.transaction.toKey !== ""
|
||||||
return (
|
return (
|
||||||
<ResponsiveDialog open={openDialog} onClose={()=>{setOpenDialog(false)}}>
|
<ResponsiveDialog open={openDialog} onClose={closeDialog}>
|
||||||
<DialogTitle>Accept Transaction</DialogTitle>
|
<DialogTitle>Accept Transaction</DialogTitle>
|
||||||
<DialogContent>
|
<DialogContent>
|
||||||
<Box>
|
<Box>
|
||||||
|
|
@ -222,6 +239,15 @@ export default function BinTransactions(props: Props){
|
||||||
})
|
})
|
||||||
setPossibleTransactionMatches(matches)
|
setPossibleTransactionMatches(matches)
|
||||||
})
|
})
|
||||||
|
//if the options are bin types check if the selected bin uses hybrid controls
|
||||||
|
if(fromType === pond.ObjectType.OBJECT_TYPE_BIN && val){
|
||||||
|
let bin = bins.get(val.value)
|
||||||
|
if(bin){
|
||||||
|
setRequiresMatch(
|
||||||
|
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR ||
|
||||||
|
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_CABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
renderInput={params => <TextField {...params} label="From" />}
|
renderInput={params => <TextField {...params} label="From" />}
|
||||||
/>
|
/>
|
||||||
|
|
@ -262,6 +288,7 @@ export default function BinTransactions(props: Props){
|
||||||
getOptionLabel={(option: Option) => option.label}
|
getOptionLabel={(option: Option) => option.label}
|
||||||
fullWidth
|
fullWidth
|
||||||
onChange={(_, val) => {
|
onChange={(_, val) => {
|
||||||
|
setToOption(val ?? undefined)
|
||||||
//once one is selected get the transactions for it that are requiring approval
|
//once one is selected get the transactions for it that are requiring approval
|
||||||
transactionAPI.listTransactionsFor(0, 0, "asc", val?.value, pond.TransactionState.TRANSACTION_STATE_APPROVAL_REQUIRED).then(resp => {
|
transactionAPI.listTransactionsFor(0, 0, "asc", val?.value, pond.TransactionState.TRANSACTION_STATE_APPROVAL_REQUIRED).then(resp => {
|
||||||
let matches: Transaction[] = []
|
let matches: Transaction[] = []
|
||||||
|
|
@ -273,14 +300,33 @@ export default function BinTransactions(props: Props){
|
||||||
})
|
})
|
||||||
setPossibleTransactionMatches(matches)
|
setPossibleTransactionMatches(matches)
|
||||||
})
|
})
|
||||||
|
//if the options are bin types check if the selected bin uses hybrid controls
|
||||||
|
if(fromType === pond.ObjectType.OBJECT_TYPE_BIN && val){
|
||||||
|
let bin = bins.get(val.value)
|
||||||
|
if(bin){
|
||||||
|
setRequiresMatch(
|
||||||
|
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_LIDAR ||
|
||||||
|
bin.inventoryControl() === pond.BinInventoryControl.BIN_INVENTORY_CONTROL_HYBRID_CABLE)
|
||||||
|
}
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
renderInput={params => <TextField {...params} label="From" />}
|
renderInput={params => <TextField {...params} label="From" />}
|
||||||
/>
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box>
|
||||||
|
<TextField
|
||||||
|
label="Message(optional)"
|
||||||
|
margin="dense"
|
||||||
|
fullWidth
|
||||||
|
variant="outlined"
|
||||||
|
value={grainMessage}
|
||||||
|
onChange={e => setGrainMessage(e.target.value)}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
{toOption &&
|
||||||
<Box paddingTop={1}>
|
<Box paddingTop={1}>
|
||||||
<Typography variant="h6">Possible matching Transactions</Typography>
|
<Typography variant="h6">Possible matching Transactions</Typography>
|
||||||
<Typography>Pick a transaction below if you want to match them together</Typography>
|
<Typography>{possibleTransactionMatches.length > 0 ? "Pick a transaction below if you want to match them together" : "No matching transactions found"}</Typography>
|
||||||
{possibleTransactionMatches.map(t => {
|
{possibleTransactionMatches.map(t => {
|
||||||
// get the display information for the transaction
|
// get the display information for the transaction
|
||||||
const grainTransaction = t.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
const grainTransaction = t.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
|
||||||
|
|
@ -291,7 +337,7 @@ export default function BinTransactions(props: Props){
|
||||||
? grainTransaction.customGrain
|
? grainTransaction.customGrain
|
||||||
: GrainDescriber(grainTransaction.grainType).name
|
: GrainDescriber(grainTransaction.grainType).name
|
||||||
return (
|
return (
|
||||||
<Card sx={{marginTop: 1, padding: 1}}>
|
<Card sx={{marginTop: 1, padding: 1}} key={t.transaction.key}>
|
||||||
<Box display="flex" justifyContent="space-between" height={40}>
|
<Box display="flex" justifyContent="space-between" height={40}>
|
||||||
<Typography sx={{fontWeight: 650, margin: "auto", marginLeft: 0}}>
|
<Typography sx={{fontWeight: 650, margin: "auto", marginLeft: 0}}>
|
||||||
{moment(t.transaction.timestamp).fromNow()}
|
{moment(t.transaction.timestamp).fromNow()}
|
||||||
|
|
@ -316,11 +362,22 @@ export default function BinTransactions(props: Props){
|
||||||
)
|
)
|
||||||
})}
|
})}
|
||||||
</Box>
|
</Box>
|
||||||
|
}
|
||||||
</DialogContent>
|
</DialogContent>
|
||||||
<DialogActions>
|
<DialogActions>
|
||||||
<Button variant="contained">Close</Button>
|
<Button variant="contained" onClick={closeDialog}>Close</Button>
|
||||||
<Button variant="contained" color="error">Reject</Button>
|
<Button variant="contained" color="error" onClick={closeDialog}>Reject</Button>
|
||||||
<Button variant="contained" color="primary">Approve</Button>
|
<Button
|
||||||
|
variant="contained"
|
||||||
|
disabled={requiresMatch && selectedMatch === undefined}
|
||||||
|
color="primary"
|
||||||
|
onClick={() => {
|
||||||
|
submit()
|
||||||
|
closeDialog()
|
||||||
|
//re-load bin
|
||||||
|
}}>
|
||||||
|
Approve
|
||||||
|
</Button>
|
||||||
</DialogActions>
|
</DialogActions>
|
||||||
</ResponsiveDialog>
|
</ResponsiveDialog>
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -166,7 +166,7 @@ export default function TransactionProvider(props: PropsWithChildren<Props>) {
|
||||||
if(view){
|
if(view){
|
||||||
url = url + "&as=" + view
|
url = url + "&as=" + view
|
||||||
}
|
}
|
||||||
return post<pond.SubmitTransactionApprovalResponse>(url, updatedData)
|
return post<pond.SubmitTransactionApprovalResponse>(pondURL(url), updatedData)
|
||||||
}
|
}
|
||||||
|
|
||||||
const removeTransaction = (key: string, otherTeam?: string) => {
|
const removeTransaction = (key: string, otherTeam?: string) => {
|
||||||
|
|
@ -175,7 +175,7 @@ export default function TransactionProvider(props: PropsWithChildren<Props>) {
|
||||||
if(view){
|
if(view){
|
||||||
url = url + "&as=" + view
|
url = url + "&as=" + view
|
||||||
}
|
}
|
||||||
return del<pond.RemoveTransactionResponse>(url)
|
return del<pond.RemoveTransactionResponse>(pondURL(url))
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue