|
1 | 1 | from collections import namedtuple |
| 2 | +from decimal import Decimal |
2 | 3 |
|
3 | 4 | Order = namedtuple("Order", "id, items") |
4 | 5 | Item = namedtuple("Item", "type, description, amount, quantity") |
5 | 6 |
|
| 7 | +MAX_ITEM_AMOUNT = 100000 # maximum price of item in the shop |
| 8 | +MAX_QUANTITY = 100 # maximum quantity of an item in the shop |
| 9 | +MIN_QUANTITY = 0 # minimum quantity of an item in the shop |
| 10 | +MAX_TOTAL = 1e6 # maximum total amount accepted for an order |
6 | 11 |
|
7 | | -def validorder(order: Order): |
8 | | - net = 0 |
| 12 | + |
| 13 | +def validorder(order): |
| 14 | + payments = Decimal("0") |
| 15 | + expenses = Decimal("0") |
9 | 16 |
|
10 | 17 | for item in order.items: |
11 | 18 | if item.type == "payment": |
12 | | - net += item.amount |
| 19 | + # Sets a reasonable min & max value for the invoice amounts |
| 20 | + if -MAX_ITEM_AMOUNT <= item.amount <= MAX_ITEM_AMOUNT: |
| 21 | + payments += Decimal(str(item.amount)) |
13 | 22 | elif item.type == "product": |
14 | | - net -= item.amount * item.quantity |
| 23 | + if ( |
| 24 | + type(item.quantity) is int |
| 25 | + and MIN_QUANTITY < item.quantity <= MAX_QUANTITY |
| 26 | + and MIN_QUANTITY < item.amount <= MAX_ITEM_AMOUNT |
| 27 | + ): |
| 28 | + expenses += Decimal(str(item.amount)) * item.quantity |
15 | 29 | else: |
16 | 30 | return "Invalid item type: %s" % item.type |
17 | 31 |
|
18 | | - if net != 0: |
19 | | - return "Order ID: %s - Payment imbalance: $%0.2f" % (order.id, net) |
| 32 | + if abs(payments) > MAX_TOTAL or expenses > MAX_TOTAL: |
| 33 | + return "Total amount payable for an order exceeded" |
| 34 | + |
| 35 | + if payments != expenses: |
| 36 | + return "Order ID: %s - Payment imbalance: $%0.2f" % ( |
| 37 | + order.id, |
| 38 | + payments - expenses, |
| 39 | + ) |
20 | 40 | else: |
21 | 41 | return "Order ID: %s - Full payment received!" % order.id |
0 commit comments