-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathabc_engine.py
More file actions
28 lines (28 loc) · 1.48 KB
/
abc_engine.py
File metadata and controls
28 lines (28 loc) · 1.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
import numpy as np
from dataclasses import dataclass, field
@dataclass
class Activity:
name:str; cost:float; driver:str; volume:float
@property
def rate(s): return s.cost/max(s.volume,1e-8)
@dataclass
class Product:
name:str; units:int; rev:float; dm:float; dl:float; usage:dict=field(default_factory=dict)
class ABCEngine:
def __init__(s): s.acts,s.prods=[],[]
def calc(s):
res=[]
for p in s.prods:
oh=sum(p.usage.get(a.name,0)*a.rate for a in s.acts); tot=p.dm*p.units+p.dl*p.units+oh
cpu=tot/max(p.units,1); m=p.rev-cpu
res.append({"name":p.name,"cpu":round(cpu,2),"margin":round(m,2),"margin_pct":round(m/max(p.rev,1e-8)*100,1),"overhead":round(oh,2)})
return res
def whale(s):
c=s.calc(); sc=sorted(c,key=lambda x:x["margin"]*1,reverse=True); tot=sum(x["margin"] for x in sc); cum=0
return [{"product":x["name"],"cum_pct":round((cum:=cum+x["margin"])/max(tot,1e-8)*100,1)} for x in sc]
def demo():
e=ABCEngine()
e.acts=[Activity("Setup",120000,"setups",400),Activity("QC",80000,"inspections",2000),Activity("Handling",60000,"moves",5000)]
e.prods=[Product("Standard",40000,25,8,3,{"Setup":50,"QC":400,"Handling":2000}),Product("Premium",5000,80,20,8,{"Setup":200,"QC":1000,"Handling":2000}),Product("Custom",1000,200,45,15,{"Setup":150,"QC":600,"Handling":1000})]
for c in e.calc(): print(f" {c['name']}: cost/unit=${c['cpu']}, margin={c['margin_pct']}%")
if __name__=="__main__": demo()