How can I sort month by order? - sql

I displays all the months even there is no data in every month. I use an SQL query to get all the months that have data and VueJS to get all the months with no data. The problem is all the months with data came first and the next one is the no data. The label looks like this April, May, June, July, August, January, February, March, September, October, November, December. How can I sort the months according to the calendar? Can somebody help me with my problem? Here's my code.
METHODS
retrieveDistributedPerMonthByLine : function() {
var self = this;
var months = ["January", 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
axios.post(this.urlRoot + this.api + "retrieve_transaction_per_month.php")
.then(response => {
// console.log("m");
console.log(response);
vm.transaction_per_month = response.data
for(var i = 0 ; i < months.length; i++) {
var isFound = false;
for(var j = 0 ; j < this.transaction_per_month.length; j++) {
if(this.transaction_per_month[j].Month == months[i]) {
isFound = true;
break;
}
}
if(!isFound) {
this.transaction_per_month.push({
Month: months[i],
Amount: 0,
Beneficiary: 0,
Quantity: 0
});
}
}
var ctxChart = self.$refs.myChart3.getContext('2d')
var myChart3 = new Chart(ctxChart, {
type: 'bar',
data: {
labels: vm.transaction_per_month.map(item => item.Month),
datasets: [{
label: 'Total Amount',
data: vm.transaction_per_month.map(item => item.Amount),
backgroundColor: this.poolColors(vm.distributed_per_day.length),
borderColor: '#eee',
borderWidth: 1
}]
},
reponsive: true,
options: {
title : {
display : true,
text : "Distributed Reports per Month",
fontFamily: "sans-serif",
fontSize: 18
},
legend: {
display: false
},
tooltips: {
enabled: true
}
}
});
}).catch(e => {
console.log(e)
});
},
SQL
public function getTransactionPerMonth() {
$sql="SELECT DATE_FORMAT(tbl_transaction.transaction_date, '%M')
AS
Month, SUM(tbl_transaction_details.total_price)
AS
Amount, SUM(tbl_transaction_details.quantity)
AS
Quantity, COUNT(tbl_transaction.beneficiary_id)
AS
Beneficiary
FROM
tbl_transaction_details
INNER JOIN
tbl_supplier_medicine ON tbl_transaction_details.supplier_medicine_id = tbl_supplier_medicine.supplier_medicine_id
INNER JOIN
tbl_transaction ON tbl_transaction.transaction_id = tbl_transaction_details.transaction_id
INNER JOIN
tbl_barangay ON tbl_barangay.barangay_id = tbl_transaction.barangay_id
WHERE
YEAR(tbl_transaction.transaction_date) = YEAR(NOW())
AND
tbl_transaction_details.total_price > 0
AND
tbl_barangay.barangay_id = $_SESSION[barangay_id]
GROUP BY
DATE_FORMAT(tbl_transaction.transaction_date, '%M')
ORDER BY
MAX(tbl_transaction.transaction_date)";
$stmt = $this->connection->prepare($sql);
$stmt->execute();
return $stmt->fetchAll();
}

Try this:
computed : {
sorted_orders_by_months() {
var months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
return this.transaction_per_month.sort(function(a, b){
return months.indexOf(a.Month) - months.indexOf(b.Month.);
});
}
}
And then to represent it you can do something like:
v-for="(value, index) in sorted_orders_by_months"

Related

Multiple conditions inside match MongoDB

I want to convert the following SQL query to MongoDB query:
SELECT count(invoiceNo), year, month, manager
FROM battle
WHERE year=2021 AND month='Dec' OR year=2022 AND month='Jan' AND manager = 'name#test.com'
GROUP BY year,month;
I've tried to do so, but it seems to be incorrect:
const getNoOfOrders = await BattlefieldInfo.aggregate([
{
$match: {
$and: [
{
year: periodDate[0]['year']
},
{ month: periodDate[0]['month'] }
],
$or: [
{
$and: [
{
year: prevYear
},
{ month: prevMonth }
]
}
],
$and: [{ manager: email }]
}
},
{
$group: {
_id: '$month'
}
},
{
$project: {
// noOfOrders: { $count: '$invoiceNo' },
month: 1,
year: 1,
manager: 1
}
}
]);
Because I am getting an empty array. But it should be something like this:
| count(invoiceNo) | manager | year | month |
+------------------+---------------+------+-------+
2 name#test.com 2021 Dec
3 name#test.com 2022 Jan
From my point of view, I think parenthesis (bracket) is important to group the conditions together such as month and year.
SELECT count(invoiceNo), `year`, month, manager
FROM battle
WHERE (`year` = 2021 AND month = 'Dec')
OR (`year` = 2022 AND month = 'Jan')
AND manager = 'abc#email.com'
GROUP BY month, `year`
Sample DBFiddle
Same goes for your MongoDB query. While to search with month and year, you can do without $and as below:
{
year: 2021,
month: "Dec"
}
Instead of:
$and: [
{
year: 2021
},
{
month: "Dec"
}
]
And make sure that $group stage need an accumulator operator:
noOfOrders: {
$count: {}
}
Or
noOfOrders: {
$sum: 1
}
Complete MongoDB query
db.collection.aggregate([
{
$match: {
$or: [
{
year: 2021,
month: "Dec"
},
{
year: 2022,
month: "Jan"
}
],
manager: "abc#email.com"
}
},
{
$group: {
_id: {
month: "$month",
year: "$year"
},
noOfOrders: {
$count: {}
},
manager: {
$first: "$manager"
}
}
},
{
$project: {
_id: 0,
noOfOrders: 1,
month: "$_id.month",
year: "$_id.year",
manager: "$manager"
}
}
])
Sample Mongo Playground
Note:
Would be great for both queries to add manager as one of the group keys. Since you are filtering for the specific (only one) manager's record(s), it's fine. But without filtering for specific manager, your query will result in the wrong output.

On-click event display data on heap map in highcharts

This image contains details about the number of projects was uploaded by the particular user
I am using heapmap highchart to display project details of a user.
on Y-axis => represents week of the days which ranges from 0 to 6
eg. Mon = 0, Tue= 1,....Sun=6
on X-axis => represents months, which ranges from 0 to 11
eg. Jan = 0, Feb = 1, ... Dec = 11
Data format
X Y Data
[0 ,1 , 3]
Suppose, 3 projects was uploaded by a user on monday in the month of January.
When I click on that 3 on heap map then it should display a pop box,
which should include project name,date and time
eg. Project Name : image recognition
Date : Uploaded on Jan 4,2019
Time : 10:04:00
In this I have hardcoded the data.
https://jsfiddle.net/k9hyfjmL/
This code retrieve data from mysql database and populates on heap map, which indicates number of projects was uploaded by a user.
$(document).on('click', '.click_once', function()
{
$.ajax(
{
url: '/profile/heap_map_data',
type: 'GET',
success: function(response)
{
var chart_data = [];
var skip_1st_data = 1;
var take_Data_upto = 0;
for (var i = 0, len = response.length; i < len; i++)
{ if(skip_1st_data == 1)
{
skip_1st_data = 2;
}
else{
take_Data_upto = take_Data_upto + 1;
chart_data.push(response[i]);
if(take_Data_upto == 31)
{
break;
}
}
}
console.log(chart_data)
Highcharts.chart('heap_map_chart',
{
chart:
{
type: 'heatmap',
marginTop: 40,
marginBottom: 80,
plotBorderWidth: 1,
},
title:
{
text: 'Project Details'
},
xAxis:
{
categories: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']
},
yAxis:
{
categories: ['Mon','Tue','Wed','Thur','Fri','Sat','Sun'],
title: null
},
colorAxis:
{
min: 0,
minColor: '#FFFFFF',
maxColor: Highcharts.getOptions().colors[0]
},
legend:
{
align: 'right',
layout: 'vertical',
margin: 0,
verticalAlign: 'top',
y: 25,
symbolHeight: 280
},
tooltip:
{
formatter: function ()
{
return + this.point.value + ' <b> project was uploaded on ' + this.series.xAxis.categories[this.point.x] + ' date, 2019' + '<br /> click to view more' ;
}
},
series: [
{
borderWidth: 1,
data: chart_data,
dataLabels:
{
enabled: true,
color: '#000000'
}
}]
});
},
error : function(jqXHR, textStatus, errorThrown)
{
console.log('jqXHR:');
console.log(jqXHR);
console.log('textStatus:');
console.log(textStatus);
console.log('errorThrown:');
console.log(errorThrown);
alert(errorThrown);
}
});
});
You can use point.events.click function to display some more information in another HTML element:
series: [{
point: {
events: {
click: function() {
document.getElementById('moreInfo').innerText =
'value: ' + this.value;
}
}
},
...
}]
Live demo: https://jsfiddle.net/BlackLabel/p261zg9d/
API Reference: https://api.highcharts.com/highcharts/series.heatmap.point.events.click

Chartist Pie Char Custom Label

I am trying to customize the label of Chartist Pie Chart so that it will show both the label and value.
So in the example below, I would want the label to show "Bananas - 20", "Apples - 15", "Grapes - 40". I know I can just change the labels:, but is there a way to do that with the labelInterpolationFnc?
https://jsfiddle.net/ckmz7L1p/
var data = {
labels: ['Bananas', 'Apples', 'Grapes'],
series: [20, 15, 40]
};
var options = {
labelInterpolationFnc: function(value) {
return value[0]
}
};
var responsiveOptions = [
['screen and (min-width: 640px)', {
chartPadding: 30,
labelOffset: 100,
labelDirection: 'explode',
labelInterpolationFnc: function(value) {
return value;
}
}],
['screen and (min-width: 1024px)', {
labelOffset: 80,
chartPadding: 20
}]
];
new Chartist.Pie('.ct-chart', data, options, responsiveOptions);
Got it figured out. Didn't realize labelInterpolationFnc can take function with both value and index parameters.
var data = {
labels: ['Bananas', 'Apples', 'Grapes'],
series: [20, 15, 40]
};
var options = {
width: "400px",
height: "400px",
labelInterpolationFnc: function(value, idx) {
return value + " - " + data.series[idx];
}
};
var responsiveOptions = [
['screen and (min-width: 640px)', {
chartPadding: 0,
labelOffset: 0,
labelDirection: 'explode',
labelInterpolationFnc: function(value, idx) {
return value + " - " + data.series[idx];
}
}],
['screen and (min-width: 1024px)', {
labelOffset: 30,
chartPadding: 0
}]
];
new Chartist.Pie('.ct-chart', data, options, responsiveOptions);

Format Date inside jQuery datatable

I am using jQuery datatables to display sms statistics on my web app, the datatable is used for ease of paging, search and sorting functionalities which works fine. However ene of the columns on the data table is a date,here is my action method that returns the json object
public ActionResult LoadStatistics(jQueryDataTableParamModel param)
{
//jQueryDataTableParamModel param = new jQueryDataTableParamModel();
var allStats = _dbManager.GetSMSStatitistics();
var filteredStats = allStats;
if (!string.IsNullOrWhiteSpace(param.sSearch))
{
filteredStats = filteredStats.Where(x => x.StaffNameF.Contains(param.sSearch, false)
|| x.StaffNameS.Contains(param.sSearch, false)
|| x.SiteID.Contains(param.sSearch, false)).ToList();
}
return Json(new
{
iTotalRecords = allStats.Count(),
iTotalDisplayRecords = filteredStats.Count(),
aaData = filteredStats
}, JsonRequestBehavior.AllowGet);
}
Now in the view I have the following piece of code,to load data into my table,
#section scripts
{
<script type="text/javascript">
$(function () {
$('#statsTable').dataTable({
bProcessing: true,
bServerSide: false,
bPaginate: true,
sAjaxSource: '#Url.Action("LoadStatistics", "Statistics")',
"aoColumnDefs": [
{ "aTargets": [0], "mData": 'StaffNameF' },
{ "aTargets": [1], "mData": 'StaffNameS' },
{ "aTargets": [2], "mData": 'StaffEmail', "sWidth": "300px" },
{ "aTargets": [3], "mData": 'SiteID' },
{ "aTargets": [4], "mData": 'DateTimeIn', "sWidth": "300px", "sFormat": "dd/MM/YYYY" },
{ "aTargets": [5], "mData": 'CellNumber' }]
});
});
</script>
This is working fine for all the columns, except the date which displays something like this "/Date(1488924000000)/". I am assuming this is the date but it just needs formatting, how can I achieve this, I have tried "sFormat": "dd/MM/YYYY" but no luck, I have no clue how to do this inside the table.
Json does not have a standard format for Dates.
You can either return the date as a string from the server or use datatables column rendering to parse and format the date clientside.
Returning the date as a formatted string from the server side:
return Json(new
{
iTotalRecords = allStats.Count(),
iTotalDisplayRecords = filteredStats.Count(),
aaData = filteredStats.Select(x => new {
StaffNameF = x.StaffNameF,
StaffNameS = x.StaffNameS,
StaffEmail = x.StaffEmail,
SiteID = x.SiteID,
DateTimeIn = x.DateTimeIn.ToString("dd/MM/YYYY"),
CellNumber = x.CellNumber })
}, JsonRequestBehavior.AllowGet);
Or formatting on the client side:
<script type="text/javascript">
$(function () {
$('#statsTable').dataTable({
bProcessing: true,
bServerSide: false,
bPaginate: true,
sAjaxSource: '#Url.Action("LoadStatistics", "Statistics")',
"aoColumnDefs": [
{ "aTargets": [0], "mData": 'StaffNameF' },
{ "aTargets": [1], "mData": 'StaffNameS' },
{ "aTargets": [2], "mData": 'StaffEmail', "sWidth": "300px" },
{ "aTargets": [3], "mData": 'SiteID' },
{ "aTargets": [4], "mData": 'DateTimeIn', "sWidth": "300px", "mRender": function ( data, type, full ) {
var d = new Date();
d.setTime(1245398693390);
return d.getDate() + "/"+ (d.getMonth() + 1) + "/" + d.getFullYear();
},
{ "aTargets": [5], "mData": 'CellNumber' }]
});
});
</script>

Display the time picker value in the textfield using sencha touch 2

Ext.define("Datetimepicker.view.Main", {
extend: 'Ext.form.Panel',
requires: [
'Ext.TitleBar',
'Ext.field.DatePicker',
'Ext.Spacer',
'Ext.Picker'
],
config: {
fullscreen:'true',
title:'DatatimePicker',
items: [
{
xtype:'fieldset',
items:[
{
xtype:'datepickerfield',
label:'Birthday',
picker:{
yearFrom:1980,
yearTo:2015
},
name:'birthday',
value:new Date()
},
{
xtype:'textfield',
label:'Time',
value:''
//In this textfield i want to display the time picker value
}
}
]
},
{
items:[
{
xtype:'spacer'
},
{
text: 'setValue',
handler: function() {
var datePickerField = Ext.ComponentQuery.query('datepickerfield')[0];
var randomNumber = function(from, to) {
return Math.floor(Math.random() * (to - from + 1) + from);
};
datePickerField.setValue({
month: randomNumber(0, 11),
day : randomNumber(0, 28),
year : randomNumber(1980, 2015)
});
}
},
{ xtype:'spacer'}
]
}
]
}
});
By using above code I'm getting the value of datepicker which successfully display in the first textfield.In the same way I want to display that value of datepicker in another textfield.
Can anyone help me to do this ...thanks in advance
You can do it by setting the value of the textfield every time your picker's value has been changed so here is a solution:
items: [
{
xtype: 'datepickerfield',
label: 'Birthday',
name: 'birthday',
value: new Date(),
listeners: {
change: function(picker, value) {
// This function use to prepend 0 to the month which less than October
function minTwoDigits(n) {
return (n < 10 ? '0' : '') + n;
}
var date = value.getDate(), // Get date's value
month = value.getMonth(); // Get month's value
month += 1; // Increase the number of month by 1 since the index started with 0
var formatMonth = minTwoDigits(month),
year = value.getFullYear(), // Get year's value
formatDate = formatMonth.concat("/",date,"/",year); // Concatenate string
Ext.ComponentQuery.query('#textfield')[0].setValue(formatDate); // Set the value of the textfield with itemID equal to textfield
}
}
},
{
xtype:'textfield',
label:'time',
itemId: 'textfield',
value:''
}
]
If you don't understand anything, feel free to ask. Hope it helps :)