terça-feira, 21 de setembro de 2010

Cigam X Gertec Busca Preço

O "busca preço" da Gertec é um aparelho super útil em lojas que usam o sistema Self-Service como supermercados ou afins. A versão com WiFi permite que se coloque em qualquer lugar que tenha um ponto de rede elétrica.

Para as empresas que usam CIGAM a integração já esta pronta, é o que vou mostrar nesse post.

O aparelho custa em média R$ 800,00. A licença do software é por conexão, ou seja, por ponto de consulta.

domingo, 19 de setembro de 2010

Classe Utilitaria para Sistema Operacional

package funcoes.util;

import java.awt.Dimension;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

public class SistemaOperacional {

public static String getNome() {
String nome = System.getProperty("os.name").toUpperCase();
if (nome.contains(" ")) {
nome = nome.substring(0, nome.indexOf(" "));
}
return nome;
}

public static String getPais() {
return System.getProperty("user.country").toUpperCase();
}

public static String getBarraDiretorios() {
String barra = "/";
if (SistemaOperacional.getNome().equals("LINUX")) {
barra = "/";
} else if ((SistemaOperacional.getNome().equals("WINDOWS"))) {
barra = "\\";
}
return barra;
}

/**
*
* @param data exemplo 01/01/01
*/
public static void mudarDataSistema(String data) {
Date newDate = new Date(data);
SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
String cmd = "cmd /C date " + sdf.format(newDate);
executarComando(cmd);
}

public static void executarComando(String comando) {
try {
Process proc = Runtime.getRuntime().exec(comando);
} catch (IOException ex) {
Logger.getLogger(Windows.class.getName()).log(Level.SEVERE, null, ex);
}
}

public static String getDiretorioAtual() {
return System.getProperty("user.dir").toUpperCase();
}

public static String getVersao() {
return System.getProperty("os.version").toUpperCase();
}

public static String getDiretorioUsuario() {
return System.getProperty("user.home").toUpperCase();
}

public static String getNomeUsuario() {
return System.getProperty("user.home").toUpperCase();
}

public static String getLinguagem() {
return System.getProperty("user.language").toUpperCase();
}

public static String getCpu() {
return System.getProperty("sun.cpu.isalist").toUpperCase();
}

/**
*
* @param hora exemplo 08:30:30
*/
public static void mudarHoraSistema(String hora) {
Date newDate = new Date("01/01/01 " + hora);
SimpleDateFormat sdf = new SimpleDateFormat("hh:mm:ss");
String cmd = "cmd /C time " + sdf.format(newDate);
executarComando(cmd);
}

public static Dimension getResolucao() {
java.awt.Toolkit toolkit = java.awt.Toolkit.getDefaultToolkit();
return toolkit.getScreenSize();
}
}

quinta-feira, 16 de setembro de 2010

HashMap para j2me

package j2meuteis;

public class HashMap {

//crie a classe ArrayList para J2ME tambem postada no blog
private ArrayList keys;
private ArrayList values;

public HashMap() {
keys = new ArrayList();
values = new ArrayList();
}

public void put(Object key, Object value) {
getKeys().add(key);
getValues().add(value);
}

public Object get(Object key) {
for (int i = 0; i < getKeys().size(); i++) {
if (key == getKeys().get(i)) {
return getValues().get(i);
}
}
return null;
}

public ArrayList getKeys() {
return keys;
}

public ArrayList getValues() {
return values;
}

public int size() {
return getKeys().size();
}
}

ArrayList para j2me

Uma grande descepcao pra quem comeca a desenvolver em J2ME, e nao poder contar com a clase arrayList.
Para resolver esse problema, so criando na mao.
Eis a classe:

package j2meuteis;

public class ArrayList {
private Object[] storedObjects;
private int growthFactor;
private int size;

public ArrayList() {
this( 10, 75 );
}

public ArrayList( int initialCapacity ) {
this( initialCapacity, 75 );
}

public ArrayList( int initialCapacity, int growthFactor ) {
this.storedObjects = new Object[ initialCapacity ];
this.growthFactor = growthFactor;
}

public int size() {
return this.size;
}

public boolean contains( Object element ) {

if (element == null) {
throw new IllegalArgumentException( "ArrayList cannot contain a null element.");
}
for (int i = 0; i < object =" this.storedObjects[i];" element ="="" i =" 0;" object =" this.storedObjects[i];">= this.size ) {
throw new IndexOutOfBoundsException("the index [" + index + "] is not valid for this list with the size [" + this.size + "].");
}
return this.storedObjects[ index ];
}

public Object remove( int index ) {
if (index <>= this.size ) {
throw new IndexOutOfBoundsException("the index [" + index + "] is not valid for this list with the size [" + this.size + "].");
}
Object removed = this.storedObjects[ index ];
for (int i = index+1; i < element ="="" index =" -1;" i =" 0;" object =" this.storedObjects[i];" index =" i;" index ="="" i =" index+1;" i =" 0;" size =" 0;" element ="="">= this.storedObjects.length) {
increaseCapacity();
}
this.storedObjects[ this.size ] = element;
this.size++;
}

public void add( int index, Object element ) {
if (element == null) {
throw new IllegalArgumentException( "ArrayList cannot contain null.");
}
if (index <> this.size ) {
throw new IndexOutOfBoundsException("the index [" + index + "] is not valid for this list with the size [" + this.size + "].");
}
if (this.size >= this.storedObjects.length) {
increaseCapacity();
}
// shift all following elements one position to the back:
for (int i = this.size; i > index; i--) {
this.storedObjects[i] = this.storedObjects[ i-1 ];
}
// insert the given element:
this.storedObjects[ index ] = element;
this.size++;
}

public Object set( int index, Object element ) {
if (index <>= this.size ) {
throw new IndexOutOfBoundsException("the index [" + index + "] is not valid for this list with the size [" + this.size + "].");
}
Object replaced = this.storedObjects[ index ];
this.storedObjects[ index ] = element;
return replaced;
}

public String toString() {
StringBuffer buffer = new StringBuffer( this.size * 23 );
buffer.append( super.toString() ).append( "{\n" );
for (int i = 0; i < this.size; i++) {
buffer.append( this.storedObjects[i] );
buffer.append('\n');
}
buffer.append('}');
return buffer.toString();
}

public Object[] toArray() {
Object[] copy = new Object[ this.size ];
System.arraycopy( this.storedObjects, 0, copy, 0, this.size );
return copy;
}

public Object[] toArray( Object[] target ) {
System.arraycopy( this.storedObjects, 0, target, 0, this.size );
return target;
}

public void trimToSize() {
if (this.storedObjects.length != this.size ) {
Object[] newStore = new Object[ this.size ];
System.arraycopy( this.storedObjects, 0, newStore, 0, this.size );
this.storedObjects = newStore;
}
}

private void increaseCapacity() {
int currentCapacity = this.storedObjects.length;
int newCapacity = currentCapacity + ((currentCapacity * this.growthFactor) / 100);
if (newCapacity == currentCapacity ) {
newCapacity++;
}
Object[] newStore = new Object[ newCapacity ];
System.arraycopy( this.storedObjects, 0, newStore, 0, this.size );
this.storedObjects = newStore;
}

public Object[] getInternalArray() {
return this.storedObjects;
}
}

Classe Utilitaria para trabalhar com diretorios

package funcoes.util;

import java.io.File;
import java.io.IOException;

public abstract class Diretorios {

public static void main(String[] args) {
criar("c:\\testeNovoDir");
}

public static void criar(String caminho) {
File file = new File(caminho);
file.mkdir();
}

public static void excluir(String caminho) {
File file = new File(caminho);
file.delete();
}

public static boolean existe(String caminho) {
File file = new File(caminho);
return file.exists();
}

public static void deletar(String caminho) {
File dir = new File(caminho);
deletar(dir);
}

public static boolean deletar(File dir) {
File candir;
try {
candir = dir.getCanonicalFile();
} catch (IOException e) {
return false;
}

if (!candir.equals(dir.getAbsoluteFile())) {
return false;
}


File[] files = candir.listFiles();
if (files != null) {
for (int i = 0; i < files.length; i++) {
File file = files[i];

boolean deleted = file.delete();
if (!deleted) {

if (file.isDirectory()) {
deletar(file);
}

}
}
}

return dir.delete();
}
}

Classe Utilitaria para trabalhar com numeros

package funcoes.util;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import javax.swing.JOptionPane;

public class Numeros {
private int incrementado;


/**
* Corta o numero de casas decimais indicados
* @param numero numero com os quebrados
* @param casasDecimais numero de casas que devem ser retornadas depois da virgula
* @return retorna um double com o numero de casas escolhido.
*/
public static double ignoraCasasDecimais(double numero, int casasDecimais) {
String quebrados = String.valueOf(numero);
String inteiros = quebrados.substring(0, quebrados.indexOf("."));
quebrados = quebrados.substring(quebrados.indexOf(".") + 1, quebrados.length());
String temp = "";

if (quebrados.length() >= casasDecimais) {
casasDecimais -= 1;

for (int i = 0; i <= casasDecimais; i++) { temp += quebrados.charAt(i); } } else { temp = quebrados; } return Double.parseDouble(inteiros + "." + temp); } /** * * @param valor1 valor 100% * @param valor2 porcentagem a ser descontada * @return valor1 menos valor2% */ public static double descontaPorcentagem(double valor1, double valor2) { return valor1 - (getValorDePorcentagem(valor1, valor2)); } /** * * @param valor1 valor 100% * @param valor2 o % * @return Retorna o valor da porcentagem */ public static double getValorDePorcentagem(double valor1, double valor2) { return (valor1 / 100) * valor2; } /** * * @param valor1 valor principal 100% * @param valor2 valor que vc quer saber o % do valor principal * @return double com o % */ public static double getPorcentagem(double valor1, double valor2) { return valor2 / (valor1 / 100); } /** * Valida uma string em número inteiro * @param inteiro string contendo um valor inteiro * @return uma string com o msmo valor se true, e 0 caso false */ public static String validaInteiro(String inteiro) { try { Integer.parseInt(inteiro); return inteiro; } catch (Exception e) { JOptionPane.showMessageDialog(null, "Insira somente valores inteiros"); return "0"; } } /** * retorna o numero de casas decimais de um numero * @param numero * @return */ public static int getNumerosCasasDecimais(double numero) { String temp = String.valueOf(numero); String[] temp2 = temp.split("[.]"); return temp2[1].length(); } /** * retorna uma string com as casas decimais do numero * @param numero numero quebrado * @return */ public static String getCasasDecimais(Double numero) { String[] strNumero = String.valueOf(numero).split("[.]"); return strNumero[1]; } public static double truncaCasasDecimais(double numero) { if (getNumerosCasasDecimais(numero) > 2) {
String num = getCasasDecimais(numero);
if (Integer.parseInt(num.substring(2, 3)) >= 1) {
numero = Numeros.arredondaPraCima(2, numero);
}
}
return numero;
}

/**
* valida uma string em um double
* @param Doubl string contendo um valor double (0.0), se na sring conter uma "," essa função transforma em "."
* @return uma string com o mesmo valor caso true, e 0 caso false;
*/
public static String validaDouble(String Doubl) {
try {
Doubl = Strings.substituirTrechos(new String[]{","}, ".", Doubl);
Double.parseDouble(Doubl);
return Doubl;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Insira somente valores numericos");
return "0";
}
}

/**
* valida uma string em Float
* @param Floa string contendo um valor float
* @return uma string com o memso valor caso true, ou 0 caso false
*/
public static String validaFloat(String Floa) {
try {
Floa = Strings.substituirTrechos(new String[]{","}, ".", Floa);
Float.parseFloat(Floa);
return Floa;
} catch (Exception e) {
JOptionPane.showMessageDialog(null, "Insira somente valores numericos");
return "0";
}
}

/**
*
* @param numero numro a ser transformado
* @param mascara mascara ex:#0,00
* @return string com formato
*/
public static String Formatar(String mascara, double numero) {
DecimalFormat formatador = new DecimalFormat();
formatador.applyPattern(mascara);

String temp = formatador.format(numero);
temp = temp.replaceAll(",", ".");
return temp;
}

/**
* arredonda o numero quebrado pra cima
* @param casasDecimais numero de casas que vc deseja que o numero retorne
* @param numero numero que sera formatado
* @return retorna o mesmo numero com a ultima casa decimal arredondada pra cima
*/
public static double arredondaPraCima(int casasDecimais, double numero) {
//VERIFICANDO SE PRECISA ARREDONDAR
String num = String.valueOf(numero);
num = num.substring(num.indexOf('.') + 1, num.length()) + "0000000000000000000000";

num = num.substring(casasDecimais, casasDecimais + 3);

if (Double.parseDouble(num) == 0) {//AUMENTAR
return numero;
}

BigDecimal bd = new BigDecimal(numero);
bd = bd.setScale(casasDecimais, BigDecimal.ROUND_UP);
return bd.doubleValue();
}

public static double arredonda(String mascara, double numero) {
DecimalFormat formatador = new DecimalFormat();
formatador.applyPattern(mascara);

String temp = formatador.format(numero);
temp = temp.replaceAll(",", ".");
return Double.parseDouble(temp);
}

/**
* entra um double sai um integer
* @param numero
* @return
*/
public static int doubleToInteger(double numero) {
int i = (int) numero;
return i;
}

public static String doubleToString(double numero) {
return Formatar("#", numero);
}

public static String doubleToIntegerToString(double numero) {
int i = (int) numero;
return String.valueOf(i);
}

public static double IntegerToDouble(int numero) {
return Double.parseDouble(String.valueOf(numero));
}

/**
* entra um float sai Double
* @param numero
* @return
*/
public static Double floatToDouble(float numero) {
Double d = new Double(String.valueOf(numero));
return d;
}

public int getIncrementado() {
return incrementado++;
}

public void setIncrementado(int aIncrementado) {
incrementado = aIncrementado;
}
}

quarta-feira, 15 de setembro de 2010

ERP CIGAM + MetaSystem

Bom, já a algum tempo desenvolvo aplicativos integrados com o ERP CIGAM. Agora em acordo com a DESERVE, um dos PARCEIROS do ERP, esta surgindo a possibilidade de distribuir essas soluções ao demais clientes.
Daqui pra frente, vou postar uma série de textos e vídeos falando de alguns módulos que tenho a oferecer. Caso venham a se interessar, procurem um representante CIGAM mais próximo e pergunte sobre o que leu aqui.
Vou começar falando do sistema num geral. Esse se chama MetaSystem, e assim é porque é uma estrutura toda interfaceada, montada pra operar "em cima" de qualquer ERP. A tecnologia empregada é basicamente JAVA e quase todas as suas plataformas:

- J2ME:Módulos móveis, celular e coletor de dados.
- J2EE:Módulos Web
- J2SE:Módulos Desktop

Os módulos trabalham em cima de uma única galeria de classes(J2SE) que fazem as validações e integrações com o banco de dados. Os bancos de dados suportados são quase todos(SQL), mas o CIGAM, que eu sei só roda ORACLE, SQLSERVER.

As opniões vão variar sobre oque esses módulos acrescentam ou não no ERP. Mas sobre isso posso destacar alguns pontos.

- Da mobilidade ao ERP, permitindo interagir online com HandHelps, Celulares, sites, terminais de auto-atendimento, terminais de consulta.
- Diminui o preço das licenças, visto que elimina boa parte das RunTimes que sempre são vendidas embutidas com o CIGAM.




- RODA EM TUDO, esse considero um grande avanço, visto que quem quiser comprar Cigam, não será mais obrigado a gastar com licenças TS "Terminal Server", windows (Server e Client). O sistema esta homologado para: Windows, Linux Ubuntu, MacOs, mas ja fiz rodar em outros SOs tb.
- Apesar de ter de seguir algumas lógicas "defasadas" que o projeto do BD impõe, acho que consegui ganhar bastante em velocidade, aproveitando melhorar os recursos do banco.

Nos próximos posts, estarei detalhando melhor cada módulo.

Cristiano Silveira

sábado, 4 de setembro de 2010

Painel eletrônico multi-midia

Em dezembro de 2009 a empresa na qual eu trabalho como Gerente de TI no turno da manha inaugurou sua nova loja. Nas dependências antigas os clientes pegavam uma ficha de atendimentos e aguardavam o vendedor chamar.

Problema a ser resolvido:
A nova loja seria muito vasta, os vendedores iam secar a "guela" gritando as senhas.

Solução 1:
Orçar um painel eletrônico para chamada de fichas.
Problemas com as soluções que encontrei no mercado.
- Todos usavam controle remoto com dois botões "próximo/anterior", que estragavam, exigiam troca de pilhas, que se limitavam a uma determinada distância do painel.
- Os visores no máximo em leds coloridos com limites de caracteres.
- Limitavam-se a chamada de fichas e ZIp....

Solução adotada:
Mais uma vez botei a mão na massa e veja oque saiu.
- Coloquei uma CPU com placa de vídeo de 1 gb de memoria com uma TV 40" para ser o visor. Rodando um software que exibe vídeos de patrocinadores, promocionais, curiosidades, documentarios inerentes ao ramo da loja.
- Nas estações outro software funcionando como controle conectado a CPU do painel.
- Distribui na loja caixas de som, ligadas a um apmplificador que por sua vez ligado a CPU.
- Contratei uma locutora para contar de 1 até 1000...rs...rs, e as palavras "guichê, ficha".

Benefícios da solução:
- Número de controles infinitos sem pagar 1 centavo a mais e sem consertos ou reposição de pilhas.
- Distância do painel ilimitada visto que funciona via rede e até pela internet.
- Geração de receita mensal pelos patrocinadores que daria pra comprar um painel desses convencionais por mês.
- O cliente alem de ver a ficha no painel também escuta a chamada, em qualquer ponto da loja que estiver, ou seja o cliente pode pegar a ficha e sair caminhar pelas prateleiras e escutar pelos auto-falantes.
- O visual da loja ficou muito mais tecnológico, alguns clientes diziam se sentir um aeroporto rs..rs.
- A garganta dos vendedores agradecem e agora embora com um motivo a menos, ja podem pedir aumento de salário bem afinadinhos rs...rs.

Contato para adquirir a solução: (51)84814667

Silveira

Vejam o vídeo: