This commit is contained in:
2026-05-29 13:37:26 +02:00
parent d290be0f6b
commit f02d6dcb8a
80 changed files with 107 additions and 1090 deletions
Binary file not shown.
@@ -1,3 +1,3 @@
2026/05/28-09:34:01.521 26f4 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/MANIFEST-000001
2026/05/28-09:34:01.522 26f4 Recovering log #3
2026/05/28-09:34:01.522 26f4 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/000003.log
2026/05/29-13:24:16.539 6b34 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/MANIFEST-000001
2026/05/29-13:24:16.540 6b34 Recovering log #3
2026/05/29-13:24:16.541 6b34 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:20:54.095 55ec Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/MANIFEST-000001
2026/05/28-09:20:54.096 55ec Recovering log #3
2026/05/28-09:20:54.096 55ec Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/000003.log
2026/05/29-13:17:37.742 5acc Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/MANIFEST-000001
2026/05/29-13:17:37.742 5acc Recovering log #3
2026/05/29-13:17:37.743 5acc Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Extension State/000003.log
Binary file not shown.
@@ -1,3 +1,3 @@
2026/05/28-09:34:11.834 4160 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/MANIFEST-000001
2026/05/28-09:34:11.835 4160 Recovering log #3
2026/05/28-09:34:11.836 4160 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/000003.log
2026/05/29-13:24:32.087 1144 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/MANIFEST-000001
2026/05/29-13:24:32.087 1144 Recovering log #3
2026/05/29-13:24:32.087 1144 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:21:04.862 2184 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/MANIFEST-000001
2026/05/28-09:21:04.864 2184 Recovering log #3
2026/05/28-09:21:04.865 2184 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/000003.log
2026/05/29-13:17:47.687 5428 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/MANIFEST-000001
2026/05/29-13:17:47.696 5428 Recovering log #3
2026/05/29-13:17:47.696 5428 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\GCM Store/000003.log
Binary file not shown.
@@ -1,3 +1,3 @@
2026/05/28-08:18:49.515 3070 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/MANIFEST-000001
2026/05/28-08:18:49.515 3070 Recovering log #3
2026/05/28-08:18:49.515 3070 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/000003.log
2026/05/29-11:20:05.334 264 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/MANIFEST-000001
2026/05/29-11:20:05.335 264 Recovering log #3
2026/05/29-11:20:05.335 264 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/000003.log
@@ -1,3 +1,3 @@
2026/05/28-08:03:00.480 474c Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/MANIFEST-000001
2026/05/28-08:03:00.481 474c Recovering log #3
2026/05/28-08:03:00.481 474c Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/000003.log
2026/05/29-11:17:21.700 5a0c Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/MANIFEST-000001
2026/05/29-11:17:21.700 5a0c Recovering log #3
2026/05/29-11:17:21.700 5a0c Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\IndexedDB\https_xsp.covance.com_0.indexeddb.leveldb/000003.log
@@ -1,6 +1,6 @@
2026/05/28-09:34:01.216 1690 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/MANIFEST-000001
2026/05/28-09:34:01.223 1690 Recovering log #106
2026/05/28-09:34:01.225 1690 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/000106.log
2026/05/28-09:34:15.864 8d0 Level-0 table #110: started
2026/05/28-09:34:15.951 8d0 Level-0 table #110: 24294 bytes OK
2026/05/28-09:34:16.039 8d0 Delete type=0 #106
2026/05/29-13:24:16.084 988 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/MANIFEST-000001
2026/05/29-13:24:16.091 988 Recovering log #160
2026/05/29-13:24:16.093 988 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/000160.log
2026/05/29-13:24:33.012 6ac4 Level-0 table #165: started
2026/05/29-13:24:33.073 6ac4 Level-0 table #165: 20511 bytes OK
2026/05/29-13:24:33.150 6ac4 Delete type=0 #160
@@ -1,3 +1,15 @@
2026/05/28-09:20:53.814 57f0 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/MANIFEST-000001
2026/05/28-09:20:53.820 57f0 Recovering log #106
2026/05/28-09:20:53.822 57f0 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/000106.log
2026/05/29-13:17:37.366 6a60 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/MANIFEST-000001
2026/05/29-13:17:37.373 6a60 Recovering log #157
2026/05/29-13:17:37.375 6a60 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Local Storage\leveldb/000157.log
2026/05/29-13:17:51.674 6264 Level-0 table #161: started
2026/05/29-13:17:51.748 6264 Level-0 table #161: 19877 bytes OK
2026/05/29-13:17:51.815 6264 Delete type=0 #157
2026/05/29-13:17:51.816 6264 Compacting 4@0 + 1@1 files
2026/05/29-13:17:51.881 6264 Generated table #162@0: 24 keys, 30021 bytes
2026/05/29-13:17:51.882 6264 Compacted 4@0 + 1@1 files => 30021 bytes
2026/05/29-13:17:51.914 6264 compacted to: files[ 0 1 1 0 0 0 0 ]
2026/05/29-13:17:51.915 6264 Delete type=2 #149
2026/05/29-13:17:51.915 6264 Delete type=2 #152
2026/05/29-13:17:51.915 6264 Delete type=2 #155
2026/05/29-13:17:51.915 6264 Delete type=2 #158
2026/05/29-13:17:51.915 6264 Delete type=2 #161
@@ -1 +1 @@
{"net":{"http_server_properties":{"servers":[{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"server":"https://login.labcorp.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"server":"https://cdn.pendo.io","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"server":"https://data.pendo.io","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427014730141327","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"network_stats":{"srtt":7242},"server":"https://content-autofill.googleapis.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",true,0],"server":"https://login.labcorp.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427019241807994","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":14394},"server":"https://accounts.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13424513642283952","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"network_stats":{"srtt":3782},"server":"https://unpkg.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427019251909434","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":8718},"server":"https://android.clients.google.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":3267},"server":"https://fonts.gstatic.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427012816734610","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":6914},"server":"https://fonts.googleapis.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"server":"https://login.labcorp.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427019284329367","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":7280},"server":"https://content-autofill.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427019266698306","port":443,"protocol_str":"quic"}],"anonymization":["MAAAACwAAABodHRwczovL3Bhc3N3b3Jkc2xlYWtjaGVjay1wYS5nb29nbGVhcGlzLmNvbQ==",false,0],"network_stats":{"srtt":3684},"server":"https://passwordsleakcheck-pa.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13424513657366598","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":6122},"server":"https://unpkg.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427019241781650","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":5175},"server":"https://www.google.com","supports_spdy":true}],"supports_quic":{"address":"192.168.1.87","used_quic":true},"version":5},"network_qualities":{"CAESABiAgICA+P////8B":"4G"}}}
{"net":{"http_server_properties":{"servers":[{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"server":"https://login.labcorp.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"server":"https://cdn.pendo.io","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"server":"https://data.pendo.io","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427112006055382","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"network_stats":{"srtt":6621},"server":"https://content-autofill.googleapis.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",true,0],"server":"https://login.labcorp.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427119456814562","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":10524},"server":"https://accounts.google.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13424613857546976","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2NvdmFuY2UuY29tAA==",false,0],"network_stats":{"srtt":5917},"server":"https://unpkg.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427107435975955","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":6306},"server":"https://fonts.googleapis.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":6502},"server":"https://fonts.gstatic.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427119484319015","port":443,"protocol_str":"quic"}],"anonymization":["MAAAACwAAABodHRwczovL3Bhc3N3b3Jkc2xlYWtjaGVjay1wYS5nb29nbGVhcGlzLmNvbQ==",false,0],"network_stats":{"srtt":4832},"server":"https://passwordsleakcheck-pa.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427119496814314","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":7750},"server":"https://android.clients.google.com","supports_spdy":true},{"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"server":"https://login.labcorp.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427119978225009","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":6055},"server":"https://content-autofill.googleapis.com","supports_spdy":true},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13424614330059042","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABMAAABodHRwczovL2xhYmNvcnAuY29tAA==",false,0],"network_stats":{"srtt":6720},"server":"https://unpkg.com"},{"alternative_service":[{"advertised_alpns":["h3"],"expiration":"13427119456718085","port":443,"protocol_str":"quic"}],"anonymization":["GAAAABIAAABodHRwczovL2dvb2dsZS5jb20AAA==",false,0],"network_stats":{"srtt":6576},"server":"https://www.google.com","supports_spdy":true}],"supports_quic":{"address":"192.168.1.87","used_quic":true},"version":5},"network_qualities":{"CAESABiAgICA+P////8B":"4G"}}}
@@ -1 +1 @@
{"sts":[{"expiry":1811489682.936012,"host":"AMsYuZ7IFgNWVHHQOkqKt9MmwK65kaqBH0lsKFOUFH8=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779953682.936014},{"expiry":1811489656.619357,"host":"CSChKrlj3luqm4YaUcREYcNSGviDSaiJLYYv+tJJLQY=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779953656.619369},{"expiry":1811485129.395782,"host":"Cz1hgA9AsWBjlwLNwma1z9V2NS3WBGpE+hAisJYAzJg=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779949129.395788},{"expiry":1811485129.780754,"host":"bwzZzlAVpSjLBr+9/WzKm/QotRxOYnqfzWRcWGuF4/M=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779949129.780757},{"expiry":1811489684.552903,"host":"eS7TxKKR6KM2rUe5fGp4j6+eHcckwVadZAWT/TaU2RQ=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779953684.552906},{"expiry":1811489657.426032,"host":"e3SziuwfuO2UvuBno+qkR1ObHAzZmSUoJhrc7dbP1Uo=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779953657.426039},{"expiry":1811483216.73492,"host":"nAuqgR4iEWti7SOdT3UHPl6rmZU/DeaIm38P2O2OkgA=","mode":"force-https","sts_include_subdomains":false,"sts_observed":1779947216.734924},{"expiry":1810638866.791394,"host":"rBPMDlZ3oSoS5nWA5b3qh68smMftsPTTcEHPHa/8Asc=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779102866.791399},{"expiry":1811489641.782165,"host":"5EdUoB7YUY9zZV+2DkgVXgho8WUvp+D+6KpeUOhNQIM=","mode":"force-https","sts_include_subdomains":false,"sts_observed":1779953641.782169},{"expiry":1811489641.808069,"host":"8/RrMmQlCD2Gsp14wUCE1P8r7B2C5+yE0+g79IPyRsc=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779953641.808072}],"version":2}
{"sts":[{"expiry":1811590376.982667,"host":"AMsYuZ7IFgNWVHHQOkqKt9MmwK65kaqBH0lsKFOUFH8=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780054376.982671},{"expiry":1811589873.806784,"host":"CSChKrlj3luqm4YaUcREYcNSGviDSaiJLYYv+tJJLQY=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780053873.80679},{"expiry":1811581653.541007,"host":"Cz1hgA9AsWBjlwLNwma1z9V2NS3WBGpE+hAisJYAzJg=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780045653.54101},{"expiry":1811582405.562701,"host":"bwzZzlAVpSjLBr+9/WzKm/QotRxOYnqfzWRcWGuF4/M=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780046405.562703},{"expiry":1811590379.118582,"host":"eS7TxKKR6KM2rUe5fGp4j6+eHcckwVadZAWT/TaU2RQ=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780054379.118586},{"expiry":1811590330.059279,"host":"e3SziuwfuO2UvuBno+qkR1ObHAzZmSUoJhrc7dbP1Uo=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780054330.059282},{"expiry":1811577835.976147,"host":"nAuqgR4iEWti7SOdT3UHPl6rmZU/DeaIm38P2O2OkgA=","mode":"force-https","sts_include_subdomains":false,"sts_observed":1780041835.97615},{"expiry":1810638866.791394,"host":"rBPMDlZ3oSoS5nWA5b3qh68smMftsPTTcEHPHa/8Asc=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1779102866.791399},{"expiry":1811589856.718672,"host":"5EdUoB7YUY9zZV+2DkgVXgho8WUvp+D+6KpeUOhNQIM=","mode":"force-https","sts_include_subdomains":false,"sts_observed":1780053856.718678},{"expiry":1811589856.814671,"host":"8/RrMmQlCD2Gsp14wUCE1P8r7B2C5+yE0+g79IPyRsc=","mode":"force-https","sts_include_subdomains":true,"sts_observed":1780053856.814676}],"version":2}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,3 +1,3 @@
2026/05/28-09:34:01.390 1690 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/MANIFEST-000001
2026/05/28-09:34:01.393 1690 Recovering log #4
2026/05/28-09:34:01.411 1690 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/000004.log
2026/05/29-13:24:16.313 988 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/MANIFEST-000001
2026/05/29-13:24:16.314 988 Recovering log #7
2026/05/29-13:24:16.318 988 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/000007.log
@@ -1,3 +1,3 @@
2026/05/28-09:20:53.976 57f0 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/MANIFEST-000001
2026/05/28-09:20:53.978 57f0 Recovering log #4
2026/05/28-09:20:53.995 57f0 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/000004.log
2026/05/29-13:17:37.578 6a60 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/MANIFEST-000001
2026/05/29-13:17:37.580 6a60 Recovering log #7
2026/05/29-13:17:37.611 6a60 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Session Storage/000007.log
@@ -1,3 +1,3 @@
2026/05/28-09:34:01.159 3804 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/MANIFEST-000001
2026/05/28-09:34:01.161 3804 Recovering log #3
2026/05/28-09:34:01.161 3804 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/000003.log
2026/05/29-13:24:16.027 3a94 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/MANIFEST-000001
2026/05/29-13:24:16.029 3a94 Recovering log #3
2026/05/29-13:24:16.030 3a94 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:20:53.754 56d0 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/MANIFEST-000001
2026/05/28-09:20:53.757 56d0 Recovering log #3
2026/05/28-09:20:53.758 56d0 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/000003.log
2026/05/29-13:17:37.311 662c Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/MANIFEST-000001
2026/05/29-13:17:37.316 662c Recovering log #3
2026/05/29-13:17:37.316 662c Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Site Characteristics Database/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:34:01.147 5b28 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/MANIFEST-000001
2026/05/28-09:34:01.153 5b28 Recovering log #3
2026/05/28-09:34:01.153 5b28 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/000003.log
2026/05/29-13:24:16.017 6b88 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/MANIFEST-000001
2026/05/29-13:24:16.020 6b88 Recovering log #3
2026/05/29-13:24:16.021 6b88 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:20:53.750 28cc Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/MANIFEST-000001
2026/05/28-09:20:53.756 28cc Recovering log #3
2026/05/28-09:20:53.757 28cc Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/000003.log
2026/05/29-13:17:37.299 6564 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/MANIFEST-000001
2026/05/29-13:17:37.306 6564 Recovering log #3
2026/05/29-13:17:37.306 6564 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\Sync Data\LevelDB/000003.log
Binary file not shown.
Binary file not shown.
@@ -1 +1 @@
v10*κE0Iω4ΗΎη4"7>ΑXιzE@κ‰Λ[ρ­σίΟ‡!,σΥ³ξxΉ#PΎ“ρτΟΣπ
v10Œ%4Â{}x|P„Ì1dlðá[5²ilpÒ(÷ZON~ éøBîžl\Û´²ÂD”°²%¥Ðɺê»
@@ -1,3 +1,3 @@
2026/05/28-09:34:01.405 26f4 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/MANIFEST-000001
2026/05/28-09:34:01.406 26f4 Recovering log #3
2026/05/28-09:34:01.408 26f4 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/000003.log
2026/05/29-13:24:16.339 6b88 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/MANIFEST-000001
2026/05/29-13:24:16.339 6b88 Recovering log #3
2026/05/29-13:24:16.341 6b88 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:20:53.995 28cc Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/MANIFEST-000001
2026/05/28-09:20:53.996 28cc Recovering log #3
2026/05/28-09:20:53.997 28cc Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/000003.log
2026/05/29-13:17:37.597 5d84 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/MANIFEST-000001
2026/05/29-13:17:37.598 5d84 Recovering log #3
2026/05/29-13:17:37.600 5d84 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:34:01.398 26f4 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/MANIFEST-000001
2026/05/28-09:34:01.399 26f4 Recovering log #3
2026/05/28-09:34:01.399 26f4 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/000003.log
2026/05/29-13:24:16.334 6b88 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/MANIFEST-000001
2026/05/29-13:24:16.334 6b88 Recovering log #3
2026/05/29-13:24:16.335 6b88 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/000003.log
@@ -1,3 +1,3 @@
2026/05/28-09:20:53.987 28cc Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/MANIFEST-000001
2026/05/28-09:20:53.988 28cc Recovering log #3
2026/05/28-09:20:53.988 28cc Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/000003.log
2026/05/29-13:17:37.591 5d84 Reusing MANIFEST U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/MANIFEST-000001
2026/05/29-13:17:37.592 5d84 Recovering log #3
2026/05/29-13:17:37.592 5d84 Reusing old log U:\PythonProject\Janssen\Covance_UCO3001\browser_profile\Default\shared_proto_db\metadata/000003.log
Binary file not shown.
Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
{"autofill":{"ablation_seed":"Pts3KboF9Gg="},"breadcrumbs":{"enabled":false,"enabled_time":"13423576449583774"},"browser":{"shortcut_migration_version":"145.0.7632.6","whats_new":{"enabled_order":["ReadAnythingReadAloud","SideBySide","PdfInk2"]}},"chrome_labs_activation_threshold":89,"chrome_labs_new_badge_dict":{},"hardware_acceleration_mode_previous":true,"legacy":{"profile":{"name":{"migrated":true}}},"local":{"password_hash_data_list":[]},"management":{"platform":{"azure_active_directory":8,"enterprise_mdm_win":0}},"network_time":{"network_time_mapping":{"local":1.77994815531412e+12,"network":1.779948155236e+12,"ticks":4838234648.0,"uncertainty":10134021.0}},"os_crypt":{"audit_enabled":true,"encrypted_key":"RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAADkezkwH4wQT6pFnkj5e+nkEAAAADQAAABHAG8AbwBnAGwAZQAgAEMAaAByAG8AbQBlACAAZgBvAHIAIABUAGUAcwB0AGkAbgBnAAAAA2YAAMAAAAAQAAAAD8GdBnyhPqKO+3clLuoubgAAAAAEgAAAoAAAABAAAADMD85LpYqkKeWfmsz19kEEKAAAADmxXqsmFE4qCIFVf7fbf6Lkktqe+GmWXWIQTJb2EHCeDDclpUygwFUUAAAAxudMuaV2vqrqS22DRgyN4Bw1/aI="},"performance_intervention":{"last_daily_sample":"13424420803777120"},"policy":{"last_statistics_update":"13424420803455233"},"profile":{"info_cache":{"Default":{"active_time":1779952853.947476,"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_26","background_apps":false,"default_avatar_fill_color":-2890755,"default_avatar_stroke_color":-16166200,"enterprise_label":"","force_signin_profile_locked":false,"gaia_given_name":"","gaia_id":"","gaia_name":"","hosted_domain":"","is_consented_primary_account":false,"is_ephemeral":false,"is_glic_eligible":false,"is_managed":0,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","metrics_bucket_index":1,"name":"Your Chromium","profile_color_seed":-16033840,"profile_highlight_color":-2890755,"signin.with_credential_provider":false,"user_name":""}},"last_active_profiles":["Default"],"metrics":{"next_bucket_index":2},"profile_counts_reported":"13424420803460889","profiles_order":["Default"]},"profile_network_context_service":{"http_cache_finch_experiment_groups":"None None None None"},"session_id_generator_last_value":"1074085646","signin":{"active_accounts_last_emitted":"13424420803387923"},"subresource_filter":{"ruleset_version":{"checksum":0,"content":"","format":0}},"tab_stats":{"discards_external":0,"discards_frozen":0,"discards_proactive":0,"discards_suggested":0,"discards_urgent":0,"last_daily_sample":"13424420803441717","max_tabs_per_window":2,"reloads_external":0,"reloads_frozen":0,"reloads_proactive":0,"reloads_suggested":0,"reloads_urgent":0,"total_tab_count_max":2,"window_count_max":1},"toast":{"non_milestone_update_toast_version":"145.0.7632.6"},"ukm":{"persisted_logs":[]},"uninstall_metrics":{"installation_date2":"1779102849"},"user_experience_metrics":{"client_id2":"43a4d29b-dfa2-4f8b-9a46-fe2351fed503","client_id_timestamp":"1779102849","limited_entropy_randomization_source":"795E664817D8383D9992183FB246CB96","log_record_id":29,"low_entropy_source3":4488,"machine_id":6709466,"pseudo_low_entropy_source":1702,"session_id":28,"stability":{"browser_last_live_timestamp":"13424427286217033","exited_cleanly":true,"saved_system_profile":"CLzkm8sGEhUxNDUuMC43NjMyLjYtNjQtZGV2ZWwYsOKr0AYiBWVuLVVTKhgKCldpbmRvd3MgTlQSCjEwLjAuMTkwNDQyfgoGeDg2XzY0EMb9ARiAgNT7sP8fIhlIUCBaMjMwIFRvd2VyIFdvcmtzdGF0aW9uKAMwgBQ4oAtCCggAEAAaADIAOgBNiU3PQlXibM9CZQAAwD9qGAoMR2VudWluZUludGVsEMONDBgIIAEoAIIBAIoBAKoBBng4Nl82NLABAUoKDW0jOl4V0IbiWUoKDZK3V7MV3xdKP0oKDQUO8PQVgI19ylAAaggIABAAOABAAIABsOKr0AaYAQD4AYgjgAL///////////8BiAIAkgIkNDNhNGQyOWItZGZhMi00ZjhiLTlhNDYtZmUyMzUxZmVkNTAzqAKmDbICoAFkHjnSnstQPTfirX7FiAAqfsiwbNubM6kLj70v2MAtsf5bz4dGdDQ67motfyp+LMUZDNsJTLRUE0n9H/9UH43yOKroA8plfhtjdx59eUuqaR4MRo3j+04u52w1YviiiC9v2UFh7INtJFaBCRbIQET+tRCH0tbGCqYb9QXxOQvdoidEg0ktvAubY+tt3VOfvs9ZduhzQuDj64SLuP9M8w1d8QKiJMcGz0wjig==","saved_system_profile_hash":"D84CCF82A85C1BE2C9DA241E7E58399ECE4C5019","stats_buildtime":"1768354364","stats_version":"145.0.7632.6-64-devel","system_crash_count":0}},"variations_google_groups":{"Default":[]},"was":{"restarted":false}}
{"autofill":{"ablation_seed":"Pts3KboF9Gg="},"breadcrumbs":{"enabled":false,"enabled_time":"13423576449583774"},"browser":{"shortcut_migration_version":"145.0.7632.6","whats_new":{"enabled_order":["ReadAnythingReadAloud","SideBySide","PdfInk2"]}},"chrome_labs_activation_threshold":89,"chrome_labs_new_badge_dict":{},"hardware_acceleration_mode_previous":true,"legacy":{"profile":{"name":{"migrated":true}}},"local":{"password_hash_data_list":[]},"management":{"platform":{"azure_active_directory":8,"enterprise_mdm_win":0}},"network_time":{"network_time_mapping":{"local":1.780042333499841e+12,"network":1.780042333448e+12,"ticks":8161390296.0,"uncertainty":10134152.0}},"os_crypt":{"audit_enabled":true,"encrypted_key":"RFBBUEkBAAAA0Iyd3wEV0RGMegDAT8KX6wEAAADkezkwH4wQT6pFnkj5e+nkEAAAADQAAABHAG8AbwBnAGwAZQAgAEMAaAByAG8AbQBlACAAZgBvAHIAIABUAGUAcwB0AGkAbgBnAAAAA2YAAMAAAAAQAAAAD8GdBnyhPqKO+3clLuoubgAAAAAEgAAAoAAAABAAAADMD85LpYqkKeWfmsz19kEEKAAAADmxXqsmFE4qCIFVf7fbf6Lkktqe+GmWXWIQTJb2EHCeDDclpUygwFUUAAAAxudMuaV2vqrqS22DRgyN4Bw1/aI="},"performance_intervention":{"last_daily_sample":"13424515424338664"},"policy":{"last_statistics_update":"13424515424054832"},"profile":{"info_cache":{"Default":{"active_time":1780050927.615976,"avatar_icon":"chrome://theme/IDR_PROFILE_AVATAR_26","background_apps":false,"default_avatar_fill_color":-2890755,"default_avatar_stroke_color":-16166200,"enterprise_label":"","force_signin_profile_locked":false,"gaia_given_name":"","gaia_id":"","gaia_name":"","hosted_domain":"","is_consented_primary_account":false,"is_ephemeral":false,"is_glic_eligible":false,"is_managed":0,"is_using_default_avatar":true,"is_using_default_name":true,"managed_user_id":"","metrics_bucket_index":1,"name":"Your Chromium","profile_color_seed":-16033840,"profile_highlight_color":-2890755,"signin.with_credential_provider":false,"user_name":""}},"last_active_profiles":[],"metrics":{"next_bucket_index":2},"profile_counts_reported":"13424515424059085","profiles_order":["Default"]},"profile_network_context_service":{"http_cache_finch_experiment_groups":"None None None None"},"session_id_generator_last_value":"1074088497","signin":{"active_accounts_last_emitted":"13424515423988667"},"subresource_filter":{"ruleset_version":{"checksum":0,"content":"","format":0}},"tab_stats":{"discards_external":0,"discards_frozen":0,"discards_proactive":0,"discards_suggested":0,"discards_urgent":0,"last_daily_sample":"13424515424040457","max_tabs_per_window":2,"reloads_external":0,"reloads_frozen":0,"reloads_proactive":0,"reloads_suggested":0,"reloads_urgent":0,"total_tab_count_max":2,"window_count_max":1},"toast":{"non_milestone_update_toast_version":"145.0.7632.6"},"ukm":{"persisted_logs":[]},"uninstall_metrics":{"installation_date2":"1779102849"},"user_experience_metrics":{"client_id2":"43a4d29b-dfa2-4f8b-9a46-fe2351fed503","client_id_timestamp":"1779102849","limited_entropy_randomization_source":"795E664817D8383D9992183FB246CB96","log_record_id":50,"low_entropy_source3":4488,"machine_id":6709466,"pseudo_low_entropy_source":1702,"session_id":49,"stability":{"browser_last_live_timestamp":"13424527980612017","exited_cleanly":true,"saved_system_profile":"CLzkm8sGEhUxNDUuMC43NjMyLjYtNjQtZGV2ZWwYsOKr0AYiBWVuLVVTKhgKCldpbmRvd3MgTlQSCjEwLjAuMTkwNDQyfgoGeDg2XzY0EMb9ARiAgJiqpv8fIhlIUCBaMjMwIFRvd2VyIFdvcmtzdGF0aW9uKAMwgBQ4oAtCCggAEAAaADIAOgBNiU3PQlXibM9CZQAAwD9qGAoMR2VudWluZUludGVsEMONDBgIIAEoAIIBAIoBAKoBBng4Nl82NLABAUoKDW0jOl4V0IbiWUoKDZK3V7MV3xdKP0oKDQUO8PQVgI19ylAAaggIABAAOABAAIABsOKr0AaYAQD4AYgjgAL///////////8BiAIAkgIkNDNhNGQyOWItZGZhMi00ZjhiLTlhNDYtZmUyMzUxZmVkNTAzqAKmDbICqAFkHjnSnstQPTfirX7FiAAqfsiwbNubM6kLj70v2MAtsf5bz4dGdDQ67motfyp+LMUZDNsJTLRUE0n9H/9UH43yOKroA8plfhtjdx59eUuqaR4MRo2A+Qiq4/tOLsZ/zmTnbDVi+KKIL2/ZQWHsg20kVoEJFshARP61EIfS1sYKphv1BfE5C92iJ0SDSS28C5tj623dU5++z1l26HNC4OPrhIu4/0zzDV3xAlCbVVVSD3qO","saved_system_profile_hash":"9DC8C008783143F7F046BE60F9A2BA31B59BCA3C","stats_buildtime":"1768354364","stats_version":"145.0.7632.6-64-devel","system_crash_count":0}},"variations_google_groups":{"Default":[]},"was":{"restarted":false}}
Binary file not shown.
Binary file not shown.
-525
View File
@@ -1,525 +0,0 @@
import glob
import os
import shutil
import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment
from openpyxl.utils import get_column_letter
from datetime import date, datetime
# Paths
src_dir = os.path.dirname(os.path.abspath(__file__)) + "/"
out_dir = "U:/Dropbox/!!!Days/Downloads Z230/"
# Find source files
src_files = glob.glob(src_dir + "Protocol 77242113UCO3001 - All Samples*.xlsx")
assert src_files, "Source file not found!"
src_file = src_files[0]
print(f"Source xlsx: {src_file}")
csv_files = glob.glob(src_dir + "_EDCStdRpt-DataListing.csv")
assert csv_files, "CSV file not found!"
csv_file = csv_files[0]
print(f"Source csv: {csv_file}")
kit_csv_files = glob.glob(src_dir + "sponsor-study-36940-kit-inventory-on-hand-expiration.csv")
assert kit_csv_files, "Kit inventory CSV not found!"
kit_csv_file = kit_csv_files[0]
print(f"Kit csv: {kit_csv_file}")
eq_csv_files = glob.glob(src_dir + "sponsor-study-36940-activity-reports-documents-equery.csv")
assert eq_csv_files, "eQuery CSV not found!"
eq_csv_file = eq_csv_files[0]
print(f"eQuery csv: {eq_csv_file}")
timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
out_filename = f"{timestamp} 77242113UCO3001 CZE Labcorp samples and kit inventory report.xlsx"
out_path = out_dir + out_filename
# Copy source file to output — preserves all formatting perfectly
shutil.copy2(src_file, out_path)
# Load data with pandas for analysis
df = pd.read_excel(src_file, sheet_name=0, header=0)
# All unique patients
all_patients = sorted(df['Patient No.'].dropna().unique())
# BXSCR and DNA rows
bxscr = df[df['Protocol Visit Code'] == 'BXSCR']
dna = df[df['Protocol Visit Code'] == 'DNA']
# Parse date value to datetime object
def fmt_date(val):
if pd.isna(val):
return None
if isinstance(val, str):
return datetime.strptime(val, '%d-%b-%Y')
return pd.to_datetime(val).to_pydatetime()
OK_STATUSES = {'Received', 'In Inventory', 'Shipped'}
def get_specimen_info(visit_df, patient, specimen_type=None):
rows = visit_df[visit_df['Patient No.'] == patient]
if specimen_type:
rows = rows[rows['Specimen Type'] == specimen_type]
rows = rows[rows['Sample Status'].isin(OK_STATUSES)]
if rows.empty:
return '', None
row = rows.iloc[0]
return fmt_date(row['Container Receipt Date']), rows.index[0] + 2
def get_label_info(patient, label_code, visit_code):
rows = df[(df['Patient No.'] == patient) &
(df['Protocol Visit Code'] == visit_code) &
(df['Container Label Line 1'] == label_code)]
rows = rows[rows['Sample Status'].isin(OK_STATUSES)]
if rows.empty:
return '', None
row = rows.iloc[0]
return fmt_date(row['Container Receipt Date']), rows.index[0] + 2
# Open copied workbook and add analysis sheet
out_wb = load_workbook(out_path)
# Rename and autofit first sheet
src_ws = out_wb.active
src_ws.title = "Zdroj"
for col in src_ws.columns:
max_len = max((len(str(cell.value)) if cell.value is not None else 0) for cell in col)
src_ws.column_dimensions[get_column_letter(col[0].column)].width = min(max_len + 2, 50)
# ── Styly ────────────────────────────────────────────────────────────────────
thin = Side(style='thin')
border = Border(left=thin, right=thin, top=thin, bottom=thin)
header_fill = PatternFill("solid", fgColor="4472C4")
header_font = Font(name='Calibri', bold=True, size=11, color="FFFFFF")
data_font = Font(name='Calibri', size=11)
date_font_link = Font(name='Calibri', size=11, color="000000", underline='single')
yes_fill = PatternFill("solid", fgColor="E2EFDA")
no_fill = PatternFill("solid", fgColor="FFE7E7")
sum_header_font = Font(name='Calibri', bold=True, size=11, color="000000")
sum_total_font = Font(name='Calibri', bold=True, size=11)
zero_font = Font(name='Calibri', size=11, color="BFBFBF")
zero_red_font = Font(name='Calibri', size=11, color="C00000")
dark_blue_fill = PatternFill("solid", fgColor="203764")
orange_fill = PatternFill("solid", fgColor="FFF2CC")
green_fill = PatternFill("solid", fgColor="E2EFDA")
total_fill = PatternFill("solid", fgColor="D9E1F2")
exp_fill = PatternFill("solid", fgColor="FFE7E7")
ok_fill = PatternFill("solid", fgColor="E2EFDA")
# ── List: Přehled vzorků ──────────────────────────────────────────────────────
analysis_ws = out_wb.create_sheet("Přehled vzorků")
columns = [
("Investigator Name", 24),
("Číslo pacienta", 20),
("Máme biopsii SM11", 20),
("Máme RNA", 16),
("Máme Cryostor", 16),
("DNA", 14),
("PLASMPK I-0 TROUGH", 18),
("PLASMA PK I-0 PEAK", 18),
("SERUM ADA I-0 PRE", 18),
("SM06/SERUM BIOM", 16),
("SM07/WB RNA", 14),
("SM10/FECAL", 14),
("PLASMPK I-2 TROUGH", 18),
("PLASMA PK I-2 PEAK", 18),
("SERUM ADA I-2 PRE", 18),
("STOOL I-2", 12),
("PLASMPK I-4 TROUGH", 18),
("PLASMA PK I-4 PEAK", 18),
("SERUM ADA I-4 PRE", 18),
("SM06/SERUM BIOM", 16),
("SM07/WB RNA", 14),
("STOOL I-4", 12),
]
group_font = Font(name='Calibri', bold=True, size=11)
group_fill = PatternFill("solid", fgColor="FFFFFF")
group_border = Border(left=thin, right=thin, top=thin, bottom=thin)
groups = [
(3, 5, "SCREENING"),
(7, 12, "RANDOMIZACE I-0"),
(13, 16, "I-2"),
(17, 22, "I-4"),
]
for start_col, end_col, label in groups:
analysis_ws.merge_cells(start_row=1, start_column=start_col, end_row=1, end_column=end_col)
cell = analysis_ws.cell(row=1, column=start_col, value=label)
cell.font = group_font
cell.fill = group_fill
cell.alignment = Alignment(horizontal='center', vertical='center')
cell.border = group_border
for c in range(start_col, end_col + 1):
analysis_ws.cell(row=1, column=c).border = group_border
analysis_ws.row_dimensions[1].height = 20
for col_idx, (hdr, width) in enumerate(columns, 1):
cell = analysis_ws.cell(row=2, column=col_idx, value=hdr)
cell.font = header_font
cell.fill = header_fill
cell.border = border
cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
analysis_ws.column_dimensions[get_column_letter(col_idx)].width = width
analysis_ws.row_dimensions[2].height = 30
analysis_ws.freeze_panes = "C3"
src_sheet_name = out_wb.sheetnames[0]
pat_sheet_name = "Seznam pacientů"
_csv_df_pre = pd.read_csv(csv_file, encoding='utf-8')
_pat_pre = _csv_df_pre[['SiteNumber', 'Subject', 'Field4Value']].copy()
_pat_pre['Field4Value'] = _pat_pre['Field4Value'].apply(lambda v: datetime.strptime(str(v).strip(), '%d %b %Y') if pd.notna(v) else None)
_pat_pre = _pat_pre.sort_values(['SiteNumber', 'Subject', 'Field4Value']).reset_index(drop=True)
patient_row_map = {}
for i, row in _pat_pre.iterrows():
pat = row['Subject']
if pat not in patient_row_map:
patient_row_map[pat] = i + 2
bxscr_patients = sorted(bxscr['Patient No.'].dropna().unique())
for row_idx, patient in enumerate(bxscr_patients, 3):
investigator = bxscr[bxscr['Patient No.'] == patient].iloc[0]['Investigator Name']
sm11, sm11_row = get_specimen_info(bxscr, patient, 'Tissue , Paraffin Block')
rna, rna_row = get_specimen_info(bxscr, patient, 'Biopsy RNA Later')
cryo, cryo_row = get_specimen_info(bxscr, patient, 'Biopsy, Frozen Tissue')
dna_date, dna_row = get_specimen_info(dna, patient)
trough, trough_row = get_label_info(patient, 'PLASMPK I-0 TROUGH', 'I-0')
peak, peak_row = get_label_info(patient, 'PLASMA PK I-0 PEAK', 'I-0')
ada, ada_row = get_label_info(patient, 'SERUM ADA I-0 PRE', 'I-0')
sm06, sm06_row = get_label_info(patient, 'SM06/SERUM BIOM', 'I-0')
sm07, sm07_row = get_label_info(patient, 'SM07/WB RNA', 'I-0')
sm10, sm10_row = get_label_info(patient, 'SM10/FECAL', 'I-0')
trough2, trough2_row = get_label_info(patient, 'PLASMPK I-2 TROUGH', 'I-2')
peak2, peak2_row = get_label_info(patient, 'PLASMA PK I-2 PEAK', 'I-2')
ada2, ada2_row = get_label_info(patient, 'SERUM ADA I-2 PRE', 'I-2')
stool2, stool2_row = get_label_info(patient, 'STOOL I-2', 'I-2')
trough4, trough4_row = get_label_info(patient, 'PLASMPK I-4 TROUGH', 'I-4')
peak4, peak4_row = get_label_info(patient, 'PLASMA PK I-4 PEAK', 'I-4')
ada4, ada4_row = get_label_info(patient, 'SERUM ADA I-4 PRE', 'I-4')
sm064, sm064_row = get_label_info(patient, 'SM06/SERUM BIOM', 'I-4')
sm074, sm074_row = get_label_info(patient, 'SM07/WB RNA', 'I-4')
stool4, stool4_row = get_label_info(patient, 'STOOL I-4', 'I-4')
row_data = [investigator, patient,
(sm11, sm11_row), (rna, rna_row), (cryo, cryo_row), (dna_date, dna_row),
(trough, trough_row), (peak, peak_row), (ada, ada_row),
(sm06, sm06_row), (sm07, sm07_row), (sm10, sm10_row),
(trough2, trough2_row), (peak2, peak2_row), (ada2, ada2_row), (stool2, stool2_row),
(trough4, trough4_row), (peak4, peak4_row), (ada4, ada4_row),
(sm064, sm064_row), (sm074, sm074_row), (stool4, stool4_row)]
for col_idx, value in enumerate(row_data, 1):
if col_idx <= 2:
cell = analysis_ws.cell(row=row_idx, column=col_idx, value=value)
if col_idx == 2 and patient in patient_row_map:
cell.hyperlink = f"#'{pat_sheet_name}'!B{patient_row_map[patient]}"
cell.font = Font(name='Calibri', size=11, underline='single')
else:
cell.font = data_font
else:
dt, excel_row = value
cell = analysis_ws.cell(row=row_idx, column=col_idx, value=dt)
if dt and excel_row is not None:
cell.hyperlink = f"#'{src_sheet_name}'!A{excel_row}"
cell.font = date_font_link
cell.fill = yes_fill
cell.number_format = 'DD-MMM-YYYY'
else:
cell.font = Font(name='Calibri', size=11, color="C00000")
cell.fill = no_fill
cell.border = border
cell.alignment = Alignment(horizontal='center', vertical='center')
# ── List: Seznam pacientů ─────────────────────────────────────────────────────
csv_df = pd.read_csv(csv_file, encoding='utf-8')
patients_ws = out_wb.create_sheet("Seznam pacientů")
pat_columns = [
("Číslo centra", 20),
("Číslo pacienta", 20),
("Kód návštěvy", 20),
("Datum návštěvy", 16),
("Typ návštěvy", 16),
]
for col_idx, (col_name, width) in enumerate(pat_columns, 1):
cell = patients_ws.cell(row=1, column=col_idx, value=col_name)
cell.font = header_font
cell.fill = header_fill
cell.border = border
cell.alignment = Alignment(horizontal='center', vertical='center', wrap_text=True)
patients_ws.column_dimensions[get_column_letter(col_idx)].width = width
patients_ws.row_dimensions[1].height = 30
patients_ws.freeze_panes = "A2"
def parse_date_edcstd(val):
if pd.isna(val) or str(val).strip() == '':
return None
try:
return datetime.strptime(str(val).strip(), '%d %b %Y')
except:
return None
pat_df = csv_df[['SiteNumber', 'Subject', 'InstanceName', 'Field4Value', 'Field5Value']].copy()
pat_df['Field4Value'] = pat_df['Field4Value'].apply(parse_date_edcstd)
pat_df = pat_df.sort_values(['SiteNumber', 'Subject', 'Field4Value']).reset_index(drop=True)
for row_idx, row in enumerate(pat_df.itertuples(index=False), 2):
for col_idx, value in enumerate(row, 1):
cell = patients_ws.cell(row=row_idx, column=col_idx, value=value)
cell.font = data_font
cell.border = border
cell.alignment = Alignment(horizontal='center', vertical='center')
if col_idx == 4 and value is not None:
cell.number_format = 'DD-MMM-YYYY'
# ── Kit inventory — načtení a příprava dat ────────────────────────────────────
kit_df_raw = pd.read_csv(kit_csv_file, encoding="utf-8")
cze = kit_df_raw[kit_df_raw["Country"] == "CZE"].copy()
def parse_kit_date(val):
if pd.isna(val):
return None
try:
return datetime.strptime(str(val).strip(), "%b %d, %Y")
except:
return None
cze["Shipped Date"] = cze["Shipped Date"].apply(parse_kit_date)
cze["Expiration Date"] = cze["Expiration Date"].apply(parse_kit_date)
cze = cze.sort_values(["Site", "Kit Type", "Expiration Date"]).reset_index(drop=True)
today_dt = datetime.combine(date.today(), datetime.min.time())
def bucket(exp_date):
if exp_date is None:
return None
return "soon" if (exp_date - today_dt).days <= 30 else "ok"
cze["_bucket"] = cze["Expiration Date"].apply(bucket)
kit_order = sorted(cze["Kit Type"].unique(), key=lambda x: (str(x).lstrip("T-").zfill(5), str(x)))
kit_desc = cze.drop_duplicates("Kit Type").set_index("Kit Type")["Description"].to_dict()
kit_sites = sorted(cze["Site"].unique())
# ── Pomocná funkce pro souhrnné tabulky ───────────────────────────────────────
def write_summary_table(ws, current_row, title, rows_data, col_a_header):
for c in range(1, 5):
cell = ws.cell(row=current_row, column=c)
cell.fill = dark_blue_fill
cell.border = border
ws.cell(row=current_row, column=1, value=title).font = Font(name='Calibri', bold=True, size=12, color="FFFFFF")
ws.cell(row=current_row, column=1).alignment = Alignment(horizontal="left", vertical="center")
ws.merge_cells(start_row=current_row, start_column=1, end_row=current_row, end_column=4)
ws.row_dimensions[current_row].height = 22
current_row += 1
for col_idx, (h, f) in enumerate(zip(
[col_a_header, "Description", "Expiruje do 30 dní", "Expiruje později"],
[header_fill, header_fill, orange_fill, green_fill]
), 1):
cell = ws.cell(row=current_row, column=col_idx, value=h)
cell.font = sum_header_font
cell.fill = f
cell.border = border
cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
ws.row_dimensions[current_row].height = 28
current_row += 1
totals = [0, 0]
for col_a, col_b, n_soon, n_ok in rows_data:
totals[0] += n_soon
totals[1] += n_ok
all_zero = (n_soon == 0 and n_ok == 0)
row_vals = [col_a, col_b, n_soon, n_ok]
row_fills = [None, None,
orange_fill if n_soon > 0 else None,
green_fill if n_ok > 0 else None]
for col_idx, (val, rfill) in enumerate(zip(row_vals, row_fills), 1):
cell = ws.cell(row=current_row, column=col_idx, value=val)
if col_idx >= 3 and val == 0:
cell.font = zero_red_font if all_zero else zero_font
else:
cell.font = data_font
cell.border = border
cell.alignment = Alignment(horizontal="center" if col_idx >= 2 else "left", vertical="center")
if rfill:
cell.fill = rfill
current_row += 1
for col_idx, val in enumerate(["CELKEM", "", totals[0], totals[1]], 1):
cell = ws.cell(row=current_row, column=col_idx, value=val)
cell.font = sum_total_font
cell.fill = total_fill
cell.border = border
cell.alignment = Alignment(horizontal="center" if col_idx >= 2 else "left", vertical="center")
current_row += 2
return current_row
# ── List: Kit Inventory CZE ───────────────────────────────────────────────────
kit_ws = out_wb.create_sheet("Kit Inventory CZE")
listing_columns = [
("Project No.", 14),
("Region", 10),
("Country", 10),
("Site", 38),
("Kit Type", 12),
("Description", 22),
("Accession", 18),
("Shipped Date", 16),
("Expiration Date", 16),
("Days to Expiration", 20),
]
for col_idx, (hdr, width) in enumerate(listing_columns, 1):
cell = kit_ws.cell(row=1, column=col_idx, value=hdr)
cell.font = header_font
cell.fill = header_fill
cell.border = border
cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
kit_ws.column_dimensions[get_column_letter(col_idx)].width = width
kit_ws.row_dimensions[1].height = 30
kit_ws.freeze_panes = "A2"
for row_idx, row in enumerate(cze.itertuples(index=False), 2):
days = row[9]
for col_idx, (col_name, _) in enumerate(listing_columns, 1):
value = row[col_idx - 1]
cell = kit_ws.cell(row=row_idx, column=col_idx, value=value)
cell.font = data_font
cell.border = border
cell.alignment = Alignment(horizontal="center", vertical="center")
if col_name in ("Shipped Date", "Expiration Date") and value is not None:
cell.number_format = "DD-MMM-YYYY"
if col_name == "Days to Expiration":
cell.fill = exp_fill if (pd.notna(days) and days <= 60) else ok_fill
kit_ws.auto_filter.ref = f"A1:{get_column_letter(len(listing_columns))}1"
# ── List: Přehled po centrech ─────────────────────────────────────────────────
ctr_ws = out_wb.create_sheet("Přehled po centrech")
ctr_ws.column_dimensions["A"].width = 22
ctr_ws.column_dimensions["B"].width = 24
ctr_ws.column_dimensions["C"].width = 22
ctr_ws.column_dimensions["D"].width = 20
current_row = 1
for site in kit_sites:
site_df = cze[cze["Site"] == site]
rows_data = []
for kit in kit_order:
desc = kit_desc.get(kit, "")
kit_site_df = site_df[site_df["Kit Type"] == kit]
n_soon = (kit_site_df["_bucket"] == "soon").sum()
n_ok = (kit_site_df["_bucket"] == "ok").sum()
rows_data.append((f"{kit}{desc}", desc, n_soon, n_ok))
current_row = write_summary_table(ctr_ws, current_row, site, rows_data, "Kit Type")
# ── List: Přehled po typech kitů ──────────────────────────────────────────────
sum_ws = out_wb.create_sheet("Přehled po typech")
sum_ws.column_dimensions["A"].width = 38
sum_ws.column_dimensions["B"].width = 22
sum_ws.column_dimensions["C"].width = 22
sum_ws.column_dimensions["D"].width = 20
current_row = 1
for kit in kit_order:
desc = kit_desc.get(kit, "")
kit_df = cze[cze["Kit Type"] == kit]
rows_data = []
for site in sorted(kit_df["Site"].unique()):
site_df = kit_df[kit_df["Site"] == site]
n_soon = (site_df["_bucket"] == "soon").sum()
n_ok = (site_df["_bucket"] == "ok").sum()
rows_data.append((site, desc, n_soon, n_ok))
current_row = write_summary_table(sum_ws, current_row, f"Kit Type {kit}{desc}", rows_data, "Centrum")
# ── List: eQueries ───────────────────────────────────────────────────────────
eq_df = pd.read_csv(eq_csv_file, encoding="utf-8")
eq_cze = eq_df[eq_df["Country"] == "CZECH REPUBLIC"].copy()
status_order = {"Open": 0, "Response Received": 1, "Closed": 2}
eq_cze["_status_order"] = eq_cze["Status"].map(status_order).fillna(99)
eq_cze = eq_cze.sort_values(["_status_order", "Site"]).reset_index(drop=True)
def parse_eq_date(val):
if pd.isna(val):
return None
for fmt in ("%b %d, %Y %I:%M %p", "%b %d, %Y %I:%M %p"):
try:
return datetime.strptime(str(val).strip(), fmt)
except:
pass
try:
return datetime.strptime(str(val).strip().split(" 12:00")[0], "%b %d, %Y")
except:
return None
eq_ws = out_wb.create_sheet("eQueries")
eq_columns = [
("Site", 36),
("Subject", 14),
("Visit", 20),
("Visit Collection Date", 20),
("Accession", 16),
("eQueryId", 12),
("Issue Type", 30),
("Status", 18),
("Create Date", 20),
("Response Date Time", 20),
("Time Before Response", 20),
("User Name", 20),
]
status_fills = {
"Open": PatternFill("solid", fgColor="FFE7E7"),
"Response Received": PatternFill("solid", fgColor="FFF2CC"),
"Closed": PatternFill("solid", fgColor="E2EFDA"),
}
for col_idx, (hdr, width) in enumerate(eq_columns, 1):
cell = eq_ws.cell(row=1, column=col_idx, value=hdr)
cell.font = header_font
cell.fill = header_fill
cell.border = border
cell.alignment = Alignment(horizontal="center", vertical="center", wrap_text=True)
eq_ws.column_dimensions[get_column_letter(col_idx)].width = width
eq_ws.row_dimensions[1].height = 30
eq_ws.freeze_panes = "A2"
for row_idx, row in enumerate(eq_cze.itertuples(index=False), 2):
status = row[eq_cze.columns.get_loc("Status")]
rfill = status_fills.get(status)
for col_idx, (col_name, _) in enumerate(eq_columns, 1):
value = row[eq_cze.columns.get_loc(col_name)]
if col_name in ("Visit Collection Date", "Create Date", "Response Date Time"):
value = parse_eq_date(value)
cell = eq_ws.cell(row=row_idx, column=col_idx, value=value)
cell.font = data_font
cell.border = border
cell.alignment = Alignment(horizontal="center" if col_idx > 1 else "left", vertical="center")
if col_name in ("Visit Collection Date", "Create Date", "Response Date Time") and value:
cell.number_format = "DD-MMM-YYYY HH:MM"
if rfill:
cell.fill = rfill
eq_ws.auto_filter.ref = f"A1:{get_column_letter(len(eq_columns))}1"
out_wb.save(out_path)
print(f"Saved: {out_path}")
print(f"Patients with BXSCR: {len(bxscr_patients)}, All unique patients: {len(all_patients)}")
print(f"CZE kit rows: {len(cze)}, Kit types: {len(kit_order)}, Sites: {len(kit_sites)}")
print(f"CZE eQueries: {len(eq_cze)} (Open: {(eq_cze['Status']=='Open').sum()}, Response Received: {(eq_cze['Status']=='Response Received').sum()}, Closed: {(eq_cze['Status']=='Closed').sum()})")
@@ -23,6 +23,9 @@ PROFILE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "browser_
def login(page):
page.goto(LOGIN_URL)
page.wait_for_load_state("networkidle")
if not page.get_by_label("Email").is_visible():
print(f"Session aktivni, prihlasen: {page.url}")
return
page.get_by_label("Email").fill(EMAIL)
page.get_by_role("button", name="Next").click()
page.wait_for_load_state("networkidle")
@@ -45,6 +45,9 @@ REPORTS = [
def login(page):
page.goto(LOGIN_URL)
page.wait_for_load_state("networkidle")
if not page.get_by_label("Email").is_visible():
print(f"Session aktivni, prihlasen: {page.url}")
return
page.get_by_label("Email").fill(EMAIL)
page.get_by_role("button", name="Next").click()
page.wait_for_load_state("networkidle")
+20 -17
View File
@@ -1,11 +1,11 @@
# =============================================================================
# Název: download_samples_report_v1.1.py
# Verze: 1.1
# Datum: 2026-05-28
# Datum: 2026-05-29
# Popis: Automatické stažení CSV reportu All Samples ze xsp.labcorp.com pro
# studie 77242113UCO3001 (study 36940) a 42847922MDD3003 (study 35472).
# Aplikuje country filtr CZ, date range od FROM_DATE, čeká na stabil
# Record Count. Výstup do příslušné složky Source/ každé studie.
# Aplikuje country filtr CZ, date range od FROM_DATE, čeká na zmize
# "Fetching Data" před exportem. Výstup do Source/ každé studie.
# =============================================================================
from playwright.sync_api import sync_playwright
from datetime import datetime
@@ -31,6 +31,9 @@ TILE_SUFFIX = "allSamples"
def login(page):
page.goto(LOGIN_URL)
page.wait_for_load_state("networkidle", timeout=120000)
if not page.get_by_label("Email").is_visible():
print(f"Session aktivni, prihlasen: {page.url}")
return
page.get_by_label("Email").fill(EMAIL)
page.get_by_role("button", name="Next").click()
page.wait_for_load_state("networkidle", timeout=120000)
@@ -83,19 +86,14 @@ def export_tile(page, tile_label, file_suffix, timestamp, study_id, out_dir):
page.wait_for_load_state("networkidle", timeout=120000)
page.wait_for_timeout(3000)
# Čekej dokud:
# 1. se neobjeví "No Data Available" (= record count je 0), nebo
# 2. record count není nenulový
page.wait_for_function("""() => {
const noData = document.querySelector('div.table-row.no-data');
if (noData) return true;
const countEl = document.querySelector('div.grid-count span');
if (countEl) {
const n = parseInt(countEl.innerText.trim().replace(/,/g, ''), 10);
return !isNaN(n) && n > 0;
}
return false;
}""", timeout=30000)
# Čekej až zmizí "Fetching Data": po filtru 5s, pak opakuj kontrolu každých 5s
page.wait_for_timeout(5000)
for _ in range(24): # max 2 minuty
if not page.get_by_text("Fetching Data").is_visible():
break
print(" Fetching Data... cekam 5s")
page.wait_for_timeout(5000)
page.wait_for_timeout(5000) # extra buffer po zmizení
if page.locator("div.table-row.no-data").is_visible():
print(f" Record Count: 0 — preskakuji.")
@@ -128,7 +126,12 @@ if __name__ == "__main__":
context = p.chromium.launch_persistent_context(
user_data_dir=PROFILE_DIR,
headless=False,
args=["--disable-blink-features=AutomationControlled", "--start-maximized"],
args=[
"--disable-blink-features=AutomationControlled",
"--start-maximized",
"--disable-restore-session-state",
"--disable-session-crashed-bubble",
],
user_agent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
accept_downloads=True,
no_viewport=True,
@@ -1,83 +0,0 @@
# Název: download_test_results_v1.0.py
# Verze: 1.0
# Datum: 2026-05-28
# Popis: Stahuje Standard Test Results ze Covance/Labcorp XSP
# pro studii 77242113UCO3001 (study 36940, report 930556).
# Login přes xsp.covance.com → Okta, pak přímá URL na report.
# Výstup: timestampované CSV do adresáře Source/.
from playwright.sync_api import sync_playwright
from datetime import datetime
import os
EMAIL = "vbuzalka@its.jnj.com"
PASSWORD = "%zT3Wqfc9)cWua5"
LOGIN_URL = "https://xsp.covance.com/"
OUT_DIR = r"U:\PythonProject\Janssen\Covance_UCO3001\Source"
PROFILE_DIR = os.path.join(os.path.dirname(os.path.abspath(__file__)), "browser_profile")
REPORTS = [
{
"site": "CZ10003",
"url": "https://xsp.labcorp.com/sponsor/study/36940/test-results/930556/standard-test-results",
"filename": "sponsor-study-36940-test-results-930556-standard-test-results.csv",
},
]
def login(page):
page.goto(LOGIN_URL)
page.wait_for_load_state("networkidle")
page.get_by_label("Email").fill(EMAIL)
page.get_by_role("button", name="Next").click()
page.wait_for_load_state("networkidle")
page.get_by_label("Password").fill(PASSWORD)
page.get_by_role("button", name="Verify").click()
page.wait_for_url(lambda url: "code=" not in url, timeout=60000)
page.wait_for_load_state("networkidle", timeout=60000)
page.wait_for_timeout(2000)
print(f"Prihlaseni OK: {page.url}")
def download_report(page, report):
print(f"\n--- {report['site']} ---")
page.goto(report["url"])
page.wait_for_load_state("networkidle", timeout=60000)
page.wait_for_timeout(3000)
print(f"Report nacteny: {page.url}")
# Kliknout 3 tečky (more_horiz) vpravo od filtrovacího řádku
page.locator("button").filter(has_text="more_horiz").last.click()
timestamp = datetime.now().strftime("%Y-%m-%d_%H%M%S")
dest = os.path.join(OUT_DIR, f"{timestamp} {report['filename']}")
with page.expect_download(timeout=60000) as dl:
page.get_by_text("Export to CSV").click()
dl.value.save_as(dest)
print(f"Stazeno: {dest}")
if __name__ == "__main__":
with sync_playwright() as p:
context = p.chromium.launch_persistent_context(
user_data_dir=PROFILE_DIR,
headless=False,
args=["--disable-blink-features=AutomationControlled", "--start-maximized"],
no_viewport=True,
user_agent=(
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
"AppleWebKit/537.36 (KHTML, like Gecko) "
"Chrome/136.0.0.0 Safari/537.36"
),
accept_downloads=True,
)
context.add_init_script(
"Object.defineProperty(navigator, 'webdriver', {get: () => undefined})"
)
page = context.new_page()
login(page)
for report in REPORTS:
download_report(page, report)
context.close()