
    LCj                         d Z ddlZddlmZ ddlmZmZmZmZmZm	Z	m
Z
 ddlmZmZmZmZ  G d de      Z G d d	e      Z G d
 de      Z G d de      Z G d de      Z G d de      Zy)u3  
SQLAlchemy ORM models.

Why a database at all, given Redis already caches results: Redis is
ephemeral (TTL-based) and not queryable in any structured way. The
client will want to know things like "how many requests for rice in
Thanjavur did we get last month" or "show me every analysis that hit a
conflict flag" — that needs a real relational store with indexes, not
a key-value cache.

AnalysisRecord is the permanent audit trail: every completed analysis,
regardless of whether it was served from cache or freshly computed.

User / CropPlan / Notification support the customer-facing SaaS layer
(see app/api/v1/endpoints/auth.py and docs/architecture.md) — these are
separate from the original API-key-based service auth, which remains in
place for any machine-to-machine integrations the client may also want.
    N)datetime)JSONBooleanDateTime
ForeignKeyIntegerStringText)DeclarativeBaseMappedmapped_columnrelationshipc                       e Zd Zy)BaseN)__name__
__module____qualname__     :C:\Crop_Prediction\Backend\crop-ai-system\app\db\models.pyr   r      s    r   r   c                      e Zd ZU dZdZ e ed      dd       Zee	   e
d<    e ed      dd	      Zee	   e
d
<    e ed            Zee	   e
d<    e ed      d      Zee	   e
d<    e ed      d      Zee	   e
d<    eed      Zee   e
d<    eed      Zee   e
d<    eeej*                        Zee   e
d<    eed      Zee   e
d<    ed      Zeed      e
d<    ed      Zeed      e
d<   y)Useru   
    Customer account for the SaaS web application. Distinct from the
    API-key auth used elsewhere in this system — API keys identify a
    calling SERVICE/integration, a User identifies an individual
    customer logging into the dashboard.
    users$   Tc                  <    t        t        j                               S Nstruuiduuid4r   r   r   <lambda>zUser.<lambda>(       RUVZV`V`VbRc r   primary_keydefaultid   )uniqueindexemailhashed_passwordnullable	full_nameorganizationr%   	is_activeFis_verified
created_atlast_login_atuserback_populatesCropPlan
crop_plansNotificationnotificationsN)r   r   r   __doc____tablename__r   r	   r&   r   r   __annotations__r*   r+   r.   r/   r   r1   boolr2   r   r   utcnowr3   r4   r   r9   listr;   r   r   r   r   r      s    M#F2JDJcdBsd&vc{4tLE6#;L#0#=OVC[=*6#;FIvc{F -fSkD IL&+I+GTBIvd|B -gu EKE#08??#SJx S&3Ht&LM6(#L+7v+NJtJ'(N2>f2UM6$~./Ur   r   c                   (   e Zd ZU dZdZ e ed      dd       Zee	   e
d<    e ed       ed      d	      Zee	   e
d
<    e ed            Zee	   e
d<    e ed            Zee	   e
d<    e ed            Zee	   e
d<    ee      Zee   e
d<    e ed      d      Zee	   e
d<    eed      Zee   e
d<    eeej2                        Zee   e
d<    eeej2                  ej2                        Zee   e
d<    ed      Zed   e
d<   y)r8   uL  
    A saved crop planning scenario a customer created via the dashboard
    (module 1.1.3 / 1.1.8 in the SaaS spec). Each plan can have multiple
    linked AnalysisRecord rows over time — e.g. the customer re-runs the
    analysis after climate data updates, or compares scenarios with
    different risk tolerance settings.
    r9   r   Tc                  <    t        t        j                               S r   r   r   r   r   r!   zCropPlan.<lambda>B   r"   r   r#   r&   users.idr)   user_idr'   name2   cropd   locationplanting_month   moderater0   risk_toleranceFis_archivedr3   )r%   onupdate
updated_atr6   r   r5   N)r   r   r   r<   r=   r   r	   r&   r   r   r>   r   rF   rG   rI   rK   r   rL   intrO   r   rP   r?   r   r   r@   r3   rR   r   r5   r   r   r   r8   r8   8   s!    !M#F2JDJcdBsd(Z
5KSWXGVC[X%fSk2D&+2%fRj1D&+1)&+6HfSk6"/"8NF3K8"/r
J"ONF3KO -gu EKE#08??#SJx S#08??]e]l]l#mJx m'|DD&.Dr   r8   c                      e Zd ZU dZdZ e ed      dd       Zee	   e
d<    e ed       ed      d	      Zee	   e
d
<    e ed            Zee	   e
d<    ee      Zee	   e
d<    e ed      d      Zee	   e
d<    e ed       ed      d      Zee	   e
d<    eed      Zee   e
d<    eed      Zee   e
d<    eeej0                  d      Zee   e
d<    ed      Zed   e
d<   y)r:   uR  
    In-app / email alert record (module 1.1.11). Generated either by a
    completed analysis (e.g. "your rice plan is now classified as
    risky") or by a scheduled job (e.g. seasonal reminders) — the
    generation logic lives in app/services/, this table is just storage
    plus read/unread state for the dashboard bell icon.
    r;   r   Tc                  <    t        t        j                               S r   r   r   r   r   r!   zNotification.<lambda>]   r"   r   r#   r&   rD   rE   rF   r'   titlemessagerM   infor0   severitycrop_plans.idr,   related_crop_plan_idFis_read
email_sentr%   r)   r3   r6   r   r5   N)r   r   r   r<   r=   r   r	   r&   r   r   r>   r   rF   rV   r
   rW   rY   r[   r   r\   r?   r]   r   r   r@   r3   r   r5   r   r   r   r:   r:   S   s
    $M#F2JDJcdBsd(Z
5KSWXGVC[X&vc{3E6#;3(.GVC[.)&*fEHfSkE(5fRj*_B]hl(m&+m)'5AGVD\A,WeDJtD#08??Z^#_Jx _'GD&.Gr   r:   c                   :   e Zd ZU dZ e ed      dd       Zee   e	d<    e ed      d      Z
ee   e	d	<    e ed       ed
      dd      Zee   e	d<    e ed       ed      dd      Zee   e	d<    e ed      d      Zee   e	d<    e ed      d      Zee   e	d<    ee      Zee   e	d<    e ed      d      Zee   e	d<    ed      Zee   e	d<    eed      Zee   e	d<    eed      Zee   e	d<    ee      Zee   e	d<    e ed            Zee   e	d<    eed      Zee   e	d<    ee      Z ee   e	d<    e ed      d      Z!ee   e	d <    e ed      d      Z"ee   e	d!<    ee#e$jJ                  d"      Z&ee$   e	d#<   y$)%AnalysisRecordanalysis_recordsr   Tc                  <    t        t        j                               S r   r   r   r   r   r!   zAnalysisRecord.<lambda>p   r"   r   r#   r&   @   rE   
request_idrD   )r-   r)   rF   rZ   crop_plan_idrH   rI   rJ   districtmonthrM   r,   feasibility_labelexpected_yield_ton_haFr0   had_conflictsdegraded_modelsfull_resultmodel_versionserved_from_cacheprocessing_msapi_key_prefix	client_ipr^   r3   N)'r   r   r   r=   r   r	   r&   r   r   r>   rd   r   rF   re   rI   rf   r   rg   rS   rh   ri   floatr   rj   r?   r
   rk   r   rl   dictrm   rn   ro   rp   rq   r   r   r@   r3   r   r   r   r`   r`   m   s   &M#F2JDJcdBsd+F2JdCJsC
 )Z
5KVZbfgGVC[g -fRj*_:U`dlp qL&+q%fRj=D&+=)&+TBHfSkB&w/E6#;/%26":%Mvc{M+8$+G6%=G"/"GM6$<G#0#EOVC[E -d 3K3!.vbz!:M6#;:&3GU&Kvd|K!.w!7M6#;7"/r
T"JNF3KJ*6":EIvc{E#08??Z^#_Jx _r   r`   c                   (   e Zd ZU dZdZ e ed      dd       Zee	   e
d<    e ed      d	      Zee	   e
d
<    e ed      d	      Zee	   e
d<    ee      Zee	   e
d<    eed      Zee   e
d<    eeej(                  d      Zee   e
d<   y)FailedRequestLogu   
    Separate table for failed requests — deliberately kept apart from
    AnalysisRecord so a flood of failures (e.g. during an LLM outage)
    doesn't pollute the table used for legitimate usage analytics.
    failed_request_logsr   Tc                  <    t        t        j                               S r   r   r   r   r   r!   zFailedRequestLog.<lambda>   r"   r   r#   r&   rc   rE   rd   rH   
error_codeerror_messager,   input_payloadr^   r3   N)r   r   r   r<   r=   r   r	   r&   r   r   r>   rd   rx   r
   ry   r   rz   rs   r   r   r@   r3   r   r   r   ru   ru      s    
 *M#F2JDJcdBsd+F2JdCJsC+F2JdCJsC!.t!4M6#;4"/t"DM6$<D#08??Z^#_Jx _r   ru   )r<   r   r   
sqlalchemyr   r   r   r   r   r	   r
   sqlalchemy.ormr   r   r   r   r   r   r8   r:   r`   ru   r   r   r   <module>r}      st   &   Q Q Q O O	? 	V4 V2Et E6H4 H4`T `B`t `r   