|
|
(79 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").
| |
− | | |
− | Um cliente não pode ser removido, sendo sempre possı́vel aceder a todo o historial de 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.
| |
− | | |
− | Um fornecedor não pode ser removido, sendo sempre possı́vel aceder a todo o historial de transacções. Um fornecedor inactivo não pode realizar transacções nem recebe notificações.
| |
− | | |
− | == Propriedades e Funcionalidade das Transacções ==
| |
− | | |
− | Existem dois tipos de transacção: vendas e encomendas. As transacções são caracterizados pelo respectivo número (inteiro) e pela data limite de pagamento.
| |
− | | |
− | As encomendas da empresa a fornecedores podem ser de produtos individuais ou de vários produtos (idem para múltiplos exemplares de um item). Cada encomenda possui informação acerca do valor total.
| |
− | | |
− | Para as vendas, são considerados os seguintes perı́odos:
| |
− | * Até 5 dias antes do limite de pagamento ('''data_limite_de_pagamento − data_actual ≥ 5'''): sem penalização (transacções não pagas); desconto de 10%;
| |
− | * Até à data limite ('''0 ≤ data_limite_de_pagamento − data_actual < 5'''): sem penalização (transacções não pagas); sem desconto;
| |
− | * Até 5 dias depois da data limite ('''1 < data_actual − data_limite_de_pagamento ≤ 5'''): multa de 5% por cada dia de atraso; sem desconto.
| |
− | * Após 5 dias depois da data limite ('''data_actual − data_limite_de_pagamento > 5'''): multa de 10% por cada dia de atraso; sem desconto.
| |
− | | |
− | == Notificações ==
| |
− | | |
− | Quando se registar um novo produto, os clientes ficam imediatamente como o entidades interessadas em receber notificações sobre eventos a ele associado. O cliente pode, mais tarde, activar ou desactivar as notificações. O cliente recebe ainda notificações quando o produto passar de stock 0 (zero) para outro valor (durante uma encomenda). Outras situações de notificação devem ser consideradas, nomeadamente a alteração de preço de um produto. As notificações são compostas pela cadeia de caracteres constituı́da pela identificação do cliente e pela identificação do produto, 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. Por omissão, as notificações são simplesmente apresentadas 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. Estas notificações não podem ser inibidas, mas não devem produzir efeitos se o fornecedor estiver inactivo. As notificações são compostas pela cadeia de caracteres constituı́da pela identificação do fornecedor e pela identificação do produto, 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 facturas (vandas) por clientes.
| |
− | | |
− | A contabilização de pontos é realizada quando se paga a factura, correspondendo 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 facturas 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 facturas, é despromovido: um cliente '''Elite''' passa a '''Selection''' se tiver facturas com um atraso de pagamento superior a 15 dias (perde 75% dos pontos acumulados); um cliente '''Selection''' passa a '''Normal''' se tiver facturas com um atraso de pagamento superior a 2 dias (perde 90% dos pontos acumulados).
| |
− | | |
− | == 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 modos de entrega de mensagens;
| |
− | * 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.-->
| |
− | | |
− | {{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]].
| |
− | | |
− | = 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.
| |
− | | |
− | === 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 o valor inteiro correspondente ao saldo da empresa. Embora internamente o valor do saldo 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 ('''requestProductId()''') e o produto não existir, é lançada a excepção '''NoSuchProductException''' (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''', '''DoRegisterBox''', '''DoRegisterContainer''', '''DoRegisterBook''', '''DoChangePrice'''.}}
| |
− | | |
− | === Visualizar todos os produtos ===
| |
− | | |
− | O formato de apresentação de cada tipo de produto é o seguinte:
| |
− | | |
− | BOX|''id''|''tipo''|''idFornecedor''|''preço''|''valor-crítico''|''current-stock''
| |
− | CONTAINER|''id''|''tipo''|''formato''|''idFornecedor''|''preço''|''valor-crítico''|''current-stock''
| |
− | BOOK|''id''|''título''|''autor''|''isbn''|''idFornecedor''|''preço''|''valor-crítico''|''current-stock''
| |
− | | |
− | === 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 ('''requestSupplierId()'''). 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 ('''requestSupplierId()'''). 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 ('''requestSupplierId()'''). 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 cliente|Activar/desactivar cliente]], [[#Autorizar/inibir notificações|Autorizar/inibir notificações]], [[#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 ('''requestClientId()''') e o cliente não existir, é lançada a excepção '''NoSuchClientException''' (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. Se já existir um cliente com o mesmo identificador, deve ser apresentada a mensagem '''duplicateClient()''', não se realizando qualquer acção. Caso contrário, pede-se o nome ('''requestName()''') (cadeia de caracteres) e o endereço do cliente ('''requestAddress()''') (cadeia de caracteres) e cria-se e regista-se o novo cliente. Quando um cliente é registado, fica no estado activo e aceita notificações.
| |
− | | |
− | === Activar/desactivar notificações de um produto ===
| |
− | | |
− | O sistema pede o identificador do cliente e a confirmação de mudança de estado: '''disableNotifications()''', para deixar de receber notificações; '''enableNotifications()''', para passar a receber notificações.
| |
− | | |
− | A resposta é um valor booleano. A acção é realizada apenas em caso de resposta afirmativa.
| |
− | | |
− | === 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]], [[#Consultar transacções|Consultar transacções]].
| |
− | | |
− | 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 ('''requestSupplierId()'''), é lançada a excepção '''NoSuchSupplierException''', 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''', '''DoLookupTransactions'''.}}
| |
− | | |
− | === 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. Se já existir um fornecedor com o mesmo identificador, deve ser apresentada a mensagem '''duplicateSupplier()''', não se realizando qualquer acção. Caso contrário, pede-se o nome ('''requestName()''') (cadeia de caracteres) e o endereço do fornecedor ('''requestAddress()''') (cadeia de caracteres) e cria-se e regista-se o novo fornecedor. Quando um fornecedor é registado, fica no estado activo.
| |
− | | |
− | === Permitir/Inibir transacções ===
| |
− | | |
− | O sistema pede o identificador do fornecedor e a confirmação de mudança de estado: '''confirmDeactivation()''', na passagem de activo
| |
− | a inactivo; '''confirmActivation()''', na passagem de inactivo a activo.
| |
− | | |
− | A resposta corresponde à leitura de um valor booleano. A acção é realizada apenas em caso de resposta afirmativa.
| |
− | | |
− | === Consultar transacções ===
| |
− | | |
− | 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 ('''requestSupplierId()'''), é lançada a excepção '''NoSuchSupplierException''', se o fornecedor indicado não existir. Sempre que é pedido o identificador do cliente ('''requestClientId()'''), é lançada a excepção '''NoSuchClientException''', se o cliente indicado não existir. Sempre que é pedido o identificador de produto ('''requestProductId()'''), é lançada a excepção '''NoSuchProductException''', se o produto indicado não existir. Sempre que é pedido o identificador da transacção ('''requestTransactionId()'''), é lançada a excepção '''NoSuchTransactionException''', 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 factura a visualizar.
| |
− | | |
− | Nas apresentações, o campo ''valor-base'' é o valor da factura sem descontos nem penalizações e os valores para o campo ''paga?'' são '''SIM''' ou '''NÃO'''.
| |
− | | |
− | Se a factura for respeitante a uma venda a um cliente, apresenta-a com o seguinte formato:
| |
− | | |
− | ''idFactura''|''idCliente''|''idProduto''|''quantidade''|''valor-base''|''data-limite''|''paga?''|''data-pagamento''
| |
− | | |
− | Se a factura corresponder a uma encomenda a um fornecedor, apresenta-a com um cabeçalho (linha inicial):
| |
− | | |
− | ''idFactura''|''idFornecedor''|''valor-base''|''data-limite''|''paga?''|''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''
| |
− | | |
− | Se uma factura ainda não foi paga, o últmo separador ('''|''') e a ''data-pagamento'' são omitidos.
| |
− | | |
− | === Registar Venda ===
| |
− | | |
− | Para registar uma venda, é pedido o identificador da venda e o identificador do cliente. Se o cliente estiver inibido de efectuar transacçõees, deve ser apresentada a mensagem '''unauthorizedClient()'''. Caso contrário, é pedida a data limite para o pagamento ('''requestDate()''') e o identificador do produto a vender. Se o produto especificado tiver as vendas inibidas, deve ser apresentada a mensagem '''unauthorizedProduct()'''. Caso contrário, é pedida a quantidade vendida ('''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 ('''requestClientId()'''), é lançada a excepção '''NoSuchClientException''', se o cliente indicado não existir. Sempre que é pedido o identificador de produto ('''requestProductId()'''), é lançada a excepção '''NoSuchProductException''', 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''|''nome-fornecedor''|''preço''|''valor-crítico''|''exemplares''
| |
− | CONTAINER|''id''|''tipo''|''formato''|''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|Publicac¸˜oes Europa-Am´erica|Lisboa, Portugal
| |
− | SUPPLIER|P3|O’Reilly|K¨oln, 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]]
| |
− | -->
| |