You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
gnucash/doc/sgml/pt_PT/xacc-repdev.sgml

448 lines
17 KiB

<article id="xacc-repdev">
<artheader>
<title>Desenvolvimento de Relatórios</title>
<author>
<firstname>Christopher</firstname>
<surname>Browne</surname>
</author>
</artheader>
<sect1 id="xacc-reportdev"> <title>Desenvolvimento de Relatórios</title>
<para> Os relatórios do <application>GnuCash</application> são gerados
de uma forma que é bastante retrospectiva dos <ulink
url="http://hoohoo.ncsa.uiuc.edu/cgi/"> CGI </ulink> da web; envolve:
<itemizedlist>
<listitem><para> Escrever programas que gerem "janelas de opções".
</para>
<para> Ao contrário da aproximação CGI, as opções do <application>GnuCash
</application> acabam por gerar directamente widgets GNOME, e não utilizam
etiquetas de FORMs HTML. As semelhanças são, no entanto, bastante grandes
já que ambos os sistemas de opções involvem:
<itemizedlist>
<listitem><para> Construir uma lista de propriedades que descreve opções e
valores de defeito;</para></listitem>
<listitem><para> Submeter essa lista de propriedades para que o utilizador
faça modificações;</para></listitem>
<listitem><para> Retornar outra lista de propriedades contendo as modificações
do utilzador.</para></listitem>
</itemizedlist></para></listitem>
<listitem><para> Escrever programas que obtenham dados da aplicação,
baseados na lista de propriedades das opções, e depois gerem resultados
em HTML.</para>
<para> Muitas aplicações web produzem HTML de integridade questionável
visto o programador gerar HTML na forma atabalhoada de apenas imprimir
comandos que possam conter um tipo de dados com "pseudo-etiquetas".
Por contraste, <application>GnuCash</application> utiliza uma estrutura
de registos orientada para o HTML que torna mais difícil construir
<emphasis> mau </emphasis> HTML do que o torna escrever HTML correcto.
</para></listitem>
</itemizedlist></para>
<para> Esta apresentação irá assumir que o leitor já está de uma forma
genérica familiarizado com o Scheme, particularmente com os seguintes
conceitos:
<itemizedlist>
<listitem><para> Ligar valores e funções utilizando
<function>define</function></para>
<para> Como em:
<screen>
(define *value-x* 25)
(define *value-y* 30)
(define *string-a* "Aqui está uma string!")
(define *string-b* "Uma string com uma aspa \" embebida")
(define (add-1 x)
(+ x 1))
</screen></para>
</listitem>
<listitem><para> Definir ligações locais utilizando
<function id="let">let</function> e <function>let</function>
</para>
<screen>
> (define let-to-hide-stuff
(lambda (x y z)
(let ((x 25);; Local binding of x inside the let
(w 11))
(display "Dentro do let, x é:") (display x) (newline)
(display "E w apenas existe dentro do let como ") (display w)
(newline)
(display "Adicionar x, y, z, w dentro do let:")
(display (+ x y z w)) (newline))
(display "Agora, fora do let:") (newline)
(display "x é:") (display x) (newline)
(display "y é:") (display y) (newline)
(display "z é:") (display z) (newline)
(display "w é:") (display w) (newline)))
> (let-to-hide-stuff 10 20 30)
> (let-to-hide-stuff 10 20 30)
Dentro do let, x é:25
E w apenas existe dentro do let como 11
Adicionar x, y, z, w dentro do let:86
Agora, fora do let:
x é:10
y é:20
z é:30
reference to undefined identifier: w
w é:>
</screen>
</listitem>
<listitem><para> Definir listas utilizando <function>list</function></para>
<para> Como em:
<screen>
> (list 1 2 3 "four" 'five)
(1 2 3 "four" five)
> '(1 2 3 "four" five)
(1 2 3 "four" five)
</screen></para>
</listitem>
<listitem><para> Representar funções anónimas utilizando
<function>lambda</function></para>
<para> A função <function>add-1</function> mostrada anteriormente é
<emphasis>na verdade</emphasis> definida como:
<screen>
(define add-1
(lambda (x) (+ x 1)))
</screen></para>
</listitem>
<listitem><para> A estrutura de controlo <function>if</function></para>
</listitem>
<listitem><para> Utilizar <function>map</function> para aplicar uma função a todos
os membros de uma lista, produzindo outra lista, como em:
<screen>
> (map (lambda (x) (+ x 1)) '(1 2 3 4))
(2 3 4 5)
</screen>
ou
<screen>
> (map (lambda (s n) (string-append s ":" (number->string n)))
'("one" "two" "three" "four") '(1 2 3 4))
("one:1" "two:2" "three:3" "four:4")
</screen></para></listitem>
</itemizedlist></para>
<para> Se os significados de alguns destes não são muito claros, veja as
referências na secção sobre <link linkend="xacc-schemedocs"> Documentação
Scheme</link>, e tente executar código como o acima utilizando Guile.</para>
<sect2> <title>Visão Geral de Relatórios</title>
<para> Um relatório do GnuCash é adicionado ao sistena utilizando a função
<function>gnc:define-report</function>, para a qual são passados os seguintes
parâmetros:
<itemizedlist>
<listitem><para> <structfield>versão</structfield></para>
<para> Este é um número de versão; actualmente não é utilizado para
fazer nada particularmente inteligente.</para></listitem>
<listitem><para> <structfield>nome</structfield></para>
<para> Este é um nome <emphasis>não-traduzido</emphasis> para o
relatório que é notavelmente utilizado para disponibilizar o nome
que será adicionado ao menu de relatórios do <application>GnuCash
</application>.</para></listitem>
<listitem><para> <link linkend="options-generator"> <structfield>
gerador de opções </structfield> </link>
</para>
<para> Este argumento é uma função que não leva parâmetros, e gera um conjunto
de opções que serão utilizadas para apresentar uma janela que o utilizador
pode utilizar para seleccionar valores para os parâmetros do relatório.</para>
<para> Isto tipicamente irá incluir coisas como intrevalos de datas e listas
de contas, para determinar que dados deverão ser seleccionados para o relatório,
bem como outros controlos que determinam como os dados irão ser visualizados. </para>
</listitem>
<listitem><para> <link linkend="renderer">
<structfield>visualizador</structfield>
</link>
</para>
<para> O "visualizador" faz o trabalho de gerar o relatório. Aceita
uma "base de dados" de opções, tal como a gerada pelo <structfield>
gerador de opções </structfield>, obtem os dados correspondentes do
motor do <application>GnuCash</application>, e gera, como resultado,
um objecto do tipo <sgmltag> documento html </sgmltag>, que é o que o
motor de relatórios do <application>GnuCash</application> sabe como
apresentar.</para></listitem>
</itemizedlist></para>
<para> Um exemplo trivial poderá assemelhar-se ao seguinte:
<informalexample>
<screen>
(let ()
(define (options-generator)
(let ((options (gnc:new-options))) ;;; Criar nova lista de opções
options)) ;;; Devolve-la
(define (renderer options)
(let ((document (gnc:make-html-document)))
document)) ;;; Gera um documento vazio
(gnc:define-report
'version 1
'name (N_ "Trivial Example")
'options-generator options-generator
'renderer renderer))
</screen>
</informalexample></para>
<para> Note que os relatórios são tipicamente definidos dentro de um ambiente <link linkend="let"> <function> let </function> </link>; as "funções
de trabalho" serão assim todas invisíveis para o código fora do
ambiente <function> let </function>, o que significa que não precisará
de se preocupar em criar nomes de funções únicos. Apenas o nome do relatório
tem forçosamente de ser único. </para>
<para> Desde que cada relatório esteja do mesmo modo envolto num ambiente
<function> let </function>, você poderia chamar a <emphasis> todas </emphasis>
as funções de "renderização" <function> rederizar </function> sem causar
quaisquer conflitos.</para>
</sect2>
<sect2 id="options-generator"> <title>A função de gerador de opções</title>
<para> O gerador de opções introduz um número adicional de funções
que são utilizadas para definir janelas de opções.
<screen>
(define (options-generator)
(let ((option-set (gnc:new-options))) <co id="newopts">
(gnc:options-add-report-date! <co id="optdate">
option-set pagename-general "End Date" "a")
(gnc:options-add-date-interval! <co id="optdaterng">
option-set pagename-general "From" "To" "a")
(gnc:options-add-interval-choice! <co id="optint">
option-set pagename-general
"Step Size" "b" 'YearDelta)
(gnc:options-add-account-levels! <co id="optacl">
option-set pagename-general
"Show Accounts down to Level" "c" 2)
(gnc:options-add-account-selection! <co id="optacc">
option-set pagename-general "Account Display Depth"
"Always show subaccounts" "Accounts" "a" 3
*LIST-OF-INCOME-AND-EXPENSE-ACCOUNTS*
options))
</screen>
<calloutlist>
<callout arearefs="newopts"> <para>
<function>gnc:new-options</function> cria um conjunto novo de opções,
vazio. Isto tem de ser executado primeiro; as funções seguintes necessitam
de ter um conjunto de opções a que se referir.</para> </callout>
<callout arearefs="optdate"> <para>
<function>gnc:options-add-report-date!</function> adiciona uma opção de
selecção que indica uma data única, geralmente utilizada como a data de
final.</para> </callout>
<callout arearefs="optdaterng"> <para>
<function>gnc:options-add-date-interval!</function> adiciona uma opção de
selecção que permite especificar um intrevalo de datas.</para></callout>
<callout arearefs="optint"> <para>
<function>gnc:options-add-interval-choice!</function> adiciona uma opção
de selecção que permite escolher entre vários intrevalos de tempo, incluindo
dias, semanas, quinzenas, meses, e anos.</para></callout>
<callout arearefs="optacl"> <para> <function>
gnc:options-add-account-levels!</function> adiciona uma opção que indica
até que profundidade um conjunto de níveis de contas deverá ser mostrado.</para></callout>
<callout arearefs="optacc"> <para> <function>
gnc:options-add-account-selection!</function> permite seleccionar um
conjunto de contas.</para> <para> Note que o último argumento é uma lista
de contas de onde seleccionar, o que significa ser necessário, a um determinado
ponto, <link linkend="filtacc">filtrar uma lista de contas relevantes</link>.</para>
</callout> </calloutlist></para>
<para> Existem ainda funções de opções adicionais:
<itemizedlist>
<listitem><para> <function>gnc:options-add-currency!</function> para
seleccionar uma moeda;</para></listitem>
<listitem><para> <function>gnc:options-add-plot-size!</function> para
controlar como um gráfico deverá ser dimensionado.</para></listitem>
</itemizedlist></para>
<para> Subjacentes a estas existem as seguintes funções base do "gerador
de opções" definidas em <filename>options-utilities.scm</filename>, que
podem ser utilizadas para criar novos tipos de opções:
<itemizedlist>
<listitem><para> <function>gnc:register-option</function></para></listitem>
<listitem><para> <function>gnc:make-date-option</function></para></listitem>
<listitem><para> <function>gnc:make-multichoice-option</function></para></listitem>
<listitem><para> <function>gnc:make-simple-boolean-option</function></para></listitem>
<listitem><para> <function>gnc:make-account-list-option</function></para></listitem>
<listitem><para> <function>gnc:make-currency-option</function></para></listitem>
<listitem><para> <function>gnc:make-number-range-option</function></para></listitem>
</itemizedlist></para></sect2>
<sect2 id="accessing-data"> <title>Aceder aos Dados do GnuCash</title>
<para> Existem vários formatos de dados que poderá querer aceder:
</para>
<itemizedlist>
<listitem><para> <link linkend="filtacc"> Informação de Contas </link></para></listitem>
<listitem><para> <link linkend="stockprices"> Preços de Acções </link></para></listitem>
<listitem><para> <link linkend="accoption"> Dados de Leitura de Opções </link></para></listitem>
</itemizedlist>
<sect3 id="filtacc"> <title> Aceder aos Dados do Motor </title>
<para> As funções utilizadas para aceder às várias formas de dados
contabilísticos podem ser encontradas no ficheiro <filename> src/g-wrap/gnc.html
</filename>. </para>
<note> <para> São necessários alguns exemplos aqui... </para> </note></sect3>
<sect3 id="accoption"> <title>Aceder a Dados de Opções</title>
<para> Functions <function>gnc:lookup-option</function>,
<function>gnc:report-options</function>, e
<function>gnc:option-value</function> são as funções cruciais
que mais provavelmente utilizará em <filename> src/scm/options.scm
</filename></para>
<para> Um excerto do <filename> src/scm/report/hello-world.scm
</filename> é o seguinte:
<screen>
;; Primeiro, construir algumas funções de apoio para procurar valores de opções.
(define (get-op section name)
(gnc:lookup-option (gnc:report-options report-obj) section name))
(define (op-value section name)
(gnc:option-value (get-op section name)))
;; O próximo passo é criar variáveis locais para todas as opções
;; específicas no conjunto de opções passado à função.
(let
((bool-val (op-value "Hello, World!" "Boolean Option"))
(mult-val (op-value "Hello, World!" "Multi Choice Option"))
(string-val (op-value "Hello, World!" "String Option"))
(date-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Just a Date Option")))
(date2-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Time and Date Option")))
(rel-date-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Relative Date Option")))
(combo-date-val (gnc:date-option-absolute-time
(op-value "Hello, World!" "Combo Date Option")))
(num-val (op-value "Hello, World!" "Number Option"))
(bg-color-op (get-op "Hello, World!" "Background Color"))
(txt-color-op (get-op "Hello, World!" "Text Color"))
(accounts (op-value "Hello Again" "An account list option"))
(list-val (op-value "Hello Again" "A list option"))
(crash-val (op-value "Testing" "Crash the report")))
(now-do-stuff-with-options))</screen>
</para></sect3>
<sect3 id="stockprices"> <title> Preços de Acções </title>
<warning>
<para> A base de dados de preços de acções está em desenvolvimento, pelo que
é um pouco sedo para ser específico sobre isto...</para> </warning></sect3></sect2>
<sect2 id="html-generation"> <title>Funções de Geração HTML</title>
<para> Os relatórios são gerados como uma árvore de registos <link linkend="guile">
Guile</link>, tendo como raíz um registo &lt;documento html&gt;, que consiste em
informação de estilos, um título, e uma lista de registos &lt;objecto html&gt que
consistem numa função de renderização e noutra lista de objectos.</para>
<para> Poderemos assim gerar um relatório simples:
<screen>
(define (build-simple-document)
(let* ((document (gnc:make-html-document))
;;; Aqui está um par de funções auxiliares
(addfpara (lambda (obj)
(gnc:html-document-add-object!
document
(gnc:make-html-text
(gnc:html-markup-p obj)))))
(addpara (lambda (text)
(addfpara
(gnc:html-markup/format text)))))
;;; Definir o título
(gnc:html-document-set-title! document (_ "Simple List of Values"))
;;; Adicionar um parágrafo de texto
(addpara
(_ "This is a simple report, starting with a paragraph of text"))
(addpara
(_ "Next, we calculate random values, adding them to a balance."))
(let loop
((balance 0))
(if (< balance 500)
(let ((newamt (- (random 500 200)))) ;;; Random number
(addfpara
(gnc:html-markup/format
(_ "Another random adjustment of %s yields %s")
(gnc:html-markup-tt (number->string newamt))
(gnc:html-markup-b (number->string balance))))
(loop (+ balance newamt)))))
document)) ;;; Finalmente, devolver o documento
</screen>
</para>
</sect2>
<sect2 id="renderer"> <title>A função de renderização</title>
<para> A função de renderização é onde as funções das secções anteriores
se juntam.
<itemizedlist>
<listitem><para> Recebe, como entrada, uma "base de dados" de opções geradas
assim que o utilizador adiciona os seus dados à janela produzida pelo
<link linkend="options-generator"> generador de opções </link>.</para></listitem>
<listitem><para> Utiliza essas opções para controlar como <link linkend="accessing-data">
aceder aos dados do GnuCash </link> </para> </listitem>
<listitem><para> Finalmente, a partir desses dados, <link linkend="html-generation"> gera
uma "base de dados" de texto HTML. </link></para></listitem> </itemizedlist></para>
<para> A fnção de renderização disponibiliza, como valor de retorno, a "base de dados
de HTML," que o <application>GnuCash</application> apresenta no visualizador de HTML.
<informalexample>
<screen>
(define (renderer options)
(let ((document (gnc:make-html-document)))
document)) ;;; Gera um documento vazio
</screen>
</informalexample></para></sect2>
<sect2> <title>Para Mais Informações</title>
<para> Se necessitar de mais informações, ou tiver desenvolvido um
relatório novo que possa ser útil para outros, por favor contacte a
lista de desenvolvimento do GnuCash em <email> gnucash-devel@gnucash.org </email>. </para>
<!-- Local variables: -->
<!-- sgml-parent-document: "gnucash.sgml" -->
<!-- End: --></sect2></sect1></article>