<repo_name>zakywtf/mini-e-wallet-pretest-<file_sep>/src/lib/signupHandler.js
import bcrypt from '<PASSWORD>js'
import users from '../schema/users'
import userBalanceModel from '../model/userBalanceModel';

const USERBALANCE = new userBalanceModel()

const signup = async(body) => {
    const {username, password} = body
    body.password = <PASSWORD>.hashSync(username+password+process.env.SALT, 10);
    body.level=2
    let userData = new users(body)
    // console.log(body);
    var data = await userData.save()
    console.log({data});
    await USERBALANCE.saveInitBalance(data.id)
    return true
}

module.exports ={
    signup
}<file_sep>/src/model/balanceBankModel.js
import Models from '../classes/classModel';
import balance_bank from '../schema/balance_bank';

class balanceBankModel extends Models{
    constructor(){
        super(balance_bank)
    }

}

module.exports=balanceBankModel<file_sep>/src/model/balanceBankHistoryModel.js
import Models from '../classes/classModel';
import balance_bank_history from '../schema/balance_bank_history';

class balanceBankHistoryModel extends Models{
    constructor(){
        super(balance_bank_history)
    }

    async saveHistory(balance_bank_id, balance_before, balance_after, activity, tipe, ip, location, user_agent, author){
        console.log({balance_bank_id, balance_before, balance_after, activity, tipe, ip, location, user_agent, author});
        var history = await this.model.create({
            balance_bank_id,
            balance_before,
            balance_after,
            activity,
            tipe,
            ip,
            location,
            user_agent,
            author
        })
        // console.log({history});
        
        return history
    }
}

module.exports=balanceBankHistoryModel<file_sep>/src/controller/logout.js
import {Router} from 'express'
import {decode, deleteSession} from '../lib/sessionHandler';
import handleRequest from '../lib/ctrlHandler'

let router = Router()

router.route('/')
    .post(
        async (req,res) =>{
            handleRequest(req,res,async(body)=>{
                var dc = await decode(req.headers['token'])
                var udata = dc.payload.payload
                return await deleteSession(udata)
            })
        }
    )

module.exports=router<file_sep>/README.md
# express.js

1. npm install --save
2. npm run debug >> /dev/null
3. import file "tes_privyid.postman_collection.json" di postmant collection untuk melakukan tes

step tes di postman

1. signup
2. signin
3. logout
4. create balance bank terlebih dahulu
5. user topup
6. user transfer
<file_sep>/src/schema/user_balance.js
let mongoose = require('mongoose')
let Schema = mongoose.Schema
const user_balance = mongoose.Schema({
    user_id:{type: Schema.Types.ObjectId, autopopulate:{ select: 'username level' }, ref:'users'},
    balance: { type: Number, default:0},
    balance_achieve: {type:Number, default:0}
})
user_balance.plugin(require('mongoose-autopopulate'))

module.exports = mongoose.model('user_balance', user_balance);<file_sep>/src/schema/users.js
let mongoose = require('mongoose')

const users = mongoose.Schema({
    username: { type: String, required: true,},
    password: {  type: String, required: true },
    level: String,
    createAt: {type:Date, default:Date.now}
})

users.index({username:1},{unique:true})

module.exports = mongoose.model('users', users);<file_sep>/src/lib/masterCache.js
import fetch from 'node-fetch';
import balanceBankModel from '../model/balanceBankModel';
import balanceBankHistoryModel from '../model/balanceBankHistoryModel';
import userBalance from '../model/userBalanceModel';
import userBalanceHistory from '../model/userBalanceHistoryModel';

const BALANCEBANKMODEL = new balanceBankModel()
const BALANCEBANKHISTORYMODEL = new balanceBankHistoryModel()
const USERBALANCE = new userBalance()
const USERBALANCEHISTORY = new userBalanceHistory()

const BALANCEBANKLIST = {}
const USERBALANCELIST = {}


const getData=async(url)=>await fetch(url).then(resp=>resp.json()).then(json=>json).catch(error=>error);

const getGeoLocation = async(ip, userAgent) => {
    try {
        return await getData(`https://ipapi.co/${ip}/json/`);
    } catch (error) {
        throw error;
    }
}

const loadBalanceBank = async() => {
    const data = await BALANCEBANKMODEL.getAll()
    await Promise.all(data.map((v)=>{
        BALANCEBANKLIST[`${v.id}`]=v._doc
    }))
}

const loadUserBalance = async() => {
    const datas = await USERBALANCE.getAll()
    await Promise.all(datas.map((v)=>{
        USERBALANCELIST[`${v._doc.user_id.id}`]={id:v.id, balance:v._doc.balance, balance_achieve:v._doc.balance_achieve}
    }))
}

const saveBalanceBank=async(id, balance)=>{
    let data = await BALANCEBANKMODEL.getById(id)
    // console.log({data});
    data.balance = balance
    data.save()
}

const updateUserBalanceTransfer=async(id, balance)=>{
    let data = await USERBALANCE.getById(id)
    // console.log({data});
    data.balance += balance
    data.save()
}

const updateUserBalanceTopup=async(userId, topup)=>{
    const user_balance = USERBALANCELIST[`${userId}`]
    if(user_balance){
        user_balance.balance += topup
        user_balance.balance_achieve += topup

        let data = await USERBALANCE.getById(user_balance.id)
        data.balance = user_balance.balance
        data.balance_achieve = user_balance.balance_achieve
        data.save()
    }

}

const processTopup=async(bankId, topup, tipe, ip, user_agent, userId)=>{
    const bank = BALANCEBANKLIST[`${bankId}`]

    if(bank){
        const min = topup * -1
        const balance_before = bank.balance
        bank.balance += min
        const balance_after = bank.balance
        const activity = "Topup"
        const location = await getGeoLocation(ip)

        await saveBalanceBank(bankId, bank.balance)
        await updateUserBalanceTopup(userId, topup)
        return await BALANCEBANKHISTORYMODEL.saveHistory(bankId, balance_before, balance_after, activity, tipe, ip, location.city, user_agent.source, user_agent.platform)
    }
}

const processTransfer=async(userId, transfer, tipe, ip, user_agent)=>{
    const user_balance = USERBALANCELIST[`${userId}`]

    if(user_balance){
        const min = transfer * -1
        const balance_before = user_balance.balance
        user_balance.balance += min
        const balance_after = user_balance.balance
        const activity = "Transfer"
        const location = await getGeoLocation(ip)
        const balanceId = user_balance.id

        await updateUserBalanceTransfer(balanceId, min)
        return await USERBALANCEHISTORY.saveHistory(balanceId, balance_before, balance_after, activity, tipe, ip, location.city, user_agent.source, user_agent.platform)
    }
}

console.log({BALANCEBANKLIST, USERBALANCELIST});


module.exports={
    loadBalanceBank,
    loadUserBalance,
    processTopup,
    processTransfer
}<file_sep>/src/model/userBalanceModel.js
import Models from '../classes/classModel';
import user_balance from '../schema/user_balance';

class userBalanceModel extends Models{
    constructor(){
        super(user_balance)
    }

    async saveInitBalance(user_id){
        const doc = await this.model.create({
            user_id
        })
        await doc.save()
        return doc;
    }

}

module.exports=userBalanceModel<file_sep>/src/schema/balance_bank.js
let mongoose = require('mongoose')

const balance_bank = mongoose.Schema({
    balance: { type: Number, default:0},
    balance_achieve: {type:Number, default:0},
    code:String,
    enable:{type:Boolean, default:true},   

})

module.exports = mongoose.model('balance_bank', balance_bank);<file_sep>/src/model/userModel.js
import Models from '../classes/classModel';
import users from '../schema/users';

class userModel extends Models{
    constructor(){
        super(users)
    }

    async getAll(){
        var udata = this.udata.payload
        console.log({udata:this.udata.payload});
        
        // if(udata.role != this.role)throw Error('You do not have access!')
        return await this.model.find({},this.getProjection())
    }

    getProjection(){
        return 'username level'
    }
}

module.exports=userModel<file_sep>/src/schema/user_balance_history.js
let mongoose = require('mongoose')
let Schema = mongoose.Schema
const user_balance_history = mongoose.Schema({
    user_balance_id:{type: Schema.Types.ObjectId, autopopulate:true, ref:'user_balance'},
    balance_before: { type: Number, default:0},
    balance_after: {type:Number, default:0},
    activity:String,
    tipe:{type:String, enum:['credit', 'debit']},
    ip:String,
    location:String,
    user_agent:String,
    author:String
})
user_balance_history.plugin(require('mongoose-autopopulate'))

module.exports = mongoose.model('user_balance_history', user_balance_history);