Source: api/routes/cards/model.js

/**
 * CogniCity Server /cards data model
 * @module src/api/cards/model
 **/
import Promise from 'bluebird';

/**
* Database interaction for Cards objects
* @alias module:src/api/cards/model
* @param {Object} config Server configuration
* @param {Object} db PG Promise database instance
* @param {Object} logger Configured Winston logger instance
* @return {Object} data Query methods
**/
export default (config, db, logger) => ({
  // Create a new card entry with the given cardId
  create: (cardId, body) => new Promise((resolve, reject) => {
    // Setup query
    let query = `INSERT INTO ${config.TABLE_GRASP_CARDS}
      (card_id, username, network, language, received)
      VALUES ($1, $2, $3, $4, $5) RETURNING pkey`;

    // Setup values
    let values = [cardId, body.username, body.network, body.language, false];

    // Execute
    logger.debug(query, values);
    db.oneOrNone(query, values).timeout(config.PGTIMEOUT)
      .then((data) => resolve(data))
      /* istanbul ignore next */
      .catch((err) => {
        /* istanbul ignore next */
        reject(err);
}
      );
  }),

  // Return specific card by id
  byCardId: (cardId) => new Promise((resolve, reject) => {
    // Setup query
    let query = `SELECT c.card_id, c.username, c.network, c.language,
      c.received, CASE WHEN r.card_id IS NOT NULL THEN
        json_build_object('created_at', r.created_at, 'disaster_type',
        r.disaster_type, 'text', r.text, 'card_data', r.card_data, 'image_url',
        r.image_url, 'status', r.status)
      ELSE null END AS report
      FROM ${config.TABLE_GRASP_CARDS} c
      LEFT JOIN ${config.TABLE_GRASP_REPORTS} r USING (card_id)
      WHERE c.card_id = $1
      LIMIT 1`;

    // Setup values
    let values = [cardId];

    // Execute
    logger.debug(query, values);
    db.oneOrNone(query, values).timeout(config.PGTIMEOUT)
      .then((data) => resolve(data))
      /* istanbul ignore next */
      .catch((err) => {
        /* istanbul ignore next */
        reject(err);
      });
  }),

  // Add entry to the reports table and then update the card record accordingly
  submitReport: (card, body) => new Promise((resolve, reject) => {
    // Setup our queries
    let queries = [
      {
        query: `INSERT INTO ${config.TABLE_GRASP_REPORTS}
          (card_id, card_data, text, created_at, disaster_type, status,
            the_geom)
          VALUES ($1, $2, COALESCE($3,''), $4, $5, $6,
          ST_SetSRID(ST_Point($7,$8),4326))`,
        values: [card.card_id, body.card_data, body.text,
          body.created_at, body.disaster_type, 'Confirmed', body.location.lng,
          body.location.lat],
      },
      {
        query: `UPDATE ${config.TABLE_GRASP_CARDS}
          SET received = TRUE WHERE card_id = $1`,
        values: [card.card_id],
      },
      {
        query: `INSERT INTO ${config.TABLE_GRASP_LOG}
              (card_id, event_type)
              VALUES ($1, $2)`,
        values: [card.card_id, 'REPORT SUBMITTED'],
      },
    ];

    // Log queries to debugger
    for (let query of queries) logger.debug(query.query, query.values);

    // Execute in a transaction as both INSERT and UPDATE must happen together
    db.tx((t) => {
      return t.batch(queries.map((query) => t.none(query.query, query.values)));
    }).timeout(config.PGTIMEOUT)
      .then((data) => resolve(data))
      /* istanbul ignore next */
      .catch((err) => {
        /* istanbul ignore next */
        reject(err);
      });
  }),

  // Update the reports table with new report details
  updateReport: (card, body) => new Promise((resolve, reject) => {
    // Setup our queries
    let queries = [
      {
        query: `UPDATE ${config.TABLE_GRASP_REPORTS} SET
          image_url = COALESCE($2, image_url)
          WHERE card_id = $1`,
        values: [card.card_id, body.image_url],
      },
      {
        query: `INSERT INTO ${config.TABLE_GRASP_LOG}
              (card_id, event_type)
              VALUES ($1, $2)`,
        values: [card.card_id, 'REPORT UPDATE (PATCH)'],
      },
    ];

    // Log queries to debugger
    for (let query of queries) logger.debug(query.query, query.values);

    // Execute in a transaction as both INSERT and UPDATE must happen together
    db.tx((t) => {
      return t.batch(queries.map((query) => t.none(query.query, query.values)));
    }).timeout(config.PGTIMEOUT)
      .then((data) => resolve(data))
      /* istanbul ignore next */
      .catch((err) => {
        /* istanbul ignore next */
        reject(err);
      });
  }),

});