
    ajH                        d dl mZ d dlZd dlmc mZ d dlm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZmZ d dlmZ d dlmZ d ZddZ ddZ!ddZ"ddZ#ddZ$ddZ%dS )    )annotationsN)Decimal)Path)RuntimePaths)Settings)create_crypto_asset)create_initial_holding_snapshot)create_wallet)load_synthetic_demo_data)build_crypto_report_contextexport_crypto_inventory_report)connect_memory)apply_migrationsc                 ^    t                      } t          |            t          |            | S N)r   r   r   )conns    X/home/agent/.hermes/worktrees/FinanceManager-sprint0-v2/tests/unit/test_crypto_report.pysetup_demo_connr      s.    DTT"""K    returnNonec                 (
   t                      } t          |           }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d	}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d
         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d
         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          d |d         D                       }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d
         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}t          d |d         D                       }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}d S )Ntitleu3   JARVIS Finance System – Crypto-Bestandsübersicht==z%(py1)s == %(py4)spy1py4assert %(py6)spy6base_currencyCHFsummary
coin_count   )>=)z%(py1)s >= %(py4)swallet_countc              3  2   K   | ]}|d          dk    |V  dS symbolDBTCN .0rows     r   	<genexpr>z\test_crypto_report_context_from_synthetic_db_aggregates_coins_and_wallets.<locals>.<genexpr>$   0      JJs#h-62I2Is2I2I2I2IJJr   coinstotal_quantity0.0999	price_chfz40000.00	value_chf	3996.0000total_value_chfz	7746.0000c              3  2   K   | ]}|d          dk    |V  dS )wallet_namezKraken DemoNr-   r.   s     r   r1   z\test_crypto_report_context_from_synthetic_db_aggregates_coins_and_wallets.<locals>.<genexpr>)   s1      [[#s=7I]7Z7Z#7Z7Z7Z7Z[[r   wallets)r   r   
@pytest_ar_call_reprcompare	_safereprAssertionError_format_explanationnext)	r   context@py_assert0@py_assert3@py_assert2@py_format5@py_format7btckrakens	            r   Itest_crypto_report_context_from_synthetic_db_aggregates_coins_and_walletsrK      sh   D)$//G7TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT?#,u,#u,,,,,,,,,,#u,,,,,#,,,,u,,,,,,,,,,,,,,,,,,,,,,,,,,,9l+0q0+q0000000000+q00000+0000q0000000000000000000000000009n-22-2222222222-22222-2222222222222222222222222222222
JJgg.JJJ
J
JC ,H, H,,,,,,,,,, H,,,,, ,,,,H,,,,,,,,,,,,,,,,,,,,,,,,,,,{)z)z))))))))))z)))))))))z))))))))))))))))))))))))))){*{*{**********{*********{***************************9/0?K?0K??????????0K?????0????K???????????????????????????[[!3[[[[[F,$1$1$$$$$$$$$$1$$$$$$$$$1$$$$$$$$$$$$$$$$$$$$$$$$$$$$$r   c                 n   t                      } |                     dd           |                                  t          |           }t	          d |d         D                       }|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          d	z  }d
d|iz  }t          t          j	        |                    d x}x}}|d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          d	z  }d
d|iz  }t          t          j	        |                    d x}x}}|d         d         }d}||k    }|slt          j        d|fd||f          t          j        |          t          j        |          d	z  }d
d|iz  }t          t          j	        |                    d x}x}}d |d         D             }t          |          }|sddt          j                    v st          j        t                    rt          j        t                    ndt          j        |          t          j        |          dz  }t          t          j	        |                    d x}}d S )NzcUPDATE crypto_holdings SET legacy_snapshot_value_chf=?, legacy_snapshot_currency=? WHERE quantity=?)999999999.99r#   z0.10c              3  2   K   | ]}|d          dk    |V  dS r*   r-   r.   s     r   r1   zgtest_crypto_report_context_preserves_decimal_text_and_ignores_legacy_snapshot_values.<locals>.<genexpr>7   r2   r   r3   r4   r5   r   r   r   r    r!   r7   r8   r$   r9   rM   )!=)z%(py1)s != %(py4)sc              3  .   K   | ]}|d          dk    V  dS )codelegacy_snapshot_value_ignoredNr-   )r/   ws     r   r1   zgtest_crypto_report_context_preserves_decimal_text_and_ignores_legacy_snapshot_values.<locals>.<genexpr>;   s,      ffqy;;ffffffr   data_quality_warnings,assert %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}anypy0py2r   )r   executecommitr   rB   r=   r>   r?   r@   rA   rV   @py_builtinslocals_should_repr_global_name)	r   rC   rI   rD   rE   rF   rG   rH   @py_assert1s	            r   Ttest_crypto_report_context_preserves_decimal_text_and_ignores_legacy_snapshot_valuesr`   -   s*   DLLm'   	KKMMM)$//G
JJgg.JJJ
J
JC ,H, H,,,,,,,,,, H,,,,, ,,,,H,,,,,,,,,,,,,,,,,,,,,,,,,,,{*{*{**********{*********{***************************9/0BNB0NBBBBBBBBBB0NBBBBB0BBBBNBBBBBBBBBBBBBBBBBBBBBBBBBBBffWMdEeffff3ffffffffffffffff3fffff3fffffffffffffffffffffffffffffffffr   c            	        t                      } |                     d                                          d         }t          | ddd           }t	          | ||t          d          ddd	
           t          |           }t          d |d         D                       }|d         }d}||k    }|slt          j	        d|fd||f          t          j
        |          t          j
        |          dz  }dd|iz  }	t          t          j        |	                    d x}x}}d |d         D             }
d}||
v }|st          j	        d|fd||
f          t          j
        |          dt          j                    v st          j        |
          rt          j
        |
          nddz  }dd|iz  }t          t          j        |                    d x}}d}||
v }|st          j	        d|fd||
f          t          j
        |          dt          j                    v st          j        |
          rt          j
        |
          nddz  }dd|iz  }t          t          j        |                    d x}}d S )Nz,SELECT wallet_id FROM crypto_wallets LIMIT 1	wallet_idzDemo MissingDMX)	coin_namer+   coingecko_idz12.34567890123456789verifiedz2026-01-31T12:00:00Zzsynthetic missing price)asset_idrb   quantityverification_statuslast_verified_atnotec              3  2   K   | ]}|d          dk    |V  dS )r+   rc   Nr-   r.   s     r   r1   z^test_crypto_report_context_warns_for_missing_price_and_missing_coingecko_id.<locals>.<genexpr>N   s0      IIs#h-52H2Hs2H2H2H2HIIr   r3   r4   r   r   r   r    r!   c                    h | ]
}|d          S rQ   r-   r/   warnings     r   	<setcomp>z^test_crypto_report_context_warns_for_missing_price_and_missing_coingecko_id.<locals>.<setcomp>P       MMMWV_MMMr   rT   missing_coingecko_idinz%(py1)s in %(py3)scodesr   py3assert %(py5)spy5missing_price)r   rZ   fetchoner   r	   r   r   rB   r=   r>   r?   r@   rA   r\   r]   r^   )r   rb   rg   rC   dmxrD   rE   rF   rG   rH   rw   @py_format4@py_format6s                r   Ktest_crypto_report_context_warns_for_missing_price_and_missing_coingecko_idr   >   s   DKLLUUWWXcdI"4>%^bcccH#/00&/&    *$//G
IIgg.III
I
IC :$:: $::::::::::: $:::::: ::::$::::::::::::::::::::::::::::MMG4K,LMMME!*!U**********!U*****!***********U*****U***************************#?e##########?e#####?###########e#####e#############################r   c                    t                      } |                     d                                          d         }t          | dddd           }|                     d||f           |                                  t          |           }d |d	         D             }d
}||v }|st          j        d|fd||f          t          j        |          dt          j
                    v st          j        |          rt          j        |          nddz  }dd|iz  }t          t          j        |                    d x}}d}||v }|st          j        d|fd||f          t          j        |          dt          j
                    v st          j        |          rt          j        |          nddz  }dd|iz  }t          t          j        |                    d x}}d S )Nz6SELECT asset_id FROM crypto_assets WHERE symbol='DETH'rg   zUnverified Demo WalletzSoftware Wallet	Synthetic)r;   wallet_typeplatform_providerrj   a5  
        INSERT INTO crypto_holdings(
            crypto_holding_id, asset_id, wallet_id, quantity, acquisition_source,
            verification_status, notes, created_at
        ) VALUES ('negative-demo', ?, ?, '-0.25', 'initial_snapshot', 'unverified', 'synthetic negative', '2026-01-31T00:00:00Z')
        c                    h | ]
}|d          S rn   r-   ro   s     r   rq   z^test_crypto_report_context_warns_for_unverified_wallet_and_negative_holding.<locals>.<setcomp>l   rr   r   rT   unverified_walletrt   rv   rw   rx   rz   r{   negative_holding)r   rZ   r}   r
   r[   r   r=   r>   r?   r\   r]   r^   r@   rA   )	r   rg   rb   rC   rw   rD   rF   r   r   s	            r   Ktest_crypto_report_context_warns_for_unverified_wallet_and_negative_holdingr   U   s@   D||TUU^^``aklH,%%  I 	LL	 
9   	KKMMM)$//GMMG4K,LMMME'%''''''''''%''''''''''''''''%'''''%'''''''''''''''''''''''''''&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&r   tmp_pathr   c                   t                      }t          j        | dz            }t          |          }t	          ||dd           }t          |d                   }|j        } |            }|sddt          j                    v st          j
        |          rt          j        |          ndt          j        |          t          j        |          d	z  }t          t          j        |                    d x}}|j        }d
}	||	k    }|st          j        d|fd||	f          dt          j                    v st          j
        |          rt          j        |          ndt          j        |          t          j        |	          dz  }
dd|
iz  }t          t          j        |                    d x}x}}	|j        }|j        }||v }|st          j        d|fd||f          dt          j                    v st          j
        |          rt          j        |          ndt          j        |          dt          j                    v st          j
        |          rt          j        |          ndt          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }t          |          }|j        } |            }|j        }t
          j        } |            }|j        } |            } ||          }| }|suddt          j                    v st          j
        t
                    rt          j        t
                    ndt          j        |          t          j        |          t          j        |          t          j        |          t          j        |          dt          j                    v st          j
        t
                    rt          j        t
                    ndt          j        |          t          j        |          t          j        |          t          j        |          t          j        |          dz  }t          t          j        |                    d x}x}x}x}x}x}x}x}x}x}}|                    d                                          }d }||u}|st          j        d|fd||f          dt          j                    v st          j
        |          rt          j        |          ndt          j        |          dz  }dd|iz  }
t          t          j        |
                    d x}}|d         }d }||k    }|slt          j        d|fd!||f          t          j        |          t          j        |          d"z  }d#d$|iz  }t          t          j        |                    d x}x}}|d         }t/          |          }||k    }|st          j        d|fd%||f          t          j        |          d&t          j                    v st          j
        t.                    rt          j        t.                    nd&dt          j                    v st          j
        |          rt          j        |          ndt          j        |          d'z  }dd|iz  }t          t          j        |                    d x}x}}|                    d(                                          }d }||u}|st          j        d|fd||f          d)t          j                    v st          j
        |          rt          j        |          nd)t          j        |          dz  }dd|iz  }
t          t          j        |
                    d x}}d S )*Nruntimeruntime_pathspdfc                    dS )NFr-   )htmlpaths     r   <lambda>zTtest_crypto_report_export_writes_runtime_report_metadata_and_audit.<locals>.<lambda>v   s    y~ r   settingspreferred_formatrenderer	file_pathAassert %(py4)s
{%(py4)s = %(py2)s
{%(py2)s = %(py0)s.exists
}()
}output_pathrW   .htmlr   )z.%(py2)s
{%(py2)s = %(py0)s.suffix
} == %(py5)srX   rY   r{   assert %(py7)spy7rt   )zP%(py2)s
{%(py2)s = %(py0)s.reports_dir
} in %(py6)s
{%(py6)s = %(py4)s.parents
})rX   rY   r   r!   zassert %(py8)spy8a  assert not %(py21)s
{%(py21)s = %(py10)s
{%(py10)s = %(py8)s
{%(py8)s = %(py6)s
{%(py6)s = %(py4)s
{%(py4)s = %(py0)s(%(py2)s)
}.resolve
}()
}.is_relative_to
}(%(py19)s
{%(py19)s = %(py17)s
{%(py17)s = %(py15)s
{%(py15)s = %(py13)s
{%(py13)s = %(py11)s.cwd
}()
}.resolve
}()
})
}r   )rX   rY   r   r!   r   py10py11py13py15py17py19py21z:SELECT * FROM reports WHERE report_type='crypto_inventory')is not)z%(py0)s is not %(py3)sreport)rX   ry   rz   r{   formatr   r   r   r    r!   )z0%(py1)s == %(py6)s
{%(py6)s = %(py3)s(%(py4)s)
}str)r   ry   r   r!   z7SELECT * FROM audit_log WHERE action='report_generated'audit)r   r   	from_baser   r   r   existsr\   r]   r=   r^   r?   r@   rA   suffixr>   reports_dirparentsresolveis_relative_tocwdrZ   r}   r   )r   r   r   r   resultr   r_   rE   rG   @py_assert4r   @py_format8@py_assert5rH   @py_format9@py_assert7@py_assert9@py_assert12@py_assert14@py_assert16@py_assert18@py_assert20@py_assert22@py_format23r   rF   r   rD   r   s                                r   Btest_crypto_report_export_writes_runtime_report_metadata_and_auditr   q   s   D$X	%9::Gg...H+D8V[f~f~Fvk*++K;;((((((((((((((((((((((((;(((((;(((((((((((((((((((((((((((((((((((((5+"55"55555555555"5555555555555755555755555555555555555+55555+555555"5555555555555555555555555555;'Wt'((W(0W0022W2AW$(W((**W*BTWBTBTBVBVWAABVWWWWWWWWWWWWWWWWWWtWWWWWtWWWWWW'WWWW(WWWW0WWWW2WWWWAWWWWWWWWWWW$WWWWW$WWWWWW(WWWW*WWWWBTWWWWBVWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW\\VWW``bbF6666(%v%v%%%%%%%%%%v%%%%%%%%%v%%%%%%%%%%%%%%%%%%%%%%%%%%%+2#k"2"22"22222222222"22222222222222222#22222#2222222222222k22222k222222"2222222222222222222222222222LLRSS\\^^E5555r   c                   t                      }t          j        | dz            }t          |          }t	          ||dd           }t          |d                   }|j        } |            }|sddt          j                    v st          j
        |          rt          j        |          ndt          j        |          t          j        |          dz  }t          t          j        |                    d x}}|j        }d	d
h}	||	v }|st          j        d|fd||	f          dt          j                    v st          j
        |          rt          j        |          ndt          j        |          t          j        |	          dz  }
dd|
iz  }t          t          j        |                    d x}x}}	|d         }ddh}||v }|slt          j        d|fd||f          t          j        |          t          j        |          dz  }dd|iz  }t          t          j        |                    d x}x}}|d         }|s:ddt          j        |          iz  }t          t          j        |                    d }d |j                            d          D             }t%          |          }|sddt          j                    v st          j
        t$                    rt          j        t$                    ndt          j        |          t          j        |          dz  }t          t          j        |                    d x}}d S )Nr   r   r   r   r   r   r   rW   r   z.mdrt   )z.%(py2)s
{%(py2)s = %(py0)s.suffix
} in %(py5)sr   r   r   r   r   markdown)z%(py1)s in %(py4)sr   r    r!   warningszassert %(py1)sr   c              3     K   | ]=}|                     t          j                                                               V  >d S r   )r   r   r   r   )r/   ps     r   r1   z\test_crypto_report_export_markdown_fallback_when_pdf_renderer_unavailable.<locals>.<genexpr>   sE      aaa1##DHJJ$6$6$8$8999aaaaaar   *rU   all)r   r   r   r   r   r   r   r\   r]   r=   r^   r?   r@   rA   r   r>   r   globr   )r   r   r   r   r   r   r_   rE   rG   r   r   r   rD   rF   rH   @py_format2s                   r   Itest_crypto_report_export_markdown_fallback_when_pdf_renderer_unavailabler      s   D$X	%9::Gg...H+D8V[fjkkkFvk*++K;;1'5!11!11111111111!1111111111111;11111;1111111111!1111111111111111111111111111(3
333333333333333333333333333333333333333333333333333*aa7CVC[C[\_C`C`aaaa3aaaaaaaaaaaaaaaa3aaaaa3aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar   )r   r   )r   r   r   r   )&
__future__r   builtinsr\   _pytest.assertion.rewrite	assertionrewriter=   decimalr   pathlibr   jarvis_finance.config.pathsr   jarvis_finance.config.settingsr   jarvis_finance.crypto.assetsr   jarvis_finance.crypto.holdingsr	   jarvis_finance.crypto.walletsr
   "jarvis_finance.dashboard.demo_datar   'jarvis_finance.reports.crypto_inventoryr   r   jarvis_finance.storage.databaser   !jarvis_finance.storage.migrationsr   r   rK   r`   r   r   r   r   r-   r   r   <module>r      s   " " " " " "                           4 4 4 4 4 4 3 3 3 3 3 3 < < < < < < J J J J J J 7 7 7 7 7 7 G G G G G G        ; : : : : : > > > > > >  % % % %$g g g g"$ $ $ $.' ' ' '8   (b b b b b br   