Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save Flatroy/148d2ea609ad4ee5bf2341c4491baf40 to your computer and use it in GitHub Desktop.

Select an option

Save Flatroy/148d2ea609ad4ee5bf2341c4491baf40 to your computer and use it in GitHub Desktop.

Revisions

  1. @JhumanJ JhumanJ revised this gist Dec 9, 2022. 1 changed file with 13 additions and 7 deletions.
    20 changes: 13 additions & 7 deletions Scriptable_MRR_profitwell.js
    Original file line number Diff line number Diff line change
    @@ -57,11 +57,12 @@ class LineChart {
    // Load MRR
    // https://gist.github.com/daolf/ae104b1ab7cabf564b47770c88d4214b

    const API_TOKEN = "PROFITWELL_API_KEY"
    const API_TOKEN = "PROFITWELL_API_TOKEN"

    // Recreating a basic auth with Scriptable lib
    const currentYear = new Date().getFullYear();
    const tempMonth = new Date().getMonth() + 1
    const currentDate = new Date().getDate()
    const currentMonth = (tempMonth < 10 ? '0' + tempMonth : tempMonth);
    const date = `${currentYear}-${currentMonth}`
    const endpoint = `https://api.profitwell.com/v2/metrics/daily/?metrics=recurring_revenue,active_customers&month=${date}`
    @@ -74,16 +75,21 @@ async function loadItems() {
    return response
    }

    function kFormatter(num) {
    return Math.abs(num) > 999 ? Math.sign(num)*((Math.abs(num)/1000).toFixed(1)) + 'k' : Math.sign(num)*Math.abs(num)
    }

    let json = await loadItems()
    let MRR = json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 1]['value']
    const ARR = kFormatter(MRR*12)

    let absoluteChange = Math.floor(MRR - json["data"]["recurring_revenue"][0]['value']).toString()
    let percentChange = (absoluteChange*100/MRR).toFixed(1).toString()

    let dailyAbsoluteChange = json["data"]["recurring_revenue"].length >= 2 ? Math.floor(MRR - json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 2]['value']).toString() : null
    let dailyAbsoluteChange = currentDate >= 2 ? Math.floor(MRR - json["data"]["recurring_revenue"][currentDate - 2]['value']).toString() : null
    MRR = Math.floor(MRR)
    let nbActiveCustomers = json["data"]["active_customers"][json["data"]["active_customers"].length - 1]['value']

    let nbActiveCustomers = json["data"]["active_customers"][currentDate - 1]['value']

    const today = new Date();
    today.setHours(23, 59, 0, 0);
    @@ -104,6 +110,7 @@ let chart = new LineChart(400, 400, data).configure((ctx, path) => {
    ctx.fillPath(path);
    }).getImage();
    widget.addText(`MRR $${MRR.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`);
    widget.addText(`ARR $${ARR.toString()}`);

    // display (% change)
    widget.addSpacer(10)
    @@ -118,7 +125,7 @@ if (absoluteChange>=0) {
    }

    // Daily change
    widget.addSpacer(10)
    widget.addSpacer(4)
    if (dailyAbsoluteChange!== null) {
    if (dailyAbsoluteChange>=0) {
    let dailyChangeText = widget.addText(`+$${dailyAbsoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} today`);
    @@ -133,8 +140,7 @@ if (dailyAbsoluteChange!== null) {
    }
    }

    // Number of customers
    widget.addSpacer(10)
    widget.addSpacer(4)
    let activeCustomerText = widget.addText(`${nbActiveCustomers} customers`);
    activeCustomerText.font = Font.semiboldSystemFont(10)
    activeCustomerText.textColor = Color.white()
    @@ -146,4 +152,4 @@ Script.setWidget(widget);
    if (!config.runsInWidget) {
    await widget.presentSmall();
    }
    Script.complete();
    Script.complete();
  2. @JhumanJ JhumanJ revised this gist Nov 9, 2022. 1 changed file with 34 additions and 4 deletions.
    38 changes: 34 additions & 4 deletions Scriptable_MRR_profitwell.js
    Original file line number Diff line number Diff line change
    @@ -64,7 +64,7 @@ const currentYear = new Date().getFullYear();
    const tempMonth = new Date().getMonth() + 1
    const currentMonth = (tempMonth < 10 ? '0' + tempMonth : tempMonth);
    const date = `${currentYear}-${currentMonth}`
    const endpoint = `https://api.profitwell.com/v2/metrics/daily/?metrics=recurring_revenue&month=${date}`
    const endpoint = `https://api.profitwell.com/v2/metrics/daily/?metrics=recurring_revenue,active_customers&month=${date}`

    async function loadItems() {
    let at = endpoint
    @@ -74,12 +74,17 @@ async function loadItems() {
    return response
    }


    let json = await loadItems()
    let MRR = Math.floor(json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 1]['value']).toString()
    let MRR = json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 1]['value']

    let absoluteChange = Math.floor(MRR - json["data"]["recurring_revenue"][0]['value']).toString()
    let percentChange = (absoluteChange*100/MRR).toFixed(1).toString()

    let dailyAbsoluteChange = json["data"]["recurring_revenue"].length >= 2 ? Math.floor(MRR - json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 2]['value']).toString() : null
    MRR = Math.floor(MRR)
    let nbActiveCustomers = json["data"]["active_customers"][json["data"]["active_customers"].length - 1]['value']

    const today = new Date();
    today.setHours(23, 59, 0, 0);
    const data = []
    @@ -103,12 +108,37 @@ widget.addText(`MRR $${MRR.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`);
    // display (% change)
    widget.addSpacer(10)
    if (absoluteChange>=0) {
    let changeText = widget.addText(`+$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (${percentChange}%)`);
    let changeText = widget.addText(`+$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (${percentChange}%) this month`);
    changeText.textColor = Color.green()
    changeText.font = Font.semiboldSystemFont(10)
    } else {
    let changeText = widget.addText(`p$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (-${percentChange}%)`);
    let changeText = widget.addText(`$${Math.abs(absoluteChange).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (-${percentChange}%) this month`);
    changeText.textColor = Color.red()
    changeText.font = Font.semiboldSystemFont(10)
    }

    // Daily change
    widget.addSpacer(10)
    if (dailyAbsoluteChange!== null) {
    if (dailyAbsoluteChange>=0) {
    let dailyChangeText = widget.addText(`+$${dailyAbsoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} today`);
    if (dailyAbsoluteChange>0){
    dailyChangeText.textColor = Color.green()
    }
    dailyChangeText.font = Font.semiboldSystemFont(10)
    } else {
    let dailyChangeText = widget.addText(`-$${Math.abs(dailyAbsoluteChange).toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} today`);
    dailyChangeText.textColor = Color.red()
    dailyChangeText.font = Font.semiboldSystemFont(10)
    }
    }

    // Number of customers
    widget.addSpacer(10)
    let activeCustomerText = widget.addText(`${nbActiveCustomers} customers`);
    activeCustomerText.font = Font.semiboldSystemFont(10)
    activeCustomerText.textColor = Color.white()

    widget.addSpacer();
    widget.backgroundImage = chart;

  3. @JhumanJ JhumanJ revised this gist Nov 9, 2022. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions Scriptable_MRR_profitwell.js
    Original file line number Diff line number Diff line change
    @@ -57,7 +57,7 @@ class LineChart {
    // Load MRR
    // https://gist.github.com/daolf/ae104b1ab7cabf564b47770c88d4214b

    const API_TOKEN = "PROFITWELL_API_TOKEN"
    const API_TOKEN = "PROFITWELL_API_KEY"

    // Recreating a basic auth with Scriptable lib
    const currentYear = new Date().getFullYear();
    @@ -78,7 +78,7 @@ let json = await loadItems()
    let MRR = Math.floor(json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 1]['value']).toString()

    let absoluteChange = Math.floor(MRR - json["data"]["recurring_revenue"][0]['value']).toString()
    let percentChange = Math.floor(absoluteChange*100/MRR).toString()
    let percentChange = (absoluteChange*100/MRR).toFixed(1).toString()

    const today = new Date();
    today.setHours(23, 59, 0, 0);
    @@ -103,10 +103,10 @@ widget.addText(`MRR $${MRR.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`);
    // display (% change)
    widget.addSpacer(10)
    if (absoluteChange>=0) {
    let changeText = widget.addText(`+ $${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (+${percentChange}%)`);
    let changeText = widget.addText(`+$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (${percentChange}%)`);
    changeText.textColor = Color.green()
    } else {
    let changeText = widget.addText(`$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (+${percentChange}%)`);
    let changeText = widget.addText(`p$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (-${percentChange}%)`);
    changeText.textColor = Color.red()
    }
    widget.addSpacer();
  4. @JhumanJ JhumanJ created this gist Nov 8, 2022.
    119 changes: 119 additions & 0 deletions Scriptable_MRR_profitwell.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,119 @@
    class LineChart {
    // LineChart by https://kevinkub.de/

    constructor(width, height, values) {
    this.ctx = new DrawContext();
    this.ctx.size = new Size(width, height);
    this.values = values;
    }

    _calculatePath() {
    let maxValue = Math.max(...this.values);
    let minValue = Math.min(...this.values);
    let difference = maxValue - minValue;
    let count = this.values.length;
    let step = this.ctx.size.width / (count - 1);
    let points = this.values.map((current, index, all) => {
    let x = step*index;
    let y = this.ctx.size.height - (current - minValue) / difference * this.ctx.size.height;
    return new Point(x, y);
    });
    return this._getSmoothPath(points);
    }

    _getSmoothPath(points) {
    let path = new Path();
    path.move(new Point(0, this.ctx.size.height));
    path.addLine(points[0]);
    for(let i = 0; i < points.length-1; i++) {
    let xAvg = (points[i].x + points[i+1].x) / 2;
    let yAvg = (points[i].y + points[i+1].y) / 2;
    let avg = new Point(xAvg, yAvg);
    let cp1 = new Point((xAvg + points[i].x) / 2, points[i].y);
    let next = new Point(points[i+1].x, points[i+1].y);
    let cp2 = new Point((xAvg + points[i+1].x) / 2, points[i+1].y);
    path.addQuadCurve(avg, cp1);
    path.addQuadCurve(next, cp2);
    }
    path.addLine(new Point(this.ctx.size.width, this.ctx.size.height));
    path.closeSubpath();
    return path;
    }

    configure(fn) {
    let path = this._calculatePath();
    if(fn) {
    fn(this.ctx, path);
    } else {
    this.ctx.addPath(path);
    this.ctx.fillPath(path);
    }
    return this.ctx;
    }

    }


    // Load MRR
    // https://gist.github.com/daolf/ae104b1ab7cabf564b47770c88d4214b

    const API_TOKEN = "PROFITWELL_API_TOKEN"

    // Recreating a basic auth with Scriptable lib
    const currentYear = new Date().getFullYear();
    const tempMonth = new Date().getMonth() + 1
    const currentMonth = (tempMonth < 10 ? '0' + tempMonth : tempMonth);
    const date = `${currentYear}-${currentMonth}`
    const endpoint = `https://api.profitwell.com/v2/metrics/daily/?metrics=recurring_revenue&month=${date}`

    async function loadItems() {
    let at = endpoint
    let req = new Request(at)
    req.headers = {"Authorization" : API_TOKEN}
    let response = await req.loadJSON()
    return response
    }

    let json = await loadItems()
    let MRR = Math.floor(json["data"]["recurring_revenue"][json["data"]["recurring_revenue"].length - 1]['value']).toString()

    let absoluteChange = Math.floor(MRR - json["data"]["recurring_revenue"][0]['value']).toString()
    let percentChange = Math.floor(absoluteChange*100/MRR).toString()

    const today = new Date();
    today.setHours(23, 59, 0, 0);
    const data = []
    for (const val of json["data"]["recurring_revenue"]){
    const date = new Date(val.date)

    if (date <= today ) {
    data.push(val.value)
    }
    }

    let widget = new ListWidget();
    let chart = new LineChart(400, 400, data).configure((ctx, path) => {
    ctx.opaque = false;
    ctx.setFillColor(new Color("8cc5ff", .5));
    ctx.addPath(path);
    ctx.fillPath(path);
    }).getImage();
    widget.addText(`MRR $${MRR.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")}`);

    // display (% change)
    widget.addSpacer(10)
    if (absoluteChange>=0) {
    let changeText = widget.addText(`+ $${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (+${percentChange}%)`);
    changeText.textColor = Color.green()
    } else {
    let changeText = widget.addText(`$${absoluteChange.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")} (+${percentChange}%)`);
    changeText.textColor = Color.red()
    }
    widget.addSpacer();
    widget.backgroundImage = chart;

    Script.setWidget(widget);
    if (!config.runsInWidget) {
    await widget.presentSmall();
    }
    Script.complete();