diff --git a/src/main/java/org/ccalm/main/AcceptASDCController.java b/src/main/java/org/ccalm/main/AcceptASDCController.java index 776598f..b654826 100644 --- a/src/main/java/org/ccalm/main/AcceptASDCController.java +++ b/src/main/java/org/ccalm/main/AcceptASDCController.java @@ -2526,7 +2526,7 @@ public class AcceptASDCController implements ServletContextAware { response.setContentType("application/xml"); return result; } - + //Connect to database Connection conn = null; try { diff --git a/src/main/java/org/ccalm/main/AcceptJSON.java b/src/main/java/org/ccalm/main/AcceptJSON.java index d2ac7e8..286d690 100644 --- a/src/main/java/org/ccalm/main/AcceptJSON.java +++ b/src/main/java/org/ccalm/main/AcceptJSON.java @@ -429,6 +429,7 @@ public class AcceptJSON implements ServletContextAware { //--------------------------------------------------------------------------- /** * Пример запроса: https://127.0.0.1:8081/AcceptJSON но в теле нужно поменять строку "Year y = Year.of(2024);" а также номер дня + * By document: "API фитомониторинг ФАО (1.3).docx" * @param user * @param model * @param file @@ -1198,6 +1199,7 @@ public class AcceptJSON implements ServletContextAware { } //--------------------------------------------------------------------------- //https://127.0.0.1:8083/AcceptJSON_UZB + // Contact: Abdulrahmon Muhitdinov in telegram. @ResponseBody @RequestMapping(value = {"/AcceptJSON_UZB", "/api/locust/v01/AcceptJSON_UZB"}, method = { RequestMethod.GET, RequestMethod.POST }, produces = MediaType.APPLICATION_JSON_VALUE) public String acceptUZB(@ModelAttribute User user) { @@ -1692,7 +1694,7 @@ public class AcceptJSON implements ServletContextAware { result.larva_age_id="1"; result.larva_age_uid="30fa1f49-166e-4a17-9cd8-d611b36844f8"; break; - case "Transiens","Переходная","Фаза 2 ru": + case "Transiens","Переходная","Фаза 2 ru","Фаза ru": result.larva_age_id="2"; result.larva_age_uid="a0146c08-17b4-4384-8764-b7541c106d10"; break; @@ -1737,7 +1739,7 @@ public class AcceptJSON implements ServletContextAware { result.kuliguli_action_id="1"; result.kuliguli_action_uid="4399f28c-b1ed-44f6-8af5-351cd944d408"; break; - case "Feeding","Питание": + case "Feeding","Питание","Поведение ru": result.kuliguli_action_id="2"; result.kuliguli_action_uid="49cd15e0-8a55-4a8f-8a2a-3872f770f248"; break; @@ -1789,7 +1791,7 @@ public class AcceptJSON implements ServletContextAware { result.imago_phase_id="4"; result.imago_phase_uid="a1325ab8-15f5-406a-be8d-d6ba78b18d11"; break; - case "Transiens","Одиночная","Фаза 2 ru": + case "Transiens","Одиночная","Фаза 2 ru","Фаза ru": result.imago_phase_id="5"; result.imago_phase_uid="454ad32d-e513-4cda-90eb-e3fcac9bd41c"; break; diff --git a/src/main/java/org/ccalm/main/Integration.java b/src/main/java/org/ccalm/main/Integration.java index 9d22059..6ccd0e6 100644 --- a/src/main/java/org/ccalm/main/Integration.java +++ b/src/main/java/org/ccalm/main/Integration.java @@ -653,6 +653,91 @@ public class Integration implements ServletContextAware { } } + @RequestMapping(value = {"/api/locust/v01/integration/days-statistics"}, method = RequestMethod.GET, produces = "application/json; charset=utf-8") + @ResponseBody + public Object getDaysStatistics( + @RequestParam(required = true, name = "country") String country, + @RequestParam(required = true, name = "dateBegin") String dateBegin, + @RequestParam(required = true, name = "dateEnd") String dateEnd) + { + int errorCode = 0; + String errorCodeDescription = ""; + + String tableSuffix; + if ("kz".equals(country)) tableSuffix = "days_kz"; + else if ("ru".equals(country)) tableSuffix = "days_ru"; + else if ("uz".equals(country)) tableSuffix = "days_uz"; + else { + JSONObject obj = new JSONObject(); + obj.put("errorCode", 1); + obj.put("errorCodeDescription", "Invalid country parameter. Allowed: kz, ru, uz"); + return obj.toString(); + } + + Connection conn = null; + try { + Class.forName("org.postgresql.Driver"); + conn = DriverManager.getConnection(db_url, db_login, db_password); + } catch (Exception ex) { + errorCode = 3; + errorCodeDescription += "Internal server error, database. "; + ex.printStackTrace(); + } + + JSONObject result = new JSONObject(); + JSONArray days = new JSONArray(); + int total = 0; + + PreparedStatement stmt = null; + ResultSet rs = null; + try { + String sql = "SELECT date::date AS day, count FROM integration." + tableSuffix + + " WHERE date::date BETWEEN TO_DATE(?,'YYYY-MM-DD') AND TO_DATE(?,'YYYY-MM-DD') ORDER BY date"; + stmt = conn.prepareStatement(sql); + stmt.setString(1, dateBegin); + stmt.setString(2, dateEnd); + + rs = stmt.executeQuery(); + if (rs != null) { + try { + while (rs.next()) { + JSONObject day = new JSONObject(); + day.put("date", rs.getString("day")); + day.put("count", rs.getInt("count")); + days.put(day); + total += rs.getInt("count"); + } + rs.close(); + } catch (SQLException ex) { + errorCode = 4; + errorCodeDescription += "Internal server error, fetch. "; + ex.printStackTrace(); + logger.info(ex.getMessage()); + } + } + } catch (SQLException ex) { + errorCode = 5; + errorCodeDescription += "Internal server error, query. "; + ex.printStackTrace(); + logger.info(ex.getMessage()); + } finally { + if (rs != null) try { rs.close(); } catch (SQLException ex) {} + if (stmt != null) try { stmt.close(); } catch (SQLException ex) {} + if (conn != null) try { conn.close(); } catch (SQLException ex) {} + } + + if (errorCode != 0) { + JSONObject obj = new JSONObject(); + obj.put("errorCode", errorCode); + obj.put("errorCodeDescription", errorCodeDescription); + return obj.toString(); + } else { + result.put("days", days); + result.put("total", total); + return result.toString(); + } + } + @Override public void setServletContext(ServletContext servletContext) { this.context=servletContext; diff --git a/src/main/resources/static/resources/engine/index.js b/src/main/resources/static/resources/engine/index.js index 6181c65..5e301dc 100644 --- a/src/main/resources/static/resources/engine/index.js +++ b/src/main/resources/static/resources/engine/index.js @@ -1017,6 +1017,214 @@ function showReportTabletsStatistics() rec.callData("ReportTabletsStatistics",settings); } +function showReportImportStatistics() +{ + let uid = getUID(); + let win = new TWin(); + win.BuildGUI(100, 100); + win.setCaption(trt('Import_statistics')); + win.setSize("750px", "500px"); + win.setCenter(); + + let d = new Date(); + let dateEnd = d.getFullYear() + '-' + ('0'+(d.getMonth()+1)).slice(-2) + '-' + ('0'+d.getDate()).slice(-2); + let dateStart = d.getFullYear() + '-01-01'; + + let html = ''; + html += '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += '
'; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += ''; + html += '
' + trt('Country') + ':' + trt('From_date') + ':'; + html += ''; + html += ''; + html += '
' + trt('To_date') + ':'; + html += ''; + html += ''; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
'; + html += '
 
'; + html += '
'; + html += '
'; + + win.setContent(html); + + new Calendar({ + inputField: document.getElementById('importStat_dateStart_' + uid), + dateFormat: "%Y-%m-%d", + trigger: document.getElementById('importStat_dateStart_trigger_' + uid), + align: "Bl", + bottomBar: false, + onSelect: function(){ this.hide(); } + }); + new Calendar({ + inputField: document.getElementById('importStat_dateEnd_' + uid), + dateFormat: "%Y-%m-%d", + trigger: document.getElementById('importStat_dateEnd_trigger_' + uid), + align: "Bl", + bottomBar: false, + onSelect: function(){ this.hide(); } + }); + + let chartInstance = null; + let btn = document.getElementById('importStat_btn_' + uid); + let chartWrap = document.getElementById('importStat_chartWrap_' + uid); + + win.addResizeListener(function() { + if(chartInstance !== null && chartWrap != null) { + chartInstance.canvas.parentNode.style.width = chartWrap.clientWidth + 'px'; + chartInstance.canvas.parentNode.style.height = chartWrap.clientHeight + 'px'; + chartInstance.resize(); + } + }); + + function loadImportStatData() + { + let country = document.getElementById('importStat_country_' + uid).value; + let dateBegin = document.getElementById('importStat_dateStart_' + uid).value.trim(); + let dateEndVal = document.getElementById('importStat_dateEnd_' + uid).value.trim(); + + if(!dateBegin || !dateEndVal) { + alert(trt('Enter_date_range')); + return; + } + + win.showProgressBar(); + + let params = new URLSearchParams({ country: country, dateBegin: dateBegin, dateEnd: dateEndVal }); + fetch('/api/locust/v01/integration/days-statistics?' + params.toString()) + .then(function(response) { + if(!response.ok) throw new Error('HTTP ' + response.status); + return response.json(); + }) + .then(function(data) + { + win.hideProgressBar(); + + if(data.errorCode) { + alert(data.errorCodeDescription); + return; + } + + let labels = []; + let counts = []; + let total = 0; + for(let i = 0; i < data.days.length; i++) { + labels.push(data.days[i].date); + counts.push(data.days[i].count); + total += data.days[i].count; + } + + let canvas = document.getElementById('importStat_chart_' + uid); + let ctx = canvas.getContext('2d'); + + if(chartInstance !== null) { + chartInstance.destroy(); + chartInstance = null; + } + + let barColor; + if(country === 'kz') barColor = '#00a2ff'; + else if(country === 'ru') barColor = '#3366CC'; + else barColor = '#009688'; + + let bgPlugin = { + id: 'whiteBg', + beforeDraw: function(chart) { + let c = chart.ctx; + c.save(); + c.fillStyle = '#ffffff'; + c.fillRect(0, 0, chart.width, chart.height); + c.restore(); + } + }; + + chartInstance = new Chart(ctx, { + type: 'bar', + data: { + labels: labels, + datasets: [{ + label: trt('Imported_forms'), + data: counts, + backgroundColor: barColor, + borderColor: barColor, + borderWidth: 1 + }] + }, + plugins: [bgPlugin], + options: { + responsive: true, + maintainAspectRatio: false, + scales: { + x: { + ticks: { + font: { size: 10 }, + maxRotation: 90, + minRotation: 45 + } + }, + y: { + beginAtZero: true, + ticks: { + font: { size: 11 }, + stepSize: 1 + } + } + }, + plugins: { + legend: { display: false }, + tooltip: { + callbacks: { + label: function(context) { + return context.parsed.y; + } + } + } + } + } + }); + + let wrapper = canvas.parentNode; + wrapper.style.position = 'absolute'; + wrapper.style.top = '0'; + wrapper.style.left = '0'; + wrapper.style.width = chartWrap.clientWidth + 'px'; + wrapper.style.height = chartWrap.clientHeight + 'px'; + + let totalDiv = document.getElementById('importStat_total_' + uid); + totalDiv.innerHTML = trt('Total') + ': ' + total; + }) + .catch(function() + { + win.hideProgressBar(); + alert(trt('Error_loading_data')); + }); + } + + btn.onclick = loadImportStatData; + loadImportStatData(); +} + //Green style (norm) diff --git a/src/main/resources/templates/engine/index.html b/src/main/resources/templates/engine/index.html index bf5f256..e8a54ac 100644 --- a/src/main/resources/templates/engine/index.html +++ b/src/main/resources/templates/engine/index.html @@ -39,8 +39,9 @@ + - +