This commit is contained in:
AzureAD\SylvainDUVERNAY
2026-03-28 17:11:52 +01:00
parent 32148a4a86
commit 32b13838f2
3 changed files with 299 additions and 0 deletions

View File

@@ -0,0 +1,60 @@
ContractType,ContractNumber,EstimatedBlDate
P,2086,2026-04-01
S,2081,2026-04-01
S,2102,2026-04-01
S,2179,2026-04-01
P,2133,2026-04-08
S,2134,2026-04-08
P,2061,2026-04-15
P,2128,2026-04-27
S,2170,2026-04-27
P,2095,2026-05-01
P,2111,2026-05-01
P,2135,2026-05-01
S,2112,2026-05-01
S,2120,2026-05-01
S,2136,2026-05-01
S,2168,2026-05-01
P,2087,2026-06-01
P,2137,2026-06-01
S,2068,2026-06-01
S,2103,2026-06-01
S,2138,2026-06-01
P,2065,2026-06-03
S,2066,2026-06-03
P,2063,2026-06-12
S,2064,2026-06-12
P,2067,2026-07-01
P,2113,2026-07-01
P,2139,2026-07-01
S,2079,2026-07-01
S,2114,2026-07-01
S,2140,2026-07-01
P,2090,2026-07-12
P,2088,2026-08-01
P,2141,2026-08-01
S,2082,2026-08-01
S,2142,2026-08-01
P,2073,2026-08-05
P,2094,2026-09-01
P,2115,2026-09-01
P,2129,2026-09-01
P,2143,2026-09-01
S,2116,2026-09-01
S,2121,2026-09-01
S,2144,2026-09-01
P,2069,2026-09-05
S,2070,2026-09-05
P,2145,2026-10-01
S,2080,2026-10-01
S,2146,2026-10-01
P,2062,2026-10-05
P,2096,2026-11-01
P,2117,2026-11-01
P,2147,2026-11-01
S,2083,2026-11-01
S,2118,2026-11-01
S,2148,2026-11-01
P,2149,2026-12-01
S,2104,2026-12-01
S,2150,2026-12-01
1 ContractType ContractNumber EstimatedBlDate
2 P 2086 2026-04-01
3 S 2081 2026-04-01
4 S 2102 2026-04-01
5 S 2179 2026-04-01
6 P 2133 2026-04-08
7 S 2134 2026-04-08
8 P 2061 2026-04-15
9 P 2128 2026-04-27
10 S 2170 2026-04-27
11 P 2095 2026-05-01
12 P 2111 2026-05-01
13 P 2135 2026-05-01
14 S 2112 2026-05-01
15 S 2120 2026-05-01
16 S 2136 2026-05-01
17 S 2168 2026-05-01
18 P 2087 2026-06-01
19 P 2137 2026-06-01
20 S 2068 2026-06-01
21 S 2103 2026-06-01
22 S 2138 2026-06-01
23 P 2065 2026-06-03
24 S 2066 2026-06-03
25 P 2063 2026-06-12
26 S 2064 2026-06-12
27 P 2067 2026-07-01
28 P 2113 2026-07-01
29 P 2139 2026-07-01
30 S 2079 2026-07-01
31 S 2114 2026-07-01
32 S 2140 2026-07-01
33 P 2090 2026-07-12
34 P 2088 2026-08-01
35 P 2141 2026-08-01
36 S 2082 2026-08-01
37 S 2142 2026-08-01
38 P 2073 2026-08-05
39 P 2094 2026-09-01
40 P 2115 2026-09-01
41 P 2129 2026-09-01
42 P 2143 2026-09-01
43 S 2116 2026-09-01
44 S 2121 2026-09-01
45 S 2144 2026-09-01
46 P 2069 2026-09-05
47 S 2070 2026-09-05
48 P 2145 2026-10-01
49 S 2080 2026-10-01
50 S 2146 2026-10-01
51 P 2062 2026-10-05
52 P 2096 2026-11-01
53 P 2117 2026-11-01
54 P 2147 2026-11-01
55 S 2083 2026-11-01
56 S 2118 2026-11-01
57 S 2148 2026-11-01
58 P 2149 2026-12-01
59 S 2104 2026-12-01
60 S 2150 2026-12-01

View File

@@ -0,0 +1,60 @@
ContractType,ContractNumber,EstimatedBlDate
P,2086,4/1/2026
S,2081,4/1/2026
S,2102,4/1/2026
S,2179,4/1/2026
P,2133,4/8/2026
S,2134,4/8/2026
P,2061,4/15/2026
P,2128,4/27/2026
S,2170,4/27/2026
P,2095,5/1/2026
P,2111,5/1/2026
P,2135,5/1/2026
S,2112,5/1/2026
S,2120,5/1/2026
S,2136,5/1/2026
S,2168,5/1/2026
P,2087,6/1/2026
P,2137,6/1/2026
S,2068,6/1/2026
S,2103,6/1/2026
S,2138,6/1/2026
P,2065,6/3/2026
S,2066,6/3/2026
P,2063,6/12/2026
S,2064,6/12/2026
P,2067,7/1/2026
P,2113,7/1/2026
P,2139,7/1/2026
S,2079,7/1/2026
S,2114,7/1/2026
S,2140,7/1/2026
P,2090,7/12/2026
P,2088,8/1/2026
P,2141,8/1/2026
S,2082,8/1/2026
S,2142,8/1/2026
P,2073,8/5/2026
P,2094,9/1/2026
P,2115,9/1/2026
P,2129,9/1/2026
P,2143,9/1/2026
S,2116,9/1/2026
S,2121,9/1/2026
S,2144,9/1/2026
P,2069,9/5/2026
S,2070,9/5/2026
P,2145,10/1/2026
S,2080,10/1/2026
S,2146,10/1/2026
P,2062,10/5/2026
P,2096,11/1/2026
P,2117,11/1/2026
P,2147,11/1/2026
S,2083,11/1/2026
S,2118,11/1/2026
S,2148,11/1/2026
P,2149,12/1/2026
S,2104,12/1/2026
S,2150,12/1/2026
1 ContractType ContractNumber EstimatedBlDate
2 P 2086 4/1/2026
3 S 2081 4/1/2026
4 S 2102 4/1/2026
5 S 2179 4/1/2026
6 P 2133 4/8/2026
7 S 2134 4/8/2026
8 P 2061 4/15/2026
9 P 2128 4/27/2026
10 S 2170 4/27/2026
11 P 2095 5/1/2026
12 P 2111 5/1/2026
13 P 2135 5/1/2026
14 S 2112 5/1/2026
15 S 2120 5/1/2026
16 S 2136 5/1/2026
17 S 2168 5/1/2026
18 P 2087 6/1/2026
19 P 2137 6/1/2026
20 S 2068 6/1/2026
21 S 2103 6/1/2026
22 S 2138 6/1/2026
23 P 2065 6/3/2026
24 S 2066 6/3/2026
25 P 2063 6/12/2026
26 S 2064 6/12/2026
27 P 2067 7/1/2026
28 P 2113 7/1/2026
29 P 2139 7/1/2026
30 S 2079 7/1/2026
31 S 2114 7/1/2026
32 S 2140 7/1/2026
33 P 2090 7/12/2026
34 P 2088 8/1/2026
35 P 2141 8/1/2026
36 S 2082 8/1/2026
37 S 2142 8/1/2026
38 P 2073 8/5/2026
39 P 2094 9/1/2026
40 P 2115 9/1/2026
41 P 2129 9/1/2026
42 P 2143 9/1/2026
43 S 2116 9/1/2026
44 S 2121 9/1/2026
45 S 2144 9/1/2026
46 P 2069 9/5/2026
47 S 2070 9/5/2026
48 P 2145 10/1/2026
49 S 2080 10/1/2026
50 S 2146 10/1/2026
51 P 2062 10/5/2026
52 P 2096 11/1/2026
53 P 2117 11/1/2026
54 P 2147 11/1/2026
55 S 2083 11/1/2026
56 S 2118 11/1/2026
57 S 2148 11/1/2026
58 P 2149 12/1/2026
59 S 2104 12/1/2026
60 S 2150 12/1/2026

View File

@@ -0,0 +1,179 @@
import sys
import csv
from pathlib import Path
# Add parent directory to Python path so we can import helpers
parent_dir = Path(__file__).parent.parent
sys.path.insert(0, str(parent_dir))
from helpers.config import get_db_connection
CSV_PATH = parent_dir / "loaders" / "Contract_Update.csv"
def check_contract_number_format(cur):
"""Show sample contract numbers from DB to confirm expected format."""
cur.execute("SELECT number FROM purchase_purchase ORDER BY id LIMIT 3")
pur_samples = [r[0] for r in cur.fetchall()]
cur.execute("SELECT number FROM sale_sale ORDER BY id LIMIT 3")
sale_samples = [r[0] for r in cur.fetchall()]
print(f" Sample purchase numbers : {pur_samples}")
print(f" Sample sale numbers : {sale_samples}")
print()
def update_estimated_bl_dates(dry_run=False):
conn = get_db_connection()
cur = conn.cursor()
print("=== Contract BL Date Update ===")
print(f"CSV : {CSV_PATH}")
print(f"Mode : {'DRY RUN (no changes will be saved)' if dry_run else 'LIVE UPDATE'}\n")
print("DB contract number format check:")
check_contract_number_format(cur)
# Read CSV
rows = []
with open(CSV_PATH, newline="", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
contract_type = row["ContractType"].strip().upper()
contract_number = row["ContractNumber"].strip()
bl_date = row["EstimatedBlDate"].strip()
if contract_type and contract_number and bl_date:
rows.append((contract_type, contract_number, bl_date))
print(f"Rows loaded from CSV: {len(rows)}\n")
updated_count = 0
skipped_count = 0
not_found_count = 0
for contract_type, contract_number, bl_date in rows:
if contract_type == "P":
# Resolve purchase_line IDs for this purchase number
# Try both raw number (e.g. "2086") and P- prefix (e.g. "P-2086")
cur.execute(
"""
SELECT pl.id
FROM purchase_line pl
JOIN purchase_purchase pp ON pp.id = pl.purchase
WHERE pp.number IN (%s, %s)
AND pl.type = 'line'
ORDER BY pl.id
""",
(contract_number, f"P-{contract_number}"),
)
line_ids = [r[0] for r in cur.fetchall()]
if not line_ids:
print(f" [NOT FOUND] Purchase {contract_number} — no matching purchase_line rows")
not_found_count += 1
continue
# Update pricing_estimated rows linked to those lines with trigger = bldate
cur.execute(
"""
UPDATE pricing_estimated
SET estimated_date = %s,
write_date = NOW(),
write_uid = 1
WHERE line = ANY(%s)
AND trigger = 'bldate'
RETURNING id, line, estimated_date
""",
(bl_date, line_ids),
)
updated_rows = cur.fetchall()
if updated_rows:
for pe_id, line_id, new_date in updated_rows:
print(
f" [{'DRY' if dry_run else 'OK '}] Purchase {contract_number}"
f" | purchase_line={line_id} | pricing_estimated.id={pe_id}"
f" | estimated_date -> {new_date}"
)
updated_count += len(updated_rows)
else:
print(
f" [SKIP] Purchase {contract_number} — lines {line_ids} found"
f" but no pricing_estimated row with trigger='bldate'"
)
skipped_count += 1
elif contract_type == "S":
# Resolve sale_line IDs for this sale number
# Try both raw number (e.g. "2086") and S- prefix (e.g. "S-2086")
cur.execute(
"""
SELECT sl.id
FROM sale_line sl
JOIN sale_sale ss ON ss.id = sl.sale
WHERE ss.number IN (%s, %s)
AND sl.type = 'line'
ORDER BY sl.id
""",
(contract_number, f"S-{contract_number}"),
)
line_ids = [r[0] for r in cur.fetchall()]
if not line_ids:
print(f" [NOT FOUND] Sale {contract_number} — no matching sale_line rows")
not_found_count += 1
continue
# Update pricing_estimated rows linked to those sale lines with trigger = bldate
cur.execute(
"""
UPDATE pricing_estimated
SET estimated_date = %s,
write_date = NOW(),
write_uid = 1
WHERE sale_line = ANY(%s)
AND trigger = 'bldate'
RETURNING id, sale_line, estimated_date
""",
(bl_date, line_ids),
)
updated_rows = cur.fetchall()
if updated_rows:
for pe_id, sale_line_id, new_date in updated_rows:
print(
f" [{'DRY' if dry_run else 'OK '}] Sale {contract_number}"
f" | sale_line={sale_line_id} | pricing_estimated.id={pe_id}"
f" | estimated_date -> {new_date}"
)
updated_count += len(updated_rows)
else:
print(
f" [SKIP] Sale {contract_number} — lines {line_ids} found"
f" but no pricing_estimated row with trigger='bldate'"
)
skipped_count += 1
else:
print(f" [WARN] Unknown ContractType '{contract_type}' for contract {contract_number} — skipped")
skipped_count += 1
print("\n--- Summary ---")
print(f" Updated : {updated_count} pricing_estimated rows")
print(f" Skipped : {skipped_count} contracts (no bldate row in pricing_estimated)")
print(f" Not found: {not_found_count} contracts (contract number not in DB)")
if dry_run:
conn.rollback()
print("\nDry run — all changes rolled back, nothing saved.")
else:
conn.commit()
print("\nAll changes committed to database.")
cur.close()
conn.close()
if __name__ == "__main__":
dry_run = "--dry-run" in sys.argv
update_estimated_bl_dates(dry_run=dry_run)