<window id="pytdprodcomp">
	<reporttitle>Production:->Previous Year Production Comparison</reporttitle>
    <layout type="vertical">
        <layout type="horizontal">
            <label>Batch Type:</label>
            <sqldrop id="batchtype" />
            <label>Approval:</label>
            <sqldrop id="approval" />
            <daterange id="dates" initial="19" /><!-- Current Year to Date -->
            <label>Days to Average:</label>
            <line validator="integer" id="days">7</line>
            <label>Weight Unit:</label>
            <sqldrop id="unit" />
            <stretch />
        </layout>
        <webview id="report" />
    </layout>
    <menu name="File">
        <item id="print" shortcut="Ctrl+P">Print...</item>
    </menu>
    <program>
        <![CDATA[
            this.windowTitle = TTR("pytdprodcomp", "Typica - Previous Year Production Comparison");
            var dateSelect = findChildObject(this, 'dates');
            dateSelect.removeIndex(23); // Remove Lifetime range
            var view = findChildObject(this, 'report');
            var printMenu = findChildObject(this, 'print');
            printMenu.triggered.connect(function() {
                view.print();
            });
            var avgField = findChildObject(this, 'days');
            var unitBox = findChildObject(this, 'unit');
            unitBox.addItem(TTR("pytdprodcomp", "Kg"));
            unitBox.addItem(TTR("pytdprodcomp", "Lb"));
            unitBox.currentIndex = QSettings.value("script/report_unit", 1);
            unitBox['currentIndexChanged(int)'].connect(function() {
                QSettings.setValue("script/report_unit", unitBox.currentIndex);
                refresh();
            });
            var batchType = findChildObject(this, 'batchtype');
            batchType.addItem(TTR("pytdprodcomp", "Any"));
            batchType.addItem(TTR("pytdprodcomp", "Production Roasts"));
            batchType.addItem(TTR("pytdprodcomp", "Sample Roasts"));
            batchType.currentIndex = QSettings.value("script/batchtypefilter", 1);
            batchType['currentIndexChanged(int)'].connect(function() {
                QSettings.setValue("script/batchtypefilter", batchType.currentIndex);
                refresh();
            });
            var approval = findChildObject(this, 'approval');
            approval.addItem(TTR("pytdprodcomp", "Any"));
            approval.addItem(TTR("pytdprodcomp", "Approved"));
            approval.addItem(TTR("pytdprodcomp", "Not Approved"));
            approval.currentIndex = QSettings.value("script/approvalfilter", 1);
            approval['currentIndexChanged(int)'].connect(function() {
                QSettings.setValue("script/approvalfilter", approval.currentIndex);
                refresh();
            });
            function refresh() {
                var conversion = 1;
                if(unitBox.currentIndex == 0) {
                    conversion = 2.2;
                }
                var buffer = new QBuffer;
                buffer.open(3);
                var output = new XmlWriter(buffer);
                output.writeStartDocument("1.0");
                output.writeDTD('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" "http://www.w3.org/2002/04/xhtml-math-svg.dtd">');
                output.writeStartElement("html");
                output.writeAttribute("xmlns", "http://www.w3.org/1999/xhtml");
                output.writeStartElement("head");
                output.writeTextElement("title", TTR("pytdprodcomp", "Previous Year Production Comparison"));
                output.writeEndElement();
                output.writeStartElement("body");
                var cdt = new Date(Date.now());
                output.writeTextElement("p", cdt.toLocaleDateString(TTR("reports", "en-US")) + " " + cdt.toLocaleTimeString(TTR("reports", "en-US")));
                output.writeTextElement("h1", TTR("pytdprodcomp", "Previous Year Production Comparison"));
                output.writeTextElement("p", TTR("pytdprodcomp", "This report provides an itemized and overall comparison of roasted coffee production for the dates specified with those dates in the previous year. A chart of this data along with percent change and rolling average of the percent change is also produced."));
                output.writeStartElement("table");
                output.writeAttribute("style", "page-break-after:auto;");
                output.writeAttribute("rules", "groups");
                output.writeAttribute("cellpadding", "3px");
                output.writeStartElement("thead");
                output.writeStartElement("tr");
                output.writeTextElement("th", "Coffee");
                switch(unitBox.currentIndex) {
                    case 0:
                        output.writeTextElement("th", TTR("pytdprodcomp", "Previous (Kg)"));
                        output.writeTextElement("th", TTR("pytdprodcomp", "Current (Kg)"));
                        output.writeTextElement("th", TTR("pytdprodcomp", "Change (Kg)"));
                        break;
                    case 1:
                        output.writeTextElement("th", TTR("pytdprodcomp", "Previous (Lb)"));
                        output.writeTextElement("th", TTR("pytdprodcomp", "Current (Lb)"));
                        output.writeTextElement("th", TTR("pytdprodcomp", "Change (Lb)"));
                        break;
                }
                output.writeEndElement();
                output.writeEndElement();
                output.writeStartElement("tbody");
                var query = new QSqlQuery();
                query.exec("START TRANSACTION");
                var dateRange = dateSelect.currentRange();
                var curStartDate = "'"+dateRange[0]+"'";
                var curEndDate = "'"+dateRange[dateRange.length - 1]+"'";
                query.exec("SELECT "+curStartDate+"::date - interval '1 year', "+curEndDate+"::date - interval '1 year' + interval '1 day', "+curEndDate+"::date + interval '1 day'");
                query.next();
                curEndDate = "'"+query.value(2)+"'";
                var prevStartDate = "'"+query.value(0)+"'";
                var prevEndDate = "'"+query.value(1)+"'";
                var transaction_filter;
                var approval_filter;
                switch(batchType.currentIndex) {
                    case 0:
                        transaction_filter = "";
                        break;
                    case 1:
                        transaction_filter = " AND transaction_type = 'ROAST'";
                        break;
                    case 2:
                        transaction_filter = " AND transaction_type = 'SAMPLEROAST'";
                        break;
                }
                switch(approval.currentIndex) {
                    case 0:
                        approval_filter = "";
                        break;
                    case 1:
                        approval_filter = " AND approval = true";
                        break;
                    case 2:
                        approval_filter = " AND approval = false";
                        break;
                }
                var q = "CREATE TEMPORARY TABLE previous ON COMMIT DROP AS SELECT roasted_id, sum(roasted_quantity) AS p FROM roasting_log WHERE time > "+prevStartDate+" AND time < "+prevEndDate+" AND roasted_id IS NOT NULL" + transaction_filter + approval_filter + " GROUP BY roasted_id";
                query.exec(q);
                q = "CREATE TEMPORARY TABLE current ON COMMIT DROP AS SELECT roasted_id, sum(roasted_quantity) AS c FROM roasting_log WHERE time > "+curStartDate+" AND time < "+curEndDate+" AND roasted_id IS NOT NULL" + transaction_filter + approval_filter + " GROUP BY roasted_id";
                query.exec(q);
                query.exec("INSERT INTO previous SELECT roasted_id, 0 FROM current WHERE roasted_id NOT IN (SELECT roasted_id FROM previous)");
                query.exec("INSERT INTO current SELECT roasted_id, 0 FROM previous WHERE roasted_id NOT IN (SELECT roasted_id FROM current)");
                query.exec("CREATE TEMPORARY TABLE comp ON COMMIT DROP AS SELECT previous.roasted_id, p, c FROM previous LEFT OUTER JOIN current ON previous.roasted_id = current.roasted_id");
                query.exec("SELECT (SELECT name FROM items WHERE id = roasted_id) AS name, p, c, (c-p) FROM comp WHERE p > 0 OR c > 0 ORDER BY name");
                while(query.next())
                {
                    output.writeStartElement("tr");
                    output.writeTextElement("td", query.value(0));
                    output.writeTextElement("td", (query.value(1) / conversion).toFixed(2));
                    output.writeTextElement("td", (query.value(2) / conversion).toFixed(2));
                    output.writeTextElement("td", (query.value(3) / conversion).toFixed(2));
                    output.writeEndElement();
                }
                output.writeEndElement();
                output.writeStartElement("tfoot");
                output.writeTextElement("th", TTR("pytdprodcomp", "Totals"));
                query.exec("SELECT sum(p), sum(c), sum(c-p) FROM comp");
                query.next();
                output.writeTextElement("td", (query.value(0) / conversion).toFixed(2));
                output.writeTextElement("td", (query.value(1) / conversion).toFixed(2));
                output.writeTextElement("td", (query.value(2) / conversion).toFixed(2));
                output.writeEndElement();
                query.exec("ABORT");
                output.writeEndElement();
                output.writeStartElement("p");
                output.writeAttribute("style", "page-break-inside: avoid");
                output.writeStartElement("svg");
                output.writeAttribute("xmlns", "http://www.w3.org/2000/svg");
                output.writeAttribute("width", "7.5in");
                output.writeAttribute("height", "6.3in");
                output.writeStartElement("g");
                output.writeAttribute("transform", "translate(0,470)");
                output.writeStartElement("g");
                output.writeAttribute("transform", "scale(1,-1)");
                output.writeStartElement("line");
                output.writeAttribute("x1", "40");
                output.writeAttribute("x2", "40");
                output.writeAttribute("y1", "0");
                output.writeAttribute("y2", "450");
                output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                output.writeEndElement();
                output.writeStartElement("line");
                output.writeAttribute("x1", "50");
                output.writeAttribute("x2", "650");
                output.writeAttribute("y1", "-10");
                output.writeAttribute("y2", "-10");
                output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                output.writeEndElement();
                output.writeStartElement("line");
                output.writeAttribute("x1", "660");
                output.writeAttribute("x2", "660");
                output.writeAttribute("y1", "0");
                output.writeAttribute("y2", "450");
                output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                output.writeEndElement();
                var q = "SELECT "+curEndDate+"::date - "+curStartDate+"::date";
                query.exec(q);
                query.next();
                var days = query.value(0);
                var dates = new Array();
                var curpounds = new Array();
                var prevpounds = new Array();
                var change = new Array();
                var avgchange = new Array();
                var i;
                for(i = 0; i < days; i++)
                {
                    q = "SELECT "+curStartDate+"::date + "+(i+1);
                    query.exec(q);
                    query.next();
                    dates[i] = query.value(0);
                    q = "SELECT sum(roasted_quantity) FROM roasting_log WHERE time > "+curStartDate+" AND time < '"+dates[i]+"'" + transaction_filter + approval_filter;
                    query.exec(q);
                    if(query.next())
                    {
                        curpounds[i] = Number(query.value(0));
                    }
                    else
                    {
                        curpounds[i] = 0;
                    }
                    q = "SELECT sum(roasted_quantity) FROM roasting_log WHERE time > "+curStartDate+"::date - '1 year'::interval AND time < '"+dates[i]+"'::date - '1 year'::interval" + transaction_filter + approval_filter;
                    query.exec(q);
                    if(query.next())
                    {
                        prevpounds[i] = Number(query.value(0));
                    }
                    else
                    {
                        prevpounds[i] = 0;
                    }
                    if(curpounds[i] > 0)
                    {
                        change[i] = (curpounds[i] - prevpounds[i])/curpounds[i];
                    }
                    else
                    {
                        if(prevpounds[i] > 0)
                        {
                            change[i] = -1;
                        }
                        else
                        {
                            change[i] = 0;
                        }
                    }
                    if(i > (parseInt(avgField.text)-2))
                    {
                        var sum = 0;
                        var j;
                        for(j = 0; j < parseInt(avgField.text); j++)
                        {
                            sum += change[i-j];
                        }
                        avgchange[i] = sum / parseInt(avgField.text);
                    }
                }
                // Calculate the domain of the primary y axis.
                var maxy1 = 0;
                    var increment = 100; // Starting increment is 100 Lb.
                    if(unitBox.currentIndex == 0) {
                        increment = 110; // Starting increment is 50 Kg if Kg is requested.
                    }
                while(maxy1 < Math.max(curpounds[days - 1], prevpounds[days - 1]))
                {
                    maxy1 += increment;
                }
                // Calculate the number of grid lines and loosen spacing if there are too many.
                var divisions = maxy1 / increment;
                while(divisions > 10) {
                    increment *= 2;
                    divisions = maxy1 / increment;
                }
                // Draw y axis grid lines.
                var pos = 0;
                while(pos <= maxy1)
                {
                    output.writeStartElement("line");
                    output.writeAttribute("x1", "35");
                    output.writeAttribute("x2", "45");
                    output.writeAttribute("y1", (450/maxy1)*pos);
                    output.writeAttribute("y2", (450/maxy1)*pos);
                    output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                    output.writeEndElement();
                    pos += increment;
                }
                var n = Math.min.apply(Math, change);
                var m = Math.max.apply(Math, change);
                var miny2 = 0;
                var maxy2;
                if(n < 0)
                {
                    while(miny2 > n)
                    {
                        miny2 -= 0.1;
                    }
                    maxy2 = miny2;
                }
                else
                {
                    while(miny2 < n)
                    {
                        miny2 += 0.1;
                    }
                    miny2 -= 0.1;
                    maxy2 = miny2;
                }
                while(maxy2 < m)
                {
                    maxy2 += 0.1;
                }
                var range = maxy2 - miny2;
                pos = miny2;
                while(pos <= maxy2)
                {
                    output.writeStartElement("line");
                    output.writeAttribute("x1", "655");
                    output.writeAttribute("x2", "665");
                    output.writeAttribute("y1", (pos-miny2)*(4.5/(range*100))*10000);
                    output.writeAttribute("y2", (pos-miny2)*(4.5/(range*100))*10000);
                    output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                    output.writeEndElement();
                    pos += 0.1;
                }
                pos = 0;
                while(pos < days)
                {
                    output.writeStartElement("line");
                    output.writeAttribute("x1", 50+((600/(days-1))*pos));
                    output.writeAttribute("x2", 50+((600/(days-1))*pos));
                    output.writeAttribute("y1", "-5");
                    output.writeAttribute("y2", "-15");
                    output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                    output.writeEndElement();
                    pos += 7;
                }
                output.writeStartElement("line");
                output.writeAttribute("x1", 50+((600/(days-1))*(days-1)));
                output.writeAttribute("x2", 50+((600/(days-1))*(days-1)));
                output.writeAttribute("y1", "-5");
                output.writeAttribute("y2", "-15");
                output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                output.writeEndElement();
                pos = 1;
                while(pos < days)
                {
                    output.writeStartElement("line");
                    output.writeAttribute("x1", 50+((600/(days-1))*(pos - 1)));
                    output.writeAttribute("x2", 50+((600/(days-1))*pos));
                    output.writeAttribute("y1", (prevpounds[pos-1]/maxy1)*450);
                    output.writeAttribute("y2", (prevpounds[pos]/maxy1)*450);
                    output.writeAttribute("style", "stroke:rgb(0,0,0);stroke-width:1;");
                    output.writeEndElement();
                    output.writeStartElement("line");
                    output.writeAttribute("x1", 50+((600/(days-1))*(pos - 1)));
                    output.writeAttribute("x2", 50+((600/(days-1))*pos));
                    output.writeAttribute("y1", (curpounds[pos-1]/maxy1)*450);
                    output.writeAttribute("y2", (curpounds[pos]/maxy1)*450);
                    output.writeAttribute("style", "stroke:rgb(255,0,0);stroke-width:1;");
                    output.writeEndElement();
                    output.writeStartElement("line");
                    output.writeAttribute("x1", 50+((600/(days-1))*(pos-1)));
                    output.writeAttribute("x2", 50+((600/(days-1))*pos));
                    output.writeAttribute("y1", (change[pos-1]-miny2)*(4.5/(range*100))*10000);
                    output.writeAttribute("y2", (change[pos]-miny2)*(4.5/(range*100))*10000);
                    output.writeAttribute("style", "stroke:rgb(0,255,0);stroke-width:1;");
                    output.writeEndElement();
                    if(pos > (parseInt(avgField.text)-1))
                    {
                        output.writeStartElement("line");
                        output.writeAttribute("x1", 50+((600/(days-1))*(pos-1)));
                        output.writeAttribute("x2", 50+((600/(days-1))*pos));
                        output.writeAttribute("y1", (avgchange[pos-1]-miny2)*(4.5/(range*100))*10000);
                        output.writeAttribute("y2", (avgchange[pos]-miny2)*(4.5/(range*100))*10000);
                        output.writeAttribute("style", "stroke:rgb(0,0,255);stroke-width:1;");
                        output.writeEndElement();
                    }
                    pos++;
                }
                output.writeEndElement();
                i = 0;
                while(i <= maxy1)
                {
                    output.writeStartElement("text");
                    output.writeAttribute("x", "0");
                    output.writeAttribute("y", -((450/maxy1)*i)+5);
                    output.writeAttribute("font-size", "12");
                    switch(unitBox.currentIndex) {
                        case 0:
                            output.writeCharacters((i / 2.2).toFixed(0));
                            break;
                        case 1:
                        default:
                            output.writeCharacters(i);
                            break;
                    }
                    output.writeEndElement();
                    i += increment;
                }
                i = miny2;
                var stepSize = 0.1;
                while((maxy2 - miny2) / stepSize > 20)
                {
                    stepSize += 0.05;
                }
                while(i <= maxy2)
                {
                    output.writeStartElement("text");
                    output.writeAttribute("x", "670");
                    output.writeAttribute("y", -((i-miny2)*(4.5/(range*100))*10000)+5);
                    output.writeAttribute("font-size", "12");
                    output.writeCharacters(Number(i*100).toFixed(0)+"%");
                    output.writeEndElement();
                    i += stepSize;
                }
                i = 0;
                while(i <= days-1)
                {
                    output.writeStartElement("text");
                    output.writeAttribute("x", 45+((600/(days-1))*i));
                    output.writeAttribute("y", "20");
                    output.writeAttribute("font-size", "12");
                    output.writeAttribute("transform", "rotate(90 "+(45+((600/(days-1))*i))+",20)");
                    q = "SELECT ('"+dates[i]+"'::date - '1 day'::interval)::date";
                    query.exec(q);
                    query.next();
                    var ds = query.value(0);
                    var parts = ds.split("-");
                    switch(parts[1])
                    {
                        case '01':
                            ds = TTR("pytdprodcomp", "January ");
                            break;
                        case '02':
                            ds = TTR("pytdprodcomp", "February ");
                            break;
                        case '03':
                            ds = TTR("pytdprodcomp", "March ");
                            break;
                        case '04':
                            ds = TTR("pytdprodcomp", "April ");
                            break;
                        case '05':
                            ds = TTR("pytdprodcomp", "May ");
                            break;
                        case '06':
                            ds = TTR("pytdprodcomp", "June ");
                            break;
                        case '07':
                            ds = TTR("pytdprodcomp", "July ");
                            break;
                        case '08':
                            ds = TTR("pytdprodcomp", "August ");
                            break;
                        case '09':
                            ds = TTR("pytdprodcomp", "September ");
                            break;
                        case '10':
                            ds = TTR("pytdprodcomp", "October ");
                            break;
                        case '11':
                            ds = TTR("pytdprodcomp", "November ");
                            break;
                        case '12':
                            ds = TTR("pytdprodcomp", "December ");
                            break;
                    }
                    ds = ds + Number(parts[2]);
                    output.writeCharacters(ds);
                    output.writeEndElement();
                    if(i == days-1)
                    {
                        break;
                    }
                    i += 7;
                    if(i > days-1)
                    {
                        i = days - 1;
                    }
                }
                query = query.invalidate();
                output.writeStartElement("rect");
                output.writeAttribute("fill", "rgb(0,0,0)");
                output.writeAttribute("x", "45");
                output.writeAttribute("y", "110");
                output.writeAttribute("width", "24");
                output.writeAttribute("height", "12");
                output.writeEndElement();
                output.writeStartElement("text");
                output.writeAttribute("x", "75");
                output.writeAttribute("y", "120");
                output.writeAttribute("font-size", "12");
                switch(unitBox.currentIndex) {
                    case 0:
                        output.writeCharacters(TTR("pytdprodcomp", "Previous Year Kg"));
                        break;
                    case 1:
                        output.writeCharacters(TTR("pytdprodcomp", "Previous Year Lb"));
                        break;
                }
                output.writeEndElement();
                output.writeStartElement("rect");
                output.writeAttribute("fill", "rgb(255,0,0)");
                output.writeAttribute("x", "195");
                output.writeAttribute("y", "110");
                output.writeAttribute("width", "24");
                output.writeAttribute("height", "12");
                output.writeEndElement();
                output.writeStartElement("text");
                output.writeAttribute("x", "225");
                output.writeAttribute("y", "120");
                output.writeAttribute("font-size", "12");
                switch(unitBox.currentIndex) {
                    case 0:
                        output.writeCharacters(TTR("pytdprodcomp", "Current Year Kg"));
                        break;
                    case 1:
                        output.writeCharacters(TTR("pytdprodcomp", "Current Year Lb"));
                        break;
                }
                output.writeEndElement();
                output.writeStartElement("rect");
                output.writeAttribute("fill", "rgb(0,255,0)");
                output.writeAttribute("x", "345");
                output.writeAttribute("y", "110");
                output.writeAttribute("width", "24");
                output.writeAttribute("height", "12");
                output.writeEndElement();
                output.writeStartElement("text");
                output.writeAttribute("x", "375");
                output.writeAttribute("y", "120");
                output.writeAttribute("font-size", "12");
                output.writeCharacters(TTR("pytdprodcomp", "% Change"));
                output.writeEndElement();
                output.writeStartElement("rect");
                output.writeAttribute("fill", "rgb(0,0,255)");
                output.writeAttribute("x", "495");
                output.writeAttribute("y", "110");
                output.writeAttribute("width", "24");
                output.writeAttribute("height", "12");
                output.writeEndElement();
                output.writeStartElement("text");
                output.writeAttribute("x", "525");
                output.writeAttribute("y", "120");
                output.writeAttribute("font-size", "12");
                output.writeCharacters(TTR("pytdprodcomp", "Average % Change"));
                output.writeEndElement();
                output.writeEndElement();
                output.writeEndElement();
                output.writeEndElement();
                output.writeEndElement();
                output.writeEndElement();
                output.writeEndDocument();
                view.setContent(buffer);
                buffer.close();
            }
            refresh();
            dateSelect.rangeUpdated.connect(function() {
                refresh();
            });
            avgField.editingFinished.connect(function() {
                refresh();
            });
            var notifier = Application.subscribe("roastinglogchange");
            notifier.notify.connect(function() {
                refresh();
            });
        ]]>
    </program>
</window>
