feat: add cashin bill counter

fix: fiat amount formatting
This commit is contained in:
Sérgio Salgado 2021-12-20 01:16:43 +00:00
parent 219dca7f90
commit 98a2797494
17 changed files with 239 additions and 218 deletions

View file

@ -68,4 +68,10 @@ function getBillsByBatchId (id) {
return db.any(sql, [id]) return db.any(sql, [id])
} }
module.exports = { createCashboxBatch, updateMachineWithBatch, getBatches, getBillsByBatchId, editBatchById } module.exports = {
createCashboxBatch,
updateMachineWithBatch,
getBatches,
getBillsByBatchId,
editBatchById
}

View file

@ -2,7 +2,9 @@ const bills = require('../../services/bills')
const resolvers = { const resolvers = {
Query: { Query: {
bills: () => bills.getBills() bills: () => bills.getBills(),
looseBills: () => bills.getLooseBills(),
looseBillsByMachine: (...[, { deviceId }]) => bills.getLooseBillsByMachine(deviceId)
} }
} }

View file

@ -2,14 +2,17 @@ const { gql } = require('apollo-server-express')
const typeDef = gql` const typeDef = gql`
type Bill { type Bill {
id: ID
fiat: Int fiat: Int
deviceId: ID deviceId: ID
created: Date created: Date
cashbox: Int cashboxBatchId: ID
} }
type Query { type Query {
bills: [Bill] @auth bills: [Bill] @auth
looseBills: [Bill] @auth
looseBillsByMachine(deviceId: ID): [Bill] @auth
} }
` `

View file

@ -1,25 +1,37 @@
const _ = require('lodash/fp')
const db = require('../../db') const db = require('../../db')
// Get all bills with device id // Get all bills with device id
const getBills = () => { const getBills = () => {
return Promise.reject(new Error('This functionality hasn\'t been implemented yet')) const sql = `SELECT b.id, b.fiat, b.fiat_code, b.created, b.cashbox_batch_id, cit.device_id AS device_id FROM bills b LEFT OUTER JOIN (
/* return db.any(` SELECT id, device_id FROM cash_in_txs
SELECT d.device_id, b.fiat, b.created, d.cashbox ) AS cit ON cit.id = b.cash_in_txs_id`
FROM cash_in_txs
INNER JOIN bills AS b ON b.cash_in_txs_id = cash_in_txs.id return db.any(sql)
INNER JOIN devices as d ON d.device_id = cash_in_txs.device_id .then(res => _.map(_.mapKeys(_.camelCase), res))
ORDER BY device_id, created DESC` }
)
.then(res => { function getLooseBills () {
return res.map(item => ({ const sql = `SELECT b.id, b.fiat, b.fiat_code, b.created, b.cashbox_batch_id, cit.device_id AS device_id FROM bills b LEFT OUTER JOIN (
fiat: item.fiat, SELECT id, device_id FROM cash_in_txs
deviceId: item.device_id, ) AS cit ON cit.id = b.cash_in_txs_id WHERE b.cashbox_batch_id IS NULL`
cashbox: item.cashbox,
created: item.created return db.any(sql)
})) .then(res => _.map(_.mapKeys(_.camelCase), res))
}) */ }
function getLooseBillsByMachine (machineId) {
const sql = `SELECT b.id, b.fiat, b.fiat_code, b.created, b.cashbox_batch_id, cit.device_id AS device_id FROM bills b LEFT OUTER JOIN (
SELECT id, device_id FROM cash_in_txs WHERE device_id = $1
) AS cit ON cit.id = b.cash_in_txs_id WHERE b.cashbox_batch_id IS NULL`
return db.any(sql, [machineId])
.then(res => _.map(_.mapKeys(_.camelCase), res))
} }
module.exports = { module.exports = {
getBills getBills,
getLooseBills,
getLooseBillsByMachine
} }

View file

@ -4,6 +4,7 @@ import React from 'react'
import Chip from 'src/components/Chip' import Chip from 'src/components/Chip'
import { Info2, Label1, Label2 } from 'src/components/typography' import { Info2, Label1, Label2 } from 'src/components/typography'
import { numberToFiatAmount } from 'src/utils/number'
import { cashboxStyles, gridStyles } from './Cashbox.styles' import { cashboxStyles, gridStyles } from './Cashbox.styles'
@ -64,11 +65,9 @@ const CashIn = ({ currency, notes, total }) => {
<Info2 className={classes.noMarginText}>{notes} notes</Info2> <Info2 className={classes.noMarginText}>{notes} notes</Info2>
</div> </div>
<div className={classes.innerRow}> <div className={classes.innerRow}>
{/* Feature on hold until this can be calculated
<Label1 className={classes.noMarginText}> <Label1 className={classes.noMarginText}>
{total} {currency.code} {total} {currency.code}
</Label1> </Label1>
*/}
</div> </div>
</div> </div>
</div> </div>
@ -112,7 +111,7 @@ const CashOut = ({
</div> </div>
<div className={classes.innerRow}> <div className={classes.innerRow}>
<Label1 className={classes.noMarginText}> <Label1 className={classes.noMarginText}>
{notes * denomination} {currency.code} {numberToFiatAmount(notes * denomination)} {currency.code}
</Label1> </Label1>
</div> </div>
</div> </div>

View file

@ -15,6 +15,7 @@ import { ReactComponent as DashLogo } from 'src/styling/logos/icon-dash-colour.s
import { ReactComponent as EthereumLogo } from 'src/styling/logos/icon-ethereum-colour.svg' import { ReactComponent as EthereumLogo } from 'src/styling/logos/icon-ethereum-colour.svg'
import { ReactComponent as LitecoinLogo } from 'src/styling/logos/icon-litecoin-colour.svg' import { ReactComponent as LitecoinLogo } from 'src/styling/logos/icon-litecoin-colour.svg'
import { ReactComponent as ZCashLogo } from 'src/styling/logos/icon-zcash-colour.svg' import { ReactComponent as ZCashLogo } from 'src/styling/logos/icon-zcash-colour.svg'
import { numberToFiatAmount } from 'src/utils/number'
import styles from './ATMWallet.styles' import styles from './ATMWallet.styles'
@ -51,9 +52,6 @@ const GET_OPERATOR_BY_USERNAME = gql`
} }
` `
const formatCurrency = amount =>
amount.toLocaleString('en-US', { maximumFractionDigits: 2 })
const CHIPS_PER_ROW = 6 const CHIPS_PER_ROW = 6
const Assets = ({ balance, wallets, currency }) => { const Assets = ({ balance, wallets, currency }) => {
@ -69,7 +67,7 @@ const Assets = ({ balance, wallets, currency }) => {
<P className={classes.fieldHeader}>Available balance</P> <P className={classes.fieldHeader}>Available balance</P>
<div className={classes.totalAssetWrapper}> <div className={classes.totalAssetWrapper}>
<Info2 noMargin className={classes.fieldValue}> <Info2 noMargin className={classes.fieldValue}>
{formatCurrency(balance)} {numberToFiatAmount(balance)}
</Info2> </Info2>
<Info2 noMargin className={classes.fieldCurrency}> <Info2 noMargin className={classes.fieldCurrency}>
{R.toUpper(currency)} {R.toUpper(currency)}
@ -81,7 +79,7 @@ const Assets = ({ balance, wallets, currency }) => {
<P className={classes.fieldHeader}>Total balance in wallets</P> <P className={classes.fieldHeader}>Total balance in wallets</P>
<div className={classes.totalAssetWrapper}> <div className={classes.totalAssetWrapper}>
<Info2 noMargin className={classes.fieldValue}> <Info2 noMargin className={classes.fieldValue}>
{formatCurrency(walletFiatSum())} {numberToFiatAmount(walletFiatSum())}
</Info2> </Info2>
<Info2 noMargin className={classes.fieldCurrency}> <Info2 noMargin className={classes.fieldCurrency}>
{R.toUpper(currency)} {R.toUpper(currency)}
@ -93,7 +91,7 @@ const Assets = ({ balance, wallets, currency }) => {
<P className={classes.fieldHeader}>Total assets</P> <P className={classes.fieldHeader}>Total assets</P>
<div className={classes.totalAssetWrapper}> <div className={classes.totalAssetWrapper}>
<Info2 noMargin className={classes.fieldValue}> <Info2 noMargin className={classes.fieldValue}>
{formatCurrency(balance)} {numberToFiatAmount(balance)}
</Info2> </Info2>
<Info2 noMargin className={classes.fieldCurrency}> <Info2 noMargin className={classes.fieldCurrency}>
{R.toUpper(currency)} {R.toUpper(currency)}
@ -144,17 +142,11 @@ const WalletInfoChip = ({ wallet, currency }) => {
<div className={classes.walletValueWrapper}> <div className={classes.walletValueWrapper}>
<Label2 className={classes.fieldHeader}>{wallet.name} value</Label2> <Label2 className={classes.fieldHeader}>{wallet.name} value</Label2>
<Label2 className={classes.walletValue}> <Label2 className={classes.walletValue}>
{wallet.amount.toFixed(1).toLocaleString('en-US', { {numberToFiatAmount(wallet.amount.toFixed(1))} {wallet.cryptoCode}
maximumFractionDigits: 2
})}{' '}
{wallet.cryptoCode}
</Label2> </Label2>
<Label2 className={classes.fieldHeader}>Hedged value</Label2> <Label2 className={classes.fieldHeader}>Hedged value</Label2>
<Label2 className={classes.walletValue}> <Label2 className={classes.walletValue}>
{wallet.fiatValue.toLocaleString('en-US', { {numberToFiatAmount(wallet.fiatValue)} {currency}
maximumFractionDigits: 2
})}{' '}
{currency}
</Label2> </Label2>
</div> </div>
</Paper> </Paper>

View file

@ -9,13 +9,11 @@ import { Tooltip } from 'src/components/Tooltip'
import TitleSection from 'src/components/layout/TitleSection' import TitleSection from 'src/components/layout/TitleSection'
import DataTable from 'src/components/tables/DataTable' import DataTable from 'src/components/tables/DataTable'
import { H4, Info2, P } from 'src/components/typography' import { H4, Info2, P } from 'src/components/typography'
import { numberToFiatAmount } from 'src/utils/number'
import { formatDate } from 'src/utils/timezones' import { formatDate } from 'src/utils/timezones'
import styles from './Accounting.styles' import styles from './Accounting.styles'
const formatCurrency = amount =>
amount.toLocaleString('en-US', { maximumFractionDigits: 2 })
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
const GET_OPERATOR_BY_USERNAME = gql` const GET_OPERATOR_BY_USERNAME = gql`
@ -64,7 +62,7 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
<P className={classes.fieldHeader}>Pazuz fiat balance</P> <P className={classes.fieldHeader}>Pazuz fiat balance</P>
<div className={classes.totalAssetWrapper}> <div className={classes.totalAssetWrapper}>
<Info2 noMargin className={classes.fieldValue}> <Info2 noMargin className={classes.fieldValue}>
{formatCurrency(balance)} {numberToFiatAmount(balance)}
</Info2> </Info2>
<Info2 noMargin className={classes.fieldCurrency}> <Info2 noMargin className={classes.fieldCurrency}>
{R.toUpper(currency)} {R.toUpper(currency)}
@ -76,7 +74,7 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
<P className={classes.fieldHeader}>Hedging reserve</P> <P className={classes.fieldHeader}>Hedging reserve</P>
<div className={classes.totalAssetWrapper}> <div className={classes.totalAssetWrapper}>
<Info2 noMargin className={classes.fieldValue}> <Info2 noMargin className={classes.fieldValue}>
{formatCurrency(hedgingReserve)} {numberToFiatAmount(hedgingReserve)}
</Info2> </Info2>
<Info2 noMargin className={classes.fieldCurrency}> <Info2 noMargin className={classes.fieldCurrency}>
{R.toUpper(currency)} {R.toUpper(currency)}
@ -88,7 +86,7 @@ const Assets = ({ balance, hedgingReserve, currency }) => {
<P className={classes.fieldHeader}>Available balance</P> <P className={classes.fieldHeader}>Available balance</P>
<div className={classes.totalAssetWrapper}> <div className={classes.totalAssetWrapper}>
<Info2 noMargin className={classes.fieldValue}> <Info2 noMargin className={classes.fieldValue}>
{formatCurrency(balance - hedgingReserve)} {numberToFiatAmount(balance - hedgingReserve)}
</Info2> </Info2>
<Info2 noMargin className={classes.fieldCurrency}> <Info2 noMargin className={classes.fieldCurrency}>
{R.toUpper(currency)} {R.toUpper(currency)}
@ -143,7 +141,7 @@ const Accounting = () => {
size: 'sm', size: 'sm',
textAlign: 'right', textAlign: 'right',
view: it => view: it =>
`${formatCurrency(it.fiatAmount)} ${R.toUpper(it.fiatCurrency)}` `${numberToFiatAmount(it.fiatAmount)} ${R.toUpper(it.fiatCurrency)}`
}, },
{ {
header: 'Balance after operation', header: 'Balance after operation',
@ -151,7 +149,9 @@ const Accounting = () => {
size: 'sm', size: 'sm',
textAlign: 'right', textAlign: 'right',
view: it => view: it =>
`${formatCurrency(it.fiatBalanceAfter)} ${R.toUpper(it.fiatCurrency)}` `${numberToFiatAmount(it.fiatBalanceAfter)} ${R.toUpper(
it.fiatCurrency
)}`
}, },
{ {
header: 'Date', header: 'Date',

View file

@ -13,6 +13,7 @@ import { ReactComponent as DownIcon } from 'src/styling/icons/dashboard/down.svg
import { ReactComponent as EqualIcon } from 'src/styling/icons/dashboard/equal.svg' import { ReactComponent as EqualIcon } from 'src/styling/icons/dashboard/equal.svg'
import { ReactComponent as UpIcon } from 'src/styling/icons/dashboard/up.svg' import { ReactComponent as UpIcon } from 'src/styling/icons/dashboard/up.svg'
import { fromNamespace } from 'src/utils/config' import { fromNamespace } from 'src/utils/config'
import { numberToFiatAmount } from 'src/utils/number'
import { DAY, WEEK, MONTH } from 'src/utils/time' import { DAY, WEEK, MONTH } from 'src/utils/time'
import styles from './Analytics.styles' import styles from './Analytics.styles'
@ -97,9 +98,7 @@ const OverviewEntry = ({ label, value, oldValue, currency }) => {
<div className={classes.overviewEntry}> <div className={classes.overviewEntry}>
<P noMargin>{label}</P> <P noMargin>{label}</P>
<Info2 noMargin className={classes.overviewFieldWrapper}> <Info2 noMargin className={classes.overviewFieldWrapper}>
<span> <span>{numberToFiatAmount(value)}</span>
{value.toLocaleString('en-US', { maximumFractionDigits: 2 })}
</span>
{!!currency && ` ${currency}`} {!!currency && ` ${currency}`}
</Info2> </Info2>
<span className={classes.overviewGrowth}> <span className={classes.overviewGrowth}>
@ -107,7 +106,7 @@ const OverviewEntry = ({ label, value, oldValue, currency }) => {
{R.lt(growthRate, 0) && <DownIcon height={10} />} {R.lt(growthRate, 0) && <DownIcon height={10} />}
{R.equals(growthRate, 0) && <EqualIcon height={10} />} {R.equals(growthRate, 0) && <EqualIcon height={10} />}
<P noMargin className={classnames(growthClasses)}> <P noMargin className={classnames(growthClasses)}>
{growthRate.toLocaleString('en-US', { maximumFractionDigits: 2 })}% {numberToFiatAmount(growthRate)}%
</P> </P>
</span> </span>
</div> </div>

View file

@ -6,6 +6,7 @@ import React, { memo } from 'react'
import { Info2, Label3, P } from 'src/components/typography' import { Info2, Label3, P } from 'src/components/typography'
import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { numberToFiatAmount } from 'src/utils/number'
import { singularOrPlural } from 'src/utils/string' import { singularOrPlural } from 'src/utils/string'
import { formatDate, formatDateNonUtc } from 'src/utils/timezones' import { formatDate, formatDateNonUtc } from 'src/utils/timezones'
@ -13,9 +14,6 @@ import styles from './GraphTooltip.styles'
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
const formatCurrency = amount =>
amount.toLocaleString('en-US', { maximumFractionDigits: 2 })
const GraphTooltip = ({ const GraphTooltip = ({
coords, coords,
data, data,
@ -67,7 +65,7 @@ const GraphTooltip = ({
{singularOrPlural(R.length(data), 'transaction', 'transactions')} {singularOrPlural(R.length(data), 'transaction', 'transactions')}
</P> </P>
<P noMargin className={classes.dotOtTransactionVolume}> <P noMargin className={classes.dotOtTransactionVolume}>
{formatCurrency(transactions.volume)} {currency} in volume {numberToFiatAmount(transactions.volume)} {currency} in volume
</P> </P>
<div className={classes.dotOtTransactionClasses}> <div className={classes.dotOtTransactionClasses}>
<Label3 noMargin> <Label3 noMargin>

View file

@ -14,8 +14,10 @@ import React, { useContext } from 'react'
import AppContext from 'src/AppContext' import AppContext from 'src/AppContext'
import TitleSection from 'src/components/layout/TitleSection' import TitleSection from 'src/components/layout/TitleSection'
import { H4, Label2, P, Info2 } from 'src/components/typography' import { H4, Label2, P, Info2 } from 'src/components/typography'
import { numberToFiatAmount } from 'src/utils/number'
import styles from './Assets.styles' import styles from './Assets.styles'
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
const GET_OPERATOR_BY_USERNAME = gql` const GET_OPERATOR_BY_USERNAME = gql`
@ -105,7 +107,7 @@ const AssetsAmountTable = ({ title, data = [], numToRender }) => {
</Cell> </Cell>
<Cell align="right"> <Cell align="right">
<P>{`${selectAmountPrefix(asset)} <P>{`${selectAmountPrefix(asset)}
${formatCurrency(Math.abs(asset.amount))} ${ ${numberToFiatAmount(Math.abs(asset.amount))} ${
asset.currency asset.currency
}`}</P> }`}</P>
</Cell> </Cell>
@ -117,7 +119,9 @@ const AssetsAmountTable = ({ title, data = [], numToRender }) => {
<Info2>{`Total ${R.toLower(title)}`}</Info2> <Info2>{`Total ${R.toLower(title)}`}</Info2>
</Cell> </Cell>
<Cell align="right"> <Cell align="right">
<Info2>{`${formatCurrency(totalAmount)} ${currency}`}</Info2> <Info2>{`${numberToFiatAmount(
totalAmount
)} ${currency}`}</Info2>
</Cell> </Cell>
</TableRow> </TableRow>
</TableBody> </TableBody>
@ -128,9 +132,6 @@ const AssetsAmountTable = ({ title, data = [], numToRender }) => {
) )
} }
const formatCurrency = amount =>
amount.toLocaleString('en-US', { maximumFractionDigits: 2 })
const Assets = () => { const Assets = () => {
const classes = useStyles() const classes = useStyles()
const { userData } = useContext(AppContext) const { userData } = useContext(AppContext)

View file

@ -82,7 +82,7 @@ const SET_CASSETTE_BILLS = gql`
} }
` `
const CashCassettes = ({ machine, config, refetchData }) => { const CashCassettes = ({ machine, config, refetchData, bills }) => {
const classes = useStyles() const classes = useStyles()
const [wizard, setWizard] = useState(false) const [wizard, setWizard] = useState(false)
@ -105,7 +105,11 @@ const CashCassettes = ({ machine, config, refetchData }) => {
width: widthsByNumberOfCassettes[numberOfCassettes].cashbox, width: widthsByNumberOfCassettes[numberOfCassettes].cashbox,
stripe: false, stripe: false,
view: value => ( view: value => (
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} /> <CashIn
currency={{ code: fiatCurrency }}
notes={value}
total={R.sum(R.map(it => it.fiat)(bills))}
/>
), ),
input: NumberInput, input: NumberInput,
inputProps: { inputProps: {

View file

@ -46,6 +46,12 @@ const GET_INFO = gql`
note note
} }
} }
looseBillsByMachine(deviceId: $deviceId) {
id
fiat
deviceId
created
}
config config
} }
` `
@ -59,12 +65,14 @@ const Machines = () => {
deviceId: getMachineID(location.pathname) deviceId: getMachineID(location.pathname)
} }
}) })
const classes = useStyles() const classes = useStyles()
const timezone = R.path(['config', 'locale_timezone'], data) ?? {} const timezone = R.path(['config', 'locale_timezone'], data) ?? {}
const machine = R.path(['machine'])(data) ?? {} const machine = R.path(['machine'])(data) ?? {}
const config = R.path(['config'])(data) ?? {} const config = R.path(['config'])(data) ?? {}
const bills = R.path(['looseBillsByMachine'])(data) ?? []
const machineName = R.path(['name'])(machine) ?? null const machineName = R.path(['name'])(machine) ?? null
const machineID = R.path(['deviceId'])(machine) ?? null const machineID = R.path(['deviceId'])(machine) ?? null
@ -102,6 +110,7 @@ const Machines = () => {
refetchData={refetch} refetchData={refetch}
machine={machine} machine={machine}
config={config ?? false} config={config ?? false}
bills={bills}
/> />
</div> </div>
<div className={classes.transactionsItem}> <div className={classes.transactionsItem}>

View file

@ -75,24 +75,21 @@ const GET_MACHINES_AND_CONFIG = gql`
numberOfCassettes numberOfCassettes
} }
config config
looseBills {
id
fiat
created
deviceId
}
} }
` `
const SAVE_CONFIG = gql` const SAVE_CONFIG = gql`
mutation Save($config: JSONObject) { mutation Save($config: JSONObject) {
saveConfig(config: $config) saveConfig(config: $config)
} }
` `
/*
// for cash in total calculation
bills {
fiat
deviceId
created
cashbox
}
*/
const SET_CASSETTE_BILLS = gql` const SET_CASSETTE_BILLS = gql`
mutation MachineAction( mutation MachineAction(
$deviceId: ID! $deviceId: ID!
@ -128,7 +125,7 @@ const CashCassettes = () => {
const [editingSchema, setEditingSchema] = useState(null) const [editingSchema, setEditingSchema] = useState(null)
const [selectedRadio, setSelectedRadio] = useState(null) const [selectedRadio, setSelectedRadio] = useState(null)
const { data } = useQuery(GET_MACHINES_AND_CONFIG) const { data, loading: dataLoading } = useQuery(GET_MACHINES_AND_CONFIG)
const [wizard, setWizard] = useState(false) const [wizard, setWizard] = useState(false)
const [machineId, setMachineId] = useState('') const [machineId, setMachineId] = useState('')
@ -143,9 +140,11 @@ const CashCassettes = () => {
refetchQueries: () => ['getData'] refetchQueries: () => ['getData']
}) })
const bills = R.groupBy(bill => bill.deviceId)(R.path(['bills'])(data) ?? []) const bills = R.groupBy(bill => bill.deviceId)(
R.path(['looseBills'])(data) ?? []
)
const deviceIds = R.uniq( const deviceIds = R.uniq(
R.map(R.prop('deviceId'))(R.path(['bills'])(data) ?? []) R.map(R.prop('deviceId'))(R.path(['looseBills'])(data) ?? [])
) )
const cashout = data?.config && fromNamespace('cashOut')(data.config) const cashout = data?.config && fromNamespace('cashOut')(data.config)
const locale = data?.config && fromNamespace('locale')(data.config) const locale = data?.config && fromNamespace('locale')(data.config)
@ -206,8 +205,12 @@ const CashCassettes = () => {
name: 'cashbox', name: 'cashbox',
header: 'Cash box', header: 'Cash box',
width: maxNumberOfCassettes > 2 ? 140 : 280, width: maxNumberOfCassettes > 2 ? 140 : 280,
view: value => ( view: (value, { id }) => (
<CashIn currency={{ code: fiatCurrency }} notes={value} total={0} /> <CashIn
currency={{ code: fiatCurrency }}
notes={value}
total={R.sum(R.map(it => it.fiat, bills[id]))}
/>
), ),
input: NumberInput, input: NumberInput,
inputProps: { inputProps: {
@ -222,7 +225,7 @@ const CashCassettes = () => {
elements.push({ elements.push({
name: `cassette${it}`, name: `cassette${it}`,
header: `Cassette ${it}`, header: `Cassette ${it}`,
width: (maxNumberOfCassettes > 2 ? 700 : 560) / maxNumberOfCassettes, width: (maxNumberOfCassettes > 2 ? 560 : 650) / maxNumberOfCassettes,
stripe: true, stripe: true,
doubleHeader: 'Cash-out', doubleHeader: 'Cash-out',
view: (value, { id }) => ( view: (value, { id }) => (
@ -268,6 +271,7 @@ const CashCassettes = () => {
}) })
return ( return (
!dataLoading && (
<> <>
<TitleSection <TitleSection
title="Cash Boxes & Cassettes" title="Cash Boxes & Cassettes"
@ -285,7 +289,7 @@ const CashCassettes = () => {
<Box <Box
display="flex" display="flex"
alignItems="center" alignItems="center"
justifyContent="flex-end" justifyContent="end"
mr="-4px"> mr="-4px">
{cashboxReset && ( {cashboxReset && (
<P className={classes.selection}> <P className={classes.selection}>
@ -332,7 +336,7 @@ const CashCassettes = () => {
/> />
{wizard && ( {wizard && (
<Wizard <Wizard
machine={R.find(R.propEq('id', machineId))(machines)} machine={R.find(R.propEq('id', machineId), machines)}
cashoutSettings={getCashoutSettings(machineId)} cashoutSettings={getCashoutSettings(machineId)}
onClose={() => { onClose={() => {
setWizard(false) setWizard(false)
@ -349,8 +353,8 @@ const CashCassettes = () => {
handleClose={() => setEditingSchema(null)} handleClose={() => setEditingSchema(null)}
open={true}> open={true}>
<P className={classes.descriptions}> <P className={classes.descriptions}>
We can automatically assume you emptied a bill validator's cash box We can automatically assume you emptied a bill validator's cash
when the machine detects that it has been removed. box when the machine detects that it has been removed.
</P> </P>
<RadioGroup <RadioGroup
name="set-automatic-reset" name="set-automatic-reset"
@ -360,8 +364,9 @@ const CashCassettes = () => {
className={classes.radioButtons} className={classes.radioButtons}
/> />
<P className={classes.descriptions}> <P className={classes.descriptions}>
Assume the cash box is emptied whenever it's removed, creating a new Assume the cash box is emptied whenever it's removed, creating a
batch on the history screen and setting its current balance to zero. new batch on the history screen and setting its current balance to
zero.
</P> </P>
<RadioGroup <RadioGroup
name="set-manual-reset" name="set-manual-reset"
@ -384,6 +389,7 @@ const CashCassettes = () => {
)} )}
</> </>
) )
)
} }
export default CashCassettes export default CashCassettes

View file

@ -1,20 +1,17 @@
import { makeStyles } from '@material-ui/core' import { makeStyles } from '@material-ui/core'
// import BigNumber from 'bignumber.js' import BigNumber from 'bignumber.js'
import * as R from 'ramda' import * as R from 'ramda'
import React from 'react' import React from 'react'
import { Info1, Info2, Info3 } from 'src/components/typography/index' import { Info1, Info2, Info3 } from 'src/components/typography/index'
// import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg' import { ReactComponent as TxInIcon } from 'src/styling/icons/direction/cash-in.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { fromNamespace } from 'src/utils/config' import { fromNamespace } from 'src/utils/config'
import { numberToFiatAmount } from 'src/utils/number.js'
import styles from './CashCassettesFooter.styles.js' import styles from './CashCassettesFooter.styles.js'
const useStyles = makeStyles(styles) const useStyles = makeStyles(styles)
/* const sortDate = function(a, b) {
return new Date(b.created).getTime() - new Date(a.created).getTime()
} */
const CashCassettesFooter = ({ const CashCassettesFooter = ({
machines, machines,
config, config,
@ -43,44 +40,34 @@ const CashCassettesFooter = ({
const totalInCassettes = R.sum(R.reduce(reducerFn, [0, 0, 0, 0], machines)) const totalInCassettes = R.sum(R.reduce(reducerFn, [0, 0, 0, 0], machines))
/* const totalInCashBox = R.sum( const totalInCashBox = R.sum(R.map(it => it.fiat)(bills))
R.flatten(
R.map(id => {
const sliceIdx = R.path([id, 0, 'cashbox'])(bills) ?? 0
return R.map(
R.prop('fiat'),
R.slice(0, sliceIdx, R.sort(sortDate, bills[id] ?? []))
)
}, deviceIds)
)
) */
// const total = new BigNumber(totalInCassettes + totalInCashBox).toFormat(0) const total = new BigNumber(totalInCassettes + totalInCashBox).toFormat(0)
return ( return (
<div className={classes.footerContainer}> <div className={classes.footerContainer}>
<div className={classes.footerContent}> <div className={classes.footerContent}>
<Info3 className={classes.footerLabel}>Cash value in System</Info3> <Info3 className={classes.footerLabel}>Cash value in System</Info3>
{/* <div className={classes.flex}> <div className={classes.flex}>
<TxInIcon className={classes.icon} /> <TxInIcon className={classes.icon} />
<Info2 className={classes.iconLabel}>Cash-in:</Info2> <Info2 className={classes.iconLabel}>Cash-in:</Info2>
<Info1 className={classes.valueDisplay}> <Info1 className={classes.valueDisplay}>
{totalInCashBox} {currencyCode} {numberToFiatAmount(totalInCashBox)} {currencyCode}
</Info1> </Info1>
</div> */} </div>
<div className={classes.flex}> <div className={classes.flex}>
<TxOutIcon className={classes.icon} /> <TxOutIcon className={classes.icon} />
<Info2 className={classes.iconLabel}>Cash-out:</Info2> <Info2 className={classes.iconLabel}>Cash-out:</Info2>
<Info1 className={classes.valueDisplay}> <Info1 className={classes.valueDisplay}>
{totalInCassettes} {currencyCode} {numberToFiatAmount(totalInCassettes)} {currencyCode}
</Info1> </Info1>
</div> </div>
{/* <div className={classes.flex}> <div className={classes.flex}>
<Info2 className={classes.iconLabel}>Total:</Info2> <Info2 className={classes.iconLabel}>Total:</Info2>
<Info1 className={classes.valueDisplay}> <Info1 className={classes.valueDisplay}>
{total} {currencyCode} {numberToFiatAmount(total)} {currencyCode}
</Info1> </Info1>
</div> */} </div>
</div> </div>
</div> </div>
) )

View file

@ -24,9 +24,7 @@ export default {
boxShadow: [[0, -1, 10, 0, 'rgba(50, 50, 50, 0.1)']] boxShadow: [[0, -1, 10, 0, 'rgba(50, 50, 50, 0.1)']]
}, },
flex: { flex: {
display: 'flex', display: 'flex'
// temp marginLeft until cashIn square is enabled
marginLeft: -640
}, },
icon: { icon: {
alignSelf: 'center', alignSelf: 'center',

View file

@ -22,6 +22,7 @@ import tejo4CassetteThree from 'src/styling/icons/cassettes/tejo/4-cassettes/4-c
import tejo4CassetteFour from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-4-left.svg' import tejo4CassetteFour from 'src/styling/icons/cassettes/tejo/4-cassettes/4-cassettes-open-4-left.svg'
import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg' import { ReactComponent as TxOutIcon } from 'src/styling/icons/direction/cash-out.svg'
import { comet, errorColor } from 'src/styling/variables' import { comet, errorColor } from 'src/styling/variables'
import { numberToFiatAmount } from 'src/utils/number'
const styles = { const styles = {
content: { content: {
@ -279,7 +280,8 @@ const WizardStep = ({
</P> </P>
</div> </div>
<P noMargin className={classes.fiatTotal}> <P noMargin className={classes.fiatTotal}>
= {cassetteTotal(values)} {fiatCurrency} = {numberToFiatAmount(cassetteTotal(values))}{' '}
{fiatCurrency}
</P> </P>
</div> </div>
</div> </div>

View file

@ -7,4 +7,7 @@ const transformNumber = value => (isValidNumber(value) ? value : null)
const defaultToZero = value => const defaultToZero = value =>
isValidNumber(parseInt(value)) ? parseInt(value) : 0 isValidNumber(parseInt(value)) ? parseInt(value) : 0
export { defaultToZero, transformNumber } const numberToFiatAmount = value =>
value.toLocaleString('en-US', { maximumFractionDigits: 2 })
export { defaultToZero, transformNumber, numberToFiatAmount }