diff --git a/lib/new-admin/graphql/schema.js b/lib/new-admin/graphql/schema.js index 26202868..32250765 100644 --- a/lib/new-admin/graphql/schema.js +++ b/lib/new-admin/graphql/schema.js @@ -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) } } diff --git a/lib/plugins.js b/lib/plugins.js index cf449c0c..d523e946 100644 --- a/lib/plugins.js +++ b/lib/plugins.js @@ -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 } }) } diff --git a/lib/coupons.js b/lib/promo-codes.js similarity index 63% rename from lib/coupons.js rename to lib/promo-codes.js index 1c8fdd94..9bc52d85 100644 --- a/lib/coupons.js +++ b/lib/promo-codes.js @@ -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 } diff --git a/lib/routes.js b/lib/routes.js index 2538ef76..19777ebb 100644 --- a/lib/routes.js +++ b/lib/routes.js @@ -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) diff --git a/new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodes.js b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js similarity index 61% rename from new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodes.js rename to new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js index 9338d43f..c35d9d52 100644 --- a/new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodes.js +++ b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js @@ -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 => ( { - deleteCoupon({ variables: { couponId: t.id } }) + deleteCode({ variables: { codeId: t.id } }) }}> @@ -123,8 +121,8 @@ const Coupons = () => { return ( <> - - {!loading && !R.isEmpty(couponResponse.coupons) && ( + + {!loading && !R.isEmpty(codeResponse.promoCodes) && ( { display="flex" justifyContent="flex-end"> - Add new coupon + Add new code )} - {!loading && !R.isEmpty(couponResponse.coupons) && ( + {!loading && !R.isEmpty(codeResponse.promoCodes) && ( )} - {!loading && R.isEmpty(couponResponse.coupons) && ( + {!loading && R.isEmpty(codeResponse.promoCodes) && ( -

Currently, there are no active coupon codes on your network.

- +

Currently, there are no active promo codes on your network.

+
)} - { setErrorMsg(null) setShowModal(false) }} errorMsg={errorMsg} - addCoupon={addCoupon} + addCode={addCode} /> ) } -export default Coupons +export default PromoCodes diff --git a/new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodes.styles.js b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.styles.js similarity index 100% rename from new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodes.styles.js rename to new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.styles.js diff --git a/new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodesModal.js b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodesModal.js similarity index 74% rename from new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodesModal.js rename to new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodesModal.js index 1971da85..63c47687 100644 --- a/new-lamassu-admin/src/pages/LoyaltyPanel/CouponCodesModal.js +++ b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodesModal.js @@ -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 && ( { initialValues={initialValues} validationSchema={validationSchema} onSubmit={({ code, discount }) => { - handleAddCoupon(code, discount) + handleAddCode(code, discount) }}> -
-

Coupon code name

+ +

Promo code name

{

Define discount rate

- 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.

- (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.

@@ -97,9 +98,9 @@ const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => { {errorMsg && {errorMsg}} @@ -110,4 +111,4 @@ const CouponCodesModal = ({ showModal, onClose, errorMsg, addCoupon }) => { ) } -export default CouponCodesModal +export default PromoCodesModal diff --git a/new-lamassu-admin/src/routing/routes.js b/new-lamassu-admin/src/routing/routes.js index 9bd5f879..be3e1c2c 100644 --- a/new-lamassu-admin/src/routing/routes.js +++ b/new-lamassu-admin/src/routing/routes.js @@ -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',