Difference between revisions of "Programação com Objectos/Projecto de Programação com Objectos/Enunciado do Projecto de 2020-2021 (rascunho de trabalho)"

From Wiki**3

< Programação com Objectos‎ | Projecto de Programação com Objectos
(Contabilização de Pontos (Clientes))
(Replaced content with "(enunciado publicado)")
 
(35 intermediate revisions by the same user not shown)
Line 1: Line 1:
{{PRJPOAvisosEN20202021}}
+
(enunciado publicado)
{{PRJPOMandatory20202021}}
 
{{TOCright}}
 
'''<font color="red">ÉPOCA NORMAL</font>'''
 
 
 
O objectivo do projecto é desenvolver uma aplicação de gestão para uma empresa de distribuição. A empresa concede prémios de fidelização aos bons clientes (volume de compras). A funcionalidade da aplicação deverá incluir, entre outras acções: registar dados de produtos para venda, registar dados de clientes, registar dados de fornecedores de produtos para venda e fazer pesquisas várias sobre a informação armazenada. Deve ainda permitir gerir a venda de caixas e contentores e de produtos de fornecedores associados; registar encomendas a fornecedores e pagamento de transacções. A lista completa encontra-se abaixo.
 
 
 
Neste texto, o tipo '''negrito''' indica um literal (i.e., é exactamente como apresentado); o símbolo ␣ indica um espaço; e o tipo ''itálico'' indica uma parte variável.
 
 
 
=  Empresa, Produtos, Clientes, Fornecedores e Transacções =
 
<!--
 
Além de manter informação sobre todas as entidades, a empresa mantém informação sobre o volume de negócios realizado, i.e., contabilização do saldo total de vendas e pagamentos a fornecedores (número em vı́rgula flutuante de dupla precisão – double)..Inicialmente, este saldo é zero.
 
-->
 
Os produtos, clientes e fornecedores possuem uma chave única (cadeia de caracteres). As transacções (vendas e encomendas) possuem uma chave inteira.
 
 
 
== Propriedades e Funcionalidade dos Produtos ==
 
 
 
A empresa vende caixas e contentores de vários tipos, consoante o nı́vel de serviço de transporte a realizar. Outros tipos de produtos diversos para venda são disponibilizados à empresa por fornecedores. <!--Também podem ser colocados para venda produtos diversos, como forma de promover os fornecedores (e.g., livros ou outras obras culturais).-->
 
 
 
Todos os produtos têm um fornecedor, um preço (um número inteiro) e um valor crı́tico (utilizado na gestão de existências).
 
 
 
Caixas são produtos que têm um volume relativamente pequeno e servem para guardar um número relativamente pequeno de itens, por forma a protegê-los durante o seu transporte. As caixas têm um dado nível de serviço: normal, aéreo, expresso e em mão.
 
 
 
Contentores são produtos que têm um volume muito maior que as caixas, permitindo guardar uma maior quantidade de itens. Também têm os mesmos 4 níveis de serviço das caixas. Adicionalmente, os contentores têm 4 níveis de qualidade de serviço: B4, C4, C5, DL.
 
 
 
Os livros são caracterizados pelo respectivo tı́tulo, autor e ISBN (cadeias de caracteres). Poderão ser definidos novos tipos de produtos (e.g. discos ou CDs/DVDs), que terão as suas próprias propriedades.<!-- pelo código do editor (cadeia de caracteres). Os DVDs são ainda caracterizados pelo limite de idade para o conteúdo associado (número inteiro).-->
 
 
 
== Propriedades e Funcionalidade dos Clientes ==
 
 
 
Os clientes fazem compras que podem ser pagas mais tarde.
 
 
 
Cada cliente é identificado pelo nome (cadeia de caracteres) e possui ainda informação acerca da morada (cadeia de caracteres). Associado a cada cliente existe ainda a informação relativa a compras efectuadas e facturas pagas, assim como o seu estatuto (e.g., cliente "Elite").
 
 
 
Dado um cliente, é possı́vel aceder ao historial das suas transacções.
 
 
 
Um cliente que iniba as notificações só pode ser considerado '''Normal''' (ver abaixo). <!--Um cliente inactivo não pode realizar transacções (este aspecto é independente da recepção de notificações). A inactivação/reactivação do cliente não afecta o seu estatuto (ver abaixo).-->
 
 
 
== Propriedades e Funcionalidade dos Fornecedores ==
 
 
 
Os fornecedores respondem a encomendas por parte da empresa.
 
 
 
Cada fornecedor é identificado pelo nome (cadeia de caracteres) e possui ainda informação acerca da morada (cadeia de caracteres). <!--Associado a cada fornecedor existe ainda a informação relativa a fornecimentos efectuados e dos pagamentos recebidos.-->
 
 
 
Dado um fornecedor, é possı́vel aceder ao seu historial de transacções. É ainda possível activar/desactivar a realização de transacções com um fornecedor. Um fornecedor inactivo, além de não pode realizar transacções, não recebe notificações.
 
 
 
== Propriedades e Funcionalidade das Transacções ==
 
 
 
Existem dois tipos de transacção: vendas e encomendas. As transacções são identificadas por um número (inteiro), atribuído de forma automática pela aplicação. Este identificador começa em 0 (zero), sendo incrementado quando se regista uma nova transacção. A sequência de identificadores é partilhada por todas as transacções (vendas e encomendas).
 
 
 
Uma encomenda está associada a um fornecedor e envolve uma ou mais unidades de um ou mais produtos fornecidos pelo fornecedor em causa. O custo unitário de cada produto corresponde ao custo do produto em causa. A encomenda guarda o seu custa total, por forma que futuras alterações no preço de um produto não alterem o valor que foi pago pela encomenda. Quando se faz uma encomenda deve considerar-se que a encomenda foi paga imediatamente e que as existências da empresa foram actualizadas considerando os produtos encomendados.
 
 
 
Uma venda envolve apenas uma ou mais unidades de um único produto. Cada venda tem uma data limite de pagamento: primeiro realiza-se a venda e só depois é que se procede ao seu pagamento.
 
 
 
Para as vendas, são considerados os seguintes perı́odos ('''N''' é 5 para caixas, 8 para contentores e 3 para livros):
 
* Até '''N''' dias antes do limite de pagamento ('''data_limite_de_pagamento − data_actual ≥ N'''): sem penalização; desconto de 10%;
 
* Até à data limite ('''0 ≤ data_limite_de_pagamento − data_actual < N'''): sem penalização; sem desconto;
 
* Até '''N''' dias depois da data limite ('''1 < data_actual − data_limite_de_pagamento ≤ N'''): multa de 5% por cada dia de atraso; sem desconto.
 
* Após '''N''' dias depois da data limite ('''data_actual − data_limite_de_pagamento > N'''): multa de 10% por cada dia de atraso; sem desconto.
 
 
 
==  Notificações ==
 
 
 
Quando se registar um novo produto, os clientes devem ser registados como entidades interessadas em receber notificações sobre eventos a ele associado. Em qualquer momento, um cliente pode activar ou desactivar as notificações relativas a um produto. Os eventos a considerar são os seguintes: (i) quando o produto passa de stock 0 (zero) para outro valor (positivo); (ii) quando um produto fica mais barato. As notificações são compostas pela cadeia de caracteres constituı́da pela identificação do produto e pela descrição da notificação ('''NEW''', para novos produtos; e '''BARGAIN''', para descidas de preços), sendo registadas tanto na empresa, como nos clientes que as recebem.
 
 
 
A entrega de notificações deve ser flexível e prever vários meios de entrega, e.g., correio postal, SMS, email, entre outras. O meio de entrega por omissão corresponde a apresentar a notificação no écrã.
 
 
 
Quando as existências de um produto atingem o correspondente valor crı́tico (abaixo do qual há perigo de o produto ficar esgotado), o fornecedor do produto deve ser notificado. Fornecedores inactivos não devem ser notificados. As notificações são compostas pela cadeia de caracteres constituı́da pela identificação do produto e pela descrição da notificação ('''CRITICAL'''), sendo registadas tanto na empresa, como nos fornecedores que as recebem.
 
 
 
==  Contabilização de Pontos (Clientes) ==
 
 
 
Nesta secção, as penalizações e os descontos aplicam-se apenas no pagamento de transacções (vendas) por clientes.
 
 
 
A contabilização de pontos é realizada quando se paga uma transacção dentro do prazo e corresponde a 10 vezes o valor pago. Não há contabilização de pontos em pagamentos atrasados.
 
 
 
Além dos clientes normais, existem clientes '''Selection''' (com mais de 2000 pontos), que podem pagar venda sem penalização até 1 dia depois da data limite (depois dessa data, são penalizados em 2% diários), e obter descontos até 2 dias antes da data limite (5%, depois do limite normal dos 5 dias). Clientes '''Elite''' (com mais de 25000 pontos) nunca são penalizados e têm descontos de 10%, mesmo após a data limite (depois de 5 dias, os descontos baixam para 5%, até ao limite de 10 dias, em que deixa de haver descontos).
 
 
 
Se um cliente se atrasa no pagamento da transacções, é despromovido: um cliente '''Elite''' passa a '''Selection''' se tiver transacções com um atraso de pagamento superior a 15 dias (perde 75% dos pontos acumulados); um cliente '''Selection''' passa a '''Normal''' se tiver transacções com um atraso de pagamento superior a 2 dias (perde 90% dos pontos acumulados). A verificação do atraso é realizada quando se paga a venda.
 
 
 
==  Pesquisas ==
 
 
 
Deve ser possı́vel efectuar pesquisas sob vários critérios e sobre as diferentes entidades geridas pela empresa: (i) produtos comprados por um determinado cliente; (ii) clientes que compram determinado produto; (iii) facturas pagas por um determinado cliente; (iv) facturas pagas com um atraso determinado; (v) produtos com um preço inferior a um dado valor. Deve ser possı́vel introduzir novos métodos de pesquisa com um impacto mı́nimo na implementação desenvolvida.
 
 
 
== Data ==
 
 
 
A data é representada por um número inteiro e tem inicialmente o valor 0 (zero). A data pode começar com outro valor se se recuperar o estado da empresa a partir de um suporte persistente.
 
 
 
Os avanços de data são valores inteiros que representam o número de dias.
 
 
 
= Requisitos de Desenho =
 
 
Devem ser possíveis extensões ou alterações de funcionalidade com impacto mínimo no código já produzido para a aplicação. O objectivo é aumentar a flexibilidade da aplicação relativamente ao suporte de novas funções. Assim, deve ser possível:
 
* Adicionar novos tipos de produtos;
 
* Definir novas entidades que desejem ser notificadas da alteração do estado dos produtos;
 
* Adicionar novos modos de entrega de mensagens (notificações);
 
* Adicionar novas políticas de recompensa de clientes;
 
* Adicionar novas formas de consulta.
 
 
 
Embora na especificação actual não seja possível a remoção de produtos ou de clientes, a inclusão destas funcionalidades deve ser prevista, por forma a minimizar o impacto da sua futura inclusão.
 
 
 
= Funcionalidade da aplicação =
 
 
 
A aplicação permite manter informação sobre as entidades do modelo. 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).
 
 
 
A base de dados com os conceitos pré-definidos é [[#Leitura de Dados a Partir de Ficheiros Textuais|carregada no início da aplicação]]. <!--Não é possível remover entidades durante a execução da aplicação.-->
 
 
 
É possível saber os saldos da distribuidora (diferencial entre vendas e compras). Existe um saldo disponível, correspondente à diferença entre as vendas realmente pagas e as encomendas e um saldo contabilístico, correspondente à diferença entre o valor contabilístico das vendas (pagas ou não e considerando descontos/penalizações à data da consulta de saldo) e as encomendas.
 
 
 
{{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 ''core'' da aplicação, tal como é visível pelos comandos da aplicação.}}
 
{{CVSCode|A interface geral do ''core''  já está parcialmente implementada na classe '''woo.StoreManager''' e outras fornecidas (cujos nomes devem ser mantidos), devendo ser adaptadas onde necessário. É ainda necessário criar e implementar as restantes classes que suportam a operação da aplicação.}}
 
 
 
== Serialização ==
 
 
 
É possível guardar e recuperar o estado actual da aplicação, preservando toda a informação relevante, descrita [[#Conceitos e Relações do Modelo|acima]].
 
 
 
== Funcionalidade Associada a Entidades do Domínio ==
 
 
 
A seguinte funcionalidade sobre produtos deve ser suportada pela aplicação: (i) visualizar um produto; (ii) registar um novo produto; (iii) alterar o preço de um produto; (iv) reforçar as existências de um produto.
 
 
 
A seguinte funcionalidade sobre clientes deve ser suportada pela aplicação: (i) visualizar um cliente; (ii) registar um novo cliente; (iii) activar/desactivar notificações relativas a produtos; <!--(iv) activar/desactivar um cliente; -->(iv) consultar o histórico de transacções realizadas por um cliente.
 
 
 
A seguinte funcionalidade sobre fornecedores deve ser suportada pela aplicação: (i) visualizar um fornecedor; (ii) registar um novo fornecedor; (iii) inibir/activar um fornecedor; (iv) consultar o histórico de transacções realizados.
 
 
 
A seguinte funcionalidade sobre transacções deve ser suportada: (i) visualizar uma transacção; (ii) registar uma nova venda; (iii) registar uma nova encomenda; (iv) pagar uma transacção.<!--; (iv) cancelar uma factura.-->
 
 
 
= Interacção com o utilizador =
 
 
 
Descreve-se nesta secção a '''funcionalidade máxima''' da interface com o utilizador. Em geral, os comandos pedem toda a informação antes de proceder à sua validação (excepto onde indicado). Todos os menus têm automaticamente a opção '''Sair''' (fecha o menu).
 
 
 
As operações de pedido e apresentação de informação ao utilizador '''devem''' realizar-se através dos objectos ''form'' e ''display'', 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]] ('''po-uuilib''' e '''woo-app'''). As mensagens não podem ser usadas no núcleo da aplicação ('''woo-core'''). Além disso, não podem ser definidas novas. Potenciais omissões devem ser esclarecidas antes de qualquer implementação.
 
 
 
As excepções usadas na interacção, excepto se indicado, são subclasses de '''pt.tecnico.po.ui.DialogException''', são lançadas pelos comandos e tratadas por '''pt.tecnico.po.ui.Menu'''. Outras excepções não devem substituir as fornecidas nos casos descritos.
 
 
 
A apresentacção de listas (e.g., Fornecedores, Transacções, etc.) faz-se por ordem crescente da respectiva chave. a ordem pode ser numérica ou lexicográfica (UTF-8), não havendo distinção entre maiúsculas e minúsculas.
 
 
 
{{CVSCode|Note-se que o programa principal e os comandos e menus, a seguir descritos, já estão parcialmente implementados nas ''packages'' '''woo.app''', '''woo.app.main''', '''woo.app.products''', '''woo.app.clients''', '''woo.app.suppliers''', '''woo.app.transactions''', '''woo.app.lookups'''. 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 CVS|CVS]] (módulo '''woo-app''').}}
 
 
 
== Menu Principal ==
 
 
 
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|Gestão de Produtos]], [[#Gestão e consulta de dados da aplicação|Gestão de Clientes]], [[#Gestão e consulta de dados da aplicação|Gestão de Fornecedores]], [[#Gestão e consulta de dados da aplicação|Gestão de Transacções]], [[#Gestão e consulta de dados da aplicação|Consultas]], [[#Menu Principal|Mostrar Saldo Global]].
 
 
 
As etiquetas das opções deste menu estão definidas na classe '''woo.app.main.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''woo.app.main.Message'''.
 
 
 
{{CVSCode|Estes comandos já estão implementados  nas classes da ''package'' '''woo.app.main''' (disponível no CVS), respectivamente: '''DoOpen''', '''DoSave''', '''DoDisplayDate''', '''DoAdvanceDate''', '''DoOpenMenuProducts''', '''DoOpenMenuClients''', '''DoOpenMenuSuppliers''', '''DoOpenManuTransactions''', '''DoOpenMenuLookups''', '''DoShowGlobalBalance'''.}}
 
 
 
=== Salvaguarda do estado actual da aplicação ===
 
 
 
Inicialmente, a aplicação está vazia ou tem apenas informação sobre as entidades que foram carregados no arranque (via ficheiro textual).
 
 
 
O conteúdo da aplicação (toda a informação actualmente em memória) pode ser guardado para posterior recuperação (via serialização Java: '''java.io.Serializable'''). Na leitura e escrita do estado da aplicação, devem ser tratadas as excepções associadas. A funcionalidade é a seguinte:
 
 
 
* '''Abrir''' -- Carrega os dados de uma sessão anterior a partir de um ficheiro previamente guardado (ficando este ficheiro associado à aplicação, para futuras operações de salvaguarda). Pede-se o nome do ficheiro a abrir ('''openFile()'''). Caso ocorra um problema na abertura ou processamento do ficheiro, deve ser lançada a excepção '''FileOpenFailedException'''. A execução bem sucedida desta opção substitui toda a informação da aplicação.
 
* '''Guardar''' -- Guarda o estado actual da aplicação no ficheiro associado. Se não existir associação, pede-se o nome do ficheiro a utilizar, ficando a ele associado. Esta interacção realiza-se através do método '''newSaveAs()'''. Não é executada nenhuma acção se não existirem alterações desde a última salvaguarda.
 
 
 
Note-se que a opção '''Abrir''' não permite a leitura de ficheiros de texto (estes apenas são utilizados na inicialização da aplicação).
 
 
 
A opção '''Sair''' nunca guarda o estado da aplicação, mesmo que existam alterações.
 
 
 
=== Mostrar data actual ===
 
 
 
A data actual do sistema é apresentada através da mensagem '''currentDate()'''.
 
 
 
=== Avançar data actual ===
 
 
 
O número de dias a avançar é pedido através de '''requestDaysToAdvance()'''. O valor indicado deve ser positivo. Caso contrário, a operação não tem efeito.
 
 
 
Além da data, o sistema deve actualizar, caso seja necessário, outros aspectos que dela dependam, designadamente, a situação dos clientes e fornecedores relativa a prazos e notificações.
 
 
 
A apresentação faz-se através da mensagem '''showBalance()'''.
 
 
 
=== Gestão e consulta de dados da aplicação ===
 
 
 
* '''Menu de Gestão de Produtos''' -- Abre o menu de gestão de produtos e operações associadas.
 
* '''Menu de Gestão de Clientes''' -- Abre o menu de gestão de clientes e operações associadas.
 
* '''Menu de Gestão de Fornecedores''' -- Abre o menu de gestão de fornecedores e operações associadas.
 
* '''Menu de Gestão de Transacções''' -- Abre o menu de gestão de transacções e operações associadas.
 
* '''Menu de Consultas''' -- Abre o menu de consultas (pesquisas)..
 
 
 
=== Mostrar saldo global ===
 
 
 
Esta opção apresenta os valores (inteiros) correspondente aos saldos disponivel e contabilístico da empresa. Embora internamente o valor dos saldos esteja representado em vírgula flutuante, a apresentação é arredondada ao inteiro mais próximo.
 
 
 
== Menu de Gestão de Produtos ==
 
 
 
Este menu permite efectuar operações sobre a base de dados de produtos. A lista completa é a seguinte: [[#Visualizar todos os produtos|Visualizar todos os produtos]], Registar produtos (de vários tipos), [[#Alterar preço de produto|Alterar preço de produto]].
 
 
 
As etiquetas das opções deste menu estão definidas na classe '''woo.app.products.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''woo.app.products.Message'''.
 
 
 
Sempre que é pedido o identificador de um produto ('''requestProductKey()''') e o produto não existir, é lançada a excepção '''UnknownProductKeyException''' (excepto no processo de registo).
 
 
 
{{CVSCode|Estes comandos já estão implementados  nas classes da ''package'' '''woo.app.products''' (disponível no CVS), respectivamente: '''DoShowAllProducts''', '''DoRegisterProductBox''', '''DoRegisterProductContainer''', '''DoRegisterProductBook''', '''DoChangePrice'''.}}
 
 
 
=== Visualizar todos os produtos ===
 
 
 
O formato de apresentação de cada tipo de produto é o seguinte:
 
 
 
BOX|''idProduto''|''idFornecedor''|''preço''|''valor-crítico''|''stock-actual''|''tipo-de-serviço''
 
CONTAINER|''idProduto''|''idFornecedor''|''preço''|''valor-crítico''|''stock-actual''|''tipo-de-serviço''|''nível-de-serviço''
 
BOOK|''idProduto''|''idFornecedor''|''preço''|''valor-crítico''|''stock-actual''|''título''|''autor''|''isbn''
 
 
 
=== Registar caixa ===
 
 
 
O sistema pede o identificador que ficará associado ao produto.
 
 
 
O sistema pede o tipo de serviço de transporte associado ('''requestServiceType()'''). A resposta deve ser '''NORMAL''', '''AIR''', '''EXPRESS''' ou '''PERSONAL'''. Se for dada outra resposta, deve ser lançada a excepção '''UnknownServiceTypeException''', não se registando o produto.
 
 
 
São também pedidos o preço ('''requestPrice()'''), o valor crítico ('''requestStockCriticalLevel()''') e o identificador do fornecedor ('''requestSupplierKey()'''). Se o fornecedor não existir, deve ser lançada a excepção '''UnknownSupplierKeyException''', não se registando o produto.
 
 
 
Imediatamente após o registo, o número de existências é zero.
 
 
 
=== Registar contentor ===
 
 
 
O sistema pede o identificador que ficará associado ao produto.
 
 
 
O sistema pede o tipo de serviço de transporte associado ('''requestServiceType()'''). A resposta deve ser '''NORMAL''', '''AIR''', '''EXPRESS''' ou '''PERSONAL'''. Se for dada outra resposta, deve ser lançada a excepção '''UnknownServiceTypeException''', não se registando o produto.
 
 
 
De seguida, é pedida a qualidade de serviço ('''requestServiceLevel()'''): a resposta deve ser '''B4''', '''C4''', '''C5''' ou '''DL'''. Se for dada outra resposta, deve ser lançada a excepção '''UnknownServiceLevelException''', não se registando o produto.
 
 
 
São também pedidos o preço ('''requestPrice()'''), o valor crítico ('''requestStockCriticalLevel()''') e o identificador do fornecedor ('''requestSupplierKey()'''). Se o fornecedor não existir, deve ser lançada a excepção '''UnknownSupplierKeyException''', não se registando o produto.
 
 
 
Imediatamente após o registo, o número de existências é zero.
 
 
 
=== Registar livro ===
 
 
 
O sistema pede o identificador que ficará associado ao produto.
 
 
 
Para registar um livro, o sistema pede o título ('''requestBookTitle()'''), o autor ('''requestBookAuthor()''') e o ISBN ('''requestISBN()''').
 
 
 
São também pedidos o preço ('''requestPrice()'''), o valor crítico ('''requestStockCriticalLevel()''') e o identificador do fornecedor ('''requestSupplierKey()'''). Se o fornecedor não existir, deve ser lançada a excepção '''UnknownSupplierKeyException''', não se registando o produto.
 
 
 
Imediatamente após o registo, o número de existências é zero.
 
 
 
=== Alterar preço de produto ===
 
 
 
O sistema pede o identificador do produto e o novo preço ('''requestPrice()'''). Em caso de erro, o preço não é alterado.
 
 
 
Tal como mencionado acima, os clientes podem ser notificados quando o preço de um produto varia. Quando o processo de alteração de preço termina, o sistema apresenta o número de clientes que foram efectivamente notificados.
 
 
 
== Menu de Gestão de Clientes ==
 
 
 
Este menu permite efectuar operações sobre a base de dados de clientes. A lista completa é a seguinte: [[#Mostrar clientes|Mostrar clientes]], [[#Registar cliente|Registar cliente]], [[#Activar/desactivar notificações de um produto|Activar/desactivar notificações de um produto]], [[#Mostrar transacções do cliente|Mostrar transacções do cliente]].
 
 
 
As etiquetas das opções deste menu estão definidas na classe '''woo.app.clientes.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''woo.app.clientes.Message'''.
 
 
 
Sempre que for pedido o identificador de um cliente ('''requestClientKey()''') e o cliente não existir, é lançada a excepção '''UnknownClientKeyException''' (excepto no processo de registo).
 
 
 
{{CVSCode|Estes comandos já estão implementados  nas classes da ''package'' '''woo.app.clients''' (disponível no CVS), respectivamente: '''DoShowAllClients''', '''DoRegisterClient''', '''DoToggleProductNotifications'''<!--, '''DoToggleNotifications'''-->, '''DoShowClientTransactions'''.}}
 
 
 
=== Mostrar clientes ===
 
 
 
O formato de apresentação é o seguinte (o valor das compras efectuadas refere-se ao momento da compra; o valor das compras
 
pagas refere-se ao valor realmente pago):
 
 
 
''id''|''nome''|''endereço''|''valor-compras-efectuadas''|''valor-compras-pagas''
 
<!--
 
''id''|''nome''|''endereço''|''activo?''|''notificações?''|''valor-compras-efectuadas''|''valor-compras-pagas''
 
 
 
Os valores para os campos ''activo?'' e ''notificações?'' são '''SIM''' ou '''NÃO'''.
 
-->
 
 
 
=== Registar cliente ===
 
 
 
O sistema pede o identificador do cliente, o nome ('''requestClientName()''') (cadeia de caracteres) e o endereço do cliente ('''requestClientAddress()''') (cadeia de caracteres) e regista-se o novo cliente. Quando um cliente é registado, aceita notificações relativas a todos os produtos.
 
 
 
Se já existir um cliente com o mesmo identificador, deve ser lançada a excepção '''DuplicateClientKeyException''', não se realizando o registo.
 
 
 
=== Activar/desactivar notificações de um produto ===
 
 
 
O sistema pede o identificador do cliente e o identificador do produto ('''requestProductKey()'''). Se as notificações relativas ao produto estavam activas, passam a estar inactivas, e vice-versa. É apresentada na saída o resultado da operação: '''notificationsOn()''' ou '''notificationsOff()'''.
 
 
 
=== Mostrar transacções do cliente ===
 
 
 
O sistema pede o identificador do cliente e apresenta todas as transacções por ele realizadas. O formato de apresentação é como descrito abaixo (visualização de transacções de venda).
 
 
 
== Menu de Gestão de Fornecedores ==
 
 
 
Este menu apresenta as operações disponíveis sobre fornecedores e assuntos relacionados. A lista completa é a seguinte: [[#Mostrar fornecedores|Mostrar fornecedores]], [[#Registar fornecedor|Registar fornecedor]], [[#Permitir/Inibir transacções|Permitir/Inibir transacções]], [[#Mostrar transacções do fornecedor|Mostrar transacções do fornecedor]].
 
 
 
As etiquetas das opções deste menu estão definidas na classe '''woo.app.suppliers.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''woo.app.suppliers.Message'''.
 
 
 
Sempre que é pedido o identificador da fornecedor ('''requestSupplierKey()'''), é lançada a excepção '''UnknownSupplierKeyException''', se o fornecedor indicado não existir.
 
 
 
{{CVSCode|Estes comandos já estão implementados  nas classes da ''package'' '''woo.app.suppliers''' (disponível no CVS), respectivamente: '''DoShowSuppliers''', '''DoRegisterSupplier''', '''DoToggleTransactions''', '''DoShowSupplierTransactions'''.}}
 
 
 
=== Mostrar fornecedores ===
 
 
 
O formato de apresentação é o seguinte:
 
 
 
''id''|''nome''|''endereço''|''activo?''
 
 
 
Os valores para o campo ''activo?'' são '''SIM''' ou '''NÃO'''.
 
 
 
=== Registar fornecedor ===
 
 
 
O sistema pede o identificador do fornecedor, o nome ('''requestSupplierName()''') (cadeia de caracteres) e o endereço ('''requestSupplierAddress()''') (cadeia de caracteres), registando-se o novo fornecedor. Quando um fornecedor é registado, fica no estado activo.
 
 
 
Se já existir um fornecedor com o mesmo identificador, deve ser lançada a excepção '''DuplicateSupplierKeyException''', não se realizando qualquer acção.
 
 
 
=== Permitir/Inibir transacções ===
 
 
 
O sistema pede o identificador do fornecedor. Se as transacções estavam activas, passam a estar inactivas, e vice-versa. É apresentada na saída o resultado da operação: '''transactionsOn()''' ou '''transactionsOff()'''.
 
 
 
=== Mostrar transacções do fornecedor ===
 
 
 
O sistema pede o identificador do fornecedor e apresenta todas as transacções por ele realizadas. O formato de apresentação é como descrito abaixo.
 
 
 
== Menu de Gestão de Transacções ==
 
Este menu apresenta as operações relacionadas com transacções. A lista completa é a seguinte: [[#Visualizar|Visualizar]], [[#Registar Venda|Registar Venda]], [[#Registar Encomenda|Registar Encomenda]], [[#Pagar|Pagar]].
 
 
 
As etiquetas das opções deste menu estão definidas na classe '''woo.app.transactions.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''woo.app.transactions.Message'''.
 
 
 
Sempre que é pedido o identificador do fornecedor ('''requestSupplierKey()'''), é lançada a excepção '''UnknownSupplierKeyException''', se o fornecedor indicado não existir. Sempre que é pedido o identificador do cliente ('''requestClientKey()'''), é lançada a excepção '''UnknownClientKeyException''', se o cliente indicado não existir. Sempre que é pedido o identificador de produto ('''requestProductKey()'''), é lançada a excepção '''UnknownProductKeyException''', se o produto indicado não existir. Sempre que é pedido o identificador da transacção ('''requestTransactionKey()'''), é lançada a excepção '''UnknownTransactionKeyException''', se a transacção indicada não existir.
 
 
 
{{CVSCode|Estes comandos já estão implementados  nas classes da ''package'' '''woo.app.transactions''' (disponível no CVS), respectivamente: '''DoShowTransaction''', '''DoRegisterSaleTransaction''', '''DoRegisterOrderTransaction''', '''DoPay'''.}}
 
 
 
=== Visualizar ===
 
 
 
O sistema pede o identificador da transacção a visualizar.
 
 
 
Nas apresentações, o campo ''valor-base'' é o valor da transacção sem descontos/penalizações e os valores para o campo ''paga?'' são '''SIM''' ou '''NÃO'''.
 
 
 
Se a transacção for respeitante a uma venda a um cliente, apresenta-a com o seguinte formato:
 
 
 
''id''|''idCliente''|''idProduto''|''quantidade''|''valor-base''|''valor-a-pagamento''|''data-limite''|''paga?''|''data-pagamento''
 
 
 
''valor-a-pagamento'' corresponde ao valor que será realmente pago (considerando possíveis descontos/penallzações).
 
 
 
Se a transacção corresponder a uma encomenda a um fornecedor, apresenta-a com um cabeçalho (linha inicial):
 
 
 
''id''|''idFornecedor''|''valor-base''|''data-pagamento''
 
 
 
A linha inicial é seguida de várias linhas, cada uma com a descrição de cada produto incluído na encomenda:
 
 
 
''idProduto''|''quantidade''
 
 
 
=== Registar Venda ===
 
 
 
Para registar uma venda, é pedido o identificador da venda, o identificador do cliente, a data limite para o pagamento ('''requestDate()'''), o identificador do produto a vender e a respectiva quantidade ('''requestAmount()'''). Se a quantidade for superior às existências actuais, deve ser apresentada a mensagem '''unavailable()''' (não se realiza a venda).
 
 
 
A actualização dos produtos da empresa tem lugar logo após o registo da venda, ou seja, considera-se que a venda é instantânea.
 
 
 
Tal como mencionado acima, os fornecedores são notificados quando um produto atinge o nível crítico. Quando o processo de registo de uma venda termina, o sistema apresenta o número de fornecedores que foram efectivamente notificados (fornecedores inibidos, embora notificáveis, não devem ser contabilizados).
 
 
 
=== Registar Encomenda ===
 
 
 
Para registar uma encomenda, é pedido o identificador da factura e o identificador do fornecedor. Se o fornecedor estiver inibido de efectuar transacções, deve ser apresentada a mensagem '''unauthorizedSupplier()'''. Caso contrário, é pedido o identificador do produto a encomendar e a quantidade a encomendar ('''requestAmount()''').
 
Estas duas perguntas são repetidas para outros produtos enquanto a resposta a '''requestMore()''' (pergunta feita depois de cada quantidade) for afirmativa (leitura de um booleano).
 
 
 
A actualização dos produtos da empresa tem lugar logo após o registo da encomenda, ou seja, considera-se que a encomenda é instantânea.
 
 
 
Assume-se que a encomenda é paga a pronto.
 
 
 
=== Pagar ===
 
 
 
O sistema pede o identificador da venda a pagar. Se a venda já tiver sido paga, não é realizada nenhuma acção.
 
 
 
== Menu de Consultas ==
 
 
 
Este menu apresenta as operações relacionadas com consultas. A lista completa é a seguinte: [[#Procurar produtos com preço abaixo de limite|Procurar produtos com preço abaixo de limite]], [[#Procurar produtos comprados por cliente|Procurar produtos comprados por cliente]], [[#Procurar clientes que compram produto|Procurar clientes que compram produto]], [[#Procurar facturas pagas por cliente|Procurar facturas pagas por cliente]], [[#Procurar facturas pagas com atraso|Procurar facturas pagas com atraso]].
 
 
 
As etiquetas das opções deste menu estão definidas na classe '''woo.app.lookups.Label'''. Todos os métodos correspondentes às mensagens de diálogo para este menu estão definidos na classe '''woo.app.lookups.Message'''.
 
 
 
Sempre que é pedido o identificador do cliente ('''requestClientKey()'''), é lançada a excepção '''UnknownClientKeyException''', se o cliente indicado não existir. Sempre que é pedido o identificador de produto ('''requestProductKey()'''), é lançada a excepção '''UnknownProductKeyException''', se o produto indicado não existir.
 
 
 
A apresentação de resultados é como indicado nos casos já descritos de apresentação das várias entidades.
 
 
 
{{CVSCode|Estes comandos já estão parcialmente implementados  nas classes da ''package'' '''woo.app.lookups''' (disponível no CVS), respectivamente: '''DoLookupProductsBoughtByClient''', '''DoLookupClientsBuyingProduct''', '''DoLookupPaymentsByClient''', '''DoLookupLatePayments'''.}}
 
 
 
=== Procurar produtos com preço abaixo de limite ===
 
 
 
O sistema pede o valor pretendido ('''requestPriceLimit()'''), apresentando os produtos relevantes.
 
 
 
=== Procurar produtos comprados por cliente ===
 
 
 
O sistema pede o código do cliente, apresentando os produtos relevantes.
 
 
 
=== Procurar clientes que compram produto ===
 
 
 
O sistema pede o código do produto, apresentando os clientes relevantes.
 
 
 
=== Procurar facturas pagas por cliente ===
 
 
 
O sistema pede o código do cliente, apresentando as facturas pagas por ele.
 
 
 
=== Procurar facturas pagas com atraso ===
 
 
 
O sistema pede o atraso pretendido ('''requestDelay()'''), apresentando as facturas que foram pagas com, pelo menos, o atraso especificado.
 
 
 
= Leitura de Dados a Partir de Ficheiros Textuais =
 
 
Além das opções de manipulação de ficheiros descritas no [[#Salvaguarda do Documento Actual|menu principal]], é possível iniciar a aplicação com um ficheiro de texto especificado pela propriedade Java '''[[#Execução dos Programas e Testes Automáticos|import]]'''.
 
 
 
As várias entidades têm os formatos descritos abaixo. Assume-se que os títulos não podem conter o carácter '''|''' e que o preço é um número inteiro (sugere-se a utilização do método '''String.split''' para o processamento preliminar destas linhas). Não existem entradas mal-formadas.
 
 
 
Cada linha tem uma descrição distinta mas que segue os seguintes formatos.
 
 
 
BOX|''id''|''tipo-de-serviço''|''nome-fornecedor''|''preço''|''valor-crítico''|''exemplares''
 
CONTAINER|''id''|''tipo-de-serviço''|''nível-de-serviço''|''nome-fornecedor''|''preço''|''valor-crítico''|''exemplares''
 
 
 
BOOK|''id''|''título''|''autor''|''isbn''|''nome-fornecedor''|''preço''|''valor-crítico''|''exemplares''
 
 
 
É ainda possível definir fornecedores e clientes, de acordo com os seguintes formatos:
 
 
 
SUPPLIER|''id''|''nome''|''endereço''
 
CLIENT|''id''|''nome''|''endereço''
 
 
 
Um exemplo de conteúdo do ficheiro inicial é como se segue:
 
 
 
{{CollapsedCode|Exemplo de ficheiro de entrada textual|
 
<source lang="text">
 
SUPPLIER|S1|Toshiba|Tokyo, Japan
 
SUPPLIER|W2|Papelaria Fernandes|Oeiras, Portugal
 
SUPPLIER|P1|Publicações Europa-Am´erica|Lisboa, Portugal
 
SUPPLIER|P3|O’Reilly|Köln, Germany
 
CLIENT|R2|Jorge Figueiredo|Lisboa, Portugal
 
CLIENT|E4|Filomena Figueiredo|Lisboa, Portugal
 
CLIENT|ER|Abdul Figueiredo|Casablanca, Morocco
 
CLIENT|O9|Hellen Figueiredo|San Francisco, CA, USA
 
CLIENT|H2SO4|John Figueiredo|Wellington, New Zealand
 
CLIENT|H2O|Rohit Figueiredo|New Delhi, India
 
BOX|C6H5OH|NORMAL|Papelaria Fernandes|2|20|100
 
BOX|H2|AIR|Papelaria Fernandes|4|20|100
 
BOX|O3|EXPRESS|Papelaria Fernandes|8|20|100
 
BOX|CO2|PERSONAL|Papelaria Fernandes|16|20|0
 
CONTAINER|M4|NORMAL|B4|Papelaria Fernandes|2|20|100
 
CONTAINER|M2|AIR|C4|Papelaria Fernandes|4|20|100
 
CONTAINER|M5|EXPRESS|B4|Papelaria Fernandes|8|20|100
 
CONTAINER|M3|PERSONAL|DL|Papelaria Fernandes|16|20|0
 
BOOK|B1256|Os Lusíadas|Luís de Camões|1234567890|Publicações Europa-América|58|2|5
 
BOOK|B9854|Head First Java|Sierra & Bates|9876543210|O’Reilly|75|2|5
 
BOOK|B1937|How to fix almost everything|Satoshi Yamada|1928374650|Toshiba|5|2|5
 
</source>
 
}}
 
A codificação dos ficheiros a ler é garantidamente [[wp:UTF-8|UTF-8]].
 
 
 
{{Suggestion|Note-se que o programa nunca produz ficheiros com este formato.}}
 
 
 
= Execução dos Programas e Testes Automáticos =
 
 
 
Usando os ficheiros '''test.import''', '''test.in''' e '''test.out''', é possível verificar automaticamente o resultado correcto do programa. Note-se que é necessária a definição apropriada da variável '''CLASSPATH''' (ou da opção equivalente '''-cp''' do comando '''java'''), para localizar as classes do programa, incluindo a que contém o método correspondente ao ponto de entrada da aplicação ('''woo.app.App.main'''). As propriedades são tratadas automaticamente pelo código de apoio.
 
 
 
        java -Dimport=test.import -Din=test.in -Dout=test.outhyp woo.app.App
 
 
 
Assumindo que aqueles ficheiros estão no directório onde é dado o comando de execução, o programa produz o ficheiro de saída '''test.outhyp'''. Em caso de sucesso, os ficheiros das saídas esperada ('''test.out''') e obtida ('''test.outhyp''') devem ser iguais. A comparação pode ser feita com o comando:
 
 
 
        diff -b test.out test.outhyp
 
 
 
Este comando não deve produzir qualquer resultado quando os ficheiros são iguais. Note-se, contudo, que este teste não garante o correcto funcionamento do código desenvolvido, apenas verificando alguns aspectos da sua funcionalidade.
 
 
 
= Notas de Implementação =
 
 
 
Tal como indicado acima, algumas classes fornecidas como [[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.
 
 
 
A serialização Java usa as classes da ''package'' '''[https://docs.oracle.com/javase/8/docs/api/java/io/package-summary.html java.io]''', em particular, a interface '''[https://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html java.io.Serializable]''' e as classes de leitura '''[https://docs.oracle.com/javase/8/docs/api/java/io/ObjectInputStream.html java.io.ObjectInputStream]''' e escrita '''[https://docs.oracle.com/javase/8/docs/api/java/io/ObjectOutputStream.html java.io.ObjectOutputStream]''' (entre outras).
 
<!--
 
A representação e manipulação de datas e tempos deve ser realizada através das classes da ''package'' '''[https://docs.oracle.com/javase/8/docs/api/java/time/package-summary.html java.time]''', em particular, através das classes '''[https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html java.time.LocalDate]''' e '''[https://docs.oracle.com/javase/8/docs/api/java/time/LocalTime.html java.time.LocalTime]'''. Diferenças entre tempos são representadas pela classe '''[https://docs.oracle.com/javase/8/docs/api/java/time/Duration.html java.time.Duration]'''.
 
-->
 
<!--
 
[[category:Ensino]]
 
[[category:PO]]
 
[[category:Projecto de PO]]
 
[[en:Object-Oriented Programming]]
 
-->
 

Latest revision as of 16:42, 3 October 2020

(enunciado publicado)