Files
c4c-download/CLAUDE.md
2026-03-14 16:22:05 +08:00

4.2 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

Project Overview

SAP C4C (Cloud for Customer) attachment downloader toolkit that retrieves attachments from ServiceRequest tickets and optionally uploads them to Synology DSM NAS.

  • sap-c4c-AttachmentFolder.py: Core downloader (Python >= 3.8) using OData APIs and web scraping
  • C4CAttachmentDownloader.java: Java wrapper that calls the Python script via ProcessBuilder
  • dsm-upload.py: Standalone Synology NAS upload example

Common Commands

# Install dependencies
pip install requests scrapling[all] playwright
python -m playwright install chromium

# Download attachments
python sap-c4c-AttachmentFolder.py \
  --tenant https://xxx.c4c.saphybriscloud.cn \
  --user admin --password xxx --ticket 24588

# Download with custom concurrency (default: 5 threads)
python sap-c4c-AttachmentFolder.py --ticket 24588 --max-workers 10

# List attachments only (no download)
python sap-c4c-AttachmentFolder.py --ticket 24588 --list-only

# JSON mode (for Java/programmatic use)
python sap-c4c-AttachmentFolder.py --ticket 24588 --json

# Download + upload to Synology DSM
python sap-c4c-AttachmentFolder.py --ticket 24588 \
  --dsm-url http://10.0.10.235:5000 --dsm-user PLM \
  --dsm-password 123456 --dsm-path /Newgonow/AU-SPFJ

# All credentials also accept environment variables:
# C4C_TENANT, C4C_USERNAME, C4C_PASSWORD, DSM_URL, DSM_USERNAME, DSM_PASSWORD, DSM_PATH
// Java: compile requires Jackson (jackson-databind, jackson-core, jackson-annotations)
javac -cp jackson-databind.jar:jackson-core.jar:jackson-annotations.jar C4CAttachmentDownloader.java

Architecture

Data Flow

  1. Authenticate to SAP C4C via Basic Auth
  2. Look up ServiceRequest by ticket ID -> get ObjectID and SerialID
  3. Fetch SR-level attachments via /sap/c4c/odata/v1/c4codata/ServiceRequestCollection('{OID}')/ServiceRequestAttachmentFolder
  4. Fetch XIssueItem-level attachments via /sap/c4c/odata/cust/v1/custticketapi/BO_XSRIssueItemAttachmentCollection (two-step: filter by UUID, then navigate to AttachmentFolder)
  5. Download concurrently using ThreadPoolExecutor:
    • CategoryCode "2" (file): OData $value endpoint or DocumentLink URL
    • CategoryCode "3" (link): Scrapling + Playwright opens Salesforce URL, clicks button.downloadbutton[title='Download'], captures download
  6. Optionally upload to Synology DSM via FileStation API, then auto-delete local files

Two OData Endpoints

  • /sap/c4c/odata/v1/c4codata (ODATA_C4C) - Standard C4C OData for ServiceRequest and SR-level attachments
  • /sap/c4c/odata/cust/v1/custticketapi (ODATA_CUST) - Custom ticket API for XIssueItem and its attachments

Java Wrapper

Invokes Python script with --json flag, passes credentials via environment variables (not CLI args for security). Parses JSON into typed classes: Result, Attachment, IssueItem, DownloadedFile, DsmUploadEntry. Default timeout: 30 minutes.

DSM Upload Directory Structure

  • SR attachments: {DSM_PATH}/{ticketID}_{serialID}/{filename}
  • IssueItem attachments: {DSM_PATH}/{ticketID}_{serialID}/{issueID}/{filename}

Concurrency Model

Multi-threaded via ThreadPoolExecutor (default 5, --max-workers). Both file and link downloads are submitted as futures. Thread-safe console output uses a print_lock. The requests.Session is shared across file-download threads (thread-safe). Scrapling/Playwright link downloads each launch their own browser.

Global State

The Python script uses module-level globals (TENANT, USERNAME, PASSWORD, ODATA_C4C, ODATA_CUST, OUTPUT_DIR, DSM_*, MAX_WORKERS) initialized in main(). The run() function is the core entry point returning a structured dict.

Troubleshooting

  • Playwright not installed: python -m playwright install chromium
  • Link download fails: Salesforce page selector button.downloadbutton[title='Download'] may have changed; update download_link_via_scrapling()
  • Timeout: Increase Java wrapper timeout or Scrapling's timeout param (currently 60s page load, 120s download wait)
  • SSL warnings: verify=False is used throughout; urllib3 warnings are suppressed