Compare commits

...

3 Commits

Author SHA1 Message Date
Igor I 291b465d89 Chart, count export in day 2026-07-15 17:35:46 +05:00
Igor I 86e570ca61 Add Locust types 2026-06-09 19:00:12 +05:00
Igor I 4b3dc84500 Fix Exception 2026-06-09 08:12:10 +05:00
6 changed files with 314 additions and 13 deletions
@@ -2526,7 +2526,7 @@ public class AcceptASDCController implements ServletContextAware {
response.setContentType("application/xml");
return result;
}
//Connect to database
Connection conn = null;
try {
+15 -9
View File
@@ -154,7 +154,7 @@ public class AcceptJSON implements ServletContextAware {
}
}
if(lastDate==null) {
lastDate = LocalDate.parse("2025-07-16");
lastDate = LocalDate.parse("2026-01-01");
}
//By number of day downloading data and write result of downloading to database, try or false, after repair need repeat download
@@ -428,7 +428,8 @@ public class AcceptJSON implements ServletContextAware {
}
//---------------------------------------------------------------------------
/**
* Пример запроса: http://127.0.0.1:8081/AcceptJSON но в теле нужно поменять строку "Year y = Year.of(2024);" а также номер дня
* Пример запроса: https://127.0.0.1:8081/AcceptJSON но в теле нужно поменять строку "Year y = Year.of(2024);" а также номер дня
* By document: "API фитомониторинг ФАО (1.3).docx"
* @param user
* @param model
* @param file
@@ -513,6 +514,10 @@ public class AcceptJSON implements ServletContextAware {
for (Object o : jsonArray) {
JSONObject jsonObj = (JSONObject) o;
FrmLocustModel locust = new FrmLocustModel();
//locust.seq = obj.getLong("seq")*1000;
locust.country_id = "7"; //Russia
locust.country_uid = "d8509c7a-6d50-480c-bc2f-d3568c86059b"; //Russia
locust.company_uid = "2925b0a4-2bc5-4083-b3f1-9fddd909289e"; //ФГБУ "Россельхозцентр"
try{
@@ -1194,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) {
@@ -1220,7 +1226,7 @@ public class AcceptJSON implements ServletContextAware {
}
}
if(lastDate==null)
lastDate = LocalDate.parse("2025-02-11");
lastDate = LocalDate.parse("2026-01-01");
//By number of day downloading data and write result of downloading to database, try or false, after repair need repeat download
while(lastDate.isBefore(LocalDate.now().minusDays(3))){
@@ -1335,7 +1341,7 @@ public class AcceptJSON implements ServletContextAware {
result.uid = obj.getString("uuid");
result.eid = String.valueOf(obj.getInt("id")); //Internal identifier in the Uzbek database
result.seq = obj.getLong("seq")*1000;
//result.seq = obj.getLong("seq")*1000;
result.country_id = "10"; //Uzbekistan
result.country_uid = "05592f5a-1c8b-4d87-a47f-67697cc12c49"; //Uzbekistan
@@ -1579,7 +1585,7 @@ public class AcceptJSON implements ServletContextAware {
result.locust_type_id = "2";
result.locust_type_uid = "8dd9e74f-d7ba-492a-8c75-7aed4f0847c6";
break;
case "LMI - Asian migratory locust", "LMI - азиатская перелетная саранча", "Азиаткая саранча":
case "LMI - Asian migratory locust", "LMI - азиатская перелетная саранча", "Азиаткая саранча", "Азиатская саранча", "Мароккская саранча, Азиатская саранча":
result.locust_type_id = "3";
result.locust_type_uid = "d61a5325-e8c7-497a-9cff-7ee4c4e1e37d";
break;
@@ -1591,7 +1597,7 @@ public class AcceptJSON implements ServletContextAware {
result.locust_type_id = "6";
result.locust_type_uid = "4effd7bb-f19e-4a98-a724-691da12c163e";
break;
case "Other", "Другое", "Другие саранчовые", "Другие саранчовые, Пустынная саранча", "Другие саранчовые, Атбасарка, Кузнечики", "Большая саксаульная горбатка, Мароккская саранча", "Большая саксаульная горбатка, Туранский прус", "Другие саранчовые, Туранский прус", "Пустынная саранча, Итальянский прус", "Кузнечики", "Другие саранчовые, Атбасарка", "Другие саранчовые, Итальянский прус", "Другие саранчовые, Мароккская саранча", "Большая саксаульная горбатка", "Пустынная саранча", "Атбасарка", "Туранский прус", "Другие саранчовые, Большая саксаульная горбатка", "Другие саранчовые, Итальянский прус, Мароккская саранча", "Другие саранчовые, Кузнечики", "Другие саранчовые, Итальянский прус, Кузнечики", "Другие саранчовые, Мароккская саранча, Атбасарка", "Другие саранчовые, Мароккская саранча, Азиаткая саранча":
case "Other", "Другое", "Другие саранчовые", "Другие саранчовые, Пустынная саранча", "Другие саранчовые, Атбасарка, Кузнечики", "Большая саксаульная горбатка, Мароккская саранча", "Большая саксаульная горбатка, Туранский прус", "Другие саранчовые, Туранский прус", "Пустынная саранча, Итальянский прус", "Кузнечики", "Другие саранчовые, Атбасарка", "Другие саранчовые, Итальянский прус", "Другие саранчовые, Мароккская саранча", "Большая саксаульная горбатка", "Пустынная саранча", "Атбасарка", "Туранский прус", "Другие саранчовые, Большая саксаульная горбатка", "Другие саранчовые, Итальянский прус, Мароккская саранча", "Другие саранчовые, Кузнечики", "Другие саранчовые, Итальянский прус, Кузнечики", "Другие саранчовые, Мароккская саранча, Атбасарка", "Другие саранчовые, Мароккская саранча, Азиаткая саранча", "Другие саранчовые, Пустынная саранча, Итальянский" :
result.locust_type_id = "4";
result.locust_type_uid = "bf79cae1-1e01-4e7f-8ec1-deb06936a58e";
break;
@@ -1688,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;
@@ -1733,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;
@@ -1785,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;
@@ -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;
@@ -125,9 +125,9 @@ public class EngineController implements ServletContextAware {
List<String> ret = jdbcTemplate.query(sql, parameters, new DBTools.JsonRowMapper());
for (int i = 0; i < ret.size(); i++) {
JSONObject obj = new JSONObject(ret.get(i));
country_id=obj.getLong("country_id");
country_id=obj.getLong("country_id"); //TODO Проверить должно по идее country_uid везде использоваться...
}
} catch( DataAccessException ex )
} catch( Exception ex )
{
logger.error(ex.getMessage());
}
@@ -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 += '<div style="width:100%; height:100%; position:relative; font-size:12px;">';
html += '<table style="width:100%; height:100%;">';
html += '<tr><td style="padding:2px;">';
html += '<table style="width:100%; border-collapse:collapse;">';
html += '<tr>';
html += '<td style="padding:2px; white-space:nowrap;">' + trt('Country') + ':</td>';
html += '<td style="padding:2px;"><select id="importStat_country_' + uid + '" style="width:100%;">';
html += '<option value="kz">Kazakhstan</option>';
html += '<option value="ru">Russia</option>';
html += '<option value="uz">Uzbekistan</option>';
html += '</select></td>';
html += '<td style="padding:2px; white-space:nowrap;">' + trt('From_date') + ':</td>';
html += '<td style="padding:2px;"><table style="border-spacing:0; border-collapse:collapse;"><tr>';
html += '<td><input id="importStat_dateStart_' + uid + '" type="text" style="width:100%;" value="' + dateStart + '"/></td>';
html += '<td style="width:25px;"><img id="importStat_dateStart_trigger_' + uid + '" src="../resources/engine/images/datepicker.jpg" style="margin-left:1px; cursor:pointer;"/></td>';
html += '</tr></table></td>';
html += '<td style="padding:2px; white-space:nowrap;">' + trt('To_date') + ':</td>';
html += '<td style="padding:2px;"><table style="border-spacing:0; border-collapse:collapse;"><tr>';
html += '<td><input id="importStat_dateEnd_' + uid + '" type="text" style="width:100%;" value="' + dateEnd + '"/></td>';
html += '<td style="width:25px;"><img id="importStat_dateEnd_trigger_' + uid + '" src="../resources/engine/images/datepicker.jpg" style="margin-left:1px; cursor:pointer;"/></td>';
html += '</tr></table></td>';
html += '<td style="padding:2px;"><input type="button" class="main" value="' + trt('Show') + '" id="importStat_btn_' + uid + '"/></td>';
html += '</tr>';
html += '</table>';
html += '</td></tr>';
html += '<tr style="height:100%;"><td style="vertical-align:top; overflow:hidden;">';
html += '<div id="importStat_chartWrap_' + uid + '" style="position:relative; width:100%; height:100%;">';
html += '<div id="importStat_chartInner_' + uid + '" style="position:absolute; top:0; left:0; width:100%; height:100%;"><canvas id="importStat_chart_' + uid + '"></canvas></div>';
html += '</div>';
html += '</td></tr>';
html += '<tr><td style="padding:2px;">';
html += '<div id="importStat_total_' + uid + '" style="font-weight:bold; font-size:13px; text-align:right;">&nbsp;</div>';
html += '</td></tr>';
html += '</table>';
html += '</div>';
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)
@@ -39,8 +39,9 @@
<script type="text/javascript" src="../resources/metadata/dbms/log.js?v=16"></script>
<script type="text/javascript" src="../resources/metadata/tree/tree.js?v=16"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js@4.4.0/dist/chart.umd.min.js"></script>
<script type="text/javascript" src="../resources/engine/popup.js?v=16"></script>
<script type="text/javascript" src="../resources/engine/index.js?v=25"></script>
<script type="text/javascript" src="../resources/engine/index.js?v=26"></script>
<script type="text/javascript" src="../resources/engine/user.js?v=18"></script>
<style>
@@ -1437,6 +1438,7 @@ new Calendar({
<button class="main" style="width:100%;margin-top:1px;" onclick="showReportCountries();" th:text="${Filling_forms_by_countries}">Filling_forms_by_countries</button>
<button class="main" style="width:100%;margin-top:1px;" onclick="showReportInspectors();" th:text="${Completed_forms_by_tablets}">Completed_forms_by_tablets</button>
<button class="main" style="width:100%;margin-top:1px;" onclick="showReportTabletsStatistics();" th:text="${Tablet_statistics}">Tablet_statistics</button>
<button class="main" style="width:100%;margin-top:1px;" onclick="showReportImportStatistics();" th:text="${Import_statistics}">Import_statistics</button>
<div id="lblDevices" th:text="${Devices}">Devices</div>
<button id="btnTerminalsShow" class="main" style="width:100%;margin-top:1px;" onclick="showDataWindow('Terminals')" th:text="${The_tablets}">The_tablets</button>