Jump to content
Fivewin Brasil

Jorge Andrade

Membros
  • Posts

    843
  • Joined

  • Last visited

  • Days Won

    77

Everything posted by Jorge Andrade

  1. Bela atitude Valdir, melhor a gente realmente ir divulgando. No meu caso, sou meio eclético. Indústria de confecções, varejo de confecções, varejo produtos de limpeza, indústria de pranchas de surf, distribuições de vacinas humanas, e varejo em geral. Sobre os locais de atuação: São Paulo, capital e interior, Belo Horizonte, Goiânia e Salvador.
  2. Aê galera! Tô gostando de ver as manifestações de vcs. Vamos esperar o levantamento das informações pelo Mário Guará do grupo Windev e também do nosso amigo Marcelo (Marca), por ser da região dele, o contato direto com os pais será mais fácil e também com os clientes, que é extremamente necessário pra certificar que eles não estarão desamparados, e haverá continuidade no sistema. Acredito que após essas confirmações e até por ideia de um colega aqui do grupo, alguém assumir de vez e ter participação nos recebimentos, desde de que não prejudique e comprometa demais os ganhos das outras partes (Pais e esposa e filho). Agradeço as boas intenções de todos. []s,
  3. Toda sugestão é bem vinda. O Marcelo deverá contatar o Mário e a família e assim, achar uma solução que atenda bem a família e a quem vai ajudar. []s,
  4. Edú como frisei, se a gente ajudar de alguma forma tecnicamente, e tentar manter os sistemas dele funcionando, acredito que será uma grande ajuda.
  5. Amigo, já te adicionei no skype e aqueles que quiserem participar de alguma forma é só me incluir fnlinf ou fnlinf@hotmail.com. []s,
  6. Dá um retorno aí amigo se deu certo e o caminho das pedras.
  7. Pessoal Boa noite Como vcs sabem, muitos trabalham sozinho e as vezes nem a família tem acesso aos nossos códigos para alguém não dar continuidade ao pequeno legado que deixamos. Não foi diferente para o nosso amigo Alexandre e as vezes a família depende exclusivamente ou boa parte dos recursos oriundos no nosso trabalho. Essa semana no grupo de Windev, tivemos uma notícia que a esposa dele está passando por necessidades e com isso já pensaram em fazer uma força tarefa para ajudar financeiramente. Após o seu falecimento, tentei contato com os pais dele e com a sua esposa sem sucesso, porém, essa semana consegui falar com eles e estes me passaram uma situação complicada, embora sem entrar no âmbito familiar, este me informou que um colega nosso (Mário Guará) do grupo de Windev entrou em contato, esteve na casa deles, onde ele teve acesso as informações relativas aos projetos Windev. Conversei com o Mário que me relatou a situação. Além da dificuldades em contatar os clientes para que ele dê continuidade aos projetos e os pais e a esposa recebam as mensalidades, porém o Mário não tem conhecimento de Fivewin e para tal, irá necessitar da ajuda dos colegas que estiverem interessados em contribuir tecnicamente. Seria interessante se algum colega do grupo que mora no RJ, de preferência em Nova Iguaçu (Onde ele residia), para facilitar contatos ou visitas aos clientes, afim de dar esta força para a família. Vejam que não estou pedindo para ajudar financeiramente e sim dispor da capacidade técnica profissional em ajudar nos projetos relativos a Fivewin. Aqueles que tiverem tempo e desejarem ajudar, manifestem-se []s,
  8. Se entendi, vc loga o TS, mas a tela da área de trabalho não aparece, bom, isso deve ser pq, na última sessão ficou alguma pendência, mas vc pode começar do zero. Independente se vc utilizar Calls para acesso ou somente os dois acessos padrão. Na sua cpu no (Regedit) registro existe um carinha de nome MSLICENSING, neste registro existe um contador de acesso, e tem duas pastas HARDWAREID e STORE. Delete as duas pastas na sua cpu e tente conectar novamente, que o contador irá iniciar do zero, isso pode liberar a pendência. []s,
  9. Puts, sem erro fica dificil, mas substitui todos os dados ou cria vários registros iguais?
  10. Giba, tem uma nota técnica que diz que este registro é dispensando, mas qqr forma, a UF tem que informar o código, vc já tem o código divulgado pela UF? []s,
  11. As Dlls, estão disponíveis para clientes Sac. Para ser cliente Sac, basta se cadastrar no ACBR, pagar uma mensalidade (R$120,00) e vc poderá baixar tudo o que existe nas áreas de downloads disponíveis para usuários Sac, mas não é obrigado a pagar todos os meses, somente quando vc precisar e querer atualizar, diferentemente de outros que tem que pagar mensalmente e por CNPJ. Nada contra, mas sempre preferi ser de certa forma independente e isso não significa que daqui há alguns anos o ACBR não passe a ser taxado também. []s,
  12. Giba, este registro é mesmo do contribuições? Qual data e versão do layout? Ah! Agora entendi, registro E115 do IPI/ICMS. Esse abaixo: 1) Introdução ao Registro E115: Veremos neste capítulo do Guia Prático o layout do Registro E115 do Sped-Fiscal, que tem o objetivo de informar os valores declaratórios relativos ao ICMS, conforme definição da legislação Estadual pertinente. Base Legal: Guia Prático da Escrituração Fiscal Digital - EFD-ICMS/IPI da Receita Federal do Brasil (Checado pela Valor Consulting em 19/01/16). 2) Layout: Este Registro tem o objetivo de informar os valores declaratórios relativos ao ICMS, conforme definição da legislação Estadual pertinente. Esses valores são meramente declaratórios e não são computados na apuração do ICMS. Nº Campo Descrição Tipo Tam. Dec. Obrig. 01 REG Texto fixo contendo "E115". C 004 - O 02 COD_INF_ADIC Código da informação adicional conforme Tabela a ser definida pelas Secretarias da Fazenda (Sefaz). C 008* - O 03 VL_INF_ADIC Valor referente à informação adicional. N - 02 O 04 DESCR_COMPL_AJ Descrição complementar do ajuste. C - - OC Observações: Nível hierárquico: 4; Ocorrência: 1:N; Coluna Entrada e/ou Saída: O "O" significa que o campo deve ser sempre preenchido (ou apresentado). Já o "OC" significa que o campo deve ser preenchido (ou apresentado) sempre que houver a informação a ser apresentada. Por fim, o "N" significa que o registro não pode ser preenchido (ou apresentado). Base Legal: Guia Prático da Escrituração Fiscal Digital - EFD-ICMS/IPI da Receita Federal do Brasil. 2.1) Observações sobre o preenchimento: * Campo 01 (REG): Valor Válido: [E115]. * Campo 02 (COD_INF_ADIC): Preenchimento: o código da informação adicional deve obedecer à Tabela definida pelas Sefazs dos Estados. Caso não haja publicação da referida Tabela, o Registro não deve ser apresentado. Base Legal: Guia Prático da Escrituração Fiscal Digital - EFD-ICMS/IPI da Receita Federal do Brasil. 2.2) Alterações do layout: Até a última atualização desta publicação no Portal Valor Consulting, foram processadas as seguintes alterações no layout do Registro E115 da EFD-ICMS/IPI (Sped-Fiscal), conforme Guia Prático EFD-ICMS/IPI publicado no Portal do Sistema Público de Escrituração Digital (Sped). É a Equipe Valor Consulting trazendo o que há de melhor para vocês, nossos estimados leitores. Precisou de assessoria e/ou consultoria em EFD-ICMS/IPI, entre em contato com nossa equipe comercial através do nosso Fale Conosco. Faça como outras empresas e profissionais, seja um cliente de valor você também! Versão Vigente a partir de Alteração Nº Data 2.0.10 06/2012 01/10/2012 Dispensa de preenchimento dos campos PIS e Cofins em toda a EFD-ICMS/IPI. 2.0.11 09/2012 10/10/2012 Os contribuintes que entregarem a EFD-Contribuições relativa ao mesmo período de apuração do registro 0000 estão dispensados do preenchimento dos campos referentes às contribuições para PIS/COFINS. 2.0.11 09/2012 10/10/2012 Inclusão da obrigatoriedade dos registros por perfis. Base Legal: Equipe Valor Consulting. Informações Adicionais: Este material foi escrito no dia 05/12/2013 pela Equipe Técnica da Valor Consulting e está atualizado até a legislação vigente em 09/07/2019 (data da sua última atualização), sujeitando-se, portanto, às mudanças em decorrência das alterações legais. Não é permitido a utilização dos materiais publicados pela Valor Consulting para fins comerciais, pois os mesmos estão protegidos por direitos autorais. Também não é permitido copiar os artigos, materias e arquivos do Portal Valor Consulting para outro site, sistema ou banco de dados para fins de divulgação em sites, revistas, jornais, etc de terceiros sem a autorização escrita dos proprietários do Portal Valor Consulting. A utilização para fins exclusivamente educacionais é permitida desde que indicada a fonte: Valor Consulting. Registro E115 do Sped-Fiscal - Informações adicionais da Apuração - Valores declaratórios. Disponível em: https://www.valor.srv.br/guias/guiasIndex.php?idGuia=140. Acesso em: 18/09/2019. []s,
  13. Ah! Pensei que vc gerava e tinha todo controle e não do banco, que por sinal não ia deixar de ganhar, pq ele ganha na baixa e na próxima liquidação do novo boleto., embora, se for realmente um novo boleto com outro vencimento, o banco está certo, pq mesmo que vc faça a prorrogação, é feita a baixa e uma nova emissão de boleto. []s,
  14. Edú, bom dia Eu não entendi? Vc não emite o boleto pelo seu sistema? E pq ele não não mantêm o mesmo número? []s,
  15. Te explico amigo. A partir do momento que vc passar a usar as DLL's, não será mais necessário vc ativar o monitor, pq ficará por sua conta enviar os comandos para a dll, então em tempo de execução ou dinamicamente vc invoca/carrega/load na dll e envia os comandos conforme a sua necessidade, como se estivesse enviando para o monitor e ela fizesse parte do seu sistema. Os exemplos acima da dll sat, o Rafael Dias (Acbr) criou um classe em Harbour/Xharbour para facilitar o uso da dll, eu deixei uns exemplos acima de envio de comandos e ele fez um exemplo de geração e envio de uma venda sat, como se estivesse gerando um arquivo INI para o monitor. Se quiser mais informações me chame no skype: fnlinf
  16. Não, a DLL é justamente pra vc não ter que usar o monitor.
  17. Oscar, é a mesma que eu postei aqui, embora postei a classe criada pelo Rafael Dias, embora, o exemplo é para quem usa o INI. []s,
  18. Classe do Sat: #include "hbclass.ch" #include "error.ch" #define DC_CALL_CDECL 0x0010 // __cdecl #define DC_CALL_STD 0x0020 // __stdcall #ifdef __XHARBOUR__ #define ACBrLIBSat "ACBrSAT32.dll" #define DLL_OSAPI DC_CALL_STD #else #ifdef __PLATFORM__WINDOWS ///#if defined( __PLATFORM__WINDOWS ) #define ACBrLIBSat "ACBrSAT32.dll" #define DLL_OSAPI DC_CALL_STD #else #define ACBrLIBSat "ACBrSAT32.dll" A classe da Nfe ainda não tenho. #define DLL_OSAPI DC_CALL_STD #endif #endif #define STR_LEN 256 CREATE CLASS ACBrSat HIDDEN: VAR hHandle METHOD CheckResult(hResult) METHOD ProcessResult(buffer, bufferLen) VISIBLE: METHOD New() CONSTRUCTOR METHOD New(eArqConfig, eChaveCrypt) CONSTRUCTOR DESTRUCTOR Destroy METHOD Nome METHOD Versao METHOD ConfigLer(eArqConfig) METHOD ConfigGravar(eArqConfig) METHOD ConfigLerValor(eSessao, eChave) METHOD ConfigGravarValor(eSessao, eChave, eValor) METHOD Inicializar METHOD DesInicializar METHOD AssociarAssinatura(CNPJvalue, assinaturaCNPJs) METHOD BloquearSAT() METHOD DesbloquearSAT() METHOD TrocarCodigoDeAtivacao(codigoDeAtivacaoOuEmergencia, opcao, novoCodigo) METHOD ConsultarSAT() METHOD ConsultarStatusOperacional() METHOD ConsultarNumeroSessao(cNumeroDeSessao) METHOD AtualizarSoftwareSAT() METHOD ComunicarCertificadoICPBRASIL(certificado) METHOD ExtrairLogs(eArquivo) METHOD TesteFimAFim(eArquivoXmlVenda) METHOD GerarAssinaturaSAT(eCNPJSHW, eCNPJEmitente) METHOD CriarCFe(eArquivoIni) METHOD CriarEnviarCFe(eArquivoIni) METHOD EnviarCFe(eArquivoXml) METHOD CancelarCFe(eArquivoXml) METHOD ImprimirExtratoVenda(eArqXMLVenda, eNomeImpressora) METHOD ImprimirExtratoResumido(eArqXMLVenda, eNomeImpressora) METHOD ImprimirExtratoCancelamento(eArqXMLVenda, eArqXMLCancelamento, eNomeImpressora) METHOD GerarImpressaoFiscalMFe(eArqXMLVenda) METHOD GerarPDFExtratoVenda(eArqXMLVenda, eNomeArquivo) METHOD GerarPDFCancelamento(eArqXMLVenda, eArqXMLCancelamento, eNomeArquivo) METHOD EnviarEmail(eArqXMLVenda, sPara, sAssunto, eNomeArquivo, sMensagem, sCC, eAnexos) END CLASS METHOD New(eArqConfig, eChaveCrypt) CLASS ACBrSat local hResult, buffer, bufferLen, oErr ::hHandle := DllLoad(ACBrLIBSat) if ::hHandle = nil oErr := ErrorNew() oErr:Severity := ES_ERROR oErr:Description := "Erro a carregar a dll [" + ACBrLIBSat + "]" Throw(oErr) endif hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_Inicializar", hb_StrToUTF8(eArqConfig), hb_StrToUTF8(eChaveCrypt)) ::CheckResult(hResult) RETURN Self PROCEDURE Destroy CLASS ACBrSat DllCall(::hHandle, DLL_OSAPI, "SAT_Finalizar") DllUnload(::hHandle) RETURN METHOD CheckResult(hResult) CLASS ACBrSat local buffer, bufferLen, oErr if hResult >= 0 RETURN nil endif bufferLen := STR_LEN buffer := Space(bufferLen) DllCall(::hHandle, DLL_OSAPI, "SAT_UltimoRetorno", @buffer, @bufferLen) if bufferLen > STR_LEN buffer := Space(bufferLen) DllCall(::hHandle, DLL_OSAPI, "SAT_UltimoRetorno", @buffer, @bufferLen) endif oErr := ErrorNew() oErr:Severity := ES_ERROR oErr:Description := hb_UTF8ToStr(buffer) Throw(oErr) RETURN nil METHOD ProcessResult(buffer, bufferLen) CLASS ACBrSat if bufferLen > STR_LEN buffer := Space(bufferLen) DllCall(::hHandle, DLL_OSAPI, "SAT_UltimoRetorno", @buffer, @bufferLen) endif RETURN buffer METHOD Nome CLASS ACBrSat local hResult, buffer, bufferLen, ret bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_Nome", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD Versao CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_Versao", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ConfigLer(eArqConfig) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConfigLer", hb_StrToUTF8(eArqConfig)) ::CheckResult(hResult) RETURN nil METHOD ConfigGravar(eArqConfig) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConfigGravar", hb_StrToUTF8(eArqConfig)) ::CheckResult(hResult) RETURN nil METHOD ConfigLerValor(eSessao, eChave) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConfigLerValor", hb_StrToUTF8(eSessao), hb_StrToUTF8(eChave), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ConfigGravarValor(eSessao, eChave, eValor) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConfigGravarValor", hb_StrToUTF8(eSessao), hb_StrToUTF8(eChave), hb_StrToUTF8(eValor)) ::CheckResult(hResult) RETURN nil METHOD Inicializar CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_InicializarSAT") ::CheckResult(hResult) RETURN nil METHOD DesInicializar CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_DesInicializar") ::CheckResult(hResult) RETURN nil METHOD AssociarAssinatura(CNPJvalue, assinaturaCNPJs) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_AssociarAssinatura", hb_StrToUTF8(CNPJvalue), hb_StrToUTF8(assinaturaCNPJs), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD BloquearSAT() CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_BloquearSAT", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD DesbloquearSAT() CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_DesbloquearSAT", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD TrocarCodigoDeAtivacao(codigoDeAtivacaoOuEmergencia, opcao, novoCodigo) local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_TrocarCodigoDeAtivacao", hb_StrToUTF8(codigoDeAtivacaoOuEmergencia), opcao, hb_StrToUTF8(novoCodigo), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ConsultarSAT() CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConsultarSAT", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ConsultarStatusOperacional() CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConsultarStatusOperacional", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ConsultarNumeroSessao(cNumeroDeSessao) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ConsultarNumeroSessao", cNumeroDeSessao, @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD AtualizarSoftwareSAT() CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_AtualizarSoftwareSAT", @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ComunicarCertificadoICPBRASIL(certificado) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ComunicarCertificadoICPBRASIL", hb_StrToUTF8(certificado), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ExtrairLogs(eArquivo) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ExtrairLogs", hb_StrToUTF8(eArquivo)) ::CheckResult(hResult) RETURN nil METHOD TesteFimAFim(eArquivoXmlVenda) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_TesteFimAFim", hb_StrToUTF8(eArquivoXmlVenda), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD GerarAssinaturaSAT(eCNPJSHW, eCNPJEmitente) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_GerarAssinaturaSAT", hb_StrToUTF8(eCNPJSHW), hb_StrToUTF8(eCNPJEmitente), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD CriarCFe(eArquivoIni) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_CriarCFe", hb_StrToUTF8(eArquivoIni), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD CriarEnviarCFe(eArquivoIni) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_CriarEnviarCFe", hb_StrToUTF8(eArquivoIni), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD EnviarCFe(eArquivoXml) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_EnviarCFe", hb_StrToUTF8(eArquivoXml), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD CancelarCFe(eArquivoXml) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_CancelarCFe", hb_StrToUTF8(eArquivoXml), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD ImprimirExtratoVenda(eArqXMLVenda, eNomeImpressora) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ImprimirExtratoVenda", hb_StrToUTF8(eArqXMLVenda), hb_StrToUTF8(eNomeImpressora)) ::CheckResult(hResult) RETURN nil METHOD ImprimirExtratoResumido(eArqXMLVenda, eNomeImpressora) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ImprimirExtratoResumido", hb_StrToUTF8(eArqXMLVenda), hb_StrToUTF8(eNomeImpressora)) ::CheckResult(hResult) RETURN nil METHOD ImprimirExtratoCancelamento(eArqXMLVenda, eArqXMLCancelamento, eNomeImpressora) CLASS ACBrSat local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_ImprimirExtratoCancelamento", hb_StrToUTF8(eArqXMLVenda), hb_StrToUTF8(eArqXMLCancelamento), hb_StrToUTF8(eNomeImpressora)) ::CheckResult(hResult) RETURN nil METHOD GerarImpressaoFiscalMFe(eArqXMLVenda) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_CancelarCFe", hb_StrToUTF8(eArqXMLVenda), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD GerarPDFExtratoVenda(eArqXMLVenda, eNomeArquivo) CLASS ACBrSat local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_GerarPDFExtratoVenda", hb_StrToUTF8(eArqXMLVenda), hb_StrToUTF8(eNomeArquivo), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD GerarPDFCancelamento(eArqXMLVenda, eArqXMLCancelamento, eNomeArquivo) local hResult, buffer, bufferLen bufferLen := STR_LEN buffer := Space(bufferLen) hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_GerarPDFCancelamento", hb_StrToUTF8(eArqXMLVenda), hb_StrToUTF8(eArqXMLCancelamento), hb_StrToUTF8(eNomeArquivo), @buffer, @bufferLen) ::CheckResult(hResult) RETURN ::ProcessResult(buffer, bufferLen) METHOD EnviarEmail(eArqXMLVenda, sPara, sAssunto, eNomeArquivo, sMensagem, sCC, eAnexos) local hResult hResult := DllCall(::hHandle, DLL_OSAPI, "SAT_EnviarEmail", hb_StrToUTF8(eArqXMLVenda), hb_StrToUTF8(sPara), hb_StrToUTF8(sAssunto), hb_StrToUTF8(eNomeArquivo), hb_StrToUTF8(sMensagem), hb_StrToUTF8(sCC), hb_StrToUTF8(eAnexos)) ::CheckResult(hResult) RETURN nil Demo para quem usar geração em TXT: Function Main () local sat local vendaRetorno, strIniVenda local hIni, hIniVenda LOCAL cSection sat := ACBrSat():New("", "") // Sessão Chave Valor // Configurações de log da Lib sat:ConfigGravarValor("Principal", "LogNivel", "4") // logParanoico sat:ConfigGravarValor("Principal", "LogPath", hb_dirBase()) //Configurações do Sat sat:ConfigGravarValor("SAT", "Modelo", "1") // satDinamico_cdecl sat:ConfigGravarValor("SAT", "NomeDLL", "C:\SAT\SAT.dll") sat:ConfigGravarValor("SAT", "CodigoDeAtivacao", "sefaz1234") sat:ConfigGravarValor("SAT", "SignAC", "111111111111122222222222222111111111111112222222222222211111111111111222222222222221111111111111122222222222222111111111111112222222222222211111111111111222222222222221111111111111122222222222222111111111111112222222222222211111111111111222222222222221111") // Softhouse sat:ConfigGravarValor("SATConfig", "infCFe_versaoDadosEnt", "0.07") sat:ConfigGravarValor("SATConfig", "ide_CNPJ", "16716114000172") sat:ConfigGravarValor("SATConfig", "ide_numeroCaixa", "0") // Emitente sat:ConfigGravarValor("SATConfig", "emit_CNPJ", "14200166000166") sat:ConfigGravarValor("SATConfig", "emit_IE", "111111111111") sat:ConfigGravarValor("SATConfig", "emit_IM", "") sat:ConfigGravarValor("SATConfig", "emit_cRegTrib", "0") // RTSimplesNacional sat:ConfigGravarValor("SATConfig", "emit_cRegTribISSQN", "0") // RTISSMicroempresaMunicipal sat:ConfigGravarValor("SATConfig", "emit_indRatISSQN", "0") // irSim // Extrato sat:ConfigGravarValor("Extrato", "Tipo", "0") // teFortes sat:ConfigGravarValor("Extrato", "MostraPreview", "1") // True // Salvando configurações sat:ConfigGravar("") ?sat:Nome ?sat:Versao sat:Inicializar() // Gerando ini venda hIniVenda := Hash() hIniVenda["infCFe"] := Hash() hIniVenda["infCFe"]["versao"] := "0.07" hIniVenda["Destinatario"] := Hash() hIniVenda["Destinatario"]["CNPJCPF"] := "05481336000137" hIniVenda["Destinatario"]["xNome"] := "D.J. SYSTEM" hIniVenda["Entrega"] := Hash() hIniVenda["Entrega"]["xLgr"] := "Rua Cel. Aureliano de Camargo" hIniVenda["Entrega"]["nro"] := "973" hIniVenda["Entrega"]["xCpl"] := "" hIniVenda["Entrega"]["xBairro"] := "Centro" hIniVenda["Entrega"]["xMun"] := "Tatui" hIniVenda["Entrega"]["UF"] := "SP" hIniVenda["Produto001"] := Hash() hIniVenda["Produto001"]["cProd"] := "1189" hIniVenda["Produto001"]["infAdProd"] := "Teste de Produto" hIniVenda["Produto001"]["cEAN"] := "" hIniVenda["Produto001"]["xProd"] := "OVO VERMELHO" hIniVenda["Produto001"]["NCM"] := "04072100" hIniVenda["Produto001"]["CFOP"] := "5102" hIniVenda["Produto001"]["uCom"] := "DZ" hIniVenda["Produto001"]["Combustivel"] := "0" hIniVenda["Produto001"]["qCom"] := "510" hIniVenda["Produto001"]["vUnCom"] := "2,70" hIniVenda["Produto001"]["indRegra"] := "A" hIniVenda["Produto001"]["vDesc"] := "0" hIniVenda["Produto001"]["vOutro"] := "0" hIniVenda["Produto001"]["vItem12741"] := "137,00" hIniVenda["ObsFiscoDet001001"] := Hash() hIniVenda["ObsFiscoDet001001"]["xCampoDet"] := "Teste" hIniVenda["ObsFiscoDet001001"]["xTextoDet"] := "Texto Teste" hIniVenda["ICMS001"] := Hash() hIniVenda["ICMS001"]["Origem"] := "0" hIniVenda["ICMS001"]["CSOSN"] := "500" hIniVenda["PIS001"] := Hash() hIniVenda["PIS001"]["CST"] := "01" hIniVenda["COFINS001"] := Hash() hIniVenda["COFINS001"]["CST"] := "01" hIniVenda["Total"] := Hash() hIniVenda["Total"]["vCFeLei12741"] := "137,00" hIniVenda["DescAcrEntr"] := Hash() hIniVenda["DescAcrEntr"]["vDescSubtot"] := "7,00" hIniVenda["Pagto001"] := Hash() hIniVenda["Pagto001"]["cMP"] := "01" hIniVenda["Pagto001"]["vMP"] := "1400" hIniVenda["DadosAdicionais"] := Hash() hIniVenda["DadosAdicionais"]["infCpl"] := "Teste emissao CFe/SAT" hIniVenda["ObsFisco001"] := Hash() hIniVenda["ObsFisco001"]["xCampo"] := "ObsFisco 1" hIniVenda["ObsFisco001"]["xTexto"] := "Teste ObsFisco 1" strIniVenda := hb_iniWriteStr(hIniVenda) // Venda ?"Ini Venda" ?strIniVenda ?"" ?"-------------------------------------------------------------------------------------------------------------" ?"" vendaRetorno := sat:CriarEnviarCFe(strIniVenda) ?vendaRetorno ?"" ?"-------------------------------------------------------------------------------------------------------------" ?"" hIni := hb_iniReadStr(vendaRetorno) cSection := hIni["ENVIO"] if cSection["CodigoDeRetorno"] != "6000" ?cSection["Resultado"] else ?"Impressão Preview" sat:ImprimirExtratoVenda(cSection["XML"], "") ?"Impressão PDF" ?sat:GerarPDFExtratoVenda(cSection["XML"], "") end if sat:DesInicializar() sat := nil return NIL Exemplos: sat := ACBrSat():New("", "") sat:ConfigGravarValor("Principal", "LogNivel", "4") sat:ConfigGravarValor("SAT", "Modelo", "2") sat:ConfigGravarValor("SAT", "ArqLog", "C:\windows\temp\satlog") sat:ConfigGravarValor("SAT", "NomeDLL", "C:\ACBrMonitorPLUS\SAT\elgin\dllsat.dll") sat:ConfigGravarValor("SAT", "CodigoDeAtivacao", "123456789") sat:ConfigGravarValor("SAT", "SignAC", "SGR-SAT SISTEMA DE GESTAO E RETAGUARDA DO SAT") sat:ConfigGravarValor("SATConfig", "ide_numeroCaixa", "3") //ide_numeroCaixa Define o numero de caixa padrão da CFe. sat:ConfigGravarValor("SATConfig", "ide_tpAmb", "0") //ide_tpAmb taProducao = 0 taHomologacao = 1 sat:ConfigGravarValor("SATConfig", "EhUTF8", "") //EhUTF8 Define se devemos utilizar codificação UTF8 ao se comunicar com o SAT. sat:ConfigGravarValor("SATConfig", "infCFe_versaoDadosEnt", "0,07") //infCFe_versaoDadosEnt Define qual será a versão do CFe utilizada.Ex.: 0,07 ou 0,08 sat:ConfigGravarValor("SATConfig", "PaginaDeCodigo", "0") //PaginaDeCodigo Define a pagina de código que se deve utilizar ao se comunicar com o SAT. sat:ConfigGravarValor("SATConfigArquivos", "PastaCFeVenda", "X:\acbr\NFESAI\AUTORIZA\59") //PastaCFeVenda Define o caminho onde será salvos os arquivos de venda. sat:ConfigGravarValor("SATConfigArquivos", "SalvarCFe","0" ) //SalvarCFe Define se será salvo o arquivo de venda. sat:ConfigGravarValor("SATConfigArquivos", "SalvarCFeCanc", "0") //SalvarCFeCanc Define se será salvo o arquivo de cancelamento. sat:ConfigGravarValor("SATConfigArquivos", "SalvarEnvio", "0") //SalvarEnvio Define se será salvo o arquivo de envio para o sat. //sat:ConfigGravarValor("SATConfigArquivos", "SepararPorCNPJ", "0") //SepararPorCNPJ Define se deverá separar os arquivos por CNPJ. //sat:ConfigGravarValor("SATConfigArquivos", "SepararPorModelo", "0") //SepararPorModelo Define se deverá separar os arquivos por modelo. //sat:ConfigGravarValor("SATConfigArquivos", "SepararPorAno", "0") //SepararPorAno Define se deverá separar os arquivos por ano. //sat:ConfigGravarValor("SATConfigArquivos", "SepararPorMes", "0") //SepararPorMes Define se deverá separar os arquivos por mês. //sat:ConfigGravarValor("SATConfigArquivos", "SepararPorDia", "0") //SepararPorDia Define se deverá separar os arquivos por dia. sat:ConfigGravarValor("SATConfig", "ide_CNPJ", "14200166000166") //ide_CNPJ Exemplo da elgin: 16716114000172 Define o padrão CNPJ do emitente da CFe. sat:ConfigGravarValor("SATConfig", "emit_IE", "144842258111") //emit_IE Define o IE padrão do emitente do CFe. //sat:ConfigGravarValor("SATConfig", "emit_IM", "inscricao municipal do emitente") //emit_IM Define o IM padrão do emitente do CFe. sat:ConfigGravarValor("SATConfig", "emit_cRegTrib","0") //emit_cRegTrib RTSimplesNacional = 0 RTRegimeNormal = 1 sat:ConfigGravarValor("SATConfig", "emit_cRegTribISSQN", "6") //emit_cRegTribISSQN RTISS MicroempresaMunicipal = 0 sat:ConfigGravarValor("SATConfig", "emit_indRatISSQN", "0") //emit_indRatISSQN Define indicador de rateio do desconto sobre subtotal entre itens sujeitos a sat:ConfigGravarValor("SATConfig", "emit_CNPJ", "16716114000172") //emit_CNPJ Exemplo da elgin: 14200166000166 Define o CNPJ padrão do emitente da CFe. sat:ConfigGravarValor("SATRede", "tipoInter", "0") //0 = infETHE sat:ConfigGravarValor("SATRede", "tipoLan", "0") sat:ConfigGravarValor("Extrato", "LarguraBobina", "302") //LarguraBobina Define a largura da bobina. sat:ConfigGravarValor("Extrato", "MargemSuperior", "2") //MargemSuperior Define a margem superior da impressão. sat:ConfigGravarValor("Extrato", "MargemInferior", "4") //MargemInferior Define a margem inferior da impressão. sat:ConfigGravarValor("Extrato", "MargemEsquerda", "2") //MargemEsquerda Define a margem esquerda da impressão. sat:ConfigGravarValor("Extrato", "MargemDireita", "2") //MargemDireita Define a margem direita da impressão. sat:ConfigGravarValor("Extrato", "Tipo", "0") //TipoDefine o tipo de impressão a ser utilizada.tpFortes = 0 tpEscPos = 1 //sat:ConfigGravarValor("Extrato", "Impressora", "nome a impressora para emissão do cupom") //Impressora Define o nome da impressora padrão a ser utilizada pela impressão. sat:ConfigGravarValor("Extrato", "ImprimeChaveEmUmaLinha", "0") //ImprimeChaveEmUma Define se deve imprimir a chave do CFe em apenas uma linha. Dll's Necessárias , a quais podems ser baixadas por qualquer usuário Sac do Acbr. ACBrSAT32.dll ACBrSAT64.dll libeay32.dll libexslt.dll libiconv.dll libxml2.dll libxslt.dll msvcr120.dll ssleay32.dll Obs: A classe da NF-e ainda não tenho. []s,
  19. Jfaguiar, a Tmysql não é uma classe? /* * $Id: tmysql.prg,v 1.17 2007/07/17 21:01:17 andresreyesh Exp $ */ /* * Harbour Project source code: * MySQL DBMS classes. * These classes try to emulate clipper dbXXXX functions on a SQL query * * Copyright 2000 Maurilio Longo <maurilio.longo@libero.it> * www - http://www.harbour-project.org * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 59 Temple Place, Suite 330, * Boston, MA 02111-1307 USA (or visit the web site http://www.gnu.org/). * * As a special exception, the Harbour Project gives permission for * additional uses of the text contained in its release of Harbour. * * The exception is that, if you link the Harbour libraries with other * files to produce an executable, this does not by itself cause the * resulting executable to be covered by the GNU General Public License. * Your use of that executable is in no way restricted on account of * linking the Harbour library code into it. * * This exception does not however invalidate any other reasons why * the executable file might be covered by the GNU General Public License. * * This exception applies only to the code released by the Harbour * Project under the name Harbour. If you copy code from other * Harbour Project or Free Software Foundation releases into a copy of * Harbour, as the General Public License permits, the exception does * not apply to the code that you add in this way. To avoid misleading * anyone as to the status of such modified files, you must delete * this exception notice from them. * * If you write modifications of your own for Harbour, it is your choice * whether to permit this exception to apply to your modifications. * If you do not wish that, delete this exception notice. * */ /* 2002-01-28 21:30 UTC+0100 Patrick Mast <email@patrickmast.com> * contrib/mysql/tmysql + Added DateTime field * Added more info on Alert message for Unknown type * Modified ClipValue2SQL() to process empty strings */ /* 2002-02-18 07:30 UTC+0100 Srdjan Dragojlovic <digikv@yahoo.com> * contrib/mysql/tmysql + Bug in GOTO Method */ #include "hbclass.ch" #include "common.ch" #include "dbstruct.ch" #include "mysql.ch" // Every single row of an answer CLASS TMySQLRow DATA aRow // a single row of answer DATA aDirty // array of booleans set to .T. if corresponding field of aRow has been changed DATA aOldValue // If aDirty[n] is .T. aOldValue[n] keeps a copy of changed value if aRow[n] is part of a primary key DATA aFieldStruct // type of each field DATA cTable // Name of table containing this row, empty if TMySQLQuery returned this row METHOD New( aRow, aFStruct, cTableName ) // Create a new Row object METHOD FieldGet( cnField ) // Same as clipper ones, but FieldGet() and FieldPut() accept a string as METHOD FieldPut( cnField, Value ) // field identifier, not only a number METHOD FieldName( nNum ) METHOD FieldPos( cFieldName ) METHOD FieldLen( nNum ) // Length of field N METHOD FieldDec( nNum ) // How many decimals in field N METHOD FieldType( nNum ) // Clipper type of field N METHOD MakePrimaryKeyWhere() // returns a WHERE x=y statement which uses primary key (if available) ENDCLASS METHOD New( aRow, aFStruct, cTableName ) CLASS TMySQLRow default cTableName to "" default aFStruct to {} ::aRow := aRow ::aFieldStruct := aFStruct ::cTable := cTableName ::aDirty := Array( Len( ::aRow ) ) ::aOldValue := Array( Len( ::aRow ) ) AFill( ::aDirty, .F. ) return Self METHOD FieldGet( cnField ) CLASS TMySQLRow local nNum if ValType( cnField ) == "C" nNum := ::FieldPos( cnField ) else nNum := cnField endif if nNum > 0 .AND. nNum <= Len( ::aRow ) // Char fields are padded with spaces since a real .dbf field would be if ::FieldType( nNum ) == "C" return PadR( ::aRow[ nNum ], ::aFieldStruct[ nNum ][ MYSQL_FS_LENGTH ]) else return ::aRow[ nNum ] endif endif return nil METHOD FieldPut( cnField, Value ) CLASS TMySQLRow local nNum if ValType( cnField ) == "C" nNum := ::FieldPos( cnField ) else nNum := cnField endif if nNum > 0 .AND. nNum <= Len( ::aRow ) if Valtype( Value ) == Valtype( ::aRow[ nNum ] ) .OR. ::aRow[ nNum ] == NIL // .OR. Empty(::aRow[nNum]) // if it is a char field remove trailing spaces if ValType( Value ) == "C" Value := RTrim( Value ) endif // Save starting value for this field if !::aDirty[ nNum ] ::aOldValue[ nNum ] := ::aRow[ nNum ] ::aDirty[ nNum ] := .T. endif ::aRow[ nNum ] := Value return Value endif endif return nil // Given a field name returns it's position METHOD FieldPos( cFieldName ) CLASS TMySQLRow local cUpperName, nPos cUpperName := Upper( cFieldName ) nPos := AScan( ::aFieldStruct, {| aItem | Upper( aItem[ MYSQL_FS_NAME ] ) == cUpperName } ) return nPos // Returns name of field N METHOD FieldName( nNum ) CLASS TMySQLRow if nNum >= 1 .AND. nNum <= Len( ::aFieldStruct ) return ::aFieldStruct[ nNum ][ MYSQL_FS_NAME ] endif return "" METHOD FieldLen(nNum) CLASS TMySQLRow if nNum >= 1 .AND. nNum <= Len( ::aFieldStruct ) return ::aFieldStruct[ nNum ][ MYSQL_FS_LENGTH ] endif return 0 METHOD FieldDec( nNum ) CLASS TMySQLRow if nNum >= 1 .AND. nNum <= Len( ::aFieldStruct ) return ::aFieldStruct[ nNum ][ MYSQL_FS_DECIMALS ] endif return 0 METHOD FieldType( nNum ) CLASS TMySQLRow if nNum >= 1 .AND. nNum <= Len( ::aFieldStruct ) Return SQL2ClipType( ::aFieldStruct[ nNum ][ MYSQL_FS_TYPE ] ) endif return "U" // returns a WHERE x=y statement which uses primary key (if available) METHOD MakePrimaryKeyWhere() CLASS TMySQLRow local cWhere := " WHERE ", aField for each aField in ::aFieldStruct // search for fields part of a primary key if ( sqlAND( aField[ MYSQL_FS_FLAGS ], PRI_KEY_FLAG ) == PRI_KEY_FLAG ) .OR.; ( sqlAND( aField[ MYSQL_FS_FLAGS ], MULTIPLE_KEY_FLAG ) == MULTIPLE_KEY_FLAG ) cWhere += aField[ MYSQL_FS_NAME ] + "=" // if a part of a primary key has been changed, use original value if ::aDirty[ HB_EnumIndex() ] cWhere += ClipValue2SQL( ::aOldValue[ HB_EnumIndex() ], SQL2ClipType(aField[ MYSQL_FS_TYPE ]) ) else cWhere += ClipValue2SQL( ::aRow[ HB_EnumIndex() ], SQL2ClipType(aField[ MYSQL_FS_TYPE ]) ) endif cWhere += " AND " endif next // remove last " AND " cWhere := Left( cWhere, Len( cWhere ) - 5 ) return cWhere /* ----------------------------------------------------------------------------------------*/ // Every single query submitted to MySQL server CLASS TMySQLQuery DATA nSocket // connection handle to MySQL server DATA nResultHandle // result handle received from MySQL DATA cQuery // copy of query that generated this object DATA nNumRows // number of rows available on answer NOTE MySQL is 0 based DATA nCurRow // I'm currently over row number DATA nNumFields // how many fields per row DATA aFieldStruct // type of each field, a copy is here a copy inside each row DATA aRow DATA lError // .T. if last operation failed DATA loRow // If return oRow in GetRow(), METHOD New( nSocket, cQuery, loRow ) // New query object METHOD Destroy() INLINE sqlFreeR( ::nResultHandle ), Self // Free result handle and associated resources METHOD End() INLINE ::Destroy() METHOD Refresh() // ReExecutes the query (cQuery) so that changes to table are visible METHOD GetRow( nRow, loRow, lSkip ) // return Row n of answer METHOD Skip( nRows ) // Same as clipper ones METHOD Bof() INLINE ::lBof // ::nCurRow == 1 METHOD Eof() INLINE ::lEof // ::nCurRow == ::nNumRows METHOD RecNo() INLINE ::nCurRow METHOD LastRec() INLINE ::nNumRows METHOD GoTop() INLINE ::GetRow( 1 ) METHOD GoBottom() INLINE ::GetRow( ::nNumRows ) //-1 ) METHOD GoTo( nRow ) INLINE ::GetRow( nRow ) METHOD FCount() INLINE ::nNumFields METHOD NetErr() INLINE ::lError // Returns .T. if something went wrong METHOD Error() INLINE ::lError := .F., sqlGetErr(::nSocket) // Returns textual description of last error and clears ::lError METHOD ErrorNo() INLINE ::lError := .F., sqlGetErrNo(::nSocket) // Returns number of last error and clears ::lError METHOD FieldName( nNum ) METHOD FieldPos( cFieldName ) METHOD FieldGet( cnField ) METHOD FieldLen( nNum ) // Length of field N METHOD FieldDec( nNum ) // How many decimals in field N METHOD FieldType( nNum ) // Clipper type of field N METHOD Locate( cFieldName, Value, bPartialKey, bSoftSeek ) METHOD RecCount() INLINE ::nNumRows PROTECTED: DATA lEof DATA lBof ENDCLASS METHOD New( nSocket, cQuery, loRow ) CLASS TMySQLQuery local nI, aField, rc, bBlock Default loRow to .t. ::nSocket := nSocket ::cQuery := cQuery ::lError := .F. ::aFieldStruct := {} ::nCurRow := 1 ::nResultHandle := nil ::nNumFields := 0 ::nNumRows := 0 ::loRow := loRow if ( rc := sqlQuery( nSocket, cQuery ) ) == 0 // save result set if ( ::nResultHandle := sqlStoreR( nSocket ) ) > 0 ::nNumRows := sqlNRows( ::nResultHandle ) ::nNumFields := sqlNumFi( ::nResultHandle ) ::aFieldStruct := Array( ::nNumFields ) ::aRow := Array( ::nNumFields ) if ::nNumRows > 0 ::lEof := .f. ::lBof := .f. else ::lEof := .t. ::lBof := .t. endif for each aField in ::aFieldStruct aField := sqlFetchF( ::nResultHandle ) bBlock := ArrayBlock( HB_EnumIndex() ) __objAddInline( Self, aField[ MYSQL_FS_NAME ], bBlock ) __objAddInline( Self, "_"+aField[ MYSQL_FS_NAME ], bBlock ) next ::getRow( ::nCurRow ) else // Should query have returned rows? (Was it a SELECT like query?) if ( ::nNumFields := sqlNumFi( nSocket ) ) == 0 // Was not a SELECT so reset ResultHandle changed by previous sqlStoreR() ::nResultHandle := nil ::lEof := .t. ::lBof := .t. else ::lError := .T. endif endif else ::lError := .T. endif return Self METHOD Refresh() CLASS TMySQLQuery local rc // free present result handle sqlFreeR( ::nResultHandle ) ::lError := .F. if ( rc := sqlQuery( ::nSocket, ::cQuery ) ) == 0 // save result set ::nResultHandle := sqlStoreR( ::nSocket ) ::nNumRows := sqlNRows( ::nResultHandle ) // NOTE: I presume that number of fields doesn't change (that is nobody alters this table) between // successive refreshes of the same // But row number could very well change if ::nCurRow > ::nNumRows ::nCurRow := ::nNumRows endif ::getRow( ::nCurRow ) else ::lError := .T. endif return !::lError METHOD Skip( nRows ) CLASS TMySQLQuery Local nOldrow := ::nCurRow // NOTE: MySQL row count starts from 0 default nRows to 1 if ::nNumRows > 0 ::lBof := .f. ::lEof := .f. else ::lBof := .t. ::lEof := .t. endif if nRows == 0 // No move elseif nRows < 0 // Negative movement if (::nCurRow += nRows) < 1 ::nCurRow := 0 ::lBof := .t. endif else // positive movement if (::nCurRow += nRows) > ::nNumRows ::nCurRow := ::nNumRows + 1 ::lEof := .t. endif endif ::getRow( ::nCurRow ) return ::nCurRow - nOldRow // Get row n of a query and return it as a TMySQLRow object METHOD GetRow( nRow, loRow, lSkip ) CLASS TMySQLQuery local cType, xField // local cDateFormat := Lower( Set( 4 ) ) default loRow to ::loRow default nRow to ::nCurRow default lSkip to .f. if ::nResultHandle <> NIL if lSkip nRow := ::nCurRow + 1 endif do case case ::nNumRows == 0 ::lBof := .t. ::lEof := .t. ::nCurRow := 1 case nRow < 1 ::lBof := .t. ::lEof := .t. ::nCurRow := ::nNumRows + 1 case nRow > 0 .and. nRow <= ::nNumRows //- 1 ::lBof := .f. ::lEof := .f. ::nCurRow := nRow case nRow > ::nNumRows ::lBof := .f. ::lEof := .t. ::nCurRow := ::nNumRows + 1 endcase nRow := ::nCurRow if nRow > 0 .AND. nRow <= ::nNumRows // NOTE: row count starts from 0 sqlDataS( ::nResultHandle, nRow - 1 ) ::nCurRow := nRow ::aRow := sqlFetchR( ::nResultHandle ) elseif nRow == ::nNumRows + 1 ::aRow := Array( Len( ::aFieldStruct ) ) Afill( ::aRow, "" ) else ::aRow := NIL endif if ::aRow <> NIL // Convert answer from text field to correct clipper types for each xField in ::aRow cType := SQL2ClipType( ::aFieldStruct[ HB_EnumIndex() ][ MYSQL_FS_TYPE ] ) switch cType case "L" xField := !( Val( xField ) == 0 ) exit case "N" case "I" case "T" xField := Val( xField ) exit case "D" if Empty(xField) xField := CToD( "" ) /* elseif cDateFormat = 'mm-dd-yyyy' // USA xField := ctod(substr(xField,6,2)+"-"+right(xField,2,0)+ "-" + Left(xField, 4)) elseif cDateFormat = 'dd/mm/yyyy' .or. cDateFormat = 'dd/mm/yy' // BRITISH ou FRENCH xField := ctod(right(xField,2,0)+ "/"+ substr(xField,6,2)+"/"+ Left(xField, 4)) elseif cDateFormat = 'yyyy.mm.dd' // ANSI xField := ctod(Left(xField, 4)+ "."+substr(xField,6,2)+"."+right(xField,2,0)) elseif cDateFormat = 'dd.mm.yyyy' //GERMAN xField :=ctod(right(xField,2,0)+ "."+ substr(xField,6,2)+"."+ Left(xField, 4 )) elseif cDateFormat = 'dd-mm-yyyy' //ITALIAN xField :=ctod(right(xField,2,0)+ "-"+ substr(xField,6,2)+"-"+ Left(xField, 4)) elseif cDateFormat = 'yyyy/mm/dd' //JAPAN xField := ctod(Left(xField, 4)+ "/"+substr(xField,6,2)+"/"+right(xField,2,0)) elseif cDateFormat = 'mm/dd/yyyy' // AMERICAN xField := ctod(substr(xField,6,2)+"/"+right(xField,2,0)+ "/" + Left(xField, 4)) else xField := "''" */ else // MySQL Date format YYYY-MM-DD xField := SToD( Left( xField, 4 ) + substr( xField, 6, 2 ) + right( xField, 2 ) ) endif exit case "C" xField := PadR( xField , ::aFieldStruct[ HB_EnumIndex() ][ MYSQL_FS_LENGTH ] ) case "M" case "B" // Character or Memo field exit default // Alert("Unknown type from SQL Server Field: " + LTrim(Str(i))+" is type "+LTrim(Str(nType))) end // __objsetValuelist(Self,{{::aFieldStruct[MYSQL_FS_NAME],xField}}) next if loRow Return TMySQLRow():New( ::aRow, ::aFieldStruct ) endif endif endif return nil // Given a field name returns it's position METHOD FieldPos( cFieldName ) CLASS TMySQLQuery local cUpperName, nPos := 0 cUpperName := Upper( cFieldName ) nPos := AScan( ::aFieldStruct, {| aItem | Upper( aItem[ MYSQL_FS_NAME ] ) == cUpperName } ) return nPos // Returns name of field N METHOD FieldName( nNum ) CLASS TMySQLQuery if nNum >= 1 .AND. nNum <= Len( ::aFieldStruct ) return ::aFieldStruct[ nNum ][ MYSQL_FS_NAME ] endif return "" METHOD FieldGet(cnField) CLASS TMySQLQuery local nNum, Value if ValType( cnField ) == "C" nNum := ::FieldPos( cnField ) else nNum := cnField endif if nNum > 0 .AND. nNum <= ::nNumfields // Value := __objsendmsg(Self,::aFieldStruct[nNum][MYSQL_FS_NAME]) Value := ::aRow[ nNum ] // Char fields are padded with spaces since a real .dbf field would be if ::FieldType( nNum ) == "C" return PadR( Value, ::aFieldStruct[ nNum ][ MYSQL_FS_LENGTH ] ) else return Value endif endif return nil METHOD FieldLen(nNum) CLASS TMySQLQuery if nNum > 0 .AND. nNum <= ::nNumFields return ::aFieldStruct[ nNum ][ MYSQL_FS_LENGTH ] endif return 0 METHOD FieldDec( nNum ) CLASS TMySQLQuery if nNum > 0 .AND. nNum <= ::nNumFields return ::aFieldStruct[ nNum ][ MYSQL_FS_DECIMALS ] endif return 0 METHOD FieldType( nNum ) CLASS TMySQLQuery local cType := "U" if nNum >= 1 .AND. nNum <= ::nNumFields cType := SQL2ClipType( ::aFieldStruct[ nNum ][ MYSQL_FS_TYPE ] ) endif return cType METHOD Locate( cFieldName, Value, bPartialKey, bSoftSeek ) CLASS TMySQLQuery local nRecPrec := ::recno(), bFound := .F. //bSoftSeek cause the record pointer to be moved to the next record if bSoftSeek == NIL ; bSoftSeek := .F. ; endif if bPartialKey == NIL ; bPartialKey := .T. ; endif ::gotop() while ! ::eof() bFound := (::FieldGet(::FieldPos(cFieldName)) == Value) .or. ((::FieldGet(::FieldPos(cFieldName)) = Value) .and. bPartialKey) if !bFound .and. ((::FieldGet(::FieldPos(cFieldName)) > Value) .and. bSoftSeek) bFound := .T. endif if bFound exit endif ::skip() enddo if !bFound ::goto(nRecPrec) endif return bFound /* ----------------------------------------------------------------------------------------*/ // A Table is a query without joins; this way I can Insert() e Delete() rows. // NOTE: it's always a SELECT result, so it will contain a full table only if // SELECT * FROM ... was issued CLASS TMySQLTable FROM TMySQLQuery DATA cTable // name of table DATA aOldValue // keeps a copy of old value METHOD New( nSocket, cQuery, cTableName, loRow ) METHOD GetRow( nRow, loRow, lSkip ) METHOD Skip( nRow ) METHOD Update( oRow ) // Gets an oRow and updates changed fields METHOD Save( oRow ) INLINE ::Update( oRow ) METHOD Delete( oRow ) // Deletes passed row from table METHOD Append( oRow ) // Inserts passed row into table METHOD GetBlankRow( loRow ) // Returns an empty row with all available fields empty METHOD Blank( loRow ) INLINE ::GetBlankRow( loRow ) METHOD FieldPut( cnField, Value ) // field identifier, not only a number METHOD Refresh() METHOD MakePrimaryKeyWhere() // returns a WHERE x=y statement which uses primary key (if available) ENDCLASS METHOD New(nSocket, cQuery, cTableName, loRow) CLASS TMySQLTable Local xValue super:New(nSocket, AllTrim(cQuery), loRow) ::cTable := Lower(cTableName) ::aOldValue := Array( ::nNumFields ) for each xValue in ::aOldValue xValue := ::fieldget( HB_EnumIndex() ) next return Self METHOD GetRow( nRow, loRow, lSkip ) CLASS TMySQLTable local oRow := super:GetRow( nRow, loRow, lSkip ), xValue if oRow <> NIL oRow:cTable := ::cTable endif ::aOldvalue := Array( ::nNumFields ) for each xValue in ::aOldValue xValue := ::fieldget( HB_EnumIndex() ) next return oRow METHOD Skip(nRow) CLASS TMySQLTable Local xValue, nSkipRows nSkipRows := super:skip(nRow) for each xValue in ::aOldValue xValue := ::fieldget( HB_EnumIndex() ) next return nSkipRows /* Creates an update query for changed fields and submits it to server */ METHOD Update( oRow ) CLASS TMySQLTable local cUpdateQuery := "UPDATE " + ::cTable + " SET " local xValue ::lError := .F. // default Current row if oRow == nil for each xValue in ::aOldValue if xValue == NIL .or. xValue <> ::FieldGet( HB_EnumIndex() ) cUpdateQuery += ::aFieldStruct[ HB_EnumIndex() ][MYSQL_FS_NAME] + "=" + ClipValue2SQL(::FieldGet( HB_EnumIndex() ),::FieldType( HB_EnumIndex() )) + "," endif next // no Change if right(cUpdateQuery,4)=="SET "; return !::lError; end // remove last comma cUpdateQuery := Left(cUpdateQuery, Len(cUpdateQuery) -1) cUpdateQuery += ::MakePrimaryKeyWhere() // alert( cUpdateQuery ) if sqlQuery( ::nSocket, cUpdateQuery ) == 0 ::refresh() for each xValue in ::aOldValue xValue := ::fieldget( HB_EnumIndex() ) next else ::lError := .T. endif else WITH OBJECT oRow if :cTable == ::cTable for each xValue in :aRow if :aDirty[ HB_EnumIndex() ] cUpdateQuery += :aFieldStruct[ HB_EnumIndex() ][ MYSQL_FS_NAME ] + "=" + ClipValue2SQL( :aRow[ HB_EnumIndex() ], :FieldType( HB_EnumIndex() ) ) + "," endif next // remove last comma cUpdateQuery := Left( cUpdateQuery, Len(cUpdateQuery ) - 1 ) cUpdateQuery += :MakePrimaryKeyWhere() // alert( cUpdateQuery ) if sqlQuery( ::nSocket, cUpdateQuery ) == 0 // All values are commited Afill( :aDirty , .F. ) Afill( :aOldValue, nil ) else ::lError := .T. endif endif END // WITH endif return !::lError METHOD Delete( oRow ) CLASS TMySQLTable local cDeleteQuery := "DELETE FROM " + ::cTable, xValue // is this a row of this table ? if oRow == nil cDeleteQuery += ::MakePrimaryKeyWhere() if sqlQuery( ::nSocket, cDeleteQuery ) == 0 ::lError := .F. // ::nCurRow-- ::refresh() for each xValue in ::aOldValue xValue := ::fieldget( HB_EnumIndex() ) next else ::lError := .T. endif else WITH OBJECT oRow if :cTable == ::cTable cDeleteQuery += :MakePrimaryKeyWhere() if sqlQuery( ::nSocket, cDeleteQuery ) == 0 ::lError := .F. else ::lError := .T. endif endif END // WITH Endif return !::lError // Adds a row with values passed into oRow METHOD Append( oRow ) CLASS TMySQLTable local cInsertQuery := "INSERT INTO " + ::cTable + " (" local xValue, lResult:= .F. // default Current row if oRow == nil // field names for each xValue in ::aFieldStruct if xValue[ MYSQL_FS_FLAGS ] <> AUTO_INCREMENT_FLAG cInsertQuery += xValue[ MYSQL_FS_NAME ] + "," endif next // remove last comma from list cInsertQuery := Left( cInsertQuery, Len( cInsertQuery ) - 1 ) + ") VALUES (" // field values for each xValue in ::aFieldStruct if xValue[ MYSQL_FS_FLAGS ] <> AUTO_INCREMENT_FLAG cInsertQuery += ClipValue2SQL( ::FieldGet(HB_EnumIndex() ), ::FieldType(HB_EnumIndex()) ) + "," endif next // remove last comma from list of values and add closing parenthesis cInsertQuery := Left( cInsertQuery, Len(cInsertQuery) - 1 ) + ")" // alert( cInsertQuery ) if sqlQuery( ::nSocket, cInsertQuery ) == 0 ::refresh() for each xValue in ::aOldValue xValue := ::fieldget( HB_EnumIndex() ) next lResult:= .T. else ::lError := .T. endif else WITH OBJECT oRow if :cTable == ::cTable // field names for each xValue in :aFieldStruct if xValue[ MYSQL_FS_FLAGS ] <> AUTO_INCREMENT_FLAG cInsertQuery += xValue[ MYSQL_FS_NAME ] + "," endif next // remove last comma from list cInsertQuery := Left( cInsertQuery, Len( cInsertQuery ) - 1 ) + ") VALUES (" // field values for each xValue in :aRow if :aFieldStruct[ HB_EnumIndex() ][ MYSQL_FS_FLAGS ] <> AUTO_INCREMENT_FLAG cInsertQuery += ClipValue2SQL( xValue, :FieldType(HB_EnumIndex()) ) + "," endif next // remove last comma from list of values and add closing parenthesis cInsertQuery := Left( cInsertQuery, Len( cInsertQuery ) - 1 ) + ")" // alert( cInsertQuery ) if sqlQuery( ::nSocket, cInsertQuery ) == 0 lResult:= .T. else ::lError := .T. endif endif END // WITH Endif return lResult METHOD GetBlankRow( loRow ) CLASS TMySQLTable local cType local xValue Default loRow to ::loRow for each xValue in ::aRow cType := SQL2ClipType( ::aFieldStruct[ HB_EnumIndex() ][ MYSQL_FS_TYPE ] ) switch cType case "C" ::aOldValue[ HB_EnumIndex() ] := xValue := SPACE(::aFieldStruct[ HB_EnumIndex() ][ MYSQL_FS_LENGTH ]) exit case "M" case "B" ::aOldValue[ HB_EnumIndex() ] := xValue := "" exit case "N" case "I" ::aOldValue[ HB_EnumIndex() ] := xValue := 0 exit case "L" ::aOldValue[ HB_EnumIndex() ] := xValue := .F. exit case "D" ::aOldValue[ HB_EnumIndex() ] := xValue := CToD("") exit default ::aOldValue[ HB_EnumIndex() ] := xValue := nil end next if loRow return TMySQLRow():New( ::aRow, ::aFieldStruct, ::cTable ) endif return nil METHOD FieldPut( cnField, Value ) CLASS TMySQLTable local nNum if ValType( cnField ) == "C" nNum := ::FieldPos( cnField ) else nNum := cnField endif if nNum > 0 .AND. nNum <= ::nNumFields // if Valtype( Value ) == Valtype( ::FieldGet( nNum ) ) .OR. ::Fieldget( nNum ) == NIL ) if Valtype( Value ) == Valtype( ::aRow[ nNum ] ) .OR. ::aRow[ nNum ] == NIL // if it is a char field remove trailing spaces if ValType( Value ) == "C" Value := RTrim( Value ) endif ::aRow[ nNum ] := Value return Value endif endif return nil METHOD Refresh() CLASS TMySQLTABLE local rc // free present result handle sqlFreeR( ::nResultHandle ) ::lError := .F. if ( rc := sqlQuery( ::nSocket, ::cQuery ) ) == 0 // save result set ::nResultHandle := sqlStoreR( ::nSocket ) ::nNumRows := sqlNRows( ::nResultHandle ) // NOTE: I presume that number of fields doesn't change (that is nobody alters this table) between // successive refreshes of the same // But row number could very well change if ::nCurRow > ::nNumRows ::nCurRow := ::nNumRows endif ::getRow( ::nCurRow ) else ::lError := .T. endif return !::lError // returns a WHERE x=y statement which uses primary key (if available) METHOD MakePrimaryKeyWhere() CLASS TMySQLTable local ni, cWhere := " WHERE ", aField for each aField in ::aFieldStruct // search for fields part of a primary key if ( sqlAND( aField[ MYSQL_FS_FLAGS ], PRI_KEY_FLAG ) == PRI_KEY_FLAG ) .OR.; ( sqlAND( aField[ MYSQL_FS_FLAGS ], MULTIPLE_KEY_FLAG ) == MULTIPLE_KEY_FLAG ) cWhere += aField[ MYSQL_FS_NAME ] + "=" // if a part of a primary key has been changed, use original value cWhere += ClipValue2SQL( ::aOldValue[ HB_EnumIndex() ], ::FieldType(HB_EnumIndex()) ) cWhere += " AND " endif next // remove last " AND " cWhere := Left( cWhere, Len( cWhere ) - 5 ) return cWhere /* ----------------------------------------------------------------------------------------*/ // Every available MySQL server CLASS TMySQLServer DATA nSocket // connection handle to server (currently pointer to a MYSQL structure) DATA cServer // server name DATA cDBName // Selected DB DATA cUser // user accessing db DATA cPassword // his/her password DATA lError // .T. if occurred an error DATA nPort DATA nFlags DATA cCreateQuery METHOD New( cServer, cUser, cPassword, nPort, nFlags ) // Opens connection to a server, returns a server object METHOD Destroy() INLINE sqlClose( ::nSocket ), Self // Closes connection to server METHOD SelectDB( cDBName ) // Which data base I will use for subsequent queries METHOD CreateDatabase( cDataBase ) // Create an New Mysql Database METHOD ListDBs() INLINE sqlListDB(::nSocket) // returns an array with list of data bases available METHOD DBExist( cDB ) INLINE ( cDB IN ::ListDBs() ) // return .T. if cTable exist in the database METHOD CreateTable( cTable, aStruct, cPrimaryKey, cUniqueKey, cAuto) // Create new table using the same syntax of dbCreate() METHOD DeleteTable( cTable ) // delete table METHOD TableExist( cTable ) INLINE ( cTable IN ::ListTables() ) // return .T. if cTable exist in the database METHOD ListTables() INLINE sqlListTbl(::nSocket) // returns an array with list of available tables in current database METHOD TableStruct( cTable ) // returns a structure array compatible with clipper's dbStruct() ones METHOD CreateIndex( cName, cTable, aFNames, lUnique ) // Create an index (unique) on field name(s) passed as an array of strings aFNames METHOD DeleteIndex( cName, cTable ) // Delete index cName from cTable METHOD Query( cQuery, loRow ) // Gets a textual query and returns a TMySQLQuery or TMySQLTable object METHOD NetErr() INLINE ::lError // Returns .T. if something went wrong METHOD Error() // Returns textual description of last error ENDCLASS METHOD New( cServer, cUser, cPassword, nPort, nFlags ) CLASS TMySQLServer ::cServer := cServer ::cUser := cUser ::cPassword := cPassword ::nPort := nPort ::nFlags := nFlags ::nSocket := sqlConnect(cServer, cUser, cPassword, nPort, nFlags ) ::lError := .F. if ::nSocket == 0 ::lError := .T. endif return Self METHOD SelectDB( cDBName ) CLASS TMySQLServer ::lError := .F. if sqlSelectD( ::nSocket, cDBName ) != 0 // table not exist ::cDBName :="" ::lError := .T. else // table exist ::cDBName := cDBName ::lError := .F. return .T. endif return .F. METHOD CreateDatabase ( cDataBase ) CLASS TMySQLServer local cCreateQuery := "CREATE DATABASE "+ lower( cDatabase ) if sqlQuery( ::nSocket, cCreateQuery ) == 0 return .T. endif return .F. // NOTE: OS/2 port of MySQL is picky about table names, that is if you create a table with // an upper case name you cannot alter it (for example) using a lower case name, this violates // OS/2 case insensibility about names METHOD CreateTable( cTable, aStruct, cPrimaryKey, cUniqueKey, cAuto ) CLASS TMySQLServer /* NOTE: all table names are created with lower case */ local aField // returns NOT NULL if extended structure has DBS_NOTNULL field to true local cNN := {| aArr | iif( Len( aArr ) > DBS_DEC, iif( aArr[ DBS_NOTNULL ], " NOT NULL ", "" ), "" ) } ::cCreateQuery := "CREATE TABLE " + Lower(cTable) + " (" for each aField in aStruct switch aField[ DBS_TYPE ] case "C" ::cCreateQuery += aField[ DBS_NAME ] + " char(" + AllTrim(Str(aField[DBS_LEN])) + ")" + Eval(cNN, aField)+ if(aField[DBS_NAME]==cPrimaryKey," NOT NULL ",'' )+ "," exit case "M" ::cCreateQuery += aField[ DBS_NAME ] + " text" + Eval(cNN, aField) + "," exit case "N" if aField[ DBS_DEC ] == 0 .and. aField[ DBS_LEN ] <= 18 do case case aField[ DBS_LEN ] <= 4 ::cCreateQuery += aField[ DBS_NAME ] + " smallint(" + AllTrim( Str( aField[ DBS_LEN ] ) ) + ")" case aField[ DBS_LEN ] <= 6 ::cCreateQuery += aField[ DBS_NAME ] + " mediumint(" + AllTrim( Str( aField[ DBS_LEN ] ) ) + ")" case aField[ DBS_LEN ] <= 9 ::cCreateQuery += aField[ DBS_NAME ] + " int(" + AllTrim( Str( aField[ DBS_LEN ] ) ) + ")" otherwise ::cCreateQuery += aField[ DBS_NAME ] + " bigint(" + AllTrim( Str( aField[ DBS_LEN ] ) ) + ")" endcase ::cCreateQuery += Eval( cNN, aField ) + if( aField[ DBS_NAME ] == cPrimaryKey, " NOT NULL ", "" ) + if( aField[ DBS_NAME ] == cAuto, " auto_increment ", "" ) + "," else ::cCreateQuery += aField[ DBS_NAME ] + " real(" + AllTrim( Str( aField[ DBS_LEN ] ) ) + "," + AllTrim( Str( aField[ DBS_DEC ] ) ) + ")" + Eval( cNN, aField ) + "," endif exit case "D" ::cCreateQuery += aField[ DBS_NAME ] + " date " + Eval( cNN, aField ) + "," exit case "L" ::cCreateQuery += aField[ DBS_NAME ] + " tinyint " + Eval( cNN, aField ) + "," exit case "B" ::cCreateQuery += aField[ DBS_NAME ] + " mediumblob " + Eval( cNN, aField ) + "," exit case "I" ::cCreateQuery += aField[ DBS_NAME ] + " mediumint " + Eval( cNN, aField ) + "," exit case "T" ::cCreateQuery += aField[ DBS_NAME ] + " timestamp(" + AllTrim( Str( aField[ DBS_LEN ] ) ) + ")" + Eval( cNN, aField ) + "," exit default ::cCreateQuery += aField[ DBS_NAME ] + " char(" + AllTrim(Str(aField[DBS_LEN])) + ")" + Eval( cNN, aField ) + "," end next if cPrimarykey != NIL ::cCreateQuery += ' PRIMARY KEY (' + cPrimaryKey + '),' endif if cUniquekey != NIL ::cCreateQuery += ' UNIQUE ' + cUniquekey + ' (' + cUniqueKey + '),' endif // remove last comma from list ::cCreateQuery := Left( ::cCreateQuery, Len( ::cCreateQuery ) - 1 ) + ");" if sqlQuery( ::nSocket, ::cCreateQuery ) == 0 return .T. else ::lError := .T. endif return .F. METHOD CreateIndex( cName, cTable, aFNames, lUnique ) CLASS TMySQLServer local cCreateQuery := "CREATE " local cField default lUnique to .F. if lUnique cCreateQuery += "UNIQUE INDEX " else cCreateQuery += "INDEX " endif cCreateQuery += cName + " ON " + Lower( cTable ) + " (" for each cField in aFNames cCreateQuery += cField + "," next // remove last comma from list cCreateQuery := Left( cCreateQuery, Len( cCreateQuery ) - 1 ) + ")" if sqlQuery( ::nSocket, cCreateQuery ) == 0 return .T. endif return .F. METHOD DeleteIndex( cName, cTable ) CLASS TMySQLServer local cDropQuery := "DROP INDEX " + cName + " FROM " + Lower( cTable ) if sqlQuery( ::nSocket, cDropQuery ) == 0 return .T. endif return .F. METHOD DeleteTable( cTable ) CLASS TMySQLServer local cDropQuery := "DROP TABLE " + Lower( cTable ) if sqlQuery( ::nSocket, cDropQuery ) == 0 return .T. endif return .F. METHOD Query( cQuery, loRow ) CLASS TMySQLServer local oQuery, cTableName, i, cUpperQuery, nNumTables, cToken default cQuery to "" cUpperQuery := Upper( AllTrim( cQuery ) ) i := 1 nNumTables := 1 while (cToken := __StrToken( cUpperQuery, i++, " " ) ) <> "FROM" .AND. !Empty( cToken ) enddo // first token after "FROM" is a table name // NOTE: SubSelects ? cTableName := __StrToken( cUpperQuery, i++, " " ) while ( cToken := __StrToken( cUpperQuery, i++, " " ) ) <> "WHERE" .AND. !Empty( cToken ) // do we have more than one table referenced ? if cToken == "," .OR. cToken == "JOIN" nNumTables++ endif enddo if nNumTables == 1 oQuery := TMySQLTable():New( ::nSocket, cQuery, cTableName, loRow ) else oQuery := TMySQLQuery():New(::nSocket, cQuery, loRow ) endif if oQuery:NetErr() ::lError := .T. endif return oQuery METHOD Error() CLASS TMySQLServer ::lError := .F. return iif(::nSocket > 0, sqlGetErr(::nSocket), "No connection to server") /* TOFIX: Conversion creates a .dbf with fields of wrong dimension (often) */ METHOD TableStruct( cTable ) CLASS TMySQLServer local nRes, aField, aStruct, aSField, i aStruct := {} /* TODO: rewrite for MySQL */ nRes := sqlListF( ::nSocket, cTable ) if nRes > 0 for i := 1 to sqlNumFi( nRes ) aField := sqlFetchF( nRes ) aSField := Array( DBS_DEC ) // don't count indexes as real fields // if aField[ MYSQL_FS_TYPE ] <= MYSQL_LAST_REAL_TYPE aSField[ DBS_NAME ] := Left( aField[ MYSQL_FS_NAME ], 10 ) aSField[ DBS_DEC ] := 0 asField[ DBS_TYPE ] := SQL2ClipType( aField[ MYSQL_FS_TYPE ] ) switch aField[ MYSQL_FS_TYPE ] case MYSQL_TINY_TYPE aSField[ DBS_TYPE ] := "L" aSField[ DBS_LEN ] := 1 exit case MYSQL_SHORT_TYPE aSField[ DBS_TYPE ] := "N" aSField[ DBS_LEN ] := Min( 6, aField[ MYSQL_FS_LENGTH ] ) exit case MYSQL_INT24_TYPE aSField[ DBS_TYPE ] := "N" aSField[ DBS_LEN ] := Min( 8, aField[ MYSQL_FS_LENGTH ] ) exit case MYSQL_LONG_TYPE aSField[ DBS_TYPE ] := "N" aSField[ DBS_LEN ] := Min( 11, aField[ MYSQL_FS_LENGTH ] ) exit case MYSQL_LONGLONG_TYPE aSField[ DBS_TYPE ] := "N" aSField[ DBS_LEN ] := Min( 20, aField[ MYSQL_FS_LENGTH ] ) exit case MYSQL_FLOAT_TYPE case MYSQL_DOUBLE_TYPE case MYSQL_DECIMAL_TYPE aSField[ DBS_TYPE ] := "N" aSField[ DBS_LEN ] := aField[ MYSQL_FS_LENGTH ] aSFIeld[ DBS_DEC ] := aField[ MYSQL_FS_DECIMALS ] exit /* case FIELD_TYPE_INT24 aSField[ DBS_TYPE ] := "I" aSField[ DBS_LEN ] := aField[ MYSQL_FS_LENGTH ] aSFIeld[ DBS_DEC ] := aField[ MYSQL_FS_DECIMALS ] exit */ case MYSQL_STRING_TYPE case MYSQL_VAR_STRING_TYPE case MYSQL_DATETIME_TYPE case MYSQL_TIME_TYPE aSField[ DBS_TYPE ] := "C" aSField[ DBS_LEN ] := aField[ MYSQL_FS_LENGTH ] exit case MYSQL_DATE_TYPE aSField[ DBS_TYPE ] := "D" aSField[ DBS_LEN ] := 8 exit case MYSQL_MEDIUM_BLOB_TYPE aSField[ DBS_TYPE ] := "B" aSField[ DBS_LEN ] := aField[ MYSQL_FS_LENGTH ] exit case MYSQL_BLOB_TYPE aSField[ DBS_TYPE ] := "M" aSField[ DBS_LEN ] := 10 exit case MYSQL_TIMESTAMP_TYPE aSField[ DBS_TYPE ] := "N" aSField[ DBS_LEN ] := aField[ MYSQL_FS_LENGTH ] exit default aSField[ DBS_TYPE ] := "C" aSField[ DBS_LEN ] := aField[ MYSQL_FS_LENGTH ] end AAdd( aStruct, aSField ) // endif next sqlFreeR( nRes ) endif return aStruct // Returns an SQL string with clipper value converted ie. Date() -> "'YYYY-MM-DD'" static function ClipValue2SQL(Value, cType) local cValue := "" // local cDateFormat := Lower( Set( 4 ) ) Default cType to ValType( Value ) switch cType case "N" case "I" cValue := AllTrim( Str( Value ) ) exit case "D" if !Empty( Value ) // MySQL dates are like YYYY-MM-DD or YYYYMMDD cValue := "'" + Transform( Dtos( Value ), "@R 9999-99-99" ) + "'" /* if cDateFormat == 'mm-dd-yyyy' // USA cValue := "'"+PadL(Month(Value), 2, "0") + '-'+ PadL(Day(Value), 2, "0") + "-" + Str(Year(Value), 4) + "'" elseif cDateFormat == 'dd/mm/yyyy' // BRITISH ou FRENCH //cValue := "'"+PadL(Day(Value), 2, "0") + "/" + PadL(Month(Value), 2, "0") + "/" + Str(Year(Value), 4) + "'" cValue := "'"+Str(Year(Value), 4) + "-" + PadL(Month(Value), 2, "0") + "-" + PadL(Day(Value), 2, "0") + "'" elseif cDateFormat == 'yyyy.mm.dd' // ANSI cValue := "'"+Str(Year(Value), 4) + "." + PadL(Month(Value), 2, "0") + "." + PadL(Day(Value), 2, "0") + "'" elseif cDateFormat == 'dd.mm.yyyy' //GERMAN cValue := "'"+PadL(Day(Value), 2, "0") + "." + PadL(Month(Value), 2, "0") + "." + Str(Year(Value), 4) + "'" elseif cDateFormat == 'dd-mm-yyyy' //ITALIAN cValue := "'"+PadL(Day(Value), 2, "0") + "-" + PadL(Month(Value), 2, "0") + "-" + Str(Year(Value), 4) + "'" elseif cDateFormat == 'yyyy/mm/dd' //JAPAN cValue := "'"+Str(Year(Value), 4) + "/" + PadL(Month(Value), 2, "0") + "/" + PadL(Day(Value), 2, "0") + "'" elseif cDateFormat == 'mm/dd/yyyy' // AMERICAN cValue := "'"+Str(Year(Value), 4) + "/" + PadL(Month(Value), 2, "0") + "/" + PadL(Day(Value), 2, "0") + "'" endif */ else cValue := "''" endif exit case "C" case "M" case "B" IF Empty( Value) cValue := "''" ELSE cValue := "'" + DATATOSQL( value ) + "'" ENDIF exit case "L" cValue := AllTrim( Str( iif(Value, 1, 0 ) ) ) exit case "T" cValue := iif( Value < 0, "NULL", Alltrim( str( Value ) ) ) exit default cValue := "''" // NOTE: Here we lose values we cannot convert end return cValue static function SQL2ClipType( nType ) switch nType case MYSQL_TINY_TYPE Return "L" case MYSQL_SHORT_TYPE case MYSQL_LONG_TYPE case MYSQL_LONGLONG_TYPE case MYSQL_FLOAT_TYPE case MYSQL_DOUBLE_TYPE case MYSQL_DECIMAL_TYPE Return "N" case MYSQL_DATE_TYPE Return "D" case MYSQL_BLOB_TYPE Return "M" case MYSQL_VAR_STRING_TYPE case MYSQL_STRING_TYPE case MYSQL_DATETIME_TYPE case MYSQL_TIME_TYPE Return "C" case MYSQL_INT24_TYPE Return "I" case MYSQL_MEDIUM_BLOB_TYPE Return "B" case MYSQL_TIMESTAMP_TYPE Return "T" end Return "U" /* Given a three letter month name gives back month number as two char string (ie. Apr -> 04) */ static function NMonth(cMonthValue) static cMonths := {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Ago", "Sep", "Oct", "Nov", "Dec" } local nMonth nMonth := AScan(cMonths, cMonthValue) return PadL(nMonth, 2, "0") static function ARRAYBLOCK( nIndex ) Local bBlock bBlock := {|Self, x | iif( PCount() == 1, ::aRow[ nIndex ], ::aRow[ nIndex ] := x ) } return bBlock
  20. O problema é que a resposta de STATUS do SEFAZ não é completa, pois se o link tiver ativo ele vai responder OK, mas nem todos os serviços podem estar ativos. []s,
  21. Mano, tem rejeição nesta lista que parece coisa de português, uma coisa é rejeitar na validação (Consistência na validação), ou é rejeitar no envio,. Parece até piada. Rejeição 925: NF-e com identificação de estrangeiro e inscrição estadual informada para destinatário Rejeição 926: Operação com Exterior e país de destino igual a Brasil. Rejeição 936: Razão Social do emitente diverge do informado no cadastro da SEFAZ. - Essa chega a ser um absurdo, pois com tantas informações como Cnpj e IE e ainda vão criticar o nome da empresa. []s,
  22. João, boa noite. Este registro eu gerava em MG, quando havia diferença de alíquota (Famoso DIFAL de hoje), como o SPED FISCAL é exclusivo das UF's, então MG, criou há muito tempo a tabela de códigos para essa situação, como não faço mais O sped para o cliente de MG há muito tempo, então não sei como está e como será em relação ao campo cBenef do layout da NF-e 4.0. Sei que algumas UF's havia divulgado as suas tabelas para isso, mas SP, até o tempo que eu gerava SPED's para os meus clientes não tinha. O resultado deste registro é informado na apuração. []s,
×
×
  • Create New...