From 990fcbbe357df755a0647c2aba35dda104bdd5b8 Mon Sep 17 00:00:00 2001 From: Cebolwethu Mzanywa Date: Mon, 1 Dec 2025 16:39:05 +0200 Subject: [PATCH 1/5] k --- __pycache__/analytics.cpython-312.pyc | Bin 0 -> 6124 bytes analytics.py | 69 +++++++++++++++++++++++--- test_inventory.py | 37 ++++++++++++++ 3 files changed, 99 insertions(+), 7 deletions(-) create mode 100644 __pycache__/analytics.cpython-312.pyc create mode 100644 test_inventory.py diff --git a/__pycache__/analytics.cpython-312.pyc b/__pycache__/analytics.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..567667ba70fc5479478b6da3352d63e2d5b6c297 GIT binary patch literal 6124 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 threshold: + above_treshold.append(i) + return above_treshold def count_product_codes(codes: list, prefix: str): @@ -33,8 +40,11 @@ def count_product_codes(codes: list, prefix: str): - Return 0 if no matches found """ # TODO: Write your code here - pass - + count = 0 + for string in list: + if prefix in string: + count += 1 + return count def calculate_moving_average(numbers: list, window_size: int): """ @@ -51,7 +61,19 @@ def calculate_moving_average(numbers: list, window_size: int): - Return 0.0 for empty list """ # TODO: Write your code here - pass + count = 0 + if len(list) == 0: + return 0.0 + elif len(list) >= 3: + for i in range(-window_size, 0): + count += list[i] + average = count/window_size + return f"{average:.2f}" + else: + for i in list: + count += i + average = count/len(list) + return f"{average:.2f}" # ========================================== @@ -72,7 +94,14 @@ def get_top_seller(sales_data: dict): - If there's a tie, return the name that appears first alphabetically """ # TODO: Write your code here - pass + max = 0 + if len(sales_data) == 0: + return f"No Data" + else: + for x in sales_data: + if sales_data[x] > max: + max = sales_data[x] + return max def merge_inventory(warehouse_a: dict, warehouse_b: dict): @@ -93,7 +122,19 @@ def merge_inventory(warehouse_a: dict, warehouse_b: dict): - Do NOT modify the original dictionaries """ # TODO: Write your code here - pass + new_warehouse = {} + if warehouse_a and warehouse_b: + return new_warehouse + else: + for a in warehouse_a: + for b in warehouse_b: + if a == b: + new_warehouse[a] = warehouse_a[a] + warehouse_b[b] + else: + new_warehouse[a] = warehouse_a[a] + new_warehouse[b] = warehouse_b[b] + return new_warehouse + # ========================================== @@ -136,4 +177,18 @@ def check_inventory_status(stock_level: int, reorder_point: int, max_capacity: i - All other cases: return "OPTIMAL" """ # TODO: Write your code here - pass + if stock_level < 0 or reorder_point < 0 or max_capacity < 0 or daily_sales < 0: + return f"Invalid Input" + elif stock_level > max_capacity: + return f"Invalid Input" + elif stock_level > (max_capacity * 0.9): + f"OVERSTOCKED" + elif stock_level < (reorder_point*0.5): + return f"CRITICAL" + elif stock_level <= reorder_point: + return f"REORDER" + elif (daily_sales > 0) and (stock_level < 7 or daily_sales < 7): + return F"LOW STOCK" + else: + return F"OPTIMAL" + diff --git a/test_inventory.py b/test_inventory.py new file mode 100644 index 0000000..e69f81b --- /dev/null +++ b/test_inventory.py @@ -0,0 +1,37 @@ +import unittest +from analytics import check_inventory_status +class TestInventory(unittest.TestCase): + def test_q6_inventory_invalid_input(self): + print("Grading Q6: Inventory Status (Invalid Input)...") + self.assertEqual(check_inventory_status(-10, 50, 100, 10), "Invalid Input") + self.assertEqual(check_inventory_status(50, -10, 100, 10), "Invalid Input") + self.assertEqual(check_inventory_status(50, 50, -100, 10), "Invalid Input") + self.assertEqual(check_inventory_status(50, 50, 100, -10), "Invalid Input") + self.assertEqual(check_inventory_status(150, 50, 100, 10), "Invalid Input") + + def test_q6_inventory_overstocked(self): + print("Grading Q6: Inventory Status (Overstocked)...") + self.assertEqual(check_inventory_status(95, 50, 100, 10), "OVERSTOCKED") + self.assertEqual(check_inventory_status(91, 50, 100, 10), "OVERSTOCKED") + + def test_q6_inventory_critical(self): + print("Grading Q6: Inventory Status (Critical)...") + self.assertEqual(check_inventory_status(20, 50, 100, 10), "CRITICAL") + self.assertEqual(check_inventory_status(10, 100, 200, 5), "CRITICAL") + + def test_q6_inventory_reorder(self): + print("Grading Q6: Inventory Status (Reorder)...") + self.assertEqual(check_inventory_status(50, 50, 100, 5), "REORDER") + self.assertEqual(check_inventory_status(45, 50, 100, 5), "REORDER") + + def test_q6_inventory_low_stock(self): + print("Grading Q6: Inventory Status (Low Stock)...") + self.assertEqual(check_inventory_status(60, 50, 100, 10), "LOW STOCK") + self.assertEqual(check_inventory_status(69, 50, 100, 10), "LOW STOCK") + + def test_q6_inventory_optimal(self): + print("Grading Q6: Inventory Status (Optimal)...") + self.assertEqual(check_inventory_status(70, 50, 100, 10), "OPTIMAL") + self.assertEqual(check_inventory_status(80, 50, 100, 5), "OPTIMAL") + # Zero daily sales should not trigger low stock + self.assertEqual(check_inventory_status(60, 50, 100, 0), "OPTIMAL") \ No newline at end of file From a0544382eba95f0bb16890660ef9254f1cf9c634 Mon Sep 17 00:00:00 2001 From: Cebolwethu Mzanywa Date: Mon, 1 Dec 2025 16:42:17 +0200 Subject: [PATCH 2/5] k --- __pycache__/analytics.cpython-312.pyc | Bin 6124 -> 6082 bytes analytics.py | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/__pycache__/analytics.cpython-312.pyc b/__pycache__/analytics.cpython-312.pyc index 567667ba70fc5479478b6da3352d63e2d5b6c297..d0c6542c8d7cdc43cfaeeff4c79d8c6cc4ee605a 100644 GIT binary patch delta 305 zcmaE(e@LJAG%qg~0}yDg)XjXbk=KPy^bn9Yogsy>mZ^jhBm)99lk?bQO=}odLq$@U zvtt+-ij+&3A@V>KjNCvytC=8t7lv4V28LSZ8m5}b7uX~O1z8yCSyEVLvjj8LFaRY* zCo{532_ej@;s&Z_=@H*-%KnUznW>0vvNC5({Uo4a4GbUT7 zE^&ij=nf}OM|ii)48cpBQg;N!W^hlaSrB+xQ2i4F6Q^p2;|)%}3Fvxc8Qx6! delta 333 zcmX@4|3;tpG%qg~0}$jd)6KlNk=KQd;}wuMogsyB;t|z)#!99VMvycJlrTYP28Pv8 zu@vU)7zTzS^%7Q?ObsJ9Q0r=_N*9J$VFrd;<{Bo1-Wp~}pyDcCpg21&yvD2nxrhyDY7zV7ZyYhM{Xk{| z!v{GAUcLs`JM3INCe4)-9GmKH@C)7HFmbAO zINspoo1!wIaH9G}PRYqLIb~I!2#SKF)PPbvf)fHey*gZPh)K_JUcxflb7Fp{`v+E_ K= 3: + elif len(numbers) >= 3: for i in range(-window_size, 0): - count += list[i] + count += numbers[i] average = count/window_size return f"{average:.2f}" else: - for i in list: + for i in numbers: count += i - average = count/len(list) + average = count/len(numbers) return f"{average:.2f}" From ffb42bfc382e33ff4782150bac16a88b7d5626eb Mon Sep 17 00:00:00 2001 From: Cebolwethu Mzanywa Date: Mon, 1 Dec 2025 16:45:51 +0200 Subject: [PATCH 3/5] k --- __pycache__/analytics.cpython-312.pyc | Bin 6082 -> 6051 bytes analytics.py | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/__pycache__/analytics.cpython-312.pyc b/__pycache__/analytics.cpython-312.pyc index d0c6542c8d7cdc43cfaeeff4c79d8c6cc4ee605a..4289aff3269e9f43d579c13fb155598d916734b5 100644 GIT binary patch delta 367 zcmX@4zgVC5G%qg~0}$+AshjzDBJX<6G$3a>Lpnq4ovt1Y%iWz%2YnZZ_Hw!QxXJli##hjCxH~BHs97gWR4a^dP9j47y69Sv+ zZwM=1;8A=aC^mT|b1=6K*z^>}TBe%K{49Np+$$M0S&DdpqD6d@*Rskma!o$Ps?U5w zNPO}iR#irx%}Q(^m?SxY^0(L%%TkLH(^HFCfjk8eDB_x|&AAV#=oP0w6HuoWPb!eJ zfQOBlrAUy0Ve)c*U2%}-Zt>@)7Nw`gXXcfq=9T0ZRTimFe$C$qRGTZXhE)})6yyjE zAXTIZBD6q+HjpT00TNJ~?8Iak4JSv7HHh#41^qO+Zn5NK7MI*&&de(*;-36YOiolC Wq|XpUfQ&2xsRKGuQG6~7hzS5JB3dW_ delta 400 zcmZ3ie@LJAG%qg~0}yDg)XjV_k$1gp8IUubA)TR?se}|8x2&6N`zo9b=|D_-DHd?F}1c`|dbunADrbcPg0pgVvpFxdQ& zxsOpmld*^$$kk*i;sa7e{FA#_Wf-|9FK5+fz9S?y`6jC>Bk$(_tRI*dxh8+$5C=+e zaP9*N9q06C0&>K8Qh}UW9yVsim6O}~b;Y@XrrhGsO)W}KjnB+0OU*0EFRCokn0%VQ z5vb5tU=6FP3dBB5kbPPpLK{Tr0EuE2AfW&RMck9+#AFzaCR>X&2=f93{WQ72?!3jE hnO9Q8Gx@xjoTvs!n-PcrnOFo;2GqwSK9>c=1OOi{Scd=r diff --git a/analytics.py b/analytics.py index b933895..143842e 100644 --- a/analytics.py +++ b/analytics.py @@ -18,10 +18,10 @@ def filter_sales_above_threshold(sales: list, threshold: int): """ # TODO: Write your code here above_treshold = [] - if len(list) == 0: + if len(sales) == 0: return above_treshold else: - for i in list: + for i in sales: if i > threshold: above_treshold.append(i) return above_treshold @@ -41,7 +41,7 @@ def count_product_codes(codes: list, prefix: str): """ # TODO: Write your code here count = 0 - for string in list: + for string in codes: if prefix in string: count += 1 return count @@ -68,12 +68,12 @@ def calculate_moving_average(numbers: list, window_size: int): for i in range(-window_size, 0): count += numbers[i] average = count/window_size - return f"{average:.2f}" + return f"{average}" else: for i in numbers: count += i average = count/len(numbers) - return f"{average:.2f}" + return f"{average}" # ========================================== From 62f565cf92828984397459e47c535a93e91edf97 Mon Sep 17 00:00:00 2001 From: Cebolwethu Mzanywa Date: Mon, 1 Dec 2025 16:49:01 +0200 Subject: [PATCH 4/5] k --- __pycache__/analytics.cpython-312.pyc | Bin 6051 -> 6039 bytes analytics.py | 6 +++--- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/__pycache__/analytics.cpython-312.pyc b/__pycache__/analytics.cpython-312.pyc index 4289aff3269e9f43d579c13fb155598d916734b5..24687a368eac817d970625bcaf1fe92cbdd90dc2 100644 GIT binary patch delta 148 zcmZ3iKV6^qG%qg~0}#wvrJH$sBd;PGWZC?U?F!@M z^Bf6`9g__>qgVvQJNPC~=G25Rj&iCqMofOo8N|*|&m;*nY_kK`7e+>p$)-Hc98xnB tJ8Lg+$ZW3WxyU6Wz98iTgEXV~4&l!r>VpfTD5LC*lFtl4YI26SH2_HYDi8nw delta 161 zcmbQPzgVC5G%qg~0}$+AshjzDBd;PGTQ`5I>sBjaX$ zt}l#?&XZMmoSB6?xHjkWT;!5bSdj98L7Guvhwx_*^}&Tvlu>v_$!7*2H91Dy8UUKO BE#LqE diff --git a/analytics.py b/analytics.py index 143842e..2f6fee4 100644 --- a/analytics.py +++ b/analytics.py @@ -68,12 +68,12 @@ def calculate_moving_average(numbers: list, window_size: int): for i in range(-window_size, 0): count += numbers[i] average = count/window_size - return f"{average}" + return average else: for i in numbers: count += i average = count/len(numbers) - return f"{average}" + return average # ========================================== @@ -101,7 +101,7 @@ def get_top_seller(sales_data: dict): for x in sales_data: if sales_data[x] > max: max = sales_data[x] - return max + return sales_data[x] def merge_inventory(warehouse_a: dict, warehouse_b: dict): From 6113bd5623f7b0fa5d7a712e0693523686e2e7e2 Mon Sep 17 00:00:00 2001 From: Cebolwethu Mzanywa Date: Mon, 1 Dec 2025 17:48:28 +0200 Subject: [PATCH 5/5] j --- __pycache__/analytics.cpython-312.pyc | Bin 6039 -> 6248 bytes analytics.py | 12 +++++++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/__pycache__/analytics.cpython-312.pyc b/__pycache__/analytics.cpython-312.pyc index 24687a368eac817d970625bcaf1fe92cbdd90dc2..c8d02f460fd853ab444d13cff9375bb06b7a2026 100644 GIT binary patch delta 500 zcmbQP|H6RpG%qg~0}yoW(9N`!+{m|&Q;-G7Wd`EU7l6cchIEF>cR3aENOufYcR2*NNn3H;oB`+}-NP^hKAm1n`OlIVftXBgvgMqj> z8%Q)Te2`(_=527k!_L)V)m%SA@e;fA4GzgC!eSGuu8V726xX;cu60>hyMyC~l*)A} zt&37xm!)(*F)(o|c6xQVOi;POFFc{*GQa!{0paOf6S-!XToq9GzzUT9!oeUQHX*sY zdWK0w^gyEeAi@Ad7*1vp y(_%FTGAB(o7F)>;a(NL*d6D_#=VG#qHj`P!eR;$g!TAn5SBF(|{S3uR?9w+lBp(P$e_~+b zROxWM!7n*Ov9oqY@nwFc8)6Cz1SjTBWd6Vkl>5NOARq;jyTBo{*@0JpnN1OBVv*A1 zFab+ebs#f)^ArI?HUSNgs3wTe0ukDiuZn508UmRUCbNjIL)f|M5-PTnCd%V;+F Xnz%2ID5LC*lFtl4>Vv^#eF;kdYu8E& diff --git a/analytics.py b/analytics.py index 2f6fee4..2024bca 100644 --- a/analytics.py +++ b/analytics.py @@ -94,14 +94,16 @@ def get_top_seller(sales_data: dict): - If there's a tie, return the name that appears first alphabetically """ # TODO: Write your code here - max = 0 + tie = [] if len(sales_data) == 0: return f"No Data" else: - for x in sales_data: - if sales_data[x] > max: - max = sales_data[x] - return sales_data[x] + max_sale = max(sales_data.values()) + for name, sale in sales_data.items(): + if sale == max_sale: + tie.append(name) + #name = [name for name in tie] + return sorted(tie)[0] def merge_inventory(warehouse_a: dict, warehouse_b: dict):