From 5dd41960147c875fcf276af0da1e41ea024b9d13 Mon Sep 17 00:00:00 2001 From: Suriya Date: Tue, 7 Apr 2026 12:44:06 +0530 Subject: [PATCH] add --- .env | 36 ++ .streamlit/config.toml | 13 + Dockerfile | 22 + app.py | 93 +++++ app_core/__init__.py | 1 + app_core/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 136 bytes app_core/config/__init__.py | 1 + .../__pycache__/__init__.cpython-312.pyc | Bin 0 -> 143 bytes .../__pycache__/settings.cpython-312.pyc | Bin 0 -> 4284 bytes app_core/config/settings.py | 78 ++++ app_core/db/__init__.py | 1 + .../db/__pycache__/__init__.cpython-312.pyc | Bin 0 -> 139 bytes .../db/__pycache__/database.cpython-312.pyc | Bin 0 -> 1142 bytes .../db/__pycache__/models.cpython-312.pyc | Bin 0 -> 2468 bytes app_core/db/database.py | 21 + app_core/db/models.py | 36 ++ .../__pycache__/auth_service.cpython-312.pyc | Bin 0 -> 3812 bytes .../__pycache__/daily_report.cpython-312.pyc | Bin 0 -> 2549 bytes .../mailer_service.cpython-312.pyc | Bin 0 -> 22040 bytes .../mappings_service.cpython-312.pyc | Bin 0 -> 3824 bytes .../scheduler_service.cpython-312.pyc | Bin 0 -> 4519 bytes app_core/services/auth_service.py | 46 +++ app_core/services/daily_report.py | 53 +++ app_core/services/mailer_service.py | 327 +++++++++++++++ app_core/services/mappings_service.py | 52 +++ app_core/services/scheduler_service.py | 89 ++++ .../ui/__pycache__/auth_ui.cpython-312.pyc | Bin 0 -> 2511 bytes .../ui/__pycache__/layout.cpython-312.pyc | Bin 0 -> 18683 bytes app_core/ui/auth_ui.py | 37 ++ app_core/ui/layout.py | 314 +++++++++++++++ assets/bg.jpg | Bin 0 -> 547877 bytes assets/workolik.png | Bin 0 -> 3993 bytes docker-compose.yml | 38 ++ docs/sample_email.txt | 61 +++ pages/__pycache__/mailer.cpython-312.pyc | Bin 0 -> 6852 bytes pages/__pycache__/mappings.cpython-312.pyc | Bin 0 -> 11625 bytes pages/__pycache__/see_logs.cpython-312.pyc | Bin 0 -> 19715 bytes pages/__pycache__/see_payload.cpython-312.pyc | Bin 0 -> 17239 bytes pages/mailer.py | 118 ++++++ pages/mappings.py | 189 +++++++++ pages/see_logs.py | 380 ++++++++++++++++++ pages/see_payload.py | 285 +++++++++++++ requirements.txt | 11 + scripts/scheduler_standalone.py | 97 +++++ scripts/send_past_reports.py | 68 ++++ scripts/send_specific_report.py | 91 +++++ scripts/test_mail.py | 85 ++++ scripts/validate_setup.py | 104 +++++ scripts/verify_scheduler.py | 48 +++ 49 files changed, 2795 insertions(+) create mode 100644 .env create mode 100644 .streamlit/config.toml create mode 100644 Dockerfile create mode 100644 app.py create mode 100644 app_core/__init__.py create mode 100644 app_core/__pycache__/__init__.cpython-312.pyc create mode 100644 app_core/config/__init__.py create mode 100644 app_core/config/__pycache__/__init__.cpython-312.pyc create mode 100644 app_core/config/__pycache__/settings.cpython-312.pyc create mode 100644 app_core/config/settings.py create mode 100644 app_core/db/__init__.py create mode 100644 app_core/db/__pycache__/__init__.cpython-312.pyc create mode 100644 app_core/db/__pycache__/database.cpython-312.pyc create mode 100644 app_core/db/__pycache__/models.cpython-312.pyc create mode 100644 app_core/db/database.py create mode 100644 app_core/db/models.py create mode 100644 app_core/services/__pycache__/auth_service.cpython-312.pyc create mode 100644 app_core/services/__pycache__/daily_report.cpython-312.pyc create mode 100644 app_core/services/__pycache__/mailer_service.cpython-312.pyc create mode 100644 app_core/services/__pycache__/mappings_service.cpython-312.pyc create mode 100644 app_core/services/__pycache__/scheduler_service.cpython-312.pyc create mode 100644 app_core/services/auth_service.py create mode 100644 app_core/services/daily_report.py create mode 100644 app_core/services/mailer_service.py create mode 100644 app_core/services/mappings_service.py create mode 100644 app_core/services/scheduler_service.py create mode 100644 app_core/ui/__pycache__/auth_ui.cpython-312.pyc create mode 100644 app_core/ui/__pycache__/layout.cpython-312.pyc create mode 100644 app_core/ui/auth_ui.py create mode 100644 app_core/ui/layout.py create mode 100644 assets/bg.jpg create mode 100644 assets/workolik.png create mode 100644 docker-compose.yml create mode 100644 docs/sample_email.txt create mode 100644 pages/__pycache__/mailer.cpython-312.pyc create mode 100644 pages/__pycache__/mappings.cpython-312.pyc create mode 100644 pages/__pycache__/see_logs.cpython-312.pyc create mode 100644 pages/__pycache__/see_payload.cpython-312.pyc create mode 100644 pages/mailer.py create mode 100644 pages/mappings.py create mode 100644 pages/see_logs.py create mode 100644 pages/see_payload.py create mode 100644 requirements.txt create mode 100644 scripts/scheduler_standalone.py create mode 100644 scripts/send_past_reports.py create mode 100644 scripts/send_specific_report.py create mode 100644 scripts/test_mail.py create mode 100644 scripts/validate_setup.py create mode 100644 scripts/verify_scheduler.py diff --git a/.env b/.env new file mode 100644 index 0000000..9e55395 --- /dev/null +++ b/.env @@ -0,0 +1,36 @@ +# Option A: single URL (recommended) +DATABASE_URL=postgresql+psycopg2://admin:Package%40123%23@31.97.228.132:5432/pgworkolik +DB_ECHO=false + +# App Settings +APP_SECRET=80khAhsZiYbCXB_mehHfGZ-oAhmU9jxPp8AR11AUuvWz-wpUgIXliqVOfNihYIhV + + +# Option B: parts (no DATABASE_URL needed if you set all parts) +DB_HOST=31.97.228.132 +DB_PORT=5432 +DB_NAME=pgworkolik +DB_USER=admin +DB_PASSWORD=Package@123# +DB_ECHO=false + +# App Settings +APP_SECRET=80khAhsZiYbCXB_mehHfGZ-oAhmU9jxPp8AR11AUuvWz-wpUgIXliqVOfNihYIhV +BACKGROUND_IMAGE_URL=assets/bg.jpg + + +SMTP_HOST=smtp.gmail.com +SMTP_PORT=587 +SMTP_USER=workolik360@gmail.com +SMTP_PASSWORD=nggo euhg chus yyyw +SMTP_USE_TLS=true +SMTP_FROM_EMAIL=workolik360@gmail.com +SMTP_FROM_NAME=Workolik Team + +REPORT_RECIPIENTS=Darshan@caman.au,darshan@caman.com.au,workolik360@gmail.com,ColinA@caman.au,ColinA@caman.com.au,tabs@tuckerfresh.com.au,jay@tuckerfresh.com.au,sanjay@tuckerfresh.com.au,veer@tuckerfresh.com.au + + +BCC_RECIPIENTS=fazulilahi@gmail.com + +# Darshan@caman.au,ColinA@caman.au,tabs@tuckerfresh.com.au, +# jay@tuckerfresh.com.au \ No newline at end of file diff --git a/.streamlit/config.toml b/.streamlit/config.toml new file mode 100644 index 0000000..2af5b77 --- /dev/null +++ b/.streamlit/config.toml @@ -0,0 +1,13 @@ +[theme] +base = "light" +primaryColor = "#4F46E5" +backgroundColor = "#F8FAFC" +secondaryBackgroundColor = "#FFFFFF" +textColor = "#0F172A" +font = "sans serif" + +[client] +showSidebarNavigation = false + +[server] +fileWatcherType = "poll" diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cc53aad --- /dev/null +++ b/Dockerfile @@ -0,0 +1,22 @@ +FROM python:3.12-slim + +ENV PYTHONDONTWRITEBYTECODE=1 \ + PYTHONUNBUFFERED=1 \ + PIP_NO_CACHE_DIR=1 \ + STREAMLIT_BROWSER_GATHER_USAGE_STATS=false + +WORKDIR /app + +# System deps (timezone data for TZ support) +RUN apt-get update && apt-get install -y --no-install-recommends tzdata && rm -rf /var/lib/apt/lists/* + +COPY requirements.txt /app/ +RUN pip install -r requirements.txt + +COPY . /app + +EXPOSE 8501 + +CMD ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"] + + diff --git a/app.py b/app.py new file mode 100644 index 0000000..586b136 --- /dev/null +++ b/app.py @@ -0,0 +1,93 @@ +# -*- coding: utf-8 -*- +import os +import streamlit as st +from app_core.config.settings import AppSettings +from app_core.services.auth_service import AuthService +from app_core.ui.auth_ui import render_auth_card +from app_core.ui.layout import apply_global_style, render_topbar, render_header, render_sidebar_logo + +settings = AppSettings() # loads env + +# App config +st.set_page_config( + page_title="Workolik", + page_icon="assets/workolik.png", + layout="wide", + initial_sidebar_state="expanded", +) + +apply_global_style(background_url=os.getenv("BACKGROUND_IMAGE_URL")) + +auth_service = AuthService() + +# Initialize session state +if "auth_user" not in st.session_state: + st.session_state.auth_user = None + +# ? SIMPLE MENU (TEXT ONLY) +menu = ["Analytics", "Data", "Mailer", "Mappings"] + +if st.session_state.auth_user is None: + render_topbar() + st.markdown('', unsafe_allow_html=True) + render_auth_card(auth_service) + st.stop() + +# Topbar +render_topbar() + +# Dim background +st.markdown(""" + +""", unsafe_allow_html=True) + +with st.sidebar: + render_sidebar_logo() + + st.markdown('', unsafe_allow_html=True) + +# Routing +if choice == "Analytics": + from pages.see_logs import render_page + render_page() + +elif choice == "Data": + from pages.see_payload import render_page + render_page() + +elif choice == "Mailer": + from pages.mailer import render_page + render_page() + +elif choice == "Mappings": + from pages.mappings import render_page + render_page() \ No newline at end of file diff --git a/app_core/__init__.py b/app_core/__init__.py new file mode 100644 index 0000000..e481a53 --- /dev/null +++ b/app_core/__init__.py @@ -0,0 +1 @@ +# App Core Package diff --git a/app_core/__pycache__/__init__.cpython-312.pyc b/app_core/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..bcf56b0035d940662b1d4ca08a6288c94572c195 GIT binary patch literal 136 zcmX@j%ge<81UsDHXNUml#~=TZlX-=wL5i3w1BM=vZ7$2D# K85xV1fh+*bqaSYo literal 0 HcmV?d00001 diff --git a/app_core/config/__init__.py b/app_core/config/__init__.py new file mode 100644 index 0000000..d71355c --- /dev/null +++ b/app_core/config/__init__.py @@ -0,0 +1 @@ +# Config Package diff --git a/app_core/config/__pycache__/__init__.cpython-312.pyc b/app_core/config/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a89a804908f9f0eecc9e8de06c6600b3381f6489 GIT binary patch literal 143 zcmX@j%ge<81UsDHX9xl5#~=PO4oID^NQl R5Ep|OADI~$8H<>KECA}IB1QlJ literal 0 HcmV?d00001 diff --git a/app_core/config/__pycache__/settings.cpython-312.pyc b/app_core/config/__pycache__/settings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..694e77705e1bdf723a7392ba33be8585e581bdff GIT binary patch literal 4284 zcmb_fO>7(25ne7=l=vf3KeQyu`k`g{hn7V7NB&bB!4ySXOem5esX8HyZdZIOnbwL+ zzg@*4(Sr^tkld(~C?tjHljXW-)Kk?{ax~B!$Zi6$ixzOvUIg?Y*FN>sdCMO&iA?m+ zB{4g1X1;mz=FR)rKee};D0sg8O(u!jDe51jQF}V7%&S9Swx~r4QAj6Haq^}G-5MRI zb%fUo`ZXrb=qQ@vX~dwG-x{9L6>L@3`eWH`3blPoAtTQ`(^o9xEy#q-$b#Cx)FUgh zp$?7fL|v#`e0Af)Q21z*N={)0gW3(Lugpzoah7^A>2w^+yMSM0N+#nIRNJX z1o;hv)yXey@m9W#H}a-s+5v&^W;A*O-Wi?i)By=B=+dcXLF5pNM43;03{B%KC-Dm+ z;)N{Z2GK1St(q%ZHqFWR)Hd;B9^)k9vmHb~!GFT7r3KzCe*aXUUI*%! zV-39yHpL9pF+B~K;iecTveu&fALg-Fo5vGPJ&x3)=xd1LWK+y2I#r7z?$GA(bW{5? z^*;I=`Z!B4{Bh*s4a+n-_bF4W!uUXjc8#fKPdXjtWjUEzk<`|?S#~}YjRnk^MuGdK!+qR~5{$Q z*{IJO@x@eQ;vSb;;aP~l#HG`$#3wK>tM*xs_x;38RO=giZ7w<^J`y+^@p=7Wzb_bzs-2i8v9p*@B-2SgB}=LS619#~iRzxMZA|2} zB`4mi-+^?C`XzN=6aSFlxufOxt7m1S^_w#R555J}(r91dkq*&FUpsrFZ;2yH$#B9{ z9`Jp{i3C#Z{!p{3+gg4oAuX`A9x1KeGa8gDEwy!qy@);<`2~d-&>VpVO$%s_h_{M4 zB4*GS0CPm#Ur@g`MX5}yt1Xy4mWJiJf_dqIFvdxlR3g1HJvo`}X%MHSOhQbrTm<<6 znR!(=t?F*7x=EFC8F3$xm?W9Qvh*+smxWfS8-Yvks-6=BOaj9s224_g$=Glg5V&?Q z5-%)E#G~^+Zhrc1l*e$*xLYgKyJT@DM9kk!h^gh|%3Z0t-?-Bm)zY}cvwaP_k-JfI z3Y<${1KFTnm~H!J=bz2a7q;$w+i1x)x^J5-*(QtUZ+~Z-FZUkb?;S7oj_>zQm3pVj z_OarG@0$m&^mJd>Aw_p~9U3Tm-+uSmQuo=Shuw>$cW@!yZ{4jt-sogUqxUf*s#G*KO0uV4t2Yfx=tS+ZPNRyDEg znuyi~!dqDO!8#{YHM9r|b%iH)J1zUFUXrnDV_7bh5@k+KiYbX@kD3#;MGzmtMXv`s zQ<)`E6tvmJ$Dxe}2^l6DeKIBE5z-tbLk34d1y9$1#-@S4BvuJMW^SHve%l}8k(3$+wqvUpS zr(GGkvhjYdJ11}UE6kO$eK0q><=^z@lRLeN{ldQeYRP_8v0vZ&S;_8&U}6g6g&G*0 zC|rDU{qgmkpDQPC6d8Lik)PYVuP`@W^bF^gwvwC4f@Nn_>6zYmFQ-?S>GGNL1^guQ zI8(fETRAgdWcuozw{K39I2u}w+k{cfzG!Jbq-`x-`NY2|c)ik72J1^A zs1yRJf$U%yju;+G&Oq|Px`>@#fy4Zon3A0n&ahXd!(My=>|A=NO>T)7R3-u6DXI~w zn@h=T5@ow;9{j@kDhDusSf%~p1MnVFYc8_!R6^#U>u}(JWY}fHet6*pLPCUm03^$J0~1p!PW#)i5g+Rf&B4ti#KwFc|z*Dh1zzbvenIC1PXFsNZ$g1O;V@(D`or} zH3a{c21;ki8+ML;Pfh-vG8g;K?Jj;#z4MwG({<%suPJyP{z6CD+`IDg6D25i>&VXB z-h&e3DO)e?#fsq%N=&3|b?>!2_mr4m*?M_TE=HmyCe|n%+l@Wfm6-R+*7JL#&jAuT z>@=F_4Z~qSWww+}X7V>%a$KQv=LGOMPyRu*T~WU5G>*|lsyA=XCkmJH_qK;#Q$`)F GjrPCey%R?O literal 0 HcmV?d00001 diff --git a/app_core/config/settings.py b/app_core/config/settings.py new file mode 100644 index 0000000..07717c4 --- /dev/null +++ b/app_core/config/settings.py @@ -0,0 +1,78 @@ +import os +from dotenv import load_dotenv +from pydantic import BaseModel + +# Load .env first (if present) +load_dotenv(dotenv_path=".env", override=False) +# Also load .env-example.txt as a fallback for local dev (does not override) +load_dotenv(dotenv_path=".env-example.txt", override=False) + +class AppSettings(BaseModel): + # Raw pieces + db_host: str | None = os.getenv("DB_HOST") + db_port: str | None = os.getenv("DB_PORT") + db_name: str | None = os.getenv("DB_NAME") + db_user: str | None = os.getenv("DB_USER") + db_password: str | None = os.getenv("DB_PASSWORD") + db_echo: bool = os.getenv("DB_ECHO", "false").lower() == "true" + + # Optional complete URL (takes precedence if set) + database_url_env: str | None = os.getenv("DATABASE_URL") + + app_secret: str = os.getenv("APP_SECRET", "change_me") + background_image_url: str | None = os.getenv("BACKGROUND_IMAGE_URL") + + # SMTP / Email settings + smtp_host: str | None = os.getenv("SMTP_HOST") + smtp_port: int | None = int(os.getenv("SMTP_PORT", "587")) + smtp_user: str | None = os.getenv("SMTP_USER") + smtp_password: str | None = os.getenv("SMTP_PASSWORD") + smtp_use_tls: bool = os.getenv("SMTP_USE_TLS", "true").lower() == "true" + smtp_from_email: str | None = os.getenv("SMTP_FROM_EMAIL") + smtp_from_name: str = os.getenv("SMTP_FROM_NAME", "Workolik Team") + + # Default recipients for automated reports (comma-separated) + report_recipients: str | None = os.getenv("REPORT_RECIPIENTS") + + @property + def database_url(self) -> str: + if self.database_url_env: + # Normalize asyncpg to psycopg2 if needed + if self.database_url_env.startswith("postgresql+asyncpg://"): + return self.database_url_env.replace( + "postgresql+asyncpg://", "postgresql+psycopg2://", 1 + ) + return self.database_url_env + # Build from parts + if all([self.db_host, self.db_port, self.db_name, self.db_user, self.db_password]): + return ( + f"postgresql+psycopg2://{self.db_user}:{self.db_password}" + f"@{self.db_host}:{self.db_port}/{self.db_name}" + ) + # Fallback empty (will error at runtime if used) + return "" + +# Fixed mapping of stores to tenant IDs and division codes +# Used by analytics and data pages to scope queries per store +STORES = [ + {"label": "Porters Liquor Claremont - PC", "code": "PC", "tenant_id": 1}, + {"label": "Porters Iluka - IP", "code": "IP", "tenant_id": 2}, + {"label": "Cellarbrations at Morris Place - ML", "code": "ML", "tenant_id": 3}, + {"label": "Cellarbrations at Lynwood - CL", "code": "CL4", "tenant_id": 4}, + {"label": "Cellarbrations at Nicholson Road - NL", "code": "NL", "tenant_id": 5}, + {"label": "Cellarbrations at Treeby - CL ", "code": "CL6", "tenant_id": 6}, + {"label": "The Bottle-O Rossmoyne - RC", "code": "RC", "tenant_id": 7}, + {"label": "Porters Liquor Piara Waters - PL", "code": "PL", "tenant_id": 8}, +] + +# Helper map for quick lookups by code (supports variants like CL-4 → CL4) +STORE_CODE_TO_TENANT_ID: dict[str, int] = { + "PC": 1, + "IP": 2, + "ML": 3, + "CL4": 4, "CL-4": 4, "CL_4": 4, "CL": 4, # default CL → 4 + "NL": 5, "NL5": 5, "NL-5": 5, + "CL6": 6, "CL-6": 6, "CL_6": 6, + "RC": 7, + "PL": 8, +} \ No newline at end of file diff --git a/app_core/db/__init__.py b/app_core/db/__init__.py new file mode 100644 index 0000000..8a8cbf1 --- /dev/null +++ b/app_core/db/__init__.py @@ -0,0 +1 @@ +# Database Package diff --git a/app_core/db/__pycache__/__init__.cpython-312.pyc b/app_core/db/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f4dcb93accbea3bcfdba98507f3beea587e40bdb GIT binary patch literal 139 zcmX@j%ge<81UsDHXNUml#~=PO4oID^M#V5Ep|O NADI~$8H<>KEC4~BAd~StUjq%w>X1atW*<3bV{eK(i~;BWs3%rl+fRrgyu$+Uo9I zR}=>IkSIySL%arZ3aiI}#~cG<&?u~1L}JJ#Ic39KB;=5)>6zUe0x9TM@4b5O)vNb? z{isyR1HP^`{^&oJ0QglHlckN7;SXH72M|Ee2LWtDD0In}0=X>*N?RG(vabeOTZ2FX zSlb+@wsowpOiv2#?Xkh5a!A>PneRH}HvI2cq#~7{9N5dAX!o^ECDYplo-ZRE>9~N@ z`^K)n$oD@hV}jYVt_4UTf9nYgWU) z&^%`nYS!oN4;QW0JA6OC*c|N(wT~LYzF;+)BY(}ZmKK|J(+f?MFZ*fS zXG+%#5jFTM+-#DW6k|QkzhT0~SpYfw$rvgCCgZ#Ya^NcXQo6?paTTn{S?a&#BocxR zUhe;5*1=`@W3Ub%$m_5I7X%hohQ&GJIzCffpNs&IP&XFcn18+9c)w#|x`t_IiO^Nz zd#fEMiforq+(F$A8iP}fHdwib6B~8yF}`$$R}j>UD_r~rUJt-exr4Wl4d!6Al zJblY}W#qpwJ~ckezy3tZl)q!a!|R1P__=Z%+}$?^zn*zd{#Ksj{Z6rbe93oww~vDj zD#pRedyXoh0TpwlsyI13X|tN~rW%hKMa6H&jETvLlQ-BY^;xl*hKU#82Bm~Doj*qa z%(RTYv@CL!c}~aC^S%K??f`V(sN@F$L8*^V(_`Ee^NT|+c4P?QOYqju;N(m2?k|Ny zw@(d>SNhbJe)LEE=yv|ljs$WG(omKP+76IZ?N0;bXYX9znmzG!_Qb>b_XnP|I$JID sw1uAM@Ic$1dgH6~q59pKC)U#Qsf&Z+wm$nzKQd5;iVFABH~E$S04s?k2><{9 literal 0 HcmV?d00001 diff --git a/app_core/db/__pycache__/models.cpython-312.pyc b/app_core/db/__pycache__/models.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f1461c3eb8d98120dbac18fc80a6e817cbae766e GIT binary patch literal 2468 zcmb7`Piz!r6u@V8XJ=<;|FjER+MqxU6aPQO!U2(oncFf%9rf>=Dqjr z`~J-Dy>EWVW<>_tUtJIMFB1&&8!BM~-EV6Ix*LqjsI0-5ti+lzDQ3o{xXDSJnUE4D zFYzp+#?-ixGzCdunHY0|QMqf3n$U#Bco0TP`BomR$quXNTLrMDI;`ocSWK_tAB#NY zkJ^T3S~U5dxttRs+oTUmPm4>uT%kyw?HVk#@eV~ob(W}4h$EEqM#N(r#?T2f7@i6$RyNkA+7 zQfhJ$r-G&m{+QGv7w8gfaPyd^7{->;ZGQ$Lr^6^<%g#O@MCg=@ZABHDnP?SV)od|G zxsn4%le=P*%eJ9kmOW4%n$S!|H)yXnCvWt~z5~z3QcP{^PK>52L^l;ul`m^mn$Rs( z`(*WRm~W&Qr-J1fhB9erl=u8ICR@RChb29JM+Fz&!l$;SL7W^+{IN!4Rhv>g!}W)Z z7Q3k+%Q%%RQ&E;pTlEZl&dBndrx&Eea-ZymbZ(<;1CJF}AS zy(ugVwEFhn7w&W43*QRgiAyD^mA`oP6xkEby@B5-IXU2NGrw8_2#z)55hF+`2frj( zxem&N*)0(Ni55}T$vSe35z-y3Cz?XUaVGMo!uUY+V}CaCi%<3EB7c-i;W())@oiUP!-H|>JBV;>B9bY2pMPmWP>L7}K5TnIB!IUFA zQ0zpp3q`~mc>&dkE3z9@nshYF1*m)wsYtZ4UeUqifXADh)ygjA9anKZ%tbq2$Z6u&`pniBc z(+^yB^~_H-&edmObk~8aCxf-&vNo`XCxC5j_*vPD$cx@AR?vXUL}&|pyfE6n&HoE& zgo+%F4|~6&V$2M%&WBde|FxnvlM%@wZO`=o|BV0mBJ8fFiXttH5#2K@Gsm<^*CuD6 z@Zgo!3pX2Dp?acOHUoQz@jf_qA6p;jB1@hFLow!eRIn|tf^hv$lCg$Rt_)RT&FK7EfdrFaP!9NcVg zleb_neiJyuARfh8mi>h}`;a;NGqZi2OR*E|^`UhJ`}MvQJ9yniWpI64idERg&>x^E Ite=1X09++AC;$Ke literal 0 HcmV?d00001 diff --git a/app_core/db/database.py b/app_core/db/database.py new file mode 100644 index 0000000..4fe2261 --- /dev/null +++ b/app_core/db/database.py @@ -0,0 +1,21 @@ +from sqlalchemy import create_engine +from sqlalchemy.orm import sessionmaker, declarative_base +from app_core.config.settings import AppSettings + +settings = AppSettings() + +if not settings.database_url: + raise RuntimeError( + "Database configuration missing. Set DATABASE_URL or DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORD in a .env file at the project root." + ) + +engine = create_engine(settings.database_url, pool_pre_ping=True, future=True, echo=settings.db_echo) +SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine, future=True) +Base = declarative_base() + +def get_db_session(): + db = SessionLocal() + try: + yield db + finally: + db.close() diff --git a/app_core/db/models.py b/app_core/db/models.py new file mode 100644 index 0000000..8d66ad6 --- /dev/null +++ b/app_core/db/models.py @@ -0,0 +1,36 @@ +from sqlalchemy import Column, Integer, String, DateTime, func, UniqueConstraint +from .database import Base + +class User(Base): + __tablename__ = "workolik_users" + __table_args__ = ( + UniqueConstraint("email", name="uq_workolik_users_email"), + ) + + id = Column(Integer, primary_key=True, index=True) + email = Column(String(255), nullable=False, unique=True, index=True) + password_hash = Column(String(255), nullable=False) + created_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) + + +class EmailLog(Base): + __tablename__ = "email_logs" + + id = Column(Integer, primary_key=True, index=True) + sent_at = Column(DateTime(timezone=True), server_default=func.now(), nullable=False) + recipients = Column(String(1024), nullable=False) + subject = Column(String(255), nullable=False) + status = Column(String(50), nullable=False) # sent / failed + error = Column(String(1024)) + date_for = Column(String(32), nullable=False) + +class TriumphDebtorMapping(Base): + __tablename__ = "triumph_debtor_mappings" + + id = Column(Integer, primary_key=True, index=True) + code = Column(String(50)) + name = Column(String(255)) + dbmacc = Column(String(50)) + outlet = Column(String(255)) + created_at = Column(DateTime(timezone=True), server_default=func.now()) + updated_at = Column(DateTime(timezone=True), server_default=func.now(), onupdate=func.now()) diff --git a/app_core/services/__pycache__/auth_service.cpython-312.pyc b/app_core/services/__pycache__/auth_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..f6e3c01be1b624966d330d67c07df789e7b4de33 GIT binary patch literal 3812 zcmeHK-ER}w6~FW4kHn4xj+=xfU?rigDWpIG+RZLs8wk*%5E9xgCe>&%bDcPhKe#g{ zIC56BLTXs8w55GWs`9W^kxIor1PPV&rONI;6typLP315J^`TFFvo9VeLK$^F$*Wr;`*H=Qxyk zolgmI!IlMGOi6LcmPOqY_kdo~y(wSZm-5H`sfKuit@G%OsX#oy5$d1Xz_{oH;p4+0CR%Ef1q+j-`jxs*~(9( z6yuo>#;s=AaNH#)6xGbIJbD4#mN3vhx^e1E|JdmHOT&XBmxiuHhey6Mb|t4?r|e)# zN$Ql1DcP*7W*8j<2jaPmF$E3@i`u=OY~J$8ax$GXWqGEh=KMYGXaKe`Fc@!>m(c@r z;$M9oYtSQBfGN{*Rxym}4Aa!=wWEee@MnMJ&p?2$-2AesS}U}K_Q+vmmanmML%ga( zR^X-p2=z_l+#oFQZs<+9F;Qc@Wj9J<{LqG!GZP2jj7gSfTxI#JX?Z7T+E8@U@=Pkm zWOf<@Qq5>^j~YcD6Ie5>$6A2E1%Rc2pBRls*$y0Pl5yUqKW27q^W`>O2<(lcK)|D+ z$VczreZLgiJ13$%dv|tWtlV*^*l}pFwbb#}QeP=_svJ6344r%CEro_xe8Vh^+u5h2 znu=#|n+F8j?H_Grix81r4gWPkK&Lyv$nX58dErxz18PYW(PjBIqrdhVFiP!f_yffKJjU&2 z{DY?2+^CO)QvpLBTCt#7qUN8`iKb ztEr}%;i_2Ru77iD{^mLefV$?MY*s9Ytig|k34U(Ka1b75qdTR5Ux(LK*8tH~&wV1e zGiN3E&PbghbPJMe%Mq}^IIC;!iR^;6{VZY^IZO<0n#aK9;FlMxp({Zi9^8nY#p{kL zX)WsBcvN9D%IJ+;l2NS(jAq)aMmnR4mIvKL(lDu`WnFL>E9g$PQ$>uwGPCEjs%CO& zGpfQQ6BddN>lEr=RL?*$?1=>|$uL5_3=<41_eK zH)u|V^BBpAbS^uyvleyE7*;|99ekUtHb>?g?=}8BSZ?krHg}bp_svN!LM^{IzZ!mL zHMpZ3>?{U5p9i}i@~e^7`S`u~1J48V*MV~MNHKckN#E1{$NkHZV((xndae{XUyfWW zMy{12Kb#wU5sIv~zP0WpP5V}Y-Cz1hOWOin>?`*Ug7xyPQt$Bd@a4HPtAVDE2Ja63 zwC}@9O&m^X<)Z^TSnc4@{|8V znb=U?{okNk5T~#-)-@Nl#%oi6CcrE#4RsAhUz2<^@jkCf2|?xSlL=O!Ism)1#{+N6 z!6Ei_*a3x^mJ8{dik{REaT-mVNkun$uEcnYPii)PW_Dae>_v^73Xdftk<$T&46+_! zF(e2%X6PaOIbJdC#HZoKeTzR>GRr3~7f)V(zISA`wciC@1wr?*_#5x9yo=pW_dniWY(Kto za%3euvhD|5m4n@X33j`{Ixx^Ad=`5H=;uw+K&uxXv{-M3;GGOF&a{%EvTQZTaw?N z6#@)r0b4w})UsqOwHJE_*05jM<&#Fa1yCY?2-A@-?pqRz9+*{OavRNVQbI{I{OvX;=b&AwDBHIF_m#B z91N2-!?fl6_pr0p2s}-7!>Jg)6g3r`Wi>dpM^<#*aoKU4jpf)$`@VOa8#=+x!Wb50 z11;cn#Bs048?Q*`E7I{d68t-PyGY)CMY<{;!bv{~{wP=`ZAH?ykXRvY&&j@Zv5On! Kz92~L<^KaLM<}oW literal 0 HcmV?d00001 diff --git a/app_core/services/__pycache__/daily_report.cpython-312.pyc b/app_core/services/__pycache__/daily_report.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..124f6a9a23b6f36511df68a9d941903c903a267a GIT binary patch literal 2549 zcmaJ@Uu@gP89!2#Na~*@Cn^%h3Frl?sw7s{bt#rO@s`APleD#6%QaTb1EGi~o3bPd zN7{)s3e$=KORxfsF$@W?6%eptNZ~xRK!N2k16uSUeUK^xa@Z6ou%L*k2A*#GD8?fTbd@iN6$bG7f6e$_ogQ2#;_GUU{?cWRu$k zZ*%KhT7E(&(`n9;w7i8ay@Dyu8C86_S~LKM&ev*LY*~7B$%JX-^}JrjB#X(KUcgR( zU~83B3w_%z5n=Sf`?Lt-ZDjTRA;cnRAdB+d$3`rk24_KDcArv!A&*)z!y3nQ7%hbu z&!cp>+ZD85z@$8?i3ed)I^?Y|w3i=0#B!Le zdervY!Y02vZv<>qI^yvdy3Uyi4p}2?UiuD09@S(PWka;Z|H^WZaUlMXEtZm=7DHN? z$xNVkr2@Z%3j9xxBGiy z-BfU;X02xwxM~#LqIL>KrIH^taV<~4odyCByP0`HV{y0>^??bPuPYP!5;iSmR7vxW zXs%u@L5Pm9Y*osRKzHK=iuA_P(gKN6P4}KtVT(?{wDQ)f>G&Z@Fcq>OU6-a@=`+d` zdf@5j2t6G_uOmVi9ADMAM(BO*2s8`Mpy?(>CAek~OLf=$HKK##IAlnrAy99-9G__s zCsxE(VHp-6e3hmTBA}ah1ifq&9MLjVO@~dyuCD53O?CIJx*Ll3y%1c`YdTmq9o{gV zz!J6~laAl4m30e6}@IpnKWU*y&|88iRvcf&Tr$HTtUU94{iBI9i`h#vvr}_3)AP#g+?B=o z)xruUqx3W}SQCq_wcE1?B!l;tP>mS#?Cb_Z%6j`BB@R!^+CEFNp&M< zn^TWM@yAl69X+-s9p4^^eI-VFqS6tSKkjQS{Nd1+I7+#(k=FCA19uO#qo=l{m#LT> z>&YV>8P>aUx_Mz+lz(;o?dz_ku`TH=6$yslP2Ei08o7C_7aZ;chr7We&5PTi!CvTS zCv>!R@$O(ZbfP)&RpM|jak7&*`FY}vkG}Wk(;uF0pPTKz^hR^~QRtv+@Xal00Ss;@ zU+N`Kcao>?AKglhcjK>hlH)Dz!N{knzob4%-x|4{+DQF2-A;}-ue9T@ZATNmsM3il zt)UNo{$TCFa{JUwdm-13D&6Q$e(_54!VTZH5b6nuj*z%jx;t}!>i!Sf$0j~A+u64s z{;X3mIt9JG+V}^26Y#SM{}$gC68}QTpW`13^2UXm&)->YnJwHNKCvZ? zK8g+Ac(E-Uyu-op?|;f@@O92DhL2xJOl5?R#|L3_Bvqw{sjBHPfjhk4Qc@khHgx#f z*zKzWtRyl8qgvFLGOS$PR&lx!)vivpPQLK(}b9(`vqgRn-Y**G&so zCa>$(`{*h7N96l3IMUgQp{4j*XgJH+VaoiV3{t_LA-`~-9zeHzt0!O%^ o8-=F`$j${03E>;{&wU3U1@~{v|7M{Z9BvE4J3b@~k#Vr_AMH$it^fc4 literal 0 HcmV?d00001 diff --git a/app_core/services/__pycache__/mailer_service.cpython-312.pyc b/app_core/services/__pycache__/mailer_service.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..c2351112132723e8495c13dbd1ad0d714b0c6bea GIT binary patch literal 22040 zcmdsf32+-%c3^ko1_+Yi3Es^^Bq5QMsEZOsQRc0Sq$E
(9q4U(X6P~D(NVgSp| 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 literal 0 HcmV?d00001 diff --git a/app_core/services/auth_service.py b/app_core/services/auth_service.py new file mode 100644 index 0000000..0447e28 --- /dev/null +++ b/app_core/services/auth_service.py @@ -0,0 +1,46 @@ +from typing import Optional +from sqlalchemy.orm import Session +from sqlalchemy import select +import bcrypt +from app_core.db.database import engine, Base, SessionLocal +from app_core.db.models import User + +# Create tables on import +Base.metadata.create_all(bind=engine) + +class AuthService: + def __init__(self) -> None: + self._session_factory = SessionLocal + + def _hash_password(self, raw_password: str) -> str: + salt = bcrypt.gensalt() + return bcrypt.hashpw(raw_password.encode("utf-8"), salt).decode("utf-8") + + def _verify_password(self, raw_password: str, hashed: str) -> bool: + try: + return bcrypt.checkpw(raw_password.encode("utf-8"), hashed.encode("utf-8")) + except Exception: + return False + + def signup(self, email: str, password: str) -> tuple[bool, str]: + email = email.strip().lower() + if not email or not password: + return False, "Email and password are required." + with self._session_factory() as db: # type: Session + exists = db.execute(select(User).where(User.email == email)).scalar_one_or_none() + if exists: + return False, "Email already registered." + user = User(email=email, password_hash=self._hash_password(password)) + db.add(user) + db.commit() + return True, "Account created. Please login." + + def login(self, email: str, password: str) -> tuple[bool, Optional[dict], str]: + email = email.strip().lower() + if not email or not password: + return False, None, "Email and password are required." + with self._session_factory() as db: # type: Session + user = db.execute(select(User).where(User.email == email)).scalar_one_or_none() + if not user or not self._verify_password(password, user.password_hash): + return False, None, "Invalid credentials." + return True, {"id": user.id, "email": user.email}, "Login successful." diff --git a/app_core/services/daily_report.py b/app_core/services/daily_report.py new file mode 100644 index 0000000..de9cbe1 --- /dev/null +++ b/app_core/services/daily_report.py @@ -0,0 +1,53 @@ +import os +from datetime import datetime +from zoneinfo import ZoneInfo + +from app_core.config.settings import AppSettings +from app_core.services.mailer_service import MailerService + + +def main(for_date: str | None = None, force: bool = False) -> int: + settings = AppSettings() + service = MailerService(settings) + + if for_date: + try: + chosen = datetime.strptime(for_date, "%Y-%m-%d").date() + except ValueError: + print(f"Invalid date format: {for_date}. Expected YYYY-MM-DD.") + return 1 + else: + today_ist = datetime.now(ZoneInfo("Asia/Kolkata")).date() + chosen = service.select_report_date(preferred=today_ist) + + if not chosen: + print("No data available to send.") + return 1 + + if not force and service.has_sent_for_date(str(chosen)): + print(f"Already sent for {chosen}; skipping.") + return 0 + + df = service.fetch_daily_rows(chosen) + if df.empty: + print("Selected date has no rows; nothing to send.") + return 0 + + row = df.iloc[0].to_dict() + html = service.build_email_html(row, df) + + recipients_env = settings.report_recipients or os.getenv("REPORT_RECIPIENTS") + if not recipients_env: + print("REPORT_RECIPIENTS env var is empty. Set it to comma-separated emails.") + return 2 + recipients = [r.strip() for r in recipients_env.split(',') if r.strip()] + ok, msg = service.send_email(recipients, subject=f"Daily Digest - {chosen}", html=html) + service.log_email(recipients, subject=f"Daily Digest - {chosen}", date_for=str(chosen), status="sent" if ok else "failed", error=None if ok else msg) + print("Sent" if ok else f"Failed: {msg}") + return 0 if ok else 3 + + +if __name__ == "__main__": + raise SystemExit(main()) + + diff --git a/app_core/services/mailer_service.py b/app_core/services/mailer_service.py new file mode 100644 index 0000000..143fdf0 --- /dev/null +++ b/app_core/services/mailer_service.py @@ -0,0 +1,327 @@ +from __future__ import annotations + +import smtplib +import sys +import os +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from typing import List, Tuple +from datetime import date +from datetime import date +import pandas as pd +from sqlalchemy import text +import streamlit as st + +# Add the project root to Python path +project_root = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +from app_core.config.settings import AppSettings, STORES +from app_core.db.database import engine, SessionLocal +from app_core.db.models import EmailLog + + +class MailerService: + def __init__(self, settings: AppSettings | None = None) -> None: + self.settings = settings or AppSettings() + + def fetch_daily_rows(self, report_date) -> pd.DataFrame: + sql = ( + 'SELECT * FROM "tenantpostings" ' + 'WHERE "created_at"::date = %(d)s ' + 'ORDER BY "id" DESC ' + 'LIMIT 10000' + ) + with engine.connect() as conn: + df = pd.read_sql(sql, conn, params={"d": report_date}) + return df + + def select_report_date(self, preferred: date | None = None) -> date | None: + """Return preferred date if it has data; else most recent date with data; else None.""" + with engine.connect() as conn: + dates_df = pd.read_sql( + 'SELECT "created_at"::date AS d, COUNT(*) AS c\n' + 'FROM "tenantpostings"\n' + 'GROUP BY d\n' + 'ORDER BY d DESC', + conn, + ) + if dates_df.empty: + return None + # Normalize + if 'd' not in dates_df.columns: + return None + dates_df['d'] = pd.to_datetime(dates_df['d'], errors='coerce') + available = [d.date() for d in dates_df['d'].dropna().tolist()] + if preferred and preferred in available: + return preferred + return available[0] if available else None + + def build_email_html(self, row: dict, df: pd.DataFrame | None = None) -> str: + outlet = row.get("outlet_name") or row.get("register_name") or "Outlet" + division = row.get("division_code") or "PC" + status = (row.get("triumph_status") or "Posted successfully").capitalize() + register_close_id = row.get("register_close_id", "—") + register_id = row.get("register_id", "—") + + def lines_for(ptype: str) -> list[str]: + """Return formatted lines for all rows of a processing_type. + Example line: 3,616.19 (Event ID: 2904783) + """ + if df is None or df.empty or 'processing_type' not in df.columns: + return [] + sub = df[df['processing_type'].astype(str).str.upper() == ptype.upper()] if 'processing_type' in df.columns else pd.DataFrame() + if sub.empty: + return [] + + # De-duplicate by triumph_event to avoid double-counting retries + if 'triumph_event' in sub.columns: + sub = sub.sort_values(['triumph_event', 'id'], ascending=[True, False]).drop_duplicates(subset=['triumph_event'], keep='first') + + result: list[str] = [] + for _, r in sub.sort_values('id', ascending=False).iterrows(): + amt = r.get('total_amount') + evt = r.get('triumph_event', '—') + try: + amt_str = f"{float(amt):,.2f}" + except Exception: + amt_str = str(amt) if amt is not None else '—' + result.append(f"{amt_str} (Event ID: {evt})") + return result + + journal_lines = lines_for('JOURNAL') + bank_journal_lines = lines_for('BANKING_JOURNAL') + invoice_lines = lines_for('INVOICE') + receipt_lines = lines_for('RECEIPT') + + # Optional: transaction summary by store (single table) + store_summary_table_html = "" + events_matrix_html = "" + if isinstance(df, pd.DataFrame) and not df.empty and ('tenant_id' in df.columns): + def summarize_for(store: dict) -> dict[str, str]: + sid = store.get('tenant_id') + name = store.get('label') + sub = df[df['tenant_id'] == sid] + + # De-duplicate each processing type context within the store + if not sub.empty and 'triumph_event' in sub.columns and 'processing_type' in sub.columns: + # Filter out non-event rows before dedupe if necessary, but here we just dedupe everything with an event ID + # We keep the one with highest ID for each event + has_event = sub['triumph_event'].fillna('').astype(str).str.strip() != '' + sub_with_events = sub[has_event].sort_values(['processing_type', 'triumph_event', 'id'], ascending=[True, True, False]).drop_duplicates(subset=['processing_type', 'triumph_event'], keep='first') + sub_no_events = sub[~has_event] + sub = pd.concat([sub_with_events, sub_no_events]).sort_values('id', ascending=False) + + def pick_total(kind: str) -> tuple[str, int]: + if sub.empty or 'processing_type' not in sub.columns: + return ("0.00", 0) + s = sub[sub['processing_type'].astype(str).str.upper() == kind] + if s.empty: + return ("0.00", 0) + try: + total = float(s['total_amount'].fillna(0).sum()) if 'total_amount' in s.columns else 0.0 + except Exception: + total = 0.0 + return (f"{total:,.2f}", len(s)) + def has_rows(kind: str) -> bool: + if sub.empty or 'processing_type' not in sub.columns: + return False + s = sub[sub['processing_type'].astype(str).str.upper() == kind] + return not s.empty + def latest_event(kind: str) -> str: + if sub.empty or 'processing_type' not in sub.columns: + return "—" + s = sub[sub['processing_type'].astype(str).str.upper() == kind] + if s.empty: + return "—" + series = s.get('triumph_event') if 'triumph_event' in s.columns else None + if series is None or series.empty: + return "—" + try: + return str(series.dropna().astype(str).iloc[0]) + except Exception: + return "—" + def latest_status_emoji(kind: str) -> str: + if sub.empty or 'processing_type' not in sub.columns: + return "" + s = sub[sub['processing_type'].astype(str).str.upper() == kind] + if s.empty: + return "" + status_series = s.get('triumph_status') if 'triumph_status' in s.columns else None + if status_series is None or status_series.empty: + return "" + try: + val = str(status_series.iloc[0]).strip().lower() + except Exception: + val = "" + if any(x in val for x in ["success", "ok", "completed", "done"]): + return " ✅" + if any(x in val for x in ["fail", "error", "invalid", "dead"]): + return " ❌" + if any(x in val for x in ["pending", "queue", "waiting", "processing"]): + return " ⚠️" + return "" + j_total, _ = pick_total('JOURNAL') + b_total, _ = pick_total('BANKING_JOURNAL') + i_total, _ = pick_total('INVOICE') + r_total, _ = pick_total('RECEIPT') + j_eid = latest_event('JOURNAL'); j_stat = latest_status_emoji('JOURNAL') + b_eid = latest_event('BANKING_JOURNAL'); b_stat = latest_status_emoji('BANKING_JOURNAL') + i_eid = latest_event('INVOICE'); i_stat = latest_status_emoji('INVOICE') + r_eid = latest_event('RECEIPT'); r_stat = latest_status_emoji('RECEIPT') + def render_cell(exists: bool, total: str, eid: str, stat: str, ptype: str = "") -> str: + if not exists: + return "Nill" + + # For INVOICE and RECEIPT, show individual line items if multiple exist + if ptype.upper() in ['INVOICE', 'RECEIPT'] and sub is not None and not sub.empty: + type_sub = sub[sub['processing_type'].astype(str).str.upper() == ptype.upper()] + if len(type_sub) > 1: # Multiple transactions + individual_lines = [] + for _, r in type_sub.sort_values('id', ascending=False).iterrows(): + amt = r.get('total_amount') + evt = r.get('triumph_event', '—') + status_val = str(r.get('triumph_status', '')).strip().lower() + status_emoji = "" + if any(x in status_val for x in ["success", "ok", "completed", "done"]): + status_emoji = " ✅" + elif any(x in status_val for x in ["fail", "error", "invalid", "dead"]): + status_emoji = " ❌" + elif any(x in status_val for x in ["pending", "queue", "waiting", "processing"]): + status_emoji = " ⚠️" + try: + amt_str = f"{float(amt):,.2f}" + except Exception: + amt_str = str(amt) if amt is not None else '—' + individual_lines.append(f"
{amt_str} ({evt}){status_emoji}
") + + return f"{total}
Total ({len(type_sub)} items)
{''.join(individual_lines)}" + + return f"{total}
({eid}) {stat}" + + return { + "name": name, + "journal": render_cell(has_rows('JOURNAL'), j_total, j_eid, j_stat), + "banking": render_cell(has_rows('BANKING_JOURNAL'), b_total, b_eid, b_stat), + "invoice": render_cell(has_rows('INVOICE'), i_total, i_eid, i_stat, 'INVOICE'), + "receipt": render_cell(has_rows('RECEIPT'), r_total, r_eid, r_stat, 'RECEIPT'), + } + + rows = [summarize_for(s) for s in STORES] + # Build single HTML table + header = ( + "" + "Store Name" + "Journal" + "Banking Journal" + "Account Sales" + "Account Payments" + "" + ) + body = [] + for r in rows: + body.append( + "" + f"{r['name']}" + f"{r['journal']}" + f"{r['banking']}" + f"{r['invoice']}" + f"{r['receipt']}" + "" + ) + store_summary_table_html = ( + "
" + "
Transaction Summary by Store
" + "" + + header + "".join(body) + "
" + ) + + html = f""" +
+

Hello Tucker Fresh,

+

Here’s your daily digest of posted transactions:

+ {store_summary_table_html} +

Thank you for staying updated with us.

+

Best regards,
Workolik Team

+
+ """ + return html + + def send_email(self, recipients: List[str], subject: str, html: str) -> Tuple[bool, str]: + s = self.settings + if not all([s.smtp_host, s.smtp_port, s.smtp_user, s.smtp_password, s.smtp_from_email]): + return False, "SMTP settings are incomplete." + + # Optional BCC via env (comma-separated), default empty + bcc_env = os.getenv("BCC_RECIPIENTS", "").strip() + bcc_recipients = [e.strip() for e in bcc_env.split(',') if e.strip()] if bcc_env else [] + all_recipients = recipients + bcc_recipients + + msg = MIMEMultipart("alternative") + msg["From"] = f"{s.smtp_from_name} <{s.smtp_from_email}>" + msg["To"] = ", ".join(recipients) + msg["Subject"] = subject + msg.attach(MIMEText(html, "html")) + + try: + server = smtplib.SMTP(s.smtp_host, s.smtp_port, timeout=30) + if s.smtp_use_tls: + server.starttls() + server.login(s.smtp_user, s.smtp_password) + server.sendmail(s.smtp_from_email, all_recipients, msg.as_string()) + server.quit() + return True, "sent" + except Exception as e: + return False, str(e) + + def log_email(self, recipients: List[str], subject: str, date_for: str, status: str, error: str | None = None) -> None: + with SessionLocal() as db: + entry = EmailLog( + recipients=", ".join(recipients), + subject=subject, + status=status, + error=error, + date_for=date_for, + ) + db.add(entry) + db.commit() + + def has_sent_for_date(self, date_for: str) -> bool: + """Return True if a successful send log exists for the given date.""" + with SessionLocal() as db: + row = ( + db.query(EmailLog) + .filter(EmailLog.date_for == date_for, EmailLog.status == "sent") + .order_by(EmailLog.sent_at.desc()) + .first() + ) + return row is not None + + def recent_logs(self, limit: int = 50) -> list[dict]: + return _get_recent_logs_cached(limit) + + +@st.cache_data(ttl=60) # Cache for 1 minute +def _get_recent_logs_cached(limit: int = 50) -> list[dict]: + """Cached function to get recent email logs.""" + with SessionLocal() as db: + rows = ( + db.query(EmailLog) + .order_by(EmailLog.sent_at.desc()) + .limit(limit) + .all() + ) + return [ + { + "id": r.id, + "sent_at": r.sent_at, + "recipients": r.recipients, + "subject": r.subject, + "status": r.status, + "error": r.error, + "date_for": r.date_for, + } + for r in rows + ] + diff --git a/app_core/services/mappings_service.py b/app_core/services/mappings_service.py new file mode 100644 index 0000000..1e41af1 --- /dev/null +++ b/app_core/services/mappings_service.py @@ -0,0 +1,52 @@ +from typing import List, Optional +from sqlalchemy.orm import Session +from app_core.db.database import SessionLocal +from app_core.db.models import TriumphDebtorMapping +from datetime import datetime + +class MappingsService: + def __init__(self): + pass + + def get_all_mappings(self) -> List[TriumphDebtorMapping]: + with SessionLocal() as db: + return db.query(TriumphDebtorMapping).order_by(TriumphDebtorMapping.id.asc()).all() + + def get_mapping_by_id(self, mapping_id: int) -> Optional[TriumphDebtorMapping]: + with SessionLocal() as db: + return db.query(TriumphDebtorMapping).filter(TriumphDebtorMapping.id == mapping_id).first() + + def create_mapping(self, code: str, name: str, dbmacc: str, outlet: str) -> TriumphDebtorMapping: + with SessionLocal() as db: + mapping = TriumphDebtorMapping( + code=code, + name=name, + dbmacc=dbmacc, + outlet=outlet + ) + db.add(mapping) + db.commit() + db.refresh(mapping) + return mapping + + def update_mapping(self, mapping_id: int, code: str, name: str, dbmacc: str, outlet: str) -> bool: + with SessionLocal() as db: + mapping = db.query(TriumphDebtorMapping).filter(TriumphDebtorMapping.id == mapping_id).first() + if mapping: + mapping.code = code + mapping.name = name + mapping.dbmacc = dbmacc + mapping.outlet = outlet + mapping.updated_at = datetime.now() + db.commit() + return True + return False + + def delete_mapping(self, mapping_id: int) -> bool: + with SessionLocal() as db: + mapping = db.query(TriumphDebtorMapping).filter(TriumphDebtorMapping.id == mapping_id).first() + if mapping: + db.delete(mapping) + db.commit() + return True + return False diff --git a/app_core/services/scheduler_service.py b/app_core/services/scheduler_service.py new file mode 100644 index 0000000..62d08a4 --- /dev/null +++ b/app_core/services/scheduler_service.py @@ -0,0 +1,89 @@ +import logging +import os +from datetime import datetime +from zoneinfo import ZoneInfo +from apscheduler.schedulers.background import BackgroundScheduler +from apscheduler.triggers.cron import CronTrigger +from apscheduler.executors.pool import ThreadPoolExecutor +from apscheduler.jobstores.memory import MemoryJobStore + +from app_core.services.daily_report import main as run_daily_report + +# Configure logging +logging.basicConfig(level=logging.INFO) +logger = logging.getLogger(__name__) + +class SchedulerService: + def __init__(self): + self.scheduler = None + self.ist = ZoneInfo("Asia/Kolkata") + + def start_scheduler(self): + """Start the background scheduler for daily email reports.""" + if self.scheduler and self.scheduler.running: + logger.info("Scheduler is already running") + return + + # Configure job stores and executors + jobstores = { + 'default': MemoryJobStore() + } + executors = { + 'default': ThreadPoolExecutor(20) + } + job_defaults = { + 'coalesce': False, + 'max_instances': 1 + } + + self.scheduler = BackgroundScheduler( + jobstores=jobstores, + executors=executors, + job_defaults=job_defaults, + timezone=self.ist + ) + + # Schedule daily email at 8:00 PM IST (20:00) + self.scheduler.add_job( + func=self._send_daily_report, + trigger=CronTrigger(hour=20, minute=0, timezone=self.ist), + id='daily_email_report', + name='Daily Email Report', + replace_existing=True + ) + + # Start the scheduler + self.scheduler.start() + logger.info("Daily email scheduler started - will send reports at 8:00 PM IST") + + def stop_scheduler(self): + """Stop the background scheduler.""" + if self.scheduler and self.scheduler.running: + self.scheduler.shutdown() + logger.info("Daily email scheduler stopped") + + def _send_daily_report(self): + """Internal method to send daily report.""" + try: + logger.info(f"Starting daily report at {datetime.now(self.ist)}") + result = run_daily_report() + if result == 0: + logger.info("Daily report sent successfully") + else: + logger.warning(f"Daily report failed with exit code: {result}") + except Exception as e: + logger.error(f"Error sending daily report: {str(e)}") + + def get_next_run_time(self): + """Get the next scheduled run time for the daily report.""" + if not self.scheduler or not self.scheduler.running: + return None + + job = self.scheduler.get_job('daily_email_report') + if job: + return job.next_run_time + return None + + def is_running(self): + """Check if scheduler is running.""" + return self.scheduler is not None and self.scheduler.running diff --git a/app_core/ui/__pycache__/auth_ui.cpython-312.pyc b/app_core/ui/__pycache__/auth_ui.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d8eb256989f321cb5a55a5409445840d29600047 GIT binary patch literal 2511 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 Am;e9( literal 0 HcmV?d00001 diff --git a/app_core/ui/auth_ui.py b/app_core/ui/auth_ui.py new file mode 100644 index 0000000..cab55a6 --- /dev/null +++ b/app_core/ui/auth_ui.py @@ -0,0 +1,37 @@ +import re +import streamlit as st +from app_core.services.auth_service import AuthService + + +def _is_valid_email(value: str) -> bool: + if not value: + return False + pattern = r"^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$" + return re.match(pattern, value.strip()) is not None + + +def render_auth_card(auth_service: AuthService) -> None: + left, center, right = st.columns([1, 1.2, 1]) + with center: + + st.markdown('
Welcome !!
', unsafe_allow_html=True) + st.markdown('
Sign in to continue
', unsafe_allow_html=True) + + with st.form("login_form", clear_on_submit=False): + email = st.text_input("Email", placeholder="you@example.com", key="login_email") + password = st.text_input("Password", type="password", placeholder="••••••••", key="login_password") + submitted = st.form_submit_button("Sign in →", use_container_width=True) + if submitted: + if not _is_valid_email(email): + st.error("Enter a valid email address.") + elif not password: + st.error("Password is required.") + else: + ok, user, msg = auth_service.login(email, password) + if ok and user: + st.session_state.auth_user = user + st.success(msg) + st.rerun() + else: + st.error(msg) + st.markdown('', unsafe_allow_html=True) diff --git a/app_core/ui/layout.py b/app_core/ui/layout.py new file mode 100644 index 0000000..809e4b3 --- /dev/null +++ b/app_core/ui/layout.py @@ -0,0 +1,314 @@ +import streamlit as st +from app_core.config.settings import STORES, STORE_CODE_TO_TENANT_ID + +def apply_global_style(background_url: str | None = None) -> None: + css = """ + + """ + st.markdown(css, unsafe_allow_html=True) + + # Optional login/background image with 50% transparency + if background_url: + # Support @prefix and local files by embedding as base64 when needed + try: + import os, base64 + url = background_url.lstrip('@').strip() + if url.startswith('http://') or url.startswith('https://'): + data_url = url + else: + # Treat as local file path + # Map shorthand names to assets/ if needed + if url in {"bg.jpg", "workolik.png"}: + url = os.path.join("assets", url) + if os.path.exists(url): + ext = os.path.splitext(url)[1].lower() + mime = 'image/jpeg' if ext in ['.jpg', '.jpeg'] else 'image/png' if ext == '.png' else 'image/webp' if ext == '.webp' else 'image/*' + with open(url, 'rb') as f: + b64 = base64.b64encode(f.read()).decode() + data_url = f'data:{mime};base64,{b64}' + else: + data_url = url # fallback; let browser try + st.markdown( + f""" + + """, + unsafe_allow_html=True, + ) + except Exception: + pass + + +def render_header(brand_name: str = "Workolik") -> None: + st.markdown( + f""" +
+ +
+ """, + unsafe_allow_html=True, + ) + + +def render_topbar(brand_name: str = "") -> None: + st.markdown( + f""" +
\n
\n \n {brand_name}\n
\n
+ """, + unsafe_allow_html=True, + ) + + +def render_sidebar_logo(brand_name: str = "Workolik") -> None: + import streamlit as st + import base64 + import os + + try: + # Read the image file and encode it as base64 + logo_path = os.path.join("assets", "workolik.png") + if os.path.exists(logo_path): + with open(logo_path, "rb") as img_file: + img_data = base64.b64encode(img_file.read()).decode() + + st.markdown( + f""" + + """, + unsafe_allow_html=True, + ) + else: + raise FileNotFoundError("Logo file not found") + except Exception as e: + # Fallback to text logo if image fails to load + st.markdown( + f""" + + """, + unsafe_allow_html=True, + ) + + +def render_store_selector() -> tuple[int | None, str | None]: + """Render a compact, classy store selector box. + + Returns (tenant_id, label). Also persists selection in session_state. + """ + st.markdown( + """ +
+
+
+ 🛍️ +
Choose the store you want to view
+ +
+
👉 Click a card to select
+
+
+ """, + unsafe_allow_html=True, + ) + + # Sub caption + clear selection + current_label = st.session_state.get("store_label") + left_cap, right_clear = st.columns([6, 1]) + with left_cap: + st.caption("Please choose a store before surfing !") + if current_label: + st.caption(f"Selected: {current_label}") + with right_clear: + if st.button("Clear", key="clear_store_sel"): + st.session_state["tenant_id"] = None + st.session_state["store_label"] = None + st.experimental_rerun() if hasattr(st, "experimental_rerun") else st.rerun() + + # We no longer use query params; selection happens in-session only + chosen_from_query: str | None = None + + # Grid of store boxes (soft gradient cards with per-store colors and emojis) + emoji_map = {"PC": "🍷", "IP": "🍻", "ML": "🥂", "CL4": "🍸", "NL": "🥃", "CL6": "🍾", "RC": "🍹", "PL": "🍺"} + + color_rgb = {"PC": (37,99,235), "IP": (22,163,74), "ML": (245,158,11), "CL4": (220,38,38), "NL": (124,58,237), "CL6": (234,179,8), "RC": (6, 182, 212), "PL": (236, 72, 153)} + preselect_label = st.session_state.get("store_label") + chosen_label = None + # No search box; show all stores + filtered_stores = STORES + # Always render 3 columns per row (e.g., 3 + 3 for 6 stores) + rows = [filtered_stores[i:i+3] for i in range(0, len(filtered_stores), 3)] + for row in rows: + cols = st.columns(3) + for i, store in enumerate(row): + with cols[i]: + icon = emoji_map.get(store["code"], "🏬") + r, g, b = color_rgb.get(store["code"], (14,165,233)) + is_selected = (preselect_label == store["label"]) or (chosen_from_query == store["label"]) # highlight current + border_alpha = 0.48 if is_selected else 0.28 + shadow = "0 18px 42px rgba(2,6,23,0.16)" if is_selected else "0 12px 28px rgba(2,6,23,0.10)" + border_width = "2px" if is_selected else "1px" + check = " ✅" if is_selected else "" + # Render a card-like button that sets selection without changing URL + clicked = st.button( + f"{icon} {store['label']}{check}", + key=f"store_card_{store['code']}", + use_container_width=True, + type="secondary", + ) + # Lightweight card styling via inline CSS targeting this button + st.markdown( + f""" + + """, + unsafe_allow_html=True, + ) + if clicked: + st.session_state["tenant_id"] = store["tenant_id"] + st.session_state["store_label"] = store["label"] + chosen_label = store["label"] + st.rerun() + + # Resolve tenant_id + effective_label = chosen_label or preselect_label + selected = next((s for s in STORES if s["label"] == effective_label), None) + tenant_id = selected["tenant_id"] if selected else None + + # Persist + st.session_state["tenant_id"] = tenant_id + st.session_state["store_label"] = selected["label"] if selected else None + st.session_state["division_code"] = None + + return tenant_id, (selected["label"] if selected else None) \ No newline at end of file diff --git a/assets/bg.jpg b/assets/bg.jpg new file mode 100644 index 0000000000000000000000000000000000000000..1f9238d42995b23a46861838965c7e8e55e9eedf GIT binary patch literal 547877 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

9Jl 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

3pU#euBJ{0Y|tE`+|2a8R*`8bj-_$ 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 SNA~meyk5Nd@Rh$g`o96=;xJtR literal 0 HcmV?d00001 diff --git a/assets/workolik.png b/assets/workolik.png new file mode 100644 index 0000000000000000000000000000000000000000..0f450e28720479fac5d9abefb9249e39d56f522b GIT binary patch literal 3993 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 m$PWnnSY0qRoD(?*0`zrCOy) +To: alice@example.com, bob@example.com + +Hello Tucker Fresh, + +Here’s your daily digest of posted transactions. + +Per-store summary (stacked lines: total — event id status): + +Porters Liquor Claremont - PC +- Journal: 3,881.24 — 2904783 ✅ +- Banking Journal: 0.00 — — +- Account Sales: 2,116.55 — 188210 ✅ +- Account Payments: 980.00 — 188050 ✅ + +Porters Iluka - IP +- Journal: 540.00 — 2905100 ✅ +- Banking Journal: 0.00 — — +- Account Sales: 320.00 — 188305 ✅ +- Account Payments: 0.00 — — + +Cellarbrations at Morris Place - ML +- Journal: 1,592.10 — 2904783 ✅ +- Banking Journal: 50.00 — 99001 ⚠️ +- Account Sales: 560.00 — 188210 ✅ +- Account Payments: 0.00 — — + +Cellarbrations at Lynwood - CL (Store 4) +- Journal: 225.00 — 2906000 ✅ +- Banking Journal: 0.00 — — +- Account Sales: Nill +- Account Payments: Nill + +Cellarbrations at Nicholson Road - NL +- Journal: 410.75 — 2907000 ✅ +- Banking Journal: 0.00 — — +- Account Sales: 120.00 — 188500 ✅ +- Account Payments: 0.00 — — + +Cellarbrations at Lynwood - CL (Store 6) +- Journal: 300.00 — 2908000 ✅ +- Banking Journal: 0.00 — — +- Account Sales: Nill +- Account Payments: Nill + + +Thank you for staying updated with us. + +Best regards, +Workolik Team + +--- +How this mail is triggered (summary): +1) scheduler_standalone.py runs a daily job at 20:00 IST (Asia/Kolkata). +2) It calls app_core/services/daily_report.py:main(). +3) That loads the full-day data, builds HTML via MailerService.build_email_html() + including the per-store totals and Event IDs matrix, then sends via SMTP. +4) Recipients from REPORT_RECIPIENTS; duplicate sends are avoided by DB check + against email_logs.date_for. + diff --git a/pages/__pycache__/mailer.cpython-312.pyc b/pages/__pycache__/mailer.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..428bce999070cc43b419f111d7ffdb8423a01719 GIT binary patch literal 6852 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 UHGPWqeTq&#GjjxSj!-xMFZP&6=Kufz literal 0 HcmV?d00001 diff --git a/pages/__pycache__/mappings.cpython-312.pyc b/pages/__pycache__/mappings.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b02e840d4832354a990514d1579e183eddceea1d GIT binary patch literal 11625 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 PdEeQ;q9WAg61V>aTVTH} literal 0 HcmV?d00001 diff --git a/pages/__pycache__/see_logs.cpython-312.pyc b/pages/__pycache__/see_logs.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a2411618098c16c1367809a523fc42eae4c8f7de GIT binary patch literal 19715 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 literal 0 HcmV?d00001 diff --git a/pages/__pycache__/see_payload.cpython-312.pyc b/pages/__pycache__/see_payload.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..84d7772d8882cf15a1f86425c06d0a46a9882b7b GIT binary patch literal 17239 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 LCP~t)oE82bU~PKx literal 0 HcmV?d00001 diff --git a/pages/mailer.py b/pages/mailer.py new file mode 100644 index 0000000..171cca0 --- /dev/null +++ b/pages/mailer.py @@ -0,0 +1,118 @@ +import streamlit as st +import pandas as pd +from datetime import date, datetime +from zoneinfo import ZoneInfo +from app_core.services.mailer_service import MailerService + + +def render_page(): + if st.session_state.get("auth_user") is None: + st.warning("Please login to continue.") + st.stop() + + st.markdown("## Mailer") + st.caption("Automated daily email sending logs and status.") + + service = MailerService() + ist = ZoneInfo("Asia/Kolkata") + + st.markdown("### Scheduler Status") + + # Check if scheduler container is running by checking if daily report was sent today + today_logs = [log for log in service.recent_logs(limit=1000) if log.get('date_for') == str(date.today())] + daily_report_sent_today = any('Daily Report' in str(log.get('subject', '')) for log in today_logs) + + if daily_report_sent_today: + st.success("Scheduler is running - Daily report already sent today") + else: + # Check if it's past 8 PM IST today + now_ist = datetime.now(ist) + eight_pm_today = now_ist.replace(hour=20, minute=0, second=0, microsecond=0) + + if now_ist >= eight_pm_today: + st.warning("Scheduler is running - Waiting for next scheduled run (8:00 PM IST daily)") + else: + next_run_ist = eight_pm_today + st.success(f"Scheduler is running - Next report will be sent at {next_run_ist.strftime('%B %d, %Y at %I:%M %p IST')}") + + st.markdown("---") + + # Show system status + st.markdown("### System Status") + col1, col2, col3 = st.columns(3) + + with col1: + st.metric("Total Emails Sent", len([log for log in service.recent_logs(limit=1000) if log.get('status') == 'sent'])) + + with col2: + failed_count = len([log for log in service.recent_logs(limit=1000) if log.get('status') == 'failed']) + st.metric("Failed Sends", failed_count, delta=f"-{failed_count}" if failed_count > 0 else None) + + with col3: + today_logs = [log for log in service.recent_logs(limit=1000) if log.get('date_for') == str(date.today())] + st.metric("Today's Sends", len(today_logs)) + + st.markdown("---") + + # Manual trigger section + st.markdown("### Manual Controls") + mcol1, mcol2, mcol3 = st.columns([2, 2, 3]) + + with mcol1: + target_date = st.date_input("Report Date", value=date.today()) + + with mcol2: + st.write("") # Spacer + force_resend = st.checkbox("Force Resend", value=True, help="Send the report even if it was already sent for this date.") + + with mcol3: + st.write("") # Spacer + if st.button("Send Report Now", type="primary", use_container_width=True): + with st.spinner(f"Sending report for {target_date}..."): + try: + from app_core.services.daily_report import main as run_daily_report + # Pass the selected date and force flag + result = run_daily_report(for_date=str(target_date), force=force_resend) + if result == 0: + st.success(f"Report for {target_date} sent successfully!") + st.rerun() + else: + st.error(f"Failed to send report (exit code: {result})") + except Exception as e: + st.error(f"Error: {str(e)}") + + st.caption("Select a date to manually trigger or re-trigger the daily report email. This is useful for reconciliations.") + + st.markdown("---") + + # Show email logs table + st.markdown("### Email Logs") + logs = service.recent_logs(limit=100) + if not logs: + st.info("No email logs yet. Automated emails will appear here once sent.") + else: + df_logs = pd.DataFrame(logs) + col_map = { + "id": "ID", + "sent_at": "Sent At", + "recipients": "Recipients", + "subject": "Subject", + "status": "Status", + "error": "Error", + "date_for": "Report Date", + } + df_logs = df_logs[["id", "sent_at", "date_for", "recipients", "subject", "status", "error"]] + df_logs = df_logs.rename(columns=col_map) + + # Add status styling + def style_status(val): + if val == 'sent': + return 'background-color: #D1FAE5; color: #065F46; font-weight: 600;' + elif val == 'failed': + return 'background-color: #FEE2E2; color: #991B1B; font-weight: 600;' + return '' + + styled_logs = df_logs.style.map(style_status, subset=['Status']) + st.dataframe(styled_logs, use_container_width=True, height=400) + +# trigger reload diff --git a/pages/mappings.py b/pages/mappings.py new file mode 100644 index 0000000..faa8a1c --- /dev/null +++ b/pages/mappings.py @@ -0,0 +1,189 @@ +import streamlit as st +import pandas as pd +from app_core.services.mappings_service import MappingsService +from app_core.config.settings import STORES + + +def render_page(): + if st.session_state.get("auth_user") is None: + st.warning("Please login to continue.") + st.stop() + + st.markdown(""" + + """, unsafe_allow_html=True) + + st.markdown("## 📋 Triumph Debtor Mappings") + st.caption("Manage POS account sale mappings to Triumph debtor codes — filtered by store.") + + service = MappingsService() + all_mappings = service.get_all_mappings() + + # Store labels from config — used only for the "Add New" dropdown + store_labels = [s["label"] for s in STORES] + + tab1, tab2 = st.tabs(["🔍 View & Search", "➕ Add New Mapping"]) + + # ── TAB 1: View & Edit ──────────────────────────────────────────────────── + with tab1: + st.markdown("### 🔍 Current Mappings") + + if not all_mappings: + st.info("No mappings found. Use the '➕ Add New Mapping' tab to create one.") + else: + # Build dataframe from raw DB values + data = [ + { + "ID": m.id, + "POS Code": m.code or "", + "Account Name": m.name or "", + "Triumph Code": m.dbmacc or "", + "Outlet": (m.outlet or "").strip(), + "Created At": m.created_at.strftime("%Y-%m-%d %H:%M") if m.created_at else "—", + "Updated At": m.updated_at.strftime("%Y-%m-%d %H:%M") if m.updated_at else "—", + } + for m in all_mappings + ] + df_full = pd.DataFrame(data) + + # Distinct outlet names actually in DB + distinct_outlets = sorted([ + o for o in df_full["Outlet"].dropna().unique().tolist() if o.strip() + ]) + + f1, f2 = st.columns([1, 2]) + with f1: + selected_store = st.selectbox( + "🏪 Filter by Store", + options=["All Stores"] + distinct_outlets, + index=0, + ) + with f2: + search_query = st.text_input( + "🔎 Search", + placeholder="POS Code, Account Name, or Triumph Code…", + ) + + df = df_full.copy() + + if selected_store != "All Stores": + df = df[df["Outlet"] == selected_store] + + if search_query: + q = search_query + df = df[ + df["POS Code"].str.contains(q, case=False, na=False) | + df["Account Name"].str.contains(q, case=False, na=False) | + df["Triumph Code"].str.contains(q, case=False, na=False) + ] + + store_label = selected_store if selected_store != "All Stores" else "all stores" + st.caption(f"Showing **{len(df)}** mapping(s) for **{store_label}**.") + + st.markdown("#### 📝 Edit Mappings") + st.caption("Double-click any editable cell to modify. Changes are saved when you press Enter.") + + st.data_editor( + df, + hide_index=True, + use_container_width=True, + num_rows="dynamic", + disabled=["ID", "Created At", "Updated At"], + column_config={ + "ID": st.column_config.NumberColumn(format="%d", width="small"), + "POS Code": st.column_config.TextColumn(max_chars=50, width="medium"), + "Account Name": st.column_config.TextColumn(max_chars=255, width="large"), + "Triumph Code": st.column_config.TextColumn(max_chars=50, width="medium"), + "Outlet": st.column_config.TextColumn(max_chars=255, width="large"), + "Created At": st.column_config.TextColumn(width="medium"), + "Updated At": st.column_config.TextColumn(width="medium"), + }, + key="mapping_editor_v2", + ) + + if st.session_state.get("mapping_editor_v2"): + edited_rows = st.session_state.mapping_editor_v2.get("edited_rows", {}) + deleted_rows = st.session_state.mapping_editor_v2.get("deleted_rows", []) + + if edited_rows or deleted_rows: + changes_made = False + + for idx, patch in edited_rows.items(): + mapping_id = df.iloc[idx]["ID"] + row = df.iloc[idx] + new_code = patch.get("POS Code", row["POS Code"]) + new_name = patch.get("Account Name", row["Account Name"]) + new_triumph = patch.get("Triumph Code", row["Triumph Code"]) + new_outlet = patch.get("Outlet", row["Outlet"]) + if service.update_mapping(mapping_id, new_code, new_name, new_triumph, new_outlet): + changes_made = True + + for idx in deleted_rows: + if service.delete_mapping(df.iloc[idx]["ID"]): + changes_made = True + + if changes_made: + st.toast("✅ Mappings updated and synced!", icon="🚀") + st.rerun() + + # ── TAB 2: Add New ──────────────────────────────────────────────────────── + with tab2: + st.markdown("### ➕ Create New Mapping") + st.caption("All fields are mandatory.") + + with st.form("new_mapping_form", clear_on_submit=True): + c1, c2 = st.columns(2) + with c1: + new_code = st.text_input("POS Code", placeholder="e.g. 0273", + help="Unique identifier from your POS system.") + new_name = st.text_input("Account Sale Name", placeholder="e.g. Suriya", + help="The name as it appears on account invoices.") + with c2: + new_triumph = st.text_input("Triumph Debtor Code (DBMACC#)", placeholder="e.g. SURI0273", + help="The debtor code in Triumph ERP.") + new_outlet = st.selectbox( + "Store / Outlet", + options=["Select a Store"] + store_labels, + index=0, + help="Select the store this mapping belongs to.", + ) + + st.markdown("
", unsafe_allow_html=True) + if st.form_submit_button("Create Mapping", type="primary", use_container_width=True): + if not all([new_code.strip(), new_name.strip(), new_triumph.strip()]) or new_outlet == "— Select a Store —": + st.error("⚠️ All fields are required — including selecting a store.") + else: + service.create_mapping(new_code.strip(), new_name.strip(), new_triumph.strip(), new_outlet) + st.success(f"✅ Mapping for **{new_name}** created under **{new_outlet}**!") + st.balloons() + st.rerun() + + st.markdown("---") + with st.expander("📖 Field definitions"): + st.write(""" + - **POS Code** — Unique identifier from your POS system. + - **Account Name** — Name used on account sales invoices. + - **Triumph Code (DBMACC#)** — Corresponding debtor code in Triumph ERP. + - **Store / Outlet** — Store this mapping is assigned to. + + *Any change here is immediately picked up by the background event processor.* + """) + + +if __name__ == "__main__": + render_page() diff --git a/pages/see_logs.py b/pages/see_logs.py new file mode 100644 index 0000000..32baec9 --- /dev/null +++ b/pages/see_logs.py @@ -0,0 +1,380 @@ +import streamlit as st +import pandas as pd +import plotly.express as px +import plotly.graph_objects as go +from datetime import datetime, date, timedelta +from app_core.db.database import engine +from sqlalchemy import text +from app_core.ui.layout import render_store_selector + + +@st.cache_data(ttl=300) # Cache for 5 minutes +def _load_available_dates(tenant_id: int, days_back: int = 60): + """Load available dates with data for the tenant.""" + with engine.connect() as conn: + dates_df = pd.read_sql( + 'SELECT "created_at"::date AS d, COUNT(*) AS c\n' + 'FROM "tenantpostings"\n' + 'WHERE "created_at" >= (CURRENT_DATE - INTERVAL \'60 days\') AND "tenant_id" = %(t)s\n' + 'GROUP BY d\n' + 'ORDER BY d DESC', + conn, + params={"t": tenant_id}, + ) + if not pd.api.types.is_datetime64_any_dtype(dates_df['d']): + dates_df['d'] = pd.to_datetime(dates_df['d'], errors='coerce') + return dates_df + + +@st.cache_data(ttl=300) # Cache for 5 minutes +def _load_daily_data(tenant_id: int, target_date: date): + """Load daily data for a specific tenant and date.""" + day_sql = ( + 'SELECT * FROM "tenantpostings" ' + 'WHERE "created_at"::date = %(d)s AND "tenant_id" = %(t)s ' + 'ORDER BY "id" DESC ' + 'LIMIT 10000' + ) + with engine.connect() as conn: + df = pd.read_sql(day_sql, conn, params={"d": target_date, "t": tenant_id}) + + # De-duplicate by triumph_event to avoid logical doubling + if not df.empty and 'triumph_event' in df.columns: + has_event = df['triumph_event'].fillna('').astype(str).str.strip() != '' + df_with_events = df[has_event].sort_values(['processing_type', 'triumph_event', 'id'], ascending=[True, True, False]).drop_duplicates(subset=['processing_type', 'triumph_event'], keep='first') + df_no_events = df[~has_event] + df = pd.concat([df_with_events, df_no_events]).sort_values('id', ascending=False) + + return df + + +@st.cache_data(ttl=300) # Cache for 5 minutes +def _load_trend_data(tenant_id: int, days_back: int = 30): + """Load trend data for charts.""" + with engine.connect() as conn: + totals_agg = pd.read_sql( + 'SELECT "created_at"::date AS d, SUM("total_amount") AS total\n' + 'FROM "tenantpostings"\n' + 'WHERE "created_at" >= (CURRENT_DATE - INTERVAL \'30 days\') AND "tenant_id" = %(t)s\n' + " AND UPPER(COALESCE(\"processing_type\", '')) = 'JOURNAL'\n" + 'GROUP BY d\n' + 'ORDER BY d ASC', + conn, + params={"t": tenant_id}, + ) + if not pd.api.types.is_datetime64_any_dtype(totals_agg['d']): + totals_agg['d'] = pd.to_datetime(totals_agg['d'], errors='coerce') + return totals_agg + + +def _normalize_name(name: str) -> str: + return "".join(ch for ch in name.lower() if ch.isalnum()) + + +def _build_display_map(df: pd.DataFrame) -> dict[str, str]: + overrides = { + "triumph_status": "Status", + "triumph_event": "Event", + "outlet_name": "Outlet Name", + "tenant_id": "Tenant ID", + "processing_type": "Processing Type", + "total_amount": "Total Amount", + "created_at": "Date", + "updated_at": "Updated At", + "id": "SNo", + } + display_map: dict[str, str] = {} + used: set[str] = set() + for col in df.columns: + key = col.lower() + if key in overrides: + display_name = overrides[key] + else: + # Convert snake_case to Title Case + display_name = col.replace("_", " ").title() + + # Ensure unique display names + final_name = display_name + counter = 1 + while final_name in used: + final_name = f"{display_name} ({counter})" + counter += 1 + + display_map[col] = final_name + used.add(final_name) + return display_map + + +def _pick_existing_columns(df: pd.DataFrame, names: list[str]) -> list[str]: + """Pick columns that exist in the DataFrame from a list of names.""" + found = [] + for name in names: + if name in df.columns: + found.append(name) + return found + + +def _format_date_columns(df: pd.DataFrame) -> pd.DataFrame: + """Format date columns to show only date part""" + df_formatted = df.copy() + for col in df_formatted.columns: + if 'created_at' in col.lower() or 'date' in col.lower(): + if pd.api.types.is_datetime64_any_dtype(df_formatted[col]): + df_formatted[col] = df_formatted[col].dt.date + else: + # Try to convert to datetime first + try: + df_formatted[col] = pd.to_datetime(df_formatted[col]).dt.date + except: + pass + return df_formatted + + +def _journal_total(frame: pd.DataFrame) -> float: + """Sum total_amount for JOURNAL rows only.""" + if frame is None or frame.empty or 'total_amount' not in frame.columns: + return 0.0 + + # We assume 'frame' is already de-duplicated by triumph_event at load time + if 'processing_type' in frame.columns: + mask = frame['processing_type'].astype(str).str.upper() == 'JOURNAL' + frame = frame[mask] + + return float(frame['total_amount'].sum()) if not frame.empty else 0.0 + + +def _stat_card(title: str, value: str, color: str, icon: str) -> str: + return f""" +
+
{icon}
+
{value}
+
{title}
+
+ """ + + +def render_page(): + if st.session_state.get("auth_user") is None: + st.warning("Please login to continue.") + st.stop() + + # Store selector (must be chosen before loading analytics) + tenant_id, store_label = render_store_selector() + if not tenant_id: + st.info("Please choose a store to view analytics.") + return + + st.markdown("## 📊 Dashboard") + # Date picker for selecting any date + picker_col1, _ = st.columns([1, 3]) + with picker_col1: + selected_date = st.date_input("Report date", value=date.today(), max_value=date.today()) + st.markdown("---") + + # Target date preference is today, but we will fall back to most recent date with data + today = date.today() + + # Database connection with caching + try: + # Find most recent available dates with data (last 60 days) + dates_df = _load_available_dates(tenant_id) + + if dates_df.empty: + st.warning("No data available in the last 60 days.") + return + + # Prefer the user-selected date if present; else pick the most recent date + available_dates = list(dates_df['d'].dt.date) + if selected_date in available_dates: + date_shown = selected_date + else: + date_shown = available_dates[0] + + # Comparison dates: the most recent prior dates (up to two) + prior_dates = [d for d in available_dates if d < date_shown] + compare_date = prior_dates[0] if prior_dates else None + compare_date2 = prior_dates[1] if len(prior_dates) > 1 else None + + # Load frames using cached functions + df = _load_daily_data(tenant_id, date_shown) + df_compare = _load_daily_data(tenant_id, compare_date) if compare_date else pd.DataFrame() + df_compare2 = _load_daily_data(tenant_id, compare_date2) if compare_date2 else pd.DataFrame() + + if date_shown == selected_date: + st.success(f"📅 Showing data for {date_shown.strftime('%B %d, %Y')} ({len(df):,} records)") + else: + st.info(f"📅 Showing most recent data: {date_shown.strftime('%B %d, %Y')} ({len(df):,} records)") + + except Exception as e: + st.error(f"Database connection failed: {str(e)}") + return + + # Calculate key metrics (Total Amount uses JOURNAL only) + total_amount = _journal_total(df) + total_transactions = len(df) + success_count = len(df[df['triumph_status'] == 'success']) if 'triumph_status' in df.columns else 0 + failed_count = len(df[df['triumph_status'] == 'failed']) if 'triumph_status' in df.columns else 0 + pending_count = len(df[df['triumph_status'] == 'pending']) if 'triumph_status' in df.columns else 0 + + # Status summary cards + st.markdown("### 📈 Today's Overview") + col1, col2, col3, col4, col5 = st.columns(5) + + with col1: + st.markdown(_stat_card("Total Amount", f"${total_amount:,.2f}", "#059669", "💰"), unsafe_allow_html=True) + with col2: + st.markdown(_stat_card("Transactions", f"{total_transactions:,}", "#2563EB", "📊"), unsafe_allow_html=True) + with col3: + st.markdown(_stat_card("Success", f"{success_count:,}", "#059669", "✅"), unsafe_allow_html=True) + with col4: + st.markdown(_stat_card("Failed", f"{failed_count:,}", "#DC2626", "❌"), unsafe_allow_html=True) + with col5: + st.markdown(_stat_card("Pending", f"{pending_count:,}", "#D97706", "⏳"), unsafe_allow_html=True) + + st.markdown("---") + + # Build simple frames map for totals lookup + frames_by_date = {date_shown: df} + if 'df_compare' in locals() and compare_date: + frames_by_date[compare_date] = df_compare + if 'df_compare2' in locals() and 'compare_date2' in locals() and compare_date2: + frames_by_date[compare_date2] = df_compare2 + + # Stock-like trend line: last 14 days JOURNAL totals, with last 3 days highlighted + st.markdown("### 📈 Sales Trend") + totals_agg = _load_trend_data(tenant_id) + last14 = totals_agg.tail(14).copy() if not totals_agg.empty else pd.DataFrame(columns=['d','total']) + if not last14.empty: + x_labels = last14['d'].dt.strftime('%b %d') + fig_line = go.Figure() + fig_line.add_trace( + go.Scatter( + x=x_labels, + y=last14['total'], + mode='lines+markers', + name='Sales', + line=dict(color="#2563EB", width=2.6), + marker=dict(size=4, color="#2563EB"), + line_shape='spline', + hovertemplate="%{x}
$%{y:,.2f}", + ) + ) + # Highlight last 3 points + last3 = last14.tail(3).reset_index(drop=True) + colors = ["#94A3B8", "#DC2626", "#16A34A"] # old->gray, prev->red, latest->green + labels = ["Prev-2", "Prev", "Latest"] + for i in range(len(last3)): + fig_line.add_trace( + go.Scatter( + x=[last3['d'].dt.strftime('%b %d').iloc[i]], + y=[last3['total'].iloc[i]], + mode='markers', + name=labels[i], + marker=dict(color=colors[i], size=9, symbol='circle'), + hovertemplate=f"{labels[i]}: %{{x}}
$%{{y:,.2f}}", + ) + ) + # Profit/Loss vs previous day + if len(last3) >= 2 and last3['total'].iloc[1] != 0: + shown_total = float(last3['total'].iloc[2]) if len(last3) == 3 else float(last3['total'].iloc[-1]) + prev_total = float(last3['total'].iloc[-2]) + delta = (shown_total - prev_total) / prev_total * 100.0 + arrow = '▲' if delta >= 0 else '▼' + color = '#16A34A' if delta >= 0 else '#DC2626' + fig_line.add_annotation( + x=1, y=1.1, xref='paper', yref='paper', showarrow=False, + text=f"{arrow} {delta:.1f}% vs {last3['d'].dt.strftime('%b %d').iloc[-2]}", + font=dict(color=color, size=14), align='right' + ) + fig_line.update_layout( + height=320, + showlegend=True, + yaxis_title="Total Amount ($)", + xaxis_title=None, + margin=dict(t=30, b=30, l=30, r=20), + plot_bgcolor='white', + hovermode='x unified' + ) + fig_line.update_yaxes(showgrid=True, gridcolor='#E5E7EB', zeroline=False) + fig_line.update_xaxes(showgrid=False, zeroline=False) + st.plotly_chart(fig_line, use_container_width=True) + + st.markdown("---") + + # Data table section + st.markdown("### 📋 Detailed Data") + + # Minimal columns for default view + minimal_names = [ + "id", + "created_at", + "outlet_name", + "processing_type", + "total_amount", + "triumph_status", + "triumph_event", + ] + minimal_cols = _pick_existing_columns(df, minimal_names) + + # Controls row: search only + q = st.text_input("Search", placeholder="Type to filter rows across all columns") + + # Filter data based on search + if q: + mask = df.astype(str).apply(lambda x: x.str.contains(q, case=False, na=False)).any(axis=1) + df_filtered = df[mask] + else: + df_filtered = df.copy() + + # Always use minimal columns + display_cols = minimal_cols if minimal_cols else list(df_filtered.columns[:8]) + + # Build display names + display_map = _build_display_map(df_filtered) + + # Format the display dataframe + df_display = df_filtered[display_cols].copy() + df_display.columns = [display_map.get(col, col) for col in display_cols] + # Format date columns + df_display = _format_date_columns(df_display) + + # Format numeric columns + for col in df_display.columns: + if 'amount' in col.lower() and df_display[col].dtype in ['float64', 'int64']: + df_display[col] = df_display[col].apply(lambda x: f"${x:,.2f}" if pd.notna(x) else "") + + # Always apply status styling + if 'Status' in df_display.columns: + def style_status(val): + if val == 'success': + return 'background-color: #D1FAE5; color: #065F46; font-weight: 600;' + elif val == 'failed': + return 'background-color: #FEE2E2; color: #991B1B; font-weight: 600;' + elif val == 'pending': + return 'background-color: #FEF3C7; color: #92400E; font-weight: 600;' + return '' + + styled_df = df_display.style.map(style_status, subset=['Status']) + st.dataframe(styled_df, use_container_width=True, height=400) + else: + st.dataframe(df_display, use_container_width=True, height=400) + + # Download button + if st.button("📥 Download Today's Data as CSV", type="primary"): + csv = df_filtered.to_csv(index=False) + st.download_button( + label="Download CSV", + data=csv, + file_name=f"workolik_data_{date_shown.strftime('%Y%m%d')}.csv", + mime="text/csv" + ) diff --git a/pages/see_payload.py b/pages/see_payload.py new file mode 100644 index 0000000..ad14e19 --- /dev/null +++ b/pages/see_payload.py @@ -0,0 +1,285 @@ +import streamlit as st +import pandas as pd +from sqlalchemy import text +from app_core.db.database import engine +from app_core.ui.layout import render_store_selector + + +@st.cache_data(ttl=300) # Cache for 5 minutes +def _load_tenant_data(tenant_id: int, limit: int = 10000): + """Load data for a specific tenant with caching.""" + with engine.connect() as conn: + df = pd.read_sql( + text('SELECT * FROM "tenantpostings" WHERE "tenant_id" = :t ORDER BY "id" DESC LIMIT :limit'), + conn, + params={"t": tenant_id, "limit": limit}, + ) + return df + + +def _detect_status_column(df: pd.DataFrame) -> str | None: + candidates = ["status", "state", "result", "triumph_status"] + lower_map = {c.lower(): c for c in df.columns} + for key in candidates: + if key in lower_map: + return lower_map[key] + for c in df.columns: + if "status" in c.lower(): + return c + return None + + +def _normalize_name(name: str) -> str: + return "".join(ch for ch in name.lower() if ch.isalnum()) + + +def _build_display_map(df: pd.DataFrame) -> dict[str, str]: + overrides = { + "triumph_status": "Status", + "triumph_event": "Event", + "outlet_name": "Outlet Name", + "tenant_id": "Tenant ID", + "processing_type": "Processing Type", + "total_amount": "Total Amount", + "created_at": "Date", + "updated_at": "Updated At", + "id": "SNo", + } + display_map: dict[str, str] = {} + used: set[str] = set() + for col in df.columns: + key = col.lower() + if key in overrides: + label = overrides[key] + else: + label = col.replace("_", " ").title() + base = label + suffix = 2 + while label in used: + label = f"{base} {suffix}" + suffix += 1 + used.add(label) + display_map[col] = label + return display_map + + +def _format_status_with_emoji(styler: "pd.io.formats.style.Styler", df: pd.DataFrame, status_col: str | None) -> "pd.io.formats.style.Styler": + if status_col is None or status_col not in df.columns: + return styler + + def fmt(val): + v = str(val) + v_lower = v.lower() + if any(k in v_lower for k in ["success", "ok", "completed", "done", "active"]): + return f"✅ {v}" + if any(k in v_lower for k in ["fail", "error", "dead", "invalid"]): + return f"❌ {v}" + if any(k in v_lower for k in ["pending", "queue", "waiting", "processing"]): + return f"⏳ {v}" + return v + + return styler.format({status_col: fmt}) + + +def _badge_status_cells(styler: "pd.io.formats.style.Styler", df: pd.DataFrame, status_col: str | None) -> "pd.io.formats.style.Styler": + if status_col is None or status_col not in df.columns: + return styler + + def badge(val): + v = str(val).lower() + bg = "#E2E8F0"; color = "#0F172A" + if any(k in v for k in ["success", "ok", "completed", "done", "active"]): + bg = "#E6F7EE"; color = "#166534" + elif any(k in v for k in ["fail", "error", "dead", "invalid"]): + bg = "#FDECEC"; color = "#991B1B" + elif any(k in v for k in ["pending", "queue", "waiting", "processing"]): + bg = "#FEF5E6"; color = "#92400E" + return f"background-color: {bg}; color:{color}; border-radius: 999px; padding: 4px 8px;" + + return styler.map(badge, subset=pd.IndexSlice[:, [status_col]]) + + +def _zebra_style(df: pd.DataFrame) -> "pd.io.formats.style.Styler": + df2 = df.reset_index(drop=True) + + def zebra(row: pd.Series): + return ["background-color: rgba(2,6,23,0.03);" if (row.name % 2 == 0) else ""] * len(row) + + styler = df2.style.apply(zebra, axis=1) + styler = styler.set_table_styles([ + {"selector": "th", "props": "position: sticky; top: 0; background: #F0F6FF; color:#0F172A; font-weight:700;"}, + {"selector": "tbody td", "props": "border-top: 1px solid rgba(15,23,42,0.06);"}, + {"selector": "table", "props": "border-collapse: separate; border-spacing: 0;"}, + ]) + styler = styler.hide(axis="index") + return styler + + +def _format_two_decimals_for_amounts(styler: "pd.io.formats.style.Styler", df: pd.DataFrame) -> "pd.io.formats.style.Styler": + candidates_norm = {"totalamount", "total_amount", "amount", "totalamounts", "totalamounttotals"} + targets = [] + for c in df.columns: + if _normalize_name(c) in candidates_norm and pd.api.types.is_numeric_dtype(df[c]): + targets.append(c) + if targets: + styler = styler.format(formatter="{:.2f}", subset=pd.IndexSlice[:, targets]) + return styler + + +def _format_date_columns(df: pd.DataFrame) -> pd.DataFrame: + """Format date columns to show only date part""" + df_formatted = df.copy() + for col in df_formatted.columns: + if 'created_at' in col.lower() or 'date' in col.lower(): + if pd.api.types.is_datetime64_any_dtype(df_formatted[col]): + df_formatted[col] = df_formatted[col].dt.date + else: + # Try to convert to datetime first + try: + df_formatted[col] = pd.to_datetime(df_formatted[col]).dt.date + except: + pass + return df_formatted + + +def _pick_existing_columns(df: pd.DataFrame, names: list[str]) -> list[str]: + lower_map = {c.lower(): c for c in df.columns} + picked = [] + for n in names: + if n.lower() in lower_map: + picked.append(lower_map[n.lower()]) + return picked + + +def _stat_card(title: str, value: int | str, color: str, emoji: str) -> str: + return f""" +
+
{emoji}
+
+
{title}
+
{value}
+
+
+ """ + + +def render_page(): + if st.session_state.get("auth_user") is None: + st.warning("Please login to continue.") + st.stop() + + # Store selector (required before loading data view) + tenant_id, _ = render_store_selector() + if not tenant_id: + st.info("Please choose a store to view data.") + return + + st.markdown( + """ + + """, + unsafe_allow_html=True, + ) + + st.title("DataHub") + st.caption("Inspect data from Warehouse.") + + st.info("Connected to database ✅.") + + df = _load_tenant_data(tenant_id) + + status_col_global = _detect_status_column(df) + + if status_col_global: + s = df[status_col_global].astype(str).str.lower() + ok = s.str_contains("success|ok|completed|done|active").sum() if hasattr(s, 'str_contains') else s.str.contains("success|ok|completed|done|active").sum() + bad = s.str_contains("fail|error|dead|invalid").sum() if hasattr(s, 'str_contains') else s.str.contains("fail|error|dead|invalid").sum() + pend = s.str_contains("pending|queue|waiting|processing").sum() if hasattr(s, 'str_contains') else s.str.contains("pending|queue|waiting|processing").sum() + total = len(df) + st.markdown('
', unsafe_allow_html=True) + c1, c2, c3, c4 = st.columns([1,1,1,2]) + with c1: st.markdown(_stat_card("Success", ok, "#166534", "✅"), unsafe_allow_html=True) + with c2: st.markdown(_stat_card("Failed", bad, "#991B1B", "❌"), unsafe_allow_html=True) + with c3: st.markdown(_stat_card("Pending", pend, "#92400E", "⏳"), unsafe_allow_html=True) + with c4: st.caption(f"Total rows: {total}") + st.markdown('
', unsafe_allow_html=True) + + minimal_names = [ + "id", + "created_at", + "outlet_name", + "processing_type", + "total_amount", + "triumph_status", + "triumph_event", + ] + minimal_cols = _pick_existing_columns(df, minimal_names) + + # Controls row: search only + q = st.text_input("Search", placeholder="Type to filter rows across all columns") + + # Apply global search + filtered = df + if q: + q_lower = q.lower() + filtered = filtered[filtered.apply(lambda r: r.astype(str).str.lower().str.contains(q_lower).any(), axis=1)] + + # Always use minimal columns + visible_cols = minimal_cols + if visible_cols: + filtered = filtered[visible_cols] + + # Pagination (moved below the table; small controls) + total_rows = len(filtered) + default_page_size = 25 + total_pages = max(1, (total_rows + default_page_size - 1) // default_page_size) + page_num_state_key = "payload_page_num" + if page_num_state_key not in st.session_state: + st.session_state[page_num_state_key] = 1 + start = (st.session_state[page_num_state_key] - 1) * default_page_size + end = start + default_page_size + page_df = filtered.iloc[start:end] + + # Build display names and style + display_map = _build_display_map(page_df) + display_df = page_df.rename(columns=display_map) + # Format date columns + display_df = _format_date_columns(display_df) + status_col_original = _detect_status_column(page_df) + status_col_display = display_map.get(status_col_original) + + styled = _zebra_style(display_df) + styled = _format_two_decimals_for_amounts(styled, display_df) + # Always apply status badges + if status_col_display: + styled = _format_status_with_emoji(styled, display_df, status_col_display) + styled = _badge_status_cells(styled, display_df, status_col_display) + styled = _format_two_decimals_for_amounts(styled, display_df) + styled = styled.set_table_styles([ + {"selector": "th", "props": "position: sticky; top: 0; background: #F0F6FF; color:#0F172A; font-weight:700;"}, + {"selector": "tbody td", "props": "border-top: 1px solid rgba(15,23,42,0.06);"}, + {"selector": "table", "props": "border-collapse: separate; border-spacing: 0;"}, + ]).hide(axis="index") + + st.dataframe(styled, use_container_width=True, height=520) + + # Bottom pagination controls + p1, p2, p3 = st.columns([1, 2, 1]) + with p1: + st.caption(f"Showing {len(page_df)} of {total_rows} rows") + with p2: + st.caption("Page") + st.session_state[page_num_state_key] = st.number_input( + " ", min_value=1, max_value=total_pages, value=st.session_state[page_num_state_key], step=1, label_visibility="collapsed") + with p3: + download_df = filtered.rename(columns=_build_display_map(filtered)) + st.download_button( + "Download filtered CSV", + data=download_df.to_csv(index=False).encode("utf-8"), + file_name="tenantpostings_filtered.csv", + use_container_width=True, + ) diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..446841f --- /dev/null +++ b/requirements.txt @@ -0,0 +1,11 @@ +streamlit>=1.36.0 +sqlalchemy>=2.0.0 +psycopg2-binary>=2.9.9 +bcrypt>=4.1.2 +python-dotenv>=1.0.1 +pydantic>=2.8.2 +cryptography>=42.0.8 +pandas>=2.2.2 +plotly>=5.17.0 +APScheduler>=3.10.4 +tzlocal>=5.3.1 diff --git a/scripts/scheduler_standalone.py b/scripts/scheduler_standalone.py new file mode 100644 index 0000000..f59fcb8 --- /dev/null +++ b/scripts/scheduler_standalone.py @@ -0,0 +1,97 @@ +#!/usr/bin/env python3 +""" +Standalone scheduler service for Workolik daily email reports. +This runs independently of the Streamlit application to avoid multiple instances. +""" +import os +import sys +import logging +from datetime import datetime +from zoneinfo import ZoneInfo +from apscheduler.schedulers.blocking import BlockingScheduler +from apscheduler.triggers.cron import CronTrigger + +# Add the project root to Python path (scripts/ -> project root) +project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +from app_core.services.daily_report import main as run_daily_report + +# Configure logging +logging.basicConfig( + level=logging.INFO, + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' +) +logger = logging.getLogger(__name__) + +def send_daily_report(): + """Send the daily report with database-based deduplication using existing email_logs table.""" + try: + + # Check if we already sent today's report + today = datetime.now(ZoneInfo('Asia/Kolkata')).date() + today_str = today.strftime('%Y-%m-%d') + + from app_core.db.database import SessionLocal + from sqlalchemy import text + + db = SessionLocal() + try: + # Check if daily report was already sent today using existing email_logs table + # Match the exact subject we generate in daily_report.py ("Daily Digest - YYYY-MM-DD") + result = db.execute( + text("SELECT id FROM email_logs WHERE date_for = :date_for AND subject = :subject LIMIT 1"), + {"date_for": today_str, "subject": f"Daily Digest - {today_str}"} + ).fetchone() + + if result: + logger.info(f"Daily report already sent today ({today}), skipping...") + return + + except Exception as e: + logger.error(f"Database error checking existing reports: {e}") + return + finally: + db.close() + + logger.info(f"Starting daily report at {datetime.now(ZoneInfo('Asia/Kolkata'))}") + result = run_daily_report() + if result == 0: + logger.info("Daily report sent successfully") + else: + logger.warning(f"Daily report failed with exit code: {result}") + + except Exception as e: + logger.error(f"Error sending daily report: {str(e)}") + +def main(): + """Main scheduler function.""" + logger.info("Starting Workolik Daily Email Scheduler") + + # Create scheduler + scheduler = BlockingScheduler(timezone=ZoneInfo('Asia/Kolkata')) + + # Schedule daily email at 8:00 PM IST (20:00) + scheduler.add_job( + func=send_daily_report, + trigger=CronTrigger(hour=20, minute=0, timezone=ZoneInfo('Asia/Kolkata')), + id='daily_email_report', + name='Daily Email Report', + replace_existing=True + ) + + logger.info("Daily email scheduler started - will send reports at 8:00 PM IST") + + try: + # Keep the scheduler running + scheduler.start() + except KeyboardInterrupt: + logger.info("Scheduler stopped by user") + scheduler.shutdown() + except Exception as e: + logger.error(f"Scheduler error: {e}") + scheduler.shutdown() + +if __name__ == "__main__": + main() diff --git a/scripts/send_past_reports.py b/scripts/send_past_reports.py new file mode 100644 index 0000000..045969c --- /dev/null +++ b/scripts/send_past_reports.py @@ -0,0 +1,68 @@ +#!/usr/bin/env python3 +import os +import sys +from datetime import date +from zoneinfo import ZoneInfo + +# Add the project root to Python path +project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +from app_core.config.settings import AppSettings +from app_core.services.mailer_service import MailerService + +def send_report_for_date(service, settings, report_date): + print(f"--- Processing date: {report_date} ---") + + # Check if we should skip if already sent (the user said "we need to send", so I'll skip the check unless specified) + # if service.has_sent_for_date(str(report_date)): + # print(f"Already sent for {report_date}; skipping.") + # return + + df = service.fetch_daily_rows(report_date) + if df.empty: + print(f"No data for {report_date}. Skipping.") + return + + row = df.iloc[0].to_dict() + html = service.build_email_html(row, df) + + recipients_env = settings.report_recipients or os.getenv("REPORT_RECIPIENTS") + if not recipients_env: + print("Error: REPORT_RECIPIENTS env var is empty.") + return + + recipients = [r.strip() for r in recipients_env.split(',') if r.strip()] + subject = f"Daily Digest - {report_date}" + + print(f"Sending email to: {recipients}") + ok, msg = service.send_email(recipients, subject=subject, html=html) + + service.log_email( + recipients=recipients, + subject=subject, + date_for=str(report_date), + status="sent" if ok else "failed", + error=None if ok else msg + ) + + if ok: + print(f"Successfully sent report for {report_date}") + else: + print(f"Failed to send report for {report_date}: {msg}") + +def main(): + settings = AppSettings() + service = MailerService(settings) + + dates_to_send = [ + date(2026, 3, 21), + date(2026, 3, 22), + ] + + for d in dates_to_send: + send_report_for_date(service, settings, d) + +if __name__ == "__main__": + main() diff --git a/scripts/send_specific_report.py b/scripts/send_specific_report.py new file mode 100644 index 0000000..eb0d9c5 --- /dev/null +++ b/scripts/send_specific_report.py @@ -0,0 +1,91 @@ +#!/usr/bin/env python3 +""" +Send a one-off Daily Digest email for a specific date using the app's template. + +Default date: 14.10.2025 (dd.mm.yyyy) +Default recipient: suriyakumar.vijayanayagam@gmail.com + +Usage examples: + python scripts/send_specific_report.py + python scripts/send_specific_report.py --date 14.10.2025 --to you@example.com +""" + +import argparse +import os +import sys +from datetime import datetime +from zoneinfo import ZoneInfo + +# Ensure project root on PYTHONPATH when running from scripts/ +PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if PROJECT_ROOT not in sys.path: + sys.path.insert(0, PROJECT_ROOT) + +from app_core.config.settings import AppSettings +from app_core.services.mailer_service import MailerService + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser(description="Send a daily digest for a specific date") + parser.add_argument( + "--date", + help="Target date in dd.mm.yyyy format (e.g., 14.10.2025)", + default="14.10.2025", + ) + parser.add_argument( + "--to", + help="Recipient email (comma-separated for multiple)", + default="suriyakumar.vijayanayagam@gmail.com", + ) + return parser.parse_args() + + +def parse_ddmmyyyy(value: str) -> datetime.date: + try: + return datetime.strptime(value, "%d.%m.%Y").date() + except ValueError as ex: + raise SystemExit(f"Invalid date '{value}'. Use dd.mm.yyyy (e.g., 14.10.2025)") from ex + + +def main() -> int: + args = parse_args() + target_date = parse_ddmmyyyy(args.date) + recipients = [e.strip() for e in args.to.split(",") if e.strip()] + + print("=" * 60) + print(f"SENDING Daily Digest for {target_date} to: {', '.join(recipients)}") + print("=" * 60) + + settings = AppSettings() + service = MailerService(settings) + + # Fetch rows for the date + df = service.fetch_daily_rows(target_date) + if df.empty: + print(f"❌ No rows found for {target_date}. Nothing to send.") + return 1 + + # Build HTML using first row context + full DataFrame for per-store summary + row = df.iloc[0].to_dict() + html = service.build_email_html(row, df) + + subject = f"Daily Digest - {target_date}" + print(f"Subject: {subject}") + + ok, msg = service.send_email(recipients, subject, html) + if ok: + print("Email sent successfully") + service.log_email(recipients, subject, str(target_date), "sent", None) + print("Logged in database") + return 0 + else: + print(f"Email failed: {msg}") + service.log_email(recipients, subject, str(target_date), "failed", msg) + print("Failure logged in database") + return 2 + + +if __name__ == "__main__": + raise SystemExit(main()) + + diff --git a/scripts/test_mail.py b/scripts/test_mail.py new file mode 100644 index 0000000..889afe1 --- /dev/null +++ b/scripts/test_mail.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python3 +""" +Single test file for mail service - does everything in one place +""" +from datetime import datetime, date +from zoneinfo import ZoneInfo + +print("=" * 60) +print("📧 MAIL SERVICE TEST") +print("=" * 60) + +try: + from app_core.services.mailer_service import MailerService + from app_core.config.settings import AppSettings + + # Initialize services + settings = AppSettings() + service = MailerService(settings) + + # Get most recent date with data + chosen_date = service.select_report_date() + if not chosen_date: + print("❌ No data available") + exit(1) + + print(f"✅ Using date: {chosen_date}") + + # Fetch data + df = service.fetch_daily_rows(chosen_date) + print(f"✅ Found {len(df)} records") + + # Build email + row = df.iloc[0].to_dict() + html = service.build_email_html(row, df) + print(f"✅ Email HTML generated ({len(html)} characters)") + + # Show what would be logged + ist = ZoneInfo("Asia/Kolkata") + now_ist = datetime.now(ist) + + print(f"\n📝 Data that would be inserted in email_logs:") + print(f" sent_at: {now_ist}") + print(f" recipients: loyalydigital@gmail.com") + print(f" subject: Daily Digest - {chosen_date}") + print(f" status: sent") + print(f" date_for: {chosen_date}") + print(f" error: null") + + # Ask user + print(f"\n🚀 Send email to loyalydigital@gmail.com? (y/n):") + send_confirm = input(" Send? ").strip().lower() + + if send_confirm == 'y': + print(f"\n📤 Sending email...") + + recipients = ["loyalydigital@gmail.com"] + subject = f"Daily Digest - {chosen_date}" + + ok, msg = service.send_email(recipients, subject, html) + + if ok: + print(f"✅ Email sent successfully!") + service.log_email(recipients, subject, str(chosen_date), "sent", None) + print(f"✅ Logged in database") + else: + print(f"❌ Email failed: {msg}") + service.log_email(recipients, subject, str(chosen_date), "failed", msg) + print(f"✅ Failed attempt logged") + else: + print(f"\n⏭️ Email not sent (test mode)") + + # Show recent logs + print(f"\n📋 Recent email logs:") + logs = service.recent_logs(limit=5) + for log in logs: + print(f" {log['status']} - {log['subject']} at {log['sent_at']}") + +except Exception as e: + print(f"❌ Error: {e}") + import traceback + traceback.print_exc() + +print(f"\n" + "=" * 60) +print("🏁 Done!") +print("=" * 60) diff --git a/scripts/validate_setup.py b/scripts/validate_setup.py new file mode 100644 index 0000000..3b71ec5 --- /dev/null +++ b/scripts/validate_setup.py @@ -0,0 +1,104 @@ +import os +import sys +from datetime import datetime + +# Ensure project root is on PYTHONPATH when running from scripts/ +project_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +if project_root not in sys.path: + sys.path.insert(0, project_root) + +from app_core.config.settings import AppSettings +from app_core.db.database import engine +from sqlalchemy import text + + +def check_env(settings: AppSettings) -> list[str]: + missing: list[str] = [] + required = [ + ("DATABASE_URL", settings.database_url or os.getenv("DATABASE_URL")), + ("SMTP_HOST", settings.smtp_host), + ("SMTP_PORT", settings.smtp_port), + ("SMTP_USER", settings.smtp_user), + ("SMTP_PASSWORD", settings.smtp_password), + ("SMTP_FROM_EMAIL", settings.smtp_from_email), + ("REPORT_RECIPIENTS", settings.report_recipients or os.getenv("REPORT_RECIPIENTS")), + ] + for key, val in required: + if not val: + missing.append(key) + return missing + + +def check_db_connection() -> tuple[bool, str | None]: + try: + with engine.connect() as conn: + # SQLAlchemy 2.0: wrap SQL in text() or use exec_driver_sql + conn.execute(text("SELECT 1")) + return True, None + except Exception as e: + return False, str(e) + + +def check_smtp_login(s: AppSettings) -> tuple[bool, str | None]: + import smtplib + + try: + server = smtplib.SMTP(s.smtp_host, s.smtp_port, timeout=20) + if s.smtp_use_tls: + server.starttls() + if s.smtp_user and s.smtp_password: + server.login(s.smtp_user, s.smtp_password) + # Probe NOOP and quit without sending + server.noop() + server.quit() + return True, None + except Exception as e: + return False, str(e) + + +def main() -> int: + print("=== Workolik Production Validation ===") + settings = AppSettings() + + # 1) Environment variables + missing = check_env(settings) + if missing: + print("❌ Missing required env vars:", ", ".join(sorted(set(missing)))) + else: + print("✅ Required env vars present") + + # Optional BCC + bcc = os.getenv("BCC_RECIPIENTS", "").strip() + if bcc: + print(f"✅ BCC_RECIPIENTS set: {bcc}") + else: + print("ℹ️ BCC_RECIPIENTS not set (no BCC will be added)") + + # 2) Database connectivity + ok_db, err_db = check_db_connection() + if ok_db: + print("✅ Database connectivity OK") + else: + print(f"❌ Database connectivity FAILED: {err_db}") + + # 3) SMTP connectivity (no email will be sent) + ok_smtp, err_smtp = check_smtp_login(settings) + if ok_smtp: + print("✅ SMTP login OK (no email sent)") + else: + print(f"❌ SMTP login FAILED: {err_smtp}") + + # 4) Scheduler subject check (ensure dedupe matches) + today_str = datetime.now().date().strftime('%Y-%m-%d') + expected_subject = f"Daily Digest - {today_str}" + print(f"✅ Scheduler dedupe subject pattern: {expected_subject}") + + failures = (1 if missing else 0) + (0 if ok_db else 1) + (0 if ok_smtp else 1) + print("=== Validation Complete ===") + return 0 if failures == 0 else 1 + + +if __name__ == "__main__": + sys.exit(main()) + + diff --git a/scripts/verify_scheduler.py b/scripts/verify_scheduler.py new file mode 100644 index 0000000..469be24 --- /dev/null +++ b/scripts/verify_scheduler.py @@ -0,0 +1,48 @@ +#!/usr/bin/env python3 +from datetime import datetime +from zoneinfo import ZoneInfo + +print("🔍 VERIFYING SCHEDULER SETUP") +print("=" * 50) + +# Check current time +ist = ZoneInfo('Asia/Kolkata') +now = datetime.now(ist) +print(f"Current IST time: {now.strftime('%Y-%m-%d %H:%M:%S %Z')}") + +# Check 8 PM today +eight_pm = now.replace(hour=20, minute=0, second=0, microsecond=0) +print(f"8:00 PM today: {eight_pm.strftime('%Y-%m-%d %H:%M:%S %Z')}") + +# Test scheduler +try: + from app_core.services.scheduler_service import SchedulerService + s = SchedulerService() + s.start_scheduler() + print(f"✅ Scheduler started: {s.is_running()}") + + next_run = s.get_next_run_time() + if next_run: + next_run_ist = next_run.astimezone(ist) + print(f"✅ Next run: {next_run_ist.strftime('%Y-%m-%d %H:%M:%S %Z')}") + else: + print("❌ No next run time found") + + s.stop_scheduler() + print("✅ Scheduler stopped") + +except Exception as e: + print(f"❌ Scheduler error: {e}") + +# Test daily report +try: + from app_core.services.daily_report import main + print("\n🧪 Testing daily report...") + result = main() + print(f"✅ Daily report result: {result}") +except Exception as e: + print(f"❌ Daily report error: {e}") + +print("\n" + "=" * 50) +print("✅ VERIFICATION COMPLETE") +print("=" * 50)