Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho): Difference between revisions

From Wiki**3

Root (talk | contribs)
Tag: Reverted
Root (talk | contribs)
Tag: Reverted
Line 609: Line 609:


{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|
<syntaxhighlight lang="text">
  ''apresentação resumida de uma compra (ver acima)''
  ''apresentação resumida de uma compra (ver acima)''
  ''idCompra'' - ''descrição do transporte'' - ''data prevista de entrega'' - ''custo''
  ''idCompra'' - ''descrição do transporte'' - ''data prevista de entrega'' - ''custo''
  ␣␣''idProduto'' - ''nome'' - ''quantidade'' - ''preço unitário'' - ''total da linha''
  ␣␣''idProduto'' - ''nome'' - ''quantidade'' - ''preço unitário'' - ''total da linha''
  ␣␣...
  ␣␣...
</syntaxhighlight>
}}
}}



Revision as of 16:52, 11 September 2026

AVISOS - Avaliação em Época Normal

Esclarecimento de dúvidas:

  • Consultar sempre o corpo docente atempadamente: presencialmente ou através do endereço oficial da disciplina [1].
  • Não utilizar fontes de informação não oficialmente associadas ao corpo docente (podem colocar em causa a aprovação à disciplina).
  • Não são aceites justificações para violações destes conselhos: quaisquer consequências nefastas são da responsabilidade do aluno.

Requisitos para desenvolvimento, material de apoio e actualizações do enunciado (ver informação completa em Projecto de Programação com Objectos):

  • O material de apoio é de uso obrigatório e não pode ser alterado.
  • Verificar atempadamente (mínimo de 48 horas antes do final de cada prazo) os requisitos exigidos pelo processo de desenvolvimento.

Processo de avaliação (ver informação completa em Avaliação do Projecto):

  • Datas: 2026/10/16 12:00 (inicial); 2026/11/20 12:00 (intercalar); 2026/12/18 12:00 (final); 2026/12/18 (early bird) 2027/01/06 (normal) (teste prático).
  • Todas as entregas são cruciais para o bom desenvolvimento do projecto, sendo obrigatórias: a não realização de uma entrega implica a exclusão da avaliação do projecto e, por consequência, da avaliação da disciplina.
  • Verificar atempadamente (até 48 horas antes do final de cada prazo) os requisitos exigidos pelo processo de avaliação, incluindo a capacidade de acesso ao repositório.
  • Apenas se consideram para avaliação os projectos existentes no repositório oficial. Apenas se considera para avaliação o ramo 'master'.
  • Trabalhos não presentes no repositório no final do prazo têm classificação 0 (zero) (não são aceites outras formas de entrega). Não são admitidas justificações para atrasos em sincronizações do repositório. A indisponibilidade temporária do repositório ou de outros materiais, desde que inferior a 24 horas, não justifica atrasos na submissão de um trabalho.
  • A avaliação do projecto pressupõe o compromisso de honra de que o trabalho correspondente foi realizado pelos alunos correspondentes ao grupo de avaliação.
  • Fraudes na execução do projecto terão como resultado a exclusão dos alunos implicados do processo de avaliação.
Material de Uso Obrigatório
As bibliotecas po-uilib e o conteúdo inicial do repositório GIT são de uso obrigatório:
  • po-uilib (classes de base) po-uilib-202608310000.tar.bz2 (não pode ser alterada) - javadoc
  • erp-core (classes do "core") (via GIT) (deve ser completada -- os nomes das classes fornecidas não podem ser alterados)
  • erp-app (classes de interacção) (via GIT) (deve ser completada -- os nomes das classes fornecidas não podem ser alterados)
A máquina virtual, fornecida para desenvolvimento do projecto, já contém todo o material de apoio.
Uso Obrigatório: Repositório GIT
Apenas se consideram para avaliação os projectos existentes no repositório GIT oficial.

Trabalhos não presentes no repositório no final do prazo têm classificação 0 (zero) (não são aceites outras formas de entrega). Não são admitidas justificações para atrasos em sincronizações do repositório. A indisponibilidade temporária do repositório, desde que inferior a 24 horas, não justifica atrasos na submissão de um trabalho.

EM PREPARAÇÃO

ÉPOCA NORMAL

O objectivo do projecto é desenvolver um sistema de gestão de entregas rápidas de produtos (ERP — Express Retail Platform). O sistema deverá permitir, entre outras operações, (i) registar dados de empresas; (ii) registar dados de clientes; (iii) registar, gerir e pesquisar produtos; (iv) efectuar e gerir características de compras; (v) gerir as entregas correspondentes; e (vi) notificar os clientes sobre a situação das suas encomendas.

Neste texto, o tipo negrito indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo itálico indica uma parte variável (i.e., uma descrição).

Conceitos e Relações do Modelo

Existem vários conceitos importantes neste contexto: empresas, produtos, clientes, cabazes, compras, encomendas e entregas.

Os conceitos listados não são os únicos possíveis no modelo e as suas relações (assim como relações com outros conceitos não mencionados) podem depender das escolhas do projecto.

Os clientes e os produtos são independentes das empresas: existem por si e podem relacionar-se com várias empresas. Cada empresa, no entanto, mantém registo dos produtos que disponibiliza, assim como das compras feitas.

Uma compra representa a aquisição de produtos por um cliente a uma empresa e resulta de finalizar um cabaz. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.

Cada encomenda pode ser enviada de acordo com uma determinada modalidade e pode incluir serviços adicionais que alteram o seu custo e/ou tempo de entrega.

Produtos

O sistema mantém um registo de todos os produtos.

Cada produto é identificado por um número de produto. O identificador é atribuído automaticamente e incrementalmente (a partir de 1 ou do último valor atribuído, caso o estado do sistema tenha sido recuperado). Todos os produtos têm: um nome/descrição (cadeia de caracteres não vazia); um preço base (número inteiro positivo); uma categoria; um prazo de entrega base (número inteiro de dias); e a proveniência.

O preço base é uma propriedade intrínseca do produto e é definido ao nível do sistema. O preço base é independente das empresas que disponibilizam o produto. O sistema utiliza o preço base para calcular o preço recomendado do produto. O preço recomendado representa o valor de referência do produto no sistema. O seu cálculo pode depender do tipo de produto e de outras informações disponíveis no sistema.

O produto existe independentemente das empresas que o disponibilizam. Assim, o mesmo produto pode ser disponibilizado por várias empresas, sendo possível que cada uma pratique um preço de venda diferente.

Cada produto tem uma categoria, de acordo com a sua natureza. Inicialmente, consideram-se as seguintes categorias: (i) alimentar; (ii) electrónica; e (iii) vestuário. Deve ser possível adicionar novas categorias com impacto mínimo na aplicação já desenvolvida.

A informação relativa à disponibilização de um produto por uma empresa não deve ser considerada parte das características intrínsecas do produto.

Proveniência de Produtos

Os produtos podem ter diferentes proveniências.

Inicialmente, consideram-se as seguintes: (i) produto nacional; e (ii) produto importado.

Um produto nacional possui apenas as propriedades gerais dos produtos.

Um produto importado possui, para além das propriedades gerais dos produtos:

  • o país de origem (cadeia de caracteres não vazia);
  • a taxa alfandegária (número inteiro expressando uma percentagem).

O preço recomendado é calculado de forma diferente consoante o tipo de produto.

Deve ser possível introduzir ou especializar proveniências com impacto mínimo na implementação desenvolvida.

Produtos Nacionais

Para um produto nacional, o preço recomendado depende do preço base e do número total de unidades actualmente disponíveis desse produto nas empresas que o disponibilizam.

Se o número total de unidades disponíveis for:

  • superior a 10000, o preço recomendado corresponde a 90% do preço base;
  • inferior a 100, o preço recomendado corresponde a 130% do preço base;
  • nos restantes casos, o preço recomendado corresponde ao preço base.

Os cálculos não são arredondados: 130% de um preço base de 45 dá 58.5.

Por exemplo, considerando um produto nacional com preço base de 100 euros:

  • Unidades disponíveis = 50 ⇒ Preço recomendado = 130 euros;
  • Unidades disponíveis = 5000 ⇒ Preço recomendado = 100 euros;
  • Unidades disponíveis = 12000 ⇒ Preço recomendado = 90 euros.

Produtos Importados

Para um produto importado, o preço recomendado corresponde ao preço base corrigido com taxa alfandegária correspondente.

Se a taxa alfandegária for t%, o preço recomendado é calculado de acordo com:

preço base × (100 + t) / 100

Por exemplo, considerando um produto importado com preço base de 100 euros e uma taxa alfandegária de 20%, o preço recomendado será:

100 × (100 + 20) / 100 = 120 euros

O cálculo do preço recomendado deve ser realizado de forma polimórfica, de modo a que o código que utiliza produtos não tenha de conhecer explicitamente a proveniência concreta de cada produto.

Empresas

O sistema mantém um registo de todas as empresas.

Cada empresa é identificada por um número de empresa. O identificador é atribuído automaticamente e incrementalmente (a partir de 1 ou do último valor atribuído, caso o estado do sistema tenha sido recuperado). Cada empresa tem ainda um nome (cadeia de caracteres não vazia).

Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.

Para cada produto que disponibiliza, a empresa deve manter informação sobre:

  • número de unidades disponíveis (valor inteiro);
  • factor multiplicativo do preço recomendado (número positivo).

O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.

O factor multiplicativo permite que uma empresa pratique um preço de venda diferente do preço recomendado pelo sistema. O preço de venda de um produto pela empresa é calculado multiplicando o preço recomendado do produto pelo factor multiplicativo definido pela empresa. Assim, duas empresas podem disponibilizar o mesmo produto a preços diferentes e com quantidades diferentes em stock.

Por exemplo, o produto P1, com um preço recomendado de 100 euros, pode ser disponibilizado pela empresa A com um preço de 90 euros (factor multiplicativo: 0,9), enquanto a empresa B pode disponibilizar o mesmo produto com um preço de 120 euros (factor multiplicativo: 1,2).

Alterações de Inventário

O inventário de um produto numa empresa pode ser alterado através da especificação de dois valores: um número inteiro e um número real. O número inteiro é somado ao número de exemplares disponíveis do produto nessa empresa: se for positivo, aumenta-o; se for negativo, diminui-o, desde que o número de exemplares não fique negativo. O número real é o novo factor multiplicativo do produto nessa empresa, que tem de ser positivo.

O inventário só é actualizado se a quantidade e o factor multiplicativo forem ambos válidos; caso contrário, a operação não tem qualquer efeito. É também por esta via que uma empresa passa a disponibilizar um produto já registado no sistema: nesse caso, a quantidade e o factor têm de ser ambos positivos, porque uma empresa não passa a disponibilizar um produto com zero exemplares.

Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero. Quando o inventário de um produto numa empresa chega a zero, o produto deixa de estar disponível nessa empresa, mas continua a existir no sistema e pode continuar a ser disponibilizado por outras empresas. Se o inventário de um produto numa empresa passar de zero para um valor positivo, o produto volta a estar disponível nessa empresa.

O número total de unidades disponíveis de um produto corresponde à soma dos inventários desse produto em todas as empresas que o disponibilizam.

Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.

Clientes

O sistema mantém um registo de todos os clientes.

Cada cliente é identificado pelo seu endereço de correio electrónico, que deve ser único. Cada cliente tem ainda informação sobre o seu nome. Estes campos não podem ser vazios.

Compras

O sistema mantém um registo de todas as compras.

Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente (a partir de 1 ou do último valor atribuído, caso o estado do sistema tenha sido recuperado). Uma compra é sempre feita por um único cliente a uma única empresa numa determinada data.

Uma compra é constituída por um conjunto de linhas, cada uma descrevendo um produto e informação correspondente, e resulta do fecho de um cabaz. A informação por linha é a seguinte:

  • um produto;
  • uma quantidade (número de exemplares adquiridos desse produto);
  • um preço unitário (o preço de venda do produto pela empresa no momento de inclusão no cabaz).

O preço unitário utilizado numa compra deve ser guardado na própria linha da compra. Alterações posteriores ao preço base, ao preço recomendado, ao factor multiplicativo da empresa, ou a qualquer outra propriedade utilizada no cálculo do preço, não devem alterar o valor de compras já efectuadas.

O preço de venda praticado por uma empresa é o preço recomendado do produto multiplicado pelo factor dessa empresa, arredondado a duas casas decimais:

// variable names are merely descriptive
unitPrice = Math.round(recommendedPrice * multiplier * 100) / 100.0;

Este é o único arredondamento do sistema: nem o preço base, nem o preço recomendado, nem as tarifas, nem os custos dos serviços ou de processamento são arredondados. Os totais são somas e múltiplos de preços unitários que já têm as suas duas casas decimais, pelo que também elas são exactas.

Os preços são apresentados com duas casas decimais, mesmo quando o valor é inteiro: 15.00, 13.50, 64.35, 312.00. O separador decimal é o ponto.

Os valores que são sempre inteiros são apresentados como tal, sem casas decimais: o preço base dos produtos, as tarifas das modalidades de transporte, os custos dos serviços adicionais e o custo de processamento de uma encomenda — e, portanto, o custo de uma encomenda e o custo total das encomendas de uma compra, que resultam apenas da soma destes.

O custo de uma linha é obtido multiplicando o preço unitário do produto pela quantidade. O custo total da compra ou encomenda corresponde à soma dos custos de todas as suas linhas.

Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma estratégia de divisão de encomendas. A divisão de uma compra em várias encomendas pode ter impacto no preço final a pagar.

Cabaz de Compras

Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num cabaz.

Cada cliente tem um cabaz por cada empresa em que compra. O cabaz é constituído por um conjunto de linhas; cada linha corresponde a um produto disponibilizado por essa empresa e a uma quantidade. Acrescentar ao cabaz um produto que já lá esteja acumula as quantidades. Quantidades negativas diminuem o total, que nunca é negativo: se o total ficar nulo — ou se a quantidade a subtrair ultrapassar a que lá está — o produto é removido do cabaz. É esta a forma de retirar um produto do cabaz.

Acrescentar exemplares — seja incluindo um produto novo, seja aumentando a quantidade de uma linha que já existe — só é aceite se a quantidade resultante dessa linha não for superior ao número de exemplares que a empresa associada ao cabaz tem do produto. Caso contrário, o cabaz não é alterado. Retirar exemplares é sempre aceite, desde que o produto esteja no cabaz.

O cabaz regista ainda as opções que serão aplicadas à compra:

A modalidade e os serviços adicionais escolhidos aplicam-se a todas as encomendas resultantes da compra.

Enquanto não for finalizado, o cabaz não tem qualquer efeito no resto do sistema: em particular, não reserva nem consome inventário, e os preços apresentados são sempre os preços de venda praticados pela empresa nesse momento. Ter sido possível colocar no cabaz uma quantidade de um produto não garante, portanto, que ela ainda esteja disponível quando a compra for finalizada: a empresa pode, entretanto, ter vendido exemplares desse produto a outros clientes. Ao finalizar o cabaz e apenas nesse momento:

  • os preços de venda são fixados nas linhas da compra;
  • a compra é dividida em encomendas de acordo com a estratégia configurada no cabaz;
  • todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;
  • o inventário dos produtos na empresa é decrementado, o cliente é debitado e a empresa passa a seguir o cliente;
  • o cabaz é limpo: fica sem linhas, sem modalidade de transporte e sem serviços adicionais, e a estratégia de divisão volta à de omissão. Nada da compra acabada de fazer transita para a seguinte.

Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenha sido escolhida a modalidade de transporte. Finalizar só tem efeito se, nesse momento, a empresa tiver exemplares suficientes de todos os produtos do cabaz: se faltarem exemplares de algum deles (por exemplo, porque foram entretanto vendidos a outro cliente, ou porque o inventário foi alterado), a operação falha por inteiro, sem qualquer efeito — nenhuma linha é comprada e o cabaz mantém-se inalterado.

Os cabazes fazem parte do estado persistente da aplicação.

Divisão das Compras em Encomendas

Cada encomenda tem um custo de processamento de 5 euros. Assim, uma compra dividida em várias encomendas pode ter um custo superior ao de uma compra enviada numa única encomenda. Se uma encomenda corresponder a produtos com valor superior a 50 euros (somatório), o custo de processamento é zero. O prazo de entrega base de uma encomenda é igual ao maior prazo de entrega base dos vários produtos presentes na encomenda.

O custo total de processamento da compra corresponde à soma dos custos de processamento das suas encomendas. A este custo podem acrescer ainda os custos associados ao método de transporte seleccionado e aos serviços adicionais.

O custo total de uma compra corresponde, assim, ao custo dos produtos acrescido:

  • do custo total de processamento associado às encomendas;
  • dos custos adicionais das tarifas de transporte;
  • dos custos dos serviços adicionais seleccionados.

A forma como uma compra é dividida em encomendas é determinada por uma estratégia de divisão de encomendas. Inicialmente, devem ser suportadas, pelo menos, as seguintes estratégias: encomenda única (UNICA) e agrupamento por prazo de entrega dos produtos (PRAZO).

Encomenda única

Todos os produtos da compra são colocados numa única encomenda.

Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.

Agrupamento por prazo de entrega

As linhas de uma compra são agrupadas de acordo com os seus prazos de entrega dos produtos correspondentes, de acordo com o procedimento a seguir descrito:

  1. calcula-se a média dos prazos de entrega dos produtos das linhas da compra;
  2. todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;
  3. cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda separada.

Por exemplo, considere-se uma compra com quatro linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2), 2 (P3) e 8 (P4). A média dos prazos é (3 + 8 + 2 + 8) / 4 ≈ 5,25. Logo, P1 e P3 (prazos ≤ 5,25) seguem juntos na encomenda A e P2 e P4 (prazo > 5,25) seguem em encomendas separadas B e C, de acordo com o método acima:

  • Encomenda A: {P1, P3} (prazo = 3)
  • Encomenda B: {P2} (prazo = 8)
  • Encomenda C: {P4} (prazo = 8)

Embora a estratégia de divisão que origina várias encomendas possa permitir que alguns produtos sejam entregues mais cedo, também pode resultar num custo superior devido ao custo adicional associado a cada encomenda.

Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.

Modalidades de Transporte

Cada encomenda é enviada utilizando uma modalidade de transporte. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (NORMAL) e expresso (EXPRESSO).

Uma modalidade de transporte é a designação de um nível de serviço. O custo e o prazo não lhe estão fixados no código: para cada modalidade são definidos:

  • uma tarifa de transporte (número inteiro); e
  • um tempo de transporte (número inteiro de dias).

A tarifa e o tempo podem ter valores diferentes consoante a modalidade de transporte.

Por exemplo:

Modalidade Tarifa Tempo
NORMAL 3 euros 3 dias
EXPRESSO 8 euros 1 dia

A modalidade de transporte é definida no cabaz e aplica-se a todas as encomendas da compra. O modelo deve, no entanto, permitir que cada encomenda seja enviada utilizando uma modalidade diferente.

A escolha da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhida a modalidade de transporte.

Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida.

Serviços Adicionais

O cliente pode seleccionar serviços adicionais, podendo aumentar o custo de cada encomenda, assim como o tempo necessário para a sua preparação e entrega. Os serviços são escolhidos no cabaz e aplicam-se a todas as encomendas da compra. O modelo deve, no entanto, permitir que cada encomenda tenha os seus próprios serviços.

Os serviços iniciais são os seguintes:

Serviço Chave Custo adicional Tempo adicional
Embrulho EMBRULHO 2 euros 1 dia
Cartão de oferta CARTAO_OFERTA 1 euro 0 dias

Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. Inclusive, deve ser possível adicionar o mesmo serviço várias vezes. Depois de adicionar um serviço, não é necessário removê-lo.

Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.

Data de Entrega das Encomendas

Cada encomenda tem uma data prevista de entrega. A data prevista de entrega é determinada considerando:

  • a data da compra;
  • os prazos de entrega da encomenda;
  • o tempo de transporte da modalidade seleccionada;
  • o tempo adicional introduzido pelos serviços seleccionados.

Uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.

Gestão de Tempo

A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente.

A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:

  • quais as encomendas que serão entregues no dia seguinte;
  • quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.

Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.

A gestão do tempo deve ainda desencadear notificações.

Pesquisas

O sistema permite efectuar pesquisas sobre toda a informação que mantém. As pesquisas podem corresponder a valores de campos individuais ou implicar avaliação de relações entre entidades.

Pesquisas lexicográficas devem ocorrer sem distinção entre letras maiúsculas e minúsculas.

O sistema deve suportar diferentes critérios de pesquisa. Deve ser possível introduzir novos métodos de pesquisa de produtos com impacto mínimo na implementação desenvolvida.

Notificações

O sistema deve notificar os clientes relativamente aos eventos associados às suas encomendas.

Devem ser enviadas notificações em duas situações:

  • um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;
  • no dia da entrega, informando o cliente de que a encomenda foi entregue.

Cada cliente pode escolher o mecanismo através do qual pretende receber notificações do sistema. O mecanismo de notificação pode variar de cliente para cliente. Por exemplo, um cliente pode receber notificações por correio electrónico, enquanto outro pode recebê-las através de WhatsApp. Por razões de simplificação, inicialmente, o sistema deve suportar um mecanismo de notificações (o mecanismo por omissão) em que cada cliente guarda directamente as suas notificações e estas depois podem ser escritas na saída do programa quando o cliente quiser. No entanto, deve ser possível introduzir novos mecanismos de notificação sem necessidade de alterar o código dos clientes ou do sistema responsável por gerar as notificações.

As notificações devem ser enviadas pela ordem em que os acontecimentos ocorrem no sistema.

Requisitos de Desenho

A aplicação a desenvolver deve seguir o princípio de desenho aberto-fechado, por forma a aumentar a extensibilidade do seu código. Por exemplo, deve ser possível adicionar novos tipos de produto com um impacto mínimo no código já existente da aplicação.

Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código já produzido para a aplicação. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Assim, deve ser possível:

  • Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis), incluindo a respectiva regra de cálculo do preço recomendado;
  • Adicionar novas categorias de produto;
  • Introduzir novas estratégias de divisão de compras em encomendas;
  • Introduzir novas modalidades de transporte;
  • Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;
  • Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;
  • Introduzir novos critérios de pesquisa de produtos.

Funcionalidade da aplicação

A aplicação permite manter informação sobre as entidades do modelo, permitindo, em particular, gerir empresas, produtos, clientes e compras. Possui ainda a capacidade de preservar o seu estado (não é possível manter várias versões do estado da aplicação em simultâneo).

Nenhuma entidade é removida pelas operações descritas neste enunciado (em particular, um produto cujo inventário numa empresa chegue a zero continua a existir no sistema). Ainda assim, a aplicação deve estar preparada para que a remoção de qualquer entidade possa vir a ser suportada.

No início, a aplicação está vazia, mas pode ser carregada uma base de dados textual com conceitos pré-definidos. Neste caso, a aplicação começará com um estado referente às entidades que foram carregadas no arranque da aplicação.

Note-se que não é necessário implementar de raiz a aplicação: já existem classes que representam e definem a interface geral da funcionalidade do core da aplicação, tal como é visível pelos comandos da aplicação.
A interface geral do core já está parcialmente implementada na classe erp.ErpManager e outras fornecidas (cujos nomes devem ser mantidos), devendo ser adaptadas onde necessário. É ainda necessário criar e implementar as restantes classes que suportam a operação da aplicação.

Serialização

É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita acima.

Após a recuperação do estado, os identificadores atribuídos a novas entidades devem continuar a ser atribuídos incrementalmente a partir do último valor utilizado em cada caso.

Interacção com o utilizador

Descreve-se nesta secção a funcionalidade máxima da interface com o utilizador. Em geral, os comandos pedem toda a informação antes de procederem à sua validação (excepto onde indicado). Todos os menus têm automaticamente a opção Sair (fecha o menu).

As operações de pedido e apresentação de informação ao utilizador devem realizar-se através de objectos dos tipos Form e Display, respectivamente, presentes em cada comando. Cada comando já tem um de cada, mas podem ser criados novos formulários, conforme as necessidades. No entanto, o objecto do tipo Display é único e partilhado por toda a aplicação.

As mensagens são produzidas pelos métodos das bibliotecas de suporte (po-uilib e erp-app). As mensagens não podem ser usadas no núcleo da aplicação (erp-core). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.

De um modo geral, sempre que no contexto de uma operação com o utilizador aconteça alguma excepção, então a operação não deve ter qualquer efeito no estado da aplicação, excepto em caso de indicação contrária na operação em causa. As excepções estão na package erp.app.exceptions, excepto em caso de indicação contrária.

As excepções usadas na interacção (subclasses de pt.tecnico.uilib.menus.CommandException), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de pt.tecnico.uilib.menus.Command) e tratadas pelos menus (instâncias de subclasses de pt.tecnico.uilib.menus.Menu). Outras excepções não devem substituir as fornecidas nos casos descritos.

Nos pedidos e usos dos vários identificadores, podem ocorrer as seguintes excepções, caso o identificador indicado não corresponda a um objecto conhecido (excepto no processo de registo ou em caso de indicação contrária). Note-se que estas excepções não são utilizáveis no núcleo da aplicação.

Tipo de dados Classe Pedido a apresentar Excepção a lançar se desconhecido
Empresa Company erp.app.company.Prompt.companyId() erp.app.exceptions.UnknownCompanyKeyException
Produto Product erp.app.product.Prompt.productId() erp.app.exceptions.UnknownProductKeyException
Cliente Client erp.app.client.Prompt.clientId() (um endereço de correio electrónico) erp.app.exceptions.UnknownClientKeyException
Compra Purchase erp.app.purchase.Prompt.purchaseId() erp.app.exceptions.UnknownPurchaseKeyException

Existe ainda um caso particular: sempre que uma operação se refira a um produto no contexto de uma empresa e essa empresa não disponibilize esse produto, deve ser lançada a excepção erp.app.exceptions.ProductNotSuppliedException (a empresa e o produto existem, mas não estão relacionados).

Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.

Vários comandos pedem ao utilizador que escolha um valor de um conjunto fechado (tipo de produto, categoria, estratégia de divisão, modalidade de transporte, serviço adicional e critério de pesquisa). Estas escolhas devem ser pedidas através de campos de opção (Command.addOptionField(), Form.addOptionField() ou Form.requestOption()), sendo o conjunto de opções obtido do núcleo através da fachada. Desta forma, a introdução de uma nova estratégia, modalidade, serviço ou critério não implica qualquer alteração aos comandos.

Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas packages erp.app, erp.app.main, erp.app.company, erp.app.product, erp.app.client, erp.app.purchase. Estas classes são de uso obrigatório e estão disponíveis no GIT (módulo erp-app).

Formatos de Apresentação

Os formatos usados pelos vários comandos são os seguintes. Todos os campos são separados por ␣-␣.

Formato de apresentação de uma empresa
id - nome
Formato de apresentação de um produto
id - tipo - nome - categoria - preço base - preço recomendado - prazo base - unidades totais - informação adicional

O tipo é NACIONAL ou IMPORTADO. As unidades totais correspondem à soma dos inventários do produto em todas as empresas que o disponibilizam. Para produtos nacionais não existe informação adicional; para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.

Exemplos de apresentação de produtos
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15.00 - 3 - 173
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260.00 - 3 - 2 - China - 30
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58.50 - 2 - 0
Formato de apresentação da disponibilização de um produto por uma empresa
idEmpresa - idProduto - unidades - factor - preço de venda
Exemplos de apresentação de disponibilizações
2 - 1 - 150 - 0.9 - 13.50
2 - 2 - 2 - 1.2 - 312.00
Formato de apresentação de um cliente
email - nome - gasto total

O email é o identificador do cliente. O valor apresentado no fim corresponde ao total gasto pelo cliente em compras.

Exemplos de apresentação de clientes
ahsoka@jedi.org - Ahsoka Tano - 0.00
obiwan@jedi.org - Obi-Wan Kenobi - 119.35
Formato de apresentação (resumida) de uma compra
id - emailCliente - idEmpresa - data - preço total dos itens - custo das encomendas - custo total
Formato de apresentação (resumida) de uma encomenda
idCompra - descrição do transporte - data prevista de entrega - custo - lista de identificadores de produtos

A descrição do transporte é a indicação da modalidade seleccionada, seguida das chaves dos serviços adicionais seleccionados, separadas por + (por exemplo, EXPRESSO+EMBRULHO+CARTAO_OFERTA). As chaves devem ser compostas pela ordem inversa pela qual os serviços foram adicionados à encomenda.

Exemplos de apresentação de encomendas
1 - EXPRESSO+EMBRULHO - 5 - 10 - 3
1 - EXPRESSO+EMBRULHO - 6 - 15 - 1

Menu Principal

As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: Abrir, Guardar, Mostrar data actual, Avançar data actual, Menu de Gestão de Empresas, Menu de Gestão de Produtos, Menu de Gestão de Clientes e Menu de Gestão de Compras. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.

As etiquetas das opções deste menu estão definidas na classe erp.app.main.Label. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe erp.app.main. Message.
Estes comandos já estão implementados nas classes da package erp.app.main, respectivamente: DoOpenFile, DoSaveFile, DoDisplayDate, DoAdvanceDate, DoOpenMenuCompanies, DoOpenMenuProducts, DoOpenMenuClients, DoOpenMenuPurchases.

Salvaguarda do estado actual da aplicação

O conteúdo da aplicação (toda a informação detida pelo ERP actualmente em memória) pode ser guardado para posterior recuperação (via serialização Java: java.io.Serializable). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:

  • Abrir -- Carrega os dados de uma sessão anterior a partir de um ficheiro previamente guardado (ficando este ficheiro associado à aplicação, para futuras operações de salvaguarda). Pede-se o nome do ficheiro a abrir (Prompt.openFile()). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção FileOpenFailedException. A execução bem-sucedida desta opção substitui toda a informação da aplicação.
    Quando se abandona uma aplicação com modificações não guardadas (porque se abre outra e existem alterações não guardadas), deve perguntar-se ao utilizador se quer guardar a informação actual antes de a abandonar, através de Prompt.saveBeforeExit() (a resposta é obtida via Form.confirm()).
  • Guardar -- Guarda o estado actual da aplicação no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associado (para operações de salvaguarda subsequentes). Esta interacção realiza-se através do método Prompt. newSaveAs(). Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.
Note-se que a opção Abrir não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).
A opção Sair nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.

Mostrar data actual

A data actual do sistema é apresentada através da mensagem Message.currentDate().

Avançar data actual

O número de dias a avançar é pedido através de Prompt.daysToAdvance(). O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.

Além da data, o sistema deve desencadear as notificações relativas às encomendas cujas datas previstas de entrega sejam atingidas ou fiquem à distância de um dia. Note-se que a situação de uma encomenda (entregue ou não) não é guardada: deriva da data actual.

Gestão e consulta de dados da aplicação

  • Menu de Gestão de Empresas -- Abre o menu de gestão de empresas e operações associadas.
  • Menu de Gestão de Produtos -- Abre o menu de gestão de produtos e operações associadas.
  • Menu de Gestão de Clientes -- Abre o menu de gestão de clientes e operações associadas.
  • Menu de Gestão de Compras -- Abre o menu de gestão de compras e operações associadas.

Menu de Gestão de Empresas

Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: Registar empresa, Mostrar empresa, Mostrar empresas, Alterar inventário de um produto, Mostrar produtos de uma empresa, Mostrar clientes de uma empresa.

As etiquetas das opções deste menu estão definidas em erp.app.company.Label. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em erp.app.company.Prompt e erp.app.company.Message.
Estes comandos já estão implementados nas classes da package erp.app.company, respectivamente: DoRegisterCompany, DoShowCompany, DoShowCompanies, DoChangeProductInventory, DoShowCompanyProducts, DoShowCompanyClients.

Registar empresa

Pede o nome (Prompt.companyName()). O registo bem sucedido é assinalado através da mensagem Message.registrationSuccessful(); caso contrário, é lançada a excepção CompanyRegistrationFailedException.

Note-se que a atribuição do identificador da empresa é automática.

Mostrar empresa

É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, no formato de apresentação de uma empresa.

Mostrar empresas

Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em Mostrar empresa.

Alterar inventário de um produto

Efectua uma alteração de inventário de um produto numa empresa.

São pedidos o identificador da empresa, o identificador do produto, a quantidade (Prompt.amountToUpdate()) e o factor multiplicativo do preço recomendado (Prompt.priceFactor()).

A alteração bem sucedida é assinalada através da mensagem Message.supplySuccessful(); se a alteração não for válida, é apresentada a mensagem Message.cannotChangeInventory().

Mostrar produtos de uma empresa

É pedido o identificador da empresa e apresentam-se os produtos que essa empresa disponibiliza, ordenados pelos identificadores dos produtos, no formato de apresentação da disponibilização de um produto por uma empresa.

Mostrar clientes de uma empresa

É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, no formato de apresentação de um cliente.

Menu de Gestão de Produtos

Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: Registar produto, Mostrar produto, Mostrar produtos e Efectuar pesquisa.

As etiquetas das opções deste menu estão definidas em erp.app.product.Label. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em erp.app.product.Prompt e erp.app.product.Message.
Estes comandos já estão implementados nas classes da package erp.app.product (disponível no GIT), respectivamente: DoRegisterProduct, DoShowProduct, DoShowProducts, DoPerformSearch.

Registar produto

Regista um produto no registo global de produtos. São pedidos, por esta ordem: o tipo de produto (Prompt.productType()), o nome (Prompt.productName()), o preço base (Prompt.basePrice()), a categoria (Prompt.productCategory()) e o prazo de entrega base (Prompt.baseDelay()).

Se o tipo indicado for IMPORTADO, são ainda pedidos o país de origem (Prompt.originCountry()) e a taxa alfandegária (Prompt.customsTax()).

O registo bem sucedido é assinalado através da mensagem Message.registrationSuccessful(); caso contrário, é lançada a excepção ProductRegistrationFailedException.

Note-se que a atribuição do identificador do produto é automática e que um produto registado não é, por si só, disponibilizado por qualquer empresa (ver Alterar inventário de um produto).

Mostrar produto

É pedido o identificador do produto. Se o produto existir, é apresentado no formato de apresentação de um produto.

Mostrar produtos

Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em Mostrar produto.

Efectuar pesquisa

Esta opção realiza uma procura sobre o registo de produtos. São pedidos o critério de pesquisa (Prompt.searchCriterion()) e um termo (Prompt.searchTerm()).

Os critérios iniciais são: NOME, CATEGORIA e ORIGEM (país de origem, que apenas os produtos importados possuem). Se se indicar pesquisa por origem, apenas os produtos importados podem verificar o critério de pesquisa.

Como resultado, deve ser apresentada uma lista dos produtos encontrados pela pesquisa, ordenados por ordem crescente do seu identificador, utilizando o formato descrito para Mostrar produto. O termo de pesquisa é comparado sem distinção entre letras maiúsculas e minúsculas. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.

Menu de Gestão de Clientes

Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: Registar cliente, Mostrar cliente, Mostrar clientes, Mostrar notificações do cliente.

As etiquetas das opções deste menu estão definidas em erp.app.client.Label. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em erp.app.client.Prompt e erp.app.client.Message.
Estes comandos já estão implementados nas classes da package erp.app.client, respectivamente: DoRegisterClient, DoShowClient, DoShowClients, DoShowClientNotifications.

Registar cliente

Pede o nome (Prompt.clientName()) e o endereço de correio electrónico (Prompt.clientEMail()). O registo bem sucedido é assinalado através da mensagem Message.registrationSuccessful(); caso contrário, é lançada a excepção ClientRegistrationFailedException.

Note-se que o endereço de correio electrónico é o identificador do cliente: registar um endereço já conhecido falha, em vez de criar um segundo cliente.

Mostrar cliente

É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, no formato de apresentação de um cliente.

Mostrar clientes

Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados pelos seus identificadores (os endereços de correio electrónico). O formato é o descrito em Mostrar cliente.

Mostrar notificações do cliente

Este comando apresenta as notificações recebidas pelo cliente através do mecanismo de notificações por omissão.

É pedido o identificador do cliente, sendo apresentadas as notificações enviadas através do mecanismo de notificações por omissão para esse cliente, de acordo com o seguinte formato:

Formato de apresentação das notificações de um cliente
assunto: descrição da encomenda

O assunto é ENTREGA_AMANHA (a encomenda será entregue no dia seguinte) ou ENTREGUE (a encomenda foi entregue). A descrição da encomenda é a descrição resumida definida em Formatos de Apresentação.

Exemplos de notificações
ENTREGA_AMANHA: 1 - EXPRESSO+EMBRULHO - 5 - 10 - 3
ENTREGUE: 1 - EXPRESSO+EMBRULHO - 6 - 15 - 1

As notificações de um cliente apenas devem ser apresentadas uma única vez. Após esta visualização, considera-se que o cliente fica sem notificações. As notificações devem ser apresentadas pela mesma ordem em que foram enviadas pelo sistema.

Caso o cliente indicado não tenha notificações, não deve ser apresentado qualquer resultado.

Menu de Gestão de Compras

Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: Efectuar compra, Mostrar compra, Mostrar compras.

As etiquetas das opções deste menu estão definidas em erp.app.purchase.Label. Os métodos correspondentes aos pedidos deste menu estão definidos em erp.app.purchase.Prompt. Este menu não tem mensagens próprias: as do processo de compra pertencem ao menu de cabaz (erp.app.basket.Message).
Estes comandos já estão implementados nas classes da package erp.app.purchase (disponível no GIT), respectivamente: DoDoPurchase, DoShowPurchase, DoShowPurchases.

Efectuar compra

Esta opção não efectua, por si só, qualquer compra: abre o menu de cabaz sobre o cabaz de um cliente numa empresa.

São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o Menu de Cabaz sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).

Como o cabaz pertence ao cliente, sair do menu sem finalizar a compra preserva o seu conteúdo e as suas opções para uma visita posterior.

Mostrar compra

É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas em detalhe — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido das suas linhas, indentadas com dois espaços e ordenadas pelos identificadores dos produtos. Cada linha tem o mesmo formato das linhas de um cabaz; o preço unitário apresentado é o que foi fixado no momento da compra, e não o preço de venda actual. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos na primeira posição da lista correspondente.

Formato de apresentação de uma compra (com encomendas em detalhe)
 ''apresentação resumida de uma compra (ver acima)''
 ''idCompra'' - ''descrição do transporte'' - ''data prevista de entrega'' - ''custo''
 ␣␣''idProduto'' - ''nome'' - ''quantidade'' - ''preço unitário'' - ''total da linha''
 ␣␣...
Exemplo de apresentação de uma compra
1 - obiwan@jedi.org - 1 - 1 - 94.35 - 25 - 119.35
1 - EXPRESSO+EMBRULHO - 5 - 10
  3 - Camisa - 1 - 64.35 - 64.35
1 - EXPRESSO+EMBRULHO - 6 - 15
  1 - Farinha - 2 - 15.00 - 30.00

Mostrar compras

Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no formato de apresentação de uma compra (apenas a linha da compra, sem as encomendas).

Menu de Cabaz

Este menu apresenta as operações sobre um cabaz: é aberto sobre o cabaz em causa, que é o alvo de todos os seus comandos. A lista completa é a seguinte: Alterar produto no cabaz, Mostrar cabaz, Definir estratégia de divisão em encomendas, Definir modalidade de transporte, Adicionar serviço adicional e Finalizar compra.

Algumas opções só estão disponíveis quando fazem sentido, não sendo apresentadas nos restantes casos:

  • Definir modalidade de transporte só está disponível se existir pelo menos uma modalidade de transporte definida;
  • Finalizar compra só está disponível se o cabaz tiver, pelo menos, uma linha e se já tiver sido escolhida a modalidade de transporte.
As etiquetas das opções deste menu estão definidas em erp.app.basket.Label. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em erp.app.basket.Prompt e erp.app.basket.Message.
Estes comandos já estão implementados nas classes da package erp.app.basket (disponível no GIT), respectivamente: DoChangeProduct, DoShowBasket, DoSetSplitStrategy, DoSetModality, DoAddService e DoCheckout. Todos derivam de erp.app.basket.BasketCommand, cujo alvo (receiver) é o cabaz.

Alterar produto no cabaz

Altera a quantidade de um produto no cabaz.

São pedidos o identificador do produto (Prompt.productToChange()) e a quantidade a alterar (Prompt.amountToChange()), que pode ser negativa. O sucesso é assinalado com a mensagem Message.productChanged(), que indica a quantidade resultante.

Se a alteração remover o produto do cabaz, é apresentada a mensagem Message.productRemoved(); se não houver linha para alterar, a mensagem Message.productNotInBasket(); e se a empresa não tiver exemplares suficientes, a mensagem Message.notEnoughInventory().

Se a empresa não disponibilizar o produto indicado, é lançada a excepção ProductNotSuppliedException.

Mostrar cabaz

Apresenta o cabaz: na primeira linha, o seu resumo; de seguida, as suas linhas, ordenadas pelos identificadores dos produtos e indentadas com dois espaços.

Formato de apresentação de um cabaz
 ''emailCliente'' - ''idEmpresa'' - ''estratégia'' - ''descrição do transporte e serviços'' - ''preço total dos itens''
 ␣␣''idProduto'' - ''nome'' - ''quantidade'' - ''preço unitário'' - ''total da linha''
 ␣␣...
Exemplo de apresentação de um cabaz
obiwan@jedi.org - 1 - PRAZO - EXPRESSO+EMBRULHO - 94.35
  1 - Farinha - 2 - 15.00 - 30.00
  3 - Camisa - 1 - 64.35 - 64.35

Note-se que os preços apresentados são os praticados pela empresa no momento em que o cabaz é mostrado: só são fixados ao finalizar a compra.

A descrição do transporte acompanha o estado da escolha: SEM TRANSPORTE enquanto faltar a modalidade de transporte.

Exemplos de descrição do transporte de um cabaz
SEM TRANSPORTE
EXPRESSO
NORMAL+EMBRULHO

Definir estratégia de divisão em encomendas

É pedida a estratégia (Prompt.splitStrategy()), que determina em quantas encomendas a compra será dividida. Por omissão, o cabaz usa a estratégia de encomenda única (UNICA).

Definir modalidade de transporte

É pedida a modalidade (Prompt.modality()), que será usada por todas as encomendas da compra. Por omissão, o cabaz não tem modalidade escolhida.

Adicionar serviço adicional

É pedido o serviço (Prompt.serviceToAdd()), que passa a ser aplicado a todas as encomendas da compra. É possível adicionar repetidamente um serviço.

Finalizar compra

Transforma o cabaz numa compra e fecha o menu de cabaz.

O efeito no modelo é o descrito em Cabaz de Compras.

A compra resultante é apresentada tal como em Mostrar compra, no formato de apresentação de uma compra com as encomendas em detalhe. É aí que se lêem a data prevista de entrega e o custo de cada encomenda, e o custo total da compra.

Se a compra não puder ser finalizada por faltarem exemplares de algum dos produtos, é lançada a excepção erp.app.exceptions.NotEnoughInventoryException e o menu de cabaz não é fechado.

Leitura de Dados a Partir de Ficheiros Textuais

Além das opções de manipulação de ficheiros descritas no menu principal, é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java import.

Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir as tarifas das modalidades de transporte e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter : e que os preços base e as tarifas são números inteiros. Não existem entradas mal-formadas.

O registo de modalidades de transporte, e das tarifas que cada uma pratica, segue o formato:

 RATE:''modalidade'':''custo'':''dias''

O registo de empresas e de clientes segue os formatos (o email é o identificador do cliente, pelo que não pode repetir-se):

 COMPANY:''nome''
 CLIENT:''nome'':''email''

Os produtos (registados no registo global) seguem os seguintes formatos, respectivamente, para produtos nacionais e importados:

 NATIONAL:''nome'':''preçoBase'':''categoria'':''prazo''
 IMPORTED:''nome'':''preçoBase'':''categoria'':''prazo'':''paisOrigem'':''taxa''

Note-se que o registo de um produto não indica qualquer empresa nem qualquer inventário: essas são propriedades da disponibilização, descrita por entradas próprias, em que unidades é o número de exemplares que a empresa tem disponíveis e factor o multiplicador (real) que aplica ao preço recomendado:

 SUPPLY:''idEmpresa'':''idProduto'':''unidades'':''factor''

As entradas SUPPLY referem empresas e produtos já registados em linhas anteriores.

Um exemplo de conteúdo do ficheiro inicial é como se segue:

Exemplo de ficheiro de entrada textual
RATE:NORMAL:3:3
RATE:EXPRESSO:8:1
COMPANY:Moageira Nacional
COMPANY:Importadora Atlantico
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org
CLIENT:Ahsoka Tano:ahsoka@jedi.org
NATIONAL:Farinha:15:ALIMENTAR:3
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30
NATIONAL:Camisa:45:VESTUARIO:2
SUPPLY:1:1:23:1.0
SUPPLY:2:1:150:0.9
SUPPLY:2:2:2:1.2
SUPPLY:1:3:4:1.1

A codificação dos ficheiros a ler é garantidamente UTF-8.

Os métodos String.split(), para partir cadeias de caracteres, e String.trim(), para remover espaços no início e no final, podem ser usados no processamento de cada linha.
Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).

Execução do Programa e Testes Automáticos

Usando os ficheiros test.import, test.in e test.out, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável CLASSPATH (ou da opção equivalente -cp do comando java), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (erp.app.App.main). As propriedades são tratadas automaticamente pelo código de apoio.

 java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App

Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída test.outhyp. Em caso de sucesso, os ficheiros das saídas esperada (test.out) e obtida (test.outhyp) devem ser iguais. A comparação pode ser feita com o comando:

 diff -b test.out test.outhyp

Este comando não deve produzir qualquer resultado quando os ficheiros são iguais. Note-se, contudo, que este teste não garante o correcto funcionamento do código desenvolvido, apenas verificando alguns aspectos da sua funcionalidade.

Notas de Implementação

Tal como indicado acima, algumas classes fornecidas como material de apoio, são de uso obrigatório e não podem ser alteradas. Outras dessas classes são de uso obrigatório e têm de ser alteradas.

A serialização Java usa as classes da package java.io, em particular, a interface java.io.Serializable e as classes de leitura java.io.ObjectInputStream e escrita java.io.ObjectOutputStream (entre outras).