feat: individual discounts migration

feat: loyalty panel routing
chore: rename promo-codes module to loyalty
This commit is contained in:
Sérgio Salgado 2021-07-22 01:15:01 +01:00 committed by Josh Harvey
parent 576979f14f
commit 07f15db851
14 changed files with 183 additions and 55 deletions

View file

@ -26,4 +26,28 @@ function getNumberOfAvailablePromoCodes () {
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
}

View file

@ -8,10 +8,10 @@ const currency = require('./currency.resolver')
const customer = require('./customer.resolver')
const funding = require('./funding.resolver')
const log = require('./log.resolver')
const loyalty = require('./loyalty.resolver')
const machine = require('./machine.resolver')
const notification = require('./notification.resolver')
const pairing = require('./pairing.resolver')
const promo = require('./promo.resolver')
const rates = require('./rates.resolver')
const scalar = require('./scalar.resolver')
const settings = require('./settings.resolver')
@ -29,10 +29,10 @@ const resolvers = [
customer,
funding,
log,
loyalty,
machine,
notification,
pairing,
promo,
rates,
scalar,
settings,

View 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

View file

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

View file

@ -8,10 +8,10 @@ const currency = require('./currency.type')
const customer = require('./customer.type')
const funding = require('./funding.type')
const log = require('./log.type')
const loyalty = require('./loyalty.type')
const machine = require('./machine.type')
const notification = require('./notification.type')
const pairing = require('./pairing.type')
const promo = require('./promo.type')
const rates = require('./rates.type')
const scalar = require('./scalar.type')
const settings = require('./settings.type')
@ -29,10 +29,10 @@ const types = [
customer,
funding,
log,
loyalty,
machine,
notification,
pairing,
promo,
rates,
scalar,
settings,

View 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

View file

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

View file

@ -20,7 +20,7 @@ const cashOutHelper = require('./cash-out/cash-out-helper')
const machineLoader = require('./machine-loader')
const customers = require('./customers')
const commissionMath = require('./commission-math')
const promoCodes = require('./promo-codes')
const loyalty = require('./loyalty')
const { cassetteMaxCapacity } = require('./constants')
@ -229,7 +229,7 @@ function plugins (settings, deviceId) {
const testnetPromises = cryptoCodes.map(c => wallet.cryptoNetwork(settings, c))
const pingPromise = recordPing(deviceTime, machineVersion, machineModel)
const currentConfigVersionPromise = fetchCurrentConfigVersion()
const currentAvailablePromoCodes = promoCodes.getNumberOfAvailablePromoCodes()
const currentAvailablePromoCodes = loyalty.getNumberOfAvailablePromoCodes()
const timezoneObj = { utcOffset: timezone[0], dstOffset: timezone[1] }
const promises = [

View file

@ -4,11 +4,11 @@ const router = express.Router()
const BN = require('../bn')
const commissionMath = require('../commission-math')
const configManager = require('../new-config-manager')
const promoCodes = require('../promo-codes')
const loyalty = require('../loyalty')
const respond = require('../respond')
function verifyPromoCode (req, res, next) {
promoCodes.getPromoCode(req.body.codeInput)
loyalty.getPromoCode(req.body.codeInput)
.then(promoCode => {
if (!promoCode) return next()

View 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()
}

View file

@ -1,7 +1,19 @@
import { Box } from '@material-ui/core'
import React from 'react'
import { Button } from 'src/components/buttons'
import { Label3 } from 'src/components/typography'
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

View file

@ -6,9 +6,8 @@ import React, { useState } from 'react'
import { DeleteDialog } from 'src/components/DeleteDialog'
import { Link, Button, IconButton } from 'src/components/buttons'
import TitleSection from 'src/components/layout/TitleSection'
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 styles from './PromoCodes.styles'
@ -131,7 +130,6 @@ const PromoCodes = () => {
return (
<>
<TitleSection title="Promo Codes"></TitleSection>
{!loading && !R.isEmpty(codeResponse.promoCodes) && (
<Box
marginBottom={4}
@ -166,7 +164,9 @@ const PromoCodes = () => {
)}
{!loading && R.isEmpty(codeResponse.promoCodes) && (
<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>
</Box>
)}

View file

@ -7,6 +7,7 @@ import Commissions from 'src/pages/Commissions'
import { Customers, CustomerProfile } from 'src/pages/Customers'
import Funding from 'src/pages/Funding'
import Locales from 'src/pages/Locales'
import IndividualDiscounts from 'src/pages/LoyaltyPanel/IndividualDiscounts'
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
import MachineLogs from 'src/pages/MachineLogs'
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
@ -212,11 +213,37 @@ const getLamassuRoutes = () => [
component: Blacklist
},
{
key: 'promo-codes',
label: 'Promo Codes',
route: '/compliance/loyalty/codes',
key: 'loyalty',
label: 'Loyalty',
route: '/compliance/loyalty',
title: 'Loyalty Panel',
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: PromoCodes
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',
label: 'Promo Codes',
route: '/compliance/loyalty/codes',
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: PromoCodes
}
]
},
{
key: 'customer',

View file

@ -10,6 +10,7 @@ import Commissions from 'src/pages/Commissions'
import { Customers, CustomerProfile } from 'src/pages/Customers'
import Funding from 'src/pages/Funding'
import Locales from 'src/pages/Locales'
import IndividualDiscounts from 'src/pages/LoyaltyPanel/IndividualDiscounts'
import PromoCodes from 'src/pages/LoyaltyPanel/PromoCodes'
import MachineLogs from 'src/pages/MachineLogs'
import CashCassettes from 'src/pages/Maintenance/CashCassettes'
@ -207,11 +208,36 @@ const getPazuzRoutes = () => [
component: Blacklist
},
{
key: 'promo-codes',
label: 'Promo Codes',
route: '/compliance/loyalty/codes',
key: 'loyalty',
label: 'Loyalty',
route: '/compliance/loyalty',
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: PromoCodes
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',
label: 'Promo Codes',
route: '/compliance/loyalty/codes',
allowedRoles: [ROLES.USER, ROLES.SUPERUSER],
component: PromoCodes
}
]
},
{
key: 'customer',