diff --git a/lib/promo-codes.js b/lib/loyalty.js
similarity index 51%
rename from lib/promo-codes.js
rename to lib/loyalty.js
index 9bc52d85..ec61c594 100644
--- a/lib/promo-codes.js
+++ b/lib/loyalty.js
@@ -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
+}
diff --git a/lib/new-admin/graphql/resolvers/index.js b/lib/new-admin/graphql/resolvers/index.js
index cbea1123..033593d7 100644
--- a/lib/new-admin/graphql/resolvers/index.js
+++ b/lib/new-admin/graphql/resolvers/index.js
@@ -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,
diff --git a/lib/new-admin/graphql/resolvers/loyalty.resolver.js b/lib/new-admin/graphql/resolvers/loyalty.resolver.js
new file mode 100644
index 00000000..9a621451
--- /dev/null
+++ b/lib/new-admin/graphql/resolvers/loyalty.resolver.js
@@ -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
diff --git a/lib/new-admin/graphql/resolvers/promo.resolver.js b/lib/new-admin/graphql/resolvers/promo.resolver.js
deleted file mode 100644
index 8e9bd337..00000000
--- a/lib/new-admin/graphql/resolvers/promo.resolver.js
+++ /dev/null
@@ -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
diff --git a/lib/new-admin/graphql/types/index.js b/lib/new-admin/graphql/types/index.js
index 0d60c2ba..8745bdb3 100644
--- a/lib/new-admin/graphql/types/index.js
+++ b/lib/new-admin/graphql/types/index.js
@@ -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,
diff --git a/lib/new-admin/graphql/types/loyalty.type.js b/lib/new-admin/graphql/types/loyalty.type.js
new file mode 100644
index 00000000..ba84e032
--- /dev/null
+++ b/lib/new-admin/graphql/types/loyalty.type.js
@@ -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
diff --git a/lib/new-admin/graphql/types/promo.type.js b/lib/new-admin/graphql/types/promo.type.js
deleted file mode 100644
index 2c9fb3be..00000000
--- a/lib/new-admin/graphql/types/promo.type.js
+++ /dev/null
@@ -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
diff --git a/lib/plugins.js b/lib/plugins.js
index f273c240..2bce6972 100644
--- a/lib/plugins.js
+++ b/lib/plugins.js
@@ -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 = [
diff --git a/lib/routes/verifyPromoCodeRoutes.js b/lib/routes/verifyPromoCodeRoutes.js
index 2a281694..6789a322 100644
--- a/lib/routes/verifyPromoCodeRoutes.js
+++ b/lib/routes/verifyPromoCodeRoutes.js
@@ -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()
diff --git a/migrations/1626891847835-add-individual-discounts.js b/migrations/1626891847835-add-individual-discounts.js
new file mode 100644
index 00000000..037ec658
--- /dev/null
+++ b/migrations/1626891847835-add-individual-discounts.js
@@ -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()
+}
diff --git a/new-lamassu-admin/src/pages/LoyaltyPanel/IndividualDiscounts.js b/new-lamassu-admin/src/pages/LoyaltyPanel/IndividualDiscounts.js
index 86abb547..e1c7806a 100644
--- a/new-lamassu-admin/src/pages/LoyaltyPanel/IndividualDiscounts.js
+++ b/new-lamassu-admin/src/pages/LoyaltyPanel/IndividualDiscounts.js
@@ -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 (
+
+
+ It seems there are no active individual customer discounts on your
+ network.
+
+
+
+ )
}
export default IndividualDiscounts
diff --git a/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js
index 1d1fa9cb..22d91322 100644
--- a/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js
+++ b/new-lamassu-admin/src/pages/LoyaltyPanel/PromoCodes.js
@@ -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 (
<>
-
{!loading && !R.isEmpty(codeResponse.promoCodes) && (
{
)}
{!loading && R.isEmpty(codeResponse.promoCodes) && (
- Currently, there are no active promo codes on your network.
+
+ Currently, there are no active promo codes on your network.
+
)}
diff --git a/new-lamassu-admin/src/routing/lamassu.routes.js b/new-lamassu-admin/src/routing/lamassu.routes.js
index 0769488e..1e8e1ff3 100644
--- a/new-lamassu-admin/src/routing/lamassu.routes.js
+++ b/new-lamassu-admin/src/routing/lamassu.routes.js
@@ -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 () => (
+
+ )
+ },
+ 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',
diff --git a/new-lamassu-admin/src/routing/pazuz.routes.js b/new-lamassu-admin/src/routing/pazuz.routes.js
index 092ee0c7..81cf8c36 100644
--- a/new-lamassu-admin/src/routing/pazuz.routes.js
+++ b/new-lamassu-admin/src/routing/pazuz.routes.js
@@ -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 () => (
+
+ )
+ },
+ 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',