Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import ShoutoutError from "../../lib/ShoutoutError";
- import { IProposalForSend, ICampaignProposal } from '../../interfaces/marketers'
- import Campaigns from '../marketers/campaigns'
- import * as _ from 'lodash'
- enum Channel {
- SINGLE = 1,
- OMNI
- }
- enum DealConfig {
- PREDEFINED=1,
- AUCTION
- }
- class Proposals {
- private static async _getDealsByIds(client, proposals, campaign_id) {
- // get deals which ids are in request; connect them with influencers who own them
- const params = proposals.map(p=>p.deal_id)
- const q = `
- SELECT
- deal.id AS deal_id,
- deal.deal_config_id AS deal_config_id,
- deal.deal_type_id AS deal_type_id,
- deal.brief AS deal_brief,
- deal.price AS deal_price,
- deal.influencer_id AS deal_influencer_id,
- deal.platform_id AS deal_platform_id,
- q.influencer_id AS candidate_id
- FROM
- deal FULL OUTER JOIN (SELECT influencer_id FROM campaign_candidate WHERE campaign_id=$1) AS q
- ON deal.influencer_id = q.influencer_id
- WHERE deal.id IN (${params.map((p,i)=>i+2).map(i=>`\$${i}`).join(',')})
- `
- console.log(`get deals of proposals: ${q}, params: ${JSON.stringify(params)}`)
- const result = await client.query(q, [campaign_id, ...params])
- if ( result.rowCount > 0 ) {
- return result.rows
- }
- }
- private static _dealsBelongToCandidates(deals) {
- // Check that deals belong to influencers which are among candidate of the campaign
- for (const deal of deals) {
- if ( deal.deal_influencer_id != deal.candidate_id ) {
- console.log(`deal ${deal.deal_id} does not belong to candidates deal`)
- return false
- }
- }
- return true
- }
- private static _proposalsContainPlatformIds(campaign, deals, proposals) {
- // Check that if campaign is omni-channel and deal is auction, the proposal should have platform id
- for ( let deal of deals ) {
- if ( campaign.channel_id == Channel.OMNI && deal.deal_config_id == DealConfig.AUCTION ) {
- const proposal = proposals.find(p=>p.deal_id == deal.deal_id)
- if (
- proposal.platform_id === undefined ||
- (proposal.platform_id !== undefined && !campaign.platform_ids.includes(proposal.platform_id))
- ) {
- console.log( `Proposal to auction deal ${deal.deal_id} in omni-channel campaign should contain platform id`)
- return false
- }
- }
- }
- return true
- }
- private static async _createProposalDeals(client, campaign, deals, proposals) {
- // insert into proposal deals
- const params = []
- const values = []
- for (let j=0; j<proposals.length; j++ ) {
- const proposal = proposals[j]
- const deal = deals.find(row=>row.deal_id == proposal.deal_id )
- console.log(`Selected deal: ${JSON.stringify(deal)}`)
- if ( deal.deal_config_id == 2 ) { // auction deal, platform is unspecified initially
- switch( campaign.channel_id ) {
- case Channel.SINGLE: // single, there is only one item in platform_ids array
- deal.deal_platform_id = campaign.platform_ids[0]
- break
- case Channel.OMNI: // omni
- deal.deal_platform_id = proposal.platform_id
- break
- }
- }
- params.push(
- deal.deal_influencer_id,
- deal.deal_platform_id,
- deal.deal_type_id,
- deal.deal_config_id,
- deal.deal_brief,
- deal.deal_price
- )
- values.push(`(${_.range(6).map(i=> '$' + (i+1 + j*6 ) )})`)
- }
- const q = `
- INSERT INTO proposal_deal(
- influencer_id,
- platform_id,
- deal_type_id,
- deal_config_id,
- brief,
- price
- )
- VALUES
- ${values.join(',')}
- RETURNING id
- `
- console.log(`q: ${q}, params: ${JSON.stringify(params)}`)
- const result1 = await client.query(q, params)
- const proposal_deal_ids = result1.rows.map(row=>row.id)
- return proposal_deal_ids
- }
- private static async _createProposals(client, campaign_id, proposal_deal_ids ) {
- // here we insert proposals with deals connected
- const params = []
- const values = []
- const proposal_state_id = 3 // proposal sent
- for ( let j=0; j<proposal_deal_ids.length; j++ ) {
- const proposal_deal_id = proposal_deal_ids[j]
- params.push(
- proposal_state_id,
- campaign_id,
- proposal_deal_id
- )
- values.push(`(${ _.range(3).map(i => '$' + (i+1 + j*3 ) )})`)
- }
- const q = `
- INSERT INTO proposal(
- proposal_state_id,
- campaign_id,
- proposal_deal_id
- )
- VALUES ${values.join(',')}
- `
- console.log(`q: ${q}, params: ${JSON.stringify(params)}`)
- await client.query(q, params )
- }
- static async create(ctx) {
- const { id: marketer_id, campaign_id } = ctx.params
- const proposals:IProposalForSend[] = ctx.request.body
- console.log(`marketer: ${marketer_id}, campaign: ${campaign_id}, proposals: ${JSON.stringify(proposals)}`)
- const client = await ctx.pool.connect()
- try {
- await client.query('BEGIN')
- const campaign = await Campaigns._getById(client, marketer_id, campaign_id )
- console.log(`Read relevant campaign: ${JSON.stringify(campaign)}`)
- if (!campaign) {
- throw new Error("No such campaign")
- }
- const deals = await Proposals._getDealsByIds(client, proposals, campaign_id)
- console.log(`Deals: ${JSON.stringify(deals)}`)
- if ( !deals ) {
- throw new Error("No deals")
- }
- if (!Proposals._dealsBelongToCandidates(deals)) {
- throw new Error("All deals should belong to campaign candidates")
- }
- if (!Proposals._proposalsContainPlatformIds(campaign, deals, proposals)) {
- throw new Error("Proposals to auction deals in omni channel campaign should contain platform id")
- }
- const proposal_deal_ids = await Proposals._createProposalDeals(client, campaign, deals, proposals)
- console.log(`Proposal deal ids: ${JSON.stringify(proposal_deal_ids)}`)
- await Proposals._createProposals(client, campaign.id, proposal_deal_ids)
- await client.query('COMMIT')
- ctx.body = { success: true }
- }
- catch( err) {
- console.log(`error: ${err.message}`)
- await client.query('ROLLBACK')
- throw err
- }
- finally {
- client.release()
- }
- }
- private static async _getDealsForCampaign(client, campaign) {
- const result = await client.query(`
- SELECT * FROM deal
- WHERE deal_config_id=(SELECT id FROM deal_config WHERE name='auction')
- OR (
- deal_config_id=(SELECT id FROM deal_config WHERE name='predefined')
- AND deal_type_id=${campaign.campaign_type_id}
- AND platform_id IN (${campaign.platform_ids.join(',')})
- )
- `)
- console.log(`deals: ${JSON.stringify(result.rows, null, 2)}`)
- if ( result.rowCount > 0 ) {
- return result.rows
- }
- }
- private static async _getProposalsForCampaign(client, campaign) {
- const result = await client.query(`
- SELECT * FROM
- proposal JOIN proposal_deal ON proposal.proposal_deal_id=proposal_deal.id
- WHERE campaign_id=${campaign.id}
- `)
- console.log(`proposals: ${JSON.stringify(result.rows, null, 2)}`)
- if ( result.rowCount > 0) {
- return result.rows
- }
- }
- static async readAll(ctx) {
- console.log("Reads deals (with propsals if proposal was sent to the deal)")
- const { id: marketer_id, campaign_id } = ctx.params
- const client = await ctx.pool.connect()
- try {
- await client.query(`BEGIN`)
- const campaign = await Campaigns._getById(client, marketer_id, campaign_id)
- if ( !campaign) {
- throw new Error("No such campaign")
- }
- const deals = await Proposals._getDealsForCampaign(client, campaign)
- const proposals = await Proposals._getProposalsForCampaign(client, campaign)
- // If among predefined proposal deals there is a deal which has campaign type id and platform type id of one of predefined deals then this means that proposal was sent to that predefined deal
- for (const proposal of proposals ) {
- for ( const deal of deals ) {
- if (
- proposal.influencer_id==deal.influencer_id &&
- proposal.deal_type_id == deal.deal_type_id &&
- proposal.platform_id == deal.platform_id &&
- proposal.deal_config_id == deal.deal_config_id
- ) {
- deal.proposal = {
- id: proposal.id,
- state_id: proposal.proposal_state_id
- }
- }
- }
- }
- // There is only one auction deal in proposal deals for a platform.
- const groupedByInfluencer =
- _(deals)
- .groupBy(row=>row.influencer_id)
- .map((v,k)=>{
- return {
- "influencer_id":k,
- "deals":v.map(i=>{
- return {
- id: i.id,
- deal_config_id: i.deal_config_id,
- price: i.price,
- proposal: i.proposal
- }
- })
- }
- })
- console.log(JSON.stringify(groupedByInfluencer, null, 2))
- await client.query(`COMMIT`)
- ctx.body = groupedByInfluencer
- }
- catch(err) {
- await client.query(`ROLLBACK`)
- throw err
- }
- finally {
- client.release()
- }
- }
- static async remove(ctx) {
- }
- }
- export default Proposals
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement