+
    i[                    6   ^ RI Ht ^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RIt^ RI	H
t
Ht ^ RIHt ^ RIHt ^ RIHt ]! ]4      P%                  4       P&                  ^,          t]R,          R,          R	,          t]R
,          R,          t]P/                  R4      t]P2                  ! R4      t]P2                  ! R4      t]P2                  ! R]P8                  ]P:                  ,          4      t]P2                  ! R]P8                  ]P:                  ,          4      t]P2                  ! R]P8                  ]P@                  ,          4      t!]
 ! R R4      4       t"R R lt#R R lt$R R lt%R R lt&R R lt'ROR R llt(R  R! lt)R" R# lt*R$ R% lt+R& R' lt,R( R) lt-R* R+ lt.R, R- lt/R. R/ lt0RPR0 R1 llt1R2 R3 lt2R4 R5 lt3R6 R7 lt4R8 R9 lt5R: R; lt6R< R= lt7R> R? lt8R@ RA lt9RB RC lt:RD RE lt;RFRG/RH RI llt<RJ RK lt=RL RM lt>]?RN8X  d
   ]>! 4        R# R# )Q    )annotationsN)	dataclassfield)datetime)StringIO)PathPulled_InfoVouchers
All_Scanedconfigzvouchers.sqlitez.rebuild.sqlitez\b\d{4,5}\bz
\b\d{3,}\bz1^\s*-\s+\*\*Program URL\*\*:\s*(https?://\S+)\s*$z1^\s*-\s+\*\*Account URL\*\*:\s*(https?://\S+)\s*$z```csv\s*(.*?)```c                      ] tR t^t$ RtR]R&   ^ tR]R&   ^ tR]R&   ^ tR]R&   ^ t	R]R&   ^ t
R]R	&   ^ tR]R
&   ^ tR]R&   RtR]R&   ]! ]R7      tR]R&   R R ltRR R lltRtR# )VoucherSummaryincrementalstrmodeintscanned_fileschanged_filesdeleted_filesskipped_filesfolder_count
file_countstyle_price_countFboolfts_enabled)default_factoryz
list[dict]warningsc               (    V ^8  d   QhRRRRRRRR/# )   coder   rel_pathmessagereturnNone )formats   " scripts/rebuild_voucher_index.py__annotate__VoucherSummary.__annotate__)   s(     
 
 
s 
S 
T 
    c           
     	L    V P                   P                  R RRVRVRV/4       R# )severitywarningr    relPathr"   N)r   append)selfr    r!   r"   s   &&&&r'   add_warningVoucherSummary.add_warning)   s-    I87		
r*   Nc                    V ^8  d   QhRRRR/# )r   elapsed_secondszfloat | Noner#   dictr%   )r&   s   "r'   r(   r)   3   s      , $ r*   c                	   R \         P                  ! 4       P                  RR7      RV P                  RV P                  RV P
                  RV P                  RV P                  RV P                  R	V P                  R
V P                  R\        V P                  4      RR\        V P                  4      RV P                  R,          //pVe   \        \!        V4      ^4      VR&   V# )generatedAtseconds)timespecr   scannedFileschangedFilesdeletedFilesskippedFilesfolderCount	fileCountstylePriceCount
ftsEnabled
validationwarningCountr   :N   NelapsedSeconds)r   now	isoformatr   r   r   r   r   r   r   r   r   r   lenr   roundfloat)r0   r4   payloads   && r'   
as_payloadVoucherSummary.as_payload3   s    8<<>33Y3GDIID..D..D..D..4,,t55$t//0DMM 2DMM#.
  &(-eO.Da(HG$%r*   r%   N)__name__
__module____qualname____firstlineno__r   __annotations__r   r   r   r   r   r   r   r   r   listr   r1   rL   __static_attributes__r%   r*   r'   r   r      s{    D#M3M3M3M3L#JsK 6Hj6
 r*   r   c                    V ^8  d   QhRRRR/# )r   valueobjectr#   r   r%   )r&   s   "r'   r(   r(   I   s     9 9f 9 9r*   c                t    \         P                  ! R R\        T ;'       g    R4      4      P                  4       # )z\s+  )resubr   striprW   s   &r'   
clean_textr`   I   s)    66&#s5;;B/06688r*   c                    V ^8  d   QhRRRR/# )r   rW   r   r#   r%   )r&   s   "r'   r(   r(   M   s     % %c %c %r*   c                4    \        V 4      P                  4       # rN   )r`   lowerr_   s   &r'   
lower_normrd   M   s    e""$$r*   c                    V ^8  d   QhRRRR/# )r   textr   r#   	list[str]r%   )r&   s   "r'   r(   r(   Q   s      # ) r*   c                    \        4       p. p\        P                  T ;'       g    R 4       F-  pW19   d   K  VP                  V4       VP	                  V4       K/  	  V# )r[   )set	NUMBER_REfindalladdr/   )rf   seenoutmatchs   &   r'   extract_numbersrp   Q   sO    UDC""4::2.=

5	 /
 Jr*   c                    V ^8  d   QhRRRR/# r   rW   rX   r#   rJ   r%   )r&   s   "r'   r(   r(   \   s      v % r*   c                    \        V 4      P                  R R4      P                  RR4      pV'       g   R#  \        V4      #   \         d     R# i ; i)$r[   ,        r`   replacerJ   	ExceptionrW   raws   & r'   parse_moneyr|   \   sM    
U

#
#C
,
4
4S"
=CSz s   
A AAc                    V ^8  d   QhRRRR/# rr   r%   )r&   s   "r'   r(   r(   f   s      & U r*   c                    \        V 4      P                  R R4      pV'       g   R#  \        V4      #   \         d     R# i ; i)%r[   rv   rw   rz   s   & r'   parse_discountr   f   s@    
U

#
#C
,CSz s   
2 A Ac               $    V ^8  d   QhRRRRRR/# )r   rf   r   	max_linesr   r#   r%   )r&   s   "r'   r(   r(   p   s!     0 0# 0# 0s 0r*   c                    \        T ;'       g    R 4      P                  4        Uu. uF  q"P                  4       NK  	  ppRP                  VRV 4      P	                  4       # u upi )r[   
N)r   
splitlinesrstripjoinr^   )rf   r   lineliness   &&  r'   preview_text_for_searchr   p   sT    '*4::2'A'A'CD'Ct[[]'CED99U:I&'--// Es   A"c               (    V ^8  d   QhRRRRRRRR/# )r   r!   r   rf   summaryr   r#   z%list[tuple[str, float, float, float]]r%   )r&   s   "r'   r(   r(   u   s)       C . Mr r*   c                   . p\         P                  T;'       g    R 4       EF=  pVP                  ^4      P                  4       pV'       g   K-  \        P
                  ! \        V4      4      pV EF  p\        V\        4      '       g   K  \        VP                  R4      ;'       g    VP                  R4      ;'       g    R 4      p\        P                  V4      p	V	'       g   Kx  \        VP                  R4      4      p
\        VP                  R4      4      p\        VP                  R4      ;'       g    VP                  R4      4      p\        VP                  R4      4      pV^ 8:  d
   V^ 8  d   TpV^ 8:  d0   V
^ 8  d)   V^ 8  d"   \        V
^VR,          ,
          ,          ^4      pV
^ 8:  d   V^ 8  d
   V^ 8:  d   Tp
V^ 8:  d1   V
^ 8:  d*   VP!                  R	V R
V	P                  ^ 4       R24       EK  TP#                  V	P                  ^ 4      \%        T
;'       g    R4      \%        T;'       g    R4      \%        T;'       g    R4      34       EK  	  EK@  	  V# )r[   STYLEStyleMSRPzFIXED PRICEz
DISCOUNT %z	DISCOUNT%zPROGRAM PRICEg      Y@voucher_price_missingz$Could not parse price row for style .rv   )CSV_BLOCK_REfinditergroupr^   csv
DictReaderr   
isinstancer5   r`   getSTYLE_REsearchr|   r   rI   r1   r/   rJ   )r!   rf   r   rowsblock_matchblockreaderrow
style_codestyle_matchmsrpfixed_pricediscount_pctprogram_prices   &&&           r'   parse_style_pricesr   u   s
   24D#,,TZZR8!!!$**,0Cc4((#CGGG$4$N$N8H$N$NBOJ"//*5Kswwv/D%cggm&<=K)#'',*?*W*W377;CWXL'(@AM!kAo +!dQh<!3C %da<%3G.H&I1 Mqy]Q.<13D$!dai##$;XImnynn  AB  oC  nD  DE  HF  GKK**1-uT[[S/A5I\I\Y\C]_dereyeyvy_z{|)  94 Kr*   c                    V ^8  d   QhRRRR/# r   connsqlite3.Connectionr#   r$   r%   )r&   s   "r'   r(   r(      s     . .1 .d .r*   c                    V P                  R 4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       R# )zpragma journal_mode = walzpragma synchronous = normalzpragma temp_store = memoryzpragma busy_timeout = 10000zpragma foreign_keys = offN)executer   s   &r'   configure_connectionr      sC    LL,-LL./LL-.LL./LL,-r*   c               $    V ^8  d   QhRRRRRR/# )r   r   r   namer   r#   r   r%   )r&   s   "r'   r(   r(      s"      )   r*   c                L    V P                  R V34      P                  4       pVRJ# )zEselect 1 from sqlite_master where type = 'table' and name = ? limit 1N)r   fetchone)r   r   r   s   && r'   table_existsr      s0    
,,O	 hj  d?r*   c                    V ^8  d   QhRRRR/# r   r%   )r&   s   "r'   r(   r(      s     N N* Nt Nr*   c                   V P                  R 4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R4       V P                  R	4       V P                  R
4        . ROp. p\        V R4      '       dW   V P                  R4      P                  4        Uu. uF-  p\        V^,          ;'       g    R4      P	                  4       NK/  	  ppV'       d   W!8w  d   V P                  R4       V P                  R4       R# u upi   \
        P                   d     R# i ; i)z
        create table if not exists voucher_filesig (
            rel_path text primary key,
            mtime_ns integer not null,
            size_bytes integer not null
        )
        z
        create table if not exists voucher_folders (
            folder text primary key,
            name text not null,
            folder_norm text not null,
            name_norm text not null
        )
        aB  
        create table if not exists voucher_items (
            rel_path text primary key,
            name text not null,
            folder text not null,
            is_dir integer not null,
            numbers_json text not null,
            preview_text text not null,
            preview_blob blob
        )
        aB  
        create table if not exists voucher_style_prices (
            rel_path text not null,
            style_code text not null,
            normal_price real not null,
            discount_pct real not null,
            discounted_price real not null,
            primary key (rel_path, style_code)
        )
        z
        create table if not exists voucher_index_meta (
            key text primary key,
            value_json text not null
        )
        zMcreate index if not exists idx_vf_folder_norm on voucher_folders(folder_norm)z?create index if not exists idx_vf_name on voucher_folders(name)zIcreate index if not exists idx_vf_name_norm on voucher_folders(name_norm)zLcreate index if not exists idx_voucher_items_folder on voucher_items(folder)zUcreate index if not exists idx_voucher_items_type_name on voucher_items(is_dir, name)zLcreate index if not exists idx_vsp_style on voucher_style_prices(style_code)voucher_search_ftsz%pragma table_info(voucher_search_fts)r[   zdrop table voucher_search_ftsz
            create virtual table if not exists voucher_search_fts using fts5(
                rel_path UNINDEXED,
                folder,
                name,
                preview_text,
                numbers_text
            )
            N)r!   folderr   preview_textnumbers_text)r   r   fetchallr   r^   sqlite3DatabaseError)r   expected_fts_columnsexisting_fts_columnsr   s   &   r'   ensure_schemar      sq   LL	 	LL		 	LL
	 	LL		 	LL	 	LL`aLLRSLL\]LL_`LLhiLL_`]!233IMV}I~  JH  JH  JJ  $K  JJ#CA"$5$;$;$=  JJ   $K$8$PLL89
	
 $K    s0   =9E" 6EE)	E" 3(E" E" "E;:E;c                    V ^8  d   QhRRRR/# )r   r   r   r#   zdict[str, tuple[int, int]]r%   )r&   s   "r'   r(   r(      s      r r!3 r8R rr*   c                   \        V R 4      '       g   / # V P                  R4      P                  4       pV UUUu/ uF:  w  r#p\        V4      \	        T;'       g    ^ 4      \	        T;'       g    ^ 4      3bK<  	  uppp# u upppi )voucher_filesigz:select rel_path, mtime_ns, size_bytes from voucher_filesig)r   r   r   r   r   )r   r   r!   mtime_ns
size_bytess   &    r'   load_existing_filesigsr      sq    /00	<<TU^^`DlpqlpJh(^hCMCA.JOO!0DEElpqqqs   3A?.A?c                    V ^8  d   QhRRRR/# )r   r   r   r#   set[str]r%   )r&   s   "r'   r(   r(      s     ) )); ) )r*   c                    \        V R 4      '       g   \        4       # V P                  R4      P                  4       pV Uu0 uF  p\	        V^ ,          4      kK  	  up# u upi )voucher_itemsz3select rel_path from voucher_items where is_dir = 0)r   ri   r   r   r   )r   r   r   s   &  r'   load_existing_indexed_relpathsr      sN    o..u<<MNWWYD#'(4CCAK4(((s    Ac                   V ^8  d   QhRR/# )r   r#   z list[tuple[str, Path, int, int]]r%   )r&   s   "r'   r(   r(     s      < r*   c            	     p   . p \         P                  R 4       F  pVP                  4       '       g   K  VP                  4       pV P	                  VP                  \         4      P                  4       V\        VP                  4      \        VP                  4      34       K  	  V P                  R R7       V # )z*.mdc                0    V ^ ,          P                  4       # )r   )rc   )items   &r'   <lambda>$iter_voucher_files.<locals>.<lambda>
  s    Qr*   )key)
SOURCE_DIRrglobis_filestatr/   relative_toas_posixr   st_mtime_nsst_sizesort)filespathr   s      r'   iter_voucher_filesr     s    .0E  (||~~yy{d&&z2;;=tSIYIYEZ\_`d`l`l\mno	 )
 
JJ/J0Lr*   c               (    V ^8  d   QhRRRRRRRR/# )	r   r!   r   r   r   r   r   r#   ztuple[tuple[str, str, str, int, str, str] | None, tuple[str, int, int] | None, list[tuple[str, str, float, float, float]], tuple[str, str, str, str, str] | None]r%   )r&   s   "r'   r(   r(     s0     )2 )2)2
)2 )2	)2r*   c                    VP                  R RR7      pTP                  4       pTP                  P                  \        4      P                  4       pTR8X  d   RMTp\        T  RTR	,           24      pT TP                  T^ \        P                  ! T4      \        T4      3pT \        TP                  4      \        TP                  4      3p\         P#                  T;'       g    R4      '       g9   \$        P#                  T;'       g    R4      '       g   TP                  R
T R4       \'        YT4      p	T	'       g   TP                  RT R4       T	 U
UUUu. uF  w  rrY
YT3NK  	  pppp
pT TTP                  \        T^xR7      RP)                  T4      3pYxY3#   \         d    TP                  RT R4       RR. R3u # i ; iu upppp
i )zutf-8ignore)encodingerrorsvoucher_read_failedz%Could not read voucher markdown file.Nr   r[   r   :Ni  Nvoucher_missing_portal_urlz4Voucher file is missing Program URL and Account URL.voucher_no_style_rowsz4Voucher file did not produce any style pricing rows.)r   rZ   )	read_textry   r1   r   parentr   r   r   rp   r   jsondumpsr   r   r   r   PROGRAM_URL_REr   ACCOUNT_URL_REr   r   )r!   r   r   rf   r   r   numbersitem_rowsig_rowpricesr   r   r   r   
style_rowsfts_rows   &&&             r'   parse_voucher_filer     s   $~~wx~@ 99;D[[$$Z099;FS=RfF
"T%[M:;G			

7%H T--.DLL0ABG  ,,^5J5J4::SU5V5V8(Dz{8F3X?uv BH  I  BHP}PZbn8]K  BHJ  I		4G j11;  $18=deT2t##$* Is   F G
$GGc                    V ^8  d   QhRRRR/# )r   valuesrg   sizer   r%   )r&   s   "r'   r(   r(   :  s     + +I +S +r*   c              #  `   "   \        ^ \        V 4      V4       F  pWW!,            x  K  	  R# 5i)r   N)rangerH   )r   r   indexs   && r'   chunkedr   :  s)     q#f+t,U\** -s   ,.c               $    V ^8  d   QhRRRRRR/# )r   r   r   	rel_pathsrg   r#   r$   r%   )r&   s   "r'   r(   r(   ?  s'     f f- f) f fr*   c                2   \        V4       F  pR P                  R V 4       4      pV P                  RV R2V4       V P                  RV R2V4       V P                  RV R2V4       \        V R4      '       g   Kq  V P                  RV R2V4       K  	  R# )	, c              3  &   "   T F  pR x  K	  	  R# 5i?Nr%   .0_s   & r'   	<genexpr>#delete_rel_paths.<locals>.<genexpr>A        4ee   4delete from voucher_style_prices where rel_path in ()z-delete from voucher_items where rel_path in (z/delete from voucher_filesig where rel_path in (r   2delete from voucher_search_fts where rel_path in (N)r   r   r   r   )r   r   chunkplaceholderss   &&  r'   delete_rel_pathsr  ?  s    #yy 4e 44KL>YZ[]bcD\NRSTV[\F|nTUVX]^233LLMl^[\]_de $r*   c                    V ^8  d   QhRRRR/# r   r%   )r&   s   "r'   r(   r(   I  s     
 
0 
T 
r*   c           	        V P                  R 4      P                  4       p. pV Fm  w  p\        T;'       g    R4      P                  4       pV'       d   \	        V4      P
                  MRpVP                  W4\        V4      \        V4      34       Ko  	  V P                  R4       V'       d   V P                  RV4       R# R# )z
        select distinct folder
        from voucher_items
        where is_dir = 0
        order by folder collate nocase
        r[   delete from voucher_folderszUinsert into voucher_folders(folder, name, folder_norm, name_norm) values (?, ?, ?, ?)N)	r   r   r   r^   r   r   r/   rd   executemany)r   r   folder_rowsr   r   s   &    r'   rebuild_folder_rowsr  I  s    <<	 hj 	 K	V\\r"((*$*tF|  F*V*<j>NOP  	LL./c	
 r*   c               $    V ^8  d   QhRRRRRR/# )r   r   r   r   r   r#   r$   r%   )r&   s   "r'   r(   r(   _  s(     C C"4 C~ CRV Cr*   c                `   \        V P                  R 4      P                  4       ^ ,          4      Vn        \        V P                  R4      P                  4       ^ ,          4      Vn        \        V P                  R4      P                  4       ^ ,          4      Vn        \        V R4      Vn        R# )z$select count(*) from voucher_foldersz3select count(*) from voucher_items where is_dir = 0z)select count(*) from voucher_style_pricesr   N)r   r   r   r   r   r   r   r   )r   r   s   &&r'   refresh_summary_from_dbr  _  s    t||,RS\\^_`abGT\\*_`iiklmnoG #DLL1\$]$f$f$hij$k lG&t-ABGr*   c                   V ^8  d   QhRR/# r   r#   r$   r%   )r&   s   "r'   r(   r(   f  s      $ r*   c                     \         \         P                  \         P                   R 24      \         P                  \         P                   R24      3 F  p  V P                  RR7       K  	  R#   \         d     K*  i ; i)z-walz-shmT)
missing_okN)WORK_DB_PATH	with_namer   unlinkry   )r   s    r'   remove_work_db_artifactsr  f  s    |559J9J8K46PQS_SiSimym~m~l  @D  kE  TF  G	KK4K( G  		s   A..A=<A=c                    V ^8  d   QhRRRR/# r   r%   )r&   s   "r'   r(   r(   n  s      0 T r*   c                N     V P                  R 4       R#   \         d     R# i ; i)zpragma wal_checkpoint(truncate)N)r   ry   r   s   &r'   checkpoint_databaser"  n  s&    67 s    $$c                    V ^8  d   QhRRRR/# )r   fullr   r#   r   r%   )r&   s   "r'   r(   r(   u  s     
 
D 
%7 
r*   c           	     <   \        4        \        P                  P                  R R R7       V '       g   \        P                  4       '       d   \        P                  ! \        ^R7      ;_uu_ 4       p\        P                  ! \        ^R7      ;_uu_ 4       p\        V4       \        V4       VP                  V4       RRR4       RRR4       \        P                  ! \        ^R7      p\        V4       V#   + '       g   i     LA; i  + '       g   i     LL; i)Tparentsexist_oktimeoutN)
r  r  r   mkdirDB_PATHr   r   connectr   backup)r$  source_conn	temp_connr   s   &   r'   bootstrap_work_dbr1  u  s    dT:GOO%%__Wb11['//R^hjBkBkox - +y) Cl1 ??<4DK ClBk11s$   2%D(C8	?D8DDD	c                   V ^8  d   QhRR/# r  r%   )r&   s   "r'   r(   r(     s       r*   c            
     .   \         P                  4       '       g   \        R \          24      h\        P                  4       '       gG   \        P                  P                  RRR7       \         P                  \        4       \        4        R# Rp \        ^4       F  p \        P                  ! \         ^R7      ;_uu_ 4       p\        P                  ! \        ^R7      ;_uu_ 4       p\        V4       \        V4       VP                  V4       RRR4       RRR4       \        4         R# 	  V e   V hR#   + '       g   i     L/; i  + '       g   i     L:; i  \        P                   d$   pTp \        P                  ! ^4        Rp?K  Rp?ii ; i)zWork database not found: Tr&  Nr)  )r  r   FileNotFoundErrorr,  r   r+  rx   r  r   r   r-  r   r.  OperationalErrortimesleep)
last_errorr  r/  target_connexcs        r'   publish_work_dbr;    s    !!";L> JKK??TD9W% "#'J1X		r::k7??[blnKoKos~$[1$[1"";/ Lp: %&    LpKo:: '' 	JJJqMM	sH   $E%E	'(D6E	E6EE		EEF1FFc               $    V ^8  d   QhRRRRRR/# )r   r   r   current_relpathsr   r#   r   r%   )r&   s   "r'   r(   r(     s$     / /*< /PX /]` /r*   c                   \        V R 4      '       d	   V'       g   ^ # V P                  R4      P                  4       pV Uu0 uFG  q3'       g   K  V^ ,          '       g   K  \        V^ ,          ;'       g    R4      P	                  4       kKI  	  pp\        W,
          4      pV'       g   ^ # ^ p\        VRR7       EF  pRP                  R V 4       4      pV P                  RV R2V4      P                  4       p	. p
V	 F  w  rrpRp \        P                  ! \        T;'       g    R	4      4      p\        V\        4      '       d   R
P                  R V 4       4      pT
P                  \        T;'       g    R4      P	                  4       \        T;'       g    R4      P	                  4       \        T;'       g    R4      P	                  4       \        T;'       g    R4      P	                  4       T34       K  	  V
'       g   EKN  V P                  RV
4       V P!                  4        V\#        V
4      ,          pEK  	  V# u upi   \         d    \        T4      p ELi ; i)r   z'select rel_path from voucher_search_ftsr[     )r   r   c              3  &   "   T F  pR x  K	  	  R# 5ir   r%   r  s   & r'   r  2bootstrap_fts_from_indexed_rows.<locals>.<genexpr>  r  r  z
            select rel_path, folder, name, preview_text, numbers_json
            from voucher_items
            where is_dir = 0 and rel_path in (z)
            z[]rZ   c              3     "   T F?  p\        V4      P                  4       '       g   K$  \        V4      P                  4       x  KA  	  R # 5irN   )r   r^   )r  rW   s   & r'   r  rA    s5     +qN5^abg^h^n^n^p,>CJ,<,<,>,>Ns
   !A	!A	z
                insert into voucher_search_fts(rel_path, folder, name, preview_text, numbers_text)
                values (?, ?, ?, ?, ?)
                )r   r   r   r   r^   sortedr   r   r   loadsr   rT   ry   r`   r/   r  commitrH   )r   r=  existing_rowsr   existing_relpathsmissing_relpathsinsertedr  r  r   fts_rowsr!   r   r   r   numbers_jsonr   parsed_numberss   &&                r'   bootstrap_fts_from_indexed_rowsrM    s   233;KLL!JKTTVM>K^mss2WZ[\W]W]2SV\\r*002m^.BCH)44yy 4e 44||/ 0<n =
 
 (* 	 :<BF>Hd,L8!%C0D0D,E!Fnd33#&88+qN+q#qL OOB'--/"%++-

O))+**+113  CG" 8  KKMH%HK 5L OW _,  8),78s+    	III4IAII! I!c                   V ^8  d   QhRR/# )r   r#   r   r%   )r&   s   "r'   r(   r(     s      / r*   c                     \         P                  P                  R R R7       \        P                  ! \         ^R7      p \        V 4       V # )Tr&  r)  )r,  r   r+  r   r-  r   r   s    r'   open_incremental_dbrP    s6    NN5??7B/DKr*   c                   V ^8  d   QhRR/# r  r%   )r&   s   "r'   r(   r(     s     ' ' 'r*   c                 ,   \         P                  4       '       g   R # \        P                  ! 4       P	                  R4      p \         P                  \         P                   RV  \         P                   24      p\        P                  ! \         V4       R # )Nz%Y%m%d_%H%M%Sz
.pre_full_)
r,  r   r   rF   strftimer  stemsuffixshutilcopy2)	timestampbackup_paths     r'   backup_live_db_for_full_rebuildrZ    s^    ??''8I##w||nJyk'..IY$Z[K
LL+&r*   r$  Fc                    V ^8  d   QhRRRR/# )r   r$  r   r#   r5   r%   )r&   s   "r'   r(   r(     s     ~ ~4 ~D ~r*   c                	   \         P                  ! 4       p\        V '       d   R MRR7      p\        P	                  RRR7       \
        P                  P	                  RRR7       V '       d   \        4        \        V 4      pM
\        4       pT;_uu_ 4       p\        V4       \        V4       V '       d   VP                  R4       VP                  R4       VP                  R4       VP                  R4       \        VR	4      '       d   VP                  R
4       VP                  R4       / p\        4       pM\        V4      p\!        V4      p\#        4       pV UU	u0 uF  vrVkK  	  p
pp	V '       g   \%        WJ4       . p. p. p. p. pV EF  w  ppppV;P&                  ^,          un        VP)                  V4      pT ;'       g    VVV38g  ;'       g    W9  pV'       g   V;P*                  ^,          un        Ks  V;P,                  ^,          un        \/        VVV4      w  ppppVe   Vf   K  VP1                  V4       VP1                  V4       VP3                  V4       Ve   VP1                  V4       VP1                  V4       EK  	  \5        \        V4      V
,
          4      p\7        V4      Vn        V'       d   \;        VV4       V'       d   \=        V4       F[  pRP?                  R V 4       4      pVP                  RV R2V4       \        VR	4      '       g   KE  VP                  RV R2V4       K]  	  VPA                  RV4       VPA                  RV4       V'       d   VPA                  RV4       V'       d%   \        VR	4      '       d   VPA                  RV4       VPC                  4        \E        V4       \G        WB4       VPI                  \         P                  ! 4       V,
          R7      pVP                  R4       VP                  RR\J        PL                  ! V^RR7      34       VPC                  4        \O        V4       RRR4       V '       dP   \Q        4        \R        PT                  ! \
        ^R7      ;_uu_ 4       p\        V4       \O        V4       RRR4       X# X# u up	pi   + '       g   i     Lo; i  + '       g   i     X# ; i)r$  r   )r   Tr&  z delete from voucher_style_priceszdelete from voucher_itemszdelete from voucher_filesigr  r   zdelete from voucher_search_ftszdelete from voucher_index_metaNr   c              3  &   "   T F  pR x  K	  	  R# 5ir   r%   r  s   & r'   r   rebuild_index.<locals>.<genexpr>  s     (<eer  r	  r
  r  a  
                insert into voucher_items(rel_path, name, folder, is_dir, numbers_json, preview_text, preview_blob)
                values (?, ?, ?, ?, ?, ?, null)
                on conflict(rel_path) do update set
                    name = excluded.name,
                    folder = excluded.folder,
                    is_dir = excluded.is_dir,
                    numbers_json = excluded.numbers_json,
                    preview_text = excluded.preview_text,
                    preview_blob = null
                a  
                insert into voucher_filesig(rel_path, mtime_ns, size_bytes)
                values (?, ?, ?)
                on conflict(rel_path) do update set
                    mtime_ns = excluded.mtime_ns,
                    size_bytes = excluded.size_bytes
                z
                    insert into voucher_style_prices(rel_path, style_code, normal_price, discount_pct, discounted_price)
                    values (?, ?, ?, ?, ?)
                    z
                    insert into voucher_search_fts(rel_path, folder, name, preview_text, numbers_text)
                    values (?, ?, ?, ?, ?)
                    )r4   z4delete from voucher_index_meta where key = 'summary'z=insert into voucher_index_meta(key, value_json) values (?, ?)r   )indent	sort_keysr)  )+r6  perf_counterr   r   r+  r,  r   rZ  r1  rP  r   r   r   r   ri   r   r   r   rM  r   r   r   r   r   r/   extendrC  rH   r   r  r   r   r  rE  r  r  rL   r   r   r"  r;  r   r-  )r$  
started_atr   conn_cmr   existing_sigsindexed_relpathscurrent_filesr!   r  r=  parsed_itemsparsed_sigsparsed_style_rowsparsed_fts_rowsparsed_relpathsr   r   r   existing_sig
is_changedr   r   r   r   deleted_relpathsr  r  summary_payloads   $                            r'   rebuild_indexrq    s4   ""$JD&mDGTD1NN5')#D)%'	DT"dLL;<LL45LL67LL67D"677=>LL9:8:M),248M=dC*,9FGHG+DCBD24HJ@B%'4A0HdHj!!Q&!(,,X6Lkk(J1G!Gkk8KkJ%%*%!!Q&!5GRVX_5`2Hgz77?)w'$$Z0"&&w/""8,! 5B$ "#m"47G"GH #$4 5T#34 1#yy(<e(<<ST`Saabcejk&:;;LL#UVbUccd!eglm	 2
 
   	 !   & <6J#K#K   $ KKMD!.!,,T=N=N=PS]=],^KLK

?1MN	
 	D!W 
X __Wb11T &% 2 ?A H% 
\ 21 sZ   C	R>R8
+AR>	R>R>%C4R>AR>*AR>0R>
CR>S8R>>S	S"	c                   V ^8  d   QhRR/# )r   r#   zargparse.Namespacer%   )r&   s   "r'   r(   r(   \  s      & r*   c                 x    \         P                  ! R R7      p V P                  RRRR7       V P                  4       # )z/Incrementally rebuild the voucher SQLite index.)descriptionz--full
store_truezEDrop current indexed rows and rebuild the voucher index from scratch.)actionhelp)argparseArgumentParseradd_argument
parse_args)parsers    r'   r{  r{  \  s>    $$1bcF
  =D  Er*   c                   V ^8  d   QhRR/# r  r%   )r&   s   "r'   r(   r(   b  s     ) )d )r*   c                     \        4       p \        \        V P                  4      R 7      p\	        \
        P                  ! V^R7      4       R# ))r$  )r_  N)r{  rq  r   r$  printr   r   )argsrK   s     r'   mainr  b  s.    <Ddii1G	$**WQ
'(r*   __main__)<   )r?  )@
__future__r   rx  r   r   r\   rV  r   r6  dataclassesr   r   r   ior   pathlibr   __file__resolver'  ROOTr   r,  with_suffixr  compiler   rj   
IGNORECASE	MULTILINEr   r   DOTALLr   r   r`   rd   rp   r|   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r  r"  r1  r;  rM  rP  rZ  rq  r{  r  rO   r%   r*   r'   <module>r     s   "  
  	    (   H~''*M!J.=

/-
-""#45::n%JJ}%	PRTR_R_bdbnbnRnoPRTR_R_bdbnbnRnozz.		0IJ ) ) )X9%0
>.Nbr))2X+
f
,C
0/d'~% ~B) zF r*   