From 62acb941dc62a4ec43d8320dc041c8397058f64f Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sat, 25 Oct 2025 17:03:39 +0000 Subject: [PATCH] V1 --- config/__pycache__/settings.cpython-311.pyc | Bin 4210 -> 4278 bytes config/__pycache__/urls.cpython-311.pyc | Bin 1143 -> 1446 bytes config/settings.py | 3 + config/urls.py | 9 +- core/__pycache__/admin.cpython-311.pyc | Bin 212 -> 662 bytes core/__pycache__/forms.cpython-311.pyc | Bin 0 -> 2947 bytes core/__pycache__/models.cpython-311.pyc | Bin 209 -> 5316 bytes core/__pycache__/urls.cpython-311.pyc | Bin 347 -> 2654 bytes core/__pycache__/views.cpython-311.pyc | Bin 1364 -> 9658 bytes core/admin.py | 6 +- core/forms.py | 38 ++++ core/migrations/0001_initial.py | 32 +++ ...te_scadenza_documento_identita_and_more.py | 61 ++++++ .../__pycache__/0001_initial.cpython-311.pyc | Bin 0 -> 2057 bytes ...ocumento_identita_and_more.cpython-311.pyc | Bin 0 -> 4056 bytes core/models.py | 85 +++++++- core/templates/base.html | 26 ++- core/templates/core/article_detail.html | 155 +++++++++++++- .../core/attivita_confirm_delete.html | 12 ++ core/templates/core/attivita_form.html | 13 ++ .../core/cliente_confirm_delete.html | 13 ++ core/templates/core/cliente_form.html | 13 ++ .../core/documento_confirm_delete.html | 12 ++ core/templates/core/documento_form.html | 13 ++ core/templates/core/index.html | 192 ++++-------------- .../core/portafoglio_confirm_delete.html | 12 ++ core/templates/core/portafoglio_form.html | 13 ++ core/urls.py | 41 +++- core/views.py | 158 ++++++++++++-- 29 files changed, 717 insertions(+), 190 deletions(-) create mode 100644 core/__pycache__/forms.cpython-311.pyc create mode 100644 core/forms.py create mode 100644 core/migrations/0001_initial.py create mode 100644 core/migrations/0002_remove_cliente_scadenza_documento_identita_and_more.py create mode 100644 core/migrations/__pycache__/0001_initial.cpython-311.pyc create mode 100644 core/migrations/__pycache__/0002_remove_cliente_scadenza_documento_identita_and_more.cpython-311.pyc create mode 100644 core/templates/core/attivita_confirm_delete.html create mode 100644 core/templates/core/attivita_form.html create mode 100644 core/templates/core/cliente_confirm_delete.html create mode 100644 core/templates/core/cliente_form.html create mode 100644 core/templates/core/documento_confirm_delete.html create mode 100644 core/templates/core/documento_form.html create mode 100644 core/templates/core/portafoglio_confirm_delete.html create mode 100644 core/templates/core/portafoglio_form.html diff --git a/config/__pycache__/settings.cpython-311.pyc b/config/__pycache__/settings.cpython-311.pyc index dadfaa7db630a06a9bc0da9edbc375273aefa0ed..6b525068ff246d2381be6586bd7cb8675c27b861 100644 GIT binary patch delta 167 zcmeyQuuYM7IWI340}xDN{F`xfBCjOlmyPNtnG90&qvTULQw*xO85p7zfGk503rHJ* z=yawi#T4Txr4*AW>%?QNB+czKLZD8Vmz$4ngd4pGU2Kz-``3A1ZP67r1 D281pj delta 102 zcmdm{_(_3xIWI340}wn|@;#$(BCjOlvyJK}nUqpFQ}nC285n@H0fZ24CSR6<#FC6# z?3sDVIi)G7nvAzNic?EUGV{`lfo!(olEjkC z^#j9h&-^_NJHy9KyprRWLS{G2!2Q~&)&dGr+V$nBPI2v3!Bqo?nv6^Ckkwy6m zi}D9nW`3py?hjlHEIciC9~c-J0~v3y@J}$CU^YYJij>X{k1IC*7lZ>Y3I|*Pk}LrY R-XQpa8Ke-Ryhse_9sqchkrV&` delta 232 zcmZ3+{hdR7IWI340}vQ{e#%g1W?*;>;=lkql<~P{qPnUG6GJL%3QHHWlNx(wUUE)pO6o0^g2a-HDz?Ow+{`@v zTMSj4$@xX8dZk4<#eSNclb*Y8Ug^i C_Bgiy diff --git a/config/settings.py b/config/settings.py index 001b8c8..a7247c1 100644 --- a/config/settings.py +++ b/config/settings.py @@ -141,6 +141,9 @@ USE_TZ = True STATIC_URL = '/static/' STATIC_ROOT = BASE_DIR / 'staticfiles' +MEDIA_URL = '/media/' +MEDIA_ROOT = BASE_DIR / 'media' + STATICFILES_DIRS = [ BASE_DIR / 'static', diff --git a/config/urls.py b/config/urls.py index 5093d47..d60536e 100644 --- a/config/urls.py +++ b/config/urls.py @@ -15,9 +15,14 @@ Including another URLconf 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) """ from django.contrib import admin -from django.urls import include, path +from django.urls import path, include +from django.conf import settings +from django.conf.urls.static import static urlpatterns = [ - path("admin/", admin.site.urls), path("", include("core.urls")), + path("admin/", admin.site.urls), ] + +if settings.DEBUG: + urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT) diff --git a/core/__pycache__/admin.cpython-311.pyc b/core/__pycache__/admin.cpython-311.pyc index cd6f855b12f4883b1ba9de01c54245c53aacd714..2bd112af4ee787880f718c6f1607ede394baf911 100644 GIT binary patch literal 662 zcmbVIOH0E*5T0!wO)D)zuWjiy2b({jf+(m6B6yM9(qwH@v)QuQ__+H6yoonYiuh*| z30UGq@YI{oTS0JB4MZ!OtjSIKE~Yb4T!RA+@_--{ zA#h5LO%O%(w~!*Wi))$*#Cv2=$39>x2ze{tjmILZPX^*6_n4?$NZ znN%I6isca3pJdu~IW2E`F7`Q2mkuc7)-mmSE={!!&fQa&TWMvB+944WbYHKeb!TY# zecH9D&zaj}*>O{qPzQSfQ$)kmEM(VX+2K+-aK&zo;l3Mi%pPDWP?)V414^(F_ClYB z20q7j$SE_UYGHlF+c1IU8ZB={`dU%~J3wEYFxDnx9LI{na6aDlttVMtM zD=3%MXJ|Y@<7zvGW&+I!n&Sex7egnRFD{}xF|-nBMbIjuyD_vAXh*rTx={BCXO@t8 delta 157 zcmbQndWA7%IWI340}y=Q^((_3NIwQ~V1NnA_$&luOlL@8NMX!j$YqRTWMoKT3TDt` zehE^b$#{!3F(o%M&rg%-7GFwMVqSW_UUGh3Nl|7}5i?N1z@L zKQ76k2aX(&!hu5%6%C~aj-2}!tR)|;Jw@s%HzVi;sZ!sY#Wvmr+DNEl@7J?4Z{Ga+ z%p3pO*B9p?{l@?Oa8cyAKk=oVq@&FKACP&;5svU>&f-;`=SYMI<%lJyf+eb=C8?4n zt1{0;xH*o9KXF7d_(w|H(Wbz0+wk~FjWR14tdujXV$3QER;=zR*5sL5+wP6 z%lEy(0pxj4TCk~AeZ%9M=qX>8O{3x%UgB$;I{JdWST=1hdfRc#Wz*5U*d4o6v%tbG z`4jLJR*R+mG5C4O8Jx-!PK~hf@GzdpW&~ypkDpY52rvfGOB{7K3uEYU*jer`phefA zA*dqZRf&LWL+&mr5r}B=ze}4ijcuF?OD3;Ii3}YnhpA&7UAt#EI?OyfZ!N(jZSB}p zHJE8lFB@L}9o^A2VroUbTEdx&&eJ8s6N&B^Td-=nJ`R?#g()4aH*SvIMa zF`v}5AHk1bLvc2q1eHeFQ;a92a*Y@i8G!W!fAf{4n&T;tO|ob>)h%uxM}PQH;h}9A zh1&PEic>2XPmEH{v1#G4O@F8^=_R93vZ+yEyLWBrsVCyBXcAgtZ`DshUUWXq)X<95 z9K61wyiQ(Pf4*MZc)qi+yWmdTbw_6FBeRW>*_IGV$5#~m&@42jmq3bJB2D8<2IZZ0 zF};X6X7wKC@Ypax4yrdnx?Q&-k`!-oVcEm7gA*!z$LO;M3G|KWZ5iu7w!Is7zpFgQ#4I4mo<&{Lo1p>834&g zyaYpVzG6OuBdC=8gIUbSgF7N)n|DDxdBHTwq{`5u!&s8|$|S_7Fv92sGz@GV?lQd$ z(g#m<9;CZ<%~Tes8MwG2zs`=YPi)-U8QmRqKfdi|XX@FRMs}t-G`3o642{)?#v4Q9 zElEhjPJ@InqVHojfv$5{hJw)U2dR;fny~C)*}(}FJ~im>T&PL5LtY4(PH1`oeVqp~ zaDParU=@QdSPEbzZwP9fC=lABhXcn)%9x^8piO`$h+n2<USW=c^Yo>l)18cckTYG$(>1ee9FyC z*E7?N%yct-d39p#)~nH-Q8$0XO;6R+Q;qag05e5I%s~DdX5%mhih|)Q6r2>qEG&Ci zc5p(4j~Ti<7tH!P_i2c;|1&fV_6*}xh#)AXSWtp{@j*$4!1An3Q79^5L_CQidNw+r zK(ib?p-^<8jZUucv-C^<&hqZEJ2~s-=IXh*Ms6;^$XkY@>o{1H5zOG97=NF!sF+WB zGI^v|7H$8|mf1yKWw$zI!IzyFoUj+WhnGC=rGF{r&=n()b~#o7}M5`)zWcx&QWUi87CIGbF25*9s6jd5oRy%9Mh+u&f$uHXH!7?Nkm% e(Kal2UiYy4pj(;gwCc9U93J_g-;M=a@P7b6$YB5g literal 0 HcmV?d00001 diff --git a/core/__pycache__/models.cpython-311.pyc b/core/__pycache__/models.cpython-311.pyc index 9aa598b9d5171b2bb0d207f045e07f9fbbb95a64..2d874a7208509e6fc1d26dfdc633d49ab5da5a9b 100644 GIT binary patch literal 5316 zcmc(jPfQzE8o*KGHk(E<1`cNK|IP}1wQY*EU&}x+>8x9=y&|{Ci?Tj>9S##YJr==pNNGt94y|E1$lccwOc)oe_ z%{TA=_j}*tZ;?odfi%JVcc~a*n1AC#GkF`C!@oo3J4R$gm%^;L=3Oqv&D>!`_t%W* zkzC8}<_Awb4D%c=JI#Bj6$@70H(0UM$_G~dH&}V8RRFAlZ?N)-p;;yu-p2;yT$XP| z6(vP0H5x>3zQ)7hS1#<7#LT-yX5L+f&i%zT?-AXir|h1GMoHe~rY$3~yWXc@{~Rtm z&HLYK5pY=eME`E!DGb*0)_~0isSTY1EcYo~&+Q68&W9Z(1lwA{Q45$jJ2}3OI=*l3 zMa*Fllsvm3M;qg9Hf)jW^W@wFR~r>Mw-uNss)8;UL{PCEsn z#?%w(Z*zL=efWJZ{;1eFJ@Eb^Hg__YvI0C`5mqFgw?aG*Wv?li=Xn0}H9={-iOd%B z#VNjUcWS&aI%{6}3J$%6kUogWLY9saN+08{W zdUoesJvwMa2hHeU?M^-Q-qr&%_1<3M=Mg=XH&S^sm9I_Kx$ey|lj}CP9+T^-jn-p5 zo9kw*XXlb08#H2rW^Ax_x1R3bS~S!BM*6&&K3|)vN4hs3n33+CPCYVULrKy9oJ zO@Wfm?6~*t>)f!x4V&CB6d2EL`OJ8BXITGmT#w%~;`hw>z1n!a_v&`P*?aYugkJnq z=SzA;(|fB%Z`JIr>TJ&e>+%j9Fzvz~I~=wWT&>jFTyDb#t3lSX%jo&GMLX$24htWU&hH={@|ImjKG>xM#K3OQVH2S?(WZ@qxX4p>8A(Hv z7!t#~oTCI}<=bo$zoR9cVuZ3Z3b=?_;bW^8d1`S5wW3J`5GjKjT!r?4GBhkJLZu`l zH?K8R`Er>^nub=_L1l%|8*D##=C*=rg@;X4s!A3|Bn5m(r2bEE(;{IMh)Y803ijRw zsNge;t*j{u!3}|Qf&lCyX-NviD`aFrLCM$;nYWQqbpOQ8GS57d8}97+m#!RiD2{wQ z?zxt~WN#|u43ubt()L_*<&Dl`!_=hT1vEtGrt~ut=k(YO`0ZTTy=muA25!)W37%*5aS0VnsuhBLu)-99 z;}tX_AD|}oKv1B5p6ZaMO+`T^1h-z?V5&Ce$R%t`76m2U70jWa1Nk4wyh6GjBwa)3 z>}fz-EQ=KD+4k>U`^PPP`jH-eY(yWM(Z>L@%(<;~Gjne5vYxqaWUiZ;>pGjPcjdlM zn_aoR89o1Jy=%_snlroRbT(b@yRtoI_Feh;$}ghcH(~Tmn0*sE`%XR4yVY+ddW}S% zndqxc)YCcS92D@YOHbc3()Y~tJ;2>-)Zx=Md;4~ZdiatNzGQ|k)kct9e?W3Mg*_HH z0wq;z^8DXrl2XEc;`@^6!ZRkI3W`eQoqYGI^IxKRPIowukCjHqOWzIhqRudmCRnk`78st9D()~04lf+$rsgzVJ9f+Cj%>IS4} zzwMZj;2SJIo3B*pzWphE15}iSio7U;m#E}{tqY+i0nkwOCs0`dq0xBq5j+;jO_2N4 z1rTaB-sra;8aomk7?K9@3dwM@f?;G1alyQmWEk_cjsXz!d1=hI;mHnUa~_K=%B!ly zqC4A|IFV)X=Abu0R)CtdJ`k-i4ghv@oBeALZt&X?cOjs|oF2GISNCKt>BJdV9G^a7 z7?wssMn*A*og`x@ur5j+@(6N3DtV<5ha6Mw%R{I z94Ad638ZO?+9wA|CU~wM=!2Ll<%19_;N;G{9(`y;ADYpJz@3K68{uv<+zpXd=+tJv z89KF{+!@hB7md(GGjy?5Xqs)4y_8vxMJGHMb4v3ER_c~6gh2)~`= z?io9WGVtMRe4jjq&tLEDG*-crE1`}}LykBNISK*+#M0TZYz+i4O=MfaFb|KjLnU)lvEY!{pB-+c8O>R%ka{2=av(P$T2zHd1! M_aiLVX+g*9f6!RjLjV8( delta 150 zcmX@2d66-FIWI340}!mp_?2M^q#uJgFu(+5d=>&SrZc24q%h_%Y=G)Yb5iY! aIDle|KwK<4`L(bV_XP$SASz-5iU0sA2O#(W diff --git a/core/__pycache__/urls.cpython-311.pyc b/core/__pycache__/urls.cpython-311.pyc index 1f807fae1897c89361c99c5e868a26d00799b73f..e9609bd7a2be2eea6bd98897ee5eaced7f234c9e 100644 GIT binary patch literal 2654 zcmd6oOK%!i6vt=a@-hryTqnkLX%k*0sywQV$U_uShdQxR*RgEJ?zlCk%+!!DfQBJ% z+0;vagMNdwRoZ=*`3UDqcM-9zvdGR-c9AOeUYLP#GPCd4KAQ9Ro%5f=;QN~(%y9I2 z#sAxQ<>k14m}6cso8x}vWKQN=oXSf)&&e*?-EygJ$*m#@sUFFrdL^&wlYFXQ z@~Z(Upw37$YETNQAt|H^lAwmAuo{sfYE+8yoQqR<8ByzgJZp}7MsJ>*4kvs5^gg3= zpVPnbHDY|!B1gt=%LFLnab#v}nIL7nj!ejw5h&wxWWu&ggff0dCTh#fQYPTY#B7;4 z%FH-2AJ{VUlnFXAS8SQ9lnFU93${$0GJ+$sXv=&^nXn_XWXpU+nTR8kuw_1`Ow^J2 z-`3Pk+=@PKUEbprYutX6sVu zuBOy<f`lPTXa8cckP<03}%g}SZucSJKZNGaTqoW<1)rY=rrF?X==UX?sr?4?m`(}UclN^=rZ)t#}ei)uhFxQ(|pYMnF%n%PDU-rOo$nQnJ_aEW}?in!%Ji5+$M?JP<{w#8>4N4wnruB35c&i z{051y;CPfH%lDiLEbwDykGC}fW)aS6e39Da`)lIy*MOL@q zkqk(|NFhiu`do)p2~q`;D&bU_q{=UT0kn_NK0*6NMG7)y$lM~CGR~}#%o=P+fDSP_ zB^4oB50;qvegP?}dhc2fK>05LyIK4*Fw9mJIB#b12B%_2r m_ZnpHkn9@HR_N2igYN+yVRS^$(M4`P;yMemAMI26+WrS|A>_^g delta 255 zcmca7a+|4sIWI340}vcY|CNyiq#uJgFu)3Be6|5HrZc24q%h_%7Ws=T@>f{oKQJ@#Gc|C7U=a_{H~@rSH^%?~ diff --git a/core/__pycache__/views.cpython-311.pyc b/core/__pycache__/views.cpython-311.pyc index 6867ddf286a519cf1754ac97038f9f1e4605fbf2..4b92fcdfb587725572e3882001a83e491f000d0e 100644 GIT binary patch literal 9658 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 UK_|tlpdA@I;tL;6S#{3+8``ZT6#xJL literal 0 HcmV?d00001 diff --git a/core/migrations/__pycache__/0002_remove_cliente_scadenza_documento_identita_and_more.cpython-311.pyc b/core/migrations/__pycache__/0002_remove_cliente_scadenza_documento_identita_and_more.cpython-311.pyc new file mode 100644 index 0000000000000000000000000000000000000000..446d7cc93b15bec0c2fe777cbc675ed54a74a48d GIT binary patch literal 4056 zcmcInO;8)j6`mRWAPIpb8w>)2#g8z;%g^#-oT^l8A;H2fW;Z|_;4(X?8!>n^BlnD0 zo65n59CF-Se57(9Nm&OUIppBu9$Qs&P|Yb-IdPNAoLrTvyzY_2ue07%WrW^zzkdCG zzW4g6`D;r{NPuTW`1kH;iy-`qP3n)YHu#W%!Jh>rAW;*xM0iV@l=p0T^4=}4C`iIr z0`mM(Kwj+GtM3txJc95BzV5T-L*kl{^qsKjN>Xw{c{N8AOEq-U@#hVMH8We2<*)YI z!KuTL+v>U-9{ay&Wk96))bchpKGz}2kbho!ES(SYvc+tF?dB= z;TqgZ&r30Q*tyf1@VRb=Z$x zl!3Y({{;3ET=M5?@k=h%$k3J3G|AW78kkO@>C()_YJ-Y+@L5v-@6$1RZH9uEGnDgf zwWEj74}awZpVa#xG(~ULAlL~{OiX+!tGa5bism$BH5Ka?cDmQH3c~t3sT1zt7=h)eve7F%ka(T6;&g5`0S%^-5AXnq{p4Lr1tk!(}<@rGBkzs zy4?19MDcI8w>34V9B_Si-PPzShCPfEPw9G5(J+a_%89!ffZR3IEH>e%M|mM@SkGCz zj&IFUECal2{!UeNbw|y@lq9%9CzLkw1r0L^G6XEnKVg-a^pJjdIZX)fC`HX818nA9 zF(6L?r3Ujsn5A>9mcOLO2^zW#Il>?mCRk&DyLd{>1;P%B8Z#L6p${qVxals%KnRchX6nJZp8JIZ{mPR?P z5Qv)BQ&OyzgKqpFD+tvjkSf=Kcf1R#h7UrhR)Xp{>Nd!M zm&43ZuptgOgEPvGk<(PeiSWqIb8db|j2%@oWU#ran%P~|NO~ZmFzAJ9+=m;(zCj+l zv4rMSD7~!8@{_8uQn?(#rpct{nCTvtL&H>grN}AM#Fm`WGz0PsmEtsW2$poV?%a5) zXpk|PPoaEH*mdHB{W5|Ftq5n~XlQalQyNu-)SPOWjg4u85Pnue401QhmE>(FAoD!S zvJ;YJxa<@)4CAmYKZh!1XO+zmE?^zbb5_MBVHYQ-c@^i4eZ0Ub!f8(PBl?7$a>8yS zPIykurQqp_U5CK_B<^YvkRS0Oclb^O9|hoJ=sQ_bn$z#;deJw?wMj)bjQ?PeXJ!E)9A~Fv{OlSy4sCBzCOl-hc4%a?-t+1eWXNi*=gEqW08BVxg_nd~ zH8^3n7jp#gdDZw-{X(#>>XF*~ua>JJA$a#sAv@4p>4;aNV^yCg7E&qmKcnrmW8}wuyJO_o`_mxZlBrH;hgt40?GBShtV*k0E*>jT zhSFKA12i#n_|#6!yql(p#d2cNPAt;MQYG40IL^GYXkxjXShf?(H1gz}y|>FWmMX_m zb}U6BbCqbE_Rky++5I!enD%GN{TaJILnHH_hRpZrYQZG_qBR_R{#oq2G>Al;e|je3C|{ zD$#yAID5EY56-@OPJj1%I=E3D+^`2XXk_!huQiU$=U1ZzJ|2i1#GWM%>k@~R*GBYf zsd_8KU~OTr0y$-*IxkM#^uPL=eTY(T9!b9wbKBt<+8%TND;=x%M6v;5@KeUyC9Lxv z%{#H%eZFT}xT7nAX;9#IsbBZ+-fh`WCkVVGX`SM@&-{Z-*A S`7vZi2H&%V(`#0_5B~v2>o6n$ literal 0 HcmV?d00001 diff --git a/core/models.py b/core/models.py index 71a8362..69ef07e 100644 --- a/core/models.py +++ b/core/models.py @@ -1,3 +1,86 @@ from django.db import models -# Create your models here. +class Cliente(models.Model): + STATO_CHOICES = [ + ('Cliente', 'Cliente'), + ('Prospect', 'Prospect'), + ('Ex-Cliente', 'Ex-Cliente'), + ] + CATEGORIA_CHOICES = [ + ('Privato', 'Privato'), + ('Azienda', 'Azienda'), + ] + + Nome = models.CharField(max_length=100) + Cognome = models.CharField(max_length=100) + Codice_Fiscale = models.CharField(max_length=16, unique=True) + Email = models.EmailField() + Telefono = models.CharField(max_length=20) + Data_di_Nascita = models.DateField() + Lavoro = models.CharField(max_length=100) + Stato = models.CharField(max_length=20, choices=STATO_CHOICES) + Categoria = models.CharField(max_length=20, choices=CATEGORIA_CHOICES) + Importo_Portafoglio_Attuale = models.DecimalField(max_digits=15, decimal_places=2, default=0.00, editable=False) + + def __str__(self): + return f"{self.Nome} {self.Cognome}" + +class Portafoglio(models.Model): + PROFILO_RISCHIO_CHOICES = [ + ('Conservativo', 'Conservativo'), + ('Bilanciato', 'Bilanciato'), + ('Aggressivo', 'Aggressivo'), + ] + cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, related_name='portafogli') + Nome_Portafoglio = models.CharField(max_length=100) + Profilo_di_Rischio = models.CharField(max_length=20, choices=PROFILO_RISCHIO_CHOICES) + Composizione_Asset_Allocation = models.TextField(blank=True, null=True) + Data_Inizio = models.DateField() + Valore_Iniziale = models.DecimalField(max_digits=15, decimal_places=2) + Valore_Corrente = models.DecimalField(max_digits=15, decimal_places=2) + Note = models.TextField(blank=True, null=True) + + def __str__(self): + return f"{self.Nome_Portafoglio} ({self.cliente})" + +class Attivita(models.Model): + TIPO_CHOICES = [ + ('Chiamata', 'Chiamata'), + ('Riunione', 'Riunione'), + ('Email', 'Email'), + ('To-Do', 'To-Do'), + ('Avviso Cedola', 'Avviso Cedola'), + ('Scadenza Obbligazione', 'Scadenza Obbligazione'), + ('Revisione Annuale', 'Revisione Annuale'), + ] + STATO_CHOICES = [ + ('Pianificato', 'Pianificato'), + ('Completato', 'Completato'), + ] + cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, related_name='attivita') + Data = models.DateField() + Ora = models.TimeField(blank=True, null=True) + Tipo = models.CharField(max_length=30, choices=TIPO_CHOICES) + Stato = models.CharField(max_length=20, choices=STATO_CHOICES, default='Pianificato') + Note = models.TextField(blank=True, null=True) + + def __str__(self): + return f"{self.Tipo} - {self.Data} - {self.cliente}" + +class Documento(models.Model): + TIPO_CHOICES = [ + ('Contratto', 'Contratto'), + ('KYC', 'KYC'), + ('Report', 'Report'), + ('Altro', 'Altro'), + ] + cliente = models.ForeignKey(Cliente, on_delete=models.CASCADE, related_name='documenti') + Nome_Documento = models.CharField(max_length=100) + Tipo = models.CharField(max_length=20, choices=TIPO_CHOICES) + Data_Caricamento = models.DateField(auto_now_add=True) + Data_di_Scadenza = models.DateField(blank=True, null=True) + File = models.FileField(upload_to='documenti/') # Placeholder, will be configured for S3 + Condivisibile = models.BooleanField(default=False) + + def __str__(self): + return f"{self.Nome_Documento} ({self.cliente})" \ No newline at end of file diff --git a/core/templates/base.html b/core/templates/base.html index 788576e..2e81fe0 100644 --- a/core/templates/base.html +++ b/core/templates/base.html @@ -6,6 +6,30 @@ {% block head %}{% endblock %} - {% block content %}{% endblock %} + + +
{% block content %} {% endblock %}
diff --git a/core/templates/core/article_detail.html b/core/templates/core/article_detail.html index 8820990..b129935 100644 --- a/core/templates/core/article_detail.html +++ b/core/templates/core/article_detail.html @@ -1,14 +1,151 @@ {% extends 'base.html' %} -{% block title %}{{ article.title }}{% endblock %} - {% block content %} -
-

{{ article.title }}

-

Published on {{ article.created_at|date:"F d, Y" }}

-
-
- {{ article.content|safe }} +
+
+
+

{{ object.Nome }} {{ object.Cognome }}

+
+
+

Codice Fiscale: {{ object.Codice_Fiscale }}

+

Email: {{ object.Email }}

+

Telefono: {{ object.Telefono }}

+

Data di Nascita: {{ object.Data_di_Nascita }}

+

Lavoro: {{ object.Lavoro }}

+

Stato: {{ object.Stato }}

+

Categoria: {{ object.Categoria }}

+

Importo Portafoglio Attuale: € {{ object.Importo_Portafoglio_Attuale }}

+
+ + + +
+
+ +
+ + + + + + + + + + + + + {% for portafoglio in portafogli %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
Nome PortafoglioProfilo di RischioValore InizialeValore CorrenteData InizioAzioni
{{ portafoglio.Nome_Portafoglio }}{{ portafoglio.Profilo_di_Rischio }}€ {{ portafoglio.Valore_Iniziale }}€ {{ portafoglio.Valore_Corrente }}{{ portafoglio.Data_Inizio }} + Modifica + Elimina +
Nessun portafoglio trovato.
+
+
+
+ +
+ + + + + + + + + + + + + {% for attivita_item in attivita %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
DataOraTipoStatoNoteAzioni
{{ attivita_item.Data }}{{ attivita_item.Ora|default_if_none:'' }}{{ attivita_item.Tipo }}{{ attivita_item.Stato }}{{ attivita_item.Note }} + Modifica + Elimina +
Nessuna attività trovata.
+
+
+
+ +
+ + + + + + + + + + + + + {% for documento in documenti %} + + + + + + + + + {% empty %} + + + + {% endfor %} + +
Nome DocumentoTipoData CaricamentoData di ScadenzaFileAzioni
{{ documento.Nome_Documento }}{{ documento.Tipo }}{{ documento.Data_Caricamento }}{{ documento.Data_di_Scadenza|default_if_none:'' }}Scarica + Modifica + Elimina +
Nessun documento trovato.
+
+
+
+ Torna alla lista
-{% endblock %} +{% endblock %} \ No newline at end of file diff --git a/core/templates/core/attivita_confirm_delete.html b/core/templates/core/attivita_confirm_delete.html new file mode 100644 index 0000000..2983d44 --- /dev/null +++ b/core/templates/core/attivita_confirm_delete.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} + +{% block content %} +
+

Sei sicuro di voler eliminare l'attività "{{ object.Tipo }}" del {{ object.Data }}?

+
+ {% csrf_token %} + + Annulla +
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/attivita_form.html b/core/templates/core/attivita_form.html new file mode 100644 index 0000000..f554834 --- /dev/null +++ b/core/templates/core/attivita_form.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +
+

{% if object %}Modifica Attività{% else %}Aggiungi Attività{% endif %}

+
+ {% csrf_token %} + {{ form.as_p }} + + Annulla +
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/cliente_confirm_delete.html b/core/templates/core/cliente_confirm_delete.html new file mode 100644 index 0000000..ab215c8 --- /dev/null +++ b/core/templates/core/cliente_confirm_delete.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +
+

Delete Client

+

Are you sure you want to delete {{ object.Nome }} {{ object.Cognome }}?

+
+ {% csrf_token %} + + Cancel +
+
+{% endblock %} diff --git a/core/templates/core/cliente_form.html b/core/templates/core/cliente_form.html new file mode 100644 index 0000000..d79ae9f --- /dev/null +++ b/core/templates/core/cliente_form.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +
+

{% if form.instance.pk %}Edit Client{% else %}Add Client{% endif %}

+
+ {% csrf_token %} + {{ form.as_p }} + + Cancel +
+
+{% endblock %} diff --git a/core/templates/core/documento_confirm_delete.html b/core/templates/core/documento_confirm_delete.html new file mode 100644 index 0000000..4e40417 --- /dev/null +++ b/core/templates/core/documento_confirm_delete.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} + +{% block content %} +
+

Sei sicuro di voler eliminare il documento "{{ object.Nome_Documento }}"?

+
+ {% csrf_token %} + + Annulla +
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/documento_form.html b/core/templates/core/documento_form.html new file mode 100644 index 0000000..dfe2b83 --- /dev/null +++ b/core/templates/core/documento_form.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +
+

{% if object %}Modifica Documento{% else %}Aggiungi Documento{% endif %}

+
+ {% csrf_token %} + {{ form.as_p }} + + Annulla +
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/index.html b/core/templates/core/index.html index 0a3f404..e2e1b3f 100644 --- a/core/templates/core/index.html +++ b/core/templates/core/index.html @@ -1,154 +1,44 @@ -{% extends "base.html" %} - -{% block title %}{{ project_name }}{% endblock %} - -{% block head %} -{% if project_description %} - - - -{% endif %} -{% if project_image_url %} - - -{% endif %} - - - - -{% endblock %} +{% extends 'base.html' %} {% block content %} -
-
-

Analyzing your requirements and generating your app…

-
- Loading… +
+
+

Clienti

+ Add Client
-

AppWizzy AI is collecting your requirements and applying the first changes.

-

This page will refresh automatically as the plan is implemented.

-

- Runtime: Django {{ django_version }} · Python {{ python_version }} - — UTC {{ current_time|date:"Y-m-d H:i:s" }} -

-
-
-
- Page updated: {{ current_time|date:"Y-m-d H:i:s" }} (UTC) -
-{% endblock %} \ No newline at end of file +
+ + + + + + + + + + + + + + + {% for cliente in clienti %} + + + + + + + + + + + {% endfor %} + +
NomeCognomeCodice FiscaleEmailTelefonoStatoCategoriaActions
{{ cliente.Nome }}{{ cliente.Cognome }}{{ cliente.Codice_Fiscale }}{{ cliente.Email }}{{ cliente.Telefono }}{{ cliente.Stato }}{{ cliente.Categoria }} + Details + Edit + Delete +
+
+
+{% endblock %} diff --git a/core/templates/core/portafoglio_confirm_delete.html b/core/templates/core/portafoglio_confirm_delete.html new file mode 100644 index 0000000..e9eff12 --- /dev/null +++ b/core/templates/core/portafoglio_confirm_delete.html @@ -0,0 +1,12 @@ +{% extends 'base.html' %} + +{% block content %} +
+

Sei sicuro di voler eliminare il portafoglio "{{ object.Nome_Portafoglio }}"?

+
+ {% csrf_token %} + + Annulla +
+
+{% endblock %} \ No newline at end of file diff --git a/core/templates/core/portafoglio_form.html b/core/templates/core/portafoglio_form.html new file mode 100644 index 0000000..4421674 --- /dev/null +++ b/core/templates/core/portafoglio_form.html @@ -0,0 +1,13 @@ +{% extends 'base.html' %} + +{% block content %} +
+

{% if object %}Modifica Portafoglio{% else %}Aggiungi Portafoglio{% endif %}

+
+ {% csrf_token %} + {{ form.as_p }} + + Annulla +
+
+{% endblock %} \ No newline at end of file diff --git a/core/urls.py b/core/urls.py index 6299e3d..af7b381 100644 --- a/core/urls.py +++ b/core/urls.py @@ -1,7 +1,40 @@ from django.urls import path - -from .views import home +from .views import ( + ClienteListView, + ClienteDetailView, + ClienteCreateView, + ClienteUpdateView, + ClienteDeleteView, + PortafoglioCreateView, + PortafoglioUpdateView, + PortafoglioDeleteView, + AttivitaCreateView, + AttivitaUpdateView, + AttivitaDeleteView, + DocumentoCreateView, + DocumentoUpdateView, + DocumentoDeleteView, +) urlpatterns = [ - path("", home, name="home"), -] + path('', ClienteListView.as_view(), name='cliente_list'), + path('cliente//', ClienteDetailView.as_view(), name='cliente_detail'), + path('cliente/new/', ClienteCreateView.as_view(), name='cliente_new'), + path('cliente//edit/', ClienteUpdateView.as_view(), name='cliente_edit'), + path('cliente//delete/', ClienteDeleteView.as_view(), name='cliente_delete'), + + # Portafoglio URLs + path('cliente//portafoglio/new/', PortafoglioCreateView.as_view(), name='portafoglio_new'), + path('portafoglio//edit/', PortafoglioUpdateView.as_view(), name='portafoglio_edit'), + path('portafoglio//delete/', PortafoglioDeleteView.as_view(), name='portafoglio_delete'), + + # Attivita URLs + path('cliente//attivita/new/', AttivitaCreateView.as_view(), name='attivita_new'), + path('attivita//edit/', AttivitaUpdateView.as_view(), name='attivita_edit'), + path('attivita//delete/', AttivitaDeleteView.as_view(), name='attivita_delete'), + + # Documento URLs + path('cliente//documento/new/', DocumentoCreateView.as_view(), name='documento_new'), + path('documento//edit/', DocumentoUpdateView.as_view(), name='documento_edit'), + path('documento//delete/', DocumentoDeleteView.as_view(), name='documento_delete'), +] \ No newline at end of file diff --git a/core/views.py b/core/views.py index c9aed12..afcb6bf 100644 --- a/core/views.py +++ b/core/views.py @@ -1,25 +1,141 @@ -import os -import platform +from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView +from django.urls import reverse_lazy, reverse +from .models import Cliente, Portafoglio, Attivita, Documento +from .forms import ClienteForm, PortafoglioForm, AttivitaForm, DocumentoForm +from django.shortcuts import get_object_or_404 -from django import get_version as django_version -from django.shortcuts import render -from django.utils import timezone +class ClienteListView(ListView): + model = Cliente + template_name = 'core/index.html' + context_object_name = 'clienti' +class ClienteDetailView(DetailView): + model = Cliente + template_name = 'core/article_detail.html' -def home(request): - """Render the landing screen with loader and environment details.""" - host_name = request.get_host().lower() - agent_brand = "AppWizzy" if host_name == "appwizzy.com" else "Flatlogic" - now = timezone.now() + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + cliente = self.get_object() + context['portafogli'] = cliente.portafogli.all() + context['attivita'] = cliente.attivita.all() + context['documenti'] = cliente.documenti.all() + return context - context = { - "project_name": "New Style", - "agent_brand": agent_brand, - "django_version": django_version(), - "python_version": platform.python_version(), - "current_time": now, - "host_name": host_name, - "project_description": os.getenv("PROJECT_DESCRIPTION", ""), - "project_image_url": os.getenv("PROJECT_IMAGE_URL", ""), - } - return render(request, "core/index.html", context) +class ClienteCreateView(CreateView): + model = Cliente + template_name = 'core/cliente_form.html' + form_class = ClienteForm + success_url = reverse_lazy('cliente_list') + +class ClienteUpdateView(UpdateView): + model = Cliente + template_name = 'core/cliente_form.html' + form_class = ClienteForm + success_url = reverse_lazy('cliente_list') + +class ClienteDeleteView(DeleteView): + model = Cliente + template_name = 'core/cliente_confirm_delete.html' + success_url = reverse_lazy('cliente_list') + +# Portafoglio Views +class PortafoglioCreateView(CreateView): + model = Portafoglio + form_class = PortafoglioForm + template_name = 'core/portafoglio_form.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['cliente_pk'] = self.kwargs['cliente_pk'] + return context + + def form_valid(self, form): + cliente = get_object_or_404(Cliente, pk=self.kwargs['cliente_pk']) + form.instance.cliente = cliente + return super().form_valid(form) + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.kwargs['cliente_pk']}) + +class PortafoglioUpdateView(UpdateView): + model = Portafoglio + form_class = PortafoglioForm + template_name = 'core/portafoglio_form.html' + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.object.cliente.pk}) + +class PortafoglioDeleteView(DeleteView): + model = Portafoglio + template_name = 'core/portafoglio_confirm_delete.html' + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.object.cliente.pk}) + +# Attivita Views +class AttivitaCreateView(CreateView): + model = Attivita + form_class = AttivitaForm + template_name = 'core/attivita_form.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['cliente_pk'] = self.kwargs['cliente_pk'] + return context + + def form_valid(self, form): + cliente = get_object_or_404(Cliente, pk=self.kwargs['cliente_pk']) + form.instance.cliente = cliente + return super().form_valid(form) + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.kwargs['cliente_pk']}) + +class AttivitaUpdateView(UpdateView): + model = Attivita + form_class = AttivitaForm + template_name = 'core/attivita_form.html' + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.object.cliente.pk}) + +class AttivitaDeleteView(DeleteView): + model = Attivita + template_name = 'core/attivita_confirm_delete.html' + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.object.cliente.pk}) + +# Documento Views +class DocumentoCreateView(CreateView): + model = Documento + form_class = DocumentoForm + template_name = 'core/documento_form.html' + + def get_context_data(self, **kwargs): + context = super().get_context_data(**kwargs) + context['cliente_pk'] = self.kwargs['cliente_pk'] + return context + + def form_valid(self, form): + cliente = get_object_or_404(Cliente, pk=self.kwargs['cliente_pk']) + form.instance.cliente = cliente + return super().form_valid(form) + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.kwargs['cliente_pk']}) + +class DocumentoUpdateView(UpdateView): + model = Documento + form_class = DocumentoForm + template_name = 'core/documento_form.html' + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.object.cliente.pk}) + +class DocumentoDeleteView(DeleteView): + model = Documento + template_name = 'core/documento_confirm_delete.html' + + def get_success_url(self): + return reverse('cliente_detail', kwargs={'pk': self.object.cliente.pk})