81 lines
3.1 KiB
Python
81 lines
3.1 KiB
Python
#!/usr/bin/env python3
|
||
"""Mirror WowPlatter's AusPost flat-rate + zone tables → RecordGod Postgres.
|
||
|
||
python3 shipping_sync.py | ssh -C root@100.94.195.115 \
|
||
'docker exec -i recordgod-db psql -U recordgod -d recordgod -q -v ON_ERROR_STOP=1'
|
||
|
||
post_flat_rate = service × size/weight bracket → price (Parcel Post / Express). post_zone = postcode range.
|
||
Prices use AusPost's 2026-07-01 "own packaging, postage only" rates (the bracket the shop ships records in) —
|
||
loaded straight in since RecordGod isn't live before the change. Update RATES below from the next Post Charges
|
||
Guide (John's PDF→Gemini path) and re-run.
|
||
"""
|
||
import re
|
||
import pathlib
|
||
import sys
|
||
|
||
import pymysql
|
||
|
||
WP_CONFIG = "/opt/homebrew/var/www/monsterrobot.localsite/wp-config.php"
|
||
SOCK = "/opt/homebrew/var/mysql/mysql.sock"
|
||
|
||
SCHEMA = """
|
||
DROP TABLE IF EXISTS post_flat_rate, post_zone CASCADE;
|
||
CREATE TABLE post_flat_rate (service_key text, packaging_type text, size_label text,
|
||
weight_min_g int, weight_max_g int, price numeric(10,2));
|
||
CREATE TABLE post_zone (postcode_start int, postcode_end int, zone_code text);
|
||
CREATE INDEX ON post_flat_rate (service_key, weight_min_g, weight_max_g);
|
||
CREATE INDEX ON post_zone (postcode_start, postcode_end);
|
||
"""
|
||
|
||
# Current AusPost rates — own packaging, postage only, by weight (effective 2026-07-01 Post Charges Guide).
|
||
RATES = { # service_key -> {size_label: price}
|
||
"PARCEL_POST": {"XS": "10.20", "S": "11.70", "M": "16.00", "L": "20.25", "XL": "24.45"},
|
||
"EXPRESS_POST": {"XS": "13.20", "S": "15.20", "M": "20.00", "L": "24.75", "XL": "32.95"},
|
||
}
|
||
|
||
FR = ["service_key", "packaging_type", "size_label", "weight_min_g", "weight_max_g", "price"]
|
||
ZN = ["postcode_start", "postcode_end", "zone_code"]
|
||
|
||
|
||
def creds():
|
||
t = pathlib.Path(WP_CONFIG).read_text()
|
||
g = lambda k: re.search(rf"'{k}',\s*'([^']*)'", t).group(1)
|
||
return g("DB_NAME"), g("DB_USER"), g("DB_PASSWORD")
|
||
|
||
|
||
def cp(v):
|
||
if v is None or v == "":
|
||
return r"\N"
|
||
return str(v).replace("\\", "\\\\").replace("\t", "\\t").replace("\n", "\\n").replace("\r", "\\r")
|
||
|
||
|
||
def block(out, table, cols, rows):
|
||
out.write(f"COPY {table} ({','.join(cols)}) FROM stdin;\n")
|
||
for r in rows:
|
||
out.write("\t".join(cp(r[c]) for c in cols) + "\n")
|
||
out.write("\\.\n\n")
|
||
print(f" {table:16} {len(rows):>4}", file=sys.stderr)
|
||
|
||
|
||
def main():
|
||
name, user, pw = creds()
|
||
my = pymysql.connect(unix_socket=SOCK, user=user, password=pw, database=name,
|
||
cursorclass=pymysql.cursors.DictCursor)
|
||
c = my.cursor()
|
||
P = "wp_rmp_disc_"
|
||
out = sys.stdout
|
||
out.write(SCHEMA)
|
||
c.execute(f"SELECT {','.join(FR)} FROM {P}post_flat_rates") # structure (brackets) from WowPlatter
|
||
rows = c.fetchall()
|
||
for r in rows: # …prices overridden with the current AusPost ones
|
||
new = RATES.get(r["service_key"], {}).get(r["size_label"])
|
||
if new is not None:
|
||
r["price"] = new
|
||
block(out, "post_flat_rate", FR, rows)
|
||
c.execute(f"SELECT {','.join(ZN)} FROM {P}post_zones")
|
||
block(out, "post_zone", ZN, c.fetchall())
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|