diff --git a/app/controllers/grant.controller.js b/app/controllers/grant.controller.js index ff23b8b..79c4f03 100644 --- a/app/controllers/grant.controller.js +++ b/app/controllers/grant.controller.js @@ -34,6 +34,7 @@ exports.createGrant = async (req, res, next) => { // get transaction transaction = await sequelize.transaction(); + // creating grant in table const grant = await Grant.create( { donor_id: user.id, @@ -48,6 +49,7 @@ exports.createGrant = async (req, res, next) => { } ); + // getting data for later use throughout await Promise.all( await organizations.map(async org => { let dbOrgs = await sequelize.query( @@ -70,7 +72,7 @@ exports.createGrant = async (req, res, next) => { }) ); - // one time charge + // one time charge with stripe helper const charge = await stripe.grantCharge({ grant, stripeToken, @@ -81,6 +83,7 @@ exports.createGrant = async (req, res, next) => { transaction }); + // mapping between bundle and orgs const grantsOrgs = organizations.map(org => { return { grant_id: grant.id, @@ -88,12 +91,11 @@ exports.createGrant = async (req, res, next) => { amount: org.finalAmountToOrg }; }); - - // mapping between bundle and orgs await GrantOrganization.bulkCreate(grantsOrgs, { transaction }); + // creating in charge table for reference await Charge.create( { id: charge.id, diff --git a/app/controllers/stripe.controller.js b/app/controllers/stripe.controller.js index 2e8e55a..e67ae64 100644 --- a/app/controllers/stripe.controller.js +++ b/app/controllers/stripe.controller.js @@ -1,6 +1,7 @@ const db = require('../../models'), errorMaker = require('../helpers/error.maker'), - requestPromise = require('request-promise'); + requestPromise = require('request-promise'), + uuidv4 = require('uuid/v4'); const stripe = require('stripe')(process.env.STRIPE_KEY); @@ -20,7 +21,27 @@ exports.grantCharge = async ({ try { const donors = await Donor.findAll({ where: { id: user.id } }); - await addCustomerPaymentSource(donors[0], stripeToken, transaction); + const paymentSourceId = await addCustomerPaymentSource( + donors[0], + stripeToken, + transaction + ); + + // set the grant's payment source id to the newly created one + await sequelize.query( + ` + UPDATE grants + SET payment_source_id = :payment_source_id + WHERE id = :grant_id`, + { + type: sequelize.QueryTypes.UPDATE, + replacements: { + payment_source_id: paymentSourceId, + grant_id: grant.id + }, + transaction + } + ); const stripeAmount = amount * 100; @@ -180,7 +201,40 @@ const addCustomerPaymentSource = async (donor, source, transaction = null) => { }); } - resolve(); + const date = new Date(); + const paymentSourceId = uuidv4(); + await sequelize.query( + ` + INSERT INTO payment_sources + (id, + token, + provider, + donor_id, + createdAt, + updatedAt + ) + VALUES + (:paymentSourceId, + :source, + :provider, + :donor_id, + :date, + :date + )`, + { + type: sequelize.QueryTypes.INSERT, + replacements: { + paymentSourceId, + source, + provider: 'stripe', + donor_id: donor.id, + date + }, + transaction + } + ); + + resolve(paymentSourceId); } catch (error) { reject(error); } diff --git a/migrations/20190511092547-create-payment-source.js b/migrations/20190511092547-create-payment-source.js new file mode 100644 index 0000000..47fe8f2 --- /dev/null +++ b/migrations/20190511092547-create-payment-source.js @@ -0,0 +1,37 @@ +'use strict'; +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.createTable('payment_sources', { + id: { + allowNull: false, + primaryKey: true, + type: Sequelize.UUID + }, + token: { + type: Sequelize.STRING + }, + provider: { + type: Sequelize.STRING + }, + donor_id: { + type: Sequelize.UUID, + allowNull: false, + references: { + model: 'donors', + key: 'id' + } + }, + createdAt: { + allowNull: false, + type: Sequelize.DATE + }, + updatedAt: { + allowNull: false, + type: Sequelize.DATE + } + }); + }, + down: (queryInterface, Sequelize) => { + return queryInterface.dropTable('PaymentSources'); + } +}; diff --git a/migrations/20190511095438-adding_payment_source_id_to_grant.js b/migrations/20190511095438-adding_payment_source_id_to_grant.js new file mode 100644 index 0000000..6f71202 --- /dev/null +++ b/migrations/20190511095438-adding_payment_source_id_to_grant.js @@ -0,0 +1,39 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + /* + Add altering commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.createTable('users', { id: Sequelize.INTEGER }); + */ + return queryInterface + .addColumn('grants', 'payment_source_id', Sequelize.UUID) + .then(() => + queryInterface.addConstraint('grants', ['payment_source_id'], { + type: 'foreign key', + name: 'grants_paymentsources_fk', + references: { + //Required field + table: 'payment_sources', + field: 'id' + }, + onDelete: 'cascade', + onUpdate: 'cascade' + }) + ); + }, + + down: (queryInterface, Sequelize) => { + /* + Add reverting commands here. + Return a promise to correctly handle asynchronicity. + + Example: + return queryInterface.dropTable('users'); + */ + return queryInterface.removeColumn('grants', 'payment_source_id'); + } +}; diff --git a/models/Grant.js b/models/Grant.js index 0cdfa37..f5bbe91 100644 --- a/models/Grant.js +++ b/models/Grant.js @@ -35,9 +35,18 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.UUID, allowNull: false, references: { - model: Donor(sequelize, DataTypes), + model: 'donors', key: 'id' } + }, + + payment_source_id: { + type: DataTypes.UUID, + references: { + //Required field + model: 'payment_sources', + field: 'id' + } } }, { diff --git a/models/PaymentSource.js b/models/PaymentSource.js new file mode 100644 index 0000000..335309d --- /dev/null +++ b/models/PaymentSource.js @@ -0,0 +1,39 @@ +'use strict'; +module.exports = (sequelize, DataTypes) => { + const PaymentSource = sequelize.define( + 'PaymentSource', + { + id: { + allowNull: false, + primaryKey: true, + type: DataTypes.UUID + }, + token: { + allowNull: false, + type: DataTypes.STRING + }, + provider: { + allowNull: false, + type: DataTypes.STRING + }, + donor_id: { + type: DataTypes.UUID, + allowNull: false, + references: { + model: 'donors', + key: 'id' + } + } + }, + { + freezeTableName: true, + + // define the table's name + tableName: 'payment_sources' + } + ); + PaymentSource.associate = function(models) { + // associations can be defined here + }; + return PaymentSource; +};