feat: simplified tx exports
This commit is contained in:
parent
2f6aac8f6d
commit
5826a29c53
4 changed files with 102 additions and 12 deletions
|
|
@ -302,6 +302,7 @@ const typeDefs = gql`
|
||||||
deviceId: ID
|
deviceId: ID
|
||||||
): [Transaction]
|
): [Transaction]
|
||||||
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int): String
|
transactionsCsv(from: Date, until: Date, limit: Int, offset: Int): String
|
||||||
|
simplifiedTransactionsCsv(from: Date, until: Date, limit: Int, offset: Int): String
|
||||||
accounts: JSONObject
|
accounts: JSONObject
|
||||||
config: JSONObject
|
config: JSONObject
|
||||||
blacklist: [Blacklist]
|
blacklist: [Blacklist]
|
||||||
|
|
@ -399,6 +400,8 @@ const resolvers = {
|
||||||
transactions.batch(from, until, limit, offset, deviceId),
|
transactions.batch(from, until, limit, offset, deviceId),
|
||||||
transactionsCsv: (...[, { from, until, limit, offset }]) =>
|
transactionsCsv: (...[, { from, until, limit, offset }]) =>
|
||||||
transactions.batch(from, until, limit, offset).then(parseAsync),
|
transactions.batch(from, until, limit, offset).then(parseAsync),
|
||||||
|
simplifiedTransactionsCsv: (...[, { from, until, limit, offset }]) =>
|
||||||
|
transactions.simplifiedBatch(from, until, limit, offset).then(parseAsync),
|
||||||
config: () => settingsLoader.loadLatestConfigOrNone(),
|
config: () => settingsLoader.loadLatestConfigOrNone(),
|
||||||
accounts: () => settingsLoader.showAccounts(),
|
accounts: () => settingsLoader.showAccounts(),
|
||||||
blacklist: () => blacklist.getBlacklist(),
|
blacklist: () => blacklist.getBlacklist(),
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,8 @@ const machineLoader = require('../machine-loader')
|
||||||
const tx = require('../tx')
|
const tx = require('../tx')
|
||||||
const cashInTx = require('../cash-in/cash-in-tx')
|
const cashInTx = require('../cash-in/cash-in-tx')
|
||||||
const { REDEEMABLE_AGE } = require('../cash-out/cash-out-helper')
|
const { REDEEMABLE_AGE } = require('../cash-out/cash-out-helper')
|
||||||
|
const coinUtils = require('../coin-utils')
|
||||||
|
const BN = require('../bn')
|
||||||
|
|
||||||
const NUM_RESULTS = 1000
|
const NUM_RESULTS = 1000
|
||||||
|
|
||||||
|
|
@ -76,6 +78,46 @@ function batch (from = new Date(0).toISOString(), until = new Date().toISOString
|
||||||
]).then(packager)
|
]).then(packager)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function simplifiedBatch (from = new Date(0).toISOString(), until = new Date().toISOString(), limit = null, offset = 0) {
|
||||||
|
return batch(from, until, limit, offset)
|
||||||
|
.then(res => {
|
||||||
|
const fields = ['txClass', 'id', 'created', 'machineName',
|
||||||
|
'cryptoCode', 'fiat', 'fiatCode', 'phone', 'toAddress',
|
||||||
|
'txHash', 'dispense', 'error', 'status', 'fiatProfit', 'cryptoAmount']
|
||||||
|
return _.map(_.compose(_.pick(fields), getStatus, getProfit, getCryptoAmount))(res)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCryptoAmount = it => { return { ...it, cryptoAmount: coinUtils.toUnit(BN(it.cryptoAtoms), it.cryptoCode).toString() } }
|
||||||
|
|
||||||
|
const getProfit = it => {
|
||||||
|
const getCommissionFee = it => Number.parseFloat(it.commissionPercentage) * Number.parseFloat(it.fiat)
|
||||||
|
if (!it.cashInFee) return { ...it, fiatProfit: getCommissionFee(it) }
|
||||||
|
return { ...it, fiatProfit: getCommissionFee(it) + Number.parseFloat(it.cashInFee) }
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCashOutStatus = it => {
|
||||||
|
if (it.hasError) return { ...it, status: 'Error' }
|
||||||
|
if (it.dispense) return { ...it, status: 'Success' }
|
||||||
|
if (it.expired) return { ...it, status: 'Expired' }
|
||||||
|
return { ...it, status: 'Pending' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCashInStatus = it => {
|
||||||
|
if (it.operatorCompleted) return { ...it, status: 'Cancelled' }
|
||||||
|
if (it.hasError) return { ...it, status: 'Error' }
|
||||||
|
if (it.sendConfirmed) return { ...it, status: 'Sent' }
|
||||||
|
if (it.expired) return { ...it, status: 'Expired' }
|
||||||
|
return { ...it, status: 'Pending' }
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatus = it => {
|
||||||
|
if (it.txClass === 'cashOut') {
|
||||||
|
return getCashOutStatus(it)
|
||||||
|
}
|
||||||
|
return getCashInStatus(it)
|
||||||
|
}
|
||||||
|
|
||||||
function getCustomerTransactionsBatch (ids) {
|
function getCustomerTransactionsBatch (ids) {
|
||||||
const packager = _.flow(it => {
|
const packager = _.flow(it => {
|
||||||
return it
|
return it
|
||||||
|
|
@ -168,4 +210,4 @@ function cancel (txId) {
|
||||||
.then(() => single(txId))
|
.then(() => single(txId))
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { batch, single, cancel, getCustomerTransactionsBatch }
|
module.exports = { simplifiedBatch, batch, single, cancel, getCustomerTransactionsBatch }
|
||||||
|
|
|
||||||
|
|
@ -128,15 +128,30 @@ const styles = {
|
||||||
const useStyles = makeStyles(styles)
|
const useStyles = makeStyles(styles)
|
||||||
const ALL = 'all'
|
const ALL = 'all'
|
||||||
const RANGE = 'range'
|
const RANGE = 'range'
|
||||||
|
const ADVANCED = 'advanced'
|
||||||
|
const SIMPLIFIED = 'simplified'
|
||||||
|
|
||||||
const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
const LogsDownloaderPopover = ({
|
||||||
|
name,
|
||||||
|
queries,
|
||||||
|
args,
|
||||||
|
title,
|
||||||
|
getLogs,
|
||||||
|
getSimplifiedLogs
|
||||||
|
}) => {
|
||||||
const [selectedRadio, setSelectedRadio] = useState(ALL)
|
const [selectedRadio, setSelectedRadio] = useState(ALL)
|
||||||
|
const [selectedAdvancedRadio, setSelectedAdvancedRadio] = useState(ADVANCED)
|
||||||
|
|
||||||
const [range, setRange] = useState({ from: null, until: null })
|
const [range, setRange] = useState({ from: null, until: null })
|
||||||
const [anchorEl, setAnchorEl] = useState(null)
|
const [anchorEl, setAnchorEl] = useState(null)
|
||||||
const [fetchLogs] = useLazyQuery(query, {
|
const [fetchLogs] = useLazyQuery(queries[0], {
|
||||||
onCompleted: data => createLogsFile(getLogs(data), range)
|
onCompleted: data => createLogsFile(getLogs(data), range)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const [fetchSimplifiedLogs] = useLazyQuery(queries[1], {
|
||||||
|
onCompleted: data => createLogsFile(getSimplifiedLogs(data), range)
|
||||||
|
})
|
||||||
|
|
||||||
const classes = useStyles()
|
const classes = useStyles()
|
||||||
|
|
||||||
const dateRangePickerClasses = {
|
const dateRangePickerClasses = {
|
||||||
|
|
@ -150,6 +165,12 @@ const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
||||||
if (selectedRadio === ALL) setRange({ from: null, until: null })
|
if (selectedRadio === ALL) setRange({ from: null, until: null })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const handleAdvancedRadioButtons = evt => {
|
||||||
|
const selectedAdvancedRadio = R.path(['target', 'value'])(evt)
|
||||||
|
setSelectedAdvancedRadio(selectedAdvancedRadio)
|
||||||
|
if (selectedAdvancedRadio === ALL) setRange({ from: null, until: null })
|
||||||
|
}
|
||||||
|
|
||||||
const handleRangeChange = useCallback(
|
const handleRangeChange = useCallback(
|
||||||
(from, until) => {
|
(from, until) => {
|
||||||
setRange({ from, until })
|
setRange({ from, until })
|
||||||
|
|
@ -157,9 +178,11 @@ const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
||||||
[setRange]
|
[setRange]
|
||||||
)
|
)
|
||||||
|
|
||||||
const downloadLogs = (range, args, fetchLogs) => {
|
const downloadLogs = (range, args) => {
|
||||||
|
const fetch =
|
||||||
|
selectedAdvancedRadio === SIMPLIFIED ? fetchSimplifiedLogs : fetchLogs
|
||||||
if (selectedRadio === ALL) {
|
if (selectedRadio === ALL) {
|
||||||
fetchLogs({
|
fetch({
|
||||||
variables: {
|
variables: {
|
||||||
...args
|
...args
|
||||||
}
|
}
|
||||||
|
|
@ -170,7 +193,7 @@ const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
||||||
if (range.from && !range.until) range.until = moment()
|
if (range.from && !range.until) range.until = moment()
|
||||||
|
|
||||||
if (selectedRadio === RANGE) {
|
if (selectedRadio === RANGE) {
|
||||||
fetchLogs({
|
fetch({
|
||||||
variables: {
|
variables: {
|
||||||
...args,
|
...args,
|
||||||
from: range.from,
|
from: range.from,
|
||||||
|
|
@ -209,7 +232,9 @@ const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
||||||
|
|
||||||
const radioButtonOptions = [
|
const radioButtonOptions = [
|
||||||
{ display: 'All logs', code: ALL },
|
{ display: 'All logs', code: ALL },
|
||||||
{ display: 'Date range', code: RANGE }
|
{ display: 'Date range', code: RANGE },
|
||||||
|
{ display: 'Advanced logs', code: ADVANCED },
|
||||||
|
{ display: 'Simplified logs', code: SIMPLIFIED }
|
||||||
]
|
]
|
||||||
|
|
||||||
const open = Boolean(anchorEl)
|
const open = Boolean(anchorEl)
|
||||||
|
|
@ -231,7 +256,7 @@ const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
||||||
<RadioGroup
|
<RadioGroup
|
||||||
name="logs-select"
|
name="logs-select"
|
||||||
value={selectedRadio}
|
value={selectedRadio}
|
||||||
options={radioButtonOptions}
|
options={radioButtonOptions.slice(0, 2)}
|
||||||
ariaLabel="logs-select"
|
ariaLabel="logs-select"
|
||||||
onChange={handleRadioButtons}
|
onChange={handleRadioButtons}
|
||||||
className={classes.radioButtons}
|
className={classes.radioButtons}
|
||||||
|
|
@ -256,10 +281,18 @@ const LogsDownloaderPopover = ({ name, query, args, title, getLogs }) => {
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<div className={classes.radioButtonsContainer}>
|
||||||
|
<RadioGroup
|
||||||
|
name="simplified-tx-logs"
|
||||||
|
value={selectedAdvancedRadio}
|
||||||
|
options={radioButtonOptions.slice(2, 4)}
|
||||||
|
ariaLabel="simplified-tx-logs"
|
||||||
|
onChange={handleAdvancedRadioButtons}
|
||||||
|
className={classes.radioButtons}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div className={classes.download}>
|
<div className={classes.download}>
|
||||||
<Link
|
<Link color="primary" onClick={() => downloadLogs(range, args)}>
|
||||||
color="primary"
|
|
||||||
onClick={() => downloadLogs(range, args, fetchLogs)}>
|
|
||||||
Download
|
Download
|
||||||
</Link>
|
</Link>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -29,6 +29,12 @@ const GET_TRANSACTIONS_CSV = gql`
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
|
|
||||||
|
const GET_SIMPLIFIED_TRANSACTIONS_CSV = gql`
|
||||||
|
query transactions($limit: Int, $from: Date, $until: Date) {
|
||||||
|
simplifiedTransactionsCsv(limit: $limit, from: $from, until: $until)
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
const GET_TRANSACTIONS = gql`
|
const GET_TRANSACTIONS = gql`
|
||||||
query transactions($limit: Int, $from: Date, $until: Date) {
|
query transactions($limit: Int, $from: Date, $until: Date) {
|
||||||
transactions(limit: $limit, from: $from, until: $until) {
|
transactions(limit: $limit, from: $from, until: $until) {
|
||||||
|
|
@ -167,8 +173,14 @@ const Transactions = () => {
|
||||||
<LogsDowloaderPopover
|
<LogsDowloaderPopover
|
||||||
title="Download logs"
|
title="Download logs"
|
||||||
name="transactions"
|
name="transactions"
|
||||||
query={GET_TRANSACTIONS_CSV}
|
queries={[
|
||||||
|
GET_TRANSACTIONS_CSV,
|
||||||
|
GET_SIMPLIFIED_TRANSACTIONS_CSV
|
||||||
|
]}
|
||||||
getLogs={logs => R.path(['transactionsCsv'])(logs)}
|
getLogs={logs => R.path(['transactionsCsv'])(logs)}
|
||||||
|
getSimplifiedLogs={logs =>
|
||||||
|
R.path(['simplifiedTransactionsCsv'])(logs)
|
||||||
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue