feat: individual discounts migration
feat: loyalty panel routing chore: rename promo-codes module to loyalty
This commit is contained in:
parent
576979f14f
commit
07f15db851
14 changed files with 183 additions and 55 deletions
|
|
@ -26,4 +26,28 @@ function getNumberOfAvailablePromoCodes () {
|
||||||
return db.one(sql).then(res => res.count)
|
return db.one(sql).then(res => res.count)
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = { getAvailablePromoCodes, getPromoCode, createPromoCode, deletePromoCode, getNumberOfAvailablePromoCodes }
|
function getAvailableIndividualDiscounts () {
|
||||||
|
const sql = `SELECT * from individual_discounts WHERE soft_deleted=false`
|
||||||
|
return db.any(sql)
|
||||||
|
}
|
||||||
|
|
||||||
|
function createIndividualDiscount (idType, value, discount) {
|
||||||
|
const sql = `INSERT INTO individual_discounts (id, identification, value, discount) VALUES ($1, $2, $3, $4) RETURNING *`
|
||||||
|
return db.one(sql, [uuid.v4(), idType, value, discount])
|
||||||
|
}
|
||||||
|
|
||||||
|
function deleteIndividualDiscount (id) {
|
||||||
|
const sql = `UPDATE individual_discounts SET soft_deleted=true WHERE id=$1`
|
||||||
|
return db.none(sql, [id])
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getAvailablePromoCodes,
|
||||||
|
getPromoCode,
|
||||||
|
createPromoCode,
|
||||||
|
deletePromoCode,
|
||||||
|
getNumberOfAvailablePromoCodes,
|
||||||
|
getAvailableIndividualDiscounts,
|
||||||
|
createIndividualDiscount,
|
||||||
|
deleteIndividualDiscount
|
||||||
|
}
|
||||||
|
|
@ -8,10 +8,10 @@ const currency = require('./currency.resolver')
|
||||||
const customer = require('./customer.resolver')
|
const customer = require('./customer.resolver')
|
||||||
const funding = require('./funding.resolver')
|
const funding = require('./funding.resolver')
|
||||||
const log = require('./log.resolver')
|
const log = require('./log.resolver')
|
||||||
|
const loyalty = require('./loyalty.resolver')
|
||||||
const machine = require('./machine.resolver')
|
const machine = require('./machine.resolver')
|
||||||
const notification = require('./notification.resolver')
|
const notification = require('./notification.resolver')
|
||||||
const pairing = require('./pairing.resolver')
|
const pairing = require('./pairing.resolver')
|
||||||
const promo = require('./promo.resolver')
|
|
||||||
const rates = require('./rates.resolver')
|
const rates = require('./rates.resolver')
|
||||||
const scalar = require('./scalar.resolver')
|
const scalar = require('./scalar.resolver')
|
||||||
const settings = require('./settings.resolver')
|
const settings = require('./settings.resolver')
|
||||||
|
|
@ -29,10 +29,10 @@ const resolvers = [
|
||||||
customer,
|
customer,
|
||||||
funding,
|
funding,
|
||||||
log,
|
log,
|
||||||
|
loyalty,
|
||||||
machine,
|
machine,
|
||||||
notification,
|
notification,
|
||||||
pairing,
|
pairing,
|
||||||
promo,
|
|
||||||
rates,
|
rates,
|
||||||
scalar,
|
scalar,
|
||||||
settings,
|
settings,
|
||||||
|
|
|
||||||
16
lib/new-admin/graphql/resolvers/loyalty.resolver.js
Normal file
16
lib/new-admin/graphql/resolvers/loyalty.resolver.js
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
const loyalty = require('../../../loyalty')
|
||||||
|
|
||||||
|
const resolvers = {
|
||||||
|
Query: {
|
||||||
|
promoCodes: () => loyalty.getAvailablePromoCodes(),
|
||||||
|
individualDiscounts: () => loyalty.getAvailableIndividualDiscounts()
|
||||||
|
},
|
||||||
|
Mutation: {
|
||||||
|
createPromoCode: (...[, { code, discount }]) => loyalty.createPromoCode(code, discount),
|
||||||
|
deletePromoCode: (...[, { codeId }]) => loyalty.deletePromoCode(codeId),
|
||||||
|
createIndividualDiscount: (...[, { identificationType, value, discount }]) => loyalty.createIndividualDiscount(identificationType, value, discount),
|
||||||
|
deleteIndividualDiscount: (...[, { discountId }]) => loyalty.deleteIndividualDiscount(discountId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = resolvers
|
||||||
|
|
@ -1,13 +0,0 @@
|
||||||
const promoCodeManager = require('../../../promo-codes')
|
|
||||||
|
|
||||||
const resolvers = {
|
|
||||||
Query: {
|
|
||||||
promoCodes: () => promoCodeManager.getAvailablePromoCodes()
|
|
||||||
},
|
|
||||||
Mutation: {
|
|
||||||
createPromoCode: (...[, { code, discount }]) => promoCodeManager.createPromoCode(code, discount),
|
|
||||||
deletePromoCode: (...[, { codeId }]) => promoCodeManager.deletePromoCode(codeId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = resolvers
|
|
||||||
|
|
@ -8,10 +8,10 @@ const currency = require('./currency.type')
|
||||||
const customer = require('./customer.type')
|
const customer = require('./customer.type')
|
||||||
const funding = require('./funding.type')
|
const funding = require('./funding.type')
|
||||||
const log = require('./log.type')
|
const log = require('./log.type')
|
||||||
|
const loyalty = require('./loyalty.type')
|
||||||
const machine = require('./machine.type')
|
const machine = require('./machine.type')
|
||||||
const notification = require('./notification.type')
|
const notification = require('./notification.type')
|
||||||
const pairing = require('./pairing.type')
|
const pairing = require('./pairing.type')
|
||||||
const promo = require('./promo.type')
|
|
||||||
const rates = require('./rates.type')
|
const rates = require('./rates.type')
|
||||||
const scalar = require('./scalar.type')
|
const scalar = require('./scalar.type')
|
||||||
const settings = require('./settings.type')
|
const settings = require('./settings.type')
|
||||||
|
|
@ -29,10 +29,10 @@ const types = [
|
||||||
customer,
|
customer,
|
||||||
funding,
|
funding,
|
||||||
log,
|
log,
|
||||||
|
loyalty,
|
||||||
machine,
|
machine,
|
||||||
notification,
|
notification,
|
||||||
pairing,
|
pairing,
|
||||||
promo,
|
|
||||||
rates,
|
rates,
|
||||||
scalar,
|
scalar,
|
||||||
settings,
|
settings,
|
||||||
|
|
|
||||||
35
lib/new-admin/graphql/types/loyalty.type.js
Normal file
35
lib/new-admin/graphql/types/loyalty.type.js
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
const { gql } = require('apollo-server-express')
|
||||||
|
|
||||||
|
const typeDef = gql`
|
||||||
|
type IndividualDiscount {
|
||||||
|
id: ID!
|
||||||
|
identificationType: DiscountIdentificationType
|
||||||
|
value: String!
|
||||||
|
discount: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DiscountIdentificationType {
|
||||||
|
phone
|
||||||
|
idCard
|
||||||
|
}
|
||||||
|
|
||||||
|
type PromoCode {
|
||||||
|
id: ID!
|
||||||
|
code: String!
|
||||||
|
discount: Int
|
||||||
|
}
|
||||||
|
|
||||||
|
type Query {
|
||||||
|
promoCodes: [PromoCode] @auth
|
||||||
|
individualDiscounts: [IndividualDiscount] @auth
|
||||||
|
}
|
||||||
|
|
||||||
|
type Mutation {
|
||||||
|
createPromoCode(code: String!, discount: Int!): PromoCode @auth
|
||||||
|
deletePromoCode(codeId: ID!): PromoCode @auth
|
||||||
|
createIndividualDiscount(identificationType: DiscountIdentificationType!, value: String!, discount: Int!): IndividualDiscount @auth
|
||||||
|
deleteIndividualDiscount(discountId: ID!): IndividualDiscount @auth
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
module.exports = typeDef
|
||||||
|
|
@ -1,20 +0,0 @@
|
||||||
const { gql } = require('apollo-server-express')
|
|
||||||
|
|
||||||
const typeDef = gql`
|
|
||||||
type PromoCode {
|
|
||||||
id: ID!
|
|
||||||
code: String!
|
|
||||||
discount: Int
|
|
||||||
}
|
|
||||||
|
|
||||||
type Query {
|
|
||||||
promoCodes: [PromoCode] @auth
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mutation {
|
|
||||||
createPromoCode(code: String!, discount: Int!): PromoCode @auth
|
|
||||||
deletePromoCode(codeId: ID!): PromoCode @auth
|
|
||||||
}
|
|
||||||
`
|
|
||||||
|
|
||||||
module.exports = typeDef
|
|
||||||
|
|
@ -20,7 +20,7 @@ const cashOutHelper = require('./cash-out/cash-out-helper')
|
||||||
const machineLoader = require('./machine-loader')
|
const machineLoader = require('./machine-loader')
|
||||||
const customers = require('./customers')
|
const customers = require('./customers')
|
||||||
const commissionMath = require('./commission-math')
|
const commissionMath = require('./commission-math')
|
||||||
const promoCodes = require('./promo-codes')
|
const loyalty = require('./loyalty')
|
||||||
|
|
||||||
const { cassetteMaxCapacity } = require('./constants')
|
const { cassetteMaxCapacity } = require('./constants')
|
||||||
|
|
||||||
|
|
@ -229,7 +229,7 @@ function plugins (settings, deviceId) {
|
||||||
const testnetPromises = cryptoCodes.map(c => wallet.cryptoNetwork(settings, c))
|
const testnetPromises = cryptoCodes.map(c => wallet.cryptoNetwork(settings, c))
|
||||||
const pingPromise = recordPing(deviceTime, machineVersion, machineModel)
|
const pingPromise = recordPing(deviceTime, machineVersion, machineModel)
|
||||||
const currentConfigVersionPromise = fetchCurrentConfigVersion()
|
const currentConfigVersionPromise = fetchCurrentConfigVersion()
|
||||||
const currentAvailablePromoCodes = promoCodes.getNumberOfAvailablePromoCodes()
|
const currentAvailablePromoCodes = loyalty.getNumberOfAvailablePromoCodes()
|
||||||
const timezoneObj = { utcOffset: timezone[0], dstOffset: timezone[1] }
|
const timezoneObj = { utcOffset: timezone[0], dstOffset: timezone[1] }
|
||||||
|
|
||||||
const promises = [
|
const promises = [
|
||||||
|
|
|
||||||
|
|
@ -4,11 +4,11 @@ const router = express.Router()
|
||||||
const BN = require('../bn')
|
const BN = require('../bn')
|
||||||
const commissionMath = require('../commission-math')
|
const commissionMath = require('../commission-math')
|
||||||
const configManager = require('../new-config-manager')
|
const configManager = require('../new-config-manager')
|
||||||
const promoCodes = require('../promo-codes')
|
const loyalty = require('../loyalty')
|
||||||
const respond = require('../respond')
|
const respond = require('../respond')
|
||||||
|
|
||||||
function verifyPromoCode (req, res, next) {
|
function verifyPromoCode (req, res, next) {
|
||||||
promoCodes.getPromoCode(req.body.codeInput)
|
loyalty.getPromoCode(req.body.codeInput)
|
||||||
.then(promoCode => {
|
.then(promoCode => {
|
||||||
if (!promoCode) return next()
|
if (!promoCode) return next()
|
||||||
|
|
||||||
|
|
|
||||||
21
migrations/1626891847835-add-individual-discounts.js
Normal file
21
migrations/1626891847835-add-individual-discounts.js
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
var db = require('./db')
|
||||||
|
|
||||||
|
exports.up = function (next) {
|
||||||
|
var sql = [
|
||||||
|
`CREATE TYPE individual_discount_identification_type AS ENUM('phone', 'id_number')`,
|
||||||
|
`CREATE TABLE individual_discounts (
|
||||||
|
id UUID PRIMARY KEY,
|
||||||
|
identification individual_discount_identification_type NOT NULL,
|
||||||
|
value TEXT NOT NULL,
|
||||||
|
discount SMALLINT NOT NULL,
|
||||||
|
soft_deleted BOOLEAN DEFAULT false
|
||||||
|
)`,
|
||||||
|
`CREATE UNIQUE INDEX uq_individual_discount ON individual_discounts (value) WHERE NOT soft_deleted`
|
||||||
|
]
|
||||||
|
|
||||||
|
db.multi(sql, next)
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.down = function (next) {
|
||||||
|
next()
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,19 @@
|
||||||
|
import { Box } from '@material-ui/core'
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
|
|
||||||
|
import { Button } from 'src/components/buttons'
|
||||||
|
import { Label3 } from 'src/components/typography'
|
||||||
|
|
||||||
const IndividualDiscounts = () => {
|
const IndividualDiscounts = () => {
|
||||||
return <></>
|
return (
|
||||||
|
<Box display="flex" alignItems="left" flexDirection="column">
|
||||||
|
<Label3>
|
||||||
|
It seems there are no active individual customer discounts on your
|
||||||
|
network.
|
||||||
|
</Label3>
|
||||||
|
<Button>Add individual discount</Button>
|
||||||
|
</Box>
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
export default IndividualDiscounts
|
export default IndividualDiscounts
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,8 @@ import React, { useState } from 'react'
|
||||||
|
|
||||||
import { DeleteDialog } from 'src/components/DeleteDialog'
|
import { DeleteDialog } from 'src/components/DeleteDialog'
|
||||||
import { Link, Button, IconButton } from 'src/components/buttons'
|
import { Link, Button, IconButton } from 'src/components/buttons'
|
||||||
import TitleSection from 'src/components/layout/TitleSection'
|
|
||||||
import DataTable from 'src/components/tables/DataTable'
|
import DataTable from 'src/components/tables/DataTable'
|
||||||
import { H2, TL1 } from 'src/components/typography'
|
import { Label3, TL1 } from 'src/components/typography'
|
||||||
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
|
import { ReactComponent as DeleteIcon } from 'src/styling/icons/action/delete/enabled.svg'
|
||||||
|
|
||||||
import styles from './PromoCodes.styles'
|
import styles from './PromoCodes.styles'
|
||||||
|
|
@ -131,7 +130,6 @@ const PromoCodes = () => {
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<TitleSection title="Promo Codes"></TitleSection>
|
|
||||||
{!loading && !R.isEmpty(codeResponse.promoCodes) && (
|
{!loading && !R.isEmpty(codeResponse.promoCodes) && (
|
||||||
<Box
|
<Box
|
||||||
marginBottom={4}
|
marginBottom={4}
|
||||||
|
|
@ -166,7 +164,9 @@ const PromoCodes = () => {
|
||||||
)}
|
)}
|
||||||
{!loading && R.isEmpty(codeResponse.promoCodes) && (
|
{!loading && R.isEmpty(codeResponse.promoCodes) && (
|
||||||
<Box display="flex" alignItems="left" flexDirection="column">
|
<Box display="flex" alignItems="left" flexDirection="column">
|
||||||
<H2>Currently, there are no active promo codes on your network.</H2>
|
<Label3>
|
||||||
|
Currently, there are no active promo codes on your network.
|
||||||
|
</Label3>
|
||||||
<Button onClick={toggleModal}>Add Code</Button>
|
<Button onClick={toggleModal}>Add Code</Button>
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import Commissions from 'src/pages/Commissions'
|
||||||
import { Customers, CustomerProfile } from 'src/pages/Customers'
|
import { Customers, CustomerProfile } from 'src/pages/Customers'
|
||||||
import Funding from 'src/pages/Funding'
|
import Funding from 'src/pages/Funding'
|
||||||
import Locales from 'src/pages/Locales'
|
import Locales from 'src/pages/Locales'
|
||||||
|
import IndividualDiscounts from 'src/pages/LoyaltyPanel/IndividualDiscounts'
|
||||||
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
|
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
|
||||||
import MachineLogs from 'src/pages/MachineLogs'
|
import MachineLogs from 'src/pages/MachineLogs'
|
||||||
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
|
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
|
||||||
|
|
@ -211,12 +212,38 @@ const getLamassuRoutes = () => [
|
||||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
component: Blacklist
|
component: Blacklist
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'loyalty',
|
||||||
|
label: 'Loyalty',
|
||||||
|
route: '/compliance/loyalty',
|
||||||
|
title: 'Loyalty Panel',
|
||||||
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
|
get component() {
|
||||||
|
return () => (
|
||||||
|
<Redirect
|
||||||
|
to={{
|
||||||
|
pathname: this.children[0].route,
|
||||||
|
state: { prev: this.state?.prev }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: 'individual-discounts',
|
||||||
|
label: 'Individual Discounts',
|
||||||
|
route: '/compliance/loyalty/individual-discounts',
|
||||||
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
|
component: IndividualDiscounts
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'promo-codes',
|
key: 'promo-codes',
|
||||||
label: 'Promo Codes',
|
label: 'Promo Codes',
|
||||||
route: '/compliance/loyalty/codes',
|
route: '/compliance/loyalty/codes',
|
||||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
component: PromoCodes
|
component: PromoCodes
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'customer',
|
key: 'customer',
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ import Commissions from 'src/pages/Commissions'
|
||||||
import { Customers, CustomerProfile } from 'src/pages/Customers'
|
import { Customers, CustomerProfile } from 'src/pages/Customers'
|
||||||
import Funding from 'src/pages/Funding'
|
import Funding from 'src/pages/Funding'
|
||||||
import Locales from 'src/pages/Locales'
|
import Locales from 'src/pages/Locales'
|
||||||
|
import IndividualDiscounts from 'src/pages/LoyaltyPanel/IndividualDiscounts'
|
||||||
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
|
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
|
||||||
import MachineLogs from 'src/pages/MachineLogs'
|
import MachineLogs from 'src/pages/MachineLogs'
|
||||||
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
|
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
|
||||||
|
|
@ -206,12 +207,37 @@ const getPazuzRoutes = () => [
|
||||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
component: Blacklist
|
component: Blacklist
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
key: 'loyalty',
|
||||||
|
label: 'Loyalty',
|
||||||
|
route: '/compliance/loyalty',
|
||||||
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
|
get component() {
|
||||||
|
return () => (
|
||||||
|
<Redirect
|
||||||
|
to={{
|
||||||
|
pathname: this.children[0].route,
|
||||||
|
state: { prev: this.state?.prev }
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
},
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
key: 'individual-discounts',
|
||||||
|
label: 'Individual Discounts',
|
||||||
|
route: '/compliance/loyalty/individual-discounts',
|
||||||
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
|
component: IndividualDiscounts
|
||||||
|
},
|
||||||
{
|
{
|
||||||
key: 'promo-codes',
|
key: 'promo-codes',
|
||||||
label: 'Promo Codes',
|
label: 'Promo Codes',
|
||||||
route: '/compliance/loyalty/codes',
|
route: '/compliance/loyalty/codes',
|
||||||
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
|
||||||
component: PromoCodes
|
component: PromoCodes
|
||||||
|
}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: 'customer',
|
key: 'customer',
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue