I have the following script:
from collections import defaultdict
class OrderLine:
def __init__(self, shop_id, qty, price):
self.shop_id = shop_id
self.qty = qty
self.price = price
order_lines = [OrderLine(1, 2, 30), OrderLine(1, 1, 50), OrderLine(3, 3, 10)]
shop_sum = defaultdict(int)
for order_line in order_lines:
print order_line.price
print order_line.qty
print order_line.shop_id
each line consists of (shop_id, qty, price) I want to loop for this shop_sum to give me for each shop_id:
total_price = qty * price
example: I have shop ids (1,3) , in shop_id =1
I have two order lines [OrderLine(1, 2, 30), OrderLine(1, 1, 50)]
I want to calculate the total price for all order lines which has the same shop_id where: total_price = qty * price
Thanks in advance
You can populate your dictionary shop_sum using the code snippet below. The if statement checks if the shop_id has already exist in the dictionary shop_sum and initialises it to zero. The logic after the if performs the actual sum. You can write this code more elegantly using list comprehension, you may want to read up on this.
from collections import defaultdict
class OrderLine:
def __init__(self, shop_id, qty, price):
self.shop_id = shop_id
self.qty = qty
self.price = price
order_lines = [OrderLine(1, 2, 30), OrderLine(1, 1, 50), OrderLine(3, 3, 10)]
shop_sum = defaultdict(int)
for order_line in order_lines:
shop_id = order_line.shop_id
if shop_id not in shop_sum:
shop_sum[shop_id]=0
shop_sum[shop_id] = shop_sum[shop_id] + order_line.qty * order_line.price
print order_line.price
print order_line.qty
print order_line.shop_id
Related
Hello I am trying to create the table below by using list. The product s and the prices are already in lists (priceList and productList). i have successfully created new more list where the person types in the product code and quantity (quan_inputed).
Any help would be greatly appreciated as I don't know what to do. I have tried several methods already and this is the closest I've come to getting multiple inputs at once.
Thank you
Try This:
def add_item():
code_inputed = []
quan_inputed = []
while True:
i = input("enter code: ")
if i != "END":
q = input("enter quantity: ")
code_inputed.append(int(i))
quan_inputed.append(int(q))
else:
break
return code_inputed,quan_inputed
def showRecord(code_inputed, quan_inputed):
product_info = {}
for kk in range(len(code_inputed)):
quan = quan_inputed[kk]
kk = code_inputed[kk]
price = priceList[kk]
product = productList[kk]
if kk not in product_info:
product_info[kk] = [kk, quan, price, product]
else:
product_info[kk][1] += quan
product_info[kk][2] = product_info[kk][1] * price
for x in ["Code", "Quanity", "Price", "Product"]:
print(x, end=" ")
print()
for x in product_info:
for info in product_info[x]:
print(info, end=" ")
print()
code_inputed, quan_inputed = add_item()
showRecord(code_inputed, quan_inputed)
Just to explain my comment about the other approach, I recommend storing the data in other way than just in multiple lists. For example like this:
items = [
{'code': 2, 'price': 39.95, 'quantity': 11, 'product': "Tea Set\t\t"},
{'code': 34, 'price': 19.95, 'quantity': 3, 'product': "Citrus Cather"}
]
print("Code\tProduct\t\t\tPrice $\tQuantinty\tCost $")
print("------------------------------------------------------")
for item in items:
print(f"{item.get('code')}\t\t{item.get('product')}\t{item.get('price')}\t{item.get('quantity')}\t\t\t{item.get('price') * item.get('quantity')}")
Those tabs (\t) in product name in dictionary are just to make the table nice, you should come up with nicer way to print it...
Result:
product_dict = {"Jeans": 150, "Jacket": 300, "Perfume": 50, "Wallet": 125, "Glasses": 100}
#product dictonary with prices
order_history = {'Andrew':[{'Jeans':2, 'Wallet': 4}, {'Perfume':2}], 'Max':[{'Jacket': 3}]}
c_name = input('customer name: ')
print('The following is order history of, c_name')
key = order_history['c_name']
for i in range(len(key)):
print('purchase', i+1, key[i])
I am creating a retail check out program, I have a predefined products stored in a dictionary along with prices that I use in other part of program, I wanted to print the output in a more presentable like this:
This is the order history of Andrew.
Jeans Wallet Perfume Jacket
Purchase 1: 2 4
Purchase 2: 2
This is more of a console display issue rather than a python issue.
You could potentially use a library for this, such as Textualize/rich. I don't want to give you the full answer, just lead you in the right direction as it appears you are learning:
from rich.console import Console
from rich.table import Table
console = Console()
table = Table(show_header=True, header_style="bold magenta")
table.add_column("Jeans", style="dim", width=12)
table.add_column("Jacket")
table.add_column("Perfume", justify="right")
table.add_column("Wallet", justify="right")
#add more columns as necessary
#iterate over your order history to add rows
table.add_row(
)
console.print(table)
In my opinion, creating a table in the console would look best.
Use a nested loop to print the quantity of each item, by looping over the keys of product_dict. Use end='' to print all the quantities on the same line, and use fixed-width fields in the formatting string to make everything line up.
product_dict = {"Jeans": 150, "Jacket": 300, "Perfume": 50, "Wallet": 125, "Glasses": 100}
#product dictonary with prices
order_history = {'Andrew':[{'Jeans':2, 'Wallet': 4}, {'Perfume':2}], 'Max':[{'Jacket': 3}]}
c_name = 'Andrew'
print(f'The following is order history of {c_name}')
print(' ' * 12, end='')
for product in product_dict:
print(f'{product:10}', end='')
print()
key = order_history[c_name]
for i, items in enumerate(key, 1):
print(f'Purchase {i}: ', end='')
for product in product_dict:
if product in items:
print(f'{items[product]:<10}', end='')
else:
print(' ' * 10, end='')
print()
If you want to accommodate additions to your dictionary with arbitrary length product names:
product_dict = {"Jeans": 150, "Jacket": 300, "Perfume": 50, "Wallet": 125, "Glasses": 100}
skus = list(product_dict)
width = 0
for sku in skus:
l = len(sku)
if l > width:
width = l
width = width + 2
pl = len('Purchase XX')
h = ' '.center(pl + 1,' ')
for sku in skus:
h = h + sku.center(width,' ')
#product dictonary with prices
order_history = {'Andrew':[{'Jeans':2, 'Wallet': 4}, {'Perfume':2}], 'Max':[{'Jacket': 3}]}
c_name = input('customer name: ')
print('The following is order history of', c_name)
print(h)
key = order_history[c_name]
for i in range(len(key)):
s = ''
for sku in skus:
if sku in list(key[i]):
s = s + str(key[i][sku]).center(width,' ')
else:
s = s + ' '.center(width,' ')
print('Purchase ' + str(i + 1).rjust(2,' ') + ' ' + s)
You'll get something like this:
The following is order history of Andrew
Jeans Jacket Perfume Wallet Glasses
Purchase 1 2 4
Purchase 2 2
So this may be a very simple thing for most of you but I'm just starting out.
Below is my first ever class:
class WeatherYear:
DEFAULT_MAX = -99
DEFAULT_MIN = 999
DEFAULT_STR = 'DATE'
def __init__(self, year):
self.year = year
self.max_temp = WeatherYear.DEFAULT_MAX
self.min_temp = WeatherYear.DEFAULT_MIN
self.max_temp_date = WeatherYear.DEFAULT_STR
self.max_humid = WeatherYear.DEFAULT_MAX
self.min_humid = WeatherYear.DEFAULT_MIN
def add_day(self, date, max_temp, min_temp, max_humid, min_humid):
if max_temp and max_temp > self.max_temp:
self.max_temp = max_temp
self.max_temp_date = date
if min_temp and min_temp < self.min_temp:
self.min_temp = min_temp
if max_humid and max_humid > self.max_humid:
self.max_humid = max_humid
if min_humid and min_humid < self.min_humid:
self.min_humid = min_humid
And here is some stuff that I used it for:
years_dict = {}
wy_obj = years_dict.get(year)
if not wy_obj:
years_dict[year] = WeatherYear(year)
wy_obj = years_dict[year]
wy_obj.add_day(date, max_temp, min_temp, max_humid, min_humid)
This is part of my code, could someone please explain to me what is happening exactly, also the major part, Do i need to keep year in my __init__ function? What if I remove it? Would it still work the same way?
You should try out the code, that's the best way to understand OOP's concepts in Python.
Coming back to your question, according to your code, you need to have year in your init function else self.year = year would give an year not defined error
Question>: Do i need to keep year in my init function?
No, as you store a date in self.max_temp_date, thats doubled as you can get the year from date using self.max_temp_date.year.
Change your class WetherYear().__init__(... to the following:
def __init__(self, measure):
self.max_temp_date, self.max_temp, self.min_temp, self.max_humid, self.min_humid = measure
Thereby you don't have to initalize the class attributes with dummy values. Set the attributes at once with the first measure values.
About your naming of class methodes, name it to what this function are doing. In this case, you don't add anything you update the class attributs by condition.
def add_day(self, date, max_temp, min_temp, max_humid, min_humid):
if max_temp and max_temp > self.max_temp:
...
You don't have to get(... the WeatherYear object, to test if this year exists. use the key year only. Also you don't have to get it again wy_obj = years_dict[year], you can use it from the dict e.g. years_dict[year].add_day(...
wy_obj = years_dict.get(year)
if not wy_obj:
years_dict[year] = WeatherYear(year)
wy_obj = years_dict[year]
wy_obj.add_day(...
Consider this example:
from datetime import date
class WeatherYear:
def __init__(self, measure):
self.max_temp_date, self.max_temp, self.min_temp, self.max_humid, self.min_humid = measure
def update(self, measure):
if measure[1] > self.max_temp:
self.max_temp_date = measure[0]
self.max_temp = measure[1]
if measure[2] > self.min_temp:
self.min_temp = measure[2]
if measure[3] > self.max_humid:
self.max_humid = measure[3]
if measure[4] > self.min_humid:
self.min_humid = measure[4]
def __str__(self):
return "WeatherYear:In {year} at {self.max_temp_date}, measured a max temperature of {self.max_temp}°C and max humid of {self.max_humid} %".format(self=self, year=self.max_temp_date.year)
def main():
# date, max_temp, min_temp, max_humid, min_humid
measurements = [(date(2018, 9, 10), 20, 8, 40, 30),
(date(2018, 9, 12), 25, 12, 50, 35),
(date(2018, 9, 13), 19, 10, 30, 25)]
max_years = {}
for measure in measurements:
if not measure[0].year in max_years:
max_years[measure[0].year] = WeatherYear(measure)
else:
max_years[measure[0].year].update(measure)
for year in max_years:
print("{}: {}".format(year, max_years[year]))
if __name__ == "__main__":
main()
Output:
2018: WeatherYear:In 2018 at 2018-09-12, measured a max temperature of 25°C, max humid of 50 %
Tested with Python: 3.4.2
I am trying to write a basic store-front script that loops until the customer says no to the question. Each time there's input of an Item Number, I'm trying to store it and then eventually be able to match those numbers up with the Item Name and the Price (not quite yet, though)...
I am just, now, trying to get it to add to the empty list "item_nums" instead of adding the last entry and over-writing the previous numbers.
STOREKEEPER
products = ['Notebook', 'Atari', 'TrapperKeeper', 'Jeans', 'Insects',
'Harbormaster', 'Lobotomy', 'PunkRock', 'HorseFeathers', 'Pants',
'Plants', 'Salami']
prices = ['$4.99', '$99.99', '$89.99', '$3.99', '$2.99', '$299.99',
'$19.99', '$3.99', '$4.99', '$2.99', '$119.99', '$1.99']
SKUs = [1, 2, 3, 4, 5, 6, 7, 8 ,9, 10, 11, 12]
item_nums = ()
quantity = []
response = ''
#MORE VARIABLES AND FUNCTIONS WILL GO HERE
print("Jay's House of Rip-Offs\n\n")
titles = ['Item Number', 'Item Name', 'Price']
data = [titles] + list(zip(SKUs, products, prices))
for i, d in enumerate(data):
line = '|'.join(str(x).ljust(16) for x in d)
print(line)
if i == 0:
print('-' * len(line))
response = str(input("Order products [Y / N]?: "))
while response != 'N':
item_nums = input("Enter an item number: ")
SKUs.append(item_nums)
response = str(input("Order products [Y / N]?: "))
if response == 'N':
break
print("Here is the list of items you ordered: ",item_nums[0])
I'm not sure why you're appending to SKU, you need a new list to track order numbers.
orders = []
while str(input("Order products [Y / N]?: ")) != 'N':
item_nums = input("Enter an item number: ")
orders.append(item_nums)
print("Here is the list of items you ordered: ", orders)
I have a product called "Coupon" with negative amount which is used to offset the product price. However, it seems like Odoo 8 does not allow computation of negative amount to price_subtotal (it becomes 0.00):
Coupon ... ... 1 Each -40.0000 0.0000
When I remove the negative sign, it computes
Coupon ... ... 1 Each 40.0000 40.0000
From an accounting perspective, the total invoice should not be negative. That stays true. However, I do need to allow negative computation of invoice line item(s). Where and what do I need to change? I tried looking into account/account.py but to no avail so far - it's all just "tax" related.
Thanks in advance!
Details of the amount column for the line total
class account_invoice(models.Model)
....
#api.one
#api.depends('invoice_line.price_subtotal', 'tax_line.amount')
def _compute_amount(self):
self.amount_untaxed = sum(line.price_subtotal for line in self.invoice_line)
self.amount_tax = sum(line.amount for line in self.tax_line)
self.amount_total = self.amount_untaxed + self.amount_tax
....
class account_invoice_line(models.Model):
_name = "account.invoice.line"
_description = "Invoice Line"
_order = "invoice_id,sequence,id"
#api.one
#api.depends('price_unit', 'discount', 'invoice_line_tax_id', 'quantity',
'product_id', 'invoice_id.partner_id', 'invoice_id.currency_id')
def _compute_price(self):
price = self.price_unit * (1 - (self.discount or 0.0) / 100.0)
taxes = self.invoice_line_tax_id.compute_all(price, self.quantity, product=self.product_id, partner=self.invoice_id.partner_id)
self.price_subtotal = taxes['total']
if self.invoice_id:
self.price_subtotal = self.invoice_id.currency_id.round(self.price_subtotal)
#api.model
def _default_price_unit(self):
if not self._context.get('check_total'):
return 0
total = self._context['check_total']
for l in self._context.get('invoice_line', []):
if isinstance(l, (list, tuple)) and len(l) >= 3 and l[2]:
vals = l[2]
price = vals.get('price_unit', 0) * (1 - vals.get('discount', 0) / 100.0)
total = total - (price * vals.get('quantity'))
taxes = vals.get('invoice_line_tax_id')
if taxes and len(taxes[0]) >= 3 and taxes[0][2]:
taxes = self.env['account.tax'].browse(taxes[0][2])
tax_res = taxes.compute_all(price, vals.get('quantity'),
product=vals.get('product_id'), partner=self._context.get('partner_id'))
for tax in tax_res['taxes']:
total = total - tax['amount']
return total
Odoo's default behaviour is handling it as expected. The problem is custom code. (For more information read the questions comments)