Ë
    §‘ˆjm  ã                   ó¢   — d Z ddlZddlmZ  ej                  e«      Zdd„Zdedede	dz  fd„Z
d	edz  d
edz  dedz  deedz  e	dz  f   fd„Zy)a2  Converts prices into a tenant's reference currency so they can be compared.

Every price rule in the matching specification divides one price by another. Across
currencies that is meaningless and silent: an INR price against a USD one yields a
ratio dozens of times out, and the output looks like a ranking opinion rather than a
data fault. Conversion happens once, at ingestion, from an operator-seeded rate
table -- never guessed, since a guessed rate is indistinguishable from a real one in
the output while a missing one is visible as an incomplete product.
é    N)Úget_master_db_connectionÚreturnc                  ó\  — t        «       } 	 | j                  «       5 }|j                  d«       d d d «       | j                  «        	 | j                  «        y # 1 sw Y   Œ+xY w# t        $ r) | j                  «        t        j                  dd¬«       ‚ w xY w# | j                  «        w xY w)Nar  
                CREATE TABLE IF NOT EXISTS fx_rates (
                    base_currency  TEXT NOT NULL,
                    quote_currency TEXT NOT NULL,
                    rate           REAL NOT NULL,
                    fetched_at     TIMESTAMPTZ NOT NULL DEFAULT now(),
                    PRIMARY KEY (base_currency, quote_currency)
                )
            zCould not ensure fx_rates tableT)Úexc_info)	r   ÚcursorÚexecuteÚcommitÚ	ExceptionÚrollbackÚloggerÚerrorÚclose)ÚconnÚcurs     ú6/var/www/html/strategist-ai/app/services/catalog/fx.pyÚensure_fx_tabler      s�   € Ü#Ó%€DðØ�[‰[‹]ð 		˜cØ�K‰Kð ô ÷		ð 	�‰�ð 	�
‰
�÷!		ð 		ûô ò Ø�‰ŒÜ�‰Ð6ÀˆÔFØðûð
 	�
‰
�ús-   ŒA$ œA®A$ ÁA!ÁA$ Á$2BÂB ÂB+ÚbaseÚquotec                 óh  — | r|sy | |k(  ryt        «        t        «       }	 |j                  «       5 }|j                  d| |f«       |j	                  «       }|rt        |d   «      nd cd d d «       |j                  «        S # 1 sw Y   nxY w	 |j                  «        y # |j                  «        w xY w)Nç      ð?zJSELECT rate FROM fx_rates WHERE base_currency = %s AND quote_currency = %sr   )r   r   r   r   ÚfetchoneÚfloatr   )r   r   r   r   Úrows        r   Úget_rater   '   s¥   € Ù‘uØØˆu‚}ØäÔÜ#Ó%€DðØ�[‰[‹]ð 	2˜cØ�K‰Kð*Ø,0°%¨=ô:ð —,‘,“.ˆCÙ$'”5˜˜Q™”=¨T÷	2ð 	2ð 	�
‰
�÷	2ð 	2úð 	2ð 	�
‰
�øˆ�
‰
�ús"   ¡B ±6BÁ'	B ÂB
ÂB ÂB1Úprice_centsÚsource_currencyÚreference_currencyc                 ó²   — | �|r|sy||k(  rt        | «      dfS t        ||«      }|€t        j                  d||«       yt        t	        | |z  «      «      |fS )al  Returns (converted_cents, rate_used), or (None, None) when no rate exists.

    Deliberately does not fall back to a default rate: a guessed conversion is
    indistinguishable from a real one in the output, whereas a null makes the
    product incomplete and therefore visible, matching the store-flag-exclude
    pattern used for every other required field.
    )NNr   z3No fx rate for %s -> %s; product will be incomplete)Úintr   r   ÚwarningÚround)r   r   r   Úrates       r   Úto_reference_centsr#   :   so   € ð Ð¡/Ñ9KØàÐ,Ò,Ü�;Ó Ð$Ð$ä�OÐ%7Ó8€DØ€|Ü�‰ÐLØ&Ð(:ô	<àäŒu�[ 4Ñ'Ó(Ó)¨4Ð/Ð/ó    )r   N)Ú__doc__ÚloggingÚapp.services.infra.databaser   Ú	getLoggerÚ__name__r   r   Ústrr   r   r   Útupler#   © r$   r   ú<module>r-      sŒ   ðñó å @à	ˆ×	Ñ	˜8Ó	$€óð,�3ð ˜sð  u¨t¡|ó ð&0Ø�t‘ð0Ø.1°D©jð0à˜d™
ð0ð ˆ3�‰:�u˜t‘|Ð#Ñ$ô0r$   