4. TP 1: Gestão básica de uma folha de pagamento
4.1. Introduction
Para aplicar o que foi abordado anteriormente, propomos agora um trabalho que consiste em desenvolver uma aplicação Android para tablet, que permita simular os cálculos das folhas de pagamento dos funcionários de uma associação.
A aplicação terá uma arquitetura cliente/servidor:

- O servidor [1] já está disponível;
- é necessário criar o cliente Android [2].
4.2. A base de dados
4.2.1. Definição
Os dados estáticos necessários para criar a folha de pagamento serão colocados numa base de dados a que, doravante, nos referiremos como dbpam. Esta base de dados contém as seguintes tabelas:
Estrutura:
chave primária | |
n.º de versão – aumenta a cada alteração da linha | |
número de segurança social do colaborador – único | |
nome do funcionário | |
o seu nome próprio | |
a sua morada | |
a sua cidade | |
o seu código postal | |
chave estrangeira no campo [ID] da tabela [INDEMNITES] |
O seu conteúdo poderia ser o seguinte:

Estrutura:
chave primária | |
n.º de versão – aumenta a cada alteração da linha | |
percentagem: contribuição social generalizada + contribuição para o reembolso da dívida social | |
percentagem: contribuição social generalizada dedutível | |
percentagem: segurança social, pensão de viuvez, velhice | |
percentagem: pensão complementar + seguro de desemprego |
O seu conteúdo poderá ser o seguinte:
![]()
As taxas das contribuições sociais são independentes do trabalhador. A tabela anterior tem apenas uma linha.
chave primária | |
n.º de versão – aumenta a cada alteração da linha | |
índice de processamento – único | |
preço líquido em euros por hora de serviço de guarda | |
Subsídio de manutenição em euros por dia de guarda | |
Subsídio de refeição em euros por dia de serviço | |
Subsídio de férias pagas. Trata-se de uma percentagem a aplicar ao salário base. |
O seu conteúdo poderia ser o seguinte:

Note-se que os subsídios podem variar de uma ama a outra. Estão, de facto, associados a uma ama específica através do seu índice salarial. Assim, a Sra. Marie Jouveinal, que tem um índice salarial de 2 (tabela EMPLOYES), tem um salário por hora de 2,1 euros (tabela INDEMNITES).
4.2.2. Geração
É fornecido o script [dbpam_hibernate.sql] para a geração da base de dados:
![]() |
Crie a base de dados [dbpam_hibernate] (este é o nome da base de dados BD que o servidor web / jSON utiliza) e certifique-se de que o login root, sem palavra-passe, tenha acesso à mesma. Pode proceder da seguinte forma:
Inicie o MySQL e, em seguida, o [PhpMyAdmin]:
![]() | ![]() |
- [1-2]: importe o script [dbpam_hibernate.sql] e, em seguida, execute-o;
4.2.3. Modelação Java da base de dados
Os elementos das tabelas [EMPLOYES], [INDEMNITES] e [COTISATIONS] são modelados pelas seguintes classes:
[Employe]
package pam.entities;
import java.io.Serializable;
public class Employe implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private String SS;
private String nom;
private String prenom;
private String adresse;
private String ville;
private String codePostal;
private int idIndemnite;
private Indemnite indemnite;
public Employe() {
}
public Employe(String SS, String nom, String prenom, String adresse, String ville, String codePostal, Indemnite indemnite) {
...
}
// getters e setters
....
}
- linhas 8-15: estes campos correspondem às colunas da tabela [EMPLOYES];
- linha 16: o campo [indemniteId] corresponde à coluna [INDEMNITE_ID], que é a chave estrangeira da tabela [EMPLOYES];
- linha 17: a indemnização do funcionário. Este campo nem sempre é preenchido:
- não o está quando se solicita o URL [/employes],
- mas está preenchido quando se solicita o URL [/salaire];
[Indemnite]
package pam.entities;
import java.io.Serializable;
public class Indemnite implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private int indice;
private double baseHeure;
private double entretienJour;
private double repasJour;
private double indemnitesCp;
public Indemnite() {
}
public Indemnite(int indice, double baseHeure, double entretienJour, double repasJour, double indemnitesCP) {
...
}
// getters e setters
....
}
- linhas 8-14: os campos correspondem às colunas da tabela [INDEMNITES];
[Cotisation]
package pam.entities;
import java.io.Serializable;
public class Cotisation implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private int version;
private double csgrds;
private double csgd;
private double secu;
private double retraite;
public Cotisation() {
}
public Cotisation(double csgrds, double csgd, double secu, double retraite) {
...
}
// getters e setters
...
}
- linhas 8-13: os campos correspondem às colunas da tabela [COTISATIONS];
4.3. Instalação do servidor web / jSON
![]() |
4.3.1. Instalação
O binário Java do servidor web / jSON é-lhe fornecido:
![]() |
Para iniciar o servidor web / jSON, proceda da seguinte forma:
- inicie o SGBD MySQL;
- certifique-se de que o BD [dbpam_hibernate] existe;
- abra uma janela DOS;
- navegue até à pasta do ficheiro .jar;
- digite o comando:
Isto pressupõe que o ficheiro binário [java.exe] se encontra no PATH do seu computador. Se não for esse o caso, introduza o caminho completo para o [java.exe], por exemplo:
São apresentados registos:
- linha 16: o URL [/salaire/{SS}/{ht}/{jt}] é detetado;
- linha 17: é detetado o URL [/employes];
4.3.2. Os URL do serviço web/jSON
![]() |
O serviço web / jSON é implementado pelo Spring MVC e expõe dois URL:
@RequestMapping(value = "/employes", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
public EmployesResponse getEmployes() {
...
@RequestMapping(value = "/salaire/{SS}/{ht}/{jt}", method = RequestMethod.GET, produces = "application/json; charset=UTF-8")
public FeuilleSalaireResponse getFeuilleSalaire(@PathVariable("SS") String SS, @PathVariable("ht") double ht, @PathVariable("jt") int jt) {
O serviço web aceita as duas seguintes URL:
- linha 1: /employes: para obter a lista de funcionários;
- linha 4: /salário/SS/ht/jt: para obter a folha de salário do funcionário com o n.º [SS] que trabalhou [ht] horas durante [jt] dias;
Eis algumas capturas de ecrã que ilustram isto.
Solicitam-se os funcionários:

Desligamos a base de dados, reiniciamos o servidor e consultamos os funcionários:

Solicita-se um salário:

Solicita-se o salário de uma pessoa inexistente:

4.3.3. As respostas jSON do serviço web/jSON
![]() |
![]() |
Os URL do serviço web / jSON enviam respostas do tipo [Response<T>]:
package client.android.dao.service;
import java.util.List;
public class Response<T> {
// ----------------- propriedades
// estado da operação
private int status;
// eventuais mensagens de estado
private List<String> messages;
// o corpo da resposta
private T body;
// construtores
public Response() {
}
public Response(int status, List<String> messages, T body) {
this.status = status;
this.messages = messages;
this.body = body;
}
// getters e setters
...
}
- o URL [/employes] devolve um tipo Response<List<Empregado>>;
- o URL e o [/salaire] devolvem um tipo Response<FeuilleSalaire>;
A classe [FeuilleSalaire] é a seguinte:
package pam.entities;
import java.io.Serializable;
public class FeuilleSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// campos privados
private Employe employe;
private Cotisation cotisation;
private ElementsSalaire elementsSalaire;
// construtores
public FeuilleSalaire() {
}
public FeuilleSalaire(Employe employe, Cotisation cotisation, ElementsSalaire elementsSalaire) {
...
}
// getters e setters
...
}
- linha 9: a classe [Employe] foi apresentada no parágrafo 4.2.3;
- linha 10: a classe [Cotisation] foi apresentada no parágrafo 4.2.3;
A classe [ElementsSalaire] (linha 11) é a seguinte:
package pam.entities;
import java.io.Serializable;
public class ElementsSalaire implements Serializable {
private static final long serialVersionUID = 1L;
// campos privados
private double salaireBase;
private double cotisationsSociales;
private double indemnitesEntretien;
private double indemnitesRepas;
private double salaireNet;
// construtores
public ElementsSalaire() {
}
public ElementsSalaire(double salaireBase, double cotisationsSociales, double indemnitesEntretien, double indemnitesRepas, double salaireNet) {
...
}
// getters e setters
...
}
4.4. Testes do cliente Android
![]() |
É-lhe fornecido o ficheiro binário executável do cliente Android finalizado:
![]() |
Com o rato, arraste o ficheiro executável [pam-client.apk] acima para um emulador de tablet [GenyMotion]. Este será então guardado e, em seguida, executado. Inicie também o servidor web / jSON, caso ainda não o tenha feito. O cliente Android tem como objetivo recuperar as informações enviadas pelo servidor web / jSON e formatá-las. As diferentes vistas do cliente Android são as seguintes:
Em primeiro lugar, é necessário estabelecer ligação ao serviço web / jSON:

- em [1], introduz-se o URL do serviço web / jSON. Com o emulador, introduza um dos endereços IP do PC (mas não 127.0.0.1). Num tablet, introduza o endereço Wi-Fi do servidor web / jSON e desative a firewall do servidor, caso exista, pois esta pode bloquear as ligações de entrada;
- no [2], faz-se a ligação;
Chega-se então à página de simulação:

- em [3], seleciona-se um funcionário;
- em [4], indica-se um número de horas;
- em [5], indica-se o número de dias;
- em [6], solicita-se a simulação;
A página de simulação obtida é a seguinte:

- em [7], a simulação obtida;
- em [8], guarda-se o resultado;

- em [9], a lista de simulações;
- em [10], remove-se uma simulação;

- em [11], já não há simulações;
- em [12], regressa-se ao formulário de simulação;

- em [13], volta-se ao formulário;
- em [14], regressa-se à página de configuração;

- em [15], volta-se ao formulário de início de sessão inicial.
4.5. Trabalho a realizar
O esqueleto do cliente Android apresentado anteriormente é-lhe fornecido. Foi construído a partir do projeto [client-android-skel] descrito no parágrafo 2.
![]() |
O projeto é executável e já possui as vistas necessárias. Basta adicionar código para que a aplicação execute as tarefas necessárias. O procedimento a seguir é o seguinte:
- execute a versão completa para compreender o trabalho a realizar;
- execute a versão simplificada e analise o seu código. Este respeita os métodos de conceção utilizados nas páginas anteriores;
- adicione o código que falta;










