UNPKG

ilp-core

Version:

ILP core module managing ledger abstraction

189 lines (160 loc) 5.44 kB
'use strict' module.exports = PaymentFactory const _ = require('lodash') const Container = require('constitute').Container const Model = require('five-bells-shared').Model const InvalidBodyError = require('five-bells-shared/errors/invalid-body-error') const PersistentModelMixin = require('five-bells-shared').PersistentModelMixin const Validator = require('five-bells-shared/lib/validator') const Sequelize = require('sequelize') const debug = require('debug')('ilp-kit:payment-model') const Database = require('../lib/db') const UserFactory = require('./user') const ActivityLogFactory = require('./activity_log') const ActivityLogsItemFactory = require('./activity_logs_item') PaymentFactory.constitute = [Database, Validator, Container, UserFactory] function PaymentFactory (sequelize, validator, container, User) { let ActivityLog class Payment extends Model { static convertFromExternal (data) { return data } static convertToExternal (data) { delete data.source_user delete data.destination_user delete data.completed_at return data } static convertFromPersistent (data) { delete data.updated_at data = _.omit(data, _.isNull) return data } static convertToPersistent (data) { return data } static createBodyParser () { const Self = this return function * (next) { let json = this.body const validationResult = Self.validateExternal(json) if (validationResult.valid !== true) { const message = validationResult.schema ? 'Body did not match schema ' + validationResult.schema : 'Body did not pass validation' throw new InvalidBodyError(message, validationResult.errors) } const model = new Self() model.setDataExternal(json) this.body = model yield next } } static * getUserStats (user) { const result = yield sequelize.query( 'SELECT source_identifier, destination_identifier,' + ' sum(source_amount) as source_amount,' + ' source_name,' + ' source_image_url,' + ' sum(destination_amount) as destination_amount,' + ' destination_name,' + ' destination_image_url,' + ' count(*) as transfers_count,' + ' max(created_at) AS recent_date' + ' FROM "Payments"' + ' WHERE state = \'success\' ' + ' AND (' + ' source_user = :id ' + ' OR source_identifier = :identifier ' + ' OR destination_user = :id ' + ' OR destination_identifier = :identifier ' + ' )' + ' GROUP BY source_identifier, source_name, source_image_url, ' + 'destination_identifier, destination_name, destination_image_url' + ' ORDER BY recent_date DESC', { replacements: {id: user.id, identifier: user.identifier}, type: sequelize.QueryTypes.SELECT } ) return result[0] } static * createOrUpdate (payment) { debug('createOrUpdate', payment) // Get the db entry let dbPayment = yield Payment.findOne({ where: { transfer: payment.transfer } }) debug('createOrUpdate payment', dbPayment) // Create the db entry if it doesn't exist yet if (!dbPayment) { dbPayment = new Payment() debug('createOrUpdate creating payment') } dbPayment.setDataExternal(payment) return dbPayment.save() } } Payment.validateExternal = validator.create('Payment') PersistentModelMixin(Payment, sequelize, { id: { type: Sequelize.UUID, primaryKey: true, defaultValue: Sequelize.UUIDV4 }, source_user: Sequelize.INTEGER, source_identifier: Sequelize.STRING(1024), source_amount: Sequelize.FLOAT, source_name: Sequelize.STRING, source_image_url: Sequelize.STRING, destination_user: Sequelize.INTEGER, destination_identifier: Sequelize.STRING(1024), destination_amount: Sequelize.FLOAT, destination_name: Sequelize.STRING, destination_image_url: Sequelize.STRING, transfer: { type: Sequelize.STRING(512), unique: true }, state: Sequelize.STRING('20'), message: Sequelize.STRING(1024), // TODO decide on the size execution_condition: Sequelize.STRING(1024), // TODO decide on the size created_at: Sequelize.DATE, completed_at: Sequelize.DATE }, { indexes: [ { name: 'Payments_execution_condition_idx', method: 'BTREE', fields: ['execution_condition'] } ] }) container.schedulePostConstructor(User => { Payment.DbModel.belongsTo(User.DbModel, { foreignKey: 'source_user', as: 'SourceUser' }) Payment.DbModel.belongsTo(User.DbModel, { foreignKey: 'destination_user', as: 'DestinationUser' }) }, [ UserFactory ]) container.schedulePostConstructor(model => { ActivityLog = model container.schedulePostConstructor(ActivityLogsItem => { Payment.DbModel.belongsToMany(ActivityLog.DbModel, { through: { model: ActivityLogsItem.DbModel, unique: false, scope: { item_type: 'payment' } }, foreignKey: 'item_id', constraints: false }) }, [ ActivityLogsItemFactory ]) }, [ ActivityLogFactory ]) return Payment }