[2ff88f42] Finalize Verticals Pains/Gains in Notion & Update Docs
Updated all Notion Verticals with sharpened Pains/Gains based on internal strategy (Ops vs Infra focus). Updated SuperOffice Connector README to reflect the 'Static Magic' architecture.
This commit is contained in:
@@ -0,0 +1,117 @@
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
NOTION_DB_ID = "2ec88f4285448014ab38ea664b4c2b81" # ID from the user's link
|
||||
|
||||
if not NOTION_API_KEY:
|
||||
print("Error: NOTION_API_KEY not found in environment.")
|
||||
exit(1)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {NOTION_API_KEY}",
|
||||
"Notion-Version": "2022-06-28",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def get_vertical_data(vertical_name):
|
||||
url = f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query"
|
||||
payload = {
|
||||
"filter": {
|
||||
"property": "Vertical",
|
||||
"title": {
|
||||
"contains": vertical_name
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
|
||||
if response.status_code != 200:
|
||||
print(f"Error fetching data for '{vertical_name}': {response.status_code} - {response.text}")
|
||||
return None
|
||||
|
||||
results = response.json().get("results", [])
|
||||
if not results:
|
||||
print(f"No entry found for vertical '{vertical_name}'")
|
||||
return None
|
||||
|
||||
# Assuming the first result is the correct one
|
||||
page = results[0]
|
||||
props = page["properties"]
|
||||
|
||||
# Extract Pains
|
||||
pains_prop = props.get("Pains", {}).get("rich_text", [])
|
||||
pains = pains_prop[0]["plain_text"] if pains_prop else "N/A"
|
||||
|
||||
# Extract Gains
|
||||
gains_prop = props.get("Gains", {}).get("rich_text", [])
|
||||
gains = gains_prop[0]["plain_text"] if gains_prop else "N/A"
|
||||
|
||||
# Extract Ops Focus (Checkbox) if available
|
||||
# The property name might be "Ops. Focus: Secondary" based on user description
|
||||
# Let's check keys to be sure, but user mentioned "Ops. Focus: Secondary"
|
||||
# Actually, let's just dump the keys if needed, but for now try to guess
|
||||
ops_focus = "Unknown"
|
||||
if "Ops. Focus: Secondary" in props:
|
||||
ops_focus = props["Ops. Focus: Secondary"].get("checkbox", False)
|
||||
elif "Ops Focus" in props: # Fallback guess
|
||||
ops_focus = props["Ops Focus"].get("checkbox", False)
|
||||
|
||||
# Extract Product Categories
|
||||
primary_product = "N/A"
|
||||
secondary_product = "N/A"
|
||||
|
||||
# Assuming these are Select or Multi-select fields, or Relations.
|
||||
# User mentioned "Primary Product Category" and "Secondary Product Category".
|
||||
if "Primary Product Category" in props:
|
||||
pp_data = props["Primary Product Category"].get("select") or props["Primary Product Category"].get("multi_select")
|
||||
if pp_data:
|
||||
if isinstance(pp_data, list):
|
||||
primary_product = ", ".join([item["name"] for item in pp_data])
|
||||
else:
|
||||
primary_product = pp_data["name"]
|
||||
|
||||
if "Secondary Product Category" in props:
|
||||
sp_data = props["Secondary Product Category"].get("select") or props["Secondary Product Category"].get("multi_select")
|
||||
if sp_data:
|
||||
if isinstance(sp_data, list):
|
||||
secondary_product = ", ".join([item["name"] for item in sp_data])
|
||||
else:
|
||||
secondary_product = sp_data["name"]
|
||||
|
||||
return {
|
||||
"name": vertical_name,
|
||||
"pains": pains,
|
||||
"gains": gains,
|
||||
"ops_focus_secondary": ops_focus,
|
||||
"primary_product": primary_product,
|
||||
"secondary_product": secondary_product
|
||||
}
|
||||
|
||||
verticals_to_check = [
|
||||
"Krankenhaus",
|
||||
"Pflege", # Might be "Altenheim" or similar
|
||||
"Hotel",
|
||||
"Industrie", # Might be "Manufacturing"
|
||||
"Logistik",
|
||||
"Einzelhandel",
|
||||
"Facility Management"
|
||||
]
|
||||
|
||||
print("-" * 60)
|
||||
for v in verticals_to_check:
|
||||
data = get_vertical_data(v)
|
||||
if data:
|
||||
print(f"VERTICAL: {data['name']}")
|
||||
print(f" Primary Product: {data['primary_product']}")
|
||||
print(f" Secondary Product: {data['secondary_product']}")
|
||||
print(f" Ops. Focus Secondary: {data['ops_focus_secondary']}")
|
||||
print(f" PAINS: {data['pains']}")
|
||||
print(f" GAINS: {data['gains']}")
|
||||
print("-" * 60)
|
||||
@@ -0,0 +1,90 @@
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
NOTION_DB_ID = "2ec88f4285448014ab38ea664b4c2b81" # Verticals DB
|
||||
PRODUCT_DB_ID = "2ec88f42854480f0b154f7a07342eb58" # Product Categories DB (from user link)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {NOTION_API_KEY}",
|
||||
"Notion-Version": "2022-06-28",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
# 1. Fetch Product Map (ID -> Name)
|
||||
product_map = {}
|
||||
def fetch_products():
|
||||
url = f"https://api.notion.com/v1/databases/{PRODUCT_DB_ID}/query"
|
||||
response = requests.post(url, headers=headers, json={"page_size": 100})
|
||||
if response.status_code == 200:
|
||||
results = response.json().get("results", [])
|
||||
for p in results:
|
||||
p_id = p["id"]
|
||||
# Name property might be "Name" or "Product Category"
|
||||
props = p["properties"]
|
||||
name = "Unknown"
|
||||
if "Name" in props:
|
||||
name = props["Name"]["title"][0]["plain_text"] if props["Name"]["title"] else "N/A"
|
||||
elif "Product Category" in props:
|
||||
name = props["Product Category"]["title"][0]["plain_text"] if props["Product Category"]["title"] else "N/A"
|
||||
|
||||
product_map[p_id] = name
|
||||
# Also map the page ID itself if used in relations
|
||||
|
||||
else:
|
||||
print(f"Error fetching products: {response.status_code}")
|
||||
|
||||
# 2. Check Verticals with Relation Resolution
|
||||
def check_vertical_relations(search_term):
|
||||
url = f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query"
|
||||
payload = {
|
||||
"filter": {
|
||||
"property": "Vertical",
|
||||
"title": {
|
||||
"contains": search_term
|
||||
}
|
||||
}
|
||||
}
|
||||
resp = requests.post(url, headers=headers, json=payload)
|
||||
if resp.status_code == 200:
|
||||
results = resp.json().get("results", [])
|
||||
if not results:
|
||||
print(f"❌ No vertical found for '{search_term}'")
|
||||
return
|
||||
|
||||
for page in results:
|
||||
props = page["properties"]
|
||||
title = props["Vertical"]["title"][0]["plain_text"]
|
||||
|
||||
# Resolve Primary
|
||||
pp_ids = [r["id"] for r in props.get("Primary Product Category", {}).get("relation", [])]
|
||||
pp_names = [product_map.get(pid, pid) for pid in pp_ids]
|
||||
|
||||
# Resolve Secondary
|
||||
sp_ids = [r["id"] for r in props.get("Secondary Product", {}).get("relation", [])]
|
||||
sp_names = [product_map.get(pid, pid) for pid in sp_ids]
|
||||
|
||||
print(f"\n🔹 VERTICAL: {title}")
|
||||
print(f" Primary Product (Rel): {', '.join(pp_names)}")
|
||||
print(f" Secondary Product (Rel): {', '.join(sp_names)}")
|
||||
|
||||
# Pains/Gains short check
|
||||
pains = props.get("Pains", {}).get("rich_text", [])
|
||||
print(f" Pains Length: {len(pains[0]['plain_text']) if pains else 0} chars")
|
||||
|
||||
else:
|
||||
print(f"Error fetching vertical: {resp.status_code}")
|
||||
|
||||
# Run
|
||||
print("Fetching Product Map...")
|
||||
fetch_products()
|
||||
print(f"Loaded {len(product_map)} products.")
|
||||
|
||||
print("\nChecking Verticals...")
|
||||
targets = ["Hospital", "Hotel", "Logistics", "Manufacturing", "Retail", "Reinigungs", "Dienstleister", "Facility"]
|
||||
for t in targets:
|
||||
check_vertical_relations(t)
|
||||
@@ -0,0 +1,87 @@
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
NOTION_DB_ID = "2ec88f4285448014ab38ea664b4c2b81"
|
||||
|
||||
if not NOTION_API_KEY:
|
||||
print("Error: NOTION_API_KEY not found.")
|
||||
exit(1)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {NOTION_API_KEY}",
|
||||
"Notion-Version": "2022-06-28",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def get_vertical_details(vertical_name_contains):
|
||||
url = f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query"
|
||||
payload = {
|
||||
"filter": {
|
||||
"property": "Vertical",
|
||||
"title": {
|
||||
"contains": vertical_name_contains
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
if response.status_code != 200:
|
||||
print(f"Error: {response.status_code}")
|
||||
return
|
||||
|
||||
results = response.json().get("results", [])
|
||||
if not results:
|
||||
print(f"❌ No entry found containing '{vertical_name_contains}'")
|
||||
return
|
||||
|
||||
for page in results:
|
||||
props = page["properties"]
|
||||
|
||||
# safely extract title
|
||||
title_list = props.get("Vertical", {}).get("title", [])
|
||||
title = title_list[0]["plain_text"] if title_list else "Unknown Title"
|
||||
|
||||
# Pains
|
||||
pains_list = props.get("Pains", {}).get("rich_text", [])
|
||||
pains = pains_list[0]["plain_text"] if pains_list else "N/A"
|
||||
|
||||
# Gains
|
||||
gains_list = props.get("Gains", {}).get("rich_text", [])
|
||||
gains = gains_list[0]["plain_text"] if gains_list else "N/A"
|
||||
|
||||
# Ops Focus
|
||||
ops_focus = props.get("Ops Focus: Secondary", {}).get("checkbox", False)
|
||||
|
||||
# Products
|
||||
# Primary is select
|
||||
pp_select = props.get("Primary Product Category", {}).get("select")
|
||||
pp = pp_select["name"] if pp_select else "N/A"
|
||||
|
||||
# Secondary is select
|
||||
sp_select = props.get("Secondary Product", {}).get("select")
|
||||
sp = sp_select["name"] if sp_select else "N/A"
|
||||
|
||||
print(f"\n🔹 VERTICAL: {title}")
|
||||
print(f" Primary: {pp}")
|
||||
print(f" Secondary: {sp}")
|
||||
print(f" Ops Focus Secondary? {'✅ YES' if ops_focus else '❌ NO'}")
|
||||
print(f" PAINS:\n {pains}")
|
||||
print(f" GAINS:\n {gains}")
|
||||
print("-" * 40)
|
||||
|
||||
targets = [
|
||||
"Hospital",
|
||||
"Hotel",
|
||||
"Logistics",
|
||||
"Manufacturing",
|
||||
"Retail",
|
||||
"Facility Management"
|
||||
]
|
||||
|
||||
for t in targets:
|
||||
get_vertical_details(t)
|
||||
@@ -0,0 +1,66 @@
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
# Load environment variables
|
||||
load_dotenv()
|
||||
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
NOTION_DB_ID = "2ec88f4285448014ab38ea664b4c2b81"
|
||||
|
||||
if not NOTION_API_KEY:
|
||||
print("Error: NOTION_API_KEY not found in environment.")
|
||||
exit(1)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {NOTION_API_KEY}",
|
||||
"Notion-Version": "2022-06-28",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
def list_pages_and_keys():
|
||||
url = f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query"
|
||||
payload = {
|
||||
"page_size": 10 # Just list a few to see structure
|
||||
}
|
||||
|
||||
response = requests.post(url, headers=headers, json=payload)
|
||||
|
||||
if response.status_code != 200:
|
||||
print(f"Error fetching data: {response.status_code} - {response.text}")
|
||||
return
|
||||
|
||||
results = response.json().get("results", [])
|
||||
|
||||
if not results:
|
||||
print("No pages found.")
|
||||
return
|
||||
|
||||
print(f"Found {len(results)} pages.")
|
||||
|
||||
# Print keys from the first page
|
||||
first_page = results[0]
|
||||
props = first_page["properties"]
|
||||
print("\n--- Property Keys Found ---")
|
||||
for key in props.keys():
|
||||
print(f"- {key}")
|
||||
|
||||
print("\n--- Page Titles (Verticals) ---")
|
||||
for page in results:
|
||||
title_prop = page["properties"].get("Vertical", {}).get("title", []) # Assuming title prop is named "Vertical" based on user input
|
||||
if not title_prop:
|
||||
# Try finding the title property dynamically if "Vertical" is wrong
|
||||
for k, v in page["properties"].items():
|
||||
if v["id"] == "title":
|
||||
title_prop = v["title"]
|
||||
break
|
||||
|
||||
if title_prop:
|
||||
title = title_prop[0]["plain_text"]
|
||||
print(f"- {title}")
|
||||
else:
|
||||
print("- (No Title)")
|
||||
|
||||
if __name__ == "__main__":
|
||||
list_pages_and_keys()
|
||||
@@ -0,0 +1,89 @@
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
NOTION_DB_ID = "2ec88f4285448014ab38ea664b4c2b81"
|
||||
|
||||
if not NOTION_API_KEY:
|
||||
print("Error: NOTION_API_KEY not found.")
|
||||
exit(1)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {NOTION_API_KEY}",
|
||||
"Notion-Version": "2022-06-28",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
# COMPLETE LIST OF UPDATES
|
||||
updates = {
|
||||
"Infrastructure - Transport": { # Airports, Stations
|
||||
"Pains": "Sicherheitsbereiche erfordern personalintensives Screening von externen Reinigungskräften. Verschmutzte Böden (Winter/Salz) erhöhen das Rutschrisiko für Passagiere und Klagerisiken.",
|
||||
"Gains": "Autonome Reinigung innerhalb der Sicherheitszonen ohne externe Personalwechsel. Permanente Trocknung von Nässe (Schneematsch) in Eingangsbereichen."
|
||||
},
|
||||
"Leisure - Indoor Active": { # Bowling, Cinema, Gym
|
||||
"Pains": "Personal ist rar und teuer, Gäste erwarten aber Service am Platz. Reinigung im laufenden Betrieb stört den Erlebnischarakter.",
|
||||
"Gains": "Service-Roboter als Event-Faktor und Entlastung: Getränke kommen zum Gast, Personal bleibt an der Bar/Theke. Konstante Sauberkeit auch bei hoher Frequenz."
|
||||
},
|
||||
"Leisure - Outdoor Park": { # Zoos, Theme Parks
|
||||
"Pains": "Enorme Flächenleistung (Wege) erfordert viele Arbeitskräfte für die Grobschmutzbeseitigung (Laub, Müll). Sichtbare Reinigungstrupps stören die Immersion der Gäste.",
|
||||
"Gains": "Autonome Großflächenreinigung (Kehren) in den frühen Morgenstunden vor Parköffnung. Erhalt der 'heilen Welt' (Immersion) für Besucher."
|
||||
},
|
||||
"Leisure - Wet & Spa": { # Pools, Thermen
|
||||
"Pains": "Hohes Unfallrisiko durch Nässe auf Fliesen (Rutschgefahr). Hoher Aufwand für permanente Desinfektion und Trocknung im laufenden Betrieb bindet Aufsichtspersonal.",
|
||||
"Gains": "Permanente Trocknung und Desinfektion kritischer Barfußbereiche. Reduktion der Rutschgefahr und Haftungsrisiken. Entlastung der Bademeister (Fokus auf Aufsicht)."
|
||||
},
|
||||
"Retail - Shopping Center": { # Malls
|
||||
"Pains": "Food-Court ist der Schmutz-Hotspot: Verschüttete Getränke und Essensreste wirken unhygienisch und binden Personal dauerhaft. Dreckige Böden senken die Verweildauer.",
|
||||
"Gains": "Sofortige Beseitigung von Malheuren im Food-Court. Steigerung der Aufenthaltsqualität und Verweildauer der Kunden durch sichtbare Sauberkeit."
|
||||
},
|
||||
"Retail - Non-Food": { # DIY, Furniture
|
||||
"Pains": "Riesige Gangflächen verstauben schnell, Personal ist knapp und soll beraten, nicht kehren. Verschmutzte Böden wirken im Premium-Segment (Möbel) wertmindernd.",
|
||||
"Gains": "Staubfreie Umgebung für angenehmes Einkaufsklima. Roboter reinigen autonom große Flächen, während Mitarbeiter für Kundenberatung verfügbar sind."
|
||||
},
|
||||
"Infrastructure - Public": { # Fairs, Schools
|
||||
"Pains": "Extrem kurze Turnaround-Zeiten zwischen Messetagen oder Events. Hohe Nachtzuschläge für die Endreinigung der Hallengänge oder Klassenzimmer.",
|
||||
"Gains": "Automatisierte Nachtreinigung der Gänge/Flure stellt die Optik für den nächsten Morgen sicher. Kalkulierbare Kosten ohne Nachtzuschlag."
|
||||
},
|
||||
"Hospitality - Gastronomy": { # Restaurants
|
||||
"Pains": "Servicepersonal verbringt Zeit auf Laufwegen statt am Gast ('Teller-Taxi'). Personalmangel führt zu langen Wartezeiten und Umsatzverlust.",
|
||||
"Gains": "Servicekräfte werden von Laufwegen befreit und haben Zeit für aktive Beratung und Verkauf (Upselling). Steigerung der Tischumschlagshäufigkeit."
|
||||
}
|
||||
}
|
||||
|
||||
def update_vertical(vertical_name, new_data):
|
||||
url = f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query"
|
||||
payload = {
|
||||
"filter": {
|
||||
"property": "Vertical",
|
||||
"title": {
|
||||
"contains": vertical_name
|
||||
}
|
||||
}
|
||||
}
|
||||
resp = requests.post(url, headers=headers, json=payload)
|
||||
if resp.status_code != 200: return
|
||||
|
||||
results = resp.json().get("results", [])
|
||||
if not results:
|
||||
print(f"Skipping {vertical_name} (Not found)")
|
||||
return
|
||||
|
||||
page_id = results[0]["id"]
|
||||
update_url = f"https://api.notion.com/v1/pages/{page_id}"
|
||||
update_payload = {
|
||||
"properties": {
|
||||
"Pains": {"rich_text": [{"text": {"content": new_data["Pains"]}}]},
|
||||
"Gains": {"rich_text": [{"text": {"content": new_data["Gains"]}}]}
|
||||
}
|
||||
}
|
||||
requests.patch(update_url, headers=headers, json=update_payload)
|
||||
print(f"✅ Updated {vertical_name}")
|
||||
|
||||
print("Starting FULL Notion Update...")
|
||||
for v_name, data in updates.items():
|
||||
update_vertical(v_name, data)
|
||||
print("Done.")
|
||||
@@ -0,0 +1,94 @@
|
||||
import os
|
||||
import requests
|
||||
import json
|
||||
from dotenv import load_dotenv
|
||||
|
||||
load_dotenv()
|
||||
|
||||
NOTION_API_KEY = os.getenv("NOTION_API_KEY")
|
||||
NOTION_DB_ID = "2ec88f4285448014ab38ea664b4c2b81"
|
||||
|
||||
if not NOTION_API_KEY:
|
||||
print("Error: NOTION_API_KEY not found.")
|
||||
exit(1)
|
||||
|
||||
headers = {
|
||||
"Authorization": f"Bearer {NOTION_API_KEY}",
|
||||
"Notion-Version": "2022-06-28",
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
|
||||
# Define the updates with "Sharp" Pains/Gains
|
||||
updates = {
|
||||
"Healthcare - Hospital": {
|
||||
"Pains": "Fachpflegekräfte sind bis zu 30% der Schichtzeit mit logistischen Routinetätigkeiten (Wäsche, Essen, Laborproben) gebunden ('Hände weg vom Bett'). Steigende Hygienerisiken bei gleichzeitigem Personalmangel im Reinigungsteam führen zu lückenhafter Dokumentation und Gefährdung der RKI-Konformität.",
|
||||
"Gains": "Rückgewinnung von ca. 2,5h Fachkraft-Kapazität pro Schicht durch automatisierte Stationslogistik. Validierbare, RKI-konforme Reinigungsqualität rund um die Uhr, unabhängig vom Krankenstand des Reinigungsteams."
|
||||
},
|
||||
"Hospitality - Hotel": {
|
||||
"Pains": "Enorme Fluktuation im Housekeeping gefährdet die pünktliche Zimmer-Freigabe (Check-in 15:00 Uhr). Hohe Nachtzuschläge oder fehlendes Personal verhindern, dass die Lobby und Konferenzbereiche morgens um 06:00 Uhr perfekt glänzen.",
|
||||
"Gains": "Lautlose Nachtreinigung der Lobby und Flure ohne Personalzuschläge. Servicekräfte im Restaurant werden von Laufwegen ('Teller-Taxi') befreit und haben Zeit für aktives Upselling am Gast."
|
||||
},
|
||||
"Logistics - Warehouse": {
|
||||
"Pains": "Verschmutzte Fahrwege durch Palettenabrieb und Staub gefährden die Sensorik von FTS (Fahrerlosen Transportsystemen) und erhöhen das Unfallrisiko für Flurförderzeuge. Manuelle Reinigung stört den 24/7-Betrieb und bindet Fachpersonal.",
|
||||
"Gains": "Permanente Staubreduktion im laufenden Betrieb schützt empfindliche Anlagentechnik (Lichtschranken). Saubere Hallen als Visitenkarte und Sicherheitsfaktor (Rutschgefahr), ohne operative Unterbrechungen."
|
||||
},
|
||||
"Industry - Manufacturing": {
|
||||
"Pains": "Hochbezahlte Facharbeiter unterbrechen die Wertschöpfung für unproduktive Such- und Holzeiten von Material (C-Teile). Intransparente Materialflüsse an der Linie führen zu Mikrostillständen und gefährden die Taktzeit.",
|
||||
"Gains": "Just-in-Time Materialversorgung direkt an die Linie. Fachkräfte bleiben an der Maschine. Stabilisierung der Taktzeiten und OEE durch automatisierten Nachschub."
|
||||
},
|
||||
"Reinigungsdienstleister": { # Facility Management
|
||||
"Pains": "Margendruck durch steigende Tariflöhne bei gleichzeitigem Preisdiktat der Auftraggeber. Hohe Fluktuation (>30%) führt zu ständiger Rekrutierung ('No-Show'-Quote), was Objektleiter bindet und die Qualitätskontrolle vernachlässigt.",
|
||||
"Gains": "Kalkulationssicherheit durch Fixkosten statt variabler Personalkosten. Garantierte Reinigungsleistung in Objekten unabhängig vom Personalstand. Innovationsträger für Ausschreibungen."
|
||||
},
|
||||
"Retail - Food": { # Supermarkets
|
||||
"Pains": "Reinigungskosten steigen linear zur Fläche, während Kundenfrequenz schwankt. Sichtbare Reinigungsmaschinen blockieren tagsüber Kundenwege ('Störfaktor'). Abends/Nachts schwer Personal zu finden.",
|
||||
"Gains": "Unsichtbare Reinigung: Roboter fahren in Randzeiten oder weichen Kunden dynamisch aus. Konstantes Sauberkeits-Level ('Lobby-Effekt') steigert Verweildauer."
|
||||
}
|
||||
}
|
||||
|
||||
def update_vertical(vertical_name, new_data):
|
||||
# 1. Find Page ID
|
||||
url = f"https://api.notion.com/v1/databases/{NOTION_DB_ID}/query"
|
||||
payload = {
|
||||
"filter": {
|
||||
"property": "Vertical",
|
||||
"title": {
|
||||
"contains": vertical_name
|
||||
}
|
||||
}
|
||||
}
|
||||
resp = requests.post(url, headers=headers, json=payload)
|
||||
if resp.status_code != 200:
|
||||
print(f"Error searching {vertical_name}: {resp.status_code}")
|
||||
return
|
||||
|
||||
results = resp.json().get("results", [])
|
||||
if not results:
|
||||
print(f"Skipping {vertical_name} (Not found)")
|
||||
return
|
||||
|
||||
page_id = results[0]["id"]
|
||||
|
||||
# 2. Update Page
|
||||
update_url = f"https://api.notion.com/v1/pages/{page_id}"
|
||||
update_payload = {
|
||||
"properties": {
|
||||
"Pains": {
|
||||
"rich_text": [{"text": {"content": new_data["Pains"]}}]
|
||||
},
|
||||
"Gains": {
|
||||
"rich_text": [{"text": {"content": new_data["Gains"]}}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
upd_resp = requests.patch(update_url, headers=headers, json=update_payload)
|
||||
if upd_resp.status_code == 200:
|
||||
print(f"✅ Updated {vertical_name}")
|
||||
else:
|
||||
print(f"❌ Failed to update {vertical_name}: {upd_resp.text}")
|
||||
|
||||
print("Starting Notion Update...")
|
||||
for v_name, data in updates.items():
|
||||
update_vertical(v_name, data)
|
||||
print("Done.")
|
||||
Reference in New Issue
Block a user