FP: APx added
This commit is contained in:
parent
4312389d5c
commit
a1e51d50df
|
@ -0,0 +1,57 @@
|
||||||
|
def isLeapYear(year):
|
||||||
|
return year % 400 == 0 if year % 100 == 0 else year % 4 == 0
|
||||||
|
|
||||||
|
|
||||||
|
def monthDays(year, month):
|
||||||
|
assert month > 0
|
||||||
|
|
||||||
|
MONTHDAYS = (0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31)
|
||||||
|
days = MONTHDAYS[month]
|
||||||
|
|
||||||
|
return days + 1 if (isLeapYear(year) and month == 2) else days
|
||||||
|
|
||||||
|
|
||||||
|
def nextDay(year, month, day):
|
||||||
|
if not dateIsValid(year, month, day): return
|
||||||
|
|
||||||
|
# Verifica se é o último dia do ano
|
||||||
|
if (month, day) == (12, 31):
|
||||||
|
year += 1
|
||||||
|
month = 1
|
||||||
|
day = 1
|
||||||
|
|
||||||
|
# Verifica se é o último dia do mês
|
||||||
|
elif (monthDays(year, month) == day):
|
||||||
|
month += 1
|
||||||
|
day = 1
|
||||||
|
|
||||||
|
# Dia comum
|
||||||
|
else:
|
||||||
|
day += 1
|
||||||
|
|
||||||
|
return year, month, day
|
||||||
|
|
||||||
|
|
||||||
|
def dateIsValid(year, month, day):
|
||||||
|
return False if (month > 12 or month <= 0) or (day > monthDays(year, month) or day <= 0) else True
|
||||||
|
|
||||||
|
|
||||||
|
def previousDay(year, month, day):
|
||||||
|
if not dateIsValid(year, month, day): return
|
||||||
|
|
||||||
|
# Primeiro dia do ano
|
||||||
|
if (month, day) == (1, 1):
|
||||||
|
year -= 1
|
||||||
|
month = 12
|
||||||
|
day = 31
|
||||||
|
|
||||||
|
# Primeiro dia do mês (sem ser janeiro)
|
||||||
|
elif day == 1:
|
||||||
|
day = monthDays(year, month - 1)
|
||||||
|
month -= 1
|
||||||
|
|
||||||
|
# Dia comum
|
||||||
|
else:
|
||||||
|
day -= 1
|
||||||
|
|
||||||
|
return year, month, day
|
Binary file not shown.
|
@ -0,0 +1,26 @@
|
||||||
|
CODIGO;NOME;SECCAO;PRECO-BASE;TAXA
|
||||||
|
p1;Ketchup;Mercearia Salgado;1.59;23%
|
||||||
|
p2;Atum;Mercearia Salgado;3.38;6%
|
||||||
|
p3;Cogumelos;Mercearia Salgado;1.98;23%
|
||||||
|
p4;Bolachas Cacau;Mercearia Doce;1.39;23%
|
||||||
|
p5;Cerelac;Mercearia Doce;5.65;6%
|
||||||
|
p6;Heineken 12x25CL;Bebidas;8.99;23%
|
||||||
|
p7;Gel Banho;Higiene;5.99;23%
|
||||||
|
p8;Lencos de Bolso;Limpeza;1.59;23%
|
||||||
|
p9;Jardineira;Congelados;1.99;6%
|
||||||
|
p10;Leite 6x1L;Lacticinios;4.92;6%
|
||||||
|
p11;Natas;Lacticinios;0.79;6%
|
||||||
|
p12;Ovos;Lacticinios;0.94;6%
|
||||||
|
p13;Espadarte Posta;Peixaria;6.49;6%
|
||||||
|
p14;Queijo;Charcutaria;3.89;6%
|
||||||
|
p15;Laranjas;Frutas e Legumes;1.449;6%
|
||||||
|
p16;Ameixa Seca;Frutas e Legumes;2.00;6%
|
||||||
|
p17;Tabuleiro;Casa;7.00;23%
|
||||||
|
p18;Batatas;Frutas e Legumes;17.0;6%
|
||||||
|
p19;Limpa Vidros;Limpeza;3.69;23%
|
||||||
|
p20;Oregaos;Mercearia Salgado;1.42;6%
|
||||||
|
p21;Bolachas Maria;Mercearia Doce;2.39;23%
|
||||||
|
p22;Pedras Salgadas;Bebidas;2.46;13%
|
||||||
|
p23;Detergente Roupa;Limpeza;12.99;23%
|
||||||
|
p24;Pao Aveia;Padaria;1.99;6%
|
||||||
|
p25;Iogurte Grego;Lacticinios;2.59;6%
|
|
@ -0,0 +1,6 @@
|
||||||
|
CODIGO;NOME;SECCAO;PRECO-BASE;TAXA
|
||||||
|
q1;Televisor 43pol;Tecnologia;300.0;23%
|
||||||
|
q2;Computador i7;Tecnologia;500.0;23%
|
||||||
|
q3;Frigorifico;Eletrodomesticos;400.0;23%
|
||||||
|
q4;Forno microondas;Eletrodomesticos;60.0;23%
|
||||||
|
q5;Tinteiro impressora;Consumiveis;10.0;13%
|
|
@ -0,0 +1,124 @@
|
||||||
|
# Pode correr o programa sem argumentos:
|
||||||
|
# python3 shop
|
||||||
|
# ou passando outros ficheiros de produtos como argumento:
|
||||||
|
# python3 shop produtos1.txt ...
|
||||||
|
|
||||||
|
def loadDataBase(fname, produtos):
|
||||||
|
"""Lê dados do ficheiro fname e atualiza/acrescenta a informação num
|
||||||
|
dicionário de produtos com o formato {código: (nome, secção, preço, iva), ...}.
|
||||||
|
"""
|
||||||
|
with open(fname, 'r') as f: # Abre o ficheiro em modo de leitura
|
||||||
|
productsFileContent = f.read() # Cria uma string com o conteudo do ficheiro
|
||||||
|
|
||||||
|
for product in productsFileContent.split('\n')[1:]: # Divide a string 'productsFileContent' numa lista com cada produto
|
||||||
|
productComponents = product.split(';') # Divide as componentes do produto (código, nome, secção, preço, iva)
|
||||||
|
|
||||||
|
if len(productComponents) != 5:
|
||||||
|
continue
|
||||||
|
|
||||||
|
produtos.update({productComponents[0]: ( # Atualiza a entrada de uma determinada chave (código)
|
||||||
|
productComponents[1], # Nome
|
||||||
|
productComponents[2], # Secção
|
||||||
|
float(productComponents[3]), # Preço
|
||||||
|
float(productComponents[4].strip('%')) / 100 # IVA
|
||||||
|
)})
|
||||||
|
|
||||||
|
|
||||||
|
def registaCompra(produtos):
|
||||||
|
"""Lê códigos de produtos (ou códigos e quantidades),
|
||||||
|
mostra nome, quantidade e preço final de cada um,
|
||||||
|
e devolve dicionário com {codigo: quantidade, ...}
|
||||||
|
"""
|
||||||
|
compra = {"totals": [0, 0, 0]} # Inicia o dicionário da compra com os totais da mesma: [total bruto, total iva, total liquido]
|
||||||
|
userInput = input('Code? ')
|
||||||
|
while userInput != "":
|
||||||
|
try:
|
||||||
|
code, amount = userInput.split(' ') # Divide o input do utilizador no código e na quantia
|
||||||
|
except ValueError:
|
||||||
|
code, amount = userInput, 1 # No caso de não ser introduzida quantia, então ela fica 1
|
||||||
|
|
||||||
|
# Caso a segunda parcela da entrada não seja um número, é pedido ao utilizador para introduzir o código de novo
|
||||||
|
try:
|
||||||
|
amount = int(amount)
|
||||||
|
except ValueError:
|
||||||
|
userInput = input('Code? ')
|
||||||
|
continue
|
||||||
|
|
||||||
|
if code in produtos:
|
||||||
|
if code not in compra: # Se o produto ainda não estiver na lista é adicionado à mesma
|
||||||
|
compra[code] = 0
|
||||||
|
|
||||||
|
compra[code] += amount # Adiciona ao dicionário da compra a quantidade comprada do produto
|
||||||
|
noIvaPrice = produtos[code][2] * amount # Obtém o preço (sem iva) do determinado produto
|
||||||
|
compra["totals"][0] += noIvaPrice # Adiciona o preço sem iva ao total bruto
|
||||||
|
compra["totals"][1] += noIvaPrice * produtos[code][3] # Adiciona o valor do iva ao total iva
|
||||||
|
print(f"{produtos[code][0]} {amount} {noIvaPrice * (1+produtos[code][3]):.2f}")
|
||||||
|
|
||||||
|
userInput = input('Code? ')
|
||||||
|
|
||||||
|
compra["totals"][2] += compra["totals"][0] + compra["totals"][1] # Calcula o total liquido da compra
|
||||||
|
return compra # Devolve a lista
|
||||||
|
|
||||||
|
|
||||||
|
def fatura(produtos, compra):
|
||||||
|
"""Imprime a fatura de uma dada compra."""
|
||||||
|
|
||||||
|
# Obtém a lista de secções presentes na compra (por ordem alfabética)
|
||||||
|
sections = sorted(list({section for section in [product[1] for code, product in produtos.items() if code in compra]}))
|
||||||
|
|
||||||
|
# Itera as secções para apresentar os produtos ordenados por secção
|
||||||
|
for section in sections:
|
||||||
|
print(section) # Mostra a secção
|
||||||
|
|
||||||
|
# Obtém a lista de codigos usados na compra presentes na secção atual
|
||||||
|
sectionProductsCodes = sorted([code for code in produtos if produtos[code][1] == section and code in compra])
|
||||||
|
|
||||||
|
# Itera os códigos para apresentar as informações de cada produto
|
||||||
|
for code in sectionProductsCodes:
|
||||||
|
print(f"{compra[code]:>4} {produtos[code][0]:<31}({int(produtos[code][3]*100):>2}%){round(compra[code]*produtos[code][2]*(1+produtos[code][3]), 2):>11}")
|
||||||
|
|
||||||
|
# Apresenta os totais da compra
|
||||||
|
print(f"""{'Total Bruto:':>41}{round(compra["totals"][0], 2):>11}
|
||||||
|
{'Total IVA:':>41}{round(compra["totals"][1], 2):>11}
|
||||||
|
{'Total Liquido:':>41}{round(compra["totals"][2], 2):>11}""")
|
||||||
|
|
||||||
|
|
||||||
|
def main(args):
|
||||||
|
# produtos guarda a informação da base de dados numa forma conveniente.
|
||||||
|
produtos = {'p1': ('Ketchup.', 'Mercearia Salgado', 1.59, 0.23)}
|
||||||
|
# Carregar base de dados principal
|
||||||
|
loadDataBase("produtos.txt", produtos)
|
||||||
|
# Juntar bases de dados opcionais (Não altere)
|
||||||
|
for arg in args:
|
||||||
|
loadDataBase(arg, produtos)
|
||||||
|
|
||||||
|
# Use este código para mostrar o menu e ler a opção repetidamente
|
||||||
|
MENU = "(C)ompra (F)atura (S)air ? "
|
||||||
|
compras = {}
|
||||||
|
repetir = True
|
||||||
|
while repetir:
|
||||||
|
# Utilizador introduz a opção com uma letra minúscula ou maiúscula
|
||||||
|
op = input(MENU).upper()
|
||||||
|
# Processar opção
|
||||||
|
if op == "C":
|
||||||
|
# Esta opção regista os produtos de uma compra
|
||||||
|
compras[len(compras)+1] = registaCompra(produtos)
|
||||||
|
|
||||||
|
elif op == "F":
|
||||||
|
# Esta opção apresenta a fatura de uma compra
|
||||||
|
try:
|
||||||
|
numCompra = int(input("Numero compra? "))
|
||||||
|
fatura(produtos, compras[numCompra])
|
||||||
|
except:
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif op == "S":
|
||||||
|
repetir = False
|
||||||
|
|
||||||
|
print("Obrigado!")
|
||||||
|
|
||||||
|
|
||||||
|
# Não altere este código / Do not change this code
|
||||||
|
import sys
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main(sys.argv[1:])
|
Loading…
Reference in New Issue