package com.qcadoo.mes.basic.controllers.dataProvider;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.qcadoo.mes.basic.controllers.dataProvider.dto.AbstractDTO;
import com.qcadoo.mes.basic.controllers.dataProvider.dto.AdditionalCodeDTO;
import com.qcadoo.mes.basic.controllers.dataProvider.dto.PalletNumberDTO;
import com.qcadoo.mes.basic.controllers.dataProvider.dto.ProductDTO;
import com.qcadoo.mes.basic.controllers.dataProvider.responses.DataResponse;
import com.qcadoo.model.api.DictionaryService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.namedparam.MapSqlParameterSource;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
import org.springframework.stereotype.Service;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Service
public class DataProvider {
@Autowired
private NamedParameterJdbcTemplate jdbcTemplate;
@Autowired
private DictionaryService dictionaryService;
private static final int MAX_RESULTS = 20;
private String prepareProductsQuery() {
return "SELECT product.id as id, product.number as code, product.number as number, product.name as name "
+ "FROM basic_product product WHERE product.active = true and product.number ilike :query ;";
}
private String prepareProductsQueryWithLimit(int limit) {
return "SELECT product.id as id, product.number as code, product.number as number, product.name as name "
+ "FROM basic_product product WHERE product.active = true and product.number ilike :query LIMIT " + limit + ";";
}
private String prepareAdditionalCodeQuery(String productnumber) {
String productNumberCondition = Strings.isNullOrEmpty(productnumber) ? "" : "and product.number = '" + productnumber + "'";
return "SELECT additionalcode.id as id, additionalcode.code as code, product.number as productnumber "
+ "FROM basic_additionalcode additionalcode "
+ "JOIN basic_product product ON (additionalcode.product_id = product.id " + productNumberCondition + ")"
+ "WHERE additionalcode.code ilike :query;";
}
private String prepareAdditionalCodeQueryWithLimit(int limit) {
return "SELECT additionalcode.id as id, additionalcode.code as code, product.number as productnumber "
+ "FROM basic_additionalcode additionalcode "
+ "JOIN basic_product product ON (additionalcode.product_id = product.id and (product.number = :productnumber OR COALESCE(:productnumber,'')='' ))"
+ "WHERE additionalcode.code ilike :query LIMIT " + limit + ";";
}
private String preparePalletNumbersQuery() {
return "SELECT palletnumber.id as id, palletnumber.number as code, palletnumber.number as number "
+ "FROM basic_palletnumber palletnumber WHERE palletnumber.active = true and palletnumber.number ilike :query;";
}
private String preparePalletNumbersQueryWithLimit(int limit) {
return "SELECT palletnumber.id as id, palletnumber.number as code, palletnumber.number as number "
+ "FROM basic_palletnumber palletnumber WHERE palletnumber.active = true and palletnumber.number ilike :query LIMIT "
+ limit + ";";
}
private int countQueryResults(String preparedQuery, String query, Map<String, Object> paramMap) {
String countQuery = "SELECT count(*) as cnt FROM (" + preparedQuery.replace(";", "") + ") sq;";
paramMap.put("query", "%" + query + "%");
return jdbcTemplate.queryForObject(countQuery, paramMap, Integer.class);
}
public DataResponse getProductsResponseByQuery(String query) {
return getDataResponse(query, prepareProductsQuery(), getProductsByQuery(query), new HashMap<String, Object>());
}
public DataResponse getAdditionalCodesResponseByQuery(String query, String productnumber) {
return getDataResponse(query, prepareAdditionalCodeQuery(productnumber), getAdditionalCodesByQuery(query, productnumber),
new HashMap<String, Object>());
}
public DataResponse getPalletNumbersResponseByQuery(String query) {
return getDataResponse(query, preparePalletNumbersQuery(), getPalletNumbersByQuery(query), new HashMap<String, Object>());
}
public DataResponse getDataResponse(String query, String preparedQuery, List<AbstractDTO> entities,
Map<String, Object> paramMap) {
int numberOfResults = countQueryResults(preparedQuery, query, paramMap);
if (numberOfResults > MAX_RESULTS) {
return new DataResponse(Lists.newArrayList(), numberOfResults);
}
return new DataResponse(entities, numberOfResults);
}
public List<ProductDTO> getAllProducts(String sidx, String sord) {
// TODO sort
String _query = "SELECT product.id, product.number as code, product.number, product.name, product.ean, product.globaltypeofmaterial, product.category "
+ "FROM basic_product product WHERE product.active = true;";
List<ProductDTO> products = jdbcTemplate.query(_query, new MapSqlParameterSource(Collections.EMPTY_MAP),
new BeanPropertyRowMapper(ProductDTO.class));
return products;
}
public List<AbstractDTO> getProductsByQuery(String query) {
String _query = prepareProductsQueryWithLimit(MAX_RESULTS);
Map<String, Object> parameters = new HashMap<>();
parameters.put("query", "%" + query + "%");
SqlParameterSource nParameters = new MapSqlParameterSource(parameters);
List<AbstractDTO> products = jdbcTemplate.query(_query, nParameters, new BeanPropertyRowMapper(ProductDTO.class));
return products;
}
public List<AdditionalCodeDTO> getAllAdditionalCodes(String sidx, String sord) {
// TODO sort
String _query = "SELECT additionalcode.id as id, additionalcode.code as code, product.number as productnumber "
+ "FROM basic_additionalcode additionalcode "
+ "JOIN basic_product product ON (additionalcode.product_id = product.id);";
List<AdditionalCodeDTO> codes = jdbcTemplate.query(_query, new MapSqlParameterSource(Collections.EMPTY_MAP),
new BeanPropertyRowMapper(AdditionalCodeDTO.class));
return codes;
}
public List<AbstractDTO> getAdditionalCodesByQuery(String query, String productnumber) {
String _query = prepareAdditionalCodeQueryWithLimit(MAX_RESULTS);
Map<String, Object> parameters = new HashMap<>();
parameters.put("query", "%" + query + "%");
parameters.put("productnumber", productnumber);
SqlParameterSource nParameters = new MapSqlParameterSource(parameters);
List<AbstractDTO> codes = jdbcTemplate.query(_query, nParameters, new BeanPropertyRowMapper(AdditionalCodeDTO.class));
return codes;
}
public List<PalletNumberDTO> getAllPalletNumbers(String sidx, String sord) {
String _query = "SELECT palletnumber.id as id, palletnumber.number as code, palletnumber.number as number "
+ "FROM basic_palletnumber palletnumber WHERE palletnumber.active = true;";
List<PalletNumberDTO> pallets = jdbcTemplate.query(_query, new MapSqlParameterSource(Collections.EMPTY_MAP),
new BeanPropertyRowMapper(PalletNumberDTO.class));
return pallets;
}
public List<AbstractDTO> getPalletNumbersByQuery(String query) {
String _query = preparePalletNumbersQueryWithLimit(MAX_RESULTS);
Map<String, Object> parameters = new HashMap<>();
parameters.put("query", "%" + query + "%");
SqlParameterSource nParameters = new MapSqlParameterSource(parameters);
List<AbstractDTO> pallets = jdbcTemplate.query(_query, nParameters, new BeanPropertyRowMapper(PalletNumberDTO.class));
return pallets;
}
public List<Map<String, String>> getUnits() {
return dictionaryService.getKeys("units").stream().map(unit -> {
Map<String, String> type = new HashMap<>();
type.put("value", unit);
type.put("key", unit);
return type;
}).collect(Collectors.toList());
}
public List<Map<String, String>> getTypeOfPallets() {
return dictionaryService.getKeys("typeOfPallet").stream().map(unit -> {
Map<String, String> type = new HashMap<>();
type.put("value", unit);
type.put("key", unit);
return type;
}).collect(Collectors.toList());
}
}