Wave Reconciliation-Reviewed

Adding Ability to see reviewed transactions on the reconciliation page

目前為 2020-01-01 提交的版本,檢視 最新版本

// ==UserScript==
// @name         Wave Reconciliation-Reviewed
// @description  Adding Ability to see reviewed transactions on the reconciliation page
// @author       Seth Parrish
// @namespace    https://sethp.cc
// @version      0.2
// @icon         https://raw.githubusercontent.com/xthexder/wide-github/master/icon.png
// @homepageURL  https://greasyfork.org/en/scripts/394287-wave-reconciliation-reviewed
// @supportURL   https://greasyfork.org/en/scripts/394287-wave-reconciliation-reviewed
// @match        https://next.waveapps.com/*
// @grant        GM_registerMenuCommand
// @grant        GM_getValue
// @grant        GM_setValue
// @grant        GM_deleteValue
// @grant        GM_addStyle
// ==/UserScript==
'use strict'
/* global confirm, XMLHttpRequest */

// Global Vars & Storage Object
// var d = document
// var b = d.body
var DBNAME = 'reviewed_db'
var db = GM_getValue(DBNAME) || []
console.log('DB:', db)

// Add GM DB deletion option
GM_registerMenuCommand('Clear Stored Data', () => {
  var shouldClear = confirm('Do you want to clear the "seen" reviewed transactions? (this will not effect data in wave)')
  if (shouldClear) {
    db = []
    GM_setValue(DBNAME, db)
    GM_deleteValue(DBNAME)
    console.log('DB:', db)
  }
})

// Add 'unmatch all' button
GM_registerMenuCommand('Unmatch All Transactions on screen', () => {
  var shouldGo = confirm('Do you want to unmatch all the transactions currently on the page?')
  if (shouldGo) {
    var className = 'account-recv2__reconciliation__table__matched-icon--true'
    var icons = Array.from(document.getElementsByClassName(className))
    icons.forEach(function (x) { x.click() })
    console.log('Finished Unmatching Transactions')
  }
})

// Adding Custom CSS
GM_addStyle('.account-recv2__reconciliation__table__reviewed--true {background: #dec9ff !important;color: #849194 !important;}')

// Check for Reviewed Status and add to the DB
function processLatestTransactions (res) {
  var isReviewed = x => Boolean(x.transaction_status.value)
  var isInDB = x => db.some(e => e.transaction_guid === x.transaction_guid)
  res.latest_transactions.forEach(x => {
    if (isReviewed(x) && !isInDB(x)) {
      db.push(x)
    }
  })
  GM_setValue(DBNAME, db)
  console.log('DB: ', db)
}

// Handle changing the status of a single transaction
function processTransactionStatusChange (res) {
  // Do not run if we are marking as reviewed (other case handles)
  if (res.transaction_status.value) {
    return
  }
  for (var i = 0; i < db.length; i++) {
    if (db[i].transaction_guid === res.guid) {
      db.splice(i, 1)
    }
  }
  GM_setValue('reviewed_db', db)
  console.log('DB: ', db)
}

// Utility function to apply custom css to a row with matching data
function turnGreen (date, desc, price_formatted) {
  var datedRows = Array.apply(null, document.querySelectorAll(`time[datetime="${date}"]`)).map(function (x) {
    return x.parentNode.parentElement.parentElement.parentElement.parentElement
  })
  if (datedRows.length === 0) {
    return
  }
  var el = datedRows.find(function (x) {
    var txt = x.textContent // Eg. "Nov 29, 2019Steam Games$13.90$1,568.22"
    return txt.includes(date.split('-')[0]) && txt.includes(desc) && txt.includes(price_formatted)
  })
  el.className += ' account-recv2__reconciliation__table__reviewed--true '
}

// Iterate DB and apply styles
function processReconciliationPage (res) {
  // Deal with this page's transaction data
  // var matched = res.transactions.filter(x => Boolean(x.is_matched))
  db.forEach(function (x) {
    turnGreen(x.transaction_date, x.transaction_description, x.transaction_total.transaction.formatted_string)
  })
}

// HTTP Listener
(function (open) {
  XMLHttpRequest.prototype.open = function () {
    this.addEventListener('readystatechange', function () {
      var json = this.responseText ? JSON.parse(this.responseText) : {}
      var doneAndIncludes = x => this.readyState === 4 && this.responseURL.includes(x)

      if (doneAndIncludes('/transactions/latest/')) {
        // Check for a finished request dealing with latest transactions
        processLatestTransactions(json)
      } else if (doneAndIncludes('/transactions/status/')) {
        // Check for a finished request, marking a transaction as "un-reviewed"
        processTransactionStatusChange(json)
      } else if (doneAndIncludes('/account_reconciliation/reconciliation_by_period/')) {
        // Check for a finished request dealing with reconciliation transactions
        processReconciliationPage(json)
      }
    }, false)
    open.apply(this, arguments)
  }
})(XMLHttpRequest.prototype.open)