svc-promo
v1.0.2
Published
Promo service that handles all promo code operations for Luxury Escapes
Downloads
1
Readme
svc-promo
General
Generates promo codes for lux group (both experiences and luxury escapes).
Promo is a payment method, so it works closely with payment-svc and order-svc.
The service hosts the promo codes, the gift-cards and the referral codes. Giftcards are synced to SF. Best people to ask re-giftcards are Diego and Anna. Best people to ask re-referrals are Dennis and Alex.
Promos can be created from a few places:
- Admin portal LE (LE and all travel whitelable brands) // Marketing menu -> Add promo
- Admin portal EE (not travel)
- API
Promos can be used from a few clients:
- Admin portal and customer portal LE
- Admin portal and customer portal EE
- Mobile apps (iOS and Android)
Some notable promo code features:
- create a promo code with a percentage discount (does not require currency)
- create a promo code with a fixed discount (requires currency)
- create a promo code with a minimum spend X, meaning that the customer should spend at least $X in order to use the promo code
- create a promo code with usage limit X, meaning an overall usage (it can’t be used more than X times no matter if 1 or more customers used it)
- create a promo code with a usage limit per customer X, meaning that one customer can’t use it more than X times
- create a promo code with a different discount for new customers and existing customers
- create a promo code for new customers only (promo value set to 0 and promo value for new customer set to X)
- create a promo code for existing customers only (promo value set to X and promo value for new customer set to 0)
- create a promo code that can be used only if the payment is done with a specific credit card. We define a list of BIN numbers and attach it to a promo code. A BIN is the first 6 characters from a credit card number. It holds info regarding the geographic location in which the credit card is issued, also the card type credit/debit, the card scheme - visa/mastercard, bank, etc. This functionality is used for the MasterCard and American Express campaigns we have in South East Asia. Because the actual credit card payment happens after the promo is applied, we can display a warning message (checkout warning message) such as “You can use this promo code with a specific credit card only” and the message is customisable.
- create a promo code that can be used by specific customers only. When we create the promo, we attach a list of emails to it so only these customers can use this promo code
We keep info on who created the promo codes.
For the used promo codes we have a log. The results you can see in the admin portal after clicking on a promo code row in the grid with all promo codes. In the admin portal you can also search for a promo code.
How limits work - if a customer uses a promo and the payment fails (for example, due to insufficient credit card funds) - then we log the promo as used and if the limit is one per user, he/she won’t be able to use it second time. For now promo-svc is agnostic to the output of the payment process.
How a promo code works:
- At the checkout page there is “Got a Promotion Code” link that displays an input after clicking on it.
- You type the promo and click Submit. If it works it will update the payment summary, otherwise it will show an error - invalid, expired, min spend not met or something else. At the time of applying the promo code we do front-end validations but when you click the actual pay button we do back-end validations on basically everything with the help of order-svc.
Rules for editing a promo:
- If the promo code hasn’t been used, all its details can be changed through the LE admin portal. (not done for not-travel EE to this point)
- if the promo has been used, it’s just the expiry date that can be changed to a future date or the limits that can be changed to a greater number
- you can expiry a promo code any time from the admin portal grid
We have an EMPLOYEE discount of 20% but note that it can be disabled for some offers. The discount can be applied to any account that has a lux domain and has the Employee role assigned to it.
Some useful Contentful materials:
- Info about the BINs. Pleas enote some things may vary as the BIN functionality was done before the new payment flow https://aussiecommerce.atlassian.net/wiki/spaces/TEC/pages/250150913/AMEX+feature+implementation+proposal
- How do we decide if a customer is new or existing https://aussiecommerce.atlassian.net/wiki/spaces/TEC/pages/346980371/Feature+new+existing+customer
Developer Tips
Be brand aware. Promo is a shared service.
All prod db changes should go in through an SQL script that is stored in /migrations.
There are too many business requirements around the promo codes, hence tests are the only way to guarantee nothing is broken so I strongly encourage writing more tests.
Prefer "import" es modules over using "require()" as it allow for the types defined in the file to be avaialbie (yay auto-complete)
- Warning: This is not possible for all exisitng files, some of the older libs are only functional through using require().
Care should be taken when developing in svc-promo as it can be hard determine which code is the "standard" we want to follow.
Some tips:
- Prefer typescript to javascript
- Prefer es6 modules/importing to require()
- Prefer mocking to e2e unit tests (use some judgment here)
- Try and keep the db clear of configuration enums (we can use strummer/lib-regions to do this dynamically)
svc-promo is on node 16.16.0 so newer versions of packages lux-group aren't supported
There is no CI for a reason. If you’ve ever done something with the promo service on your local env you know it’s very painful to set up the whole flow from customer portal, order service, order service process-queues, payment service, payment service event-devourer and promo service. Most people don’t bother so it’s good to test the whole payment flow on the test env before deployed promo on prod. While the promo-svc has more than 100 tests, they are still not enough because of the many business requirements and edge cases.
There is a Slack channel called svc-promo. We have an alert on logs containing the word “error”. This can be refined with a better pattern since we get a lot of false positive alerts because people tend to include the “error” word in the promo descriptions.
Routes and Schemas
If you need to add an API please follow a strummer way. An example would be create gift card API See "/api/gift-card". It uses stummer schema here:
Advantages of doing it this way would be automatic OpenAPI schema generation and payload validation, that we previously had to do manually.
Rendered Swagger schema can be viewed at HOST/api/docs/promo. Raw OpenAPI schema can be downloaded from HOST/api/docs/promo/raw
Setup
Requires Node, Yarn and Postgres
- Clone this repo on your local machine
git clone [email protected]:brandsExclusive/svc-promo.git
- Copy example config:
cp .env.example .env
cp src/config/development.example.ts src/config/development.ts
Create a database for the service on your local env. For example svc_promo_development. If you use another name, please change it in the .env file as well.
Setup the db
yarn run db-migrate
- Install the node modules
yarn install
- Start the app
yarn run start
This will create an output 'build' folder containing the javascript that has been compiled.
Development
This project is setup to run locally with nodemon:
yarn run dev
this will use the configuration defined in the "nodemon.json" file
Note: this project relies on dependencies from private NPM repo, meaning that you need to have your NPM_TOKEN defined in env variables
Testing
Run tests
yarn run test
(includes database changes and linting)
yarn run js:test:local
yarn run js:test:local:watch
(includes file watching)
Typescript
This service is in the processing of migrating to typescript. Please help by developing new features in typescript and converting existing code where possible.
On require vs import
Prefer ES6 modules ("import") to "require" as it provides better typescript support (intellisense, F12-auto-naviagtion etc). You may need to convert the export of the file being imported:
// "require" style
module.exports = {
FunctionNumber1,
FunctionNumber2
}
// "import" ES6 modules
export default {
FunctionNumber1,
FunctionNumber2
}
Docker
Dockerfile included for local development. Refer to https://github.com/brandsExclusive/infra-le-local-dev for instructions with Docker Compose.
Referral Earn Options
Referral Earn Options allow a region/brand to config different referral earn options (i.e. the reward after a referral order has been made). After a successful referral, referrers can choose from referral earn option, which will then be provided.
Referral logs
The status of the Referrer's Earn is tracked via the referral logs:
referral_log_status:
- pending_cooldown - Awaiting cooldown. The referral must wait until a month after the referee booking date (to reduce fraud), these emails goes out after the first day of the month has passed.
- pending_selection - the earn email has been sent to the referrer (only when more than one earn option is avaiaible, i.e. an earn selection to be made)
- redeeming - Currently processed an earn option selection for this referral log (prevent double-click, double reward)
- redeemed - Referrer earn process complete
referrer_email_sent - Indicate the orignal "Here is your reward" email has been sent. (Only set when there is only one earn option)
referrer_earn_email_sent - The number of 'earn_emails' sent. When an earn selection email is sent, this value will be incremented
Earn Type
An Earn Type is set against each Earn Option. It determines what type of reward is provided to the Referrer. Examples:
- Credit
- (coming soon) Qantas Frequent Flyer Points
Earn Models
An Earn Models is set against each Earn Option. It is used provide different ways of calculating the Earn Amount.
Two Earn Models exist:
FlatModel - Allow for a single, flat configurable value. i.e. $50 credit
RatioModel - The amount the referrer earns is based on a configured ratio and promo value the referee received:
earn_amount = referees_promo_value * earn_ratio
Earn Amounts
An Earn Amount is the result of an Earn Model calculation. An earn_amount will be included with each referral earn option - if it can be calculated. The "RatioModel" requires the referral_log_id to lookup the promo value).
Earn Option "Condtions"
The conditons a user must meet to qualify for a Referral Earn Option. (None are currently written)