From 128ba9cc9009bc483170a9fe70e9719a59be81f7 Mon Sep 17 00:00:00 2001 From: "Juan M. Ley" Date: Fri, 13 Feb 2026 16:00:09 -0600 Subject: [PATCH] updated to use 2 apis --- .../__pycache__/exceptions.cpython-314.pyc | Bin 436 -> 759 bytes src/application/exceptions.py | 5 + .../order_repository.cpython-314.pyc | Bin 0 -> 2236 bytes src/application/ports/order_repository.py | 23 ++++ .../order_services.cpython-314.pyc | Bin 0 -> 5538 bytes src/application/services/order_services.py | 68 +++++++++++ src/domain/__pycache__/orders.cpython-314.pyc | Bin 0 -> 956 bytes src/domain/orders.py | 11 ++ .../__pycache__/models.cpython-314.pyc | Bin 845 -> 1379 bytes .../order_repository_sql.cpython-314.pyc | Bin 0 -> 6439 bytes .../adapters/persistence/models.py | 14 ++- .../persistence/order_repository_sql.py | 108 ++++++++++++++++++ src/infrastructure/api/orders/__init__.py | 0 .../__pycache__/__init__.cpython-314.pyc | Bin 0 -> 199 bytes .../orders/__pycache__/app.cpython-314.pyc | Bin 0 -> 850 bytes .../orders/__pycache__/orders.cpython-314.pyc | Bin 0 -> 3780 bytes .../orders/__pycache__/root.cpython-314.pyc | Bin 0 -> 748 bytes .../orders/__pycache__/router.cpython-314.pyc | Bin 0 -> 604 bytes src/infrastructure/api/orders/app.py | 10 ++ src/infrastructure/api/orders/orders.py | 77 +++++++++++++ src/infrastructure/api/orders/root.py | 16 +++ src/infrastructure/api/orders/router.py | 17 +++ src/main.py | 51 +++++++-- src/main_orders.py | 17 +++ src/users.db | Bin 24576 -> 53248 bytes 25 files changed, 407 insertions(+), 10 deletions(-) create mode 100644 src/application/ports/__pycache__/order_repository.cpython-314.pyc create mode 100644 src/application/ports/order_repository.py create mode 100644 src/application/services/__pycache__/order_services.cpython-314.pyc create mode 100644 src/application/services/order_services.py create mode 100644 src/domain/__pycache__/orders.cpython-314.pyc create mode 100644 src/domain/orders.py create mode 100644 src/infrastructure/adapters/persistence/__pycache__/order_repository_sql.cpython-314.pyc create mode 100644 src/infrastructure/adapters/persistence/order_repository_sql.py create mode 100644 src/infrastructure/api/orders/__init__.py create mode 100644 src/infrastructure/api/orders/__pycache__/__init__.cpython-314.pyc create mode 100644 src/infrastructure/api/orders/__pycache__/app.cpython-314.pyc create mode 100644 src/infrastructure/api/orders/__pycache__/orders.cpython-314.pyc create mode 100644 src/infrastructure/api/orders/__pycache__/root.cpython-314.pyc create mode 100644 src/infrastructure/api/orders/__pycache__/router.cpython-314.pyc create mode 100644 src/infrastructure/api/orders/app.py create mode 100644 src/infrastructure/api/orders/orders.py create mode 100644 src/infrastructure/api/orders/root.py create mode 100644 src/infrastructure/api/orders/router.py create mode 100644 src/main_orders.py diff --git a/src/application/__pycache__/exceptions.cpython-314.pyc b/src/application/__pycache__/exceptions.cpython-314.pyc index 6841d90968577da47927ca836321d2b1c0481018..00e33abedf3bdb611596d636bf8146daff723706 100644 GIT binary patch literal 759 zcma)3u};G<5Ve!Ev_Po}0>p@zDpayCBBV;Rf`Nh}Rbl}vBt}?D;$k}pwoVKzW#kw7 zOJU>(kXkY0a~jbu2oL9X@8o-T&--h&Wu#AkG-9v%{)D7Br5Tuw4ZLaf1El+% A$N&HU delta 169 zcmey)x`mlnn~#@^0SKHw_hjl%Uwrf*8aZf*4~NOqf9m7#KV zG?^z)U{swrQ<+h7;@h8o7L;V>=YfTaSU{3s u72H79Ee@O9{FKt1RJ$TxAeRw{iv@wi2WCb_#xG2ajGQw#zcBzQuoeLFVjyn- diff --git a/src/application/exceptions.py b/src/application/exceptions.py index 5c6014b..2a82d07 100644 --- a/src/application/exceptions.py +++ b/src/application/exceptions.py @@ -1,2 +1,7 @@ class UserAlreadyExists(Exception): pass +class OrderNotFound(Exception): + pass + +class OrderAlreadyExists(Exception): + pass \ No newline at end of file diff --git a/src/application/ports/__pycache__/order_repository.cpython-314.pyc b/src/application/ports/__pycache__/order_repository.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..71f040f1bc61c35ea6e6ff85d4ea3664fe36de1b GIT binary patch literal 2236 zcmb_e&u<$=6n?X7JDb=}T9Pz{6s4`zNG>EsqK6(TL|TNB0|6G13ra?t-AS|3ddJL+ zgL3l$iDS9;z@bM={6T0Xgb-YM3o>eZ;r=8QjN75B9)kTd>It+jNYxLf_7oyIC@&6^5-fND$I3qSsVa^pYc1ut9QXLAB?kC zGVV2yuv^-J51G%FAn|+$<&}Gdz9|NrGJfgTzTKIGisCW;5F2RpFm-2WaR!qpq_B|Ai? zzGB}%i{W9;bK0MkB@v`38pvYhK&p0NvO4Es5@;R8q2XN9&fC2#Y8}e9Xek-V)+aLT zwnb`ms~v|*YN3weQ0UgDfi@doY^|-WeKxkPRoDtTog@we6U(&KkqUL~NUnHL1v9AHHLrA6%2N8u-cmvYwfe#Jn zv+X`PUeY2tP*q&F&aSSiS)Ai?a3r#YNgHUD7#oo2!S7yGUB%g0G$;}_8Xw@~qG(`5 z*!%C`refsLQB*luMG4bYDH)i=nA&7`(@`~isXB@xGS*l%N2^y*kgC3pVw{$Rr{bq& zOU;?JxXF%ls8REXC}OwC)FQq#Z7PVFI*P@28%dHaO>$EJ)1*u`oZakPyqj(9M9%Q7`P-k&KN)|hyitr&Lpj2f_UWa!{eYMNZ-JP%EAfFPAWKiGixvCJlj6(&D+gN<_7zrB95)ASv`{N zAWqjM{f23q2X?DvG1s(h+rPN8|0Q=LUH0U#(smwudwoWX`a=73||1gtl~d| C3c4l$ literal 0 HcmV?d00001 diff --git a/src/application/ports/order_repository.py b/src/application/ports/order_repository.py new file mode 100644 index 0000000..b78eea4 --- /dev/null +++ b/src/application/ports/order_repository.py @@ -0,0 +1,23 @@ +from abc import ABC, abstractmethod +from domain.orders import Order + +class OrderRepository(ABC): + @abstractmethod + def save(self, order: Order): + ... + + @abstractmethod + def viewAll(self) -> list[Order]: + ... + + @abstractmethod + def viewById(self, order_id: int): + ... + + @abstractmethod + def removeOrder(self, order_id: int): + ... + + @abstractmethod + def editOrder(self, order_id: int, order: Order): + ... diff --git a/src/application/services/__pycache__/order_services.cpython-314.pyc b/src/application/services/__pycache__/order_services.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..66c3f45067a8f406194af13c93d27fe778966049 GIT binary patch literal 5538 zcmd5=&2JmW6`%bgmy#$_HudF?ik57pia+SaO5?VM8%vI1_k&e7DGju$7VL6WEwbdY zvqQNufYR=!j{CIQInMe`xZ+wZ08a7(LfyO#nB8GH}+?1F!fo=Jgd{be{ z1Q{l$h@p%UL!Fhy2&QtL2E0U@r*U2qczT7el*lE?kVc8C z8#2%=Q#l8=0vwfdG(%&F5@AUr0Rkk0{&{Mbna!8AB$yW;EV!5gPb&}PinI=sFUgmG zOGpK{C&;_f3M}=W^ixuhrbtu%4EqNv1<9!j%^5jJEPJ$CW0`&q z^}sHycvZVVy^2@3?pckhU1NTs>R8nCZMy1MwqLkW_SvpQ>##}*Imad zGsmkH+5f7!z zf8pAno~DD?Q8!Je=D?W*xwu{gm+K@C9oNZ|%=kyA|B`u}x%iLF#V1FOZ=JaI=*ZmG zz}!x5><=k=1UkixM+XKso;RS;%XkbKOh_^mG$ca>Di>6+ON}CkgJc7a(sU|8f5rAK z>eTVH1O1nca*a7`E$C-(u&!CBU@bFBpg1)aC_bZsw(NRkHX~C|IiYDFq1o|`(+qO6 zKyVfRbs+rM`?cX`1jxt!E>?d%%B#OAyxKNy^N(V)?L&mI;AMm{{0JpenNiHcRwWKX{j)pN>F=&gik)&ZsqVLSZDs|8%|Kq)06Q<@+p1hzua48gPL z6|j8fRPAOW&;>l43jG>`Yi4VDkdmSqtnPo=>w(a-Ql(aW>j9aXOeUr zzjc{{4+=ECil2l|(^&F(VQoqKSGLt)c5t-Q*g_^hh^sJUojldgJjo9443F&Oj_-_3 z?F^qpIy&*-!}}lp>DT{BCx`krwB0O8r8iUeQk#SK2LIUjr+#uLliL{Jhtrg}xW%T9 z7G5h?5&3;;*{*Avup~D!#Pi$2#&G`>i3*R8D*NL1u)94O{K_smm%To)vCq-axYWF_ z1>M>uawM(Gz>2y1(dW5)j9N@H)X>FiU1yc0z6s<1w z>^)EwjP5TMbFgDLdN#{Hl-qXD0I<5autr~n(M+lT1t=*7!r~S z{0NIY(jjRGos%$t+t)hT85({tet-P&(B$^eQF(x-Uk6^0pf+pJTCpip zz9!DxJM`Xw9RQ54QzlRF>K9JtPdk=bi z1D;Oc%}a>0c}YNTUTSLM{V?!CA@$ZxnBrxDXF$?jk_O~4Zz zQu23m`HJn@%&z49h6Q=xa>I4kBAoWqeM_W8+{;x`R%UKXpA#VK0oZq8K8ge<_7VPvE_$e5MC`mIX2ah9 zBV^xvX~?GEsW^;l^s52vvDkVsxPBA%`^v&~UU$Jr^=>S-h>OmE;XL67gi<73F<5jUmH zJ|jR7_E0q~USYBeZ-0jj7^>~^vZz0(Z~1rr^}!uJLO6!b%(R^W{{&`_{|RM5YvR3;Th6W`Nzzj?@swQMQ->tDvjN$g)}@hW1jt@aM;;JtVPHYJ Nm&-`AEdqq^;=d<==>Px# literal 0 HcmV?d00001 diff --git a/src/application/services/order_services.py b/src/application/services/order_services.py new file mode 100644 index 0000000..37199f7 --- /dev/null +++ b/src/application/services/order_services.py @@ -0,0 +1,68 @@ +from domain.orders import Order +from application.ports.order_repository import OrderRepository + +class CreateOrder: + def __init__(self, repo: OrderRepository): + if not isinstance(repo, OrderRepository): + raise TypeError("repo must implement OrderRepository") + self.repo = repo + + def execute(self, user_id: int, description: str, quantity: int, total_price: float): + from datetime import datetime + order = Order( + order_id=0, + user_id=user_id, + description=description, + quantity=quantity, + total_price=total_price, + created_at=datetime.now() + ) + self.repo.save(order) + return order + +class ViewOrders: + def __init__(self, repo: OrderRepository): + if not isinstance(repo, OrderRepository): + raise TypeError("repo must implement OrderRepository") + self.repo = repo + + def execute(self): + orders = self.repo.viewAll() + return orders + +class ViewOrderById: + def __init__(self, repo: OrderRepository): + if not isinstance(repo, OrderRepository): + raise TypeError("repo must implement OrderRepository") + self.repo = repo + + def execute(self, order_id: int) -> Order | None: + order = self.repo.viewById(order_id) + return order + +class RemoveOrderById: + def __init__(self, repo: OrderRepository): + if not isinstance(repo, OrderRepository): + raise TypeError("repo must implement OrderRepository") + self.repo = repo + + def execute(self, order_id: int) -> Order: + order = self.repo.removeOrder(order_id) + return {"Result": f"Order {order_id} deleted succesfully"} + +class EditOrderById: + def __init__(self, repo: OrderRepository): + if not isinstance(repo, OrderRepository): + raise TypeError("repo must implement OrderRepository") + self.repo = repo + + def execute(self, order_id: int, user_id: int, description: str, quantity: int, total_price: float) -> Order | None: + order = Order( + order_id=order_id, + user_id=user_id, + description=description, + quantity=quantity, + total_price=total_price, + created_at=None + ) + return self.repo.editOrder(order_id, order) diff --git a/src/domain/__pycache__/orders.cpython-314.pyc b/src/domain/__pycache__/orders.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2dede9ddce83ceaa679eff1b47710ffe3941bc56 GIT binary patch literal 956 zcmY*XK}*~~6n-;FcH^$PxK&r7MYK>@TFs#z3YF4ADGF8FlzJ&T#3YLYNyg617QERa zc=UJl=SXh@LQ7BHT=&o(`z9O34$RBWm0_>6*ScK5&KcHk)qNe41tyCK!y4(M9wU=`PR+cHUI zOfb`KyIkB3?%_U~HFAvUd-T}}K!V=;@SYry06vgU@SKL^5yn)QR+ymQx#M>$OwsRE z*g;&g7@MeHS^>rvwiCt^Q}3%0XeOzOB|p?$6vqGDj|$E8k!fn7ql_I&9;c=e%M^!_ zut=jEhZov7N=xJQG7)KM#dN8u^@PkLZ6+8iXPNL=Gp20erDL-l9Edy(q)0^YTEzW4 zEwl=99!r6pe8Dm*coQl8>fOfj^77_?ekJ1|5qZRmpcJ514v)+@V^L9HmpWz4w96T< z-1XVE)E1h*r|=DaO-_B?9C$#;pazKF4(b;B(4IMWrw3z}G@#YSpr*y+(C(bOvx5ms zCShv++?~5_AsOP0@Ex|gb>lNuM7b^BU@R9&KeHGc!!c&nNsF-_mr7^6NDG0-Q+Imo z^@|u?GdL#H!DAe-mVCdjQ#Fdb9b}wl8Dm`{?^#v$8NHO#Xl3ojlyd9HQ0^(5fb86y zY~fF9-aheEN&E83zc$LAv$Tx1HyVF!B;|!%L~2W^B{WwKA>;xUFW|vX()dGbWc~`! N3>~1&YfH;J{s9pt@B;t< literal 0 HcmV?d00001 diff --git a/src/domain/orders.py b/src/domain/orders.py new file mode 100644 index 0000000..f5e25fb --- /dev/null +++ b/src/domain/orders.py @@ -0,0 +1,11 @@ +from dataclasses import dataclass +from datetime import datetime + +@dataclass +class Order: + order_id: int + user_id: int + description: str + quantity: int + total_price: float + created_at: datetime diff --git a/src/infrastructure/adapters/persistence/__pycache__/models.cpython-314.pyc b/src/infrastructure/adapters/persistence/__pycache__/models.cpython-314.pyc index 138ba89f2226b19527b1b3f7682f8654ab0a036d..7c947c575287db2a0cb9aa473829945eb3082fb9 100644 GIT binary patch delta 749 zcmY+B&ubGw6vt;K`zxDtvx!MsO|gW6vbK6E_EPMn)UDczOGFUTxMqj4m}J|@1kEXX z5b@Rx@z7(A?ah-1{|7I!f>{s|@!+k8;MtjhLNl=6_vZ5+@4b2ZMft58E5@7-*m-(< z?4P5dv2gI5-9oSr9Jm8)NTH1=vQso=OH{IDDlhRE+EHwks!N~*s=!Ij14pW>Ybjm{ z0ICTpGpbyoX-8cKmiCvYSn@Eqnos2IR^ZY^+j1$c`E5LWf3|#vlFT9T+b-!hUg3Ts z`yCIz*|t!k^g8}g4-;clgAp`Gf8c9{4^Q;bOY|sR5iXNqR5m{_8-hBZ&;bAH}G&PQ3CFF zYh;jRZ7oO)W{AmT&&rcLzZAG!;Zo#M;=*@HBqoU_3N(C=lsS_*%XqlkB>o}wgHECy z_1q5iX`d(}Mg!`$8f=G6OjJ(vCc!QpV6Wj)a*Y?^?TJ{}BKNLe2p_TggvmSby|@_e z{>qi2gVVK-G|p{=_QWVg&&FG^VTJc6g@u#yn8tStnv(^42ldv%;F3|EU~O6%pemO7)scJSd|$x*b>B`0oQ$*4Iwkx`M6 zdvY`51V-M;B249M96;$Jj>!|5d{iXBOd#Q>$$pEgxG*O%CpjZEx3UOiWDyI9V4ZxO zMaQ2Frm%k OquB(OZwx>RtQP>x`7sv& diff --git a/src/infrastructure/adapters/persistence/__pycache__/order_repository_sql.cpython-314.pyc b/src/infrastructure/adapters/persistence/__pycache__/order_repository_sql.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..6d4e029183ac8507fe74fef627c72244ce7a0dc8 GIT binary patch literal 6439 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 list[Order]: + models = self.db.query(OrderModel).all() + + return [ + Order( + order_id=model.order_id, + user_id=model.user_id, + description=model.description, + quantity=model.quantity, + total_price=model.total_price, + created_at=model.created_at + ) for model in models + ] + + def viewById(self, order_id: int) -> Order | None: + model = self.db.query(OrderModel).filter(OrderModel.order_id == order_id).first() + + if not model: + return None + + return Order( + order_id=model.order_id, + user_id=model.user_id, + description=model.description, + quantity=model.quantity, + total_price=model.total_price, + created_at=model.created_at + ) + + def removeOrder(self, order_id: int): + model = self.db.query(OrderModel).filter(OrderModel.order_id == order_id).first() + + if not model: + return False + + try: + self.db.delete(model) + self.db.commit() + return True + except IntegrityError: + self.db.rollback() + raise Exception("Cannot delete order due to existing references.") + + def editOrder(self, order_id: int, order: Order) -> Order | None: + model = self.db.query(OrderModel).filter(OrderModel.order_id == order_id).first() + + if not model: + return None + + try: + model.user_id = order.user_id + model.description = order.description + model.quantity = order.quantity + model.total_price = order.total_price + + self.db.commit() + self.db.refresh(model) + + return Order( + order_id=model.order_id, + user_id=model.user_id, + description=model.description, + quantity=model.quantity, + total_price=model.total_price, + created_at=model.created_at + ) + except IntegrityError: + self.db.rollback() + raise Exception("An error occurred while updating the order.") diff --git a/src/infrastructure/api/orders/__init__.py b/src/infrastructure/api/orders/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/infrastructure/api/orders/__pycache__/__init__.cpython-314.pyc b/src/infrastructure/api/orders/__pycache__/__init__.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9396fecedbdf3db05012317b8c5f563ea59416db GIT binary patch literal 199 zcmdPqjTva`(22JC4M z-h1gk(X)So|A2yESj@>&Z_cYaOkvOFhGS$7q|!fn%=0@Tx30h5OJfo~k4#BrWdrBKcys z(zlF zu#$GFVlWw%u?U0;R=N9JjCwLsdGDpJeZWW57To9dHuvHY4P<1Gm?wBd#h7_Cvgdua zTCF#i?2+(n7W4&hK^gxn5c`gaw~a)s!gF;Tt`E;s|^GR{4QPl zexo(Hb$7D9{m<0OJ0#gUD}cH5%UJzktR9bl8tapCHF+hL(f@6;m=^oU3^I~;Q1-Z> zmWMwY8wiy*tzRb3LRTv%&$`fM*2f8CS@R~Bo{hL459xDp6Vs@rW^|tEgpeuRo7%Q6rR~XJ9ca*Zkjf6(zs2bSZ(Y=tF}@LC6t0w)DpHKg{C5tUAmEVXG?u!Rx)7AC~3WJ_7u zma~ejWCL~}8?=L*Cr)%_Lw0C{yhyi_z0Ixc@QdNe0q=lzuS$F23~Z{riKxmZQtoNV zL_lWP<@%{lCa|e}LTr`Q!PW^~a6+i#gdUI?_3!PD)wWC+WV$PDL_1{q z)YvFV^(>)SN^rWyCnr>+YHQ4iWT&PkkG@gVOj|c9DcK1hVOqh~o@FKAhNgAxbw0G5 zNNfDW{6xu#soJbD=dR-uk)tKu=4r_eJVCUV zvp{NOn!F?&c#n`0%ngy}=xbD^IpDZW6>>srEc)i9oaD`CBzUL1gzKC@)zVmAFFE0o zW)+#vU+4r+R|^$ex96R(ZPWMrN+iq%=IVq2M6y~qqWXbyI#Y-eSd!UYTLQX4Rry zWm=|S>KOyIY&E;IIq!7m^My(U?qzHFJlhQCqKd4CfYiwEq>F~`BDpf!!0zf1-d*3r zyYHXpyk%HRiY<-6M*x0Y%b&xbMsl9^Ne*Xu^K9O;RZ~ikX=zgS`0f4_JvF+wx%((d zlAPl46jB;O+)O#w<;|%i7xuK9N!wUW#G#a01#JS`p0H>1tUp!>h4AAh0ru;~0`2B)veKKocv6 zY8GDoL1@V&+l0LCBDeiKhlOo}DO8<{H-a(@i!k46E!eKW)H-1!02{duSq`z)~mZ?YBS~z9dCiKXh(9;U>pjoRcIna1r`>n8xoSxnl8-Vdmmjf}S_@ z0e&SD2J5s9I!*6q8PmkW*c7IP8St4Ql0)0$O$7&4#kRXn3-CPY#L~wA_@A+7F@7Z> zUL|LYYNf<2ASE%B_8EW#p9>E9K#2D z_zW*@*iXRdZ*@}!+l524Bmf2P=rhNAl1Fg${gNn{LBdlD>J)Q3#Fu7v@6n(@?J(edu;w8A ztha&O8(`cF-@EzKkq<|{dFbYIxdtI;>4b23WSNloG2x=ph>~D*t+4aQ$^hx!xSoPw zBV6EvLoKIXlS*N`#0@S|CA`#*Z95woh5WFyWe(>Uv zcSr7eyxx0w$Ln-(MSz@&f{6x>8iOb}e17=inK~VAF}L`bxT`A(Ud<(c6JW&O@i(y( BxRL+> literal 0 HcmV?d00001 diff --git a/src/infrastructure/api/orders/__pycache__/root.cpython-314.pyc b/src/infrastructure/api/orders/__pycache__/root.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e7ee25db17da1257273c77daab66164cfae8ac0b GIT binary patch literal 748 zcmZ8e&ubGw6rS1NDVu0wL8(exJS`drv`48FjhMs6Fr_`E; zt!AC3dB%7{ViKzA+$;b}%j^)`0JY|I)YKMm0nYXG5e3D&sA(+71#m$>FlzDzbJ0DW z>cBY{2uO)W4Qf)0+C&HKj_!Qb+Outm*QBw+Wpvmncbv}v9sQL-eV_eP@CorN ziY+VFc@U@VyvH{AHAvMt#2s)`9b^0r-TaC!eJ@nrUmsW}*nYe6dga}tH>88d-t$I87Ke;~+OE_N!~AV>o7sI3pWIQUsf*KVS6VBm@XSxE&-QH@xkscG5BcM|oJi~ncoHZr5-fIQ~4-HV{XV*3gDdKGzU zpYs;8kvF(q=5EkpZQGWQj_=dxAYb03*?_6ADR FastAPI: + app = FastAPI(title="Orders Microservice", + version="1.0.0", + description="Microservicio de gestión de pedidos") + app.include_router(router) + return app diff --git a/src/infrastructure/api/orders/orders.py b/src/infrastructure/api/orders/orders.py new file mode 100644 index 0000000..65d8547 --- /dev/null +++ b/src/infrastructure/api/orders/orders.py @@ -0,0 +1,77 @@ +from fastapi import APIRouter, HTTPException +from application.services.order_services import CreateOrder, ViewOrders, ViewOrderById, RemoveOrderById, EditOrderById +from infrastructure.adapters.persistence.order_repository_sql import SqlOrderRepository + +router = APIRouter() + +@router.post("/") +def create_order(user_id: int, description: str, quantity: int, total_price: float): + service = CreateOrder(SqlOrderRepository()) + + try: + return service.execute(user_id, description, quantity, total_price) + except Exception as e: + raise HTTPException( + status_code=400, + detail=str(e) + ) + +@router.get("/") +def view_all_orders(): + service = ViewOrders(SqlOrderRepository()) + + try: + return service.execute() + except Exception as e: + raise HTTPException( + status_code=500, + detail=str(e) + ) + +@router.get("/{order_id}") +def view_order_by_id(order_id: int): + service = ViewOrderById(SqlOrderRepository()) + + result = service.execute(order_id) + + if result is None: + raise HTTPException( + status_code=404, + detail="Order not found" + ) + + return result + +@router.delete("/{order_id}") +def delete_order_by_id(order_id: int): + service = RemoveOrderById(SqlOrderRepository()) + + result = service.execute(order_id) + + if result is None: + raise HTTPException( + status_code=404, + detail="Order not found" + ) + + return result + +@router.put("/{order_id}") +def edit_order_by_id(order_id: int, user_id: int, description: str, quantity: int, total_price: float): + service = EditOrderById(SqlOrderRepository()) + + try: + result = service.execute(order_id=order_id, user_id=user_id, description=description, quantity=quantity, total_price=total_price) + except Exception as e: + raise HTTPException( + status_code=500, + detail=str(e) + ) + + if result is None: + raise HTTPException( + status_code=404, + detail="Order not found" + ) + + return result diff --git a/src/infrastructure/api/orders/root.py b/src/infrastructure/api/orders/root.py new file mode 100644 index 0000000..a84bc57 --- /dev/null +++ b/src/infrastructure/api/orders/root.py @@ -0,0 +1,16 @@ +from fastapi import APIRouter +import platform + +router = APIRouter() + +@router.get("/") +def root(): + uname = platform.uname() + return { + "machine": { + "OS": f"{uname.system} {uname.release}", + "Arch": uname.machine + }, + "Status": "Running", + "Docs": "/docs" + } diff --git a/src/infrastructure/api/orders/router.py b/src/infrastructure/api/orders/router.py new file mode 100644 index 0000000..4a52cd3 --- /dev/null +++ b/src/infrastructure/api/orders/router.py @@ -0,0 +1,17 @@ +from fastapi import APIRouter +from infrastructure.api.orders.orders import router as orders_router +from infrastructure.api.orders.root import router as root_router + +router = APIRouter() + +router.include_router( + orders_router, + prefix="/orders", + tags=["orders"] +) + +router.include_router( + root_router, + prefix='', + tags=["root"] +) diff --git a/src/main.py b/src/main.py index aa15ff6..a4c4fcd 100644 --- a/src/main.py +++ b/src/main.py @@ -1,17 +1,52 @@ -from infrastructure.api.users.app import create_app +from infrastructure.api.users.app import create_app as create_users_app +from infrastructure.api.orders.app import create_app as create_orders_app from core.config import ConfSettings +import threading +import uvicorn -app = create_app() - -def run(): - import uvicorn +def run_users_api(): + """Ejecuta la API de usuarios en puerto 8000""" + app_users = create_users_app() uvicorn.run( - "main:app", + app_users, host=ConfSettings.host, - port=ConfSettings.port, - reload=ConfSettings.reload, + port=8000, + reload=False, log_level=ConfSettings.log_level, ) +def run_orders_api(): + """Ejecuta la API de pedidos en puerto 8001""" + app_orders = create_orders_app() + uvicorn.run( + app_orders, + host=ConfSettings.host, + port=8001, + reload=False, + log_level=ConfSettings.log_level, + ) + +def run(): + """Inicia ambas APIs en threads separados""" + print("Iniciando microservicios...") + + users_thread = threading.Thread(target=run_users_api, daemon=True, name="Users-API") + orders_thread = threading.Thread(target=run_orders_api, daemon=True, name="Orders-API") + + users_thread.start() + orders_thread.start() + + print("✓ API de Usuarios ejecutándose en http://0.0.0.0:8000") + print("✓ API de Pedidos ejecutándose en http://0.0.0.0:8001") + print("\nDocumentación disponible en:") + print(" - Usuarios: http://localhost:8000/docs") + print(" - Pedidos: http://localhost:8001/docs") + + try: + users_thread.join() + orders_thread.join() + except KeyboardInterrupt: + print("\n\nAteniendo señal de salida...") + if __name__ == "__main__": run() \ No newline at end of file diff --git a/src/main_orders.py b/src/main_orders.py new file mode 100644 index 0000000..00d78d7 --- /dev/null +++ b/src/main_orders.py @@ -0,0 +1,17 @@ +from infrastructure.api.orders.app import create_app +from core.config import ConfSettings + +app = create_app() + +def run(): + import uvicorn + uvicorn.run( + "main_orders:app", + host=ConfSettings.host, + port=8001, + reload=ConfSettings.reload, + log_level=ConfSettings.log_level, + ) + +if __name__ == "__main__": + run() diff --git a/src/users.db b/src/users.db index c120b74fceeaa854aed95dc0db7161537233d18d..0a471ff62a9a9f452dc3ace17808d22ce6219f82 100644 GIT binary patch literal 53248 zcmeI*&u`jh7{GDAaRN1vc&fB|Op5mQv{+p-AU~${RMyfh8X*lOQ+gS4z->?oq{flj zNjs#s9roAkU)ZtQt{_l|R6bIKP_9X-D9R=8KJDG3TgF?Mj8?q=BDOqg@shIe>%V@HO!`wrzpsBX z^ZQJ1=CkRw%wL&bGKKUXY1eyz8v+O*fB*srAb>% zPOtu8-|Dz6_ffbyeZ5*L)=F}{;_5%u0}*+{o4B>rwUQsc zRb5>xR`1B~OLyd4)RUPqt5XTXG(<1jD}G14`rb~rV+V_g{$_1fRyQ_dFN0W~j}@%S zx!`%``eefR+z{R4H9OXBSaRx(CH=HmMSs<-s>7PJcdb@C7x^Sty;p9mm;00IagfB*sr zAbMoT(O>F+k9sC?1Q0*~0R#|0009ILKmY**5IBDVX?0eM zz8er8{~s#)p?-M&wuFumKmY**5I_I{1Q0*~0R#|0V7S1vdRZHM|3AF`-xEcDGCZ3o z0tg_000IagfB*srAb=-#`Ttjn{_4Zp7P>(I0R#|0009ILKmY**5I_KdcOo#U3auF) z|36doXYZsYMG!y$0R#|0009ILKmY**5J2Ee1ZLHu_J8O9{onsPljax{0R#|0009IL zKmY**5I_I{1m3g2;P?MtDEf={JQ(E>KmY**5I_I{1Q0*~0R#|0U_1gB)hpVGYXgLz z|L6Swcy<7zAbqH%6ab5