From 07f15db8517d91759c5044b26da9fd3da69a3271 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Salgado?= Date: Thu, 22 Jul 2021 01:15:01 +0100 Subject: [PATCH] feat: individual discounts migration feat: loyalty panel routing chore: rename promo-codes module to loyalty --- lib/{promo-codes.js => loyalty.js} | 26 +++++++++++++- lib/new-admin/graphql/resolvers/index.js | 4 +-- .../graphql/resolvers/loyalty.resolver.js | 16 +++++++++ .../graphql/resolvers/promo.resolver.js | 13 ------- lib/new-admin/graphql/types/index.js | 4 +-- lib/new-admin/graphql/types/loyalty.type.js | 35 +++++++++++++++++++ lib/new-admin/graphql/types/promo.type.js | 20 ----------- lib/plugins.js | 4 +-- lib/routes/verifyPromoCodeRoutes.js | 4 +-- .../1626891847835-add-individual-discounts.js | 21 +++++++++++ .../pages/LoyaltyPanel/IndividualDiscounts.js | 14 +++++++- .../src/pages/LoyaltyPanel/PromoCodes.js | 8 ++--- .../src/routing/lamassu.routes.js | 35 ++++++++++++++++--- new-lamassu-admin/src/routing/pazuz.routes.js | 34 +++++++++++++++--- 14 files changed, 183 insertions(+), 55 deletions(-) rename lib/{promo-codes.js => loyalty.js} (51%) create mode 100644 lib/new-admin/graphql/resolvers/loyalty.resolver.js delete mode 100644 lib/new-admin/graphql/resolvers/promo.resolver.js create mode 100644 lib/new-admin/graphql/types/loyalty.type.js delete mode 100644 lib/new-admin/graphql/types/promo.type.js create mode 100644 migrations/1626891847835-add-individual-discounts.js 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',