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:
csawatzky 2025-06-04 15:20:46 -06:00
parent a083f7d8ed
commit 691b3be1f9
3 changed files with 85 additions and 26 deletions

View file

@ -34,7 +34,11 @@ export default function BinTransactions(props: Props){
const [tablePageSize, setTablePageSize] = useState(10)
const { openSnack } = useSnackbar();
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 [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 [toOption, setToOption] = useState<Option | undefined>()
//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
const [requiresMatch, setRequiresMatch] = useState(false)
//load bins
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
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)
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()
},[state, bin, loadTransactionsFor])
const closeDialog = () => {
setPossibleTransactionMatches([])
setselectedMatch(undefined)
setRequiresMatch(false)
setOpenDialog(false)
}
const submit = () => {
console.log("submitting transaction")
let transaction = cloneDeep(selectedTransaction)
if(transaction){
if(selectedMatch){
if (transaction.transaction.fromKey === ""){
transaction.transaction.fromObject = selectedMatch.transaction.fromObject
transaction.transaction.fromKey = selectedMatch.transaction.fromKey
}
if (transaction.transaction.toKey === ""){
transaction.transaction.toObject = selectedMatch.transaction.toObject
transaction.transaction.toKey = selectedMatch.transaction.toKey
}
//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
transaction.transaction.fromObject = fromType
transaction.transaction.fromKey = fromOption?.value ?? ""
transaction.transaction.toObject = toType
transaction.transaction.toKey = toOption?.value ?? ""
//need to do a check to make sure the transaction data contains a grain transaction
if(transaction.transaction.transaction && transaction.transaction.transaction.grainTransaction) {
transaction.transaction.transaction.grainTransaction.message = grainMessage
}
//submit approval
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){
transactionAPI.removeTransaction(selectedMatch.transaction.key).then(resp => {
openSnack("Updated and matched transactions")
}).catch(err => {
openSnack("Updated primary transaction but failed to remove matched transaction")
})
}else{
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 toDisabled = selectedTransaction?.transaction.toKey !== ""
return (
<ResponsiveDialog open={openDialog} onClose={()=>{setOpenDialog(false)}}>
<ResponsiveDialog open={openDialog} onClose={closeDialog}>
<DialogTitle>Accept Transaction</DialogTitle>
<DialogContent>
<Box>
@ -222,6 +239,15 @@ export default function BinTransactions(props: Props){
})
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" />}
/>
@ -262,6 +288,7 @@ export default function BinTransactions(props: Props){
getOptionLabel={(option: Option) => option.label}
fullWidth
onChange={(_, val) => {
setToOption(val ?? undefined)
//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 => {
let matches: Transaction[] = []
@ -273,14 +300,33 @@ export default function BinTransactions(props: Props){
})
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" />}
/>
</Box>
<Box>
<TextField
label="Message(optional)"
margin="dense"
fullWidth
variant="outlined"
value={grainMessage}
onChange={e => setGrainMessage(e.target.value)}
/>
</Box>
{toOption &&
<Box paddingTop={1}>
<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 => {
// get the display information for the transaction
const grainTransaction = t.transaction.transaction?.grainTransaction ?? pond.GrainTransaction.create()
@ -291,7 +337,7 @@ export default function BinTransactions(props: Props){
? grainTransaction.customGrain
: GrainDescriber(grainTransaction.grainType).name
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}>
<Typography sx={{fontWeight: 650, margin: "auto", marginLeft: 0}}>
{moment(t.transaction.timestamp).fromNow()}
@ -316,11 +362,22 @@ export default function BinTransactions(props: Props){
)
})}
</Box>
}
</DialogContent>
<DialogActions>
<Button variant="contained">Close</Button>
<Button variant="contained" color="error">Reject</Button>
<Button variant="contained" color="primary">Approve</Button>
<Button variant="contained" onClick={closeDialog}>Close</Button>
<Button variant="contained" color="error" onClick={closeDialog}>Reject</Button>
<Button
variant="contained"
disabled={requiresMatch && selectedMatch === undefined}
color="primary"
onClick={() => {
submit()
closeDialog()
//re-load bin
}}>
Approve
</Button>
</DialogActions>
</ResponsiveDialog>
)