From f381a46186af15a80e967381fac7047501909403 Mon Sep 17 00:00:00 2001 From: MrWaradana Date: Wed, 4 Feb 2026 16:48:35 +0700 Subject: [PATCH] feat: Introduce `EquipmentHistoricalMasterData` model and expose replacement history in equipment details. --- .../__pycache__/model.cpython-311.pyc | Bin 8649 -> 10376 bytes .../__pycache__/router.cpython-311.pyc | Bin 16457 -> 16507 bytes .../__pycache__/schema.cpython-311.pyc | Bin 15471 -> 16348 bytes .../__pycache__/service.cpython-311.pyc | Bin 40950 -> 41581 bytes src/equipment/model.py | 35 ++++++++++++++++++ src/equipment/router.py | 10 ++--- src/equipment/schema.py | 8 ++++ src/equipment/service.py | 12 +++++- 8 files changed, 58 insertions(+), 7 deletions(-) diff --git a/src/equipment/__pycache__/model.cpython-311.pyc b/src/equipment/__pycache__/model.cpython-311.pyc index 765df7e134e231666c3cbc01c7e8663d219442a2..b10150a5e8961e44f74b454b614e814b45458810 100644 GIT binary patch delta 1648 zcma))!Ef4D9LFETIDr6bj12^Wah84or!WO*4Q-`L z8%Wz>M>-Dk5ouC})J1Wuz>Ag%rQ)Q~he-$b-;hGN+@m zqy#=encz>8QnFipX@xg^{PEWvH$vYc6;)gcs<;(bWlnKdC^u3)Dy_`@KpheNF`3g* znYWdN8H(3dd^40qTWKsPo-^C|kGDIk1RRy1qw<=q_#n@q;0<*>s=YpSgeBXHo>2|s zxO2!+VNY_N%EMi9l){cm`d~k$Wzis)%>r~R1qY}53S;t;+j7fAIgLtAO6TEoZCCEd5BE>3Lc=x- z3b6|ZElp4%vJ0U?TGpzy`h8Uq9@NyPAXkahu6OFK=G47flbg5Ib|yCw4y#qE(U$CB zh?Q!u@=CDv73~};@wyfy)ItOgugXnDN;}j^PYWG<5y<2+a~ca#93V`vpIOzS@UaYt z5lrSKNoiFjNsE6Ik9HGaho7SHfFwWwtO8yKtO3>uCjLgfDXDT*syE5;&x1V$xBy54 zGJrP#S-?fWn}8hPEkF(61#BTCBCP<+w*l_}K6{Dp$fEs^3!&bt$D(dw>XyZdgS+%z zm%_=Ckt~_X5~fxxCfZNwkx>ydd4tKDOul#3O04NOhUKw>6Wc~&+e~a@DrWKP`oZw# zxP$o}gWoav9Zbb7HrBtQZ;)sWQ3r>MM!0B(i@lGmNTPpVzdfdKWW$JTn2`-kvC|s45sR6e z!Q@OPM{2a|{vWoOpr?l1n8h*Ch>2!Qd=FC*E6VG%{(xAcq7fC%sE8@f$`(fA`23S~ zoGlyKvY9PoDm^{+r{n9G-!k|uliwQrIiKCL;;XtiOpS{;zG=ia&G;s!qJNxQ>HDpP zkQHDpR<@S7XI{?|{Tvaz0Q5e9XWBDp*M5c>#Dve&cI*Dz&c7FS8ZG7Cp?XQvh$rbL hYKuSrD!5#wj!SUS&(K*6cSje02|Neo#SGcb`!DJ)imU(t delta 102 zcmeAOJn780oR^o20SIpSG-Ni(PUMqdTsKjDEn5nAFoPz~#$UGb%zm1Jlb5R1DjNb- s6&ZmDV<7R1!zMRBr8Fnit|%ACWd!14_RU`EjEsB?=8TpfKm=Gd0BU*|MF0Q* diff --git a/src/equipment/__pycache__/router.cpython-311.pyc b/src/equipment/__pycache__/router.cpython-311.pyc index 40ff91a01d61e7a112f350f80b9fd9a53ebc0bfc..4726dee910bb7f337fe0ca3899b63ee977b71804 100644 GIT binary patch delta 444 zcmX@v!1%j?k#9LKFBbz4+!JZeG&9`Dr?1N;0OU3U@#lM!8BHZ8C+NyE@=R{fm0+pm zt6`mdm)m9XJzXWP8oo6w%Xk081`;_*eP$@xVo#l`$UOB5zA)K?ar4`h7>;^M17;sp>kFnpDpd{bYYNt$;u zlYuhF4G!rKYz#bNlWj~?C;J;{YTl4F_#ny4$Mul`NPGbiA7mH=^*+c8@UVSk01{t7 z#0Lg}$@2_$FfN!JZs^Ch0BCs8!pW-*O<9)#nev;T8dfs0Ed_}#n4Ds4&$xK<5@R(1 zh%%697l>Fo`IfO7>q;O~Z!@dOIY!1+ldqU2vaN#1S(_=dt_3o^HYc0yWReDXBijPc4-7!+f@?U0PEG^U b2;w6%1Cux76-KWQOh9!Xf;P+BYcT=i& zfw=fQkaz)v4GdppCbJr-GfDDH)-zCM{lLb+BQ`nDM0IkVfu`CAaUMRdj|@QK3yAn2 z#UQBnL6)C~?IQz__yQt6Fz`>lV6cO6-sDb0Kel;5V~gfbzH4a8x&+8n+$?TX$;h@C zBsy>MG-G?lg_Exts|i4qfkeAN#Nx?3CTgt9flPzV<|gMD8COhZGfQM!0g=l!Q)XQa zWcqBLYPOR}8svprECu<+B}E`BZZQ{>mK1^X7OkF~X(`LNcXPXC6>ES50~1HPRFhPP z?*%QZ9ky4rJR77gGJ0KM^!mW0!pOG3^8*8ry5JfPp_9|VG=liZ%)sQ$2vh#SZ*!o% G79#*NNOy7o diff --git a/src/equipment/__pycache__/schema.cpython-311.pyc b/src/equipment/__pycache__/schema.cpython-311.pyc index 46c3bba699b6cc37370fc94189b516a6daa77dd3..374415414a7d2f5ffea8fdaaffe603b31cab212b 100644 GIT binary patch delta 1318 zcmZva-%Aux6vyX|v#!p%>n{G<)yPfPA7lR5w6zuO2R&p^DXu2ugTu0O#YNY3XV+58 z+%!wX2jwDG7#2i9*+a}j{s;Nc!wM#{^d1Odg7_dr-E&1;7w5-^bIXVM>c%$uwz{-w;08pQW09QTR7hgVlN&oy&O-cwGoVq=n)!!#S!^09$L zQ2{cNB~;LANZMy*`wHnkJ5J7TW7;{Y72))xxO}C!os%5eHY#^mH)%nO9Ok-^!gcX? zIR$m4@EjJ1vo`0B4yR(h?WkxDrzyH7x&mF{l@y%5lA4rTq!ES_5&EMD$XJj;b>j&= zEm0pgQ9bj7o({Ug(~8A-rUwu9dwn>72O`(KVLaO0?(4+?ue~Rz+SOyt-s=xXg6fF9 zyhjZN?EOBU90Xr`GNRLtb%s>ku3(x~7p^(g~1a<}B zJVjhD%SzBE%c>q+EKUbjHJ}Pm17K;KV6j}4U_nAPg|wAqk=v3f_aj|K6YedcEhe-P zxw?cji=|}4QB3wT9LAV%l|E`M1P_pq)5f3W$v>A(t1A75$m3F*J`Wq{_^hP5EYDzO zV-x7uEaafLx<8KG8OQ2f4#IttE*fJXof z7y}GIJ7Ne-Kp)wu%F+6yPIPI@eR);4s;qUy+@5u}XT$A@3E6YKFCuSRHwrIq_=Gx+KJf(kTHA>xh^g+LI1Rf2Gg_$b1tLG{EhOL7S_D~JBz@8+SC0>yW{1r{ zIADoL_mv~Ki`7goC=70R> zyaHb(YkM9{z&q0Ip4WrbA{CH*_s|WPGn)u&nDxP`VJEW~^#W{Re@q><4$_(eL1m~P zUs0Fo645vOTU%*}B1MO;p+DT|oa@_V%3h*w%0TTj;&jg4+GWaKqJBo}ZnU8P&5|%K delta 679 zcmZvYPe>a<6vp?hG2+G*16q@aBt}7_X;2r}qzO_`5EMmG1ic8lQF0O7Xse(m#vopV zhUY&pg`V_KFEU3#^xArmUIg)E4?;ky;KiHsrU()oc7A;CeINT~<|grPq4ZEy6^XBj zzGUp#n<;g`>2bXWLh3<*B>m+3{~9ZorEbZnOiP9%YRmH~gy-a*E2?4=s=$U>sM3_Y zoI~W?Jm-lP=Xp+}W=QgRnN@D6lWzgt0WZrnoPyP`@O~NQ8ZTsDCH`vCI!t~fvyjkC zh!f@r^MnB53&*v^h)vF!U#VUoEE1x4RbK-!HtnAR`=w=oe`YHgGaQo{dj+cw6!G7sD?8358&Tm3;DnHA6|naM;_vO;S9dc&v|9?hyQhyjyQlkC4T!aHfbP~jyGRmRZ7>KA();|@`zV~Jx4w)0?y$oP*y);e diff --git a/src/equipment/__pycache__/service.cpython-311.pyc b/src/equipment/__pycache__/service.cpython-311.pyc index 1905fec91240bc5e3c3b35822983166cde97e41a..83de7cf5bdae46315b14395d3c8c9fb7f0539ec5 100644 GIT binary patch delta 5054 zcmbst3s6+ob>Ds-?DAPaT?7SIezL%>BKQYC{4^?v3IR99^|9{)3-9gXeQz}?DO#=h zRFj$;<75(N%uFYVld02mr)g)}OwuGxn@V|*=V;^y_npd|Yqf}{DxMuxy+N;Fku9=I zS)djNi#eXAl&Gb_Qoz&Y45dsh50(R-DZ7=0YDKU@^#y%uWw4UVW+_!_b+B6X2mNXw z7~r&QWs$l#xR~QPN{zZCxP;?^QX8y=cg<4j)TP0tK-+AQXDiFp<-z4#V3x817%P+b zD!^BBe2!ADHUt|u?ormLYlCY!E-34Q>p-EPtPiedj|oLWW8wwjfUvEJG?Nz6*k{c{ zr};x#<+ggjD=MLC8xywc>r}p%TauE2P zT(fDHjTFq_-v#`xQ7*8Hn|Qmx-5_wMEXcc`6u4A~bjy2^E>2gKDoe-2U=No;_owsh zaxZAvndD&#yJxsDYL~+x5d1HjW#HX~ygsW;0N=&s`bb5eUG9hV-P6_su-?tr5zZfk zb%?KrNP!$7K8T3|v^|`LhC_c!x~- zq`0Ef)j**2>=}18Y#(=*3GM8r`=GEi5zqRIL#SYq=MJHSJ?E(qx1wYRd*9O!lIwGe zg>XX7?Gd{gkj~YJh+!2PVqZjopm5_1TO=9+@8iP?p*xV9qCwass?jc7rG;af9*RdJ zdZ^atqB1HWEW7ag@R}D2D}?=t>xB&hI8@**cc%mQDExj_2-tmowx^+q1-7TNho~#@ zocCO++pjkPJNex2PXv7zge?75FIy}+gn)hA=waXT=0dF2R8+BrC7uinO!65lW$x{T zENej~TeQP1RIvFq%yU$YRGo9M?51LNqO@#Y^@w96btG-1bfoM7|47M5)=2h9 z`G{|%x-Xr1tBw@bfkH^U{Q!}u&uUl$iw)s`W(BI(OP8^is-z68kn>iWjIF==DWRXe zTb(Nuus>EGS}+1!x(|Snu0jxr6b_*-&Bj$61|3KJ@dc>ES4MgC=i`n+1RV%4+*DB! zi5^05FM`7ejv)9p0!$D+#u^rH628OkUwom-$fjgik-`K!C$u+C=m8^VI*AeuiqV)g zlNOFqS)&htHZ8!0hvu@5nz^=h;I&#a-}NGp-$B-?1gp8?82uvE;&fkjSC6Io$5Z{+ zo$d!cm$UriS<8M}aVe{D%-J;VY`X5uesJ#PoJHd~>#pQ9U&?77%V{0YX&rNJ7O;K;LXrk!AsScdFHweFSal3uP`lbI?0y9Z?YV9zc!MFpcPV2>NEz_mO8H;Ddo% z%8LcfH6y?cvuRLczr)>W8c|4C5B1TQdV64a#<*X6hIOL6EfytoEnrZKi}^XhUAm6? zuOhfra)yn@_G@sfGJWFX_GfK{j!%H{p7?lMLU2bA*y zpYc8`9l@O^aiIKi|*1jyt7iLIb)s)xTOn0IRf4)Wq>7n052;;1PY&Z z_Y`Jx)zd4V9q%c0+yL<#?0nA!IGTHQzC6lxd&>tb4N>NP;>mW(L29^cf*4UZgHVDt3 zf_9u+xQzbK7nr_9cMHMxT0j8r-i4)kDyJ68#s-eFZ?9;q&@k1r8frByw1I z*S+BL$Gbie>exGX=dP&-S#wrI^vR)X2TAUinHW2WV0)P(R}51Ej?h#PDqtnM2Sv;h zJ(*y;KNLkj;?-;)StV>_&y#Z^FLjdW?mH#~+JFg1hYPNQRM+-L^Z__8umB8U$Po5T zofW9$TkP6Ek+7Hf23CT>;ep0nEF5zv+0C-aL_6K==L7RaJPndt_Oq`CmZWi`a9|o9 zwspkAwna9laa+v5v1cL+dDd@QS9wjPd1j*su6I9UPY`G!F~i$1Oo^n2v!4t z=^vvyk!c!kXGl%~%&_l+E05veM*=NG!E}BEg!&?cwGFz;i%=9(!>fVrgr(18&O9t# zYUYC7J6I-~_ONFMhlLo+8`>shv!S6PH+P*|gP=U|_|P@SCSEi%yJhlhzBOoO#M{VD zo(8whQjJ!CSr4#Z?A-$ifb&1Gnq~^CevMXf&FJ8y($|rSnrA8%;j|-AEL9--J$6(( z0#)wNCq%IT<@?!}2P-pY0k0J%0nbhct39+`XiFSF6m_Ja6Vf9tcH&S;qVUKMT`frH z^kq>W{Dq>8QwX|wEl=gQk;xg$Z-Ry+ti+%*Fr<`c5HAPx2{!9QWiC%sI zo{92QOxRnGlsZ~KcoF;j5tVn2uaEV!SA{!S)uWAgZ5@2nJDP{Pb2J(b;30>N9pF{N zZ@z|yOn%70G{WzxJ#Ry7JA`2y? zxIPfjN(kK-f$z0aq`QzFjz#+-{S>FH;TX{M;d|J*({mj(9)v)(dK^xU}^$6 delta 4542 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 diff --git a/src/equipment/model.py b/src/equipment/model.py index 24578ca..3b27bb3 100644 --- a/src/equipment/model.py +++ b/src/equipment/model.py @@ -158,3 +158,38 @@ class EquipmentHistoricalTransactionRecords(Base, DefaultMixin, IdentityMixin): efdh_equivalent_forced_derated_hours = Column(Float, nullable=False) foh_forced_outage_hours = Column(Float, nullable=False) acquisition_year_ref = Column(String, nullable=True) + + +class EquipmentHistoricalMasterData(Base, DefaultMixin, IdentityMixin): + """Historical master data for equipment (archived when acquisition data changes).""" + __tablename__ = "lcc_ms_equipment_historical_data" + + assetnum = Column(String, nullable=False) + acquisition_year = Column(Integer, nullable=False) + acquisition_cost = Column(Float, nullable=False) + capital_cost_record_time = Column(Integer, nullable=True) + design_life = Column(Integer, nullable=True) + forecasting_start_year = Column(Integer, nullable=True) + forecasting_target_year = Column(Integer, nullable=True) + manhours_rate = Column(Float, nullable=True) + harga_saat_ini = Column(Float, nullable=True) + min_eac_info = Column(String, nullable=True) + minimum_eac_seq = Column(Integer, nullable=True) + minimum_eac_year = Column(Integer, nullable=True) + minimum_eac = Column(Float, nullable=True) + minimum_npv = Column(Float, nullable=True) + minimum_pmt = Column(Float, nullable=True) + minimum_pmt_aq_cost = Column(Float, nullable=True) + minimum_is_actual = Column(Integer, nullable=True) + efdh_equivalent_forced_derated_hours = Column(Float, nullable=True) + foh_forced_outage_hours = Column(Float, nullable=True) + category_no = Column(String, nullable=True) + proportion = Column(Float, nullable=True) + acquisition_year_ref = Column(String, nullable=True) + + equipment = relationship( + "Equipment", + lazy="raise", + primaryjoin="and_(EquipmentHistoricalMasterData.assetnum == foreign(Equipment.assetnum))", + viewonly=True, + ) diff --git a/src/equipment/router.py b/src/equipment/router.py index ae1ac28..cbcf66b 100644 --- a/src/equipment/router.py +++ b/src/equipment/router.py @@ -242,10 +242,6 @@ async def get_generated_equipment_transaction(db_session: DbSession, token: Toke message="Equipment transactions generated successfully", ) - - - - @router.get("/{assetnum}", response_model=StandardResponse[EquipmentRead]) async def get_equipment(db_session: DbSession, collector_db_session: CollectorDbSession, assetnum: str): ( @@ -259,7 +255,8 @@ async def get_equipment(db_session: DbSession, collector_db_session: CollectorDb maximo_data, joined_maximo_record, min_eac_disposal_cost, - historical_records + historical_records, + replacement_records, ) = await get_master_by_assetnum(db_session=db_session, collector_db_session=collector_db_session, assetnum=assetnum) # raise Exception(equipment[0]) if not chart_data: @@ -280,7 +277,8 @@ async def get_equipment(db_session: DbSession, collector_db_session: CollectorDb maximo_data=maximo_data, joined_maximo=joined_maximo_record, min_eac_disposal_cost=min_eac_disposal_cost, - historical_data=historical_records + historical_data=historical_records, + replacement_data=replacement_records, ), message="Data retrieved successfully", ) diff --git a/src/equipment/schema.py b/src/equipment/schema.py index c61594b..edd29a9 100644 --- a/src/equipment/schema.py +++ b/src/equipment/schema.py @@ -97,6 +97,13 @@ class EquipmentCreate(EquipmentBase): class EquipmentUpdate(EquipmentBase): pass +class ReplacementBase(DefaultBase): + """Schema for replacement history (from lcc_ms_equipment_historical_data).""" + acquisition_year: Optional[int] = Field(None, nullable=True) + acquisition_cost: Optional[float] = Field(None, nullable=True, le=MAX_PRICE) + acquisition_year_ref: Optional[str] = Field(None, nullable=True) + created_at: Optional[datetime] = Field(None, nullable=True) + class EquipmentRead(DefaultBase): equipment_master_record: EquipmentMasterBase equipment_data: EquipmentBase @@ -109,6 +116,7 @@ class EquipmentRead(DefaultBase): joined_maximo: Optional[List[dict]] = Field(None, nullable=True) min_eac_disposal_cost: Optional[float] = Field(None, nullable=True, le=MAX_PRICE) historical_data: Optional[List[HistoricalBase]] = Field(None, nullable=True) + replacement_data: Optional[List[ReplacementBase]] = Field(None, nullable=True) class EquipmentTop10(EquipmentBase): id: UUID diff --git a/src/equipment/service.py b/src/equipment/service.py index 9c507d0..5a4a8ad 100644 --- a/src/equipment/service.py +++ b/src/equipment/service.py @@ -9,7 +9,7 @@ from sqlalchemy.ext.asyncio import AsyncSession from asyncpg.exceptions import InterfaceError as AsyncpgInterfaceError from src.database.service import search_filter_sort_paginate -from src.equipment.model import Equipment, EquipmentTransactionRecords, EquipmentHistoricalTransactionRecords +from src.equipment.model import Equipment, EquipmentTransactionRecords, EquipmentHistoricalTransactionRecords, EquipmentHistoricalMasterData from src.acquisition_cost.model import AcquisitionData from src.yeardata.model import Yeardata from ..equipment_master.model import EquipmentMaster @@ -311,6 +311,15 @@ async def get_master_by_assetnum( historical_result = await db_session.execute(historical_query) historical_records = historical_result.scalars().all() + # Replacement history query (from lcc_ms_equipment_historical_data) + replacement_query = ( + Select(EquipmentHistoricalMasterData) + .filter(EquipmentHistoricalMasterData.assetnum == assetnum) + .order_by(EquipmentHistoricalMasterData.acquisition_year.asc()) + ) + replacement_result = await db_session.execute(replacement_query) + replacement_records = replacement_result.scalars().all() + return ( equipment_master_record, equipment_record, @@ -323,6 +332,7 @@ async def get_master_by_assetnum( joined_maximo_record, min_eac_disposal_cost, historical_records, + replacement_records ) # return result.scalars().all()