fix: change coupons to promo codes

This commit is contained in:
Sérgio Salgado 2021-02-02 13:58:01 +00:00 committed by Josh Harvey
parent 840afa866d
commit 59cb33570b
8 changed files with 87 additions and 88 deletions

View file

@ -13,7 +13,7 @@ const settingsLoader = require('../../new-settings-loader')
// const tokenManager = require('../../token-manager')
const blacklist = require('../../blacklist')
const machineEventsByIdBatch = require("../../postgresql_interface").machineEventsByIdBatch
const couponManager = require('../../coupons')
const promoCodeManager = require('../../promo-codes')
const serverVersion = require('../../../package.json').version
const transactions = require('../transactions')
@ -177,7 +177,7 @@ const typeDefs = gql`
ip_address: String
}
type Coupon {
type PromoCode {
id: ID!
code: String!
discount: Int!
@ -276,7 +276,7 @@ const typeDefs = gql`
config: JSONObject
blacklist: [Blacklist]
# userTokens: [UserToken]
coupons: [Coupon]
promoCodes: [PromoCode]
cryptoRates: JSONObject
fiatRates: [Rate]
}
@ -310,8 +310,8 @@ const typeDefs = gql`
# revokeToken(token: String!): UserToken
deleteBlacklistRow(cryptoCode: String!, address: String!): Blacklist
insertBlacklistRow(cryptoCode: String!, address: String!): Blacklist
createCoupon(code: String!, discount: Int!): Coupon
deleteCoupon(couponId: ID!): Coupon
createPromoCode(code: String!, discount: Int!): PromoCode
deletePromoCode(codeId: ID!): PromoCode
}
`
@ -362,7 +362,7 @@ const resolvers = {
accounts: () => settingsLoader.loadAccounts(),
blacklist: () => blacklist.getBlacklist(),
// userTokens: () => tokenManager.getTokenList()
coupons: () => couponManager.getAvailableCoupons(),
promoCodes: () => promoCodeManager.getAvailablePromoCodes(),
cryptoRates: () =>
settingsLoader.loadLatest().then(settings => {
const pi = plugins(settings)
@ -372,7 +372,7 @@ const resolvers = {
withoutCommissions: pi.buildRatesNoCommission(r)
}
})
}),
}),
fiatRates: () => forex.getFiatRates()
},
Mutation: {
@ -396,8 +396,8 @@ const resolvers = {
insertBlacklistRow: (...[, { cryptoCode, address }]) =>
blacklist.insertIntoBlacklist(cryptoCode, address),
// revokeToken: (...[, { token }]) => tokenManager.revokeToken(token)
createCoupon: (...[, { code, discount }]) => couponManager.createCoupon(code, discount),
deleteCoupon: (...[, { couponId }]) => couponManager.deleteCoupon(couponId)
createPromoCode: (...[, { code, discount }]) => promoCodeManager.createPromoCode(code, discount),
deletePromoCode: (...[, { codeId }]) => promoCodeManager.deletePromoCode(codeId)
}
}

View file

@ -22,7 +22,7 @@ const machineLoader = require('./machine-loader')
const customers = require('./customers')
const coinUtils = require('./coin-utils')
const commissionMath = require('./commission-math')
const coupons = require('./coupons')
const promoCodes = require('./promo-codes')
const mapValuesWithKey = _.mapValues.convert({
cap: false
@ -224,13 +224,13 @@ function plugins (settings, deviceId) {
const testnetPromises = cryptoCodes.map(c => wallet.cryptoNetwork(settings, c))
const pingPromise = recordPing(deviceTime, machineVersion, machineModel)
const currentConfigVersionPromise = fetchCurrentConfigVersion()
const currentAvailableCoupons = coupons.getNumberOfAvailableCoupons()
const currentAvailablePromoCodes = promoCodes.getNumberOfAvailablePromoCodes()
const promises = [
buildAvailableCassettes(),
pingPromise,
currentConfigVersionPromise
].concat(tickerPromises, balancePromises, testnetPromises, currentAvailableCoupons)
].concat(tickerPromises, balancePromises, testnetPromises, currentAvailablePromoCodes)
return Promise.all(promises)
.then(arr => {
@ -242,7 +242,7 @@ function plugins (settings, deviceId) {
const testNets = arr.slice(2 * cryptoCodesCount + 3, arr.length - 1)
const coinParams = _.zip(cryptoCodes, testNets)
const coinsWithoutRate = _.map(mapCoinSettings, coinParams)
const areThereAvailableCoupons = arr[arr.length - 1] > 0
const areThereAvailablePromoCodes = arr[arr.length - 1] > 0
return {
cassettes,
@ -250,7 +250,7 @@ function plugins (settings, deviceId) {
balances: buildBalances(balances),
coins: _.zipWith(_.assign, coinsWithoutRate, tickers),
configVersion,
areThereAvailableCoupons
areThereAvailablePromoCodes
}
})
}

View file

@ -1,29 +1,29 @@
const db = require('./db')
const uuid = require('uuid')
function getAvailableCoupons () {
function getAvailablePromoCodes () {
const sql = `SELECT * FROM coupons WHERE soft_deleted=false`
return db.any(sql)
}
function getCoupon (code) {
function getPromoCode (code) {
const sql = `SELECT * FROM coupons WHERE code=$1 AND soft_deleted=false`
return db.oneOrNone(sql, [code])
}
function createCoupon (code, discount) {
function createPromoCode (code, discount) {
const sql = `INSERT INTO coupons (id, code, discount) VALUES ($1, $2, $3) RETURNING *`
return db.one(sql, [uuid.v4(), code, discount])
}
function deleteCoupon (couponId) {
function deletePromoCode (id) {
const sql = `UPDATE coupons SET soft_deleted=true WHERE id=$1`
return db.none(sql, [couponId])
return db.none(sql, [id])
}
function getNumberOfAvailableCoupons () {
function getNumberOfAvailablePromoCodes () {
const sql = `SELECT COUNT(id) FROM coupons WHERE soft_deleted=false`
return db.one(sql).then(res => res.count)
}
module.exports = { getAvailableCoupons, getCoupon, createCoupon, deleteCoupon, getNumberOfAvailableCoupons }
module.exports = { getAvailablePromoCodes, getPromoCode, createPromoCode, deletePromoCode, getNumberOfAvailablePromoCodes }

View file

@ -25,7 +25,7 @@ const E = require('./error')
const customers = require('./customers')
const logs = require('./logs')
const compliance = require('./compliance')
const couponManager = require('./coupons')
const promoCodes = require('./promo-codes')
const BN = require('./bn')
const commissionMath = require('./commission-math')
@ -216,15 +216,15 @@ function verifyTx (req, res, next) {
.catch(next)
}
function verifyCoupon (req, res, next) {
couponManager.getCoupon(req.body.codeInput)
.then(coupon => {
if (!coupon) return next()
function verifyPromoCode (req, res, next) {
promoCodes.getPromoCode(req.body.codeInput)
.then(promoCode => {
if (!promoCode) return next()
const transaction = req.body.tx
const commissions = configManager.getCommissions(transaction.cryptoCode, req.deviceId, req.settings.config)
const tickerRate = BN(transaction.rawTickerPrice)
const discount = commissionMath.getDiscountRate(coupon.discount, commissions[transaction.direction])
const discount = commissionMath.getDiscountRate(promoCode.discount, commissions[transaction.direction])
const rates = {
[transaction.cryptoCode]: {
[transaction.direction]: (transaction.direction === 'cashIn')
@ -234,7 +234,7 @@ function verifyCoupon (req, res, next) {
}
respond(req, res, {
coupon: coupon,
promoCode: promoCode,
newRates: rates
})
})
@ -479,7 +479,7 @@ const configRequiredRoutes = [
'/phone_code',
'/customer',
'/tx',
'/verify_coupon'
'/verify_promo_code'
]
const app = express()
@ -506,7 +506,7 @@ app.post('/state', stateChange)
app.post('/verify_user', verifyUser)
app.post('/verify_transaction', verifyTx)
app.post('/verify_coupon', verifyCoupon)
app.post('/verify_promo_code', verifyPromoCode)
app.post('/phone_code', getCustomerWithPhoneCode)
app.patch('/customer/:id', updateCustomer)

View file

@ -10,17 +10,17 @@ import DataTable from 'src/components/tables/DataTable'
import { H2, TL1 } from 'src/components/typography'
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
import styles from './CouponCodes.styles'
import CouponCodesModal from './CouponCodesModal'
import styles from './PromoCodes.styles'
import PromoCodesModal from './PromoCodesModal'
const useStyles = makeStyles(styles)
const DUPLICATE_ERROR_MSG = 'There is already a coupon with that code!'
const DUPLICATE_ERROR_MSG = 'There is already a promotion with that code!'
const DEFAULT_ERROR_MSG = 'Failed to save'
const GET_COUPONS = gql`
query coupons {
coupons {
const GET_PROMO_CODES = gql`
query promoCodes {
promoCodes {
id
code
discount
@ -28,17 +28,17 @@ const GET_COUPONS = gql`
}
`
const DELETE_COUPON = gql`
mutation deleteCoupon($couponId: ID!) {
deleteCoupon(couponId: $couponId) {
const DELETE_CODE = gql`
mutation deletePromoCode($codeId: ID!) {
deletePromoCodes(codeId: $codeId) {
id
}
}
`
const CREATE_COUPON = gql`
mutation createCoupon($code: String!, $discount: Int!) {
createCoupon(code: $code, discount: $discount) {
const CREATE_CODE = gql`
mutation createPromoCode($code: String!, $discount: Int!) {
createPromoCode(code: $code, discount: $discount) {
id
code
discount
@ -46,38 +46,36 @@ const CREATE_COUPON = gql`
}
`
const Coupons = () => {
const PromoCodes = () => {
const classes = useStyles()
const [showModal, setShowModal] = useState(false)
const [errorMsg, setErrorMsg] = useState(null)
const toggleModal = () => setShowModal(!showModal)
const { data: couponResponse, loading } = useQuery(GET_COUPONS)
const { data: codeResponse, loading } = useQuery(GET_PROMO_CODES)
const [deleteCoupon] = useMutation(DELETE_COUPON, {
refetchQueries: () => ['coupons']
const [deleteCode] = useMutation(DELETE_CODE, {
refetchQueries: () => ['promoCodes']
})
const [createCoupon] = useMutation(CREATE_COUPON, {
refetchQueries: () => ['coupons']
const [createCode] = useMutation(CREATE_CODE, {
refetchQueries: () => ['promoCodes']
})
const addCoupon = (code, discount) => {
const addCode = (code, discount) => {
setErrorMsg(null)
createCoupon({
createCode({
variables: { code: code, discount: discount }
})
.then(res => {
if (!res.errors) return setShowModal(false)
const duplicateCouponError = R.any(it =>
const duplicateCodeError = R.any(it =>
R.includes('duplicate', it?.message)
)(res.errors)
const msg = duplicateCouponError
? DUPLICATE_ERROR_MSG
: DEFAULT_ERROR_MSG
const msg = duplicateCodeError ? DUPLICATE_ERROR_MSG : DEFAULT_ERROR_MSG
setErrorMsg(msg)
})
.catch(err => {
@ -88,7 +86,7 @@ const Coupons = () => {
const elements = [
{
header: 'Coupon Code',
header: 'Code',
width: 300,
textAlign: 'left',
size: 'sm',
@ -113,7 +111,7 @@ const Coupons = () => {
view: t => (
<IconButton
onClick={() => {
deleteCoupon({ variables: { couponId: t.id } })
deleteCode({ variables: { codeId: t.id } })
}}>
<DeleteIcon />
</IconButton>
@ -123,8 +121,8 @@ const Coupons = () => {
return (
<>
<TitleSection title="Discount Coupons"></TitleSection>
{!loading && !R.isEmpty(couponResponse.coupons) && (
<TitleSection title="Promo Codes"></TitleSection>
{!loading && !R.isEmpty(codeResponse.promoCodes) && (
<Box
marginBottom={4}
marginTop={-5}
@ -132,32 +130,32 @@ const Coupons = () => {
display="flex"
justifyContent="flex-end">
<Link color="primary" onClick={toggleModal}>
Add new coupon
Add new code
</Link>
</Box>
)}
{!loading && !R.isEmpty(couponResponse.coupons) && (
{!loading && !R.isEmpty(codeResponse.promoCodes) && (
<DataTable
elements={elements}
data={R.path(['coupons'])(couponResponse)}
data={R.path(['promoCodes'])(codeResponse)}
/>
)}
{!loading && R.isEmpty(couponResponse.coupons) && (
{!loading && R.isEmpty(codeResponse.promoCodes) && (
<Box display="flex" alignItems="left" flexDirection="column">
<H2>Currently, there are no active coupon codes on your network.</H2>
<Button onClick={toggleModal}>Add coupon</Button>
<H2>Currently, there are no active promo codes on your network.</H2>
<Button onClick={toggleModal}>Add Code</Button>
</Box>
)}
<CouponCodesModal
<PromoCodesModal
showModal={showModal}
onClose={() => {
setErrorMsg(null)
setShowModal(false)
}}
errorMsg={errorMsg}
addCoupon={addCoupon}
addCode={addCode}
/>
</>
)
}
export default Coupons
export default PromoCodes

View file

@ -11,7 +11,7 @@ import { Button } from 'src/components/buttons'
import { TextInput, NumberInput } from 'src/components/inputs/formik'
import { H3, TL1, P } from 'src/components/typography'
import styles from './CouponCodes.styles'
import styles from './PromoCodes.styles'
const useStyles = makeStyles(styles)
@ -31,18 +31,18 @@ const validationSchema = Yup.object().shape({
.max(100)
})
const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => {
const PromoCodesModal = ({ showModal, onClose, errorMsg, addCode }) => {
const classes = useStyles()
const handleAddCoupon = (code, discount) => {
addCoupon(R.toUpper(code), parseInt(discount))
const handleAddCode = (code, discount) => {
addCode(R.toUpper(code), parseInt(discount))
}
return (
<>
{showModal && (
<Modal
title="Add coupon code discount"
title="Add promo code discount"
closeOnBackdropClick={true}
width={600}
height={500}
@ -52,10 +52,10 @@ const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => {
initialValues={initialValues}
validationSchema={validationSchema}
onSubmit={({ code, discount }) => {
handleAddCoupon(code, discount)
handleAddCode(code, discount)
}}>
<Form id="coupon-form" className={classes.form}>
<H3 className={classes.modalLabel1}>Coupon code name</H3>
<Form id="promo-form" className={classes.form}>
<H3 className={classes.modalLabel1}>Promo code name</H3>
<Field
name="code"
autoFocus
@ -69,13 +69,14 @@ const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => {
<H3 className={classes.modalLabel2}>Define discount rate</H3>
<Tooltip width={304}>
<P>
The discount rate inserted will be applied to the
commissions of all transactions performed with this
respective coupon code.
This is a percentage discount off of your existing
commission rates for a customer entering this code at the
machine.
</P>
<P>
(It should be a number between 0 (zero) and 100 (one
hundred)).
For instance, if you charge 8% commissions, and this code is
set for 50%, then you'll instead be charging 4% on
transactions using the code.
</P>
</Tooltip>
</div>
@ -97,9 +98,9 @@ const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => {
{errorMsg && <ErrorMessage>{errorMsg}</ErrorMessage>}
<Button
type="submit"
form="coupon-form"
form="promo-form"
className={classes.submit}>
Add coupon
Add code
</Button>
</div>
</Form>
@ -110,4 +111,4 @@ const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => {
)
}
export default CouponCodesModal
export default PromoCodesModal

View file

@ -22,7 +22,7 @@ import { Customers, CustomerProfile } from 'src/pages/Customers'
import Dashboard from 'src/pages/Dashboard'
import Funding from 'src/pages/Funding'
import Locales from 'src/pages/Locales'
import Coupons from 'src/pages/LoyaltyPanel/CouponCodes'
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
import MachineLogs from 'src/pages/MachineLogs'
import Machines from 'src/pages/Machines'
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
@ -212,10 +212,10 @@ const tree = [
component: Blacklist
},
{
key: 'discount-coupons',
label: 'Discount Coupons',
route: '/compliance/loyalty/coupons',
component: Coupons
key: 'promo-codes',
label: 'Promo Codes',
route: '/compliance/loyalty/codes',
component: PromoCodes
},
{
key: 'customer',