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

89 lines
4.2 KiB
Markdown

# 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
```bash
# 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
// 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