Saturday, 24 January 2015

Using Bootstrap with Web 2.0 technologies (JQuery / AJAX / DataTables/ HighCharts/ etc..) for making a Dashboard for Back-End

A must in Javascript Framework is the well-known JQuery:

Advantages of using JQuery:
-best known javascript Framework
-as says: write less and do more
-simplifying the use of AJAX technology
-multi-browsers compability

AJAX ((Asynchronous JavaScript and XML) is a javascript technology that enables refreshing only a part of a web page without reloading the entire web page while accessing  data from PHP server.

As a back developper, when building web pages, I also use other tools :
- the well known Bootstrap, a CSS/HTML/JS responsive framework (http://getbootstrap.com/)
- The JavaScript library for inserting graphs such  as"Highcharts" library  (cf. http://www.highcharts.com/)
and the Morris library for making good looking graphs (http://www.jqueryscript.net/chart-graph/Morris-Good-looking-Charts-Plugin.html)
- The DataTables jquery library (https://github.com/DataTables/DataTables)
- The Font Awesome  CSS : an Iconic font and CSS Toolkit  (http://fortawesome.github.io/Font-Awesome/)


Using AJAX / Jquery with these tools, one can make website more professional and auto-refreshing, reponsive and thus more versatile.

Here are various internet web sites ("Google is your best friend") that I do recommend  in order to learn and use all those technologies :

-You need to find a course in JQuery/AJAX :  a web site that I particularly recommend is that one :
http://openclassrooms.com/courses/un-site-web-dynamique-avec-jquery

-One of the problem that I encounter was to retrieve JSON data from arrays using AJAX and insert those data dynamically in a HTML table using Jquery/Javascript : I used this tutorial to solve that issue :
https://jonsuh.com/blog/convert-loop-through-json-php-jav
ascript-arrays-objects/

-I also needed to add a column dynamically to those tables (like a delete link)  http://www.amitpatil.me/ajax-table-adding-removing-rows-dynamically-using-javascript-animation/

-I also needed to do some kind of action, giving, for example, a particular purchase serial number and retreive the result of that action, in order to solve some issue straight away using my dashboard : I started from that tutorial  http://ninetofive.me/blog/build-a-live-search-with-ajax-php-and-mysql

- Then, come the necessity of showing some graphs instead of data-tables ; I use different types of javascript libraries such as HighCharts: there is an excellent tutorial on that site, which is using  AJAX to retreive data from server (PHP) : http://blueflame-software.com/blog/column-chart-with-data-from-mysql-using-highcharts/

- Another javacript library for graphs is Morris/Raphael libraries ; for making donut like pie charts, bar charts, or line graphs, there is this tutorial : http://www.jqueryscript.net/chart-graph/Morris-Good-looking-Charts-Plugin.html
(line_graph,bar graph etc..)

- For Morris graphs, I also needed to interact with PHP server using AJAX to get the data : here is a tutorial that solves that issue with Morris Chart graphs :
http://stackoverflow.com/questions/21797450/morris-chart-to-fetch-data-from-a-local-json-file
( another of doing this is also there  : http://stackoverflow.com/questions/24354015/morris-js-donut-chart-not-displaying-chart-when-getting-data-through-ajax-from-p)

- I also encounter the problem of adding a date and the hour within the title of graphs / tables ; this was not that obvious : for doing this, I rely on that tutorial :  http://stackoverflow.com/questions/8398897/how-to-get-current-date-in-jquery

- Another good library is the dataTable.js library, easily adding search fonction, and the possiblility of sorting data from any column of the tables : http://www.datatables.net/examples/ajax/deep.html


Here below, you will find the different type of JS scripts and the  associated HTMLfile  hat I have been using when making the dashboard :

- For Morris graphs : 

$(document).ready(function(){
    $.getJSON("http://localhost/boot/get_montant_commande_par_type_30_jours_glissants_line.php", function (json) {
        Morris.Line({
            element: 'graph_line',
            data: json,
            xkey: 'date',
            ykeys: ['annulation', 'geste_co','expedie'],
            labels: ['Annulations', 'Gestes commerciaux',"Commande non annulées"]
        });
    });
    $.getJSON("http://localhost/boot/get_nb_commande_statut_fraud_5_jours_glissants_bar.php", function (json) {
        Morris.Bar({
            element: 'graph_bar',
            data: json,
            xkey: 'date_purchase',
            ykeys: ['y0', 'y40', 'y80','y90','y100'],
            labels: ['0', '40', '80','90','100']
        }).on('click', function(i, row){
            console.log(i, row);
        });
    });
    $.getJSON("http://localhost/boot/get_repartition_order_status_today_morris_donut.php", function (json) {
        Morris.Donut({
            element: 'morris-donut-chart',
            data: json
        });
    });
});

- For adding hour and date 
// SCRIPT FOR THE "TODAY" BUTTON
function getActualFullDate() {
    var d = new Date();
    var day = addZero(d.getDate());
    var month = addZero(d.getMonth()+1);
    var year = addZero(d.getFullYear());
    var h = addZero(d.getHours());
    var m = addZero(d.getMinutes());
    var s = addZero(d.getSeconds());
    return day + ". " + month + ". " + year + " (" + h + ":" + m + ")";
}

function getActualHour() {
    var d = new Date();
    var h = addZero(d.getHours());
    var m = addZero(d.getMinutes());
    var s = addZero(d.getSeconds());
    return h + ":" + m + ":" + s;
}

function getActualDate() {
    var d = new Date();
    var day = addZero(d.getDate());
    var month = addZero(d.getMonth()+1);
    var year = addZero(d.getFullYear());
    return day + "/" + month + "/" + year;
}
function addZero(i) {
    if (i < 10) {
        i = "0" + i;
    }
    return i;
}

$(document).ready(function(){
    // $("#full").html(getActualFullDate());
    $("#hour_donut").html(getActualHour());
    $("#date_donut").html(getActualDate());
    $("#hour_bar").html(getActualHour());
    $("#date_bar").html(getActualDate());
});

- I also needed to retreive various counters through AJAX using setInterval function :

            var delay = 30000;

            var autoRefreshrefundLate_payment4 = setInterval(
                function ()
                {
                    $.get( "http://localhost/boot/late_payment.php?function=controle_paiement_retard&param=count_duplicate_serveur_paiement", function(data) {
                        $('#blocage_paiement_duplicate').text(data + " Pb Duplicate Back vs Paiement");
                    });

                }
                , delay);    
         
- Here below is one way to dynamically load a table data using AJAX (without dataTable.js)
            var autoRefreshrefundLate12monthsgraph = setInterval(
                function ()
                {
                       $.getJSON( "http://localhost/boot/late_payment.php?function=controle_remboursement_retard&param=json", function(JSONObject) {
                        var RefundHTML = "";

                        // Loop through Object and create RefundHTML
                        for (var key in JSONObject) {
                            if (JSONObject.hasOwnProperty(key)) {
                                RefundHTML += "<tr>";                        
                                RefundHTML += '<td><a href="#?type_id=purchase_serial_number&id=' + JSONObject[key]["purchase_serial_number"]  + '">' + JSONObject[key]["purchase_serial_number"] + "</a></td>";
                                RefundHTML += "<td>" + JSONObject[key]["purchase_creation_date"] + "</td>";
                                RefundHTML += "<td>" + JSONObject[key]["lastmod"] + " <input type='hidden' id='hiddenID' value='" + JSONObject[key]["purchase_serial_number"] +"'> </td>";
                                RefundHTML += '<td><a href="#/payment_reader.php?order_id=' + JSONObject[key]["purchase_serial_number"]  + '"> Serveur de Paiement</a> '
                                + '<a href="#?cart_id=' + JSONObject[key]["purchase_serial_number"] + '"> Cart Détails  ' + "</a></td>";
                                '</td>';

                                RefundHTML += "</tr>";
                            }
                        }
                        // Replace table’s tbody html with RefundHTML
                        $("#tbrefund tbody").html(RefundHTML);
                    });
                }
                , delay);
         

- Here below is one way to dynamically load a table data using AJAX (with dataTable.js tool) : I had to add "a" tag for hyperlink
         
            $(document).ready(function() {

                var table =  $('#tbpaiement').dataTable( {
                    "ajax": {
                        "url": "http://localhost/boot/late_payment.php?function=controle_paiement_retard&param=commandes_attente_synchro",
                        "dataSrc": ""
                    },
                    "columns": [        
                        { "data": "purchase_serial_number" },
                        { "data": "purchase_creation_date" },
                        { "data": "lastmod" },
                        { "data": "purchase_status_fraud" },
                        { "data": "statut_BO" },
                    ],
                     "columnDefs":[
                        {
                            // The `data` parameter refers to the data for the cell (defined by the
                            // `data` option, which defaults to the column being worked with, in
                            // this case `data: 0`.
                            //"data" : "purchase_serial_number",
                            "render": function ( data, type, row ) {
                             
                                return '<a href="xxxxxx?type_id=purchase_serial_number&id=' + data + '"> ' + data + ' </a>';
                            },
                            "targets": [0]
                        }

                    ]
                } );

            );
           
  - Here below, is the way to deal with "HighCharts" :            
            $(document).ready(function() {
                var options = {
                    chart: {
                        renderTo: 'graph_retard_refund',
                        type: 'area',
                        marginRight: 130,
                        marginBottom: 25
                    },
                    title: {
                        text: 'Nbre Commandes en Retards de remboursement par mois',
                        x: -20 //center
                    },
                    subtitle: {
                        text: '',
                        x: -20
                    },
                    xAxis: {
                        categories: []
                    },
                    yAxis: {
                        title: {
                            text: 'Nb de Commandes'
                        },
                        plotLines: [{
                            value: 0,
                            width: 1,
                            color: '#808080'
                        }]
                    },
                    tooltip: {
                        formatter: function() {
                            return '<b>'+ this.series.name +'</b><br/>'+
                            this.x +': '+ this.y;
                        }
                    },
                    legend: {
                        layout: 'vertical',
                        align: 'right',
                        verticalAlign: 'top',
                        x: -10,
                        y: 100,
                        borderWidth: 0
                    },
                    plotOptions: {
                        area: {
                            stacking: 'normal',
                            lineColor: '#666666',
                            lineWidth: 1,
                            marker: {
                                lineWidth: 1,
                                lineColor: '#666666'
                            }
                        }
                    },
                    series: []
                }

                $.getJSON("http://localhost/boot/late_payment.php?function=controle_remboursement_retard&param=graph", function(json) {
                    options.xAxis.categories = json[0]['data'];
                    options.series[0] = json[1];
                    chart = new Highcharts.Chart(options);
                });
            });
         

- Adding an action to the click of a button through AJAX  
    $(document).on("click",".DelFraudQueue", function() {      
        // Set Search String
        var search_string = $(this).attr("id");
        //testdelete($(this).attr("id"));
        // Do Search
        if (search_string == '') {
            $(".badge#results").fadeOut();
            $('.badge#results-text').fadeOut();
        }else{
            $(".badge#results").fadeIn();
            $('.badge#results-text').fadeIn();
            delfraudQueue(search_string);
        };
     
     
    });

function delfraudQueue(query_value) {

$('#search-fraud').text("Processing the resynchronisation for " + query_value + " ....");
if(query_value !== ''){
$.ajax({
type: "GET",
                dataType: 'JSON',
url: "http://localhost/boot/deleteFraudQueue.php",
data: { query: query_value },
cache: false,
success: function(data){
$("#results").text(data["comment"]);
                    $("#results-text").text(data["isprocessed"]);
}
});
}  
}           

- Here below, is the related HTML file that was building using JQuery/Bootstrap/DataTable/Morris/HighCharts/Font Awesome

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <meta http-equiv="X-UA-Compatible" content="IE=edge">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="description" content="">
        <meta name="author" content="jm">
        <link rel="icon" href="../../favicon.ico">

        <title>Dashboard Template for Bootstrap</title>

        <!-- Bootstrap core CSS -->
        <link href="../dist/css/bootstrap.min.css" rel="stylesheet">
        <link href="../dist/css/style.css" rel="stylesheet">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
        <!-- Custom styles for this template --> 
        <link href="dashboard.css" rel="stylesheet">
        <script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
        
        <!-- Morris -->
        <script  type="text/javascript"  src="http://cdnjs.cloudflare.com/ajax/libs/raphael/2.1.0/raphael-min.js"></script>
        <script  type="text/javascript"  src="../js/morris/morris.js"></script>
        <link rel="stylesheet" href="../js/morris/morris.css">
        <script  type="text/javascript"  src="../js/morris/cust_morris-data.js"></script>

        <!-- Load jQuery datatables library   -->
        <script  type="text/javascript"  src="../js/media/js/jquery.dataTables.min.js"></script>

        <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/plug-ins/3cfcc339e89/integration/bootstrap/3/dataTables.bootstrap.css">
      
      
        <!-- Load custom js -->
        <script type="text/javascript" src="../js/custom_deblocage.js"></script>
        <script type="text/javascript" src="../js/custom_delay.js"></script>

    </head>

    <body>
        <nav class="navbar navbar-inverse navbar-fixed-top">
            <div class="container-fluid">
                <div class="navbar-header">

                    <a class="navbar-brand" href="#">Dashboard for Rue Du Commerce</a>
                </div>
                <div id="navbar" class="navbar-collapse collapse">
                    <ul class="nav navbar-nav navbar-right">
                        <li><a href="http://localhost/Tools/dashboard">Dashboard Back</a></li>></li>

                    </ul>
                </div>
            </div>
        </nav>
        <div class="container-fluid" id="main">

            <!-- Example row of columns -->
            <div class="row">
                <div class="col-md-3">
                    
                    <div class="panel panel-default">  
                        <div class="panel-body">
                            <a href="http://localhost/latePayment" > 
                                <button type="button" id="late_paiementbtn"  class="btn btn-primary" data-loading-text="Loading...">
                                    <span  class="glyphicon glyphicon-exclamation-sign" aria-hidden="true"></span>                                                                   <span id="late_paiement" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>   
                    </div>     
                </div>
                <div class="col-md-3">
                    <div class="panel panel-default">
                        <div class="panel-body">
                            <a href="#tbrefundall" > 
                                <button type="button" id="late_refundbtn" class="btn btn-success" data-loading-text="Loading...">
                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>                                                                          <span id="late_refund" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>  
                    </div>
                </div>
                <div class="col-md-3">
                    <div class="panel panel-default">
                        <div class="panel-body">
                            <a href="#tblate_refund_12months" > 
                                <button type="button"  id="late_refund_12monthsbtn" class="btn btn-success" data-loading-text="Loading...">
                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>                                                                          <span id="late_refund_12months" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>  
                    </div>
                </div>                
                <div class="col-md-3">
                    <div class="panel panel-default">
                        <div class="panel-body">
                            <a href="#tblateSynchro" > 
                                <button type="button" id="late_synchro_countbtn" class="btn btn-warning" data-loading-text="Loading...">
                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>                                                                          <span id="late_synchro_count" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>  
                    </div>
                </div> 
            </div>

       
                
            

            <div class="row">   
                 <div class="col-md-3">
                    <div class="panel panel-default">
                        <div class="panel-body">
                            <a href="#tbCmd_inexistante" > 
                                <button type="button" id="Order_not_in_BObtn" class="btn btn-danger" data-loading-text="Loading...">
                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>                                                                          <span id="Order_not_in_BO" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>  
                    </div>
                </div>            

                <div class="col-md-3">
                    <div class="panel panel-default">
                        <div class="panel-body">
                            <a href="#tbBlocage_Fraud" > 
                                <button type="button" id="blocage_fraud_mallbtn" class="btn btn-danger" data-loading-text="Loading...">
                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>                                                                          <span id="blocage_fraud_mall" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>  
                    </div>
                </div>     

                <div class="col-md-3">
                    <div class="panel panel-default">
                        <div class="panel-body">
                            <a href="#tbPb_duplicate_serveur_paiement" > 
                                <button type="button" id="blocage_paiement_duplicatebtn"  class="btn btn-info" data-loading-text="Loading...">
                                    <span class="glyphicon glyphicon-warning-sign" aria-hidden="true"></span>                                                                          <span id="blocage_paiement_duplicate" >Loading...</span>
                                </button>      
                            </a>                                 
                        </div>  
                    </div>
                </div>                
            </div>
                <hr> 
            
            <div class="row">
                <div class="col-lg-6"> 
                    <a name="tblate_refund_12months">
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Remboursements en retard depuis 01/01/2014</h3>
                            </div>
                            <div class="panel-body">
                                <div class="table-responsive">
                                    <table  id="tbrefund" class="table table-bordered table-hover table-striped">
                                        <thead>
                                            <th>PSN </th>
                                            <th>Date commande</th>
                                            <th>Date de dernière modification</th>
                                        </thead>
                                        <tbody>
                                        </tbody>
                                    </table>
                                </div>

                            </div>
                        </div>  
                    </a>
                </div>

                <div class="col-lg-6">
                    <div class="panel panel-info">
                        <div class="panel-heading">
                            <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Remboursements en retard depuis 01/01/2014</h3>
                        </div>
                        <div class="panel-body">
                            <div id="graph_retard_refund" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
                        </div>
                    </div>  

                </div>

            </div>
            <!-- Example row of columns -->
     <hr>
            <div class="row">
                <div class="col-lg-6"> 
                    <a name="tblateSynchro">
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Paiements en attente de synchro</h3>
                            </div>
                            <div class="panel-body">
                                <div class="table-responsive">
                                    <table  id="tbpaiement" class="table table-bordered table-hover table-striped">
                                        <thead>
                                            <th>PSN </th>
                                            <th>Date commande</th>
                                            <th>Date de dernière modification</th>
                                            <th>Status fraud Mall</th>
                                            <th>Status fraud BO</th>
                                        </thead>
                                    </table>
                                </div>
                            </div>
                        </div>  
                    </a>
                </div>

                <div class="col-lg-6">
                    <div class="panel panel-info">
                        <div class="panel-heading">
                            <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Répartition des Paiements en retard</h3>
                        </div>
                        <div class="panel-body">
                            <div id="graph_retard_payment" style="min-width: 400px; height: 400px; margin: 0 auto"></div>
                        </div>
                    </div>  

                </div>

            </div>        
            
            
              <div class="row">
               
             
                <div class="col-lg-4"> 
                     <a name="tbCmd_inexistante">
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Commandes inexistantes</h3>
                            </div>
                            <div class="panel-body">
                                <div class="table-responsive">
                                    <table  id="tbCmd_inexistante" class="table table-bordered table-hover table-striped">
                                        <thead>
                                            <th>PSN </th>
                                            <th>Date commande</th>
                                            <th>Date de dernière modification</th>
                                            <th>Status fraud</th>
                                        </thead>
                                        <tbody>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>  
                            </a>
                </div>
      
                
                <div class="col-lg-4"> 
                    <a name="tbBlocage_Fraud">
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Blocage des fraudes</h3>
                            </div>
                            <div class="panel-body">
                                <div class="table-responsive">
                                    <table  id="tbBlocage_Fraud" class="table table-bordered table-hover table-striped">
                                        <thead>
                                            <th>PSN </th>
                                            <th>Date commande</th>
                                            <th>Date de dernière modification</th>
                                            <th>Status fraud Mall</th>

                                        </thead>
                                        <tbody>
                                        </tbody>
                                    </table>
                                </div>
                                <form class="form-horizontal" role="form" method="get">
                                    <div class="form-group">
                                        <label class="col-sm-2 control-label" for="PSN">PSN</label>
                                        <div class="input-group col-sm-9">
                                            <input id="PSN" name="PSN" type="text" class="form-control" placeholder="Give PSN" />
                                            <span class="input-group-btn">
                                                <button type="button" class="btn btn-default btn-danger">
                                                     Delete Fraud_queue
                                                </button>
                                            </span>
                                        </div>
                                    </div>
                                </form>
                                <div class="list-group">
                                    <li class="list-group-item">
                                        <span class="badge" id="search-fraud"></span>
                                        <i class="fa fa-fw fa-calendar"></i>Process
                                    </li>
                                    <li class="list-group-item">
                                        <span class="badge" id="results"></span>
                                        <i class="fa fa-fw fa-calendar"></i>Result
                                    </li>
                                    <li class="list-group-item">
                                        <span class="badge" id="results-text"></span>
                                        <i class="fa fa-fw fa-comment"></i> Resynchronisation
                                    </li>
                                </div>
                                <!-- Show Results -->

                            </div>
                        </div>  
                    </a>
                </div>
                
                <div class="col-lg-4"> 
                    <a name="tbPb_duplicate_serveur_paiement">
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Pb de cohérence sur duplicate</h3>
                            </div>
                            <div class="panel-body">
                                <div class="table-responsive">
                                    <table  id="tbPb_duplicate_serveur_paiement" class="table table-bordered table-hover table-striped">
                                        <thead>
                                            <th>PSN </th>
                                            <th>Date commande</th>
                                            <th>Date de dernière modification</th>
                                            <th>Status fraud</th>
                                        </thead>
                                        <tbody>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>  
                    </a>
                </div>

            </div> 
            
             <div class="row">      
                 
                <div class="col-lg-5"> 
                  <a name="tbrefundall">      
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Liste des remboursements en retard</h3>
                            </div>
                            <div class="panel-body">
                                <div class="table-responsive">
                                    <table  id="tbrefundall">
                                        <thead>
                                            <tr>
                                                <th>Purchase Serial Number (PSN)        </th>
                                                <th>Montant Rembt</th>
                                                <th>Order Detail Unit Id</th>
                                                <th>Date Commande</th>
                                                <th>Date de derniere modification</th>
                                            </tr>
                                        </thead>

                                        <tfoot>
                                            <tr>
                                                <th>Purchase Serial Number (PSN)  </th>
                                                <th>Montant Remboursement</th>
                                                <th>Order Detail Unit Id</th>
                                                <th>Date de Commande</th>
                                                <th>Date de derniere modification</th>
                                            </tr>
                                        </tfoot>
                                    </table>
                                </div>
                            </div>
                        </div>  
                    </a>
                </div>    
            
            
                 <div class="col-lg-3"> 
                     <div class="panel panel-info">
                         <div class="panel-heading">
                             <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Répartition des commandes  du <span id='date_donut'></span> par Status à <span id='hour_donut'></span></h3>
                         </div>
                         <div class="panel-body">
                             <div id="morris-donut-chart" ></div>    
                    
                         </div>
                     </div>  
                 </div>    
                 
                 <div class="col-lg-4"> 
                     <div class="panel panel-info">
                         <div class="panel-heading">
                             <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Répartition des status de fraude sur les 5 derniers jours - situation du <span id='date_bar'></span> à <span id='hour_bar'></span></h3>
                         </div>
                         <div class="panel-body">
                                <div id="graph_bar" ></div>      
                         </div>
                     </div>  
                 </div>    

             </div> <!-- /row -->
             <div class="row">      
                 
                <div class="col-lg-12"> 
                  <a name="tbrefundall">      
                        <div class="panel panel-info">
                            <div class="panel-heading">
                                <h3 class="panel-title"><i class="fa fa-money fa-fw"></i> Répartitions sur les 30 derniers jours des montants pour les commandes annulées, non annulées ou remboursées par gestes commerciaux </h3>
                            </div>
                            <div class="panel-body">
                                    <div id="graph_line" ></div>    
                            </div>
                        </div>  
                    </a>
                </div>  
             </div>    

            <br>
            <footer>
                <p>&copy; Company 2013</p>
            </footer>

        </div> <!-- /container -->


        <!-- Bootstrap core JavaScript
        ================================================== -->
        <!-- Placed at the end of the document so the pages load faster -->
        <script src="../dist/js/bootstrap.min.js"></script>
         <script src="http://code.highcharts.com/highcharts.js"></script>
        <script src="http://code.highcharts.com/modules/exporting.js"></script>
    </body>
</html>


Here is a view of the dashboard once finished :





Thursday, 30 October 2014

Difference when declaring variables in Mysql / SQL

You may have notice that there is a lot of differences in writing queries in SQL vs. Mysql; One of this difference concerns the definition of variables:

One way to do it in SQL :

DECLARE @ID VARCHAR(15)
SELECT  @ID ='000000001'

SELECT * from [TABLE] (nolock) WHERE  ID = @cID;

(we could use SET instead of SELECT - here, we have used VARCHAR but  any other kind of variable could have been used!!)

The equivalent in Mysql will be the following :

SELECT @ID:= '000000001';

SELECT * from [TABLE] (nolock) WHERE  ID = @cID;

Wednesday, 29 October 2014

Managing errors with cURL library access

Having one URL ($sURL), we would like to get the associated file content (this can be any file, not only an  XML file):

Here is the PHP code using cURL library with the 'cur_exec' function to get the content, and the 'curl_errno' function to get the possible error message !!!

<?php
$sUrl = "http://tycaron.blogspot.fr/2014/10/managing-errors-with-curl-library-access.ht";
$bError = false;
$sXml = GetCurl_Response($sUrl);
 if ($sXml === false)
{
        $bError = true;
        $aErrors[] = GetCurl_Error($sUrl);
}

if ($bError) var_dump($aErrors);

/*
 * get the file content related to an URL
* @param  string $url
* @return string
*/
function GetCurl_Response($url)
{
  // create curl resource
  $curl = curl_init($url);

  // var_dump($curl);
  curl_setopt($curl, CURLOPT_FAILONERROR, true);
  curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  $result = curl_exec($curl);


  //close curl resource to free up system resources
  curl_close($curl);
  return $result;
}

/*
 * get cURL error (return 'false' if no error)
 * @return string
*/
function GetCurl_Error($url)
{
  // create curl resource
  $curl = curl_init($url);

  // var_dump($curl);
  curl_setopt($curl, CURLOPT_FAILONERROR, true);
  curl_setopt($curl, CURLOPT_FOLLOWLOCATION, true);
  curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
  curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
  curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
  $result = curl_exec($curl);
 if ($result===false)
   $error_curl = 'Erreur Curl : ' .curl_error($curl).' ('.curl_errno($curl).')';
  else
   $error_curl = false;

  //close curl resource to free up system resources
  curl_close($curl);
  return $error_curl ;
}
?>

Having made volontarily an error when writing URL, the output error message will then be :
array(1) { [0]=> string(66) "Erreur Curl : The requested URL returned error: 404 Not Found (22)" }

Thursday, 9 October 2014

Rewriting URL

When dealing with resful webservice, one of the principle for the architecture is to use "cleaning URL" or the also called Semantic URL  ; one way to do that is to add some rules to redirect URL within an .htaccess file;
Say you have a resource "users",. I could set up a number of URIs like so:
/api/users     when called with GET, lists users
/api/users     when called with POST, creates user record
/api/users/1   when called with GET, shows user record
               when called with PUT, updates user record
               when called with DELETE, deletes user record
To have a correct representation of a RESTful architecture, one can define  an .htaccess file to so that it redirects any of these URIs to one file, 'user.php' :
.htaccess
Options +FollowSymLinks
RewriteEngine On
RewriteRule ^api/([0-9a-zA-Z]+)/([0-9_-]+)$ user.php [L]
user.php
<?php
    $path = $_SERVER['REQUEST_URI'];
    $url_elements = explode('/', $path);
    $verb = $_SERVER['REQUEST_METHOD'];
    echo $verb."<br>";
    echo "ID = ".$url_elements[5]."<br>";
    echo "NAME = ".$url_elements[6]."<br>";;
    
?>

In doing so, while accessing the following URL http://localhost/api/user/12, the screen will print out :

ID = user
NAME = 12

Wednesday, 8 October 2014

Calling a database stored procedure from PHP

If a stored procedure retuns a 'select' query within a database, a PHP function calling that stored procedure will be similar to :

function ExecStoreProcSelect()
{
$oStatement = $this->mssql->prepare("Exec [Procedure name]  @Json= :Json ;");
  $oStatement ->bindValue(':Json', $sJson, \PDO::PARAM_STR);

$bResult = $oStatement->execute();
if (!$bResult)
{
return false;
}
return $oStatement->fetchAll(\PDO::FETCH_ASSOC);
/* OR 
  $sSelect = "SELECT @@ROWCOUNT as nb_line_return"; // give the nb of line being returned during the last instruction

  $aResults = $this->mssqlBosql->query($sSelect)->fetch(\PDO::FETCH_ASSOC);
  if ($aResults['nb_line_return'] < 1) { return array('errors' => array('No return by the stored   procedure !')); }
  else { return true; }
*/
} 

If no return is expected from the stored procedure, this function could be simplify like this :

function ExecStoreProcUpdate()
{
$oStatement = $this->mssql->prepare("Exec [Procedure name];");
$bResult = $oStatement->execute();
if (!$bResult)
{
return false;
}
return true;
} 


In mysql, the syntax will be slightly different (cf . http://www.mysqltutorial.org/php-calling-mysql-stored-procedures/) using CALL instead of EXEC :

for a stored procedure like this one :
"
DELIMITER $$
CREATE PROCEDURE GetCustomerLevel(
    in  p_customerNumber int(11),
    out p_customerLevel  varchar(10))
BEGIN
    DECLARE creditlim double;
    SELECT creditlimit INTO creditlim
    FROM customers
    WHERE customerNumber = p_customerNumber;
    IF creditlim > 50000 THEN
    SET p_customerLevel = 'PLATINUM';
    ELSEIF (creditlim <= 50000 AND creditlim >= 10000) THEN
        SET p_customerLevel = 'GOLD';
    ELSEIF creditlim < 10000 THEN
        SET p_customerLevel = 'SILVER';
    END IF; 
END$$
"

The access through PHP can be done via :
require_once 'dbconfig.php';
$customerNumber = 103;
try {
    $conn = new PDO("mysql:host=$host;dbname=$dbname", $username, $password);
    // execute the stored procedure
    $sql = 'CALL GetCustomerLevel(:id,@level)';
    $stmt = $conn->prepare($sql);
    $stmt->bindParam(':id', $customerNumber, PDO::PARAM_INT);
    $stmt->execute();
    $stmt->closeCursor();
    // execute the second query to get customer's level
    $r = $conn->query("SELECT @level AS level")->fetch(PDO::FETCH_ASSOC);
    if ($r) {
        echo sprintf('Customer #%d is %s', $customerNumber, $r['level']);
    }
} catch (PDOException $pe) {
    die("Error occurred:" . $pe->getMessage());
}

The use of "===" instead "==" to test the result of a function

When managing one error, which is returning from a function, I have been faced with the importance of using "= = =" instead of " =  = " ;

Imagine the following case: a function with database query within a foreach with a control from the query return (here, we have just a 'select' but it could have been an 'insert',  an 'update', a 'delete' etc..)


[..]
foreach ($parcels as $aparcel)
{
$events = $this->getEvents($aparcel[id]);
if ($events === false)
        {
$_aMsgs['errors'][$i] = "Error in the resulting data getParcelsEvents";
$i = $i + 1;
continue;
       }
       else { //using $events for doing stuff even if empty
     
       }
}
[..]

protected function getEvents($parcelsid)
{

   $sQuery = "select [fields]
   from [table] (nolock)
   where no_colis = '$parcelsid';";

$oStatement = mysql->prepare($sQuery);

$bResult = $oStatement->execute();
if (!$bResult)
{
//echo $sQuery.PHP_EOL;
return false;
}
return $oStatement->fetchAll(\PDO::FETCH_ASSOC);
}


At start, I was using "if ($events = = false)" to control the results from the getEvents function, but, doing so,  one empty result from the database query was considered as an error - that was not the behavior that I was expected ; the solution was to use "=  =  =" to be sure to test only the "false" returning case and not that empty case !!!

From now on, I am using mostly the triple "=" when dealing return of a function!