Desenvolvimento de RelatóriosChristopherBrowneDesenvolvimento de Relatórios Os relatórios do GnuCash são gerados
de uma forma que é bastante retrospectiva dos CGI da web; envolve:
Escrever programas que gerem "janelas de opções".
Ao contrário da aproximação CGI, as opções do GnuCash
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:
Construir uma lista de propriedades que descreve opções e
valores de defeito; Submeter essa lista de propriedades para que o utilizador
faça modificações; Retornar outra lista de propriedades contendo as modificações
do utilzador. Escrever programas que obtenham dados da aplicação,
baseados na lista de propriedades das opções, e depois gerem resultados
em HTML. 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, GnuCash utiliza uma estrutura
de registos orientada para o HTML que torna mais difícil construir
mau HTML do que o torna escrever HTML correcto.
Esta apresentação irá assumir que o leitor já está de uma forma
genérica familiarizado com o Scheme, particularmente com os seguintes
conceitos:
Ligar valores e funções utilizando
define Como em:
(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))
Definir ligações locais utilizando
let e let
> (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 é:>
Definir listas utilizando list Como em:
> (list 1 2 3 "four" 'five)
(1 2 3 "four" five)
> '(1 2 3 "four" five)
(1 2 3 "four" five)
Representar funções anónimas utilizando
lambda A função add-1 mostrada anteriormente é
na verdade definida como:
(define add-1
(lambda (x) (+ x 1)))
A estrutura de controlo if Utilizar map para aplicar uma função a todos
os membros de uma lista, produzindo outra lista, como em:
> (map (lambda (x) (+ x 1)) '(1 2 3 4))
(2 3 4 5)
ou
> (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")
Se os significados de alguns destes não são muito claros, veja as
referências na secção sobre Documentação
Scheme, e tente executar código como o acima utilizando Guile.Visão Geral de Relatórios Um relatório do GnuCash é adicionado ao sistena utilizando a função
gnc:define-report, para a qual são passados os seguintes
parâmetros:
versão Este é um número de versão; actualmente não é utilizado para
fazer nada particularmente inteligente.nome Este é um nome não-traduzido para o
relatório que é notavelmente utilizado para disponibilizar o nome
que será adicionado ao menu de relatórios do GnuCash
.
gerador de opções 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. 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. visualizador O "visualizador" faz o trabalho de gerar o relatório. Aceita
uma "base de dados" de opções, tal como a gerada pelo
gerador de opções , obtem os dados correspondentes do
motor do GnuCash, e gera, como resultado,
um objecto do tipo documento html , que é o que o
motor de relatórios do GnuCash sabe como
apresentar. Um exemplo trivial poderá assemelhar-se ao seguinte:
(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))
Note que os relatórios são tipicamente definidos dentro de um ambiente let ; as "funções
de trabalho" serão assim todas invisíveis para o código fora do
ambiente let , 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. Desde que cada relatório esteja do mesmo modo envolto num ambiente
let , você poderia chamar a todas
as funções de "renderização" rederizar sem causar
quaisquer conflitos.A função de gerador de opções O gerador de opções introduz um número adicional de funções
que são utilizadas para definir janelas de opções.
(define (options-generator)
(let ((option-set (gnc:new-options)))
(gnc:options-add-report-date!
option-set pagename-general "End Date" "a")
(gnc:options-add-date-interval!
option-set pagename-general "From" "To" "a")
(gnc:options-add-interval-choice!
option-set pagename-general
"Step Size" "b" 'YearDelta)
(gnc:options-add-account-levels!
option-set pagename-general
"Show Accounts down to Level" "c" 2)
(gnc:options-add-account-selection!
option-set pagename-general "Account Display Depth"
"Always show subaccounts" "Accounts" "a" 3
*LIST-OF-INCOME-AND-EXPENSE-ACCOUNTS*
options))
gnc:new-options 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.gnc:options-add-report-date! adiciona uma opção de
selecção que indica uma data única, geralmente utilizada como a data de
final.gnc:options-add-date-interval! adiciona uma opção de
selecção que permite especificar um intrevalo de datas.gnc:options-add-interval-choice! adiciona uma opção
de selecção que permite escolher entre vários intrevalos de tempo, incluindo
dias, semanas, quinzenas, meses, e anos.
gnc:options-add-account-levels! adiciona uma opção que indica
até que profundidade um conjunto de níveis de contas deverá ser mostrado.
gnc:options-add-account-selection! permite seleccionar um
conjunto de contas. Note que o último argumento é uma lista
de contas de onde seleccionar, o que significa ser necessário, a um determinado
ponto, filtrar uma lista de contas relevantes. Existem ainda funções de opções adicionais:
gnc:options-add-currency! para
seleccionar uma moeda;gnc:options-add-plot-size! para
controlar como um gráfico deverá ser dimensionado. Subjacentes a estas existem as seguintes funções base do "gerador
de opções" definidas em options-utilities.scm, que
podem ser utilizadas para criar novos tipos de opções:
gnc:register-optiongnc:make-date-optiongnc:make-multichoice-optiongnc:make-simple-boolean-optiongnc:make-account-list-optiongnc:make-currency-optiongnc:make-number-range-optionAceder aos Dados do GnuCash Existem vários formatos de dados que poderá querer aceder:
Informação de Contas Preços de Acções Dados de Leitura de Opções Aceder aos Dados do Motor As funções utilizadas para aceder às várias formas de dados
contabilísticos podem ser encontradas no ficheiro src/g-wrap/gnc.html
. São necessários alguns exemplos aqui... Aceder a Dados de Opções Functions gnc:lookup-option,
gnc:report-options, e
gnc:option-value são as funções cruciais
que mais provavelmente utilizará em src/scm/options.scm
Um excerto do src/scm/report/hello-world.scm
é o seguinte:
;; 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)) Preços de Acções A base de dados de preços de acções está em desenvolvimento, pelo que
é um pouco sedo para ser específico sobre isto...Funções de Geração HTML Os relatórios são gerados como uma árvore de registos
Guile, tendo como raíz um registo <documento html>, que consiste em
informação de estilos, um título, e uma lista de registos <objecto html> que
consistem numa função de renderização e noutra lista de objectos. Poderemos assim gerar um relatório simples:
(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
A função de renderização A função de renderização é onde as funções das secções anteriores
se juntam.
Recebe, como entrada, uma "base de dados" de opções geradas
assim que o utilizador adiciona os seus dados à janela produzida pelo
generador de opções . Utiliza essas opções para controlar como
aceder aos dados do GnuCash Finalmente, a partir desses dados, gera
uma "base de dados" de texto HTML. A fnção de renderização disponibiliza, como valor de retorno, a "base de dados
de HTML," que o GnuCash apresenta no visualizador de HTML.
(define (renderer options)
(let ((document (gnc:make-html-document)))
document)) ;;; Gera um documento vazio
Para Mais Informações 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 gnucash-devel@gnucash.org .