Advertisement
Guest User

Untitled

a guest
May 23rd, 2018
72
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import ShoutoutError from "../../lib/ShoutoutError";
  2. import { IProposalForSend, ICampaignProposal } from '../../interfaces/marketers'
  3. import Campaigns from '../marketers/campaigns'
  4. import * as _ from 'lodash'
  5.  
  6. enum Channel {
  7.   SINGLE = 1,
  8.   OMNI
  9. }
  10.  
  11. enum DealConfig {
  12.   PREDEFINED=1,
  13.   AUCTION
  14. }
  15.  
  16.  
  17. class Proposals {
  18.  
  19.   private static async _getDealsByIds(client, proposals, campaign_id) {
  20.     // get deals which ids are in request; connect them with influencers who own them
  21.     const params = proposals.map(p=>p.deal_id)  
  22.     const q = `
  23.       SELECT
  24.         deal.id AS deal_id,
  25.         deal.deal_config_id AS deal_config_id,
  26.         deal.deal_type_id AS deal_type_id,
  27.         deal.brief AS deal_brief,
  28.         deal.price AS deal_price,
  29.         deal.influencer_id AS deal_influencer_id,
  30.         deal.platform_id AS deal_platform_id,
  31.         q.influencer_id AS candidate_id
  32.       FROM
  33.       deal FULL OUTER JOIN (SELECT influencer_id FROM campaign_candidate WHERE campaign_id=$1) AS q
  34.       ON deal.influencer_id = q.influencer_id
  35.       WHERE deal.id IN (${params.map((p,i)=>i+2).map(i=>`\$${i}`).join(',')})
  36.     `
  37.  
  38.     console.log(`get deals of proposals: ${q}, params: ${JSON.stringify(params)}`)
  39.     const result = await client.query(q, [campaign_id, ...params])
  40.  
  41.     if ( result.rowCount > 0 ) {
  42.       return result.rows
  43.     }
  44.  
  45.   }
  46.  
  47.   private static _dealsBelongToCandidates(deals) {
  48.      // Check that deals belong to influencers which are among candidate of the campaign
  49.     for (const deal of deals) {
  50.       if ( deal.deal_influencer_id != deal.candidate_id ) {
  51.         console.log(`deal ${deal.deal_id} does not belong to candidates deal`)
  52.         return false
  53.       }
  54.     }
  55.     return true
  56.   }
  57.  
  58.   private static _proposalsContainPlatformIds(campaign, deals, proposals) {
  59.     // Check that if campaign is omni-channel and deal is auction, the proposal should have platform id
  60.     for ( let deal of deals ) {
  61.       if ( campaign.channel_id == Channel.OMNI && deal.deal_config_id == DealConfig.AUCTION ) {
  62.         const proposal = proposals.find(p=>p.deal_id == deal.deal_id)
  63.         if (
  64.           proposal.platform_id === undefined ||
  65.           (proposal.platform_id !== undefined && !campaign.platform_ids.includes(proposal.platform_id))
  66.         ) {
  67.           console.log( `Proposal to auction deal ${deal.deal_id} in omni-channel campaign should contain platform id`)
  68.           return false
  69.         }
  70.       }
  71.     }
  72.     return true
  73.   }
  74.  
  75.  
  76.   private static async _createProposalDeals(client, campaign, deals, proposals) {
  77.     // insert into proposal deals
  78.     const params = []
  79.     const values = []
  80.     for (let j=0; j<proposals.length; j++ ) {
  81.       const proposal = proposals[j]
  82.       const deal = deals.find(row=>row.deal_id == proposal.deal_id )
  83.       console.log(`Selected deal: ${JSON.stringify(deal)}`)
  84.       if ( deal.deal_config_id == 2 ) { // auction deal, platform is unspecified initially
  85.         switch( campaign.channel_id ) {
  86.           case Channel.SINGLE: // single, there is only one item in platform_ids array
  87.             deal.deal_platform_id = campaign.platform_ids[0]
  88.             break
  89.           case Channel.OMNI: // omni
  90.             deal.deal_platform_id = proposal.platform_id
  91.             break
  92.         }
  93.       }
  94.       params.push(
  95.         deal.deal_influencer_id,
  96.         deal.deal_platform_id,
  97.         deal.deal_type_id,
  98.         deal.deal_config_id,
  99.         deal.deal_brief,
  100.         deal.deal_price
  101.       )
  102.       values.push(`(${_.range(6).map(i=> '$' + (i+1 + j*6 ) )})`)
  103.     }
  104.    
  105.     const q = `
  106.       INSERT INTO proposal_deal(
  107.         influencer_id,
  108.         platform_id,
  109.         deal_type_id,
  110.         deal_config_id,
  111.         brief,
  112.         price
  113.       )
  114.       VALUES
  115.       ${values.join(',')}
  116.       RETURNING id
  117.     `
  118.  
  119.     console.log(`q: ${q}, params: ${JSON.stringify(params)}`)
  120.     const result1 = await client.query(q, params)
  121.     const proposal_deal_ids = result1.rows.map(row=>row.id)
  122.     return proposal_deal_ids
  123.   }
  124.  
  125.   private static async _createProposals(client, campaign_id, proposal_deal_ids ) {
  126.     // here we insert proposals with deals connected
  127.     const params = []
  128.     const values = []
  129.     const proposal_state_id = 3 // proposal sent
  130.     for ( let j=0; j<proposal_deal_ids.length; j++ ) {
  131.       const proposal_deal_id = proposal_deal_ids[j]
  132.       params.push(
  133.         proposal_state_id,
  134.         campaign_id,
  135.         proposal_deal_id
  136.       )
  137.       values.push(`(${ _.range(3).map(i => '$' + (i+1 + j*3 ) )})`)
  138.     }
  139.    
  140.     const q = `
  141.     INSERT INTO proposal(
  142.       proposal_state_id,
  143.       campaign_id,
  144.       proposal_deal_id
  145.     )
  146.     VALUES ${values.join(',')}
  147.     `
  148.     console.log(`q: ${q}, params: ${JSON.stringify(params)}`)
  149.  
  150.     await client.query(q, params )
  151.   }
  152.  
  153.   static async create(ctx) {
  154.     const { id: marketer_id, campaign_id } = ctx.params
  155.     const proposals:IProposalForSend[] = ctx.request.body
  156.     console.log(`marketer: ${marketer_id}, campaign: ${campaign_id}, proposals: ${JSON.stringify(proposals)}`)
  157.  
  158.     const client = await ctx.pool.connect()
  159.     try {
  160.  
  161.       await client.query('BEGIN')
  162.  
  163.       const campaign = await Campaigns._getById(client, marketer_id, campaign_id )
  164.       console.log(`Read relevant campaign: ${JSON.stringify(campaign)}`)
  165.       if (!campaign) {
  166.         throw new Error("No such campaign")
  167.       }
  168.       const deals = await Proposals._getDealsByIds(client, proposals, campaign_id)
  169.       console.log(`Deals: ${JSON.stringify(deals)}`)
  170.       if ( !deals ) {
  171.         throw new Error("No deals")
  172.       }
  173.  
  174.       if (!Proposals._dealsBelongToCandidates(deals)) {
  175.         throw new Error("All deals should belong to campaign candidates")
  176.       }
  177.  
  178.       if (!Proposals._proposalsContainPlatformIds(campaign, deals, proposals)) {
  179.         throw new Error("Proposals to auction deals in omni channel campaign should contain platform id")
  180.       }
  181.  
  182.       const proposal_deal_ids = await Proposals._createProposalDeals(client, campaign, deals, proposals)
  183.       console.log(`Proposal deal ids: ${JSON.stringify(proposal_deal_ids)}`)
  184.  
  185.       await Proposals._createProposals(client, campaign.id, proposal_deal_ids)
  186.  
  187.       await client.query('COMMIT')
  188.  
  189.       ctx.body = { success: true }
  190.  
  191.     }
  192.     catch( err) {
  193.       console.log(`error: ${err.message}`)
  194.       await client.query('ROLLBACK')
  195.       throw err
  196.     }
  197.  
  198.     finally {
  199.       client.release()
  200.     }
  201.  
  202.    
  203.   }
  204.  
  205.   private static async _getDealsForCampaign(client, campaign) {
  206.     const result = await client.query(`
  207.     SELECT * FROM deal
  208.     WHERE deal_config_id=(SELECT id FROM deal_config WHERE name='auction')
  209.     OR (
  210.       deal_config_id=(SELECT id FROM deal_config WHERE name='predefined')
  211.       AND deal_type_id=${campaign.campaign_type_id}
  212.       AND platform_id IN (${campaign.platform_ids.join(',')})
  213.     )
  214.     `)
  215.     console.log(`deals: ${JSON.stringify(result.rows, null, 2)}`)
  216.     if ( result.rowCount > 0  ) {
  217.       return result.rows
  218.     }
  219.   }
  220.  
  221.   private static async _getProposalsForCampaign(client, campaign) {
  222.     const result = await client.query(`
  223.       SELECT * FROM
  224.       proposal JOIN proposal_deal ON proposal.proposal_deal_id=proposal_deal.id
  225.       WHERE campaign_id=${campaign.id}
  226.     `)      
  227.     console.log(`proposals: ${JSON.stringify(result.rows, null, 2)}`)
  228.     if ( result.rowCount > 0) {
  229.       return result.rows
  230.     }
  231.   }
  232.  
  233.   static async readAll(ctx) {
  234.     console.log("Reads deals (with propsals if proposal was sent to the deal)")
  235.     const { id: marketer_id, campaign_id } = ctx.params
  236.  
  237.     const client = await ctx.pool.connect()
  238.     try {
  239.       await client.query(`BEGIN`)
  240.      
  241.       const campaign = await Campaigns._getById(client, marketer_id, campaign_id)
  242.       if ( !campaign) {
  243.         throw new Error("No such campaign")
  244.       }
  245.       const deals = await Proposals._getDealsForCampaign(client, campaign)
  246.       const proposals = await Proposals._getProposalsForCampaign(client, campaign)
  247.      
  248.         // 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
  249.       for (const proposal of proposals ) {
  250.         for ( const deal of deals ) {
  251.           if (
  252.             proposal.influencer_id==deal.influencer_id &&
  253.             proposal.deal_type_id == deal.deal_type_id &&
  254.             proposal.platform_id == deal.platform_id &&
  255.             proposal.deal_config_id == deal.deal_config_id
  256.           ) {
  257.             deal.proposal = {
  258.               id: proposal.id,
  259.               state_id: proposal.proposal_state_id
  260.             }
  261.           }
  262.         }
  263.       }
  264.      
  265.       //  There is only one auction deal in proposal deals for a platform.
  266.  
  267.       const groupedByInfluencer =
  268.         _(deals)
  269.         .groupBy(row=>row.influencer_id)
  270.         .map((v,k)=>{
  271.           return {
  272.             "influencer_id":k,
  273.             "deals":v.map(i=>{
  274.               return {
  275.                 id: i.id,
  276.                 deal_config_id: i.deal_config_id,
  277.                 price: i.price,
  278.                 proposal: i.proposal
  279.               }
  280.             })
  281.           }
  282.         })
  283.       console.log(JSON.stringify(groupedByInfluencer, null, 2))
  284.       await client.query(`COMMIT`)
  285.       ctx.body = groupedByInfluencer
  286.  
  287.      
  288.     }
  289.  
  290.     catch(err) {
  291.       await client.query(`ROLLBACK`)
  292.       throw err
  293.     }
  294.  
  295.     finally {
  296.       client.release()
  297.     }
  298.        
  299.   }
  300.  
  301.   static async remove(ctx) {
  302.  
  303.   }
  304. }
  305.  
  306. export default Proposals
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement