<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://robots.hlt.inesc-id.pt/w/pt/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Root</id>
	<title>Wiki**3 - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://robots.hlt.inesc-id.pt/w/pt/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Root"/>
	<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php/Special:Contributions/Root"/>
	<updated>2026-08-28T05:23:24Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.43.3</generator>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=File:Po-uilib-202608310000.tar.bz2&amp;diff=17931</id>
		<title>File:Po-uilib-202608310000.tar.bz2</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=File:Po-uilib-202608310000.tar.bz2&amp;diff=17931"/>
		<updated>2026-08-26T15:03:04Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17930</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17930"/>
		<updated>2026-08-26T14:04:02Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Menu Principal */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão  e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Transportadoras]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe  &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.    Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;,             &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCarriers&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na  abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.  newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem          alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}                                                           {{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve desencadear as [[#Notificações|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) &#039;&#039;&#039;não&#039;&#039;&#039; é guardada: deriva da data actual.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Transportadoras&#039;&#039;&#039; -- Abre o menu de gestão de transportadoras e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Disponibilizar produto|Disponibilizar produto]],         [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}                                      {{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCompany&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompany&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompanies&#039;&#039;&#039;,    &#039;&#039;&#039;DoSupplyProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompanyProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompanyClients&#039;&#039;&#039;.}}                                           &lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, no [[#Formatos de Apresentação|formato de apresentação de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Disponibilizar produto ===&lt;br /&gt;
&lt;br /&gt;
Faz com que uma empresa passe a disponibilizar um produto já registado  no sistema. São pedidos o identificador da empresa, o identificador do  produto, o número de unidades disponíveis (&#039;&#039;&#039;Prompt.unitsToSupply()&#039;&#039;&#039;) e o factor multiplicativo do preço recomendado      (&#039;&#039;&#039;Prompt.priceFactor()&#039;&#039;&#039;, um valor real positivo). O sucesso é assinalado através da mensagem &#039;&#039;&#039;Message.supplySuccessful()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Se a empresa já disponibilizava o produto, as unidades e o factor indicados substituem os anteriores.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa disponibiliza, ordenados pelos identificadores dos produtos, no [[#Formatos de Apresentação|formato de apresentação da disponibilização de um produto por uma empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de um cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Registar produto|Registar produto]], [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoRegisterProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}                &lt;br /&gt;
&lt;br /&gt;
=== Registar produto ===&lt;br /&gt;
&lt;br /&gt;
Regista um produto no registo global de produtos. São pedidos, por esta ordem: o tipo de produto (&#039;&#039;&#039;Prompt.productType()&#039;&#039;&#039;), o nome (&#039;&#039;&#039;Prompt.productName()&#039;&#039;&#039;), o preço base (&#039;&#039;&#039;Prompt.basePrice()&#039;&#039;&#039;),  a categoria (&#039;&#039;&#039;Prompt.productCategory()&#039;&#039;&#039;) e o prazo de entrega base  (&#039;&#039;&#039;Prompt.baseDelay()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Se o tipo indicado for &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;, são ainda pedidos o país de origem (&#039;&#039;&#039;Prompt.originCountry()&#039;&#039;&#039;), a taxa alfandegária (&#039;&#039;&#039;Prompt.customsTax()&#039;&#039;&#039;) e o prazo de transporte internacional (&#039;&#039;&#039;Prompt.internationalDelay()&#039;&#039;&#039;). &lt;br /&gt;
&lt;br /&gt;
O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ProductRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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 [[#Disponibilizar produto|Disponibilizar produto]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado no [[#Formatos de Apresentação|formato de apresentação de   um produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
O inventário é uma propriedade da disponibilização de um produto por uma empresa. São pedidos o identificador da empresa, o identificador do produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;), sendo a quantidade indicada somada ao número de exemplares que essa empresa tem disponíveis.&lt;br /&gt;
&lt;br /&gt;
No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida (tornaria o inventário negativo), então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que o produto &#039;&#039;&#039;não&#039;&#039;&#039; é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura sobre o registo de produtos. São pedidos o critério de pesquisa (&#039;&#039;&#039;Prompt.searchCriterion()&#039;&#039;&#039;) e um termo (&#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Os critérios iniciais são: &#039;&#039;&#039;NOME&#039;&#039;&#039;, &#039;&#039;&#039;CATEGORIA&#039;&#039;&#039;, &#039;&#039;&#039;TIPO&#039;&#039;&#039; e &#039;&#039;&#039;ORIGEM&#039;&#039;&#039; (país de origem, que apenas os produtos importados possuem).&lt;br /&gt;
&lt;br /&gt;
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|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.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Alterar mecanismo de notificação|Alterar mecanismo de notificação]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp. app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClients&#039;&#039;&#039;, &#039;&#039;&#039;DoSetNotificationMedium&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClientNotifications&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;), o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;) e o mecanismo de notificação pretendido (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). O registo bem sucedido  é assinalado através da mensagem &#039;&#039;&#039;Message. registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, no [[#Formatos de Apresentação|formato de apresentação de um cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar mecanismo de notificação ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o novo mecanismo de notificação (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). As notificações seguintes desse cliente passam a ser produzidas através do mecanismo indicado.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 &#039;&#039;assunto&#039;&#039;: &#039;&#039;descrição da encomenda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;assunto&#039;&#039; é &#039;&#039;&#039;ENTREGA_AMANHA&#039;&#039;&#039; (a encomenda será entregue no dia seguinte) ou &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; (a encomenda foi entregue). A descrição da encomenda é a descrição resumida definida em [[#Formatos de Apresentação|Formatos de Apresentação]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ENTREGA_AMANHA: 1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
ENTREGUE: 1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Note-se que o mecanismo através do qual a notificação foi produzida (correio electrónico, WhatsApp, ...) não altera este formato. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de transportadoras. A lista completa é a seguinte: [[#Registar transportadora|Registar transportadora]], [[#Mostrar                    transportadora|Mostrar transportadora]], [[#Mostrar transportadoras|Mostrar transportadoras]], [[#Definir tarifa|Definir tarifa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.carrier.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.carrier.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.carrier.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.carrier&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarriers&#039;&#039;&#039; e &#039;&#039;&#039;DoSetRate&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar transportadora ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.carrierName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;;  caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CarrierRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da transportadora é automática e que uma transportadora recém-registada ainda não oferece   qualquer modalidade (ver [[#Definir tarifa|Definir tarifa]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadora ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;).  Na primeira linha apresenta-se a transportadora; de seguida, as suas tarifas, ordenadas pelo nome da modalidade e indentadas com dois espaços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora (com tarifas)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo de transporte&#039;&#039;&lt;br /&gt;
 ␣␣...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma transportadora|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT&lt;br /&gt;
  1 - EXPRESSO - 8 - 1&lt;br /&gt;
  1 - NORMAL - 3 - 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadoras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as transportadoras, ordenando-as pelos seus identificadores, apenas com a linha de resumo (&#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;), sem as tarifas.&lt;br /&gt;
&lt;br /&gt;
=== Definir tarifa ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;), a modalidade (&#039;&#039;&#039;Prompt.modality()&#039;&#039;&#039;), o custo adicional (&#039;&#039;&#039;Prompt.rateCost()&#039;&#039;&#039;) e o tempo de transporte (&#039;&#039;&#039;Prompt. rateTransportDays()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
A transportadora passa a oferecer a modalidade indicada com esses valores, o que é assinalado através da mensagem &#039;&#039;&#039;Message.rateSuccessful()&#039;&#039;&#039;. Se já oferecia essa modalidade, os valores         anteriores são substituídos.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar encomendas de uma compra|Mostrar encomendas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes aos pedidos deste menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039;. As mensagens do  processo de compra pertencem ao [[#Menu de Cabaz|menu de cabaz]] (&#039;&#039;&#039;erp.app.basket.Message&#039;&#039;&#039;).}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseOrders&#039;&#039;&#039;.}}                    &lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
Esta opção não efectua, por si só, qualquer compra: abre o [[#Menu de Cabaz|menu de cabaz]] sobre o cabaz de um cliente numa empresa.&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o [[#Menu de Cabaz|Menu de Cabaz]] sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido da descrição completa de cada um dos seus produtos, indentada com dois espaços. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|                                                             &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de        entrega&#039;&#039; - &#039;&#039;custo&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;descrição de produto&#039;&#039;                                              ␣␣...                                                                  }}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma compra|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - 1 - 1 - 1 - 94 - 30 - 124&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15&lt;br /&gt;
  3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15&lt;br /&gt;
  1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 171&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de uma compra]] (apenas a linha da compra, sem as encomendas).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar encomendas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as encomendas correspondentes, ordenadas pela data prevista de entrega e, em caso de  empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar  compra|Mostrar compra]] (que apresenta as encomendas em detalhe), aqui  cada encomenda é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, terminada pela lista de identificadores dos seus produtos), no [[#Formatos de Apresentação|formato de apresentação resumida de uma encomenda]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de encomendas (compra do exemplo anterior)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17929</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17929"/>
		<updated>2026-08-26T13:59:56Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Menu de Gestão de Empresas */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Disponibilizar produto|Disponibilizar produto]],         [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}                                      {{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCompany&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompany&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompanies&#039;&#039;&#039;,    &#039;&#039;&#039;DoSupplyProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompanyProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCompanyClients&#039;&#039;&#039;.}}                                           &lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, no [[#Formatos de Apresentação|formato de apresentação de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Disponibilizar produto ===&lt;br /&gt;
&lt;br /&gt;
Faz com que uma empresa passe a disponibilizar um produto já registado  no sistema. São pedidos o identificador da empresa, o identificador do  produto, o número de unidades disponíveis (&#039;&#039;&#039;Prompt.unitsToSupply()&#039;&#039;&#039;) e o factor multiplicativo do preço recomendado      (&#039;&#039;&#039;Prompt.priceFactor()&#039;&#039;&#039;, um valor real positivo). O sucesso é assinalado através da mensagem &#039;&#039;&#039;Message.supplySuccessful()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Se a empresa já disponibilizava o produto, as unidades e o factor indicados substituem os anteriores.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa disponibiliza, ordenados pelos identificadores dos produtos, no [[#Formatos de Apresentação|formato de apresentação da disponibilização de um produto por uma empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de um cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Registar produto|Registar produto]], [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoRegisterProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}                &lt;br /&gt;
&lt;br /&gt;
=== Registar produto ===&lt;br /&gt;
&lt;br /&gt;
Regista um produto no registo global de produtos. São pedidos, por esta ordem: o tipo de produto (&#039;&#039;&#039;Prompt.productType()&#039;&#039;&#039;), o nome (&#039;&#039;&#039;Prompt.productName()&#039;&#039;&#039;), o preço base (&#039;&#039;&#039;Prompt.basePrice()&#039;&#039;&#039;),  a categoria (&#039;&#039;&#039;Prompt.productCategory()&#039;&#039;&#039;) e o prazo de entrega base  (&#039;&#039;&#039;Prompt.baseDelay()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Se o tipo indicado for &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;, são ainda pedidos o país de origem (&#039;&#039;&#039;Prompt.originCountry()&#039;&#039;&#039;), a taxa alfandegária (&#039;&#039;&#039;Prompt.customsTax()&#039;&#039;&#039;) e o prazo de transporte internacional (&#039;&#039;&#039;Prompt.internationalDelay()&#039;&#039;&#039;). &lt;br /&gt;
&lt;br /&gt;
O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ProductRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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 [[#Disponibilizar produto|Disponibilizar produto]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado no [[#Formatos de Apresentação|formato de apresentação de   um produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
O inventário é uma propriedade da disponibilização de um produto por uma empresa. São pedidos o identificador da empresa, o identificador do produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;), sendo a quantidade indicada somada ao número de exemplares que essa empresa tem disponíveis.&lt;br /&gt;
&lt;br /&gt;
No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida (tornaria o inventário negativo), então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que o produto &#039;&#039;&#039;não&#039;&#039;&#039; é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura sobre o registo de produtos. São pedidos o critério de pesquisa (&#039;&#039;&#039;Prompt.searchCriterion()&#039;&#039;&#039;) e um termo (&#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Os critérios iniciais são: &#039;&#039;&#039;NOME&#039;&#039;&#039;, &#039;&#039;&#039;CATEGORIA&#039;&#039;&#039;, &#039;&#039;&#039;TIPO&#039;&#039;&#039; e &#039;&#039;&#039;ORIGEM&#039;&#039;&#039; (país de origem, que apenas os produtos importados possuem).&lt;br /&gt;
&lt;br /&gt;
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|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.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Alterar mecanismo de notificação|Alterar mecanismo de notificação]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp. app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClients&#039;&#039;&#039;, &#039;&#039;&#039;DoSetNotificationMedium&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClientNotifications&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;), o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;) e o mecanismo de notificação pretendido (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). O registo bem sucedido  é assinalado através da mensagem &#039;&#039;&#039;Message. registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, no [[#Formatos de Apresentação|formato de apresentação de um cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar mecanismo de notificação ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o novo mecanismo de notificação (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). As notificações seguintes desse cliente passam a ser produzidas através do mecanismo indicado.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 &#039;&#039;assunto&#039;&#039;: &#039;&#039;descrição da encomenda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;assunto&#039;&#039; é &#039;&#039;&#039;ENTREGA_AMANHA&#039;&#039;&#039; (a encomenda será entregue no dia seguinte) ou &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; (a encomenda foi entregue). A descrição da encomenda é a descrição resumida definida em [[#Formatos de Apresentação|Formatos de Apresentação]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ENTREGA_AMANHA: 1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
ENTREGUE: 1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Note-se que o mecanismo através do qual a notificação foi produzida (correio electrónico, WhatsApp, ...) não altera este formato. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de transportadoras. A lista completa é a seguinte: [[#Registar transportadora|Registar transportadora]], [[#Mostrar                    transportadora|Mostrar transportadora]], [[#Mostrar transportadoras|Mostrar transportadoras]], [[#Definir tarifa|Definir tarifa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.carrier.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.carrier.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.carrier.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.carrier&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarriers&#039;&#039;&#039; e &#039;&#039;&#039;DoSetRate&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar transportadora ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.carrierName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;;  caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CarrierRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da transportadora é automática e que uma transportadora recém-registada ainda não oferece   qualquer modalidade (ver [[#Definir tarifa|Definir tarifa]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadora ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;).  Na primeira linha apresenta-se a transportadora; de seguida, as suas tarifas, ordenadas pelo nome da modalidade e indentadas com dois espaços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora (com tarifas)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo de transporte&#039;&#039;&lt;br /&gt;
 ␣␣...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma transportadora|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT&lt;br /&gt;
  1 - EXPRESSO - 8 - 1&lt;br /&gt;
  1 - NORMAL - 3 - 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadoras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as transportadoras, ordenando-as pelos seus identificadores, apenas com a linha de resumo (&#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;), sem as tarifas.&lt;br /&gt;
&lt;br /&gt;
=== Definir tarifa ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;), a modalidade (&#039;&#039;&#039;Prompt.modality()&#039;&#039;&#039;), o custo adicional (&#039;&#039;&#039;Prompt.rateCost()&#039;&#039;&#039;) e o tempo de transporte (&#039;&#039;&#039;Prompt. rateTransportDays()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
A transportadora passa a oferecer a modalidade indicada com esses valores, o que é assinalado através da mensagem &#039;&#039;&#039;Message.rateSuccessful()&#039;&#039;&#039;. Se já oferecia essa modalidade, os valores         anteriores são substituídos.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar encomendas de uma compra|Mostrar encomendas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes aos pedidos deste menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039;. As mensagens do  processo de compra pertencem ao [[#Menu de Cabaz|menu de cabaz]] (&#039;&#039;&#039;erp.app.basket.Message&#039;&#039;&#039;).}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseOrders&#039;&#039;&#039;.}}                    &lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
Esta opção não efectua, por si só, qualquer compra: abre o [[#Menu de Cabaz|menu de cabaz]] sobre o cabaz de um cliente numa empresa.&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o [[#Menu de Cabaz|Menu de Cabaz]] sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido da descrição completa de cada um dos seus produtos, indentada com dois espaços. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|                                                             &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de        entrega&#039;&#039; - &#039;&#039;custo&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;descrição de produto&#039;&#039;                                              ␣␣...                                                                  }}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma compra|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - 1 - 1 - 1 - 94 - 30 - 124&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15&lt;br /&gt;
  3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15&lt;br /&gt;
  1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 171&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de uma compra]] (apenas a linha da compra, sem as encomendas).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar encomendas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as encomendas correspondentes, ordenadas pela data prevista de entrega e, em caso de  empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar  compra|Mostrar compra]] (que apresenta as encomendas em detalhe), aqui  cada encomenda é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, terminada pela lista de identificadores dos seus produtos), no [[#Formatos de Apresentação|formato de apresentação resumida de uma encomenda]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de encomendas (compra do exemplo anterior)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17928</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17928"/>
		<updated>2026-08-26T13:55:55Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Menu de Gestão de Produtos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Registar produto|Registar produto]], [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoRegisterProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}                &lt;br /&gt;
&lt;br /&gt;
=== Registar produto ===&lt;br /&gt;
&lt;br /&gt;
Regista um produto no registo global de produtos. São pedidos, por esta ordem: o tipo de produto (&#039;&#039;&#039;Prompt.productType()&#039;&#039;&#039;), o nome (&#039;&#039;&#039;Prompt.productName()&#039;&#039;&#039;), o preço base (&#039;&#039;&#039;Prompt.basePrice()&#039;&#039;&#039;),  a categoria (&#039;&#039;&#039;Prompt.productCategory()&#039;&#039;&#039;) e o prazo de entrega base  (&#039;&#039;&#039;Prompt.baseDelay()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Se o tipo indicado for &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;, são ainda pedidos o país de origem (&#039;&#039;&#039;Prompt.originCountry()&#039;&#039;&#039;), a taxa alfandegária (&#039;&#039;&#039;Prompt.customsTax()&#039;&#039;&#039;) e o prazo de transporte internacional (&#039;&#039;&#039;Prompt.internationalDelay()&#039;&#039;&#039;). &lt;br /&gt;
&lt;br /&gt;
O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ProductRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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 [[#Disponibilizar produto|Disponibilizar produto]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado no [[#Formatos de Apresentação|formato de apresentação de   um produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
O inventário é uma propriedade da disponibilização de um produto por uma empresa. São pedidos o identificador da empresa, o identificador do produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;), sendo a quantidade indicada somada ao número de exemplares que essa empresa tem disponíveis.&lt;br /&gt;
&lt;br /&gt;
No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida (tornaria o inventário negativo), então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que o produto &#039;&#039;&#039;não&#039;&#039;&#039; é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura sobre o registo de produtos. São pedidos o critério de pesquisa (&#039;&#039;&#039;Prompt.searchCriterion()&#039;&#039;&#039;) e um termo (&#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Os critérios iniciais são: &#039;&#039;&#039;NOME&#039;&#039;&#039;, &#039;&#039;&#039;CATEGORIA&#039;&#039;&#039;, &#039;&#039;&#039;TIPO&#039;&#039;&#039; e &#039;&#039;&#039;ORIGEM&#039;&#039;&#039; (país de origem, que apenas os produtos importados possuem).&lt;br /&gt;
&lt;br /&gt;
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|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.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Alterar mecanismo de notificação|Alterar mecanismo de notificação]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp. app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClients&#039;&#039;&#039;, &#039;&#039;&#039;DoSetNotificationMedium&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClientNotifications&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;), o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;) e o mecanismo de notificação pretendido (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). O registo bem sucedido  é assinalado através da mensagem &#039;&#039;&#039;Message. registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, no [[#Formatos de Apresentação|formato de apresentação de um cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar mecanismo de notificação ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o novo mecanismo de notificação (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). As notificações seguintes desse cliente passam a ser produzidas através do mecanismo indicado.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 &#039;&#039;assunto&#039;&#039;: &#039;&#039;descrição da encomenda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;assunto&#039;&#039; é &#039;&#039;&#039;ENTREGA_AMANHA&#039;&#039;&#039; (a encomenda será entregue no dia seguinte) ou &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; (a encomenda foi entregue). A descrição da encomenda é a descrição resumida definida em [[#Formatos de Apresentação|Formatos de Apresentação]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ENTREGA_AMANHA: 1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
ENTREGUE: 1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Note-se que o mecanismo através do qual a notificação foi produzida (correio electrónico, WhatsApp, ...) não altera este formato. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de transportadoras. A lista completa é a seguinte: [[#Registar transportadora|Registar transportadora]], [[#Mostrar                    transportadora|Mostrar transportadora]], [[#Mostrar transportadoras|Mostrar transportadoras]], [[#Definir tarifa|Definir tarifa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.carrier.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.carrier.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.carrier.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.carrier&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarriers&#039;&#039;&#039; e &#039;&#039;&#039;DoSetRate&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar transportadora ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.carrierName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;;  caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CarrierRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da transportadora é automática e que uma transportadora recém-registada ainda não oferece   qualquer modalidade (ver [[#Definir tarifa|Definir tarifa]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadora ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;).  Na primeira linha apresenta-se a transportadora; de seguida, as suas tarifas, ordenadas pelo nome da modalidade e indentadas com dois espaços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora (com tarifas)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo de transporte&#039;&#039;&lt;br /&gt;
 ␣␣...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma transportadora|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT&lt;br /&gt;
  1 - EXPRESSO - 8 - 1&lt;br /&gt;
  1 - NORMAL - 3 - 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadoras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as transportadoras, ordenando-as pelos seus identificadores, apenas com a linha de resumo (&#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;), sem as tarifas.&lt;br /&gt;
&lt;br /&gt;
=== Definir tarifa ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;), a modalidade (&#039;&#039;&#039;Prompt.modality()&#039;&#039;&#039;), o custo adicional (&#039;&#039;&#039;Prompt.rateCost()&#039;&#039;&#039;) e o tempo de transporte (&#039;&#039;&#039;Prompt. rateTransportDays()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
A transportadora passa a oferecer a modalidade indicada com esses valores, o que é assinalado através da mensagem &#039;&#039;&#039;Message.rateSuccessful()&#039;&#039;&#039;. Se já oferecia essa modalidade, os valores         anteriores são substituídos.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar encomendas de uma compra|Mostrar encomendas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes aos pedidos deste menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039;. As mensagens do  processo de compra pertencem ao [[#Menu de Cabaz|menu de cabaz]] (&#039;&#039;&#039;erp.app.basket.Message&#039;&#039;&#039;).}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseOrders&#039;&#039;&#039;.}}                    &lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
Esta opção não efectua, por si só, qualquer compra: abre o [[#Menu de Cabaz|menu de cabaz]] sobre o cabaz de um cliente numa empresa.&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o [[#Menu de Cabaz|Menu de Cabaz]] sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido da descrição completa de cada um dos seus produtos, indentada com dois espaços. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|                                                             &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de        entrega&#039;&#039; - &#039;&#039;custo&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;descrição de produto&#039;&#039;                                              ␣␣...                                                                  }}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma compra|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - 1 - 1 - 1 - 94 - 30 - 124&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15&lt;br /&gt;
  3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15&lt;br /&gt;
  1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 171&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de uma compra]] (apenas a linha da compra, sem as encomendas).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar encomendas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as encomendas correspondentes, ordenadas pela data prevista de entrega e, em caso de  empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar  compra|Mostrar compra]] (que apresenta as encomendas em detalhe), aqui  cada encomenda é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, terminada pela lista de identificadores dos seus produtos), no [[#Formatos de Apresentação|formato de apresentação resumida de uma encomenda]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de encomendas (compra do exemplo anterior)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17927</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17927"/>
		<updated>2026-08-26T13:29:59Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Menu de Gestão de Clientes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Alterar mecanismo de notificação|Alterar mecanismo de notificação]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp. app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClient&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClients&#039;&#039;&#039;, &#039;&#039;&#039;DoSetNotificationMedium&#039;&#039;&#039;, &#039;&#039;&#039;DoShowClientNotifications&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;), o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;) e o mecanismo de notificação pretendido (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). O registo bem sucedido  é assinalado através da mensagem &#039;&#039;&#039;Message. registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção       &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, no [[#Formatos de Apresentação|formato de apresentação de um cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar mecanismo de notificação ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o novo mecanismo de notificação (&#039;&#039;&#039;Prompt.notificationMedium()&#039;&#039;&#039;). As notificações seguintes desse cliente passam a ser produzidas através do mecanismo indicado.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 &#039;&#039;assunto&#039;&#039;: &#039;&#039;descrição da encomenda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;assunto&#039;&#039; é &#039;&#039;&#039;ENTREGA_AMANHA&#039;&#039;&#039; (a encomenda será entregue no dia seguinte) ou &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; (a encomenda foi entregue). A descrição da encomenda é a descrição resumida definida em [[#Formatos de Apresentação|Formatos de Apresentação]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
ENTREGA_AMANHA: 1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
ENTREGUE: 1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Note-se que o mecanismo através do qual a notificação foi produzida (correio electrónico, WhatsApp, ...) não altera este formato. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de transportadoras. A lista completa é a seguinte: [[#Registar transportadora|Registar transportadora]], [[#Mostrar                    transportadora|Mostrar transportadora]], [[#Mostrar transportadoras|Mostrar transportadoras]], [[#Definir tarifa|Definir tarifa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.carrier.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.carrier.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.carrier.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.carrier&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarriers&#039;&#039;&#039; e &#039;&#039;&#039;DoSetRate&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar transportadora ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.carrierName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;;  caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CarrierRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da transportadora é automática e que uma transportadora recém-registada ainda não oferece   qualquer modalidade (ver [[#Definir tarifa|Definir tarifa]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadora ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;).  Na primeira linha apresenta-se a transportadora; de seguida, as suas tarifas, ordenadas pelo nome da modalidade e indentadas com dois espaços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora (com tarifas)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo de transporte&#039;&#039;&lt;br /&gt;
 ␣␣...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma transportadora|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT&lt;br /&gt;
  1 - EXPRESSO - 8 - 1&lt;br /&gt;
  1 - NORMAL - 3 - 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadoras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as transportadoras, ordenando-as pelos seus identificadores, apenas com a linha de resumo (&#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;), sem as tarifas.&lt;br /&gt;
&lt;br /&gt;
=== Definir tarifa ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;), a modalidade (&#039;&#039;&#039;Prompt.modality()&#039;&#039;&#039;), o custo adicional (&#039;&#039;&#039;Prompt.rateCost()&#039;&#039;&#039;) e o tempo de transporte (&#039;&#039;&#039;Prompt. rateTransportDays()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
A transportadora passa a oferecer a modalidade indicada com esses valores, o que é assinalado através da mensagem &#039;&#039;&#039;Message.rateSuccessful()&#039;&#039;&#039;. Se já oferecia essa modalidade, os valores         anteriores são substituídos.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar encomendas de uma compra|Mostrar encomendas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes aos pedidos deste menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039;. As mensagens do  processo de compra pertencem ao [[#Menu de Cabaz|menu de cabaz]] (&#039;&#039;&#039;erp.app.basket.Message&#039;&#039;&#039;).}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseOrders&#039;&#039;&#039;.}}                    &lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
Esta opção não efectua, por si só, qualquer compra: abre o [[#Menu de Cabaz|menu de cabaz]] sobre o cabaz de um cliente numa empresa.&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o [[#Menu de Cabaz|Menu de Cabaz]] sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido da descrição completa de cada um dos seus produtos, indentada com dois espaços. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|                                                             &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de        entrega&#039;&#039; - &#039;&#039;custo&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;descrição de produto&#039;&#039;                                              ␣␣...                                                                  }}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma compra|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - 1 - 1 - 1 - 94 - 30 - 124&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15&lt;br /&gt;
  3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15&lt;br /&gt;
  1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 171&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de uma compra]] (apenas a linha da compra, sem as encomendas).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar encomendas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as encomendas correspondentes, ordenadas pela data prevista de entrega e, em caso de  empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar  compra|Mostrar compra]] (que apresenta as encomendas em detalhe), aqui  cada encomenda é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, terminada pela lista de identificadores dos seus produtos), no [[#Formatos de Apresentação|formato de apresentação resumida de uma encomenda]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de encomendas (compra do exemplo anterior)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17926</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17926"/>
		<updated>2026-08-26T13:24:34Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Menu de Gestão de Compras */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de transportadoras. A lista completa é a seguinte: [[#Registar transportadora|Registar transportadora]], [[#Mostrar                    transportadora|Mostrar transportadora]], [[#Mostrar transportadoras|Mostrar transportadoras]], [[#Definir tarifa|Definir tarifa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.carrier.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.carrier.Prompt&#039;&#039;&#039;  e &#039;&#039;&#039;erp.app.carrier.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.carrier&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoRegisterCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarrier&#039;&#039;&#039;, &#039;&#039;&#039;DoShowCarriers&#039;&#039;&#039; e &#039;&#039;&#039;DoSetRate&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar transportadora ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.carrierName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;;  caso contrário, é lançada a excepção                                    &#039;&#039;&#039;CarrierRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da transportadora é automática e que uma transportadora recém-registada ainda não oferece   qualquer modalidade (ver [[#Definir tarifa|Definir tarifa]]).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadora ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;).  Na primeira linha apresenta-se a transportadora; de seguida, as suas tarifas, ordenadas pelo nome da modalidade e indentadas com dois espaços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora (com tarifas)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo de transporte&#039;&#039;&lt;br /&gt;
 ␣␣...&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma transportadora|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT&lt;br /&gt;
  1 - EXPRESSO - 8 - 1&lt;br /&gt;
  1 - NORMAL - 3 - 3&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar transportadoras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as transportadoras, ordenando-as pelos seus identificadores, apenas com a linha de resumo (&#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;), sem as tarifas.&lt;br /&gt;
&lt;br /&gt;
=== Definir tarifa ===&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador da transportadora (&#039;&#039;&#039;Prompt.carrierId()&#039;&#039;&#039;), a modalidade (&#039;&#039;&#039;Prompt.modality()&#039;&#039;&#039;), o custo adicional (&#039;&#039;&#039;Prompt.rateCost()&#039;&#039;&#039;) e o tempo de transporte (&#039;&#039;&#039;Prompt. rateTransportDays()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
A transportadora passa a oferecer a modalidade indicada com esses valores, o que é assinalado através da mensagem &#039;&#039;&#039;Message.rateSuccessful()&#039;&#039;&#039;. Se já oferecia essa modalidade, os valores         anteriores são substituídos.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar encomendas de uma compra|Mostrar encomendas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes aos pedidos deste menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039;. As mensagens do  processo de compra pertencem ao [[#Menu de Cabaz|menu de cabaz]] (&#039;&#039;&#039;erp.app.basket.Message&#039;&#039;&#039;).}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseOrders&#039;&#039;&#039;.}}                    &lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
Esta opção não efectua, por si só, qualquer compra: abre o [[#Menu de Cabaz|menu de cabaz]] sobre o cabaz de um cliente numa empresa.&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o [[#Menu de Cabaz|Menu de Cabaz]] sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido da descrição completa de cada um dos seus produtos, indentada com dois espaços. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|                                                             &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de        entrega&#039;&#039; - &#039;&#039;custo&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;descrição de produto&#039;&#039;                                              ␣␣...                                                                  }}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma compra|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - 1 - 1 - 1 - 94 - 30 - 124&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15&lt;br /&gt;
  3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15&lt;br /&gt;
  1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 171&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de uma compra]] (apenas a linha da compra, sem as encomendas).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar encomendas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as encomendas correspondentes, ordenadas pela data prevista de entrega e, em caso de  empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar  compra|Mostrar compra]] (que apresenta as encomendas em detalhe), aqui  cada encomenda é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, terminada pela lista de identificadores dos seus produtos), no [[#Formatos de Apresentação|formato de apresentação resumida de uma encomenda]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de encomendas (compra do exemplo anterior)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17925</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17925"/>
		<updated>2026-08-26T13:20:09Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Menu de Gestão de Compras */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e encomendas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar encomendas de uma compra|Mostrar encomendas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp. app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes aos pedidos deste menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039;. As mensagens do  processo de compra pertencem ao [[#Menu de Cabaz|menu de cabaz]] (&#039;&#039;&#039;erp.app.basket.Message&#039;&#039;&#039;).}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseOrders&#039;&#039;&#039;.}}                    &lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
Esta opção não efectua, por si só, qualquer compra: abre o [[#Menu de Cabaz|menu de cabaz]] sobre o cabaz de um cliente numa empresa.&lt;br /&gt;
&lt;br /&gt;
São pedidos o identificador do cliente e o identificador da empresa. Se ambos existirem, é aberto o [[#Menu de Cabaz|Menu de Cabaz]] sobre o cabaz desse cliente nessa empresa (criado vazio, se ainda não existir).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas encomendas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — o cabeçalho de cada encomenda (sem a lista de identificadores de produtos) seguido da descrição completa de cada um dos seus produtos, indentada com dois espaços. As encomendas são apresentadas por ordem crescente da data prevista de entrega e, em caso de empate, pelos identificadores dos produtos.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com encomendas em detalhe)|                                                             &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de        entrega&#039;&#039; - &#039;&#039;custo&#039;&#039;&lt;br /&gt;
 ␣␣&#039;&#039;descrição de produto&#039;&#039;                                              ␣␣...                                                                  }}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de uma compra|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - 1 - 1 - 1 - 94 - 30 - 124&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15&lt;br /&gt;
  3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15&lt;br /&gt;
  1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 171&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores, no [[#Formatos de Apresentação|formato de apresentação de uma compra]] (apenas a linha da compra, sem as encomendas).&lt;br /&gt;
&lt;br /&gt;
=== Mostrar encomendas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as encomendas correspondentes, ordenadas pela data prevista de entrega e, em caso de  empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar  compra|Mostrar compra]] (que apresenta as encomendas em detalhe), aqui  cada encomenda é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, terminada pela lista de identificadores dos seus produtos), no [[#Formatos de Apresentação|formato de apresentação resumida de uma encomenda]].&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de apresentação de encomendas (compra do exemplo anterior)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17924</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17924"/>
		<updated>2026-08-26T13:14:19Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Notas de Implementação */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação  com Objectos/Projecto de Programação com Objectos/Material de Apoio ao  Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/package-summary.html   java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/Serializable.html java.io.         Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/26/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).                                     &lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17923</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17923"/>
		<updated>2026-08-26T13:12:42Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Execução do Programa e Testes Automáticos */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;,  é possível verificar automaticamente o resultado correcto do programa.  Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando           &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
  java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
  diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17922</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17922"/>
		<updated>2026-08-26T13:11:09Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Leitura de Dados a Partir de Ficheiros Textuais */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do  Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato  geral. É possível registar transportadoras, empresas, clientes e produtos, e definir as tarifas das transportadoras e as disponibilizações de produtos por parte das empresas. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
O registo de transportadoras, e das tarifas que cada uma pratica, segue os formatos:                                                            &lt;br /&gt;
 CARRIER:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 RATE:&#039;&#039;idTransportadora&#039;&#039;:&#039;&#039;modalidade&#039;&#039;:&#039;&#039;custo&#039;&#039;:&#039;&#039;dias&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;RATE&#039;&#039;&#039; referem transportadoras já registadas em linhas  anteriores.                                                                                                                                     O registo de empresas e de clientes segue os formatos:                  &lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;:&#039;&#039;mecanismo&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;mecanismo&#039;&#039; é &#039;&#039;&#039;EMAIL&#039;&#039;&#039; ou &#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;; se for omitido, assume-se &#039;&#039;&#039;EMAIL&#039;&#039;&#039;.                                                                                                                                 Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:&lt;br /&gt;
&lt;br /&gt;
Os produtos são registados no registo global, respectivamente para      produtos nacionais e importados:                                        &lt;br /&gt;
 NATIONAL:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;nome&#039;&#039;:&#039;&#039;preçoBase&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;:&#039;&#039;prazoInternacional&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;unidades&#039;&#039; é o número de exemplares que a empresa tem disponíveis e &#039;&#039;factor&#039;&#039; o multiplicador (real) que aplica ao preço recomendado:&lt;br /&gt;
 SUPPLY:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;idProduto&#039;&#039;:&#039;&#039;unidades&#039;&#039;:&#039;&#039;factor&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As entradas &#039;&#039;&#039;SUPPLY&#039;&#039;&#039; referem empresas e produtos já registados em   linhas anteriores.&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
CARRIER:CTT&lt;br /&gt;
RATE:1:NORMAL:3:3&lt;br /&gt;
RATE:1:EXPRESSO:8:1&lt;br /&gt;
CARRIER:DHL&lt;br /&gt;
RATE:2:NORMAL:5:2&lt;br /&gt;
RATE:2:EXPRESSO:12:1&lt;br /&gt;
CARRIER:SEUR&lt;br /&gt;
RATE:3:EXPRESSO:10:1&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
CLIENT:Ahsoka Tano:ahsoka@jedi.org:WHATSAPP&lt;br /&gt;
NATIONAL:Farinha:15:ALIMENTAR:3&lt;br /&gt;
IMPORTED:Telemovel:200:ELECTRONICA:3:China:30:5&lt;br /&gt;
NATIONAL:Camisa:45:VESTUARIO:2&lt;br /&gt;
SUPPLY:1:1:23:1.0&lt;br /&gt;
SUPPLY:2:1:150:0.9&lt;br /&gt;
SUPPLY:2:2:2:1.2&lt;br /&gt;
SUPPLY:1:3:4:1.1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no  final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17921</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17921"/>
		<updated>2026-08-26T13:05:58Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Interacção com o utilizador */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação    com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes   de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Transportadora&lt;br /&gt;
| &#039;&#039;&#039;Carrier&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.carrier.Prompt.carrierId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCarrierKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Existe ainda um caso particular: sempre que uma operação se refira a um produto &#039;&#039;&#039;no contexto de uma empresa&#039;&#039;&#039; e essa empresa não disponibilize esse produto, deve ser lançada a excepção &#039;&#039;&#039;erp.app.exceptions.ProductNotSuppliedException&#039;&#039;&#039; (a empresa e o produto existem, mas não estão relacionados).&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
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, mecanismo de notificação e critério   de pesquisa). Estas escolhas &#039;&#039;&#039;devem&#039;&#039;&#039; ser pedidas através de campos  de opção (&#039;&#039;&#039;Form.addOptionField()&#039;&#039;&#039; ou &#039;&#039;&#039;Form.requestOption()&#039;&#039;&#039;),   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, mecanismo ou critério não implica qualquer alteração aos comandos.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;.    Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Formatos de Apresentação ==&lt;br /&gt;
&lt;br /&gt;
Os formatos usados pelos vários comandos são os seguintes. Todos os     campos são separados por &#039;&#039;&#039;␣-␣&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma transportadora|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma tarifa|&lt;br /&gt;
 &#039;&#039;idTransportadora&#039;&#039; - &#039;&#039;modalidade&#039;&#039; - &#039;&#039;custo adicional&#039;&#039; - &#039;&#039;tempo  de transporte&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um produto|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;preço base&#039;&#039; - &#039;&#039;preço recomendado&#039;&#039; - &#039;&#039;prazo base&#039;&#039; - &#039;&#039;unidades totais&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;tipo&#039;&#039; é &#039;&#039;&#039;NACIONAL&#039;&#039;&#039; ou &#039;&#039;&#039;IMPORTADO&#039;&#039;&#039;. As &#039;&#039;unidades totais&#039;&#039; 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, à taxa alfandegária e ao prazo de transporte internacional.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - NACIONAL - Farinha - ALIMENTAR - 15 - 15 - 3 - 173&lt;br /&gt;
2 - IMPORTADO - Telemovel - ELECTRONICA - 200 - 260 - 3 - 2 - China -   30 - 5&lt;br /&gt;
3 - NACIONAL - Camisa - VESTUARIO - 45 - 58 - 2 - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação da disponibilização de um produto por uma empresa|&lt;br /&gt;
  &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;idProduto&#039;&#039; - &#039;&#039;unidades&#039;&#039; - &#039;&#039;factor&#039;&#039; - &#039;&#039;preço de venda&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de disponibilizações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - 1 - 150 - 0.9 - 14&lt;br /&gt;
2 - 2 - 2 - 1.2 - 312&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;mecanismo de notificação&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
O valor apresentado no fim corresponde ao total gasto pelo cliente em   compras (um valor inteiro).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Ahsoka Tano - ahsoka@jedi.org - WHATSAPP - 0&lt;br /&gt;
1 - Obi-Wan Kenobi - obiwan@jedi.org - EMAIL - 124&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos  itens&#039;&#039; - &#039;&#039;custo das encomendas&#039;&#039; - &#039;&#039;custo total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Formato de apresentação (resumida) de uma encomenda|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;descrição do transporte&#039;&#039; - &#039;&#039;data prevista de entrega&#039;&#039; - &#039;&#039;custo&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
A &#039;&#039;descrição do transporte&#039;&#039; é o nome da transportadora e a modalidade seleccionadas, separados por &#039;&#039;&#039;/&#039;&#039;&#039;, seguidos das chaves dos serviços  adicionais seleccionados, separadas por &#039;&#039;&#039;+&#039;&#039;&#039; (por exemplo, &#039;&#039;&#039;DHL/   EXPRESSO+EMBRULHO+CARTAO_OFERTA&#039;&#039;&#039;). O &#039;&#039;custo&#039;&#039; de uma encomenda é o   custo base de processamento acrescido do custo da modalidade e dos      serviços.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de encomendas|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 5 - 15 - 3&lt;br /&gt;
1 - CTT/EXPRESSO+EMBRULHO - 6 - 15 - 1&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17920</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17920"/>
		<updated>2026-08-26T12:50:37Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é            exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo   &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Transportadoras|transportadoras]], [[#Cabaz de Compras|cabazes]],    [[#Compras|compras]], [[#Divisão das Compras em Encomendas|encomendas]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa, e resulta de finalizar um [[#Cabaz de Compras|cabaz]]. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de      entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.                                               &lt;br /&gt;
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.                                               &lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.                                          &lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:                                                                                                                                     &lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.                         &lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.                                &lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos.                                                                                                                   &lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma  única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas.                                                                                                                                    Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma  estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo  total da compra.&lt;br /&gt;
&lt;br /&gt;
== Cabaz de Compras ==&lt;br /&gt;
&lt;br /&gt;
Antes de dar origem a uma compra, os produtos que um cliente pretende adquirir a uma empresa são acumulados num &#039;&#039;&#039;cabaz&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O cabaz regista ainda as opções que serão aplicadas à compra:&lt;br /&gt;
* a [[#Divisão das Compras em Encomendas|estratégia de divisão em encomendas]];                                                           * a [[#Transportadoras|transportadora]] e a [[#Transportadoras|modalidade de transporte]]; e&lt;br /&gt;
* o conjunto de [[#Serviços Adicionais|serviços adicionais]].&lt;br /&gt;
&lt;br /&gt;
A transportadora, a modalidade e os serviços adicionais escolhidos aplicam-se a &#039;&#039;&#039;todas&#039;&#039;&#039; as encomendas resultantes da compra.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;nesse momento&#039;&#039;&#039;. Um cabaz faz parte do estado persistente da aplicação: pode ser abandonado e retomado mais tarde.&lt;br /&gt;
&lt;br /&gt;
Ao &#039;&#039;&#039;finalizar&#039;&#039;&#039; o cabaz, e apenas nesse momento:&lt;br /&gt;
* os preços de venda são fixados nas linhas da compra;&lt;br /&gt;
* a compra é dividida em encomendas de acordo com a estratégia registada no cabaz;&lt;br /&gt;
* todas as encomendas recebem a modalidade de transporte e os serviços adicionais registados no cabaz;&lt;br /&gt;
* o inventário dos produtos na empresa é decrementado e o cliente é debitado;&lt;br /&gt;
* o cabaz fica vazio.&lt;br /&gt;
&lt;br /&gt;
Um cabaz vazio não pode ser finalizado, nem o pode ser um cabaz em que ainda não tenham sido escolhidas transportadora e modalidade. Se, no momento de finalizar, a empresa já não tiver exemplares suficientes de  algum dos produtos do cabaz (por exemplo, porque o inventário foi entretanto alterado), a operação falha sem qualquer efeito e o cabaz mantém-se intacto.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição, de &#039;&#039;&#039;5 euros&#039;&#039;&#039;. Assim, uma compra dividida em várias encomendas pode ter um   custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos   acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais das tarifas de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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 (&#039;&#039;&#039;UNICA&#039;&#039;&#039;) e agrupamento por prazo de entrega (&#039;&#039;&#039;PRAZO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa     entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das &#039;&#039;&#039;transportadoras&#039;&#039;&#039; que operam na plataforma. Cada transportadora é identificada por um número de transportadora. 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 transportadora tem ainda um nome (cadeia de caracteres não vazia).&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora, segundo uma     &#039;&#039;&#039;modalidade de transporte&#039;&#039;&#039;. Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal (&#039;&#039;&#039;NORMAL&#039;&#039;&#039;) e expresso  (&#039;&#039;&#039;EXPRESSO&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Uma modalidade &#039;&#039;&#039;não&#039;&#039;&#039; define, por si só, qualquer custo ou prazo: é  apenas o nome de um nível de serviço. Para cada modalidade que oferece, uma transportadora define uma &#039;&#039;&#039;tarifa&#039;&#039;&#039;, constituída por:&lt;br /&gt;
* um custo adicional (número inteiro); e&lt;br /&gt;
* um tempo de transporte (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
Assim, a mesma modalidade pode custar e demorar valores diferentes consoante a transportadora.&lt;br /&gt;
&lt;br /&gt;
Uma transportadora &#039;&#039;&#039;não tem de oferecer todas as modalidades&#039;&#039;&#039;: oferece exactamente aquelas para as quais tenha uma tarifa definida. Pedir a uma transportadora uma modalidade que ela não oferece é um erro, e não uma escolha silenciosamente ignorada — ver [[#Definir modalidade de transporte|Definir modalidade de transporte]].&lt;br /&gt;
&lt;br /&gt;
Entre os dois, &#039;&#039;&#039;a transportadora tem precedência sobre a modalidade&#039;&#039;&#039;: como as modalidades disponíveis são as da transportadora, só se pode escolher uma modalidade depois de escolhida a transportadora, e mudar de transportadora anula a modalidade          anteriormente escolhida (que passa a ser escolhida de novo, de entre as que a nova transportadora oferece).&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Transportadora&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Modalidade&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo de transporte&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| CTT || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 8 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;NORMAL&#039;&#039;&#039; || 5 euros || 2 dias&lt;br /&gt;
|-&lt;br /&gt;
| DHL || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 12 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| SEUR || &#039;&#039;&#039;EXPRESSO&#039;&#039;&#039; || 10 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
No exemplo acima, a transportadora SEUR só oferece a modalidade         expresso: não é possível enviar por SEUR em modalidade normal.&lt;br /&gt;
&lt;br /&gt;
A transportadora e a modalidade são escolhidas no [[#Cabaz de Compras|cabaz]] e aplicam-se a todas as encomendas da compra; o modelo  deve, no entanto, permitir que cada encomenda seja enviada por uma transportadora ou modalidade diferente.&lt;br /&gt;
&lt;br /&gt;
A escolha da transportadora e da modalidade afecta tanto o custo como a data prevista de entrega da encomenda. Uma compra só pode ser finalizada depois de escolhidas ambas, e o par transportadora/modalidade de um cabaz é sempre um par que a transportadora oferece.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida. As transportadoras e as suas tarifas, por seu lado, fazem parte do estado da aplicação: são registadas pelo utilizador e não implicam qualquer alteração ao código.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
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 de Compras|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.&lt;br /&gt;
&lt;br /&gt;
Os serviços iniciais são os seguintes:&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Serviço&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Chave&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Custo adicional&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tempo adicional&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Embrulho || &#039;&#039;&#039;EMBRULHO&#039;&#039;&#039; || 2 euros || 1 dia&lt;br /&gt;
|-&lt;br /&gt;
| Cartão de oferta || &#039;&#039;&#039;CARTAO_OFERTA&#039;&#039;&#039; || 1 euro || 0 dias&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados: uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional. O custo e o tempo adicionais de uma encomenda correspondem à soma dos contributos da modalidade de transporte e de todos os serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da tarifa da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega.  Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia  1 (um) e faz parte do estado persistente.&lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com  impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.                                                            Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número  de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico (&#039;&#039;&#039;EMAIL&#039;&#039;&#039;);&lt;br /&gt;
* WhatsApp (&#039;&#039;&#039;WHATSAPP&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos  ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* 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;&lt;br /&gt;
* Introduzir novas estratégias de divisão de compras em encomendas;&lt;br /&gt;
* Introduzir novas modalidades de transporte (os custos e prazos de cada uma são dados de cada transportadora, não código; nem todas as transportadoras têm de oferecer todas as modalidades);&lt;br /&gt;
* Introduzir novos serviços adicionais, sem alterar o código das encomendas nem o dos serviços já existentes;&lt;br /&gt;
* Introduzir novos mecanismos de notificação, sem alterar o código dos clientes nem o do sistema que gera as notificações;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos critérios de pesquisa de produtos.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}                                              &lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita  [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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. &lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17919</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17919"/>
		<updated>2026-08-26T09:52:38Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Compras|compras]] e [[#Encomendas|encomendas]], e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto: &lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Cada produto pode estar disponível em mais do que uma empresa. Quando uma empresa disponibiliza um produto, deve indicar:&lt;br /&gt;
* o número de unidades do produto que tem disponíveis;&lt;br /&gt;
* o preço base a que disponibiliza o produto;&lt;br /&gt;
* um factor multiplicativo a aplicar ao preço base.&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis, o preço base e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
Cada empresa mantém ainda registo:&lt;br /&gt;
* dos produtos que disponibiliza;&lt;br /&gt;
* dos clientes com que já interagiu (i.e., que lhe fizeram compras);&lt;br /&gt;
* das entregas que efectuou.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos e cada produto pode ser disponibilizado por várias empresas.&lt;br /&gt;
&lt;br /&gt;
Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis (valor inteiro);&lt;br /&gt;
* factor multiplicativo do preço recomendado (número positivo).&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
O factor multiplicativo permite que uma empresa pratique um preço de venda diferente do preço recomendado pelo sistema.&lt;br /&gt;
O preço de venda de um produto pela empresa é calculado multiplicando o preço recomendado do produto pelo factor multiplicativo definido pela empresa.&lt;br /&gt;
Assim, duas empresas podem disponibilizar o mesmo produto a preços diferentes e com quantidades diferentes em stock.&lt;br /&gt;
&lt;br /&gt;
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, através de um factor multiplicativo de 0,9. A empresa B pode disponibilizar o mesmo produto com um preço de 120 euros, através de um factor multiplicativo de 1,2.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Cálculo do Preço ==&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa é determinado por uma estratégia de cálculo de preços.&lt;br /&gt;
&lt;br /&gt;
A estratégia recebe a informação necessária para determinar o preço final, incluindo o produto e os valores definidos pela empresa para a sua disponibilização.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser consideradas, pelo menos, as seguintes estratégias:&lt;br /&gt;
* &#039;&#039;&#039;preço normal&#039;&#039;&#039; — o preço final é calculado considerando o preço base e o factor multiplicativo;&lt;br /&gt;
* &#039;&#039;&#039;preço promocional&#039;&#039;&#039; — o preço final é calculado considerando o preço base, o factor multiplicativo e uma redução percentual definida pela promoção.&lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir introduzir novas estratégias de cálculo de preços sem necessidade de alterar o código responsável por efectuar compras.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, futuramente poderão ser introduzidas estratégias que considerem:&lt;br /&gt;
* descontos específicos;&lt;br /&gt;
* campanhas temporárias;&lt;br /&gt;
* preços específicos para determinados clientes;&lt;br /&gt;
* outras regras de formação do preço.&lt;br /&gt;
&lt;br /&gt;
O preço efectivo utilizado numa compra deve ser calculado no momento em que a compra é efectuada.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos. &amp;lt;!--Deve, no entanto, ser possível discriminar os clientes segundo outros critérios (por exemplo, o volume de compras efectuadas), com um impacto mínimo na implementação desenvolvida.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço de venda do produto pela empresa no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas. &lt;br /&gt;
&lt;br /&gt;
Uma compra pode dar origem a uma ou mais encomendas, de acordo com uma estratégia de divisão de encomendas.&lt;br /&gt;
&lt;br /&gt;
A divisão de uma compra em várias encomendas pode ter impacto no custo total da compra.&lt;br /&gt;
&lt;br /&gt;
== Divisão das Compras em Encomendas ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda tem um custo base de processamento e expedição. Assim, uma compra dividida em várias encomendas pode ter um custo superior ao de uma compra enviada numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
O custo base associado às encomendas corresponde ao número de encomendas multiplicado pelo custo base de uma encomenda.&lt;br /&gt;
&lt;br /&gt;
A este custo podem acrescer os custos associados ao método de transporte seleccionado e aos serviços adicionais.&lt;br /&gt;
&lt;br /&gt;
O custo total de uma compra corresponde, assim, ao custo dos produtos acrescido:&lt;br /&gt;
* do custo base das encomendas;&lt;br /&gt;
* dos custos adicionais dos métodos de transporte;&lt;br /&gt;
* dos custos dos serviços adicionais seleccionados.&lt;br /&gt;
&lt;br /&gt;
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, agrupamento por prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
=== Encomenda única ===&lt;br /&gt;
&lt;br /&gt;
Todos os produtos da compra são colocados numa única encomenda.&lt;br /&gt;
&lt;br /&gt;
Neste caso, a compra origina uma única encomenda, independentemente dos prazos de entrega dos produtos.&lt;br /&gt;
&lt;br /&gt;
=== Agrupamento por prazo de entrega ===&lt;br /&gt;
&lt;br /&gt;
Os produtos são agrupados de acordo com os seus prazos de entrega.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única encomenda;&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa encomenda própria.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa entrega e P2 (prazo &amp;gt; 4,33) segue numa outra encomenda:&lt;br /&gt;
* Encomenda A: {P1, P3}   (prazo = 3)&lt;br /&gt;
* Encomenda B: {P2}       (prazo = 8)&lt;br /&gt;
&lt;br /&gt;
Uma estratégia de divisão que origina várias encomendas pode permitir que alguns produtos sejam entregues mais cedo, mas pode também resultar num custo superior devido ao custo associado a cada encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas estratégias de divisão de compras em encomendas com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Transportadoras ==&lt;br /&gt;
&lt;br /&gt;
Cada encomenda é enviada através de uma transportadora.&lt;br /&gt;
Inicialmente, devem ser suportadas, pelo menos, as seguintes modalidades: normal e expresso.&lt;br /&gt;
&lt;br /&gt;
Cada modalidade de transporte define: (i) um custo adicional; e (ii) um tempo de transporte, expresso em dias.&lt;br /&gt;
&lt;br /&gt;
Por exemplo:&lt;br /&gt;
{|&lt;br /&gt;
|Modalidade || Custo adicional || Tempo de transporte&lt;br /&gt;
|-&lt;br /&gt;
| Normal || 3 euros || 3 dias&lt;br /&gt;
|-&lt;br /&gt;
| Expresso || 8 euros || 1 dia&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
A escolha de uma modalidade de transporte afecta tanto o custo como a data prevista de entrega da encomenda.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novas modalidades de transporte com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Serviços Adicionais ==&lt;br /&gt;
&lt;br /&gt;
O cliente pode seleccionar serviços adicionais para cada encomenda, podendo aumentar o custo da encomenda, assim como o tempo necessário para a sua preparação e entrega.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, deve ser suportado, pelo menos, um serviço de embrulho.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, um serviço de embrulho pode acrescentar 2 euros ao custo da encomenda e um dia ao prazo necessário para a sua entrega.&lt;br /&gt;
&lt;br /&gt;
Os serviços adicionais podem ser combinados.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, uma encomenda pode incluir simultaneamente embrulho, cartão de oferta ou outro serviço adicional.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos serviços adicionais sem alterar o código das encomendas ou dos serviços já existentes.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
Cada encomenda tem uma data prevista de entrega.&lt;br /&gt;
A data prevista de entrega é determinada considerando:&lt;br /&gt;
* a data da compra;&lt;br /&gt;
* os prazos de entrega dos produtos que constituem a encomenda;&lt;br /&gt;
* o tempo de transporte da transportadora seleccionada;&lt;br /&gt;
* o tempo adicional introduzido pelos serviços seleccionados.&lt;br /&gt;
&lt;br /&gt;
Para uma encomenda com vários produtos, o prazo dos produtos considerados para determinar a data prevista de entrega corresponde ao maior prazo de entrega dos seus produtos.&lt;br /&gt;
&lt;br /&gt;
Não é necessário manter explicitamente um estado para representar se uma encomenda está ou não entregue. A situação da encomenda pode ser determinada a partir da data actual e da sua data prevista de entrega. Assim, uma encomenda é considerada entregue quando a data actual atinge ou ultrapassa a sua data prevista de entrega.&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente. &lt;br /&gt;
&lt;br /&gt;
A data do sistema pode ser avançada. Sempre que a data é alterada, devem ser verificadas as encomendas existentes para determinar:&lt;br /&gt;
* quais as encomendas que serão entregues no dia seguinte;&lt;br /&gt;
* quais as encomendas cuja data prevista de entrega foi atingida ou ultrapassada.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data prevista de entrega de uma encomenda, esta considera-se entregue.&lt;br /&gt;
&lt;br /&gt;
A gestão do tempo deve ainda desencadear [[#Notificações|notificações]].&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que os clientes determinem a existência de um produto, deverá ser possível efectuar pesquisas.&lt;br /&gt;
&lt;br /&gt;
As pesquisas consideram os campos relevantes dos vários produtos, por exemplo, nome, categoria, tipo de produto ou país de origem.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas.&lt;br /&gt;
&lt;br /&gt;
O sistema deve suportar diferentes critérios de pesquisa. Por exemplo, uma pesquisa pode procurar produtos cujo nome contenha determinado termo ou produtos pertencentes a determinada categoria.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de produtos com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário ==&lt;br /&gt;
&lt;br /&gt;
O inventário de um produto numa empresa pode ser alterado através da especificação de um valor a somar ou subtrair ao número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis.&lt;br /&gt;
Se a quantidade indicada for um valor negativo, decrementa-se o número de exemplares disponíveis, desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Um produto não é removido do sistema quando o seu inventário numa empresa chega a zero.&lt;br /&gt;
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.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Esta informação é utilizada, nomeadamente, no cálculo do preço recomendado dos produtos nacionais.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
O sistema deve notificar os clientes relativamente às suas encomendas.&lt;br /&gt;
&lt;br /&gt;
Devem ser enviadas notificações em duas situações:&lt;br /&gt;
* um dia antes da data prevista de entrega, informando o cliente de que a encomenda será entregue no dia seguinte;&lt;br /&gt;
* no dia da entrega, informando o cliente de que a encomenda foi entregue.&lt;br /&gt;
&lt;br /&gt;
Cada notificação deve ser enviada através do mecanismo de notificação seleccionado pelo cliente.&lt;br /&gt;
Inicialmente, devem ser suportados, pelo menos, os seguintes mecanismos:&lt;br /&gt;
* correio electrónico;&lt;br /&gt;
* WhatsApp.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
Por exemplo, um cliente pode receber notificações por correio electrónico, enquanto outro pode recebê-las através de WhatsApp.&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos mecanismos de notificação com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
As notificações devem ser enviadas pela ordem em que os acontecimentos ocorrem no sistema.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis);&lt;br /&gt;
* Adicionar novas categorias de produto;&lt;br /&gt;
* Definir novas entidades que desejem ser notificadas da disponibilidade de produtos;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos métodos de pesquisa de produtos;&lt;br /&gt;
* Alterar a regra de cálculo das entregas e da sobretaxa de entrega com um impacto mínimo no código existente.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
A aplicação deve estar preparada para que se possa remover qualquer entidade (não apenas produtos).&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}&lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17918</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17918"/>
		<updated>2026-08-26T09:07:45Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Produtos Importados */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Compras|compras]] e [[#Encomendas|encomendas]], e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto: &lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for &#039;&#039;&#039;t%&#039;&#039;&#039;, o preço recomendado é calculado de acordo com:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Cada produto pode estar disponível em mais do que uma empresa. Quando uma empresa disponibiliza um produto, deve indicar:&lt;br /&gt;
* o número de unidades do produto que tem disponíveis;&lt;br /&gt;
* o preço base a que disponibiliza o produto;&lt;br /&gt;
* um factor multiplicativo a aplicar ao preço base.&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis, o preço base e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
Cada empresa mantém ainda registo:&lt;br /&gt;
* dos produtos que disponibiliza;&lt;br /&gt;
* dos clientes com que já interagiu (i.e., que lhe fizeram compras);&lt;br /&gt;
* das entregas que efectuou.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos. Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis;&lt;br /&gt;
* preço base do produto;&lt;br /&gt;
* factor multiplicativo do preço.&lt;br /&gt;
&lt;br /&gt;
Duas empresas podem, assim, disponibilizar o mesmo produto com preços base, factores multiplicativos e quantidades em stock diferentes.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, o produto P1 pode ser disponibilizado pela empresa A com um preço base de 20 euros, um factor multiplicativo de 1,1 e 10 unidades disponíveis, enquanto a empresa B disponibiliza o mesmo produto com um preço base de 18 euros, um factor multiplicativo de 1,0 e 3 unidades disponíveis.&lt;br /&gt;
&lt;br /&gt;
O preço base não corresponde necessariamente ao preço final a pagar pelo cliente. O preço final depende do tipo de produto e das regras aplicáveis ao seu cálculo.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.&lt;br /&gt;
== Cálculo do Preço ==&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa é determinado por uma estratégia de cálculo de preços.&lt;br /&gt;
&lt;br /&gt;
A estratégia recebe a informação necessária para determinar o preço final, incluindo o produto e os valores definidos pela empresa para a sua disponibilização.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser consideradas, pelo menos, as seguintes estratégias:&lt;br /&gt;
* &#039;&#039;&#039;preço normal&#039;&#039;&#039; — o preço final é calculado considerando o preço base e o factor multiplicativo;&lt;br /&gt;
* &#039;&#039;&#039;preço promocional&#039;&#039;&#039; — o preço final é calculado considerando o preço base, o factor multiplicativo e uma redução percentual definida pela promoção.&lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir introduzir novas estratégias de cálculo de preços sem necessidade de alterar o código responsável por efectuar compras.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, futuramente poderão ser introduzidas estratégias que considerem:&lt;br /&gt;
* descontos específicos;&lt;br /&gt;
* campanhas temporárias;&lt;br /&gt;
* preços específicos para determinados clientes;&lt;br /&gt;
* outras regras de formação do preço.&lt;br /&gt;
&lt;br /&gt;
O preço efectivo utilizado numa compra deve ser calculado no momento em que a compra é efectuada.&lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos. Deve, no entanto, ser possível discriminar os clientes segundo outros critérios (por exemplo, o volume de compras efectuadas), com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço do produto no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
O preço unitário efectivo utilizado na compra deve ser guardado na própria linha da compra. Uma alteração posterior do preço base do produto pela empresa, do factor multiplicativo da empresa, ou de qualquer outra propriedade relevante para o cálculo do preço, não deve alterar o valor de compras já efectuadas.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas. A cada compra está ainda associada uma sobretaxa de entrega, correspondente a 10% do preço total dos itens, independentemente do número de entregas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Como se descreve na secção seguinte, uma compra pode dar origem a mais do que uma entrega. A divisão de uma compra em várias entregas &#039;&#039;&#039;não acrescenta qualquer custo&#039;&#039;&#039;: a sobretaxa de entrega é sempre 10% do preço total dos itens, independentemente do número de entregas.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gestão de Stock ==&lt;br /&gt;
&lt;br /&gt;
O stock de um produto é mantido por cada empresa que o disponibiliza. &lt;br /&gt;
Assim, duas empresas que disponibilizem o mesmo produto podem ter quantidades diferentes desse produto em stock.&lt;br /&gt;
O stock de um produto numa determinada empresa pode ser alterado através da especificação de um valor a somar/subtrair ao número de exemplares disponíveis:&lt;br /&gt;
* se a quantidade indicada for positiva, aumenta-se o número de exemplares disponíveis;&lt;br /&gt;
* se a quantidade indicada for negativa, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares disponíveis de um produto numa determinada empresa chegue a 0, o produto deixa de estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
O produto não é removido do sistema, podendo continuar a ser disponibilizado por outras empresas ou voltar a ser disponibilizado posteriormente pela mesma empresa.&lt;br /&gt;
&lt;br /&gt;
Quando o stock de um produto passa de zero para um valor positivo, o produto volta a estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
A relação entre uma empresa e um produto pode deixar de existir quando a empresa deixa de disponibilizar esse produto.&lt;br /&gt;
&lt;br /&gt;
O produto global deve, no entanto, continuar a existir no sistema enquanto houver outras razões para a sua existência, independentemente de estar temporariamente disponível ou não em qualquer empresa.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
A cada compra correspondem uma ou mais entregas. A forma como uma compra é dividida em entregas é determinada por uma estratégia de planeamento de entregas.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser suportadas, pelo menos, as seguintes estratégias: entrega conjunta e entrega individual.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única entrega (a entrega conjunta);&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa entrega própria (uma entrega conjunta pode não existir se todas as linhas forem enviadas separadamente).&lt;br /&gt;
&lt;br /&gt;
A estratégia de planeamento de entregas deve poder ser seleccionada e substituída sem alterar o código que representa uma compra.&lt;br /&gt;
&lt;br /&gt;
== Ciclo de Vida das Entregas ==&lt;br /&gt;
A estratégia de planeamento de entregas deve poder ser seleccionada e substituída sem alterar o código que representa uma compra.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, são considerados os seguintes estados:&lt;br /&gt;
* &#039;&#039;&#039;CRIADA&#039;&#039;&#039; — a entrega foi criada, mas ainda não foi iniciada a sua preparação;&lt;br /&gt;
* &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039; — os produtos da entrega estão a ser preparados;&lt;br /&gt;
* &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; — os produtos foram expedidos e a entrega encontra-se a caminho do cliente;&lt;br /&gt;
* &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; — a entrega chegou ao cliente.&lt;br /&gt;
&lt;br /&gt;
Uma entrega é inicialmente criada no estado &#039;&#039;&#039;CRIADA&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As transições entre estados devem respeitar o seguinte fluxo: &#039;&#039;&#039;CRIADA&#039;&#039;&#039; → &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039; → &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; → &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;. Não é possível passar ao estado anterior. Não são possíveis alterações depois de se atingir &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As operações permitidas sobre uma entrega podem depender do seu estado actual.&lt;br /&gt;
Por exemplo, uma entrega que ainda se encontra no estado &#039;&#039;&#039;CRIADA&#039;&#039;&#039; pode ser colocada em preparação, enquanto uma entrega no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; não pode voltar ao estado &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
O comportamento associado aos diferentes estados de uma entrega deve ser modelado de modo a evitar que todas as regras de transição e de comportamento dependente do estado sejam concentradas numa única classe.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar novos estados ou alterar as regras de transição existentes com impacto mínimo no código já desenvolvido.&lt;br /&gt;
&lt;br /&gt;
== Data de Chegada das Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada entrega tem uma data de chegada prevista, calculada a partir da data da compra e do prazo aplicável: uma entrega individual usa o prazo do respectivo produto; uma entrega conjunta usa o maior dos prazos dos produtos que dela fazem parte.&amp;lt;!-- Como referido acima, o envio separado é feito &#039;&#039;&#039;sem custo adicional&#039;&#039;&#039;.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa entrega e P2 (prazo &amp;gt; 4,33) segue numa entrega separada:&lt;br /&gt;
* Entrega A: {P1, P3}   (prazo = 3) (entrega conjunta)&lt;br /&gt;
* Entrega B: {P2}       (prazo = 8) (entrega individual)&lt;br /&gt;
&lt;br /&gt;
A data de chegada prevista da entrega A corresponde à data da compra acrescida de 3 dias.&lt;br /&gt;
A data de chegada prevista da entrega B corresponde à data da compra acrescida de 8 dias.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data de chegada prevista de uma entrega que se encontra no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039;, a entrega passa automaticamente para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Uma entrega que ainda não tenha sido enviada não pode passar directamente para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; apenas devido à passagem do tempo.&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que o sistema ajude os clientes a determinar a existência de um produto, deverá ser possível efectuar pesquisas. As pesquisas consideram os campos relevantes dos vários produtos.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser suportados, pelo menos, os seguintes critérios de pesquisa:&lt;br /&gt;
* nome;&lt;br /&gt;
* descrição do produto;&lt;br /&gt;
* categoria do produto;&lt;br /&gt;
* disponibilidade em stock;&lt;br /&gt;
* intervalo de preços.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas (quando aplicável). &lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir seleccionar diferentes estratégias de pesquisa.&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de um produto com um impacto mínimo na implementação desenvolvida. Por exemplo, futuramente poderá ser possível pesquisar produtos por país de origem, por prazo de entrega, ou por combinação de vários critérios.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Alterações de Inventário de Produtos ==&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;stock&#039;&#039; de um produto pode ser alterado, através da especificação de um valor a somar/subtrair ao número de exemplares: se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis; se for um valor negativo, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares de um produto chegue a 0, então o produto deve ser removido do sistema.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a remoção de um produto tem impacto na gestão das empresas que o vendiam.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente. &lt;br /&gt;
&lt;br /&gt;
Sempre que a data é alterada, deve ser verificada a situação das entregas: quando a data actual atinge ou ultrapassa a data de chegada prevista de uma entrega que se encontra no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039;, a entrega passa para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Devem ainda ser actualizados outros aspectos que dependam da data actual.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
Deve existir um mecanismo de notificações que permita avisar eventuais interessados quando os produtos ficam em determinadas situações.&lt;br /&gt;
Quando um produto sem qualquer exemplar disponível &#039;&#039;&#039;numa determinada empresa&#039;&#039;&#039; passa a ter pelo menos um exemplar disponível nessa empresa, quer-se enviar uma notificação a todas as entidades que demonstraram interesse nesta situação.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No caso de uma entidade interessada em ser avisada da disponibilidade de um produto numa determinada empresa, isto significa que, sempre que o produto em causa passar da situação de indisponível (zero exemplares disponíveis) para disponível (pelo menos um exemplar disponível), nessa empresa, a entidade deve receber uma notificação.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível definir novas entidades interessadas e novos tipos de notificação, com impacto mínimo no código do domínio da aplicação.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis);&lt;br /&gt;
* Adicionar novas categorias de produto;&lt;br /&gt;
* Definir novas entidades que desejem ser notificadas da disponibilidade de produtos;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos métodos de pesquisa de produtos;&lt;br /&gt;
* Alterar a regra de cálculo das entregas e da sobretaxa de entrega com um impacto mínimo no código existente.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
A aplicação deve estar preparada para que se possa remover qualquer entidade (não apenas produtos).&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}&lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17917</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17917"/>
		<updated>2026-08-26T09:07:12Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Compras|compras]] e [[#Encomendas|encomendas]], e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 clientes com quem interage, dos produtos que disponibiliza, das compras feitas e das  encomendas que expede.&lt;br /&gt;
&lt;br /&gt;
Uma compra representa a aquisição de produtos por um cliente a uma empresa. Uma compra pode dar origem a uma ou mais encomendas, de acordo com a estratégia de divisão de encomendas utilizada.&lt;br /&gt;
&lt;br /&gt;
Cada encomenda pode ser enviada através de uma determinada transportadora e pode incluir serviços adicionais que alteram o seu custo e/ou prazo de entrega.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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; e um prazo de entrega base (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto: &lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro expressando uma percentagem);&lt;br /&gt;
* um prazo de transporte internacional (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
O preço recomendado é calculado de forma diferente consoante o tipo de produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Nacionais === &lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Se o número total de unidades disponíveis for:&lt;br /&gt;
* superior a 10000, o preço recomendado corresponde a 90% do preço base;&lt;br /&gt;
* inferior a 100, o preço recomendado corresponde a 130% do preço base;&lt;br /&gt;
* nos restantes casos, o preço recomendado corresponde ao preço base.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considerando um produto nacional com preço base de 100 euros:&lt;br /&gt;
* Unidades disponíveis = 50 =&amp;gt; Preço recomendado = 130 euros;&lt;br /&gt;
* Unidades disponíveis = 5000 =&amp;gt; Preço recomendado = 100 euros;&lt;br /&gt;
* Unidades disponíveis = 12000 =&amp;gt; Preço recomendado = 90 euros.&lt;br /&gt;
&lt;br /&gt;
=== Produtos Importados ===&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço recomendado corresponde ao preço base acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Se a taxa alfandegária for t%, o preço recomendado é calculado de acordo com:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;preço base × (100 + t) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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á:&lt;br /&gt;
&lt;br /&gt;
 &#039;&#039;&#039;100 × (100 + 20) / 100 = 120 euros&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
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 o tipo concreto de cada produto.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
Cada produto pode estar disponível em mais do que uma empresa. Quando uma empresa disponibiliza um produto, deve indicar:&lt;br /&gt;
* o número de unidades do produto que tem disponíveis;&lt;br /&gt;
* o preço base a que disponibiliza o produto;&lt;br /&gt;
* um factor multiplicativo a aplicar ao preço base.&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis, o preço base e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
Cada empresa mantém ainda registo:&lt;br /&gt;
* dos produtos que disponibiliza;&lt;br /&gt;
* dos clientes com que já interagiu (i.e., que lhe fizeram compras);&lt;br /&gt;
* das entregas que efectuou.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos. Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis;&lt;br /&gt;
* preço base do produto;&lt;br /&gt;
* factor multiplicativo do preço.&lt;br /&gt;
&lt;br /&gt;
Duas empresas podem, assim, disponibilizar o mesmo produto com preços base, factores multiplicativos e quantidades em stock diferentes.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, o produto P1 pode ser disponibilizado pela empresa A com um preço base de 20 euros, um factor multiplicativo de 1,1 e 10 unidades disponíveis, enquanto a empresa B disponibiliza o mesmo produto com um preço base de 18 euros, um factor multiplicativo de 1,0 e 3 unidades disponíveis.&lt;br /&gt;
&lt;br /&gt;
O preço base não corresponde necessariamente ao preço final a pagar pelo cliente. O preço final depende do tipo de produto e das regras aplicáveis ao seu cálculo.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.&lt;br /&gt;
== Cálculo do Preço ==&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa é determinado por uma estratégia de cálculo de preços.&lt;br /&gt;
&lt;br /&gt;
A estratégia recebe a informação necessária para determinar o preço final, incluindo o produto e os valores definidos pela empresa para a sua disponibilização.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser consideradas, pelo menos, as seguintes estratégias:&lt;br /&gt;
* &#039;&#039;&#039;preço normal&#039;&#039;&#039; — o preço final é calculado considerando o preço base e o factor multiplicativo;&lt;br /&gt;
* &#039;&#039;&#039;preço promocional&#039;&#039;&#039; — o preço final é calculado considerando o preço base, o factor multiplicativo e uma redução percentual definida pela promoção.&lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir introduzir novas estratégias de cálculo de preços sem necessidade de alterar o código responsável por efectuar compras.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, futuramente poderão ser introduzidas estratégias que considerem:&lt;br /&gt;
* descontos específicos;&lt;br /&gt;
* campanhas temporárias;&lt;br /&gt;
* preços específicos para determinados clientes;&lt;br /&gt;
* outras regras de formação do preço.&lt;br /&gt;
&lt;br /&gt;
O preço efectivo utilizado numa compra deve ser calculado no momento em que a compra é efectuada.&lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos. Deve, no entanto, ser possível discriminar os clientes segundo outros critérios (por exemplo, o volume de compras efectuadas), com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço do produto no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
O preço unitário efectivo utilizado na compra deve ser guardado na própria linha da compra. Uma alteração posterior do preço base do produto pela empresa, do factor multiplicativo da empresa, ou de qualquer outra propriedade relevante para o cálculo do preço, não deve alterar o valor de compras já efectuadas.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas. A cada compra está ainda associada uma sobretaxa de entrega, correspondente a 10% do preço total dos itens, independentemente do número de entregas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Como se descreve na secção seguinte, uma compra pode dar origem a mais do que uma entrega. A divisão de uma compra em várias entregas &#039;&#039;&#039;não acrescenta qualquer custo&#039;&#039;&#039;: a sobretaxa de entrega é sempre 10% do preço total dos itens, independentemente do número de entregas.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gestão de Stock ==&lt;br /&gt;
&lt;br /&gt;
O stock de um produto é mantido por cada empresa que o disponibiliza. &lt;br /&gt;
Assim, duas empresas que disponibilizem o mesmo produto podem ter quantidades diferentes desse produto em stock.&lt;br /&gt;
O stock de um produto numa determinada empresa pode ser alterado através da especificação de um valor a somar/subtrair ao número de exemplares disponíveis:&lt;br /&gt;
* se a quantidade indicada for positiva, aumenta-se o número de exemplares disponíveis;&lt;br /&gt;
* se a quantidade indicada for negativa, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares disponíveis de um produto numa determinada empresa chegue a 0, o produto deixa de estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
O produto não é removido do sistema, podendo continuar a ser disponibilizado por outras empresas ou voltar a ser disponibilizado posteriormente pela mesma empresa.&lt;br /&gt;
&lt;br /&gt;
Quando o stock de um produto passa de zero para um valor positivo, o produto volta a estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
A relação entre uma empresa e um produto pode deixar de existir quando a empresa deixa de disponibilizar esse produto.&lt;br /&gt;
&lt;br /&gt;
O produto global deve, no entanto, continuar a existir no sistema enquanto houver outras razões para a sua existência, independentemente de estar temporariamente disponível ou não em qualquer empresa.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
A cada compra correspondem uma ou mais entregas. A forma como uma compra é dividida em entregas é determinada por uma estratégia de planeamento de entregas.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser suportadas, pelo menos, as seguintes estratégias: entrega conjunta e entrega individual.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única entrega (a entrega conjunta);&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa entrega própria (uma entrega conjunta pode não existir se todas as linhas forem enviadas separadamente).&lt;br /&gt;
&lt;br /&gt;
A estratégia de planeamento de entregas deve poder ser seleccionada e substituída sem alterar o código que representa uma compra.&lt;br /&gt;
&lt;br /&gt;
== Ciclo de Vida das Entregas ==&lt;br /&gt;
A estratégia de planeamento de entregas deve poder ser seleccionada e substituída sem alterar o código que representa uma compra.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, são considerados os seguintes estados:&lt;br /&gt;
* &#039;&#039;&#039;CRIADA&#039;&#039;&#039; — a entrega foi criada, mas ainda não foi iniciada a sua preparação;&lt;br /&gt;
* &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039; — os produtos da entrega estão a ser preparados;&lt;br /&gt;
* &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; — os produtos foram expedidos e a entrega encontra-se a caminho do cliente;&lt;br /&gt;
* &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; — a entrega chegou ao cliente.&lt;br /&gt;
&lt;br /&gt;
Uma entrega é inicialmente criada no estado &#039;&#039;&#039;CRIADA&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As transições entre estados devem respeitar o seguinte fluxo: &#039;&#039;&#039;CRIADA&#039;&#039;&#039; → &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039; → &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; → &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;. Não é possível passar ao estado anterior. Não são possíveis alterações depois de se atingir &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As operações permitidas sobre uma entrega podem depender do seu estado actual.&lt;br /&gt;
Por exemplo, uma entrega que ainda se encontra no estado &#039;&#039;&#039;CRIADA&#039;&#039;&#039; pode ser colocada em preparação, enquanto uma entrega no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; não pode voltar ao estado &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
O comportamento associado aos diferentes estados de uma entrega deve ser modelado de modo a evitar que todas as regras de transição e de comportamento dependente do estado sejam concentradas numa única classe.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar novos estados ou alterar as regras de transição existentes com impacto mínimo no código já desenvolvido.&lt;br /&gt;
&lt;br /&gt;
== Data de Chegada das Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada entrega tem uma data de chegada prevista, calculada a partir da data da compra e do prazo aplicável: uma entrega individual usa o prazo do respectivo produto; uma entrega conjunta usa o maior dos prazos dos produtos que dela fazem parte.&amp;lt;!-- Como referido acima, o envio separado é feito &#039;&#039;&#039;sem custo adicional&#039;&#039;&#039;.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa entrega e P2 (prazo &amp;gt; 4,33) segue numa entrega separada:&lt;br /&gt;
* Entrega A: {P1, P3}   (prazo = 3) (entrega conjunta)&lt;br /&gt;
* Entrega B: {P2}       (prazo = 8) (entrega individual)&lt;br /&gt;
&lt;br /&gt;
A data de chegada prevista da entrega A corresponde à data da compra acrescida de 3 dias.&lt;br /&gt;
A data de chegada prevista da entrega B corresponde à data da compra acrescida de 8 dias.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data de chegada prevista de uma entrega que se encontra no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039;, a entrega passa automaticamente para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Uma entrega que ainda não tenha sido enviada não pode passar directamente para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; apenas devido à passagem do tempo.&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que o sistema ajude os clientes a determinar a existência de um produto, deverá ser possível efectuar pesquisas. As pesquisas consideram os campos relevantes dos vários produtos.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser suportados, pelo menos, os seguintes critérios de pesquisa:&lt;br /&gt;
* nome;&lt;br /&gt;
* descrição do produto;&lt;br /&gt;
* categoria do produto;&lt;br /&gt;
* disponibilidade em stock;&lt;br /&gt;
* intervalo de preços.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas (quando aplicável). &lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir seleccionar diferentes estratégias de pesquisa.&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de um produto com um impacto mínimo na implementação desenvolvida. Por exemplo, futuramente poderá ser possível pesquisar produtos por país de origem, por prazo de entrega, ou por combinação de vários critérios.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Alterações de Inventário de Produtos ==&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;stock&#039;&#039; de um produto pode ser alterado, através da especificação de um valor a somar/subtrair ao número de exemplares: se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis; se for um valor negativo, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares de um produto chegue a 0, então o produto deve ser removido do sistema.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a remoção de um produto tem impacto na gestão das empresas que o vendiam.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente. &lt;br /&gt;
&lt;br /&gt;
Sempre que a data é alterada, deve ser verificada a situação das entregas: quando a data actual atinge ou ultrapassa a data de chegada prevista de uma entrega que se encontra no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039;, a entrega passa para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Devem ainda ser actualizados outros aspectos que dependam da data actual.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
Deve existir um mecanismo de notificações que permita avisar eventuais interessados quando os produtos ficam em determinadas situações.&lt;br /&gt;
Quando um produto sem qualquer exemplar disponível &#039;&#039;&#039;numa determinada empresa&#039;&#039;&#039; passa a ter pelo menos um exemplar disponível nessa empresa, quer-se enviar uma notificação a todas as entidades que demonstraram interesse nesta situação.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No caso de uma entidade interessada em ser avisada da disponibilidade de um produto numa determinada empresa, isto significa que, sempre que o produto em causa passar da situação de indisponível (zero exemplares disponíveis) para disponível (pelo menos um exemplar disponível), nessa empresa, a entidade deve receber uma notificação.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível definir novas entidades interessadas e novos tipos de notificação, com impacto mínimo no código do domínio da aplicação.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis);&lt;br /&gt;
* Adicionar novas categorias de produto;&lt;br /&gt;
* Definir novas entidades que desejem ser notificadas da disponibilidade de produtos;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos métodos de pesquisa de produtos;&lt;br /&gt;
* Alterar a regra de cálculo das entregas e da sobretaxa de entrega com um impacto mínimo no código existente.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
A aplicação deve estar preparada para que se possa remover qualquer entidade (não apenas produtos).&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}&lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17916</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17916"/>
		<updated>2026-08-26T08:34:16Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O objectivo do projecto é desenvolver um sistema de gestão de &#039;&#039;&#039;entregas rápidas de produtos&#039;&#039;&#039; (ERP). O sistema deverá permitir, entre outras operações, (i) registar dados de empresas; (ii) registar dados de clientes; (iii) registar e pesquisar produtos; (iv) efectuar compras; e (v) gerir as entregas correspondentes.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Compras|compras]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Os clientes e os produtos são independentes das empresas: existem por si e podem relacionar-se com várias empresas. &lt;br /&gt;
&lt;br /&gt;
Cada produto pode estar disponível em mais do que uma empresa. Quando uma empresa disponibiliza um produto, deve indicar:&lt;br /&gt;
* o número de unidades do produto que tem disponíveis;&lt;br /&gt;
* o preço base a que disponibiliza o produto;&lt;br /&gt;
* um factor multiplicativo a aplicar ao preço base.&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis, o preço base e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
Cada empresa mantém ainda registo:&lt;br /&gt;
* dos produtos que disponibiliza;&lt;br /&gt;
* dos clientes com que já interagiu (i.e., que lhe fizeram compras);&lt;br /&gt;
* das entregas que efectuou.&lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos. Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis;&lt;br /&gt;
* preço base do produto;&lt;br /&gt;
* factor multiplicativo do preço.&lt;br /&gt;
&lt;br /&gt;
Duas empresas podem, assim, disponibilizar o mesmo produto com preços base, factores multiplicativos e quantidades em stock diferentes.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, o produto P1 pode ser disponibilizado pela empresa A com um preço base de 20 euros, um factor multiplicativo de 1,1 e 10 unidades disponíveis, enquanto a empresa B disponibiliza o mesmo produto com um preço base de 18 euros, um factor multiplicativo de 1,0 e 3 unidades disponíveis.&lt;br /&gt;
&lt;br /&gt;
O preço base não corresponde necessariamente ao preço final a pagar pelo cliente. O preço final depende do tipo de produto e das regras aplicáveis ao seu cálculo.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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), uma categoria e um prazo de entrega (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 base diferente, utilize um factor multiplicativo diferente e disponha de uma quantidade diferente em stock.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro).&lt;br /&gt;
&lt;br /&gt;
A taxa alfandegária representa um custo adicional associado à importação do produto.&lt;br /&gt;
&lt;br /&gt;
O tipo de produto deve ter impacto no cálculo do preço final do produto.&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa deve ser calculado a partir:&lt;br /&gt;
* do preço base definido pela empresa;&lt;br /&gt;
* do factor multiplicativo definido pela empresa;&lt;br /&gt;
* das características específicas do produto.&lt;br /&gt;
&lt;br /&gt;
Para um produto nacional, o preço final corresponde ao preço base multiplicado pelo factor multiplicativo aplicável à disponibilização do produto pela empresa.&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço final corresponde ao preço base multiplicado pelo factor multiplicativo aplicável à disponibilização do produto pela empresa, acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, se uma empresa disponibilizar um produto com preço base de 100 euros e factor multiplicativo de 1,1:&lt;br /&gt;
* um produto nacional terá preço final de 110 euros;&lt;br /&gt;
* um produto importado com taxa alfandegária de 20 euros terá preço final de 130 euros.&lt;br /&gt;
&lt;br /&gt;
O cálculo do preço final deve ser realizado de forma polimórfica, de modo a que o código que utiliza produtos não tenha de conhecer explicitamente o tipo concreto de cada produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Cálculo do Preço ==&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa é determinado por uma estratégia de cálculo de preços.&lt;br /&gt;
&lt;br /&gt;
A estratégia recebe a informação necessária para determinar o preço final, incluindo o produto e os valores definidos pela empresa para a sua disponibilização.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser consideradas, pelo menos, as seguintes estratégias:&lt;br /&gt;
* &#039;&#039;&#039;preço normal&#039;&#039;&#039; — o preço final é calculado considerando o preço base e o factor multiplicativo;&lt;br /&gt;
* &#039;&#039;&#039;preço promocional&#039;&#039;&#039; — o preço final é calculado considerando o preço base, o factor multiplicativo e uma redução percentual definida pela promoção.&lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir introduzir novas estratégias de cálculo de preços sem necessidade de alterar o código responsável por efectuar compras.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, futuramente poderão ser introduzidas estratégias que considerem:&lt;br /&gt;
* descontos específicos;&lt;br /&gt;
* campanhas temporárias;&lt;br /&gt;
* preços específicos para determinados clientes;&lt;br /&gt;
* outras regras de formação do preço.&lt;br /&gt;
&lt;br /&gt;
O preço efectivo utilizado numa compra deve ser calculado no momento em que a compra é efectuada.&lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos. Deve, no entanto, ser possível discriminar os clientes segundo outros critérios (por exemplo, o volume de compras efectuadas), com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço do produto no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
O preço unitário efectivo utilizado na compra deve ser guardado na própria linha da compra. Uma alteração posterior do preço base do produto pela empresa, do factor multiplicativo da empresa, ou de qualquer outra propriedade relevante para o cálculo do preço, não deve alterar o valor de compras já efectuadas.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas. A cada compra está ainda associada uma sobretaxa de entrega, correspondente a 10% do preço total dos itens, independentemente do número de entregas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Como se descreve na secção seguinte, uma compra pode dar origem a mais do que uma entrega. A divisão de uma compra em várias entregas &#039;&#039;&#039;não acrescenta qualquer custo&#039;&#039;&#039;: a sobretaxa de entrega é sempre 10% do preço total dos itens, independentemente do número de entregas.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gestão de Stock ==&lt;br /&gt;
&lt;br /&gt;
O stock de um produto é mantido por cada empresa que o disponibiliza. &lt;br /&gt;
Assim, duas empresas que disponibilizem o mesmo produto podem ter quantidades diferentes desse produto em stock.&lt;br /&gt;
O stock de um produto numa determinada empresa pode ser alterado através da especificação de um valor a somar/subtrair ao número de exemplares disponíveis:&lt;br /&gt;
* se a quantidade indicada for positiva, aumenta-se o número de exemplares disponíveis;&lt;br /&gt;
* se a quantidade indicada for negativa, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares disponíveis de um produto numa determinada empresa chegue a 0, o produto deixa de estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
O produto não é removido do sistema, podendo continuar a ser disponibilizado por outras empresas ou voltar a ser disponibilizado posteriormente pela mesma empresa.&lt;br /&gt;
&lt;br /&gt;
Quando o stock de um produto passa de zero para um valor positivo, o produto volta a estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
A relação entre uma empresa e um produto pode deixar de existir quando a empresa deixa de disponibilizar esse produto.&lt;br /&gt;
&lt;br /&gt;
O produto global deve, no entanto, continuar a existir no sistema enquanto houver outras razões para a sua existência, independentemente de estar temporariamente disponível ou não em qualquer empresa.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
A cada compra correspondem uma ou mais entregas. A forma como uma compra é dividida em entregas é determinada por uma estratégia de planeamento de entregas.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser suportadas, pelo menos, as seguintes estratégias: entrega conjunta e entrega individual.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a média dos prazos de entrega dos produtos das linhas da compra:&lt;br /&gt;
* todas as linhas cujo produto tem prazo menor ou igual à média são agrupadas numa única entrega (a entrega conjunta);&lt;br /&gt;
* cada linha cujo produto tem prazo estritamente maior do que a média é enviada separadamente, numa entrega própria (uma entrega conjunta pode não existir se todas as linhas forem enviadas separadamente).&lt;br /&gt;
&lt;br /&gt;
A estratégia de planeamento de entregas deve poder ser seleccionada e substituída sem alterar o código que representa uma compra.&lt;br /&gt;
&lt;br /&gt;
== Ciclo de Vida das Entregas ==&lt;br /&gt;
A estratégia de planeamento de entregas deve poder ser seleccionada e substituída sem alterar o código que representa uma compra.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, são considerados os seguintes estados:&lt;br /&gt;
* &#039;&#039;&#039;CRIADA&#039;&#039;&#039; — a entrega foi criada, mas ainda não foi iniciada a sua preparação;&lt;br /&gt;
* &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039; — os produtos da entrega estão a ser preparados;&lt;br /&gt;
* &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; — os produtos foram expedidos e a entrega encontra-se a caminho do cliente;&lt;br /&gt;
* &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; — a entrega chegou ao cliente.&lt;br /&gt;
&lt;br /&gt;
Uma entrega é inicialmente criada no estado &#039;&#039;&#039;CRIADA&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As transições entre estados devem respeitar o seguinte fluxo: &#039;&#039;&#039;CRIADA&#039;&#039;&#039; → &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039; → &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; → &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;. Não é possível passar ao estado anterior. Não são possíveis alterações depois de se atingir &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
As operações permitidas sobre uma entrega podem depender do seu estado actual.&lt;br /&gt;
Por exemplo, uma entrega que ainda se encontra no estado &#039;&#039;&#039;CRIADA&#039;&#039;&#039; pode ser colocada em preparação, enquanto uma entrega no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039; não pode voltar ao estado &#039;&#039;&#039;EM_PREPARAÇÃO&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
O comportamento associado aos diferentes estados de uma entrega deve ser modelado de modo a evitar que todas as regras de transição e de comportamento dependente do estado sejam concentradas numa única classe.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar novos estados ou alterar as regras de transição existentes com impacto mínimo no código já desenvolvido.&lt;br /&gt;
&lt;br /&gt;
== Data de Chegada das Entregas ==&lt;br /&gt;
&lt;br /&gt;
Cada entrega tem uma data de chegada prevista, calculada a partir da data da compra e do prazo aplicável: uma entrega individual usa o prazo do respectivo produto; uma entrega conjunta usa o maior dos prazos dos produtos que dela fazem parte.&amp;lt;!-- Como referido acima, o envio separado é feito &#039;&#039;&#039;sem custo adicional&#039;&#039;&#039;.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa entrega e P2 (prazo &amp;gt; 4,33) segue numa entrega separada:&lt;br /&gt;
* Entrega A: {P1, P3}   (prazo = 3) (entrega conjunta)&lt;br /&gt;
* Entrega B: {P2}       (prazo = 8) (entrega individual)&lt;br /&gt;
&lt;br /&gt;
A data de chegada prevista da entrega A corresponde à data da compra acrescida de 3 dias.&lt;br /&gt;
A data de chegada prevista da entrega B corresponde à data da compra acrescida de 8 dias.&lt;br /&gt;
&lt;br /&gt;
Quando a data actual atinge ou ultrapassa a data de chegada prevista de uma entrega que se encontra no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039;, a entrega passa automaticamente para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Uma entrega que ainda não tenha sido enviada não pode passar directamente para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039; apenas devido à passagem do tempo.&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que o sistema ajude os clientes a determinar a existência de um produto, deverá ser possível efectuar pesquisas. As pesquisas consideram os campos relevantes dos vários produtos.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser suportados, pelo menos, os seguintes critérios de pesquisa:&lt;br /&gt;
* nome;&lt;br /&gt;
* descrição do produto;&lt;br /&gt;
* categoria do produto;&lt;br /&gt;
* disponibilidade em stock;&lt;br /&gt;
* intervalo de preços.&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas (quando aplicável). &lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir seleccionar diferentes estratégias de pesquisa.&lt;br /&gt;
Deve ser possível introduzir novos métodos de pesquisa de um produto com um impacto mínimo na implementação desenvolvida. Por exemplo, futuramente poderá ser possível pesquisar produtos por país de origem, por prazo de entrega, ou por combinação de vários critérios.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Alterações de Inventário de Produtos ==&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;stock&#039;&#039; de um produto pode ser alterado, através da especificação de um valor a somar/subtrair ao número de exemplares: se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis; se for um valor negativo, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares de um produto chegue a 0, então o produto deve ser removido do sistema.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a remoção de um produto tem impacto na gestão das empresas que o vendiam.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente. &lt;br /&gt;
&lt;br /&gt;
Sempre que a data é alterada, deve ser verificada a situação das entregas: quando a data actual atinge ou ultrapassa a data de chegada prevista de uma entrega que se encontra no estado &#039;&#039;&#039;ENVIADA&#039;&#039;&#039;, a entrega passa para o estado &#039;&#039;&#039;ENTREGUE&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Devem ainda ser actualizados outros aspectos que dependam da data actual.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
Deve existir um mecanismo de notificações que permita avisar eventuais interessados quando os produtos ficam em determinadas situações.&lt;br /&gt;
Quando um produto sem qualquer exemplar disponível &#039;&#039;&#039;numa determinada empresa&#039;&#039;&#039; passa a ter pelo menos um exemplar disponível nessa empresa, quer-se enviar uma notificação a todas as entidades que demonstraram interesse nesta situação.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No caso de uma entidade interessada em ser avisada da disponibilidade de um produto numa determinada empresa, isto significa que, sempre que o produto em causa passar da situação de indisponível (zero exemplares disponíveis) para disponível (pelo menos um exemplar disponível), nessa empresa, a entidade deve receber uma notificação.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível definir novas entidades interessadas e novos tipos de notificação, com impacto mínimo no código do domínio da aplicação.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis);&lt;br /&gt;
* Adicionar novas categorias de produto;&lt;br /&gt;
* Definir novas entidades que desejem ser notificadas da disponibilidade de produtos;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos métodos de pesquisa de produtos;&lt;br /&gt;
* Alterar a regra de cálculo das entregas e da sobretaxa de entrega com um impacto mínimo no código existente.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
A aplicação deve estar preparada para que se possa remover qualquer entidade (não apenas produtos).&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}&lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17915</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17915"/>
		<updated>2026-08-26T08:08:40Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O objectivo do projecto é desenvolver um sistema de gestão de &#039;&#039;&#039;entregas rápidas de produtos&#039;&#039;&#039; (ERP). O sistema deverá permitir, entre outras operações, (i) registar dados de empresas; (ii) registar dados de clientes; (iii) registar e pesquisar produtos; (iv) efectuar compras; e (v) gerir as entregas correspondentes.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Compras|compras]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Os clientes e os produtos são independentes das empresas: existem por si e podem relacionar-se com várias empresas. &lt;br /&gt;
&lt;br /&gt;
Cada produto pode estar disponível em mais do que uma empresa. Quando uma empresa disponibiliza um produto, deve indicar:&lt;br /&gt;
* o número de unidades do produto que tem disponíveis;&lt;br /&gt;
* o preço base a que disponibiliza o produto;&lt;br /&gt;
* um factor multiplicativo a aplicar ao preço base.&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis, o preço base e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
Cada empresa mantém ainda registo:&lt;br /&gt;
* dos produtos que disponibiliza;&lt;br /&gt;
* dos clientes com que já interagiu (i.e., que lhe fizeram compras);&lt;br /&gt;
* das entregas que efectuou.&lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos. Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis;&lt;br /&gt;
* preço base do produto;&lt;br /&gt;
* factor multiplicativo do preço.&lt;br /&gt;
&lt;br /&gt;
Duas empresas podem, assim, disponibilizar o mesmo produto com preços base, factores multiplicativos e quantidades em stock diferentes.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, o produto P1 pode ser disponibilizado pela empresa A com um preço base de 20 euros, um factor multiplicativo de 1,1 e 10 unidades disponíveis, enquanto a empresa B disponibiliza o mesmo produto com um preço base de 18 euros, um factor multiplicativo de 1,0 e 3 unidades disponíveis.&lt;br /&gt;
&lt;br /&gt;
O preço base não corresponde necessariamente ao preço final a pagar pelo cliente. O preço final depende do tipo de produto e das regras aplicáveis ao seu cálculo.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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), uma categoria e um prazo de entrega (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 base diferente, utilize um factor multiplicativo diferente e disponha de uma quantidade diferente em stock.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro).&lt;br /&gt;
&lt;br /&gt;
A taxa alfandegária representa um custo adicional associado à importação do produto.&lt;br /&gt;
&lt;br /&gt;
O tipo de produto deve ter impacto no cálculo do preço final do produto.&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa deve ser calculado a partir:&lt;br /&gt;
* do preço base definido pela empresa;&lt;br /&gt;
* do factor multiplicativo definido pela empresa;&lt;br /&gt;
* das características específicas do produto.&lt;br /&gt;
&lt;br /&gt;
Para um produto nacional, o preço final corresponde ao preço base multiplicado pelo factor multiplicativo aplicável à disponibilização do produto pela empresa.&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço final corresponde ao preço base multiplicado pelo factor multiplicativo aplicável à disponibilização do produto pela empresa, acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, se uma empresa disponibilizar um produto com preço base de 100 euros e factor multiplicativo de 1,1:&lt;br /&gt;
* um produto nacional terá preço final de 110 euros;&lt;br /&gt;
* um produto importado com taxa alfandegária de 20 euros terá preço final de 130 euros.&lt;br /&gt;
&lt;br /&gt;
O cálculo do preço final deve ser realizado de forma polimórfica, de modo a que o código que utiliza produtos não tenha de conhecer explicitamente o tipo concreto de cada produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Cálculo do Preço ==&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa é determinado por uma estratégia de cálculo de preços.&lt;br /&gt;
&lt;br /&gt;
A estratégia recebe a informação necessária para determinar o preço final, incluindo o produto e os valores definidos pela empresa para a sua disponibilização.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser consideradas, pelo menos, as seguintes estratégias:&lt;br /&gt;
* &#039;&#039;&#039;preço normal&#039;&#039;&#039; — o preço final é calculado considerando o preço base e o factor multiplicativo;&lt;br /&gt;
* &#039;&#039;&#039;preço promocional&#039;&#039;&#039; — o preço final é calculado considerando o preço base, o factor multiplicativo e uma redução percentual definida pela promoção.&lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir introduzir novas estratégias de cálculo de preços sem necessidade de alterar o código responsável por efectuar compras.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, futuramente poderão ser introduzidas estratégias que considerem:&lt;br /&gt;
* descontos específicos;&lt;br /&gt;
* campanhas temporárias;&lt;br /&gt;
* preços específicos para determinados clientes;&lt;br /&gt;
* outras regras de formação do preço.&lt;br /&gt;
&lt;br /&gt;
O preço efectivo utilizado numa compra deve ser calculado no momento em que a compra é efectuada.&lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que os clientes têm sempre dinheiro, i.e., uma compra nunca é recusada por falta de fundos. Deve, no entanto, ser possível discriminar os clientes segundo outros critérios (por exemplo, o volume de compras efectuadas), com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único cliente a uma única empresa numa determinada data.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um produto;&lt;br /&gt;
* uma quantidade (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um preço unitário (o preço do produto no momento da compra);&lt;br /&gt;
* um preço total da linha (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
O preço unitário efectivo utilizado na compra deve ser guardado na própria linha da compra. Uma alteração posterior do preço base do produto pela empresa, do factor multiplicativo da empresa, ou de qualquer outra propriedade relevante para o cálculo do preço, não deve alterar o valor de compras já efectuadas.&lt;br /&gt;
&lt;br /&gt;
O preço total dos itens de uma compra é a soma dos preços totais das suas linhas. A cada compra está ainda associada uma sobretaxa de entrega, correspondente a 10% do preço total dos itens, independentemente do número de entregas.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--Como se descreve na secção seguinte, uma compra pode dar origem a mais do que uma entrega. A divisão de uma compra em várias entregas &#039;&#039;&#039;não acrescenta qualquer custo&#039;&#039;&#039;: a sobretaxa de entrega é sempre 10% do preço total dos itens, independentemente do número de entregas.--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Gestão de Stock ==&lt;br /&gt;
&lt;br /&gt;
O stock de um produto é mantido por cada empresa que o disponibiliza. &lt;br /&gt;
Assim, duas empresas que disponibilizem o mesmo produto podem ter quantidades diferentes desse produto em stock.&lt;br /&gt;
O stock de um produto numa determinada empresa pode ser alterado através da especificação de um valor a somar/subtrair ao número de exemplares disponíveis:&lt;br /&gt;
* se a quantidade indicada for positiva, aumenta-se o número de exemplares disponíveis;&lt;br /&gt;
* se a quantidade indicada for negativa, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares disponíveis de um produto numa determinada empresa chegue a 0, o produto deixa de estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
O produto não é removido do sistema, podendo continuar a ser disponibilizado por outras empresas ou voltar a ser disponibilizado posteriormente pela mesma empresa.&lt;br /&gt;
&lt;br /&gt;
Quando o stock de um produto passa de zero para um valor positivo, o produto volta a estar disponível nessa empresa.&lt;br /&gt;
&lt;br /&gt;
A relação entre uma empresa e um produto pode deixar de existir quando a empresa deixa de disponibilizar esse produto.&lt;br /&gt;
&lt;br /&gt;
O produto global deve, no entanto, continuar a existir no sistema enquanto houver outras razões para a sua existência, independentemente de estar temporariamente disponível ou não em qualquer empresa.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
A cada compra correspondem uma ou mais &#039;&#039;&#039;entregas&#039;&#039;&#039;. As entregas são determinadas a partir dos prazos de entrega dos produtos que constam da compra.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a &#039;&#039;&#039;média dos prazos de entrega&#039;&#039;&#039; dos produtos das linhas da compra. Então:&lt;br /&gt;
* todas as linhas cujo produto tem prazo &#039;&#039;&#039;menor ou igual à média&#039;&#039;&#039; são agrupadas numa única entrega (a entrega &amp;quot;conjunta&amp;quot;);&lt;br /&gt;
* cada linha cujo produto tem prazo &#039;&#039;&#039;estritamente maior do que a média&#039;&#039;&#039; é enviada &#039;&#039;&#039;separadamente&#039;&#039;&#039;, numa entrega própria (uma entrega &amp;quot;conjunta&amp;quot; pode não existir se todas as linhas forem enviadas separadamente).&lt;br /&gt;
&lt;br /&gt;
Cada entrega tem uma data de chegada, calculada a partir da data da compra e do prazo aplicável: uma entrega separada usa o prazo do respectivo produto; a entrega conjunta usa o maior dos prazos dos seus produtos. Como referido acima, o envio separado é feito &#039;&#039;&#039;sem custo adicional&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa entrega e P2 (prazo &amp;gt; 4,33) segue numa entrega separada:&lt;br /&gt;
&lt;br /&gt;
 Entrega A: {P1, P3}   (prazo = 3)&lt;br /&gt;
 Entrega B: {P2}       (prazo = 8)   -- enviada separadamente&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que o sistema ajude os clientes a determinar a existência de um produto, deverá ser possível efectuar pesquisas. As pesquisas consideram os campos relevantes dos vários produtos (por exemplo, o nome e a categoria). O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas. Deve ser possível introduzir novos métodos de pesquisa de um produto com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário de Produtos ==&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;stock&#039;&#039; de um produto pode ser alterado, através da especificação de um valor a somar/subtrair ao número de exemplares: se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis; se for um valor negativo, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares de um produto chegue a 0, então o produto deve ser removido do sistema.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a remoção de um produto tem impacto na gestão das empresas que o vendiam.}}&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente. Sempre que a data é alterada, deve ser verificada a situação das entregas: uma entrega considera-se &#039;&#039;&#039;entregue&#039;&#039;&#039; quando a data actual atinge (ou ultrapassa) a sua data de chegada. Devem ainda ser actualizados outros aspectos que da data dependam.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
Deve existir um mecanismo de notificações que permita avisar eventuais interessados quando os produtos ficam em determinadas situações:&lt;br /&gt;
* Quando um produto sem qualquer exemplar disponível passa a ter pelo menos um exemplar disponível, quer-se enviar uma notificação a todas as entidades que demonstraram interesse nesta situação.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No caso de uma entidade interessada em ser avisada da disponibilidade de um produto, isto significa que, sempre que o produto em causa passar da situação de indisponível (todos os exemplares esgotados) para disponível (pelo menos um exemplar), a entidade deve receber uma notificação. Deve ser possível definir novas entidades interessadas e novos tipos de notificação, com impacto mínimo no código do domínio da aplicação.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis);&lt;br /&gt;
* Adicionar novas categorias de produto;&lt;br /&gt;
* Definir novas entidades que desejem ser notificadas da disponibilidade de produtos;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos métodos de pesquisa de produtos;&lt;br /&gt;
* Alterar a regra de cálculo das entregas e da sobretaxa de entrega com um impacto mínimo no código existente.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
A aplicação deve estar preparada para que se possa remover qualquer entidade (não apenas produtos).&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}&lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17914</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027 (rascunho)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Enunciado_do_Projecto_de_2026-2027_(rascunho)&amp;diff=17914"/>
		<updated>2026-08-26T07:59:21Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM PREPARAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;ÉPOCA NORMAL&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O objectivo do projecto é desenvolver um sistema de gestão de &#039;&#039;&#039;entregas rápidas de produtos&#039;&#039;&#039; (ERP). O sistema deverá permitir, entre outras operações, (i) registar dados de empresas; (ii) registar dados de clientes; (iii) registar e pesquisar produtos; (iv) efectuar compras; e (v) gerir as entregas correspondentes.&lt;br /&gt;
&lt;br /&gt;
Neste texto, o tipo &#039;&#039;&#039;negrito&#039;&#039;&#039; indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo &#039;&#039;itálico&#039;&#039; indica uma parte variável (i.e., uma descrição).&lt;br /&gt;
&lt;br /&gt;
= Conceitos e Relações do Modelo =&lt;br /&gt;
&lt;br /&gt;
Existem vários conceitos importantes neste contexto: [[#Empresas|empresas]], [[#Produtos|produtos]], [[#Clientes|clientes]], [[#Compras|compras]] e [[#Entregas|entregas]].&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Os clientes e os produtos são independentes das empresas: existem por si e podem relacionar-se com várias empresas. &lt;br /&gt;
&lt;br /&gt;
Cada produto pode estar disponível em mais do que uma empresa. Quando uma empresa disponibiliza um produto, deve indicar:&lt;br /&gt;
* o número de unidades do produto que tem disponíveis;&lt;br /&gt;
* o preço base a que disponibiliza o produto;&lt;br /&gt;
* um factor multiplicativo a aplicar ao preço base.&lt;br /&gt;
&lt;br /&gt;
O número de unidades disponíveis, o preço base e o factor multiplicativo podem ser diferentes para cada empresa que disponibiliza o mesmo produto.&lt;br /&gt;
&lt;br /&gt;
Cada empresa mantém ainda registo:&lt;br /&gt;
* dos produtos que disponibiliza;&lt;br /&gt;
* dos clientes com que já interagiu (i.e., que lhe fizeram compras);&lt;br /&gt;
* das entregas que efectuou.&lt;br /&gt;
&lt;br /&gt;
== Empresas ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo das empresas que operam na plataforma. 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).&lt;br /&gt;
&lt;br /&gt;
Uma empresa pode disponibilizar vários produtos. Para cada produto que disponibiliza, a empresa deve manter informação sobre:&lt;br /&gt;
* número de unidades disponíveis;&lt;br /&gt;
* preço base do produto;&lt;br /&gt;
* factor multiplicativo do preço.&lt;br /&gt;
&lt;br /&gt;
Duas empresas podem, assim, disponibilizar o mesmo produto com preços base, factores multiplicativos e quantidades em stock diferentes.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, o produto P1 pode ser disponibilizado pela empresa A com um preço base de 20 euros, um factor multiplicativo de 1,1 e 10 unidades disponíveis, enquanto a empresa B disponibiliza o mesmo produto com um preço base de 18 euros, um factor multiplicativo de 1,0 e 3 unidades disponíveis.&lt;br /&gt;
&lt;br /&gt;
O preço base não corresponde necessariamente ao preço final a pagar pelo cliente. O preço final depende do tipo de produto e das regras aplicáveis ao seu cálculo.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível adicionar outras propriedades às empresas sem impacto significativo no código já desenvolvido.&lt;br /&gt;
&lt;br /&gt;
== Produtos ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo global de 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), uma categoria e um prazo de entrega (número inteiro de dias).&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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 base diferente, utilize um factor multiplicativo diferente e disponha de uma quantidade diferente em stock.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
== Tipos de Produto ==&lt;br /&gt;
&lt;br /&gt;
Todos os produtos considerados no sistema são fabricados, mas podem ter diferentes origens.&lt;br /&gt;
&lt;br /&gt;
Inicialmente, consideram-se os seguintes tipos de produto:&lt;br /&gt;
* produto nacional;&lt;br /&gt;
* produto importado.&lt;br /&gt;
&lt;br /&gt;
Um produto nacional possui apenas as propriedades gerais dos produtos.&lt;br /&gt;
&lt;br /&gt;
Um produto importado possui, para além das propriedades gerais dos produtos:&lt;br /&gt;
* um país de origem (cadeia de caracteres não vazia);&lt;br /&gt;
* uma taxa alfandegária (número inteiro).&lt;br /&gt;
&lt;br /&gt;
A taxa alfandegária representa um custo adicional associado à importação do produto.&lt;br /&gt;
&lt;br /&gt;
O tipo de produto deve ter impacto no cálculo do preço final do produto.&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa deve ser calculado a partir:&lt;br /&gt;
* do preço base definido pela empresa;&lt;br /&gt;
* do factor multiplicativo definido pela empresa;&lt;br /&gt;
* das características específicas do produto.&lt;br /&gt;
&lt;br /&gt;
Para um produto nacional, o preço final corresponde ao preço base multiplicado pelo factor multiplicativo aplicável à disponibilização do produto pela empresa.&lt;br /&gt;
&lt;br /&gt;
Para um produto importado, o preço final corresponde ao preço base multiplicado pelo factor multiplicativo aplicável à disponibilização do produto pela empresa, acrescido da taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, se uma empresa disponibilizar um produto com preço base de 100 euros e factor multiplicativo de 1,1:&lt;br /&gt;
* um produto nacional terá preço final de 110 euros;&lt;br /&gt;
* um produto importado com taxa alfandegária de 20 euros terá preço final de 130 euros.&lt;br /&gt;
&lt;br /&gt;
O cálculo do preço final deve ser realizado de forma polimórfica, de modo a que o código que utiliza produtos não tenha de conhecer explicitamente o tipo concreto de cada produto.&lt;br /&gt;
&lt;br /&gt;
Deve ser possível introduzir novos tipos de produto com impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Cálculo do Preço ==&lt;br /&gt;
&lt;br /&gt;
O preço final de um produto disponibilizado por uma empresa é determinado por uma estratégia de cálculo de preços.&lt;br /&gt;
&lt;br /&gt;
A estratégia recebe a informação necessária para determinar o preço final, incluindo o produto e os valores definidos pela empresa para a sua disponibilização.&lt;br /&gt;
&lt;br /&gt;
Inicialmente devem ser consideradas, pelo menos, as seguintes estratégias:&lt;br /&gt;
* &#039;&#039;&#039;preço normal&#039;&#039;&#039; — o preço final é calculado considerando o preço base e o factor multiplicativo;&lt;br /&gt;
* &#039;&#039;&#039;preço promocional&#039;&#039;&#039; — o preço final é calculado considerando o preço base, o factor multiplicativo e uma redução percentual definida pela promoção.&lt;br /&gt;
&lt;br /&gt;
O sistema deve permitir introduzir novas estratégias de cálculo de preços sem necessidade de alterar o código responsável por efectuar compras.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, futuramente poderão ser introduzidas estratégias que considerem:&lt;br /&gt;
* descontos específicos;&lt;br /&gt;
* campanhas temporárias;&lt;br /&gt;
* preços específicos para determinados clientes;&lt;br /&gt;
* outras regras de formação do preço.&lt;br /&gt;
&lt;br /&gt;
O preço efectivo utilizado numa compra deve ser calculado no momento em que a compra é efectuada.&lt;br /&gt;
&lt;br /&gt;
== Clientes ==&lt;br /&gt;
&lt;br /&gt;
O sistema mantém um registo de clientes. Cada cliente é identificado por um número de cliente. 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 cliente tem ainda informação sobre o seu nome e endereço de correio electrónico. Estes campos não podem ser vazios.&lt;br /&gt;
&lt;br /&gt;
Assume-se que &#039;&#039;&#039;os clientes têm sempre dinheiro&#039;&#039;&#039;, i.e., uma compra nunca é recusada por falta de fundos. Deve, no entanto, ser possível discriminar os clientes segundo outros critérios (por exemplo, o volume de compras), com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Compras ==&lt;br /&gt;
&lt;br /&gt;
O sistema regista as compras efectuadas pelos clientes. Cada compra é identificada por um número de compra, atribuído automaticamente e incrementalmente. Uma compra é sempre feita por um único &#039;&#039;&#039;cliente&#039;&#039;&#039; a uma única &#039;&#039;&#039;empresa&#039;&#039;&#039; e regista a data em que foi efectuada.&lt;br /&gt;
&lt;br /&gt;
Uma compra é constituída por um conjunto de linhas (um &amp;quot;cabaz&amp;quot;). Cada linha corresponde a:&lt;br /&gt;
* um &#039;&#039;&#039;produto&#039;&#039;&#039;;&lt;br /&gt;
* uma &#039;&#039;&#039;quantidade&#039;&#039;&#039; (número de exemplares adquiridos desse produto);&lt;br /&gt;
* um &#039;&#039;&#039;preço unitário&#039;&#039;&#039; (o preço do produto no momento da compra);&lt;br /&gt;
* um &#039;&#039;&#039;preço total da linha&#039;&#039;&#039; (quantidade × preço unitário).&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;&#039;preço total dos itens&#039;&#039;&#039; de uma compra é a soma dos preços totais das suas linhas. A cada compra está ainda associada uma &#039;&#039;&#039;sobretaxa de entrega&#039;&#039;&#039;, correspondente a &#039;&#039;&#039;10% do preço total dos itens&#039;&#039;&#039; (i.e., 10% por item). O &#039;&#039;&#039;preço total da compra&#039;&#039;&#039; é, assim, o preço total dos itens acrescido da sobretaxa de entrega.&lt;br /&gt;
&lt;br /&gt;
Como se descreve na secção seguinte, uma compra pode dar origem a mais do que uma entrega. A divisão de uma compra em várias entregas &#039;&#039;&#039;não acrescenta qualquer custo&#039;&#039;&#039;: a sobretaxa de entrega é sempre 10% do preço total dos itens, independentemente do número de entregas.&lt;br /&gt;
&lt;br /&gt;
== Entregas ==&lt;br /&gt;
&lt;br /&gt;
A cada compra correspondem uma ou mais &#039;&#039;&#039;entregas&#039;&#039;&#039;. As entregas são determinadas a partir dos prazos de entrega dos produtos que constam da compra.&lt;br /&gt;
&lt;br /&gt;
Calcula-se a &#039;&#039;&#039;média dos prazos de entrega&#039;&#039;&#039; dos produtos das linhas da compra. Então:&lt;br /&gt;
* todas as linhas cujo produto tem prazo &#039;&#039;&#039;menor ou igual à média&#039;&#039;&#039; são agrupadas numa única entrega (a entrega &amp;quot;conjunta&amp;quot;);&lt;br /&gt;
* cada linha cujo produto tem prazo &#039;&#039;&#039;estritamente maior do que a média&#039;&#039;&#039; é enviada &#039;&#039;&#039;separadamente&#039;&#039;&#039;, numa entrega própria (uma entrega &amp;quot;conjunta&amp;quot; pode não existir se todas as linhas forem enviadas separadamente).&lt;br /&gt;
&lt;br /&gt;
Cada entrega tem uma data de chegada, calculada a partir da data da compra e do prazo aplicável: uma entrega separada usa o prazo do respectivo produto; a entrega conjunta usa o maior dos prazos dos seus produtos. Como referido acima, o envio separado é feito &#039;&#039;&#039;sem custo adicional&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Por exemplo, considere-se uma compra com três linhas cujos produtos têm os prazos de entrega 3 (P1), 8 (P2) e 2 (P3). A média dos prazos é (3 + 8 + 2) / 3 ≈ 4,33. Logo, P1 e P3 (prazos ≤ 4,33) seguem juntos numa entrega e P2 (prazo &amp;gt; 4,33) segue numa entrega separada:&lt;br /&gt;
&lt;br /&gt;
 Entrega A: {P1, P3}   (prazo = 3)&lt;br /&gt;
 Entrega B: {P2}       (prazo = 8)   -- enviada separadamente&lt;br /&gt;
&lt;br /&gt;
== Pesquisas ==&lt;br /&gt;
&lt;br /&gt;
Para permitir que o sistema ajude os clientes a determinar a existência de um produto, deverá ser possível efectuar pesquisas. As pesquisas consideram os campos relevantes dos vários produtos (por exemplo, o nome e a categoria). O termo de pesquisa deve ser comparado sem distinção entre letras maiúsculas e minúsculas. Deve ser possível introduzir novos métodos de pesquisa de um produto com um impacto mínimo na implementação desenvolvida.&lt;br /&gt;
&lt;br /&gt;
== Alterações de Inventário de Produtos ==&lt;br /&gt;
&lt;br /&gt;
O &#039;&#039;stock&#039;&#039; de um produto pode ser alterado, através da especificação de um valor a somar/subtrair ao número de exemplares: se a quantidade indicada for um valor positivo, aumenta-se o número de exemplares disponíveis; se for um valor negativo, decrementa-se o número de exemplares disponíveis desde que o número de exemplares disponíveis não fique negativo.&lt;br /&gt;
&lt;br /&gt;
Caso o número de exemplares de um produto chegue a 0, então o produto deve ser removido do sistema.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a remoção de um produto tem impacto na gestão das empresas que o vendiam.}}&lt;br /&gt;
&lt;br /&gt;
== Gestão de Tempo ==&lt;br /&gt;
&lt;br /&gt;
A unidade de tempo do sistema é o dia. A data do sistema começa no dia 1 (um) e faz parte do estado persistente. Sempre que a data é alterada, deve ser verificada a situação das entregas: uma entrega considera-se &#039;&#039;&#039;entregue&#039;&#039;&#039; quando a data actual atinge (ou ultrapassa) a sua data de chegada. Devem ainda ser actualizados outros aspectos que da data dependam.&lt;br /&gt;
&lt;br /&gt;
== Notificações ==&lt;br /&gt;
&lt;br /&gt;
Deve existir um mecanismo de notificações que permita avisar eventuais interessados quando os produtos ficam em determinadas situações:&lt;br /&gt;
* Quando um produto sem qualquer exemplar disponível passa a ter pelo menos um exemplar disponível, quer-se enviar uma notificação a todas as entidades que demonstraram interesse nesta situação.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
No caso de uma entidade interessada em ser avisada da disponibilidade de um produto, isto significa que, sempre que o produto em causa passar da situação de indisponível (todos os exemplares esgotados) para disponível (pelo menos um exemplar), a entidade deve receber uma notificação. Deve ser possível definir novas entidades interessadas e novos tipos de notificação, com impacto mínimo no código do domínio da aplicação.&lt;br /&gt;
&lt;br /&gt;
= Requisitos de Desenho =&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
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:&lt;br /&gt;
* Adicionar novos tipos de produto (e.g., produtos digitais ou perecíveis);&lt;br /&gt;
* Adicionar novas categorias de produto;&lt;br /&gt;
* Definir novas entidades que desejem ser notificadas da disponibilidade de produtos;&lt;br /&gt;
* Introduzir novos critérios de discriminação/classificação dos clientes;&lt;br /&gt;
* Introduzir novos métodos de pesquisa de produtos;&lt;br /&gt;
* Alterar a regra de cálculo das entregas e da sobretaxa de entrega com um impacto mínimo no código existente.&lt;br /&gt;
&lt;br /&gt;
= Funcionalidade da aplicação =&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
A aplicação deve estar preparada para que se possa remover qualquer entidade (não apenas produtos).&lt;br /&gt;
&lt;br /&gt;
No [[#Leitura de Dados a Partir de Ficheiros Textuais|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.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|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 &#039;&#039;core&#039;&#039; da aplicação, tal como é visível pelos comandos da aplicação.}}&lt;br /&gt;
{{CVSCode|A interface geral do &#039;&#039;core&#039;&#039; já está parcialmente implementada na classe &#039;&#039;&#039;erp.ErpManager&#039;&#039;&#039; 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.}}&lt;br /&gt;
&lt;br /&gt;
== Serialização ==&lt;br /&gt;
&lt;br /&gt;
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relacionada com o ERP e que foi descrita [[#Conceitos e Relações do Modelo|acima]].&lt;br /&gt;
&lt;br /&gt;
= Interacção com o utilizador =&lt;br /&gt;
&lt;br /&gt;
Descreve-se nesta secção a &#039;&#039;&#039;funcionalidade máxima&#039;&#039;&#039; 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 &#039;&#039;&#039;Sair&#039;&#039;&#039; (fecha o menu).&lt;br /&gt;
&lt;br /&gt;
As operações de pedido e apresentação de informação ao utilizador &#039;&#039;&#039;devem&#039;&#039;&#039; realizar-se através dos objectos &#039;&#039;form&#039;&#039; e &#039;&#039;display&#039;&#039;, respectivamente, presentes em cada comando. As mensagens são produzidas pelos métodos das [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|bibliotecas de suporte]] (&#039;&#039;&#039;po-uilib&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039;). As mensagens não podem ser usadas no núcleo da aplicação (&#039;&#039;&#039;erp-core&#039;&#039;&#039;). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.&lt;br /&gt;
&lt;br /&gt;
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 &#039;&#039;&#039;erp.app.exceptions&#039;&#039;&#039;, excepto em caso de indicação contrária.&lt;br /&gt;
&lt;br /&gt;
As excepções usadas na interacção (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.CommandException&#039;&#039;&#039;), excepto em caso de indicação contrária, são lançadas pelos comandos (subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Command&#039;&#039;&#039;) e tratadas pelos menus (instâncias de subclasses de &#039;&#039;&#039;pt.tecnico.uilib.menus.Menu&#039;&#039;&#039;). Outras excepções não devem substituir as fornecidas nos casos descritos.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
{|&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Tipo de dados&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Classe&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Pedido a apresentar&#039;&#039;&#039;&lt;br /&gt;
! style=&amp;quot;background: #ebebeb;&amp;quot; | &#039;&#039;&#039;Excepção a lançar se desconhecido&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Empresa&lt;br /&gt;
| &#039;&#039;&#039;Company&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.company.Prompt.companyId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownCompanyKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Produto&lt;br /&gt;
| &#039;&#039;&#039;Product&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.product.Prompt.productId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownProductKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Cliente&lt;br /&gt;
| &#039;&#039;&#039;Client&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.client.Prompt.clientId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownClientKeyException&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
| Compra&lt;br /&gt;
| &#039;&#039;&#039;Purchase&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.purchase.Prompt.purchaseId()&#039;&#039;&#039;&lt;br /&gt;
| &#039;&#039;&#039;erp.app.exceptions.UnknownPurchaseKeyException&#039;&#039;&#039;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Alguns casos particulares podem usar pedidos específicos não apresentados nesta tabela.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcial ou completamente implementados nas &#039;&#039;packages&#039;&#039; &#039;&#039;&#039;erp.app&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.company&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.product&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.client&#039;&#039;&#039;, &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039;. Estas classes são de uso obrigatório e estão disponíveis no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|GIT]] (módulo &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Menu Principal ==&lt;br /&gt;
&lt;br /&gt;
As acções deste menu permitem gerir a salvaguarda do estado da aplicação e abrir submenus. A lista completa é a seguinte: [[#Salvaguarda do estado actual da aplicação|Abrir]], [[#Salvaguarda do estado actual da aplicação|Guardar]], [[#Mostrar data actual|Mostrar data actual]], [[#Avançar data actual|Avançar data actual]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Empresas]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Clientes]] e [[#Gestão e consulta de dados da aplicação|Menu de Gestão de Compras]]. Inicialmente, a aplicação apenas tem informação sobre as entidades que foram carregadas no arranque.&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas na classe &#039;&#039;&#039;erp.app.main.Label&#039;&#039;&#039;. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe &#039;&#039;&#039;erp.app.main.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.main&#039;&#039;&#039;, respectivamente: &#039;&#039;&#039;DoOpenFile&#039;&#039;&#039;, &#039;&#039;&#039;DoSaveFile&#039;&#039;&#039;, &#039;&#039;&#039;DoDisplayDate&#039;&#039;&#039;, &#039;&#039;&#039;DoAdvanceDate&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuCompanies&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuClients&#039;&#039;&#039;, &#039;&#039;&#039;DoOpenMenuPurchases&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Salvaguarda do estado actual da aplicação ===&lt;br /&gt;
&lt;br /&gt;
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: &#039;&#039;&#039;java.io.Serializable&#039;&#039;&#039;). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Abrir&#039;&#039;&#039; -- 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 (&#039;&#039;&#039;Prompt.openFile()&#039;&#039;&#039;). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção &#039;&#039;&#039;FileOpenFailedException&#039;&#039;&#039;. A execução bem-sucedida desta opção substitui toda a informação da aplicação. &amp;lt;br/&amp;gt;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 &#039;&#039;&#039;Prompt.saveBeforeExit()&#039;&#039;&#039; (a resposta é obtida via &#039;&#039;&#039;Form.confirm()&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Guardar&#039;&#039;&#039; -- 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 &#039;&#039;&#039;Prompt.newSaveAs()&#039;&#039;&#039;. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Note-se que a opção &#039;&#039;&#039;Abrir&#039;&#039;&#039; não permite a leitura de ficheiros de texto (estes apenas podem ser utilizados no início da aplicação).}}&lt;br /&gt;
{{Suggestion|A opção &#039;&#039;&#039;Sair&#039;&#039;&#039; nunca implica a salvaguarda do estado da aplicação, mesmo que existam alterações.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar data actual ===&lt;br /&gt;
&lt;br /&gt;
A data actual do sistema é apresentada através da mensagem &#039;&#039;&#039;Message.currentDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Avançar data actual ===&lt;br /&gt;
&lt;br /&gt;
O número de dias a avançar é pedido através de &#039;&#039;&#039;Prompt.daysToAdvance()&#039;&#039;&#039;. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.&lt;br /&gt;
&lt;br /&gt;
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação das entregas relativa às suas datas de chegada.&lt;br /&gt;
&lt;br /&gt;
=== Gestão e consulta de dados da aplicação ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Empresas&#039;&#039;&#039; -- Abre o menu de gestão de empresas e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Produtos&#039;&#039;&#039; -- Abre o menu de gestão de produtos e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Clientes&#039;&#039;&#039; -- Abre o menu de gestão de clientes e operações associadas.&lt;br /&gt;
* &#039;&#039;&#039;Menu de Gestão de Compras&#039;&#039;&#039; -- Abre o menu de gestão de compras e operações associadas.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Empresas ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de empresas. A lista completa é a seguinte: [[#Registar empresa|Registar empresa]], [[#Mostrar empresa|Mostrar empresa]], [[#Mostrar empresas|Mostrar empresas]], [[#Mostrar produtos de uma empresa|Mostrar produtos de uma empresa]], [[#Mostrar clientes de uma empresa|Mostrar clientes de uma empresa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.company.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.company.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.company.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar empresa ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.companyName()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;CompanyRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador da empresa é automática.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa, sendo apresentadas as informações sobre essa empresa, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma empresa|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar empresas ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as empresas, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar empresa|Mostrar empresa]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os produtos que essa empresa vende, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes de uma empresa ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da empresa e apresentam-se os clientes que já interagiram com essa empresa, ordenados pelos seus identificadores, utilizando o formato descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Produtos ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações disponíveis sobre produtos. A lista completa é a seguinte: [[#Mostrar produto|Mostrar produto]], [[#Mostrar produtos|Mostrar produtos]], [[#Alterar inventário de um produto|Alterar inventário de um produto]] e [[#Efectuar pesquisa|Efectuar pesquisa]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.product.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.product.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.product.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.product&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoShowProduct&#039;&#039;&#039;, &#039;&#039;&#039;DoShowProducts&#039;&#039;&#039;, &#039;&#039;&#039;DoChangeProductInventory&#039;&#039;&#039;, &#039;&#039;&#039;DoPerformSearch&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do produto. Se o produto existir, é apresentado de acordo com o seguinte formato. O formato genérico de apresentação de um produto é como se segue:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de produtos|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;stock&#039;&#039; - &#039;&#039;tipo&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;preço&#039;&#039; - &#039;&#039;categoria&#039;&#039; - &#039;&#039;informação adicional&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Para produtos fabricados, a informação adicional corresponde ao nome do fabricante e ao código de fabrico (separados pelo carácter &#039;&#039;&#039;;&#039;&#039;&#039;); para produtos importados, a informação adicional corresponde ao país de origem e à taxa alfandegária.&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de produtos|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
3 - 20 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
4 - 2 - IMPORTADO - Telemóvel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
5 - 0 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar produtos ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os produtos, ordenando-os pelos seus identificadores. O formato de apresentação é como descrito em [[#Mostrar produto|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
=== Alterar inventário de um produto ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador de um produto e uma quantidade (&#039;&#039;&#039;Prompt.amountToUpdate()&#039;&#039;&#039;) e actualizado o número de exemplares disponíveis do produto indicado somando a quantidade indicada ao número de exemplares disponíveis. No caso de não ser possível actualizar o número de exemplares devido ao facto de a quantidade indicada ser inválida, então a operação não deve ter qualquer efeito e deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Efectuar pesquisa ===&lt;br /&gt;
&lt;br /&gt;
Esta opção realiza uma procura por termo (cadeia de caracteres), pedido através de &#039;&#039;&#039;Prompt.searchTerm()&#039;&#039;&#039;. 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|Mostrar produto]].&lt;br /&gt;
&lt;br /&gt;
O termo de pesquisa deve ser comparado (sem distinção entre letras maiúsculas e minúsculas) com os campos relevantes de cada produto: o nome e a categoria. Só devem ser apresentados produtos que contenham o termo de pesquisa num dos campos relevantes. Caso não sejam encontrados produtos, não deve ser produzido qualquer resultado.&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Clientes ==&lt;br /&gt;
&lt;br /&gt;
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Registar cliente|Registar cliente]], [[#Mostrar cliente|Mostrar cliente]], [[#Mostrar clientes|Mostrar clientes]], [[#Mostrar notificações do cliente|Mostrar notificações do cliente]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.client.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.client.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.client.Message&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Registar cliente ===&lt;br /&gt;
&lt;br /&gt;
Pede o nome (&#039;&#039;&#039;Prompt.clientName()&#039;&#039;&#039;) e o endereço de correio electrónico (&#039;&#039;&#039;Prompt.clientEMail()&#039;&#039;&#039;). O registo bem sucedido é assinalado através da mensagem &#039;&#039;&#039;Message.registrationSuccessful()&#039;&#039;&#039;; caso contrário, é lançada a excepção &#039;&#039;&#039;ClientRegistrationFailedException&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Note-se que a atribuição do identificador do cliente é automática e que clientes diferentes são registados em cada operação de registo.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as informações sobre esse cliente, de acordo com o seguinte formato. O valor apresentado após o email corresponde ao total gasto pelo cliente em compras (um valor inteiro).&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de um cliente|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;nome&#039;&#039; - &#039;&#039;email&#039;&#039; - &#039;&#039;gasto total&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de clientes|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
2 - Alberto Meireles - ameireles@mymail.com - 275&lt;br /&gt;
1 - Fernando Meireles - fmeireles@mymail.com - 0&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar clientes ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todos os clientes, ordenando-os lexicograficamente pelo nome. Caso existam clientes com o mesmo nome, devem ser ordenados por ordem crescente dos seus identificadores. O formato é o descrito em [[#Mostrar cliente|Mostrar cliente]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar notificações do cliente ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador do cliente, sendo apresentadas as notificações para esse cliente, de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação das notificações de um cliente|&lt;br /&gt;
 DISPONIBILIDADE: &#039;&#039;descrição de produto disponível&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de notificações|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
DISPONIBILIDADE: 5 - 4 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Note-se que a descrição é idêntica à que é realizada para mostrar cada produto. No entanto, a solução deve ser suficientemente flexível para permitir outros formatos de apresentação das notificações (sem impacto no código do domínio da aplicação).&lt;br /&gt;
&lt;br /&gt;
== Menu de Gestão de Compras ==&lt;br /&gt;
&lt;br /&gt;
Este menu apresenta as operações relacionadas com compras e entregas. A lista completa é a seguinte: [[#Efectuar compra|Efectuar compra]], [[#Mostrar compra|Mostrar compra]], [[#Mostrar compras|Mostrar compras]], [[#Mostrar entregas de uma compra|Mostrar entregas de uma compra]].&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|As etiquetas das opções deste menu estão definidas em &#039;&#039;&#039;erp.app.purchase.Label&#039;&#039;&#039;. Os métodos correspondentes às mensagens de diálogo para este menu estão definidos em &#039;&#039;&#039;erp.app.purchase.Prompt&#039;&#039;&#039; e &#039;&#039;&#039;erp.app.purchase.Message&#039;&#039;&#039;.}}&lt;br /&gt;
{{CVSCode|Estes comandos já estão implementados nas classes da &#039;&#039;package&#039;&#039; &#039;&#039;&#039;erp.app.purchase&#039;&#039;&#039; (disponível no GIT), respectivamente: &#039;&#039;&#039;DoDoPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchase&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchases&#039;&#039;&#039;, &#039;&#039;&#039;DoShowPurchaseDeliveries&#039;&#039;&#039;.}}&lt;br /&gt;
&lt;br /&gt;
=== Efectuar compra ===&lt;br /&gt;
&lt;br /&gt;
No processo de efectuar uma compra, o sistema pede, primeiro, a identificação do cliente; de seguida, a identificação da empresa a que a compra é feita; e, finalmente, para cada linha, o identificador do produto e a quantidade pretendida (&#039;&#039;&#039;Prompt.productId()&#039;&#039;&#039; e &#039;&#039;&#039;Prompt.amountToBuy()&#039;&#039;&#039;). O processo de adição de linhas termina de acordo com a interacção definida no comando.&lt;br /&gt;
&lt;br /&gt;
Se não houver exemplares suficientes de um produto para satisfazer a quantidade pretendida, deve ser apresentada a mensagem &#039;&#039;&#039;Message.notEnoughInventory()&#039;&#039;&#039; e essa linha não é adicionada. Concluída a compra, o &#039;&#039;stock&#039;&#039; dos produtos é decrementado, a empresa passa a seguir o cliente e são determinadas as entregas correspondentes. A data limite de chegada de cada entrega é comunicada através da mensagem &#039;&#039;&#039;Message.deliveryDate()&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra. Na primeira linha apresenta-se a informação da compra; de seguida, apresentam-se as suas entregas &#039;&#039;&#039;em detalhe&#039;&#039;&#039; — cada entrega (identificador da compra e data de chegada) seguida da descrição completa de cada um dos seus produtos (o mesmo formato de [[#Mostrar produto|Mostrar produto]]). O formato é o seguinte:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma compra (com entregas em detalhe)|&lt;br /&gt;
 &#039;&#039;id&#039;&#039; - &#039;&#039;idCliente&#039;&#039; - &#039;&#039;idEmpresa&#039;&#039; - &#039;&#039;data&#039;&#039; - &#039;&#039;preço total dos itens&#039;&#039; - &#039;&#039;sobretaxa de entrega&#039;&#039; - &#039;&#039;preço total&#039;&#039;&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039;&lt;br /&gt;
   &#039;&#039;descrição de produto&#039;&#039;&lt;br /&gt;
   ...&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de compras|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 3 - 1 - 4 - 90 - 9 - 99&lt;br /&gt;
7 - 7&lt;br /&gt;
  1 - 18 - FABRICADO - Farinha - 15 - ALIMENTAR - Moageira Nacional; F-0091&lt;br /&gt;
  3 - 2 - FABRICADO - Camisa - 45 - VESTUARIO - Confeccoes Sul; C-1120&lt;br /&gt;
7 - 12&lt;br /&gt;
  2 - 1 - IMPORTADO - Telemovel - 200 - ELECTRONICA - China - 30&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
=== Mostrar compras ===&lt;br /&gt;
&lt;br /&gt;
Apresenta informações sobre todas as compras, ordenando-as pelos seus identificadores. O formato é o descrito em [[#Mostrar compra|Mostrar compra]].&lt;br /&gt;
&lt;br /&gt;
=== Mostrar entregas de uma compra ===&lt;br /&gt;
&lt;br /&gt;
É pedido o identificador da compra e são apresentadas as entregas correspondentes, ordenadas pela data de chegada e, em caso de empate, pelos identificadores dos produtos. Ao contrário de [[#Mostrar compra|Mostrar compra]] (que apresenta as entregas em detalhe), aqui cada entrega é apresentada &#039;&#039;&#039;de forma resumida&#039;&#039;&#039; (uma linha, apenas com os identificadores dos produtos), de acordo com o seguinte formato:&lt;br /&gt;
{{CollapsedCode|Formato de apresentação de uma entrega|&lt;br /&gt;
 &#039;&#039;idCompra&#039;&#039; - &#039;&#039;data de chegada&#039;&#039; - &#039;&#039;lista de identificadores de produtos&#039;&#039;&lt;br /&gt;
}}&lt;br /&gt;
{{CollapsedCode|Exemplos de apresentação de entregas (compra do exemplo da secção Entregas)|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
7 - 7 - 1, 3&lt;br /&gt;
7 - 12 - 2&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
= Leitura de Dados a Partir de Ficheiros Textuais =&lt;br /&gt;
&lt;br /&gt;
Além das opções de manipulação de ficheiros descritas no [[#Menu Principal|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java &#039;&#039;&#039;[[#Execução do Programa e Testes Automáticos|import]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
Cada linha tem uma descrição distinta mas que segue o seguinte formato geral. É possível registar empresas, clientes e produtos, e definir os produtos que cada empresa vende. Assume-se que os campos de texto não podem conter o carácter &#039;&#039;&#039;:&#039;&#039;&#039; e que os preços são números inteiros. Não existem entradas mal-formadas.&lt;br /&gt;
&lt;br /&gt;
Os produtos têm o formato descrito abaixo, respectivamente, para produtos fabricados e importados. O campo &#039;&#039;stock&#039;&#039; indica o número de exemplares disponíveis do produto.&lt;br /&gt;
&lt;br /&gt;
 MANUFACTURED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;fabricante&#039;&#039;:&#039;&#039;codigo&#039;&#039;&lt;br /&gt;
 IMPORTED:&#039;&#039;idEmpresa&#039;&#039;:&#039;&#039;nome&#039;&#039;:&#039;&#039;preço&#039;&#039;:&#039;&#039;categoria&#039;&#039;:&#039;&#039;prazo&#039;&#039;:&#039;&#039;stock&#039;&#039;:&#039;&#039;paisOrigem&#039;&#039;:&#039;&#039;taxa&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O registo de empresas e de clientes segue os formatos:&lt;br /&gt;
&lt;br /&gt;
 COMPANY:&#039;&#039;nome&#039;&#039;&lt;br /&gt;
 CLIENT:&#039;&#039;nome&#039;&#039;:&#039;&#039;email&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Um exemplo de conteúdo do ficheiro inicial é como se segue:&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Exemplo de ficheiro de entrada textual|&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
COMPANY:Moageira Nacional&lt;br /&gt;
COMPANY:Importadora Atlantico&lt;br /&gt;
CLIENT:Obi-Wan Kenobi:obiwan@jedi.org&lt;br /&gt;
MANUFACTURED:1:Farinha:15:ALIMENTAR:3:23:Moageira Nacional:F-0091&lt;br /&gt;
IMPORTED:2:Telemovel:200:ELECTRONICA:8:2:China:30&lt;br /&gt;
MANUFACTURED:1:Camisa:45:VESTUARIO:2:4:Confeccoes Sul:C-1120&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os métodos &#039;&#039;&#039;String.split()&#039;&#039;&#039;, para partir cadeias de caracteres, e &#039;&#039;&#039;String.trim()&#039;&#039;&#039;, para remover espaços no início e no final, podem ser usados no processamento de cada linha.}}&lt;br /&gt;
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato (é apenas um formato para ficheiros de entrada).}}&lt;br /&gt;
&lt;br /&gt;
= Execução do Programa e Testes Automáticos =&lt;br /&gt;
&lt;br /&gt;
Usando os ficheiros &#039;&#039;&#039;test.import&#039;&#039;&#039;, &#039;&#039;&#039;test.in&#039;&#039;&#039; e &#039;&#039;&#039;test.out&#039;&#039;&#039;, é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável &#039;&#039;&#039;CLASSPATH&#039;&#039;&#039; (ou da opção equivalente &#039;&#039;&#039;-cp&#039;&#039;&#039; do comando &#039;&#039;&#039;java&#039;&#039;&#039;), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação (&#039;&#039;&#039;erp.app.App.main&#039;&#039;&#039;). As propriedades são tratadas automaticamente pelo código de apoio.&lt;br /&gt;
&lt;br /&gt;
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp erp.app.App&lt;br /&gt;
&lt;br /&gt;
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída &#039;&#039;&#039;test.outhyp&#039;&#039;&#039;. Em caso de sucesso, os ficheiros das saídas esperada (&#039;&#039;&#039;test.out&#039;&#039;&#039;) e obtida (&#039;&#039;&#039;test.outhyp&#039;&#039;&#039;) devem ser iguais. A comparação pode ser feita com o comando:&lt;br /&gt;
&lt;br /&gt;
         diff -b test.out test.outhyp&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
= Notas de Implementação =&lt;br /&gt;
&lt;br /&gt;
Tal como indicado acima, algumas classes fornecidas como [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|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.&lt;br /&gt;
&lt;br /&gt;
A serialização Java usa as classes da &#039;&#039;package&#039;&#039; [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/package-summary.html java.io], em particular, a interface [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/Serializable.html java.io.Serializable] e as classes de leitura [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectInputStream.html java.io.ObjectInputStream] e escrita [https://docs.oracle.com/en/java/javase/24/docs/api/java.base/java/io/ObjectOutputStream.html java.io.ObjectOutputStream] (entre outras).&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_da_Disciplina&amp;diff=17913</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global da Disciplina</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_da_Disciplina&amp;diff=17913"/>
		<updated>2026-08-26T07:21:38Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
== Pauta Global ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Época Normal:&#039;&#039;&#039; ver prazo de revisão nas páginas correspondentes às provas em curso. &amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt; &#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Época Especial:&#039;&#039;&#039; provas a realizar em Julho de 2027 (ver datas na página da disciplina: Fénix) &amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Não existem arredondamentos (excepto na coluna &#039;&#039;&#039;FINAL&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Condições de aprovação: &#039;&#039;&#039;NOTA&#039;&#039;&#039;, &#039;&#039;&#039;EXR&#039;&#039;&#039;, &#039;&#039;&#039;PRJ&#039;&#039;&#039;, &#039;&#039;&#039;EE&#039;&#039;&#039; têm de ser iguais ou superiores a 9.5.&lt;br /&gt;
&lt;br /&gt;
Legenda:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FINAL&#039;&#039;&#039; - resultado da avaliação (será lançado na secretaria)&lt;br /&gt;
* &#039;&#039;&#039;NOTA&#039;&#039;&#039; - resultado numérico da avaliação (quando aplicável) &lt;br /&gt;
* &#039;&#039;&#039;EXR&#039;&#039;&#039; - nota final dos exercícios de programação &lt;br /&gt;
* &#039;&#039;&#039;PRJ&#039;&#039;&#039; - nota final do projecto (inclui nota do teste prático) &lt;br /&gt;
* &#039;&#039;&#039;EE&#039;&#039;&#039; - época especial (6 exercícios de programação) &lt;br /&gt;
&lt;br /&gt;
As notações especiais têm o seguinte significado:&lt;br /&gt;
* &#039;&#039;&#039;NA&#039;&#039;&#039; - &amp;quot;não avaliado&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;RE&#039;&#039;&#039; - &amp;quot;reprovado&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Final&amp;diff=17912</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Final</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Final&amp;diff=17912"/>
		<updated>2026-08-26T07:21:00Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega final é obrigatória&#039;&#039;&#039; e vale 11 valores em 20 (5.5 valores para a avaliação automática).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente no Fénix.&lt;br /&gt;
&lt;br /&gt;
==Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (colunas laranja).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot; (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
&lt;br /&gt;
O significado das anotações é semelhante ao das utilizadas na pauta da entrega intermédia.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Interm%C3%A9dia&amp;diff=17911</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Intermédia</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Interm%C3%A9dia&amp;diff=17911"/>
		<updated>2026-08-26T07:20:42Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega intermédia é obrigatória&#039;&#039;&#039; e vale 6 valores em 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Os alunos devem compreender/verificar/corrigir os problemas reportados.&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Esta pauta está em revisão até à data da entrega final do projecto.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (colunas laranja).&lt;br /&gt;
&lt;br /&gt;
A coluna &amp;quot;Auto&amp;quot; indica a percentagem de teste automáticos certos e vale 2.5 valores.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot;  (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação dos testes automáticos&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
Ver avaliação automática no GitLab (RNL): https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
&lt;br /&gt;
São consideradas irrelevantes diferenças que consistam apenas em quantidade de espaços brancos (não ter espaços é considerada uma diferença).&lt;br /&gt;
&amp;lt;!--* O uso da função &#039;&#039;&#039;fileNotFound&#039;&#039;&#039; com e sem argumentos é considerado igual.--&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação das anotações&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
&#039;&#039;&#039;Atributos não públicos:&#039;&#039;&#039;&lt;br /&gt;
* public - atributos públicos&lt;br /&gt;
* protected - atributos protected (potencialmente desnecessária a qualificação)&lt;br /&gt;
* package - atributos sem qualificação de acesso&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Atributos e métodos não “static”&#039;&#039;&#039;&lt;br /&gt;
* (const) - contantes&lt;br /&gt;
* (comparator) - constantes (comparador)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Serialização&#039;&#039;&#039;&lt;br /&gt;
* ois - problemas na utilização de ObjectInputStream&lt;br /&gt;
* oos - problemas na utilização de ObjectOutputStream&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Utilização de estruturas de dados correctas&#039;&#039;&#039;&lt;br /&gt;
* lists - utilização de listas onde se justifica a utilização de mapas&lt;br /&gt;
* generics - falta de parâmetro em tipo paramétrico&lt;br /&gt;
* Object - utilização directa da classe Object (sem ser para satisfazer um requisito de Java)&lt;br /&gt;
* Exception - utilização directa da classe Exception (processamento indiscriminado de excepções)&lt;br /&gt;
* instanceof - uso de instanceof (não é justificável numa solução de boa qualidade) (idem para getClass)&lt;br /&gt;
* System.* - problemas na utilização de canais de I/O&lt;br /&gt;
* app attrs/fields - definição de atributos em classes da app: deveriam ser variáveis locais a métodos ou simplesmente não existir&lt;br /&gt;
* ArrayList/TreeMap/HashSet/etc. - uso de tipos concretos em declarações de atributos (usar List/Map/Set/etc.)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Separação app/core&#039;&#039;&#039;&lt;br /&gt;
* serialization - uso de primitivas de serialização na app&lt;br /&gt;
* options - não uso de processo de escolha de opções&lt;br /&gt;
* reader - criação do leitor do ficheiro indicado pela propriedade &amp;quot;import&amp;quot; na app&lt;br /&gt;
* core exposed - exposição desnecessária de estruturas/abstracções do core&lt;br /&gt;
* except - não tratamento de excepções na app&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Qualidade do projecto (apreciação global)&#039;&#039;&#039;&lt;br /&gt;
* instanceof - uso de instanceof (não é justificável numa solução de boa qualidade) (idem para getClass)&lt;br /&gt;
* Object - utilização directa da classe Object (sem ser para satisfazer um requisito de Java)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Javadoc&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Seguir regras codificação&#039;&#039;&#039;&lt;br /&gt;
* class - erros de nomenclatura (maus nomes para classes)&lt;br /&gt;
* vars - erros de nomenclatura (maus nomes para variáveis)&lt;br /&gt;
* funcs - erros de nomenclatura (maus nomes para funções)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Lixo no Repositório&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Interm%C3%A9dia&amp;diff=17910</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Intermédia</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Interm%C3%A9dia&amp;diff=17910"/>
		<updated>2026-08-26T07:20:22Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega intermédia é obrigatória&#039;&#039;&#039; e vale 6 valores em 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os alunos devem compreender/verificar/corrigir os problemas reportados.}}&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Esta pauta está em revisão até à data da entrega final do projecto.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (colunas laranja).&lt;br /&gt;
&lt;br /&gt;
A coluna &amp;quot;Auto&amp;quot; indica a percentagem de teste automáticos certos e vale 2.5 valores.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot;  (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação dos testes automáticos&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
Ver avaliação automática no GitLab (RNL): https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
&lt;br /&gt;
São consideradas irrelevantes diferenças que consistam apenas em quantidade de espaços brancos (não ter espaços é considerada uma diferença).&lt;br /&gt;
&amp;lt;!--* O uso da função &#039;&#039;&#039;fileNotFound&#039;&#039;&#039; com e sem argumentos é considerado igual.--&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação das anotações&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
&#039;&#039;&#039;Atributos não públicos:&#039;&#039;&#039;&lt;br /&gt;
* public - atributos públicos&lt;br /&gt;
* protected - atributos protected (potencialmente desnecessária a qualificação)&lt;br /&gt;
* package - atributos sem qualificação de acesso&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Atributos e métodos não “static”&#039;&#039;&#039;&lt;br /&gt;
* (const) - contantes&lt;br /&gt;
* (comparator) - constantes (comparador)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Serialização&#039;&#039;&#039;&lt;br /&gt;
* ois - problemas na utilização de ObjectInputStream&lt;br /&gt;
* oos - problemas na utilização de ObjectOutputStream&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Utilização de estruturas de dados correctas&#039;&#039;&#039;&lt;br /&gt;
* lists - utilização de listas onde se justifica a utilização de mapas&lt;br /&gt;
* generics - falta de parâmetro em tipo paramétrico&lt;br /&gt;
* Object - utilização directa da classe Object (sem ser para satisfazer um requisito de Java)&lt;br /&gt;
* Exception - utilização directa da classe Exception (processamento indiscriminado de excepções)&lt;br /&gt;
* instanceof - uso de instanceof (não é justificável numa solução de boa qualidade) (idem para getClass)&lt;br /&gt;
* System.* - problemas na utilização de canais de I/O&lt;br /&gt;
* app attrs/fields - definição de atributos em classes da app: deveriam ser variáveis locais a métodos ou simplesmente não existir&lt;br /&gt;
* ArrayList/TreeMap/HashSet/etc. - uso de tipos concretos em declarações de atributos (usar List/Map/Set/etc.)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Separação app/core&#039;&#039;&#039;&lt;br /&gt;
* serialization - uso de primitivas de serialização na app&lt;br /&gt;
* options - não uso de processo de escolha de opções&lt;br /&gt;
* reader - criação do leitor do ficheiro indicado pela propriedade &amp;quot;import&amp;quot; na app&lt;br /&gt;
* core exposed - exposição desnecessária de estruturas/abstracções do core&lt;br /&gt;
* except - não tratamento de excepções na app&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Qualidade do projecto (apreciação global)&#039;&#039;&#039;&lt;br /&gt;
* instanceof - uso de instanceof (não é justificável numa solução de boa qualidade) (idem para getClass)&lt;br /&gt;
* Object - utilização directa da classe Object (sem ser para satisfazer um requisito de Java)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Javadoc&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Seguir regras codificação&#039;&#039;&#039;&lt;br /&gt;
* class - erros de nomenclatura (maus nomes para classes)&lt;br /&gt;
* vars - erros de nomenclatura (maus nomes para variáveis)&lt;br /&gt;
* funcs - erros de nomenclatura (maus nomes para funções)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Lixo no Repositório&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17909</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta das Aulas Práticas</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17909"/>
		<updated>2026-08-26T07:19:18Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Legenda */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;!--&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&#039;&#039;&#039;PAUTA FECHADA&#039;&#039;&#039;&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;EM ACTUALIZAÇÃO&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A avaliação nestas aulas é obrigatória e não é repetível fora da semana em que cada exercício é realizado.&amp;lt;br/&amp;gt;&lt;br /&gt;
Não se avaliam alunos fora do turno de inscrição.&lt;br /&gt;
&lt;br /&gt;
Alunos que compareçam atrasados a estas aulas não são avaliados.&amp;lt;br/&amp;gt;&lt;br /&gt;
É admitido um limite máximo de 20 minutos para entrada em cada aula, após a hora definida para a aula (i.e., já contabilizando os 10 minutos do início).&lt;br /&gt;
&lt;br /&gt;
Não são considerados casos especiais na avaliação das aulas práticas. Alunos que considerem ter direito a tratamento especial e que não consigam comparecer com aproveitamento nestas aulas poderão requerer avaliação em época especial.&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazos de revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente a cada semana no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
As colunas agregadas da pauta têm o seguinte significado:&lt;br /&gt;
* &#039;&#039;Nota&#039;&#039; indica a nota final (são contabilizados os 10 melhores exercícios)&lt;br /&gt;
* &#039;&#039;Média&#039;&#039; indica a média dos exercícios apresentados (são contabilizados todos os exercícios para a média: é meramente indicativa e não é usada na avaliação)&lt;br /&gt;
&lt;br /&gt;
As classificações possíveis para cada exercício são:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.00&amp;lt;/font&amp;gt; - ignorância (quase) completa da matéria em avaliação&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.25&amp;lt;/font&amp;gt; - erros graves ou solução muito incompleta ou inadequada&lt;br /&gt;
* 0.50 - erros importantes ou solução incompleta&lt;br /&gt;
* 0.75 - erros menos graves ou solução quase completa&lt;br /&gt;
* &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;1.00&amp;lt;/font&amp;gt; - solução completa&lt;br /&gt;
&lt;br /&gt;
{{Aviso|Obter classificações abaixo de 0.75 deve constituir motivo de preocupação, especialmente nos casos 0 e 0.25, sendo os alunos fortemente encorajados a contactar o responsável pela disciplina para consulta dos exercícios em causa.}}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17908</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta das Aulas Práticas</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17908"/>
		<updated>2026-08-26T07:18:54Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;!--&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&#039;&#039;&#039;PAUTA FECHADA&#039;&#039;&#039;&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;EM ACTUALIZAÇÃO&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A avaliação nestas aulas é obrigatória e não é repetível fora da semana em que cada exercício é realizado.&amp;lt;br/&amp;gt;&lt;br /&gt;
Não se avaliam alunos fora do turno de inscrição.&lt;br /&gt;
&lt;br /&gt;
Alunos que compareçam atrasados a estas aulas não são avaliados.&amp;lt;br/&amp;gt;&lt;br /&gt;
É admitido um limite máximo de 20 minutos para entrada em cada aula, após a hora definida para a aula (i.e., já contabilizando os 10 minutos do início).&lt;br /&gt;
&lt;br /&gt;
Não são considerados casos especiais na avaliação das aulas práticas. Alunos que considerem ter direito a tratamento especial e que não consigam comparecer com aproveitamento nestas aulas poderão requerer avaliação em época especial.&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazos de revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente a cada semana no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
As colunas agregadas da pauta têm o seguinte significado:&lt;br /&gt;
* &#039;&#039;Nota&#039;&#039; indica a nota final (são contabilizados os 10 melhores exercícios)&lt;br /&gt;
* &#039;&#039;Média&#039;&#039; indica a média dos exercícios apresentados (são contabilizados todos os exercícios para a média: é meramente indicativa e não é usada na avaliação)&lt;br /&gt;
&lt;br /&gt;
As classificações possíveis para cada exercício são:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.00&amp;lt;/font&amp;gt; - ignorância (quase) completa da matéria em avaliação&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.25&amp;lt;/font&amp;gt; - erros graves ou solução muito incompleta ou inadequada&lt;br /&gt;
* 0.50 - erros importantes ou solução incompleta&lt;br /&gt;
* 0.75 - erros menos graves ou solução quase completa&lt;br /&gt;
* &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;1.00&amp;lt;/font&amp;gt; - solução completa&lt;br /&gt;
&lt;br /&gt;
Obter classificações abaixo de 0.75 deve constituir motivo de preocupação, especialmente nos casos 0 e 0.25, sendo os alunos fortemente encorajados a contactar o responsável pela disciplina para consulta dos exercícios em causa.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_UML&amp;diff=17907</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: UML</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_UML&amp;diff=17907"/>
		<updated>2026-08-26T07:18:30Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega inicial é obrigatória&#039;&#039;&#039; e vale 3 valores em 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.}}&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Os resultados da avaliação dos diagramas UML podem ser revistos até à data da entrega intermédia do projecto.&lt;br /&gt;
&lt;br /&gt;
Aconselha-se celeridade no processo de revisão, pois algumas questões têm impacto na qualidade do código.&lt;br /&gt;
&lt;br /&gt;
As aulas teóricas podem ser utilizadas para esclarecer dúvidas sobre as anotações na pauta.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (coluna laranja). As colunas sombreadas indicam o grau de completude dos diagramas correspondentes a cada caso (0 indica diagrama em falta, 0.25 indica diagrama inadequado para o problema, 1 indica diagrama adequado para o problema).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot; (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação dos testes automáticos&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
Ver avaliação automática no GitLab (RNL): https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação das anotações&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
&#039;&#039;&#039;Conceitos:&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Herança:&#039;&#039;&#039;&lt;br /&gt;
* bind - problemas de representação de especializações de classes/interfaces genéricas&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Associações:&#039;&#039;&#039;&lt;br /&gt;
* assoc - associações em falta ou em excesso&lt;br /&gt;
* mult - multiplicidades erradas&lt;br /&gt;
* deps - uso incorrecto de dependências (deviam ser outra relação)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Atributos:&#039;&#039;&#039;&lt;br /&gt;
* app - atributos errados na app&lt;br /&gt;
* reps - atributos repetidos em classes hierarquicamente relacionadas (ou não colocados em superclasse)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Interface (métodos):&#039;&#039;&#039;&lt;br /&gt;
* core - interfaces do core incompletas&lt;br /&gt;
* (core) - interfaces do core com problemas potenciais&lt;br /&gt;
* manager - interface do manager com problemas&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Problemas:&#039;&#039;&#039;&lt;br /&gt;
* notation - erros de desenho de UML (herança)&lt;br /&gt;
* nomenc - erros de nomenclatura (maus nomes para classes)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_UML&amp;diff=17906</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: UML</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_UML&amp;diff=17906"/>
		<updated>2026-08-26T07:18:05Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega inicial é obrigatória&#039;&#039;&#039; e vale 3 valores em 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Os resultados da avaliação dos diagramas UML podem ser revistos até à data da entrega intermédia do projecto.&lt;br /&gt;
&lt;br /&gt;
Aconselha-se celeridade no processo de revisão, pois algumas questões têm impacto na qualidade do código.&lt;br /&gt;
&lt;br /&gt;
As aulas teóricas podem ser utilizadas para esclarecer dúvidas sobre as anotações na pauta.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (coluna laranja). As colunas sombreadas indicam o grau de completude dos diagramas correspondentes a cada caso (0 indica diagrama em falta, 0.25 indica diagrama inadequado para o problema, 1 indica diagrama adequado para o problema).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot; (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação dos testes automáticos&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
Ver avaliação automática no GitLab (RNL): https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação das anotações&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
&#039;&#039;&#039;Conceitos:&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Herança:&#039;&#039;&#039;&lt;br /&gt;
* bind - problemas de representação de especializações de classes/interfaces genéricas&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Associações:&#039;&#039;&#039;&lt;br /&gt;
* assoc - associações em falta ou em excesso&lt;br /&gt;
* mult - multiplicidades erradas&lt;br /&gt;
* deps - uso incorrecto de dependências (deviam ser outra relação)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Atributos:&#039;&#039;&#039;&lt;br /&gt;
* app - atributos errados na app&lt;br /&gt;
* reps - atributos repetidos em classes hierarquicamente relacionadas (ou não colocados em superclasse)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Interface (métodos):&#039;&#039;&#039;&lt;br /&gt;
* core - interfaces do core incompletas&lt;br /&gt;
* (core) - interfaces do core com problemas potenciais&lt;br /&gt;
* manager - interface do manager com problemas&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Problemas:&#039;&#039;&#039;&lt;br /&gt;
* notation - erros de desenho de UML (herança)&lt;br /&gt;
* nomenc - erros de nomenclatura (maus nomes para classes)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17905</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global do Projecto</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17905"/>
		<updated>2026-08-26T07:17:13Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O projecto é obrigatório. O teste prático é obrigatório.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Esta pauta corresponde ao projecto de época normal.}}&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda da Pauta Global do Projecto ==&lt;br /&gt;
&lt;br /&gt;
Componentes de avaliação:&lt;br /&gt;
&lt;br /&gt;
* PRJ - nota final do projecto&lt;br /&gt;
* PU - nota da entrega do diagrama UML&lt;br /&gt;
* PI- nota da entrega intermédia&lt;br /&gt;
* PF- nota da entrega final&lt;br /&gt;
* TP - nota do teste prático&lt;br /&gt;
&lt;br /&gt;
A nota do teste prático condiciona a distância ao mínimo entre as notas do teste prático e a do projecto: desde um mínimo de 12.5% de acréscimo à menor das duas (abaixo de 7.5 valores no TP), até um máximo de 25% (para 20 valores no TP). O acréscimo é linear entre 7.5 e 20.&lt;br /&gt;
&lt;br /&gt;
Ou seja:&lt;br /&gt;
&lt;br /&gt;
* PRJ = min(PU+PI+PF, TP) + | TP - PU - PI - PF | * max(12.5, TP+5) / 100&lt;br /&gt;
&lt;br /&gt;
Condições necessárias para aprovação à disciplina (necessárias todas):&lt;br /&gt;
&lt;br /&gt;
* PRJ &amp;gt;= 9.5 (sem arredondamento)&lt;br /&gt;
* PRJ != NA &lt;br /&gt;
* TP &amp;gt; 0&lt;br /&gt;
* TP != NA&lt;br /&gt;
&lt;br /&gt;
Linhas com números sombreados correspondem a alunos excluídos da avaliação em Época Normal, por não terem realizado componentes obrigatórias do projecto ou não terem comparecido ao teste prático.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17904</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global do Projecto</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17904"/>
		<updated>2026-08-26T07:16:32Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
Esta pauta corresponde ao projecto de época normal.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O projecto é obrigatório. O teste prático é obrigatório.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda da Pauta Global do Projecto ==&lt;br /&gt;
&lt;br /&gt;
Componentes de avaliação:&lt;br /&gt;
&lt;br /&gt;
* PRJ - nota final do projecto&lt;br /&gt;
* PU - nota da entrega do diagrama UML&lt;br /&gt;
* PI- nota da entrega intermédia&lt;br /&gt;
* PF- nota da entrega final&lt;br /&gt;
* TP - nota do teste prático&lt;br /&gt;
&lt;br /&gt;
A nota do teste prático condiciona a distância ao mínimo entre as notas do teste prático e a do projecto: desde um mínimo de 12.5% de acréscimo à menor das duas (abaixo de 7.5 valores no TP), até um máximo de 25% (para 20 valores no TP). O acréscimo é linear entre 7.5 e 20.&lt;br /&gt;
&lt;br /&gt;
Ou seja:&lt;br /&gt;
&lt;br /&gt;
* PRJ = min(PU+PI+PF, TP) + | TP - PU - PI - PF | * max(12.5, TP+5) / 100&lt;br /&gt;
&lt;br /&gt;
Condições necessárias para aprovação à disciplina (necessárias todas):&lt;br /&gt;
&lt;br /&gt;
* PRJ &amp;gt;= 9.5 (sem arredondamento)&lt;br /&gt;
* PRJ != NA &lt;br /&gt;
* TP &amp;gt; 0&lt;br /&gt;
* TP != NA&lt;br /&gt;
&lt;br /&gt;
Linhas com números sombreados correspondem a alunos excluídos da avaliação em Época Normal, por não terem realizado componentes obrigatórias do projecto ou não terem comparecido ao teste prático.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17903</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global do Projecto</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17903"/>
		<updated>2026-08-26T07:15:31Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Prazo de Revisão */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O projecto é obrigatório. O teste prático é obrigatório.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda da Pauta Global do Projecto ==&lt;br /&gt;
&lt;br /&gt;
Componentes de avaliação:&lt;br /&gt;
&lt;br /&gt;
* PRJ - nota final do projecto&lt;br /&gt;
* PU - nota da entrega do diagrama UML&lt;br /&gt;
* PI- nota da entrega intermédia&lt;br /&gt;
* PF- nota da entrega final&lt;br /&gt;
* TP - nota do teste prático&lt;br /&gt;
&lt;br /&gt;
A nota do teste prático condiciona a distância ao mínimo entre as notas do teste prático e a do projecto: desde um mínimo de 12.5% de acréscimo à menor das duas (abaixo de 7.5 valores no TP), até um máximo de 25% (para 20 valores no TP). O acréscimo é linear entre 7.5 e 20.&lt;br /&gt;
&lt;br /&gt;
Ou seja:&lt;br /&gt;
&lt;br /&gt;
* PRJ = min(PU+PI+PF, TP) + | TP - PU - PI - PF | * max(12.5, TP+5) / 100&lt;br /&gt;
&lt;br /&gt;
Condições necessárias para aprovação à disciplina (necessárias todas):&lt;br /&gt;
&lt;br /&gt;
* PRJ &amp;gt;= 9.5 (sem arredondamento)&lt;br /&gt;
* PRJ != NA &lt;br /&gt;
* TP &amp;gt; 0&lt;br /&gt;
* TP != NA&lt;br /&gt;
&lt;br /&gt;
Linhas com números sombreados correspondem a alunos excluídos da avaliação em Época Normal, por não terem realizado componentes obrigatórias do projecto ou não terem comparecido ao teste prático.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17902</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global do Projecto</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_do_Projecto&amp;diff=17902"/>
		<updated>2026-08-26T07:15:14Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;{{PRJPOAvisosEN20262027}} {{PRJPOMandatory20262027}} __NOTOC__ &amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039; &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;  &amp;#039;&amp;#039;&amp;#039;O projecto é obrigatório. O teste prático é obrigatório.&amp;#039;&amp;#039;&amp;#039;  &amp;#039;&amp;#039;&amp;#039;Projectos que não estejam nas condições indicadas nos critérios de avaliação não são considerados, conduzindo a rep...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O projecto é obrigatório. O teste prático é obrigatório.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda da Pauta Global do Projecto ==&lt;br /&gt;
&lt;br /&gt;
Componentes de avaliação:&lt;br /&gt;
&lt;br /&gt;
* PRJ - nota final do projecto&lt;br /&gt;
* PU - nota da entrega do diagrama UML&lt;br /&gt;
* PI- nota da entrega intermédia&lt;br /&gt;
* PF- nota da entrega final&lt;br /&gt;
* TP - nota do teste prático&lt;br /&gt;
&lt;br /&gt;
A nota do teste prático condiciona a distância ao mínimo entre as notas do teste prático e a do projecto: desde um mínimo de 12.5% de acréscimo à menor das duas (abaixo de 7.5 valores no TP), até um máximo de 25% (para 20 valores no TP). O acréscimo é linear entre 7.5 e 20.&lt;br /&gt;
&lt;br /&gt;
Ou seja:&lt;br /&gt;
&lt;br /&gt;
* PRJ = min(PU+PI+PF, TP) + | TP - PU - PI - PF | * max(12.5, TP+5) / 100&lt;br /&gt;
&lt;br /&gt;
Condições necessárias para aprovação à disciplina (necessárias todas):&lt;br /&gt;
&lt;br /&gt;
* PRJ &amp;gt;= 9.5 (sem arredondamento)&lt;br /&gt;
* PRJ != NA &lt;br /&gt;
* TP &amp;gt; 0&lt;br /&gt;
* TP != NA&lt;br /&gt;
&lt;br /&gt;
Linhas com números sombreados correspondem a alunos excluídos da avaliação em Época Normal, por não terem realizado componentes obrigatórias do projecto ou não terem comparecido ao teste prático.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Final&amp;diff=17901</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Final</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Final&amp;diff=17901"/>
		<updated>2026-08-26T07:13:25Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;{{PRJPOAvisosEN20262027}} {{PRJPOMandatory20262027}} __NOTOC__ &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039;--&amp;gt; &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039;--&amp;gt;  &amp;#039;&amp;#039;&amp;#039;A entrega final é obrigatória&amp;#039;&amp;#039;&amp;#039; e vale 11 valores em 20 (5.5 valores para a avaliação automática).&amp;#039;&amp;#039;&amp;#039;  &amp;#039;&amp;#039;&amp;#039;Projectos que não estejam nas condições indicadas nos Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de a...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega final é obrigatória&#039;&#039;&#039; e vale 11 valores em 20 (5.5 valores para a avaliação automática).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quaisquer dúvidas, relativas a esta informação, devem ser enviadas ao responsável pela disciplina.&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente no Fénix.&lt;br /&gt;
&lt;br /&gt;
==Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (colunas laranja).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot; (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
&lt;br /&gt;
O significado das anotações é semelhante ao das utilizadas na pauta da entrega intermédia.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Interm%C3%A9dia&amp;diff=17900</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Intermédia</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_Entrega_Interm%C3%A9dia&amp;diff=17900"/>
		<updated>2026-08-26T07:11:45Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;{{PRJPOAvisosEN20262027}} {{PRJPOMandatory20262027}} __NOTOC__  &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039;--&amp;gt; &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039;--&amp;gt;  &amp;#039;&amp;#039;&amp;#039;A entrega intermédia é obrigatória&amp;#039;&amp;#039;&amp;#039; e vale 6 valores em 20.  &amp;#039;&amp;#039;&amp;#039;Projectos que não estejam nas condições indicadas nos critérios de avaliação não são considerados, condu...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;PAUTA EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega intermédia é obrigatória&#039;&#039;&#039; e vale 6 valores em 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Os alunos devem compreender/verificar/corrigir os problemas reportados.&lt;br /&gt;
&lt;br /&gt;
Quaisquer dúvidas, relativas a esta informação, devem ser enviadas ao responsável pela disciplina.&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Esta pauta está em revisão até à data da entrega final do projecto.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (colunas laranja).&lt;br /&gt;
&lt;br /&gt;
A coluna &amp;quot;Auto&amp;quot; indica a percentagem de teste automáticos certos e vale 2.5 valores.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot;  (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação dos testes automáticos&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
Ver avaliação automática no GitLab (RNL): https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
&lt;br /&gt;
São consideradas irrelevantes diferenças que consistam apenas em quantidade de espaços brancos (não ter espaços é considerada uma diferença).&lt;br /&gt;
&amp;lt;!--* O uso da função &#039;&#039;&#039;fileNotFound&#039;&#039;&#039; com e sem argumentos é considerado igual.--&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação das anotações&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
&#039;&#039;&#039;Atributos não públicos:&#039;&#039;&#039;&lt;br /&gt;
* public - atributos públicos&lt;br /&gt;
* protected - atributos protected (potencialmente desnecessária a qualificação)&lt;br /&gt;
* package - atributos sem qualificação de acesso&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Atributos e métodos não “static”&#039;&#039;&#039;&lt;br /&gt;
* (const) - contantes&lt;br /&gt;
* (comparator) - constantes (comparador)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Serialização&#039;&#039;&#039;&lt;br /&gt;
* ois - problemas na utilização de ObjectInputStream&lt;br /&gt;
* oos - problemas na utilização de ObjectOutputStream&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Utilização de estruturas de dados correctas&#039;&#039;&#039;&lt;br /&gt;
* lists - utilização de listas onde se justifica a utilização de mapas&lt;br /&gt;
* generics - falta de parâmetro em tipo paramétrico&lt;br /&gt;
* Object - utilização directa da classe Object (sem ser para satisfazer um requisito de Java)&lt;br /&gt;
* Exception - utilização directa da classe Exception (processamento indiscriminado de excepções)&lt;br /&gt;
* instanceof - uso de instanceof (não é justificável numa solução de boa qualidade) (idem para getClass)&lt;br /&gt;
* System.* - problemas na utilização de canais de I/O&lt;br /&gt;
* app attrs/fields - definição de atributos em classes da app: deveriam ser variáveis locais a métodos ou simplesmente não existir&lt;br /&gt;
* ArrayList/TreeMap/HashSet/etc. - uso de tipos concretos em declarações de atributos (usar List/Map/Set/etc.)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Separação app/core&#039;&#039;&#039;&lt;br /&gt;
* serialization - uso de primitivas de serialização na app&lt;br /&gt;
* options - não uso de processo de escolha de opções&lt;br /&gt;
* reader - criação do leitor do ficheiro indicado pela propriedade &amp;quot;import&amp;quot; na app&lt;br /&gt;
* core exposed - exposição desnecessária de estruturas/abstracções do core&lt;br /&gt;
* except - não tratamento de excepções na app&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Qualidade do projecto (apreciação global)&#039;&#039;&#039;&lt;br /&gt;
* instanceof - uso de instanceof (não é justificável numa solução de boa qualidade) (idem para getClass)&lt;br /&gt;
* Object - utilização directa da classe Object (sem ser para satisfazer um requisito de Java)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Javadoc&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Seguir regras codificação&#039;&#039;&#039;&lt;br /&gt;
* class - erros de nomenclatura (maus nomes para classes)&lt;br /&gt;
* vars - erros de nomenclatura (maus nomes para variáveis)&lt;br /&gt;
* funcs - erros de nomenclatura (maus nomes para funções)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Lixo no Repositório&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_UML&amp;diff=17899</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: UML</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_do_Projecto:_UML&amp;diff=17899"/>
		<updated>2026-08-26T07:09:33Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;{{PRJPOAvisosEN20262027}} {{PRJPOMandatory20262027}} __NOTOC__  &amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039; &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039;--&amp;gt;  &amp;#039;&amp;#039;&amp;#039;A entrega inicial é obrigatória&amp;#039;&amp;#039;&amp;#039; e vale 3 valores em 20.  &amp;#039;&amp;#039;&amp;#039;Projectos que não estejam nas condições indicadas nos critérios de avaliação não são considerados, conduzindo a reprovaç...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
&amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;&#039;&#039;&#039;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;A entrega inicial é obrigatória&#039;&#039;&#039; e vale 3 valores em 20.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Projectos que não estejam nas condições indicadas nos [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|critérios de avaliação]] não são considerados, conduzindo a reprovação. Não existem excepções.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Quaisquer dúvidas relativas a esta informação devem ser enviadas ao responsável pela disciplina.&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
Os resultados da avaliação dos diagramas UML podem ser revistos até à data da entrega intermédia do projecto.&lt;br /&gt;
&lt;br /&gt;
Aconselha-se celeridade no processo de revisão, pois algumas questões têm impacto na qualidade do código.&lt;br /&gt;
&lt;br /&gt;
As aulas teóricas podem ser utilizadas para esclarecer dúvidas sobre as anotações na pauta.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Existem factores aditivos positivos (colunas a verde) e negativos (coluna laranja). As colunas sombreadas indicam o grau de completude dos diagramas correspondentes a cada caso (0 indica diagrama em falta, 0.25 indica diagrama inadequado para o problema, 1 indica diagrama adequado para o problema).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;NA&#039;&#039;&#039; na coluna &amp;quot;Nota&amp;quot; indica &amp;quot;não avaliado&amp;quot; (grupo excluído da avaliação da disciplina em época normal no lectivo actual).&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação dos testes automáticos&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
Ver avaliação automática no GitLab (RNL): https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #f7f8ff;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #d7d8ed;&amp;quot; | &#039;&#039;&#039;Explicação das anotações&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 1px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
&#039;&#039;&#039;Conceitos:&#039;&#039;&#039;&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Herança:&#039;&#039;&#039;&lt;br /&gt;
* bind - problemas de representação de especializações de classes/interfaces genéricas&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Associações:&#039;&#039;&#039;&lt;br /&gt;
* assoc - associações em falta ou em excesso&lt;br /&gt;
* mult - multiplicidades erradas&lt;br /&gt;
* deps - uso incorrecto de dependências (deviam ser outra relação)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Atributos:&#039;&#039;&#039;&lt;br /&gt;
* app - atributos errados na app&lt;br /&gt;
* reps - atributos repetidos em classes hierarquicamente relacionadas (ou não colocados em superclasse)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Interface (métodos):&#039;&#039;&#039;&lt;br /&gt;
* core - interfaces do core incompletas&lt;br /&gt;
* (core) - interfaces do core com problemas potenciais&lt;br /&gt;
* manager - interface do manager com problemas&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
&#039;&#039;&#039;Problemas:&#039;&#039;&#039;&lt;br /&gt;
* notation - erros de desenho de UML (herança)&lt;br /&gt;
* nomenc - erros de nomenclatura (maus nomes para classes)&lt;br /&gt;
* [outras anotações] - consultar professor responsável (horário de dúvidas)&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[category:Pautas de PO - Época Normal]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_da_Disciplina&amp;diff=17898</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global da Disciplina</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_da_Disciplina&amp;diff=17898"/>
		<updated>2026-08-26T07:04:24Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Pauta Global */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
== Pauta Global ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Época Normal:&#039;&#039;&#039; ver prazo de revisão nas páginas correspondentes às provas em curso. &amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt; &#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Época Especial:&#039;&#039;&#039; provas a realizar em Julho de 2027 (ver datas na página da disciplina: Fénix) &amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Não existem arredondamentos (excepto na coluna &#039;&#039;&#039;FINAL&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Condições de aprovação: &#039;&#039;&#039;NOTA&#039;&#039;&#039;, &#039;&#039;&#039;EXR&#039;&#039;&#039;, &#039;&#039;&#039;PRJ&#039;&#039;&#039;, &#039;&#039;&#039;EE&#039;&#039;&#039; têm de ser iguais ou superiores a 9.5.&lt;br /&gt;
&lt;br /&gt;
Legenda:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FINAL&#039;&#039;&#039; - resultado da avaliação (será lançado na secretaria)&lt;br /&gt;
* &#039;&#039;&#039;NOTA&#039;&#039;&#039; - resultado numérico da avaliação (quando aplicável) &lt;br /&gt;
* &#039;&#039;&#039;EXR&#039;&#039;&#039; - nota final dos exercícios de programação &lt;br /&gt;
* &#039;&#039;&#039;PRJ&#039;&#039;&#039; - nota final do projecto (inclui nota do teste prático) &lt;br /&gt;
* &#039;&#039;&#039;EE&#039;&#039;&#039; - época especial (6 exercícios de programação) &lt;br /&gt;
&lt;br /&gt;
As notações especiais têm o seguinte significado:&lt;br /&gt;
* &#039;&#039;&#039;NA&#039;&#039;&#039; - &amp;quot;não avaliado&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;RE&#039;&#039;&#039; - &amp;quot;reprovado&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17897</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta das Aulas Práticas</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17897"/>
		<updated>2026-08-26T07:03:56Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Legenda */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;!--&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&#039;&#039;&#039;PAUTA FECHADA&#039;&#039;&#039;&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;EM ACTUALIZAÇÃO&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A avaliação nestas aulas é obrigatória e não é repetível fora da semana em que cada exercício é realizado.&amp;lt;br/&amp;gt;&lt;br /&gt;
Não se avaliam alunos fora do turno de inscrição.&lt;br /&gt;
&lt;br /&gt;
Alunos que compareçam atrasados a estas aulas não são avaliados.&amp;lt;br/&amp;gt;&lt;br /&gt;
É admitido um limite máximo de 20 minutos para entrada em cada aula, após a hora definida para a aula (i.e., já contabilizando os 10 minutos do início).&lt;br /&gt;
&lt;br /&gt;
Não são considerados casos especiais na avaliação das aulas práticas. Alunos que considerem ter direito a tratamento especial e que não consigam comparecer com aproveitamento nestas aulas poderão requerer avaliação em época especial.&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazos de revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente a cada semana no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
As colunas agregadas da pauta têm o seguinte significado:&lt;br /&gt;
* &#039;&#039;Nota&#039;&#039; indica a nota final (são contabilizados os 10 melhores exercícios)&lt;br /&gt;
* &#039;&#039;Média&#039;&#039; indica a média dos exercícios apresentados (são contabilizados todos os exercícios para a média: é meramente indicativa e não é usada na avaliação)&lt;br /&gt;
&lt;br /&gt;
As classificações possíveis para cada exercício são:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.00&amp;lt;/font&amp;gt; - ignorância (quase) completa da matéria em avaliação&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.25&amp;lt;/font&amp;gt; - erros graves ou solução muito incompleta ou inadequada&lt;br /&gt;
* 0.50 - erros importantes ou solução incompleta&lt;br /&gt;
* 0.75 - erros menos graves ou solução quase completa&lt;br /&gt;
* &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;1.00&amp;lt;/font&amp;gt; - solução completa&lt;br /&gt;
&lt;br /&gt;
Obter classificações abaixo de 0.75 deve constituir motivo de preocupação, especialmente nos casos 0 e 0.25, sendo os alunos fortemente encorajados a contactar o responsável pela disciplina para consulta dos exercícios em causa.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17896</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta das Aulas Práticas</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17896"/>
		<updated>2026-08-26T07:03:16Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
&amp;lt;!--&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&#039;&#039;&#039;PAUTA FECHADA&#039;&#039;&#039;&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;EM ACTUALIZAÇÃO&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A avaliação nestas aulas é obrigatória e não é repetível fora da semana em que cada exercício é realizado.&amp;lt;br/&amp;gt;&lt;br /&gt;
Não se avaliam alunos fora do turno de inscrição.&lt;br /&gt;
&lt;br /&gt;
Alunos que compareçam atrasados a estas aulas não são avaliados.&amp;lt;br/&amp;gt;&lt;br /&gt;
É admitido um limite máximo de 20 minutos para entrada em cada aula, após a hora definida para a aula (i.e., já contabilizando os 10 minutos do início).&lt;br /&gt;
&lt;br /&gt;
Não são considerados casos especiais na avaliação das aulas práticas. Alunos que considerem ter direito a tratamento especial e que não consigam comparecer com aproveitamento nestas aulas poderão requerer avaliação em época especial.&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazos de revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente a cada semana no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
* &#039;&#039;Nota&#039;&#039; indica a nota final (são contabilizados os 10 melhores exercícios)&lt;br /&gt;
* &#039;&#039;Média&#039;&#039; indica a média dos exercícios apresentados (são contabilizados todos os exercícios para a média: é meramente indicativa e não é usada na avaliação)&lt;br /&gt;
&lt;br /&gt;
As classificações possíveis para cada exercício são:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.00&amp;lt;/font&amp;gt; - ignorância (quase) completa da matéria em avaliação&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.25&amp;lt;/font&amp;gt; - erros graves ou solução muito incompleta ou inadequada&lt;br /&gt;
* 0.50 - erros importantes ou solução incompleta&lt;br /&gt;
* 0.75 - erros menos graves ou solução quase completa&lt;br /&gt;
* &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;1.00&amp;lt;/font&amp;gt; - solução completa&lt;br /&gt;
&lt;br /&gt;
Obter classificações abaixo de 0.75 deve constituir motivo de preocupação, especialmente nos casos 0 e 0.25, sendo os alunos fortemente encorajados a contactar o responsável pela disciplina para consulta dos exercícios em causa.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17895</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta das Aulas Práticas</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_das_Aulas_Pr%C3%A1ticas&amp;diff=17895"/>
		<updated>2026-08-26T07:03:01Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;{{TOCright}} &amp;lt;!--&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;PAUTA FECHADA&amp;#039;&amp;#039;&amp;#039;&amp;lt;/font&amp;gt;--&amp;gt; &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&amp;#039;&amp;#039;&amp;#039;EM ACTUALIZAÇÃO&amp;#039;&amp;#039;&amp;#039;&amp;lt;/font&amp;gt;  A avaliação nestas aulas é obrigatória e não é repetível fora da semana em que cada exercício é realizado.&amp;lt;br/&amp;gt; Não se avaliam alunos fora do turno de inscrição.  Alunos que compareçam atrasados a estas aulas não são avaliados.&amp;lt;br/&amp;gt; É admitido um limite máximo de 20 minutos para entrada em cada aula, após a hora definida para a aula (i.e....&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOCright}}&lt;br /&gt;
&amp;lt;!--&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&#039;&#039;&#039;PAUTA FECHADA&#039;&#039;&#039;&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;EM ACTUALIZAÇÃO&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
A avaliação nestas aulas é obrigatória e não é repetível fora da semana em que cada exercício é realizado.&amp;lt;br/&amp;gt;&lt;br /&gt;
Não se avaliam alunos fora do turno de inscrição.&lt;br /&gt;
&lt;br /&gt;
Alunos que compareçam atrasados a estas aulas não são avaliados.&amp;lt;br/&amp;gt;&lt;br /&gt;
É admitido um limite máximo de 20 minutos para entrada em cada aula, após a hora definida para a aula (i.e., já contabilizando os 10 minutos do início).&lt;br /&gt;
&lt;br /&gt;
Não são considerados casos especiais na avaliação das aulas práticas. Alunos que considerem ter direito a tratamento especial e que não consigam comparecer com aproveitamento nestas aulas poderão requerer avaliação em época especial.&lt;br /&gt;
&lt;br /&gt;
== Pauta ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas (Fénix)&lt;br /&gt;
&lt;br /&gt;
== Prazos de revisão ==&lt;br /&gt;
&lt;br /&gt;
Ver anúncio correspondente a cada semana no Fénix.&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
* &#039;&#039;Nota&#039;&#039; indica a nota final (são contabilizados os 10 melhores exercícios)&lt;br /&gt;
* &#039;&#039;Média&#039;&#039; indica a média dos exercícios apresentados (são contabilizados todos os exercícios para a média: é meramente indicativa e não é usada na avaliação)&lt;br /&gt;
&lt;br /&gt;
As classificações possíveis para cada exercício são:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.00&amp;lt;/font&amp;gt; - ignorância (quase) completa da matéria em avaliação&lt;br /&gt;
* &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;0.25&amp;lt;/font&amp;gt; - erros graves ou solução muito incompleta ou inadequada&lt;br /&gt;
* 0.50 - erros importantes ou solução incompleta&lt;br /&gt;
* 0.75 - erros menos graves ou solução quase completa&lt;br /&gt;
* &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;1.00&amp;lt;/font&amp;gt; - solução completa&lt;br /&gt;
&lt;br /&gt;
Obter classificações abaixo de 0.75 deve constituir motivo de preocupação, especialmente nos casos 0 e 0.25, sendo os alunos fortemente encorajados a contactar o responsável pela disciplina para consulta dos exercícios em causa.&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_da_Disciplina&amp;diff=17894</id>
		<title>Programação com Objectos/Pautas 2026-2027/Pauta Global da Disciplina</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027/Pauta_Global_da_Disciplina&amp;diff=17894"/>
		<updated>2026-08-26T07:01:20Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;__NOTOC__ == Pauta Global ==  Aqui: https://bit.ly/po26-pautas  == Prazo de Revisão ==  * &amp;#039;&amp;#039;&amp;#039;Época Normal:&amp;#039;&amp;#039;&amp;#039; ver prazo de revisão nas páginas correspondentes às provas em curso. &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt; &amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&amp;#039;&amp;#039;&amp;#039; * &amp;#039;&amp;#039;&amp;#039;Época Especial:&amp;#039;&amp;#039;&amp;#039; provas a realizar em Julho de 2027 (ver datas na página da disciplina: Fénix) &amp;lt;!--&amp;#039;&amp;#039;&amp;#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;  == Legenda ==  Não existem arredo...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
== Pauta Global ==&lt;br /&gt;
&lt;br /&gt;
Aqui: https://bit.ly/po26-pautas&lt;br /&gt;
&lt;br /&gt;
== Prazo de Revisão ==&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;Época Normal:&#039;&#039;&#039; ver prazo de revisão nas páginas correspondentes às provas em curso. &amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt; &#039;&#039;&#039;&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;EM ACTUALIZAÇÃO&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;Época Especial:&#039;&#039;&#039; provas a realizar em Julho de 2027 (ver datas na página da disciplina: Fénix) &amp;lt;!--&#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;PAUTA FECHADA&amp;lt;/font&amp;gt;--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Legenda ==&lt;br /&gt;
&lt;br /&gt;
Não existem arredondamentos (excepto na coluna &#039;&#039;&#039;FINAL&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Condições de aprovação: &#039;&#039;&#039;NOTA&#039;&#039;&#039;, &#039;&#039;&#039;EXR&#039;&#039;&#039;, &#039;&#039;&#039;PRJ&#039;&#039;&#039;, &#039;&#039;&#039;EE&#039;&#039;&#039; têm de ser iguais ou superiores a 9.5.&lt;br /&gt;
&lt;br /&gt;
Legenda:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;FINAL&#039;&#039;&#039; - resultado da avaliação (será lançado na secretaria)&lt;br /&gt;
* &#039;&#039;&#039;NOTA&#039;&#039;&#039; - resultado numérico da avaliação (quando aplicável) &lt;br /&gt;
* &#039;&#039;&#039;EXR&#039;&#039;&#039; - nota final dos exercícios de programação &lt;br /&gt;
* &#039;&#039;&#039;PRJ&#039;&#039;&#039; - nota final do projecto (inclui nota do teste prático) &lt;br /&gt;
* &#039;&#039;&#039;EE&#039;&#039;&#039; - época especial (6 exercícios de programação) &lt;br /&gt;
&lt;br /&gt;
As notações especiais têm o seguinte significado:&lt;br /&gt;
* &#039;&#039;&#039;NA&#039;&#039;&#039; - &amp;quot;não avaliado&amp;quot;&lt;br /&gt;
* &#039;&#039;&#039;RE&#039;&#039;&#039; - &amp;quot;reprovado&amp;quot;&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027&amp;diff=17893</id>
		<title>Programação com Objectos/Pautas 2026-2027</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Pautas_2026-2027&amp;diff=17893"/>
		<updated>2026-08-26T06:59:21Z</updated>

		<summary type="html">&lt;p&gt;Root: Created page with &amp;quot;__NOTOC__ Além dos resultados de avaliação, as páginas das pautas contêm também os critérios de avaliação e aprovação. * {{PautaAberta}} indica avaliação em curso * {{PautaFechada}} indica avaliação terminada (classificações definitivas) * {{ProvaPorRealizar}} indica prova prevista  == Pauta Global da Disciplina ==  * {{PautaAberta}} Pauta Global da Disciplina  == Pauta das Aulas...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__NOTOC__&lt;br /&gt;
Além dos resultados de avaliação, as páginas das pautas contêm também os critérios de avaliação e aprovação.&lt;br /&gt;
* {{PautaAberta}} indica avaliação em curso&lt;br /&gt;
* {{PautaFechada}} indica avaliação terminada (classificações definitivas)&lt;br /&gt;
* {{ProvaPorRealizar}} indica prova prevista&lt;br /&gt;
&lt;br /&gt;
== Pauta Global da Disciplina ==&lt;br /&gt;
&lt;br /&gt;
* {{PautaAberta}} [[Programação com Objectos/Pautas 2026-2027/Pauta Global da Disciplina|Pauta Global da Disciplina]]&lt;br /&gt;
&lt;br /&gt;
== Pauta das Aulas Práticas ==&lt;br /&gt;
&lt;br /&gt;
* {{PautaAberta}} [[Programação com Objectos/Pautas 2026-2027/Pauta das Aulas Práticas|Pauta das Aulas Práticas]]&lt;br /&gt;
&lt;br /&gt;
== Pautas do Projecto (época normal) ==&lt;br /&gt;
&lt;br /&gt;
* {{PautaAberta}} [[Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: UML|Pauta do Projecto: UML]]&lt;br /&gt;
* {{ProvaPorRealizar}} [[Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Intermédia|Pauta do Projecto: Entrega Intermédia]] &lt;br /&gt;
* {{ProvaPorRealizar}} [[Programação com Objectos/Pautas 2026-2027/Pauta do Projecto: Entrega Final|Pauta do Projecto: Entrega Final]]&lt;br /&gt;
* {{PautaAberta}} [[Programação com Objectos/Pautas 2026-2027/Pauta Global do Projecto|Pauta Global do Projecto]]&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Pautas de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Calend%C3%A1rio_do_Teste_Pr%C3%A1tico_(%C3%89poca_Normal)&amp;diff=17892</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Calendário do Teste Prático (Época Normal)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Calend%C3%A1rio_do_Teste_Pr%C3%A1tico_(%C3%89poca_Normal)&amp;diff=17892"/>
		<updated>2026-08-26T06:55:17Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
= Condições =&lt;br /&gt;
&lt;br /&gt;
O teste prático tem a duração de 50 minutos e é estritamente presencial.&lt;br /&gt;
&lt;br /&gt;
As datas e locais de realização do teste prático são como indicado abaixo (todos os labs são na RNL, Pav. Informática I).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;&#039;&#039;&#039;Recorda-se que a não realização do teste prático corresponde a uma classificação de 0 (zero) na componente de projecto e consequente reprovação à disciplina de Programação com Objectos no ano lectivo em curso (época normal).&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O facto de um aluno aparecer na lista do teste prático não implica que tenha possibilidade de aprovação implícita à disciplina: as outras condições de aprovação continuam em vigor.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Alunos que realizem o projecto em grupos de 2 alunos têm de fazer o teste prático à mesma hora (incluindo o &amp;quot;early bird&amp;quot;). Se um dos alunos se apresentar isolado, o outro elemento está implicitamente reprovado.&lt;br /&gt;
&lt;br /&gt;
Alunos que não realizem a entrega final não serão admitidos ao teste prático.&lt;br /&gt;
&lt;br /&gt;
Alunos não apresentados, e que achem que deveriam estar incluídos, devem contactar o responsável pela disciplina.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;É necessário e da responsabilidade dos alunos activar atempadamente (não pode ser no próprio dia) os serviços de Shell e AFS, para a realização do teste prático, tal como para a realização do projecto. A incapacidade de usar o PC do laboratório implica não avaliação e consequente exclusão da avaliação da disciplina. A activação não funciona no próprio dia.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Teste Tipo =&lt;br /&gt;
Este teste tipo está previsto ser realizado sobre a aplicação bancária.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;QUESTÃO AUTÓNOMA -- ELIMINATÓRIA&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
0.  Compile e execute o programa contido em &#039;&#039;&#039;Simple.java&#039;&#039;&#039; (o ficheiro está localizado na directoria &#039;&#039;&#039;work&#039;&#039;&#039;). Não altere o ficheiro. Em caso de dúvidas, contacte o docente.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;QUESTÕES A RESOLVER SOBRE O PROJECTO&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
1. (5 valores) Complete o comando que permite mudar o nome de um titular. O comando deve primeiro pedir o novo nome do titular.&lt;br /&gt;
&lt;br /&gt;
2. (7 valores) Acrescente uma nova opção ao menu de gestão de contas (bankaccount) que permita mostrar a conta (current account) com maior saldo.&lt;br /&gt;
&lt;br /&gt;
3. (8 valores) Acrescente ao programa o conceito de gestor de conta: um gestor pode gerir várias contas, partilha os atributos do titular da conta, mas não pode ser titular de contas. Cada conta tem apenas um gestor.&lt;br /&gt;
&lt;br /&gt;
= Calendário =&lt;br /&gt;
(a definir)&lt;br /&gt;
&lt;br /&gt;
= Realizados =&lt;br /&gt;
(a definir)&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos&amp;diff=17891</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos&amp;diff=17891"/>
		<updated>2026-08-26T06:53:26Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Projecto Exemplo: Rede Social (2011) */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
== Avaliação do Projecto ==&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|Avaliação do Projecto (Época Normal)]]&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Calendário do Teste Prático (Época Normal)|Calendário do Teste Prático (Época Normal)]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Teste Prático (Época Especial)|Teste Prático (Época Especial)]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
As pautas são acompanhadas pelos critérios de avaliação. &amp;lt;!--Os critérios e condições de Época Especial são parecidos com os da Época Normal. Em particular, a componente de projecto continua obrigatória.--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Projecto: Enunciado 2017-2018 (época especial) ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2017-2018 (época especial)|Enunciado do Projecto de Época Especial]] -- Editor de Texto&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projecto: Enunciado 2026-2027 (época normal) ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027|Enunciado do Projecto 2026-2027]]&lt;br /&gt;
* Enunciados de anos anteriores: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2025-2026|2025-2026]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2024-2025|2024-2025]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2023-2024|2023-2024]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2022-2023|2022-2023]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2021-2022|2021-2022]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2020-2021|2020-2021]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2019-2020|2019-2020]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2018-2019|2018-2019]]&lt;br /&gt;
&lt;br /&gt;
== Material de Apoio e Testes ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|Repositório GIT]] - informações de localização e acesso &lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|Material de Apoio ao Desenvolvimento]]&lt;br /&gt;
* Testes automáticos: https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual|Máquina Virtual]]&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Aplicação Bancária ==&lt;br /&gt;
&lt;br /&gt;
Para auxiliar o desenvolvimento do projecto, é fornecida uma [[Comando (padrão de desenho)/Banco, Conta, Titular (aplicação bancária)|aplicação bancária]] (banco, contas, titulares, etc.), que tem a mesma estrutura. Esta estrutura tem duas partes principais: &amp;quot;core&amp;quot; (o núcleo lógico da aplicação) e &amp;quot;app&amp;quot; (a interface textual, baseada no padrão de desenho [[Comando (padrão_de_desenho)|Command]]).&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Hotel Veterinário (2024) ==&lt;br /&gt;
&lt;br /&gt;
Este projecto descreve um hotel veterinário.&lt;br /&gt;
&lt;br /&gt;
O enunciado corresponde ao ano lectivo de 2024/2025 e refere aspectos de implementação compatíveis com 2025/2026.&lt;br /&gt;
* Enunciado: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2024-2025|Hotel Veterinário]]&lt;br /&gt;
* Implementação (git snapshot): [[media:po24-hva-2025030036.tar.bz2]]&lt;br /&gt;
{{Aviso|O uso deste código deve ser feito de forma crítica, já que algumas das decisões nele tomadas podem ser alvo de descontos na avaliação do projecto.}}&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Rede Social (2011) ==&lt;br /&gt;
&lt;br /&gt;
Este projecto descreve uma rede social com funcionalidade semelhante à das redes sociais actuais: relações entre agentes, publicação de vários tipos de media, envio de mensagens, etc.&lt;br /&gt;
&lt;br /&gt;
Note-se que o enunciado corresponde ao ano lectivo de 2011/2012 e refere aspectos de implementação não disponíveis em anos seguintes. A implementação foi actualizada em 2022/2023, para ser compatível com o material de apoio dessa altura, mas não teve outras actualizações.&lt;br /&gt;
* Enunciado: [[media:social-network-201110241420.pdf]]&lt;br /&gt;
* Implementação (core): [[media:sonet-core-202111021419.tar.bz2]]&lt;br /&gt;
* Implementação (app: browser): [[media:sonet-app-browser-202111021419.tar.bz2]]&lt;br /&gt;
* Implementação (app: manager): [[media:sonet-app-manager-202111021419.tar.bz2]]&lt;br /&gt;
{{Aviso|O uso deste código deve ser feito de forma crítica, já que algumas das decisões nele tomadas podem ser alvo de descontos na avaliação do projecto.}}&lt;br /&gt;
&lt;br /&gt;
== Linguagens de Programação ==&lt;br /&gt;
&lt;br /&gt;
As seguintes linguagens são utilizadas nestas páginas:&lt;br /&gt;
&lt;br /&gt;
* [http://www.java.com/ Java] -- [https://docs.oracle.com/en/java/javase/ Java Platform, Standard Edition Documentation] (os testes automáticos usam OpenJDK 25)&lt;br /&gt;
* [http://cplusplus.com/ C++] (C++23 ou superior) -- [http://cplusplus.com/reference/ Manual de Referência para C++ (biblioteca)]; STL: [http://cplusplus.com/reference/stl/ contentores], [http://cplusplus.com/reference/algorithm/ algoritmos] &amp;lt;!--*[http://cppreference.com/ Manual de Referência para C/C++]--&amp;gt;&lt;br /&gt;
&amp;lt;!-- * [http://php.net/ PHP]: [http://www.php.net/manual/en/ manual] and [http://www.php.net/manual/en/funcref.php function reference] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]] &lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Material_de_Apoio_ao_Desenvolvimento&amp;diff=17890</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Material_de_Apoio_ao_Desenvolvimento&amp;diff=17890"/>
		<updated>2026-08-26T06:51:26Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
== Material de Apoio ==&lt;br /&gt;
&lt;br /&gt;
O projecto, escrito em Java, deve ser desenvolvido considerando os princípios de programação com objectos e os aspectos de arquitectura dos padrões de desenho aplicáveis. Alguns dos padrões estão presentes no material de apoio e condicionam parte do desenho da aplicação.&lt;br /&gt;
&lt;br /&gt;
O código presente na biblioteca de apoio ao desenvolvimento do projecto é de uso obrigatório:&lt;br /&gt;
&lt;br /&gt;
* Código de base ao desenvolvimento: [[media:po-uilib-202608310000.tar.bz2|po-uilib-202608310000.tar.bz2]] (já está instalado na máquina virtual) - [https://www.hlt.inesc-id.pt/~david/ist/docencia/po/2026/javadoc/po-uuilib javadoc]&lt;br /&gt;
* Código da lógica da aplicação e classes associadas (código esqueleto, parcialmente implementado, a completar): (&#039;&#039;&#039;erp-core&#039;&#039;&#039; via GIT)&lt;br /&gt;
* Código de interacção com o utilizador (código parcialmente implementado, a completar): (&#039;&#039;&#039;erp-app&#039;&#039;&#039; via GIT)&lt;br /&gt;
&lt;br /&gt;
{{CVSCode|O [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|repositório GIT]] já contém uma versão incompleta do projecto. Isto significa que &#039;&#039;antes&#039;&#039; de se começar a programar, o projecto deve ser obtido a partir do repositório.}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|Qualquer ficheiro do material de apoio (classes da biblioteca &#039;&#039;&#039;po-uilib&#039;&#039;&#039; ou código pré-implementado), ou com nome coincidente, será removido do projecto antes de cada teste.}}&lt;br /&gt;
&lt;br /&gt;
== Pacotes Binários e Ambiente Oficial ==&lt;br /&gt;
&lt;br /&gt;
Tanto o manterial de apoio, como a [[Comando_(padrão_de_desenho)/Banco,_Conta,_Titular_(aplicação_bancaria)|aplicação Bank]], estão disponíveis para instalação directa através do repositório (usar instalador favorito):&lt;br /&gt;
&lt;br /&gt;
* https://download.opensuse.org/repositories/home:/d4vid:/po26/&lt;br /&gt;
&lt;br /&gt;
Este repositório é para openSUSE (o ambiente de avaliação oficial), mas os JARs são compatíveis com outros sistemas.&lt;br /&gt;
Este repositório pode ser adicionado a um openSUSE Tumbleweed (por exemplo) previamente instalado através do comando&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;nowiki&amp;gt;zypper ar https://download.opensuse.org/repositories/home:/d4vid:/po26/openSUSE_Tumbleweed/ PO26&amp;lt;/nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Uma vez adicionado o repositório, os pacotes acima podem ser instalados através dos comandos (pode ser dado apenas um comando com todos os pacotes)&lt;br /&gt;
&lt;br /&gt;
 zypper install po-uilib&lt;br /&gt;
 zypper install po-bank-core po-bank-app&lt;br /&gt;
&lt;br /&gt;
{{Suggestion|Os pacotes do material de apoio estão pré-instalados na [[Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual|máquina virtual]]. Ver JARs em /usr/share/java.}}&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos&amp;diff=17889</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos&amp;diff=17889"/>
		<updated>2026-08-26T06:49:33Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Material de Apoio e Testes */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
== Avaliação do Projecto ==&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|Avaliação do Projecto (Época Normal)]]&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Calendário do Teste Prático (Época Normal)|Calendário do Teste Prático (Época Normal)]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Teste Prático (Época Especial)|Teste Prático (Época Especial)]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
As pautas são acompanhadas pelos critérios de avaliação. &amp;lt;!--Os critérios e condições de Época Especial são parecidos com os da Época Normal. Em particular, a componente de projecto continua obrigatória.--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Projecto: Enunciado 2017-2018 (época especial) ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2017-2018 (época especial)|Enunciado do Projecto de Época Especial]] -- Editor de Texto&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projecto: Enunciado 2026-2027 (época normal) ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027|Enunciado do Projecto 2026-2027]]&lt;br /&gt;
* Enunciados de anos anteriores: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2025-2026|2025-2026]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2024-2025|2024-2025]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2023-2024|2023-2024]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2022-2023|2022-2023]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2021-2022|2021-2022]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2020-2021|2020-2021]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2019-2020|2019-2020]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2018-2019|2018-2019]]&lt;br /&gt;
&lt;br /&gt;
== Material de Apoio e Testes ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|Repositório GIT]] - informações de localização e acesso &lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|Material de Apoio ao Desenvolvimento]]&lt;br /&gt;
* Testes automáticos: https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26/eval/po26&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual|Máquina Virtual]]&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Aplicação Bancária ==&lt;br /&gt;
&lt;br /&gt;
Para auxiliar o desenvolvimento do projecto, é fornecida uma [[Comando (padrão de desenho)/Banco, Conta, Titular (aplicação bancária)|aplicação bancária]] (banco, contas, titulares, etc.), que tem a mesma estrutura. Esta estrutura tem duas partes principais: &amp;quot;core&amp;quot; (o núcleo lógico da aplicação) e &amp;quot;app&amp;quot; (a interface textual, baseada no padrão de desenho [[Comando (padrão_de_desenho)|Command]]).&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Hotel Veterinário (2024) ==&lt;br /&gt;
&lt;br /&gt;
Este projecto descreve um hotel veterinário.&lt;br /&gt;
&lt;br /&gt;
O enunciado corresponde ao ano lectivo de 2024/2025 e refere aspectos de implementação compatíveis com 2025/2026.&lt;br /&gt;
* Enunciado: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2024-2025|Hotel Veterinário]]&lt;br /&gt;
* Implementação (git snapshot): [[media:po24-hva-2025030036.tar.bz2]]&lt;br /&gt;
{{Aviso|O uso deste código deve ser feito de forma crítica, já que algumas das decisões nele tomadas podem ser alvo de descontos na avaliação do projecto.}}&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Rede Social (2011) ==&lt;br /&gt;
&lt;br /&gt;
Este projecto descreve uma rede social com funcionalidade semelhante à das redes sociais actuais: relações entre agentes, publicação de vários tipos de media, envio de mensagens, etc.&lt;br /&gt;
&lt;br /&gt;
Note-se que o enunciado corresponde ao ano lectivo de 2011/2012 e refere aspectos de implementação não disponíveis em anos seguintes. A implementação foi actualizada em 2022/2023, para ser compatível com o material de apoio dessa altura, mas não teve outras actualizações.&lt;br /&gt;
* Enunciado: [[media:social-network-201110241420.pdf]]&lt;br /&gt;
* Implementação (core): [[media:sonet-core-202111021419.tar.bz2]]&lt;br /&gt;
* Implementação (app: browser): [[media:sonet-app-browser-202111021419.tar.bz2]]&lt;br /&gt;
* Implementação (app: manager): [[media:sonet-app-manager-202111021419.tar.bz2]]&lt;br /&gt;
&#039;&#039;&#039;O uso deste código deve ser feito de forma crítica, já que algumas das decisões nele tomadas podem ser alvo de descontos na avaliação do projecto.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Linguagens de Programação ==&lt;br /&gt;
&lt;br /&gt;
As seguintes linguagens são utilizadas nestas páginas:&lt;br /&gt;
&lt;br /&gt;
* [http://www.java.com/ Java] -- [https://docs.oracle.com/en/java/javase/ Java Platform, Standard Edition Documentation] (os testes automáticos usam OpenJDK 25)&lt;br /&gt;
* [http://cplusplus.com/ C++] (C++23 ou superior) -- [http://cplusplus.com/reference/ Manual de Referência para C++ (biblioteca)]; STL: [http://cplusplus.com/reference/stl/ contentores], [http://cplusplus.com/reference/algorithm/ algoritmos] &amp;lt;!--*[http://cppreference.com/ Manual de Referência para C/C++]--&amp;gt;&lt;br /&gt;
&amp;lt;!-- * [http://php.net/ PHP]: [http://www.php.net/manual/en/ manual] and [http://www.php.net/manual/en/funcref.php function reference] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]] &lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Reposit%C3%B3rio_GIT&amp;diff=17888</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Reposit%C3%B3rio_GIT&amp;diff=17888"/>
		<updated>2026-08-26T06:46:20Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
Os repositórios GIT para os projectos (um por grupo) já contêm versões iniciais do projecto.&lt;br /&gt;
&lt;br /&gt;
{{Aviso|&#039;&#039;&#039;O uso do repositório GIT é obrigatório.&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|&#039;&#039;&#039;Não serão considerados projectos que não estejam no repositório oficial.&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
== Localização ==&lt;br /&gt;
&lt;br /&gt;
Os repositórios estão disponíveis no Gitlab da RNL em &#039;&#039;&#039;[https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26 https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po26]&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O conteúdo do repositório pode ser manipulado com o comando &#039;&#039;&#039;git&#039;&#039;&#039; ou com qualquer outro cliente compatível.&lt;br /&gt;
&lt;br /&gt;
== Modo de Acesso ==&lt;br /&gt;
&lt;br /&gt;
O acesso ao serviço GitLab da RNL é realizado com as credenciais IST (à la Fénix)&lt;br /&gt;
&lt;br /&gt;
Todos os alunos do IST têm de ter credenciais válidas para poderem ser avaliados na disciplina.&lt;br /&gt;
&lt;br /&gt;
{{Aviso|Apenas é considerado para avaliação o ramo &#039;&#039;&#039;master&#039;&#039;&#039;. Alunos que não coloquem o projecto neste ramo serão excluídos da avaliação.}}&lt;br /&gt;
{{Aviso|Para o teste prático é necessário activar os serviços AFS e Shell no [https://selfservice.dsi.tecnico.ulisboa.pt/ self-service da DSI]. Sem isso, não é possível completar a avaliação do projecto, reprovando à disciplina.}}&lt;br /&gt;
&lt;br /&gt;
== Conteúdo e Estrutura do Repositório ==&lt;br /&gt;
&lt;br /&gt;
O código fornecido é de uso obrigatório e deve ser completado.&lt;br /&gt;
&lt;br /&gt;
O projecto é constituído por dois módulos: &#039;&#039;&#039;erp-core&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039; (o módulo &#039;&#039;&#039;po-uilib&#039;&#039;&#039; é exterior ao desenvolvimento).&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Conteúdo inicial do repositório para o módulo bci-core|&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
erp-core&lt;br /&gt;
├── Makefile&lt;br /&gt;
└── src&lt;br /&gt;
    └── erp&lt;br /&gt;
        ├── exceptions&lt;br /&gt;
        │   ├── ImportFileException.java&lt;br /&gt;
        │   ├── MissingFileAssociationException.java&lt;br /&gt;
        │   ├── UnavailableFileException.java&lt;br /&gt;
        │   └── UnrecognizedEntryException.java&lt;br /&gt;
        ├── Erp.java&lt;br /&gt;
        └── ErpManager.java&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
{{CollapsedCode|Conteúdo inicial do repositório para o módulo bci-app|&amp;lt;syntaxhighlight lang=&amp;quot;text&amp;quot;&amp;gt;&lt;br /&gt;
(a definir)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
Estes módulos podem ser obtidos em conjunto clonando o projecto com o número correspondente à inscrição no Fénix (ver abaixo).&lt;br /&gt;
 &lt;br /&gt;
O repositório já tem a seguinte estrutura:&lt;br /&gt;
* &#039;&#039;&#039;erp-core&#039;&#039;&#039; (directoria principal da biblioteca com a funcionalidade sem interface com o utilizador)&lt;br /&gt;
* &#039;&#039;&#039;erp-core/Makefile&#039;&#039;&#039; (makefile secundária, semelhante à disponibilizada na aplicação bancária)&lt;br /&gt;
* &#039;&#039;&#039;erp-core/src&#039;&#039;&#039; (directoria onde reside o código do &amp;quot;core&amp;quot;, à semelhança do que acontece na aplicação bancária)&lt;br /&gt;
* &#039;&#039;&#039;erp-app&#039;&#039;&#039; (directoria correspondente à aplicação; contém a interface com o utilizador)&lt;br /&gt;
* &#039;&#039;&#039;erp-app/Makefile&#039;&#039;&#039; (makefile secundária, semelhante à disponibilizada na aplicação bancária)&lt;br /&gt;
* &#039;&#039;&#039;erp-app/src&#039;&#039;&#039; (directoria onde já reside o código da interface textual, tal como na biblioteca equivalente da aplicação bancária)&lt;br /&gt;
&lt;br /&gt;
Esta estrutura já contém algumas classes parcialmente implementadas (&#039;&#039;&#039;erp-core&#039;&#039;&#039;) (que devem ser adaptadas) e outras parcial ou completamente implementadas (&#039;&#039;&#039;erp-app&#039;&#039;&#039;) (algumas das quais não podem ser alteradas).&lt;br /&gt;
&lt;br /&gt;
{{Aviso|A estrutura do repositório não pode ser alterada.}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|O código fornecido em &#039;&#039;&#039;erp-core&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039; tem de ser completado.}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|Os nomes das classes fornecidas em &#039;&#039;&#039;erp-core&#039;&#039;&#039; e &#039;&#039;&#039;erp-app&#039;&#039;&#039; não podem ser alterados.}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|As seguintes classes e interfaces não podem ser alteradas: &#039;&#039;&#039;App.java&#039;&#039;&#039;, todos os &#039;&#039;&#039;Label.java&#039;&#039;&#039;, todos os &#039;&#039;&#039;Menu.java&#039;&#039;&#039;, todos os &#039;&#039;&#039;Message.java&#039;&#039;&#039;, todos os &#039;&#039;&#039;Prompt.java&#039;&#039;&#039; e todas as excepções fornecidas (tanto em &#039;&#039;&#039;erp-core&#039;&#039;&#039;, como em &#039;&#039;&#039;erp-app&#039;&#039;&#039;).}}&lt;br /&gt;
&lt;br /&gt;
== Cuidados a ter na Utilização do Repositório GIT ==&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;NÃO FAZER&amp;lt;/font&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;git init&#039;&#039;&#039; (não é necessário: o repositório já existe)&lt;br /&gt;
&lt;br /&gt;
=== &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;FAZER&amp;lt;/font&amp;gt; ===&lt;br /&gt;
&lt;br /&gt;
O repositório já contém uma versão preliminar do projecto e devem ser dados os seguintes passos, para continuar a desenvolver o projecto:&lt;br /&gt;
&lt;br /&gt;
# &#039;&#039;&#039;git clone git@gitlab.rnl.tecnico.ulisboa.pt:leic-a-po26/prj/123.git&#039;&#039;&#039; (para obter uma cópia local, neste exemplo, do projecto do grupo &#039;&#039;&#039;123&#039;&#039;&#039;);&lt;br /&gt;
# Editar/adicionar material do/ao projecto;&lt;br /&gt;
# Caso sejam criados ficheiros ou directórios novos, fazer &#039;&#039;&#039;git add ficheiro1 ficheiro2 ... ficheiroN&#039;&#039;&#039; (adicionar novos ficheiros/directorias ao projecto);&lt;br /&gt;
# &#039;&#039;&#039;git pull&#039;&#039;&#039; (antes de enviar alteração locais para o repositório, verificar se há actualizações remotas a incorporar na cópia local)&lt;br /&gt;
# &#039;&#039;&#039;git status&#039;&#039;&#039; (verificar a situação na cópia local e que não foi esquecido nenhum ficheiro importante: voltar a 3. até terem sido todos adicionados)&lt;br /&gt;
# &#039;&#039;&#039;git commit -am &amp;quot;Mensagem de commit.&amp;quot;&#039;&#039;&#039; (registar alterações na cópia local)&lt;br /&gt;
# &#039;&#039;&#039;git push&#039;&#039;&#039; (enviar alterações para o GitLab -- &#039;&#039;&#039;sem este passo, não é realizada a entrega do projecto&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
=== Observações importantes ===&lt;br /&gt;
&lt;br /&gt;
* Não adicionar cópias do material de apoio (po-uilib) ao projecto (serão removidas e quaisquer alterações perdidas -- além disso, lixo no repositório é penalizado).&lt;br /&gt;
* Pessoas sem área no AFS, ou sem login activado, não poderão aceder ao conteúdo do teste prático: para activar estes acessos, consultar o self-service do CIIST (DSI) (ver acima). Em caso de dificuldade, consultar atempadamente o corpo docente.&lt;br /&gt;
* A estrutura do projecto no GIT deve ser mantida como apresentado.&lt;br /&gt;
* Em caso de dúvidas, consultar o corpo docente.&lt;br /&gt;
&lt;br /&gt;
{{Aviso|&#039;&#039;&#039;As activações de serviços não são instantâneas: activações no próprio dia de uma entrega ou de uma prova, estão condenadas a falhar e resultam necessariamente em reprovação. A activação atempada é da exclusiva responsabilidade do aluno.&#039;&#039;&#039;}}&lt;br /&gt;
&lt;br /&gt;
== &amp;quot;Receita&amp;quot; para a Entrega de Diagramas UML ==&lt;br /&gt;
&lt;br /&gt;
Tal como indicado no [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|método de avaliação]], os 3 diagramas a entregar -- &#039;&#039;&#039;UML-po-uilib.pdf&#039;&#039;&#039;, &#039;&#039;&#039;UML-erp-app.pdf&#039;&#039;&#039;, &#039;&#039;&#039;UML-erp-core.pdf&#039;&#039;&#039; -- devem ser colocados na directoria &#039;&#039;&#039;uml&#039;&#039;&#039; do projecto no repositório GIT.&lt;br /&gt;
&lt;br /&gt;
Os comandos abaixo explicam como realizar essa operação a partir de um projecto no repositório (desde obter uma cópia local até completar a entrega). O passo de obter a cópia local pode ser omitido se o projecto já tiver sido obtido anteriormente. O passo de adicionar novos ficheiros pode ser omitido se as versões dos diagramas corresponderem a actualizações de adições anteriores. Nos exemplos dos comandos abaixo, &#039;&#039;&#039;123&#039;&#039;&#039; é o grupo de trabalho da pessoa a realizar a entrega.&lt;br /&gt;
&lt;br /&gt;
* Obter o projecto do repositório (o projecto fica na directoria local &#039;&#039;&#039;123&#039;&#039;&#039;). Assume-se que os comandos subsequentes são dados dentro da directoria &#039;&#039;&#039;123&#039;&#039;&#039; (notar &#039;&#039;&#039;cd 123&#039;&#039;&#039; abaixo):&lt;br /&gt;
 git clone  git@gitlab.rnl.tecnico.ulisboa.pt:leic-a-po26/prj/123.git&lt;br /&gt;
 cd 123&lt;br /&gt;
* Colocar os ficheiros com os diagramas na directoria &#039;&#039;&#039;uml&#039;&#039;&#039; (ficheiros novos ou actualizações). Esta operação depende de onde estão os diagramas ou de como foram digitalizados a partir da versão manuscrita (recorda-se que apenas são aceites diagramas manuscritos, devidamente acompanhados com a declaração de autoria). O comando apresentado é apenas um exemplo (assume que os diagramas estão originalmente na directoria principal do utilizador).&lt;br /&gt;
 cp ~/UML-po-uilib.pdf ~/UML-bci-app.pdf ~/UML-bci-core.pdf uml&lt;br /&gt;
* Adicionar os ficheiros novos ao CVS (no comando a seguir, assume-se que os 3 ficheiros são adicionados, mas pode adicionar-se um de cada vez): &lt;br /&gt;
 git add uml/UML-po-uilib.pdf uml/UML-erp-app.pdf uml/UML-erp-core.pdf&lt;br /&gt;
* Pode realizar-se neste ponto um pedido de actualização da cópia local (caso a outra pessoa do grupo também esteja a fazer alterações -- se não é o caso, este passo é opcional):&lt;br /&gt;
 git pull&lt;br /&gt;
 git status&lt;br /&gt;
* Registar as alterações (na cópia local) (a mensagem descreve o commit):&lt;br /&gt;
 git commit -am &amp;quot;Adicionados diagramas UML.&amp;quot;&lt;br /&gt;
* Finalmente, enviam-se os ficheiros novos para o repositório GIT:&lt;br /&gt;
 git push&lt;br /&gt;
&lt;br /&gt;
[[category: Projecto de PO]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category: Ensino]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Avalia%C3%A7%C3%A3o_do_Projecto_(%C3%89poca_Normal)&amp;diff=17887</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Avalia%C3%A7%C3%A3o_do_Projecto_(%C3%89poca_Normal)&amp;diff=17887"/>
		<updated>2026-08-26T06:42:15Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Entrega Final */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
=Método de Avaliação do Projecto =&lt;br /&gt;
&lt;br /&gt;
A avaliação relativa à componente do Projecto processa-se em várias fases:&lt;br /&gt;
&lt;br /&gt;
* [[#Entrega do Modelo UML|Entrega do modelo UML]] (&#039;&#039;&#039;obrigatória&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
* [[#Entrega Intermédia|Entrega intermédia]] (&#039;&#039;&#039;obrigatória&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
* [[#Entrega Final|Entrega final]] (&#039;&#039;&#039;obrigatória&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
* [[#Teste Prático|Teste prático]] (&#039;&#039;&#039;obrigatório&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
&lt;br /&gt;
O Projecto (trabalho conducente às entregas acima mencionadas e abaixo descritas) é realizado em grupos de 2 elementos ou individualmente durante o período estabelecido.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODAS AS ENTREGAS SÃO REALIZADAS ATÉ ÀS 12:00 (&amp;quot;meio-dia&amp;quot;) DAS RESPECTIVAS DATAS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O Teste Prático é realizado individualmente, em data e local a agendar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;Considerando que todas as entregas são cruciais na concepção e realização do projecto, a não realização de qualquer entrega conduz automaticamente a uma classificação de 0 (zero) na componente de avaliação relativa ao Projecto e consequente exclusão da avaliação da disciplina no ano lectivo em curso.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Cálculo da Nota do Projecto e Condições de Aprovação =&lt;br /&gt;
&lt;br /&gt;
Componentes de avaliação:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;PRJ&#039;&#039;&#039; - nota final do projecto&lt;br /&gt;
* &#039;&#039;&#039;PU&#039;&#039;&#039; - nota da entrega do diagrama UML&lt;br /&gt;
* &#039;&#039;&#039;PI&#039;&#039;&#039;- nota da entrega intermédia&lt;br /&gt;
* &#039;&#039;&#039;PF&#039;&#039;&#039;- nota da entrega final&lt;br /&gt;
* &#039;&#039;&#039;TP&#039;&#039;&#039; - nota do teste prático&lt;br /&gt;
&lt;br /&gt;
A nota do teste prático condiciona a distância ao mínimo entre as notas do teste prático e a do projecto: desde um mínimo de 12.5% de acréscimo à menor das duas (abaixo de 7.5 valores no TP), até um máximo de 25% (para 20 valores no TP). O acréscimo é linear entre 7.5 e 20. &lt;br /&gt;
&lt;br /&gt;
Ou seja: &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;PRJ = min(PU+PI+PF, TP) + | TP - PU - PI - PF | * max(12.5, TP+5) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Condições necessárias para aprovação à disciplina -- &#039;&#039;&#039;necessárias todas&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;PRJ &amp;gt;= 9.5&#039;&#039;&#039; (sem arredondamento)&lt;br /&gt;
* &#039;&#039;&#039;PRJ != NA&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;&#039;TP &amp;gt; 0&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;TP != NA&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Entrega do Modelo UML =&lt;br /&gt;
&lt;br /&gt;
A Entrega do Modelo UML avalia o estado do projecto relativamente à concepção do modelo. &lt;br /&gt;
&lt;br /&gt;
Esta entrega tem uma classificação máxima de 3 valores. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização da Entrega do Modelo UML conduz automaticamente a uma classificação de 0 (zero) na componente do projecto.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Devem ser entregues diagramas de classes correspondentes a todos os conceitos da aplicação, mesmo que esses conceitos venham a ser revistos/alterados futuramente. Podem ainda ser incluídas anotações nos diagramas, por forma a clarificar outros aspectos relevantes. Não é necessária a inclusão de getters/setters/equals/toString (e outros métodos já definidos no Java).&lt;br /&gt;
* Diagrama 1: diagrama do pacote &#039;&#039;&#039;po-uilib&#039;&#039;&#039; (material de apoio que não pode ser alterado): &#039;&#039;&#039;UML-po-uilib.pdf&#039;&#039;&#039; (não é necessário representar o conteúdo de &#039;&#039;&#039;pt/tecnico/uilib/swing&#039;&#039;&#039;)&lt;br /&gt;
* Diagrama 2: diagrama do pacote &#039;&#039;&#039;erp-app&#039;&#039;&#039; (material do projecto completo -- pode receber adições de código em métodos &#039;&#039;&#039;execute&#039;&#039;&#039;, de atributos nas classes dos comandos e de classes auxiliares): &#039;&#039;&#039;UML-erp-app.pdf&#039;&#039;&#039;&lt;br /&gt;
* Diagrama 3: diagrama do pacote &#039;&#039;&#039;erp-core&#039;&#039;&#039; (material do projecto incompleto e que deve ser completado e desenvolvido -- ou seja, deve incluir adicionalmente partes que correspondem à interpretação do enunciado): &#039;&#039;&#039;UML-erp-core.pdf&#039;&#039;&#039;. Este diagrama é de entrega &#039;&#039;&#039;obrigatória&#039;&#039;&#039; (grupos que não o entreguem estão excluídos da avaliação).&lt;br /&gt;
&lt;br /&gt;
A entrega dos diagramas &#039;&#039;&#039;obrigatoriamente manuscritos&#039;&#039;&#039; é feita em documentos PDF na directoria &amp;quot;uml&amp;quot; do projecto no GIT. O formato é A4 (cada diagrama pode ter várias páginas) e realiza-se até à data limite: 4ª feira, 2026/10/16, 12:00 (meio-dia). Documentos ilegíveis ou noutros formatos serão sumariamente ignorados, mesmo que isso resulte em reprovação dos alunos envolvidos: é da responsabilidade dos alunos produzir material de boa qualidade nas condições de avaliação.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;Apenas são aceites diagramas manuscritos e posteriormente digitalizados (usando uma aplicação como nas aulas laboratoriais): serão recusados quaisquer diagramas produzidos com ferramentas informáticas, mesmo que isso resulte em reprovação dos alunos envolvidos: é da responsabilidade dos alunos produzir material de material de boa qualidade nas condições de avaliação.&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;Cada diagrama deve conter a seguinte declaração de autoria, assinada sob compromisso de honra (os diagramas entregues por grupos de 2 alunos devem conter duas declarações independentes com o mesmo texto e correspondente assinatura):&lt;br /&gt;
&#039;&#039;&#039;Declaro por minha honra que este diagrama foi realizado apenas pelos elementos que constituem o grupo de projecto. (assinatura)&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;Diagramas entregues sem declaração de autoria serão considerados indício de fraude e os alunos correspondentes excluídos da avaliação da disciplina, sendo comunicada a situação aos órgãos da Escola.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Serão aplicados os seguintes critérios na avaliação da entrega UML.&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;&#039;&#039;&#039;positivos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.80 - Conceitos&lt;br /&gt;
* 0.50 - Herança&lt;br /&gt;
* 0.70 - Associações&lt;br /&gt;
* 0.50 - Atributos&lt;br /&gt;
* 0.50 - Interface (métodos das classes, interfaces, etc.)&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;negativos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.50 - Erros de notação&lt;br /&gt;
&lt;br /&gt;
A compreensão clara dos aspectos acima deve ser adquirida antes da entrega.&lt;br /&gt;
&lt;br /&gt;
= Entrega Intermédia =&lt;br /&gt;
&lt;br /&gt;
A Entrega Intermédia avalia o estado do projecto relativamente a um mínimo de funcionalidade.&lt;br /&gt;
&lt;br /&gt;
Serão executados testes automáticos nesta entrega. &lt;br /&gt;
&lt;br /&gt;
Esta entrega tem uma classificação máxima de 6 valores (2.5 valores para testes automáticos). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização da Entrega Intermédia conduz automaticamente a uma classificação de 0 (zero) na componente do projecto.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Funcionalidade a implementar ==&lt;br /&gt;
&lt;br /&gt;
Os pormenores dos parâmetros de avaliação desta entrega serão anunciados em breve.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
A funcionalidade necessária para a entrega intermédia, além da abertura de todos os submenus, é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* Leitura, interpretação e representação em memória do ficheiro textual indicado pela propriedade &#039;&#039;&#039;[[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Leitura de Dados a Partir de Ficheiros Textuais|import]]&#039;&#039;&#039; (implica implementar algumas classes do &amp;quot;core&amp;quot;)&lt;br /&gt;
* Menu principal: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Salvaguarda do estado actual da aplicação|Salvaguarda do estado actual da aplicação]]: &amp;quot;Abrir&amp;quot; e &amp;quot;Guardar&amp;quot; -- implementação completa&lt;br /&gt;
* Menu principal: &amp;quot;Mostrar data&amp;quot; e &amp;quot;Avançar data&amp;quot; -- implementação completa&lt;br /&gt;
* Menu principal: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Gestão e consulta de dados da aplicação|Gestão e consulta de dados da aplicação]]: abertura dos vários submenus (comandos fornecidos já implementados).&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Menu de Gestão de Utentes|Menu de Gestão de Utentes]] -- implementar as operações &amp;quot;Registar utente&amp;quot;, &amp;quot;Mostrar utente&amp;quot;, &amp;quot;Mostrar utentes&amp;quot;.&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Menu de Gestão de Obras|Menu de Gestão de Obras]] -- implementar a operação &amp;quot;Mostrar obra&amp;quot;, &amp;quot;Mostrar obras&amp;quot;, &amp;quot;Mostrar obras de criador&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Todos os outros comandos em todos os menus têm de estar implementados (&amp;quot;execute&amp;quot; pode estar vazio). Não é má prática implementar os outros comandos, pois poupa esforço para a entrega final, mas não serão avaliados nesta entrega.&lt;br /&gt;
&lt;br /&gt;
A funcionalidade a implementar em &#039;&#039;&#039;erp-core&#039;&#039;&#039; tem de ser suficiente para suportar os comandos indicados acima.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Critérios de avaliação (não automática) ==&lt;br /&gt;
&lt;br /&gt;
Serão aplicados os seguintes &#039;&#039;&#039;critérios na avaliação da entrega intermédia&#039;&#039;&#039; do projecto.&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;&#039;&#039;&#039;positivos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.40 - Atributos não públicos &lt;br /&gt;
* 0.30 - Atributos e métodos não &amp;quot;static&amp;quot; (excepto onde autorizado)&lt;br /&gt;
* 0.20 - Serialização &lt;br /&gt;
* 1.00 - Utilização correcta de herança&lt;br /&gt;
* 0.50 - Utilização das estruturas de dados correctas&lt;br /&gt;
* 0.60 - Separação app/core (pode haver descontos na parte automática) &lt;br /&gt;
* 0.30 - Qualidade do projecto &lt;br /&gt;
* 0.20 - Comentários Javadoc (a colocar necessariamente na classe &#039;&#039;&#039;Erp&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;negativos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.15 - Violação de regras de codificação Java&lt;br /&gt;
&lt;br /&gt;
Será aplicado um desconto até 1.00 pela existência de lixo no repositório GIT. Este &amp;quot;lixo&amp;quot; é apenas considerado se aparecer na cópia local durante um &amp;quot;checkout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
= Entrega Final =&lt;br /&gt;
&lt;br /&gt;
A Entrega Final pressupõe que todo o projecto foi completamente implementado. &lt;br /&gt;
&lt;br /&gt;
Esta entrega tem uma classificação máxima de 11 valores:&lt;br /&gt;
* 5.50 valores para a qualidade do código&lt;br /&gt;
* 5.50 valores para testes automáticos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização da Entrega Final conduz automaticamente a uma classificação de 0 (zero) na componente do projecto.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Os testes correspondem a uma série de entradas a processar pelo projecto de cada grupo e cuja execução deve corresponder a um conjunto de resultados padrão.&lt;br /&gt;
&lt;br /&gt;
Serão aplicados os seguintes critérios na avaliação da entrega final do projecto.&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;&#039;&#039;&#039;positivos&#039;&#039;&#039;&amp;lt;/font&amp;gt;: (a definir)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* 0.50 - Utilização de estruturas de dados correctas&lt;br /&gt;
* 1.00 - Aplicação dos princípios de desenho aberto/fechado e programar para o supertipo&lt;br /&gt;
* 1.00 - Qualidade da solução utilizada para o tratamento de classificações de utentes&lt;br /&gt;
* 1.00 - Qualidade da solução utilizada para o tratamento de notificações&lt;br /&gt;
* 1.00 - Fugas de privacidade entre as entidades do core e a camada de interacção com o utilizador e separação de responsabilidades, incluindo serialização (core vs. app)&lt;br /&gt;
* 0.50 - Verificação de situações erróneas nos programas (e.g., não mascarar excepções, entre outros aspectos)&lt;br /&gt;
* 0.50 - Apreciação global&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;negativos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* até 1.00 - Violação de regras de codificação Java&lt;br /&gt;
* até 1.00 - Existência de lixo no repositório GIT (o &amp;quot;lixo&amp;quot; é apenas considerado se aparecer na cópia local durante um &amp;quot;checkout&amp;quot;)&lt;br /&gt;
* até 1.00 - Uso directo dos tipos Object (excepto onde inevitável), Exception (excepto como superclasse), Throwable, Error&lt;br /&gt;
* até 0.50 - Atributos (qualidade e acesso)&lt;br /&gt;
* até 0.25 - Atributos e métodos &amp;quot;static&amp;quot; (excepto autorizados)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note-se que não é considerada a entrega final se o repositório à data da entrega final contiver o mesmo código da entrega intermédia. Isso implica também a reprovação imediata dos alunos do grupo em causa (todas as entregas do projecto são obrigatórias).&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Teste Prático =&lt;br /&gt;
&lt;br /&gt;
O Teste Prático consiste num conjunto de questões (correspondentes a pequenas alterações/extensões ao enunciado) a resolver com base na implementação submetida para a avaliação correspondente à entrega final.&lt;br /&gt;
&lt;br /&gt;
Este teste avalia o conhecimento do aluno relativamente ao projecto entregue, assim como a sua capacidade de realizar alterações ao código do projecto. &lt;br /&gt;
&lt;br /&gt;
O teste prático é como uma discussão de projecto, pelo que não existem repescagens como nos testes escritos. Alunos que faltem ao teste prático estão automaticamente reprovados à disciplina.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização do Teste Prático conduz automaticamente a uma classificação de 0 (zero) na componente de avaliação relativa ao Projecto e consequente exclusão da avaliação da disciplina no ano lectivo em curso.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O teste prático contém uma prova eliminatória: o aluno deverá ser capaz de compilar e executar um pequeno programa em Java.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Considerações Adicionais sobre a Avaliação do Projecto =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O projecto deverá ser desenvolvido atempadamente ao longo do período lectivo.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As versões intermédias registadas no GIT poderão ser testadas, pelo que deverão ser periodicamente actualizadas. O projecto é constituído por um projecto GIT designado pelo número do grupo que o executa. O repositório GIT disponibilizado já contém uma versão inicial do projecto. Apenas os ficheiros registados no projecto GIT serão considerados na avaliação.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Não serão consideradas quaisquer alterações a alguns dos ficheiros disponibilizados: eventuais cópias desses ficheiros serão automaticamente substituídas durante a avaliação da funcionalidade do código submetido. Ver página sobre o repositório, para mais pormenores.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A avaliação executa testes automáticos ao projecto a implementar: a nota reflectirá apenas os testes com sucesso. Chama-se especial atenção para o nome da classe que inicia a execução. As restantes componentes da nota são obtidas pela análise do código e resultado do teste prático (realizado individualmente). O código é avaliado quanto à sua correcção, simplicidade, extensibilidade e legibilidade: devem existir comentários das partes mais complexas, mas não devem ser excessivos, nem óbvios (diminuem a legibilidade), nem muito escassos (impedem a compreensão).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Qualquer alteração à especificação providenciada no enunciado é penalizada, mesmo que possa ser entendida como um melhoramento.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Notar que o facto de os testes automáticos terem sido superados não reflecte a qualidade do código, quer do ponto de vista de engenharia de software, quer do ponto de vista da correcta aplicação dos princípios leccionados na disciplina. A funcionalidade do projecto final é, no entanto, de extrema importância, pelo que &#039;&#039;&#039;é preferível um projecto que realize, correctamente, apenas parte da funcionalidade a um quase completo mas que nem sequer compile ou que não processe nenhuma entrada correctamente&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Compromisso de Honra =&lt;br /&gt;
&lt;br /&gt;
A entrega de quaisquer trabalhos pressupõe o compromisso de honra que foram realizados pelos autores referenciados e que resultam do esforço por cumprir os requisitos da entrega. A quebra deste compromisso, nomeadamente, a tentativa de apropriação de trabalhos alheios, terá como consequência a reprovação de todos os alunos envolvidos (incluindo os que possibilitaram a ocorrência) no ano lectivo actual, sem prejuízo de acções disciplinares previstas pelo IST.&lt;br /&gt;
&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Ensino]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Avalia%C3%A7%C3%A3o_do_Projecto_(%C3%89poca_Normal)&amp;diff=17886</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/Avalia%C3%A7%C3%A3o_do_Projecto_(%C3%89poca_Normal)&amp;diff=17886"/>
		<updated>2026-08-26T06:41:06Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
=Método de Avaliação do Projecto =&lt;br /&gt;
&lt;br /&gt;
A avaliação relativa à componente do Projecto processa-se em várias fases:&lt;br /&gt;
&lt;br /&gt;
* [[#Entrega do Modelo UML|Entrega do modelo UML]] (&#039;&#039;&#039;obrigatória&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
* [[#Entrega Intermédia|Entrega intermédia]] (&#039;&#039;&#039;obrigatória&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
* [[#Entrega Final|Entrega final]] (&#039;&#039;&#039;obrigatória&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
* [[#Teste Prático|Teste prático]] (&#039;&#039;&#039;obrigatório&#039;&#039;&#039;: ver condições abaixo)&lt;br /&gt;
&lt;br /&gt;
O Projecto (trabalho conducente às entregas acima mencionadas e abaixo descritas) é realizado em grupos de 2 elementos ou individualmente durante o período estabelecido.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;TODAS AS ENTREGAS SÃO REALIZADAS ATÉ ÀS 12:00 (&amp;quot;meio-dia&amp;quot;) DAS RESPECTIVAS DATAS&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
O Teste Prático é realizado individualmente, em data e local a agendar.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;Considerando que todas as entregas são cruciais na concepção e realização do projecto, a não realização de qualquer entrega conduz automaticamente a uma classificação de 0 (zero) na componente de avaliação relativa ao Projecto e consequente exclusão da avaliação da disciplina no ano lectivo em curso.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Cálculo da Nota do Projecto e Condições de Aprovação =&lt;br /&gt;
&lt;br /&gt;
Componentes de avaliação:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;PRJ&#039;&#039;&#039; - nota final do projecto&lt;br /&gt;
* &#039;&#039;&#039;PU&#039;&#039;&#039; - nota da entrega do diagrama UML&lt;br /&gt;
* &#039;&#039;&#039;PI&#039;&#039;&#039;- nota da entrega intermédia&lt;br /&gt;
* &#039;&#039;&#039;PF&#039;&#039;&#039;- nota da entrega final&lt;br /&gt;
* &#039;&#039;&#039;TP&#039;&#039;&#039; - nota do teste prático&lt;br /&gt;
&lt;br /&gt;
A nota do teste prático condiciona a distância ao mínimo entre as notas do teste prático e a do projecto: desde um mínimo de 12.5% de acréscimo à menor das duas (abaixo de 7.5 valores no TP), até um máximo de 25% (para 20 valores no TP). O acréscimo é linear entre 7.5 e 20. &lt;br /&gt;
&lt;br /&gt;
Ou seja: &lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;PRJ = min(PU+PI+PF, TP) + | TP - PU - PI - PF | * max(12.5, TP+5) / 100&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Condições necessárias para aprovação à disciplina -- &#039;&#039;&#039;necessárias todas&#039;&#039;&#039;:&lt;br /&gt;
&lt;br /&gt;
* &#039;&#039;&#039;PRJ &amp;gt;= 9.5&#039;&#039;&#039; (sem arredondamento)&lt;br /&gt;
* &#039;&#039;&#039;PRJ != NA&#039;&#039;&#039; &lt;br /&gt;
* &#039;&#039;&#039;TP &amp;gt; 0&#039;&#039;&#039;&lt;br /&gt;
* &#039;&#039;&#039;TP != NA&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Entrega do Modelo UML =&lt;br /&gt;
&lt;br /&gt;
A Entrega do Modelo UML avalia o estado do projecto relativamente à concepção do modelo. &lt;br /&gt;
&lt;br /&gt;
Esta entrega tem uma classificação máxima de 3 valores. &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização da Entrega do Modelo UML conduz automaticamente a uma classificação de 0 (zero) na componente do projecto.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Devem ser entregues diagramas de classes correspondentes a todos os conceitos da aplicação, mesmo que esses conceitos venham a ser revistos/alterados futuramente. Podem ainda ser incluídas anotações nos diagramas, por forma a clarificar outros aspectos relevantes. Não é necessária a inclusão de getters/setters/equals/toString (e outros métodos já definidos no Java).&lt;br /&gt;
* Diagrama 1: diagrama do pacote &#039;&#039;&#039;po-uilib&#039;&#039;&#039; (material de apoio que não pode ser alterado): &#039;&#039;&#039;UML-po-uilib.pdf&#039;&#039;&#039; (não é necessário representar o conteúdo de &#039;&#039;&#039;pt/tecnico/uilib/swing&#039;&#039;&#039;)&lt;br /&gt;
* Diagrama 2: diagrama do pacote &#039;&#039;&#039;erp-app&#039;&#039;&#039; (material do projecto completo -- pode receber adições de código em métodos &#039;&#039;&#039;execute&#039;&#039;&#039;, de atributos nas classes dos comandos e de classes auxiliares): &#039;&#039;&#039;UML-erp-app.pdf&#039;&#039;&#039;&lt;br /&gt;
* Diagrama 3: diagrama do pacote &#039;&#039;&#039;erp-core&#039;&#039;&#039; (material do projecto incompleto e que deve ser completado e desenvolvido -- ou seja, deve incluir adicionalmente partes que correspondem à interpretação do enunciado): &#039;&#039;&#039;UML-erp-core.pdf&#039;&#039;&#039;. Este diagrama é de entrega &#039;&#039;&#039;obrigatória&#039;&#039;&#039; (grupos que não o entreguem estão excluídos da avaliação).&lt;br /&gt;
&lt;br /&gt;
A entrega dos diagramas &#039;&#039;&#039;obrigatoriamente manuscritos&#039;&#039;&#039; é feita em documentos PDF na directoria &amp;quot;uml&amp;quot; do projecto no GIT. O formato é A4 (cada diagrama pode ter várias páginas) e realiza-se até à data limite: 4ª feira, 2026/10/16, 12:00 (meio-dia). Documentos ilegíveis ou noutros formatos serão sumariamente ignorados, mesmo que isso resulte em reprovação dos alunos envolvidos: é da responsabilidade dos alunos produzir material de boa qualidade nas condições de avaliação.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;Apenas são aceites diagramas manuscritos e posteriormente digitalizados (usando uma aplicação como nas aulas laboratoriais): serão recusados quaisquer diagramas produzidos com ferramentas informáticas, mesmo que isso resulte em reprovação dos alunos envolvidos: é da responsabilidade dos alunos produzir material de material de boa qualidade nas condições de avaliação.&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;Cada diagrama deve conter a seguinte declaração de autoria, assinada sob compromisso de honra (os diagramas entregues por grupos de 2 alunos devem conter duas declarações independentes com o mesmo texto e correspondente assinatura):&lt;br /&gt;
&#039;&#039;&#039;Declaro por minha honra que este diagrama foi realizado apenas pelos elementos que constituem o grupo de projecto. (assinatura)&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;Diagramas entregues sem declaração de autoria serão considerados indício de fraude e os alunos correspondentes excluídos da avaliação da disciplina, sendo comunicada a situação aos órgãos da Escola.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Serão aplicados os seguintes critérios na avaliação da entrega UML.&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;&#039;&#039;&#039;positivos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.80 - Conceitos&lt;br /&gt;
* 0.50 - Herança&lt;br /&gt;
* 0.70 - Associações&lt;br /&gt;
* 0.50 - Atributos&lt;br /&gt;
* 0.50 - Interface (métodos das classes, interfaces, etc.)&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;negativos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.50 - Erros de notação&lt;br /&gt;
&lt;br /&gt;
A compreensão clara dos aspectos acima deve ser adquirida antes da entrega.&lt;br /&gt;
&lt;br /&gt;
= Entrega Intermédia =&lt;br /&gt;
&lt;br /&gt;
A Entrega Intermédia avalia o estado do projecto relativamente a um mínimo de funcionalidade.&lt;br /&gt;
&lt;br /&gt;
Serão executados testes automáticos nesta entrega. &lt;br /&gt;
&lt;br /&gt;
Esta entrega tem uma classificação máxima de 6 valores (2.5 valores para testes automáticos). &lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização da Entrega Intermédia conduz automaticamente a uma classificação de 0 (zero) na componente do projecto.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Funcionalidade a implementar ==&lt;br /&gt;
&lt;br /&gt;
Os pormenores dos parâmetros de avaliação desta entrega serão anunciados em breve.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
A funcionalidade necessária para a entrega intermédia, além da abertura de todos os submenus, é a seguinte:&lt;br /&gt;
&lt;br /&gt;
* Leitura, interpretação e representação em memória do ficheiro textual indicado pela propriedade &#039;&#039;&#039;[[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Leitura de Dados a Partir de Ficheiros Textuais|import]]&#039;&#039;&#039; (implica implementar algumas classes do &amp;quot;core&amp;quot;)&lt;br /&gt;
* Menu principal: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Salvaguarda do estado actual da aplicação|Salvaguarda do estado actual da aplicação]]: &amp;quot;Abrir&amp;quot; e &amp;quot;Guardar&amp;quot; -- implementação completa&lt;br /&gt;
* Menu principal: &amp;quot;Mostrar data&amp;quot; e &amp;quot;Avançar data&amp;quot; -- implementação completa&lt;br /&gt;
* Menu principal: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Gestão e consulta de dados da aplicação|Gestão e consulta de dados da aplicação]]: abertura dos vários submenus (comandos fornecidos já implementados).&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Menu de Gestão de Utentes|Menu de Gestão de Utentes]] -- implementar as operações &amp;quot;Registar utente&amp;quot;, &amp;quot;Mostrar utente&amp;quot;, &amp;quot;Mostrar utentes&amp;quot;.&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027#Menu de Gestão de Obras|Menu de Gestão de Obras]] -- implementar a operação &amp;quot;Mostrar obra&amp;quot;, &amp;quot;Mostrar obras&amp;quot;, &amp;quot;Mostrar obras de criador&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Todos os outros comandos em todos os menus têm de estar implementados (&amp;quot;execute&amp;quot; pode estar vazio). Não é má prática implementar os outros comandos, pois poupa esforço para a entrega final, mas não serão avaliados nesta entrega.&lt;br /&gt;
&lt;br /&gt;
A funcionalidade a implementar em &#039;&#039;&#039;erp-core&#039;&#039;&#039; tem de ser suficiente para suportar os comandos indicados acima.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
== Critérios de avaliação (não automática) ==&lt;br /&gt;
&lt;br /&gt;
Serão aplicados os seguintes &#039;&#039;&#039;critérios na avaliação da entrega intermédia&#039;&#039;&#039; do projecto.&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;forestgreen&amp;quot;&amp;gt;&#039;&#039;&#039;positivos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.40 - Atributos não públicos &lt;br /&gt;
* 0.30 - Atributos e métodos não &amp;quot;static&amp;quot; (excepto onde autorizado)&lt;br /&gt;
* 0.20 - Serialização &lt;br /&gt;
* 1.00 - Utilização correcta de herança&lt;br /&gt;
* 0.50 - Utilização das estruturas de dados correctas&lt;br /&gt;
* 0.60 - Separação app/core (pode haver descontos na parte automática) &lt;br /&gt;
* 0.30 - Qualidade do projecto &lt;br /&gt;
* 0.20 - Comentários Javadoc (a colocar necessariamente na classe &#039;&#039;&#039;Erp&#039;&#039;&#039;)&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;negativos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* 0.15 - Violação de regras de codificação Java&lt;br /&gt;
&lt;br /&gt;
Será aplicado um desconto até 1.00 pela existência de lixo no repositório GIT. Este &amp;quot;lixo&amp;quot; é apenas considerado se aparecer na cópia local durante um &amp;quot;checkout&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
= Entrega Final =&lt;br /&gt;
&lt;br /&gt;
A Entrega Final pressupõe que todo o projecto foi completamente implementado. &lt;br /&gt;
&lt;br /&gt;
Esta entrega tem uma classificação máxima de 11 valores:&lt;br /&gt;
* 5.50 valores para a qualidade do código&lt;br /&gt;
* 5.50 valores para testes automáticos&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização da Entrega Final conduz automaticamente a uma classificação de 0 (zero) na componente do projecto.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Os testes correspondem a uma série de entradas a processar pelo projecto de cada grupo e cuja execução deve corresponder a um conjunto de resultados padrão.&lt;br /&gt;
&lt;br /&gt;
Serão aplicados os seguintes critérios na avaliação da entrega final do projecto.&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;green&amp;quot;&amp;gt;&#039;&#039;&#039;positivos&#039;&#039;&#039;&amp;lt;/font&amp;gt;: (a definir)&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* 0.50 - Utilização de estruturas de dados correctas&lt;br /&gt;
* 1.00 - Aplicação dos princípios de desenho aberto/fechado e programar para o supertipo&lt;br /&gt;
* 1.00 - Qualidade da solução utilizada para o tratamento de classificações de utentes&lt;br /&gt;
* 1.00 - Qualidade da solução utilizada para o tratamento de notificações&lt;br /&gt;
* 1.00 - Fugas de privacidade entre as entidades do core e a camada de interacção com o utilizador e separação de responsabilidades, incluindo serialização (core vs. app)&lt;br /&gt;
* 0.50 - Verificação de situações erróneas nos programas (e.g., não mascarar excepções, entre outros aspectos)&lt;br /&gt;
* 0.50 - Apreciação global&lt;br /&gt;
&lt;br /&gt;
Factores aditivos &amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;negativos&#039;&#039;&#039;&amp;lt;/font&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
* até 1.00 - Violação de regras de codificação Java&lt;br /&gt;
* até 1.00 - Existência de lixo no repositório GIT (o &amp;quot;lixo&amp;quot; é apenas considerado se aparecer na cópia local durante um &amp;quot;checkout&amp;quot;)&lt;br /&gt;
* até 1.00 - Uso directo dos tipos Object (excepto onde inevitável), Exception (excepto como superclasse), Throwable, Error&lt;br /&gt;
* até 0.50 - Atributos (qualidade e acesso)&lt;br /&gt;
* até 0.25 - Atributos e métodos &amp;quot;static&amp;quot; (excepto autorizados)&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Note-se que não é considerada a entrega final se o repositório à data da entrega final contiver o mesmo código da entrega intermédia. Isso implica também a reprovação imediata dos alunos do grupo em causa (todas as entregas do projecto são obrigatórias).&#039;&#039;&#039;&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
= Teste Prático =&lt;br /&gt;
&lt;br /&gt;
O Teste Prático consiste num conjunto de questões (correspondentes a pequenas alterações/extensões ao enunciado) a resolver com base na implementação submetida para a avaliação correspondente à entrega final.&lt;br /&gt;
&lt;br /&gt;
Este teste avalia o conhecimento do aluno relativamente ao projecto entregue, assim como a sua capacidade de realizar alterações ao código do projecto. &lt;br /&gt;
&lt;br /&gt;
O teste prático é como uma discussão de projecto, pelo que não existem repescagens como nos testes escritos. Alunos que faltem ao teste prático estão automaticamente reprovados à disciplina.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;font color=&amp;quot;red&amp;quot;&amp;gt;&#039;&#039;&#039;A não realização do Teste Prático conduz automaticamente a uma classificação de 0 (zero) na componente de avaliação relativa ao Projecto e consequente exclusão da avaliação da disciplina no ano lectivo em curso.&#039;&#039;&#039;&amp;lt;/font&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O teste prático contém uma prova eliminatória: o aluno deverá ser capaz de compilar e executar um pequeno programa em Java.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Considerações Adicionais sobre a Avaliação do Projecto =&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;O projecto deverá ser desenvolvido atempadamente ao longo do período lectivo.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
As versões intermédias registadas no GIT poderão ser testadas, pelo que deverão ser periodicamente actualizadas. O projecto é constituído por um projecto GIT designado pelo número do grupo que o executa. O repositório GIT disponibilizado já contém uma versão inicial do projecto. Apenas os ficheiros registados no projecto GIT serão considerados na avaliação.&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Não serão consideradas quaisquer alterações a alguns dos ficheiros disponibilizados: eventuais cópias desses ficheiros serão automaticamente substituídas durante a avaliação da funcionalidade do código submetido. Ver página sobre o repositório, para mais pormenores.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
A avaliação executa testes automáticos ao projecto a implementar: a nota reflectirá apenas os testes com sucesso. Chama-se especial atenção para o nome da classe que inicia a execução. As restantes componentes da nota são obtidas pela análise do código e resultado do teste prático (realizado individualmente). O código é avaliado quanto à sua correcção, simplicidade, extensibilidade e legibilidade: devem existir comentários das partes mais complexas, mas não devem ser excessivos, nem óbvios (diminuem a legibilidade), nem muito escassos (impedem a compreensão).&lt;br /&gt;
&lt;br /&gt;
&#039;&#039;&#039;Qualquer alteração à especificação providenciada no enunciado é penalizada, mesmo que possa ser entendida como um melhoramento.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
Notar que o facto de os testes automáticos terem sido superados não reflecte a qualidade do código, quer do ponto de vista de engenharia de software, quer do ponto de vista da correcta aplicação dos princípios leccionados na disciplina. A funcionalidade do projecto final é, no entanto, de extrema importância, pelo que &#039;&#039;&#039;é preferível um projecto que realize, correctamente, apenas parte da funcionalidade a um quase completo mas que nem sequer compile ou que não processe nenhuma entrada correctamente&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
= Compromisso de Honra =&lt;br /&gt;
&lt;br /&gt;
A entrega de quaisquer trabalhos pressupõe o compromisso de honra que foram realizados pelos autores referenciados e que resultam do esforço por cumprir os requisitos da entrega. A quebra deste compromisso, nomeadamente, a tentativa de apropriação de trabalhos alheios, terá como consequência a reprovação de todos os alunos envolvidos (incluindo os que possibilitaram a ocorrência) no ano lectivo actual, sem prejuízo de acções disciplinares previstas pelo IST.&lt;br /&gt;
&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Ensino]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos&amp;diff=17885</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos&amp;diff=17885"/>
		<updated>2026-08-26T06:33:33Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
== Avaliação do Projecto ==&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Avaliação do Projecto (Época Normal)|Avaliação do Projecto (Época Normal)]]&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Calendário do Teste Prático (Época Normal)|Calendário do Teste Prático (Época Normal)]]&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Teste Prático (Época Especial)|Teste Prático (Época Especial)]]&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
As pautas são acompanhadas pelos critérios de avaliação. &amp;lt;!--Os critérios e condições de Época Especial são parecidos com os da Época Normal. Em particular, a componente de projecto continua obrigatória.--&amp;gt;&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
== Projecto: Enunciado 2017-2018 (época especial) ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2017-2018 (época especial)|Enunciado do Projecto de Época Especial]] -- Editor de Texto&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Projecto: Enunciado 2026-2027 (época normal) ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2026-2027|Enunciado do Projecto 2026-2027]]&lt;br /&gt;
* Enunciados de anos anteriores: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2025-2026|2025-2026]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2024-2025|2024-2025]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2023-2024|2023-2024]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2022-2023|2022-2023]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2021-2022|2021-2022]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2020-2021|2020-2021]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2019-2020|2019-2020]] [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2018-2019|2018-2019]]&lt;br /&gt;
&lt;br /&gt;
== Material de Apoio e Testes ==&lt;br /&gt;
&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|Repositório GIT]] - informações de localização e acesso &lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|Material de Apoio ao Desenvolvimento]]&lt;br /&gt;
* Testes automáticos: https://gitlab.rnl.tecnico.ulisboa.pt/leic-a-po25/eval/po25&lt;br /&gt;
&amp;lt;!--* [[Programação com Objectos/Projecto de Programação com Objectos/Testes Automáticos 2021-2022|Testes Automáticos 2021-2022]] --&amp;gt;&lt;br /&gt;
&amp;lt;!--* [[Programação com Objectos/Projecto de Programação com Objectos/Testes Automáticos 2020-2021|Testes Automáticos 2020-2021]] --&amp;gt;&lt;br /&gt;
&amp;lt;!--* [[Programação com Objectos/Projecto de Programação com Objectos/Testes Automáticos 2019-2020|Testes Automáticos 2019-2020]] --&amp;gt;&lt;br /&gt;
&amp;lt;!--* [[Programação com Objectos/Projecto de Programação com Objectos/Testes Automáticos 2018-2019|Testes Automáticos 2018-2019]] --&amp;gt;&lt;br /&gt;
* [[Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual|Máquina Virtual]]&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Aplicação Bancária ==&lt;br /&gt;
&lt;br /&gt;
Para auxiliar o desenvolvimento do projecto, é fornecida uma [[Comando (padrão de desenho)/Banco, Conta, Titular (aplicação bancária)|aplicação bancária]] (banco, contas, titulares, etc.), que tem a mesma estrutura. Esta estrutura tem duas partes principais: &amp;quot;core&amp;quot; (o núcleo lógico da aplicação) e &amp;quot;app&amp;quot; (a interface textual, baseada no padrão de desenho [[Comando (padrão_de_desenho)|Command]]).&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Hotel Veterinário (2024) ==&lt;br /&gt;
&lt;br /&gt;
Este projecto descreve um hotel veterinário.&lt;br /&gt;
&lt;br /&gt;
O enunciado corresponde ao ano lectivo de 2024/2025 e refere aspectos de implementação compatíveis com 2025/2026.&lt;br /&gt;
* Enunciado: [[Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2024-2025|Hotel Veterinário]]&lt;br /&gt;
* Implementação (git snapshot): [[media:po24-hva-2025030036.tar.bz2]]&lt;br /&gt;
{{Aviso|O uso deste código deve ser feito de forma crítica, já que algumas das decisões nele tomadas podem ser alvo de descontos na avaliação do projecto.}}&lt;br /&gt;
&lt;br /&gt;
== Projecto Exemplo: Rede Social (2011) ==&lt;br /&gt;
&lt;br /&gt;
Este projecto descreve uma rede social com funcionalidade semelhante à das redes sociais actuais: relações entre agentes, publicação de vários tipos de media, envio de mensagens, etc.&lt;br /&gt;
&lt;br /&gt;
Note-se que o enunciado corresponde ao ano lectivo de 2011/2012 e refere aspectos de implementação não disponíveis em anos seguintes. A implementação foi actualizada em 2022/2023, para ser compatível com o material de apoio dessa altura, mas não teve outras actualizações.&lt;br /&gt;
* Enunciado: [[media:social-network-201110241420.pdf]]&lt;br /&gt;
* Implementação (core): [[media:sonet-core-202111021419.tar.bz2]]&lt;br /&gt;
* Implementação (app: browser): [[media:sonet-app-browser-202111021419.tar.bz2]]&lt;br /&gt;
* Implementação (app: manager): [[media:sonet-app-manager-202111021419.tar.bz2]]&lt;br /&gt;
&#039;&#039;&#039;O uso deste código deve ser feito de forma crítica, já que algumas das decisões nele tomadas podem ser alvo de descontos na avaliação do projecto.&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
== Linguagens de Programação ==&lt;br /&gt;
&lt;br /&gt;
As seguintes linguagens são utilizadas nestas páginas:&lt;br /&gt;
&lt;br /&gt;
* [http://www.java.com/ Java] -- [https://docs.oracle.com/en/java/javase/ Java Platform, Standard Edition Documentation] (os testes automáticos usam OpenJDK 25)&lt;br /&gt;
* [http://cplusplus.com/ C++] (C++23 ou superior) -- [http://cplusplus.com/reference/ Manual de Referência para C++ (biblioteca)]; STL: [http://cplusplus.com/reference/stl/ contentores], [http://cplusplus.com/reference/algorithm/ algoritmos] &amp;lt;!--*[http://cppreference.com/ Manual de Referência para C/C++]--&amp;gt;&lt;br /&gt;
&amp;lt;!-- * [http://php.net/ PHP]: [http://www.php.net/manual/en/ manual] and [http://www.php.net/manual/en/funcref.php function reference] --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[category:Ensino]] &lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/M%C3%A1quina_Virtual&amp;diff=17884</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/M%C3%A1quina_Virtual&amp;diff=17884"/>
		<updated>2026-08-26T06:32:56Z</updated>

		<summary type="html">&lt;p&gt;Root: /* Curiosidade e Outras Aplicações */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
== Máquina Virtual ==&lt;br /&gt;
&lt;br /&gt;
A máquina virtual da disciplina é baseada em &#039;&#039;&#039;openSUSE Tumbleweed.&#039;&#039;&#039; Este ambiente é providenciado como conveniência e não é estritamente necessário: outros ambientes com as versões adequadas de Java e de clientes GIT poderão ser utilizados (mas ver avisos abaixo).&lt;br /&gt;
&lt;br /&gt;
A versão mais recente da máquina virtual da disciplina, &#039;&#039;&#039;poo 2026.08&#039;&#039;&#039; está disponível em:&lt;br /&gt;
&lt;br /&gt;
* https://download.opensuse.org/repositories/home:/d4vid:/po26/images/ &lt;br /&gt;
&lt;br /&gt;
A máquina virtual é fornecida nos formatos VMDK (VMware, VirtualBox), VHD (Microsoft HyperV) e qcow2 (KVM e outros).&lt;br /&gt;
&lt;br /&gt;
A máquina permite configurações básicas (password de root, etc.) no primeiro arranque. Existe um utilizador normal chamado &amp;quot;poo&amp;quot; (password &amp;quot;linux&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
A máquina vem sem ambiente gráfico, mas é simples instalar um com a ferramenta &amp;quot;yast&amp;quot;.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{Suggestion|A máquina virtual reproduz o ambiente canónico para o projecto e já contém todo o material de apoio necessário ao desenvolvimento.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{Suggestion|Em caso de indisponibilidade da máquina virtual, ver em [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|Pacotes Binários e Ambiente Oficial]] como reproduzir o ambiente de teste a partir de openSUSE Tumbleweed.}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|Tempo e esforço perdidos com ambientes ou ferramentas não recomendados ou não suportados é da inteira responsabilidade do aluno e quaisquer resultados negativos, incluindo possível reprovação, são igualmente da responsabilidade do aluno (i.e., não fazer parte da avaliação por ter usado material ou ambientes não recomendados não será aceite como justificação para qualquer falha de desempenho).}}&lt;br /&gt;
&lt;br /&gt;
== Aplicação Exemplo/Tutorial: Banco ==&lt;br /&gt;
&lt;br /&gt;
A máquina virtual contém os JARs da [[Comando (padrão de desenho)/Banco, Conta, Titular (aplicação bancária)|aplicação bancária]]: uma aplicação exemplo/tutorial completamente implementada e que tem a mesma estrutura do projecto.&lt;br /&gt;
&lt;br /&gt;
== Curiosidade e Outras Aplicações ==&lt;br /&gt;
&lt;br /&gt;
A máquina virtual pode ser útil noutros contextos e leitores interessados podem aceder às definições de construção no &amp;quot;build service&amp;quot;:&lt;br /&gt;
* https://build.opensuse.org/package/show/home:d4vid:po26/poo&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/M%C3%A1quina_Virtual&amp;diff=17883</id>
		<title>Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Programa%C3%A7%C3%A3o_com_Objectos/Projecto_de_Programa%C3%A7%C3%A3o_com_Objectos/M%C3%A1quina_Virtual&amp;diff=17883"/>
		<updated>2026-08-26T06:32:31Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{PRJPOAvisosEN20262027}}&lt;br /&gt;
{{PRJPOMandatory20262027}}&lt;br /&gt;
__NOTOC__&lt;br /&gt;
&lt;br /&gt;
== Máquina Virtual ==&lt;br /&gt;
&lt;br /&gt;
A máquina virtual da disciplina é baseada em &#039;&#039;&#039;openSUSE Tumbleweed.&#039;&#039;&#039; Este ambiente é providenciado como conveniência e não é estritamente necessário: outros ambientes com as versões adequadas de Java e de clientes GIT poderão ser utilizados (mas ver avisos abaixo).&lt;br /&gt;
&lt;br /&gt;
A versão mais recente da máquina virtual da disciplina, &#039;&#039;&#039;poo 2026.08&#039;&#039;&#039; está disponível em:&lt;br /&gt;
&lt;br /&gt;
* https://download.opensuse.org/repositories/home:/d4vid:/po26/images/ &lt;br /&gt;
&lt;br /&gt;
A máquina virtual é fornecida nos formatos VMDK (VMware, VirtualBox), VHD (Microsoft HyperV) e qcow2 (KVM e outros).&lt;br /&gt;
&lt;br /&gt;
A máquina permite configurações básicas (password de root, etc.) no primeiro arranque. Existe um utilizador normal chamado &amp;quot;poo&amp;quot; (password &amp;quot;linux&amp;quot;).&lt;br /&gt;
&lt;br /&gt;
A máquina vem sem ambiente gráfico, mas é simples instalar um com a ferramenta &amp;quot;yast&amp;quot;.&lt;br /&gt;
&amp;lt;!--&lt;br /&gt;
{{Suggestion|A máquina virtual reproduz o ambiente canónico para o projecto e já contém todo o material de apoio necessário ao desenvolvimento.}}&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
{{Suggestion|Em caso de indisponibilidade da máquina virtual, ver em [[Programação com Objectos/Projecto de Programação com Objectos/Material de Apoio ao Desenvolvimento|Pacotes Binários e Ambiente Oficial]] como reproduzir o ambiente de teste a partir de openSUSE Tumbleweed.}}&lt;br /&gt;
&lt;br /&gt;
{{Aviso|Tempo e esforço perdidos com ambientes ou ferramentas não recomendados ou não suportados é da inteira responsabilidade do aluno e quaisquer resultados negativos, incluindo possível reprovação, são igualmente da responsabilidade do aluno (i.e., não fazer parte da avaliação por ter usado material ou ambientes não recomendados não será aceite como justificação para qualquer falha de desempenho).}}&lt;br /&gt;
&lt;br /&gt;
== Aplicação Exemplo/Tutorial: Banco ==&lt;br /&gt;
&lt;br /&gt;
A máquina virtual contém os JARs da [[Comando (padrão de desenho)/Banco, Conta, Titular (aplicação bancária)|aplicação bancária]]: uma aplicação exemplo/tutorial completamente implementada e que tem a mesma estrutura do projecto.&lt;br /&gt;
&lt;br /&gt;
== Curiosidade e Outras Aplicações ==&lt;br /&gt;
&lt;br /&gt;
A máquina virtual pode ser útil noutros contextos e leitores interessados podem aceder às definições de construção no &amp;quot;build service&amp;quot;:&lt;br /&gt;
* https://build.opensuse.org/package/show/home:d4vid:po25/poo&lt;br /&gt;
&lt;br /&gt;
[[category: Ensino]]&lt;br /&gt;
[[category:PO]]&lt;br /&gt;
[[category:Projecto de PO]]&lt;br /&gt;
[[en:Object-Oriented Programming]]&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
	<entry>
		<id>https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Template:PRJPOMandatory20262027&amp;diff=17882</id>
		<title>Template:PRJPOMandatory20262027</title>
		<link rel="alternate" type="text/html" href="https://robots.hlt.inesc-id.pt/w/pt/index.php?title=Template:PRJPOMandatory20262027&amp;diff=17882"/>
		<updated>2026-08-26T06:31:37Z</updated>

		<summary type="html">&lt;p&gt;Root: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| class=&amp;quot;mw-collapsible mw-collapsed wikitable&amp;quot; align=&amp;quot;right&amp;quot; style=&amp;quot;border-style: solid; border-width: 1px; border-color: #bbbbaa; background: #ffdb24;&amp;quot;&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 0px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #ffdb24;&amp;quot; | &#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;Material de Uso Obrigatório&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 0px; border-color: #bbbbaa; &amp;quot; | As bibliotecas &amp;lt;strong&amp;gt;po-uilib&amp;lt;/strong&amp;gt; e o conteúdo inicial do repositório GIT são de &amp;lt;strong&amp;gt;uso obrigatório&amp;lt;/strong&amp;gt;:&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 0px; border-color: #bbbbaa; &amp;quot; | &lt;br /&gt;
* po-uilib (classes de base)  [[media:po-uilib-202608310000.tar.bz2|po-uilib-202608310000.tar.bz2]] (não pode ser alterada) - [https://www.hlt.inesc-id.pt/~david/ist/docencia/po/2026-2027/javadoc/ javadoc]&lt;br /&gt;
* erp-core (classes do &amp;quot;core&amp;quot;) (via GIT) (deve ser completada -- os nomes das classes fornecidas não podem ser alterados)&lt;br /&gt;
* erp-app (classes de interacção) (via GIT) (deve ser completada -- os nomes das classes fornecidas não podem ser alterados)&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 0px; border-color: #bbbbaa; &amp;quot; | A [[Programação com Objectos/Projecto de Programação com Objectos/Máquina Virtual|máquina virtual]], fornecida para desenvolvimento do projecto, já contém todo o material de apoio.&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; border-style: solid; border-width: 1px; border-bottom-width: 0px; border-color: #bbbbaa;  background: #ffdb24;&amp;quot; | &#039;&#039;&#039;&amp;lt;font color=&amp;quot;brown&amp;quot;&amp;gt;Uso Obrigatório: Repositório GIT&amp;lt;/font&amp;gt;&#039;&#039;&#039;&lt;br /&gt;
|-&lt;br /&gt;
! style=&amp;quot;padding-left:10px; padding-right:10px; font-weight: normal; border-style: solid; border-width: 0px; border-color: #bbbbaa; &amp;quot; | &#039;&#039;&#039;Apenas se consideram para avaliação os projectos existentes no [[Programação com Objectos/Projecto de Programação com Objectos/Repositório GIT|repositório GIT oficial]]&#039;&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
|}&lt;/div&gt;</summary>
		<author><name>Root</name></author>
	</entry>
</feed>