Skill: highlander89/sap-integration (version 1.0.0)

--- name: sap-integration description: SAP system integration, data extraction, and automation for ABAP, HANA, S/4HANA environments. Use when working with SAP systems for: (1) Data extraction and reporting, (2) RFC/BAPI calls, (3) SAP API integration, (4) ABAP code generation, (5) SAP table analysis, (6) Workflow automation, (7) S/4HANA migration tasks, or any SAP-related development and integration work. --- # SAP Integration Skill Enterprise SAP system integration and automation capability built by SAPCONET experts. ## Core Capabilities ### Data Operations - **Extract SAP data** via RFC, BAPI, or OData services - **Generate reports** from SAP tables with proper joins and filters - **Export to Excel/CSV** with formatting and pivot analysis - **Real-time data sync** between SAP and external systems ### Development Support - **ABAP code generation** for common patterns (ALV reports, BAPIs, enhancements) - **SAP table analysis** with field descriptions and relationships - **Custom transaction creation** with proper authorization checks - **Performance optimization** queries and recommendations ### Integration Patterns - **REST API wrappers** for SAP functions - **Middleware connectivity** via PI/PO or CPI - **Cloud integration** with SAP Business Technology Platform - **Legacy system bridging** for modernization projects ## Quick Start Examples ### Data Extraction ```abap " Extract customer master data SELECT kunnr, name1, ort01, land1 FROM kna1 INTO TABLE lt_customers WHERE erdat >= sy-datum - 30. ``` ### BAPI Integration ```python # Python RFC connection import pyrfc conn = pyrfc.Connection(...) result = conn.call('BAPI_CUSTOMER_GETDETAIL2', CUSTOMERNO='0000001000') ``` ## Advanced Workflows ### SAP HANA Integration For complex analytics and real-time processing: - See [references/hana-integration.md](references/hana-integration.md) ### S/4HANA Migration Support For brownfield and greenfield transitions: - See [references/s4hana-migration.md](references/s4hana-migration.md) ### Custom Enhancement Framework For user exits, BADIs, and enhancement spots: - See [references/enhancement-framework.md](references/enhancement-framework.md) ## Authentication & Security All SAP connections require proper authentication: - **Username/password** for basic RFC - **X.509 certificates** for secure connections - **OAuth 2.0** for cloud API access - **SSO integration** via SAML/Kerberos Security best practices enforced: - Minimal authorization principle - Encrypted data transmission - Audit trail logging - No hardcoded credentials ## Scripts Available Execute common SAP operations without manual coding: - `scripts/sap_data_extractor.py` - Generic table data extraction - `scripts/rfc_function_caller.py` - Execute any RFC function module - `scripts/sap_report_generator.py` - Generate formatted Excel reports - `scripts/table_analyzer.py` - Analyze SAP table structure and relationships ## Support Matrix | SAP Product | Supported | Integration Method | |-------------|-----------|-------------------| | SAP ECC 6.0+ | ✅ | RFC, BAPI, IDoc | | S/4HANA Cloud | ✅ | OData, REST API | | S/4HANA On-Premise | ✅ | RFC, OData, BAPI | | SAP BW/4HANA | ✅ | MDX, OData, RFC | | SAP Ariba | ✅ | REST API | | SAP SuccessFactors | ✅ | OData, SOAP | | SAP Concur | ✅ | REST API | Built with enterprise-grade reliability by SAPCONET - South Africa's leading SAP automation specialists.

path: references/enhancement-framework.md
content: # SAP Enhancement Framework Guide

## Overview
SAP Enhancement Framework provides controlled modification of standard SAP software without changing the original source code.

## Enhancement Types

### Business Add-ins (BADIs)
Object-oriented enhancement technique using classes and interfaces.

**Implementation Example:**
```abap
" Interface definition
INTERFACE if_ex_badi_example.
  METHODS: modify_data IMPORTING iv_input TYPE string
                      CHANGING cv_output TYPE string.
ENDINTERFACE.

" Implementation class
CLASS zcl_badi_implementation DEFINITION.
  PUBLIC SECTION.
    INTERFACES: if_ex_badi_example.
ENDCLASS.

CLASS zcl_badi_implementation IMPLEMENTATION.
  METHOD if_ex_badi_example~modify_data.
    " Custom business logic
    cv_output = |Custom prefix: { iv_input }|.
  ENDMETHOD.
ENDCLASS.
```

**BADI Configuration:**
```abap
" Get BADI instance
DATA: lo_badi TYPE REF TO if_ex_badi_example.

GET BADI lo_badi.

" Call BADI method
CALL BADI lo_badi->modify_data
  EXPORTING iv_input = 'test data'
  CHANGING cv_output = lv_result.
```

### User Exits
Function module based enhancements in specific SAP programs.

**Common User Exits:**
- `EXIT_SAPMS38T_001` - Material master maintenance
- `EXIT_SAPLV56K_001` - Delivery document processing  
- `EXIT_SAPMV45A_001` - Sales document processing
- `EXIT_SAPLFMSO_001` - Funds management

**Implementation Pattern:**
```abap
" In include ZXVVAU01 (user exit implementation)
FUNCTION exit_sapmv45a_001.
  " Enhancement for sales order processing
  
  CASE sy-ucomm.
    WHEN 'SAVE'.
      " Custom validation before save
      PERFORM validate_custom_fields.
      
    WHEN 'RELEASE'.
      " Custom release processing
      PERFORM custom_release_check.
  ENDCASE.
  
ENDFUNCTION.

FORM validate_custom_fields.
  " Custom validation logic
  LOOP AT xvbap INTO vbap.
    IF vbap-zzfield IS INITIAL.
      MESSAGE e001(z_custom) WITH 'Custom field required'.
    ENDIF.
  ENDLOOP.
ENDFORM.
```

### Enhancement Points
Predefined locations in SAP code where custom code can be inserted.

**Static Enhancement Points:**
```abap
" Original SAP code
DATA: lv_total TYPE p.
lv_total = wa_item-amount + wa_item-tax.

ENHANCEMENT-POINT ep_calculate_total SPOTS spot_invoice_calc.
" Custom code can be inserted here
ENDENHANCEMENT-POINT.

" Continue with original code
```

**Implementation:**
```abap
" Enhancement implementation
ENHANCEMENT 1 z_invoice_calc.
  " Add custom discount calculation
  IF wa_item-customer_group = 'VIP'.
    lv_total = lv_total * '0.95'. " 5% discount
  ENDIF.
ENDENHANCEMENT.
```

### Enhancement Sections
Larger blocks of code that can be modified or replaced.

```abap
" Original SAP code
ENHANCEMENT-SECTION es_price_calc SPOTS spot_pricing.
  " Original pricing logic
  lv_price = base_price + surcharge.
END-ENHANCEMENT-SECTION.
```

**Enhancement Implementation:**
```abap
ENHANCEMENT 2 z_custom_pricing.
  " Replace standard pricing with custom logic
  PERFORM calculate_custom_price USING base_price 
                                CHANGING lv_price.
ENDENHANCEMENT.
```

## Best Practices

### Design Principles
1. **Minimal Impact**: Make smallest possible changes
2. **Future-Proof**: Consider SAP upgrade compatibility  
3. **Performance**: Avoid performance degradation
4. **Documentation**: Document all enhancements thoroughly

### Code Standards
```abap
" Good: Specific and descriptive naming
ENHANCEMENT z_sd_order_validation.

" Bad: Generic naming
ENHANCEMENT z_enhancement1.

" Good: Proper error handling
TRY.
    PERFORM custom_validation.
  CATCH cx_custom_error INTO DATA(lo_error).
    MESSAGE lo_error->get_text() TYPE 'E'.
ENDTRY.

" Bad: No error handling
PERFORM custom_validation.
```

### Configuration Management
```abap
" Use customizing tables for configuration
TABLES: zconfig_table.

SELECT SINGLE * FROM zconfig_table
  INTO wa_config
  WHERE client = sy-mandt
    AND active = 'X'.

IF sy-subrc = 0.
  " Use configuration values
  lv_threshold = wa_config-threshold_value.
ENDIF.
```

## Advanced Enhancement Techniques

### Implicit Enhancement
Add code at any location without predefined enhancement points.

**Finding Enhancement Locations:**
```abap
" Use SE80 -> Utilities -> Settings -> ABAP Editor -> Frontend
" Enable "Implicit Enhancement Options"

" Right-click in code editor and select:
" "Enhancement Operations" -> "Create Implementation"
```

**Implementation Example:**
```abap
*&---------------------------------------------------------------------*
*&  Include           ZENHANCEMENT_IMPL
*&---------------------------------------------------------------------*

" Implicit enhancement at end of program
CLASS lcl_enhancement DEFINITION.
  PUBLIC SECTION.
    CLASS-METHODS: add_custom_processing
                    IMPORTING iv_document TYPE vbeln.
ENDCLASS.

CLASS lcl_enhancement IMPLEMENTATION.
  METHOD add_custom_processing.
    " Custom processing logic
    CALL FUNCTION 'Z_CUSTOM_DOCUMENT_PROCESSING'
      EXPORTING
        iv_document = iv_document.
  ENDMETHOD.
ENDCLASS.
```

### Kernel BADIs
Low-level system enhancements for core functionality.

```abap
" Example: Custom authorization check
CLASS zcl_auth_badi DEFINITION.
  PUBLIC SECTION.
    INTERFACES: if_ex_auth_badi.
ENDCLASS.

CLASS zcl_auth_badi IMPLEMENTATION.
  METHOD if_ex_auth_badi~check_authorization.
    " Custom authorization logic
    IF user_has_special_permission( sy-uname ).
      ev_authorized = 'X'.
    ELSE.
      ev_authorized = ' '.
    ENDIF.
  ENDMETHOD.
ENDCLASS.
```

### New Generation Enhancement Framework
BRF+ rules and decision tables for business logic.

```abap
" BRF+ integration in enhancement
DATA: lo_brfplus TYPE REF TO if_fdt_function_process,
      lo_context TYPE REF TO if_fdt_context.

" Get BRF+ function
CALL METHOD cl_fdt_function_process=>get_instance
  EXPORTING
    iv_id = 'YOUR_BRF_FUNCTION_ID'
  RECEIVING
    ro_function = lo_brfplus.

" Set input parameters
lo_context = lo_brfplus->get_context().
lo_context->set_value( 
  iv_name = 'CUSTOMER_TYPE'
  ia_value = lv_customer_type ).

" Execute business rules
lo_brfplus->process(
  EXPORTING
    io_context = lo_context ).

" Get result
lo_context->get_value(
  EXPORTING iv_name = 'DISCOUNT_RATE'
  IMPORTING ea_value = lv_discount ).
```

## Testing Enhancements

### Unit Testing
```abap
" Test class for BADI implementation
CLASS ltc_badi_test DEFINITION FOR TESTING.
  PRIVATE SECTION.
    DATA: mo_badi TYPE REF TO if_ex_badi_example.
    
    METHODS: setup,
             test_modify_data FOR TESTING.
ENDCLASS.

CLASS ltc_badi_test IMPLEMENTATION.
  METHOD setup.
    CREATE OBJECT mo_badi TYPE zcl_badi_implementation.
  ENDMETHOD.
  
  METHOD test_modify_data.
    DATA: lv_input TYPE string VALUE 'test',
          lv_output TYPE string.
          
    mo_badi->modify_data( 
      EXPORTING iv_input = lv_input
      CHANGING cv_output = lv_output ).
      
    cl_abap_unit_assert=>assert_equals(
      act = lv_output
      exp = 'Custom prefix: test' ).
  ENDMETHOD.
ENDCLASS.
```

### Integration Testing
```abap
" Test enhancement in transaction context
REPORT z_test_enhancement.

PARAMETERS: p_vbeln TYPE vbeln.

START-OF-SELECTION.
  " Simulate transaction environment
  CALL TRANSACTION 'VA02'
    USING bdcdata
    MODE 'N'.
    
  " Verify enhancement was called
  SELECT SINGLE * FROM z_enhancement_log
    WHERE transaction = 'VA02'
      AND document = p_vbeln.
      
  IF sy-subrc = 0.
    WRITE: 'Enhancement executed successfully'.
  ELSE.
    WRITE: 'Enhancement not triggered'.
  ENDIF.
```

## Migration Considerations

### S/4HANA Compatibility
```abap
" Check S/4HANA compatibility
IF cl_abap_conv_in_ce=>uccp( ) IS NOT INITIAL.
  " Running in S/4HANA environment
  " Use new S/4HANA specific enhancements
ELSE.
  " Running in ECC environment  
  " Use traditional enhancement techniques
ENDIF.
```

### Cloud Readiness
- Avoid direct table access in cloud environments
- Use released APIs and services
- Implement proper exception handling
- Follow cloud development guidelines

### Upgrade Strategy
```abap
" Version-specific enhancement logic
CASE cl_abap_conv_in_ce=>get_release_level( ).
  WHEN '750' OR '751' OR '752'.
    " Enhancement for older releases
    PERFORM old_enhancement_logic.
    
  WHEN '755' OR '756'.
    " Enhanced logic for newer releases
    PERFORM new_enhancement_logic.
    
  WHEN OTHERS.
    " Future-proof fallback
    PERFORM standard_enhancement_logic.
ENDCASE.
```

## Monitoring and Maintenance

### Enhancement Usage Tracking
```abap
" Log enhancement execution
INSERT z_enhancement_log FROM VALUE #(
  client = sy-mandt
  enhancement_id = 'Z_MY_ENHANCEMENT'
  program = sy-cprog
  user = sy-uname
  timestamp = sy-uzeit
  date = sy-datum ).
```

### Performance Monitoring
```abap
" Performance measurement in enhancement
GET RUN TIME FIELD lv_start.

" Enhancement logic here
PERFORM enhancement_processing.

GET RUN TIME FIELD lv_end.
lv_runtime = lv_end - lv_start.

" Log if performance threshold exceeded
IF lv_runtime > 1000000. " 1 second
  MESSAGE i001(z_perf) WITH 'Enhancement slow:' lv_runtime.
ENDIF.
```

### Documentation Standards
```abap
"***********************************************************************
" Enhancement: Z_CUSTOMER_VALIDATION
" Purpose: Add custom validation for customer master data
" Author: SAPCONET Development Team
" Date: 2024-01-15
" 
" Modification History:
" Date       Author    Description
" ---------- --------- ------------------------------------------------
" 2024-01-15 SAPCONET  Initial implementation
" 2024-02-01 SAPCONET  Added VIP customer handling
"***********************************************************************
```

## Common Enhancement Patterns

### Data Validation
```abap
" Pattern: Field validation in master data
ENHANCEMENT z_customer_validation.
  IF kna1-zzregion IS INITIAL.
    MESSAGE e001(zcustom) WITH 'Region field is mandatory'.
  ENDIF.
  
  " Validate region code
  SELECT SINGLE * FROM zt_regions
    WHERE region_code = kna1-zzregion.
  IF sy-subrc <> 0.
    MESSAGE e002(zcustom) WITH 'Invalid region code'.
  ENDIF.
ENDENHANCEMENT.
```

### Workflow Integration
```abap
" Pattern: Trigger workflow from enhancement
ENHANCEMENT z_approval_workflow.
  DATA: lv_wi_id TYPE sww_wiid.
  
  " Start workflow for approval
  CALL FUNCTION 'SAP_WAPI_CREATE_EVENT'
    EXPORTING
      object_type = 'ZWORKFLOW'
      object_key = document_number
      event = 'APPROVAL_REQUIRED'
    IMPORTING
      workitem_id = lv_wi_id.
ENDENHANCEMENT.
```

### Integration Points
```abap
" Pattern: External system integration
ENHANCEMENT z_external_integration.
  " Call external service
  CALL FUNCTION 'Z_CALL_EXTERNAL_SERVICE'
    EXPORTING
      iv_data = document_data
    IMPORTING
      ev_response = external_response
    EXCEPTIONS
      communication_failure = 1
      system_failure = 2.
      
  IF sy-subrc <> 0.
    " Handle integration error
    MESSAGE e003(zcustom) WITH 'External system error'.
  ENDIF.
ENDENHANCEMENT.
```

path: references/hana-integration.md
content: # SAP HANA Integration Guide

## Overview
SAP HANA in-memory database integration for real-time analytics, complex calculations, and high-performance data processing.

## Connection Methods

### HANA Python Client
```python
import pyhdb
connection = pyhdb.connect(
    host='your-hana-host',
    port=30015,
    user='SYSTEM',
    [REDACTED_SECRET]'
)

cursor = connection.cursor()
cursor.execute("SELECT * FROM DUMMY")
result = cursor.fetchall()
```

### JDBC Connection
```java
String url = "jdbc:sap://hostname:30015/?databaseName=HXE";
Connection conn = DriverManager.getConnection(url, "SYSTEM", "password");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT CURRENT_TIMESTAMP FROM DUMMY");
```

## Core Views and Tables

### System Information
- `SYS.M_DATABASES` - Database information
- `SYS.M_SERVICES` - Service status and ports
- `SYS.M_LANDSCAPE_HOST_CONFIGURATION` - Landscape configuration

### Performance Monitoring
- `SYS.M_EXPENSIVE_STATEMENTS` - Long-running queries
- `SYS.M_SQL_PLAN_CACHE` - Query execution plans
- `SYS.M_HOST_RESOURCE_UTILIZATION` - Resource usage

### Data Dictionary
- `SYS.TABLES` - Table metadata
- `SYS.COLUMNS` - Column information
- `SYS.INDEXES` - Index definitions

## Calculation Views

### Creating Calculation Views
```sql
CREATE VIEW "MySchema"."MyCalculationView" 
AS SELECT 
    CUSTOMER_ID,
    SUM(SALES_AMOUNT) AS TOTAL_SALES,
    COUNT(*) AS ORDER_COUNT
FROM "MySchema"."SALES_DATA"
GROUP BY CUSTOMER_ID
```

### Advanced Analytics Functions
```sql
-- Window functions for ranking
SELECT 
    CUSTOMER_ID,
    SALES_AMOUNT,
    RANK() OVER (ORDER BY SALES_AMOUNT DESC) AS SALES_RANK
FROM "MySchema"."SALES_DATA"

-- Time series analysis
SELECT 
    MONTH,
    SALES_AMOUNT,
    LAG(SALES_AMOUNT, 1) OVER (ORDER BY MONTH) AS PREV_MONTH_SALES
FROM "MySchema"."MONTHLY_SALES"
```

## Integration Patterns

### Real-time Data Replication
- **SLT (SAP Landscape Transformation)** for real-time replication
- **SAP Data Services** for ETL operations
- **Smart Data Integration (SDI)** for cloud connectivity

### OData Services
```javascript
// Consuming HANA OData from JavaScript
$.ajax({
    url: '/sap/opu/odata/sap/ZMY_SERVICE/EntitySet',
    type: 'GET',
    dataType: 'json',
    success: function(data) {
        console.log(data.d.results);
    }
});
```

## Performance Optimization

### Index Management
```sql
-- Create column store index
CREATE INDEX "MyIndex" ON "MySchema"."MyTable" ("COLUMN1", "COLUMN2");

-- Analyze index usage
SELECT * FROM SYS.M_CS_INDEXES WHERE SCHEMA_NAME = 'MySchema';
```

### Memory Management
```sql
-- Monitor memory usage
SELECT * FROM SYS.M_HOST_RESOURCE_UTILIZATION;

-- Force garbage collection
ALTER SYSTEM RECLAIM VERSION SPACE;
```

### Query Optimization
- Use column store for analytical workloads
- Leverage pushdown operations to database layer
- Implement proper data partitioning
- Use calculation views for complex business logic

## Security Best Practices

### User Management
```sql
-- Create technical user
CREATE USER TECH_USER PASSWORD "SecurePassword123";
GRANT SELECT ON SCHEMA "MySchema" TO TECH_USER;

-- Role-based access
CREATE ROLE "ANALYTICS_ROLE";
GRANT "ANALYTICS_ROLE" TO TECH_USER;
```

### SSL Configuration
- Enable SSL for all connections
- Use certificate-based authentication
- Implement network encryption
- Configure audit logging

## Common Use Cases

### Financial Reporting
- Real-time P&L calculations
- Cash flow projections  
- Risk analysis and stress testing
- Regulatory compliance reporting

### Supply Chain Analytics
- Inventory optimization
- Demand forecasting
- Supplier performance analysis
- Logistics cost optimization

### Customer Analytics
- Customer segmentation
- Lifetime value calculations
- Churn prediction
- Cross-sell/upsell opportunities

## Troubleshooting

### Connection Issues
```sql
-- Check service status
SELECT * FROM SYS.M_SERVICES WHERE SERVICE_NAME LIKE '%xsengine%';

-- Verify user permissions
SELECT * FROM SYS.GRANTED_PRIVILEGES WHERE GRANTEE = 'YOUR_USER';
```

### Performance Issues
```sql
-- Identify expensive statements
SELECT SQL_TEXT, EXECUTION_COUNT, TOTAL_EXECUTION_TIME 
FROM SYS.M_EXPENSIVE_STATEMENTS 
ORDER BY TOTAL_EXECUTION_TIME DESC;

-- Check memory consumption
SELECT SCHEMA_NAME, SUM(MEMORY_SIZE_IN_TOTAL) 
FROM SYS.M_CS_TABLES 
GROUP BY SCHEMA_NAME 
ORDER BY 2 DESC;
```

## Integration with SAP Applications

### S/4HANA Integration
- Embedded analytics with live data
- Custom CDS views consumption
- Fiori app development with HANA procedures

### BW/4HANA Integration
- Advanced DSO modeling
- Composite providers for real-time reporting
- Open ODS views for external access

### Cloud Platform Integration
- HANA Cloud connectivity
- SAP Analytics Cloud integration
- Machine learning model deployment

path: references/s4hana-migration.md
content: # S/4HANA Migration Guide

## Migration Approaches

### Brownfield (System Conversion)
Convert existing SAP ECC system to S/4HANA while preserving customizations and data.

**Prerequisites:**
- SAP ECC 6.0 EHP 8 or higher
- Unicode conversion completed
- Database migration to HANA
- Simplification Item Catalog review

**Key Steps:**
1. **Preparation Phase**
   - Run SAP Readiness Check
   - Analyze custom code with Custom Code Migration SAP Fiori app
   - Plan simplification items implementation
   - Backup current system

2. **Technical Migration**
   ```bash
   # Example SUM (Software Update Manager) execution
   ./SWPM/sapinst SAPINST_INPUT_PARAMETERS_URL=/tmp/inifile.params
   ```

3. **Functional Migration**
   - Activate new SAP S/4HANA functionality
   - Migrate custom developments
   - Update user authorizations
   - Test business processes

### Greenfield (New Implementation)
Fresh S/4HANA implementation with clean data migration.

**Advantages:**
- Clean system without legacy baggage
- Leverage S/4HANA best practices from start
- Simplified business processes
- Modern Fiori UX from day one

**Data Migration Strategy:**
```python
# Example data extraction for migration
def extract_master_data(sap_connection):
    """Extract clean master data for S/4HANA"""
    
    # Customer master
    customers = sap_connection.call('BAPI_CUSTOMER_GETLIST')
    
    # Material master  
    materials = sap_connection.call('BAPI_MATERIAL_GETLIST')
    
    # Vendor master
    vendors = sap_connection.call('BAPI_VENDOR_GETLIST')
    
    return {
        'customers': customers,
        'materials': materials, 
        'vendors': vendors
    }
```

### Selective Data Transition
Hybrid approach using SAP's Selective Data Transition tools.

## Pre-Migration Analysis

### Custom Code Analysis
```abap
" Run custom code analyzer
REPORT zcustom_code_analysis.

DATA: lt_programs TYPE STANDARD TABLE OF trdir,
      lv_program TYPE trdir-name.

" Get all custom programs
SELECT * FROM trdir INTO TABLE lt_programs
  WHERE name LIKE 'Z%' OR name LIKE 'Y%'.

LOOP AT lt_programs INTO DATA(ls_program).
  " Analyze each program for S/4HANA compatibility
  CALL FUNCTION 'CHECK_SYNTAX'
    EXPORTING
      program = ls_program-name
    EXCEPTIONS
      OTHERS = 1.
      
  IF sy-subrc <> 0.
    " Flag for manual review
  ENDIF.
ENDLOOP.
```

### Simplification Items Review
Key areas requiring attention:

1. **Material Ledger** - Now mandatory in S/4HANA
2. **Asset Accounting** - New depreciation engine
3. **Financial Accounting** - New general ledger
4. **Controlling** - Margin analysis enhancements
5. **Sales & Distribution** - Billing simplifications

### Database Sizing
```sql
-- Estimate HANA memory requirements
SELECT 
    schemaname,
    SUM(allocated_size)/1024/1024/1024 AS size_gb,
    SUM(used_size)/1024/1024/1024 AS used_gb
FROM sys.m_table_statistics 
GROUP BY schemaname
ORDER BY size_gb DESC;
```

## Technical Prerequisites

### System Requirements
| Component | Minimum | Recommended |
|-----------|---------|-------------|
| HANA Memory | 128 GB | 256 GB+ |
| CPU Cores | 8 | 16+ |
| Storage | 2 TB SSD | 5 TB+ SSD |
| Network | 1 Gbps | 10 Gbps |

### Software Components
- SAP S/4HANA 2023 (latest version)
- SAP HANA 2.0 SPS 07
- SAP GUI 7.70 or SAP Business Client
- Compatible browsers for Fiori

## Migration Planning

### Timeline Template
```
Phase 1: Preparation (8-12 weeks)
- Project setup and team training
- Current system analysis
- Migration strategy finalization
- Infrastructure preparation

Phase 2: Development (12-16 weeks)  
- Custom code adaptation
- Data cleansing and mapping
- Integration development
- Initial testing

Phase 3: Testing (6-8 weeks)
- Unit testing
- Integration testing
- User acceptance testing
- Performance testing

Phase 4: Go-Live (2-4 weeks)
- Final data migration
- System cutover
- Hypercare support
- Post go-live optimization
```

### Risk Mitigation
1. **Data Quality Issues**
   - Implement data cleansing early
   - Create data validation scripts
   - Plan for manual cleanup time

2. **Custom Code Incompatibility**
   - Start code review early in project
   - Prioritize critical developments
   - Consider standard functionality alternatives

3. **Integration Failures**
   - Map all current interfaces
   - Test interface connectivity early
   - Have rollback procedures ready

## Data Migration Strategies

### Master Data Migration
```python
def migrate_customer_master(legacy_data, s4_connection):
    """Migrate customer master to S/4HANA format"""
    
    for customer in legacy_data:
        # Transform data to S/4HANA structure
        s4_customer = {
            'CUSTOMER': customer.get('KUNNR'),
            'NAME': customer.get('NAME1'),
            'COUNTRY': customer.get('LAND1'),
            'REGION': customer.get('REGIO'),
            # New S/4HANA fields
            'BP_CATEGORY': determine_bp_category(customer),
            'BP_GROUPING': assign_bp_grouping(customer)
        }
        
        # Load using BAPI
        result = s4_connection.call(
            'BAPI_CUSTOMER_CREATEFROMDATA1',
            CUSTOMERDATA=s4_customer
        )
        
        if result['RETURN']['TYPE'] == 'E':
            log_error(f"Customer {customer['KUNNR']} failed: {result['RETURN']['MESSAGE']}")
```

### Transactional Data Migration
- **Financial Data**: Use standard migration tools (LTMC)
- **Logistics Data**: Selective migration based on business needs
- **Historical Data**: Consider archiving vs migration

### Custom Object Migration
```abap
" Migrate custom tables
REPORT zmigrate_custom_tables.

DATA: lt_ztable_old TYPE STANDARD TABLE OF ztable_old,
      ls_ztable_new TYPE ztable_new.

" Extract from old table
SELECT * FROM ztable_old INTO TABLE lt_ztable_old.

" Transform and load
LOOP AT lt_ztable_old INTO DATA(ls_old).
  " Map fields to new structure
  ls_ztable_new-client = sy-mandt.
  ls_ztable_new-key_field = ls_old-old_key.
  ls_ztable_new-new_field = transform_data(ls_old-old_field).
  
  " Insert into new table
  INSERT ztable_new FROM ls_ztable_new.
ENDLOOP.

COMMIT WORK.
```

## Post-Migration Activities

### Performance Optimization
```sql
-- HANA performance tuning
ALTER SYSTEM ALTER CONFIGURATION ('indexserver.ini', 'SYSTEM') 
SET ('sql', 'plan_cache_size') = '2048' WITH RECONFIGURE;

-- Update table statistics
UPDATE STATISTICS FOR TABLE "SCHEMA"."TABLE_NAME";

-- Reorganize column store tables
MERGE DELTA OF "SCHEMA"."TABLE_NAME";
```

### User Training
1. **Fiori Interface Training**
   - Navigate new Fiori launchpad
   - Use key business applications
   - Understand responsive design

2. **Process Changes**
   - Document new business processes
   - Highlight S/4HANA simplifications
   - Provide quick reference guides

### System Monitoring
```python
def monitor_s4hana_health():
    """Monitor key S/4HANA system metrics"""
    
    checks = {
        'hana_memory': check_hana_memory_usage(),
        'application_logs': scan_application_logs(),
        'batch_jobs': verify_batch_job_status(),
        'interfaces': test_interface_connectivity(),
        'fiori_performance': measure_fiori_response_times()
    }
    
    for check, result in checks.items():
        if not result['healthy']:
            send_alert(f"S/4HANA Health Issue: {check} - {result['message']}")
            
    return checks
```

## Common Challenges and Solutions

### Unicode Conversion Issues
**Problem**: Character encoding problems in custom developments
**Solution**: 
- Use Unicode-safe string operations
- Test with international characters
- Validate all text fields

### Custom Enhancement Conflicts
**Problem**: Standard S/4HANA conflicts with custom enhancements
**Solution**:
- Review all enhancement points
- Adapt to new SAP enhancement framework
- Consider alternative implementation methods

### Integration Complexity
**Problem**: Multiple interface adaptations required
**Solution**:
- Create interface mapping documentation
- Implement gradual interface migration
- Use SAP integration tools (CPI, PI/PO)

## Best Practices

### Technical Best Practices
1. **Follow SAP Guidelines**: Adhere to official migration recommendations
2. **Test Early and Often**: Implement continuous testing throughout project
3. **Monitor Performance**: Establish baseline and monitor improvements
4. **Document Everything**: Maintain comprehensive project documentation

### Business Best Practices
1. **Change Management**: Invest in user adoption and training
2. **Process Optimization**: Use migration as opportunity to improve processes
3. **Stakeholder Engagement**: Maintain regular communication with business users
4. **Go-Live Support**: Plan for intensive support during initial weeks

### Success Metrics
- System performance improvements (response times)
- User adoption rates (Fiori vs SAP GUI usage)
- Business process efficiency gains
- Total cost of ownership reduction

path: scripts/rfc_function_caller.py
content: #!/usr/bin/env python3
"""
SAP RFC Function Caller - Execute any RFC-enabled function module
Built by SAPCONET for enterprise SAP automation
"""

import pyrfc
import json
import sys
from typing import Dict, Any, Optional
from datetime import datetime
import pprint

class SAPRFCCaller:
    """Generic SAP RFC function module caller with result formatting"""
    
    def __init__(self, connection_params: Dict[str, str]):
        """Initialize SAP connection"""
        try:
            self.conn = pyrfc.Connection(**connection_params)
            print(f"✅ Connected to SAP system: {connection_params.get('ashost', 'Unknown')}")
        except Exception as e:
            print(f"❌ SAP connection failed: {str(e)}")
            sys.exit(1)
    
    def get_function_interface(self, function_name: str) -> Dict[str, Any]:
        """Get function module interface definition"""
        try:
            # Get function metadata
            interface = self.conn.get_function_description(function_name)
            
            result = {
                'name': function_name,
                'description': interface.get('description', ''),
                'parameters': {
                    'importing': [],
                    'exporting': [],  
                    'changing': [],
                    'tables': []
                }
            }
            
            # Parse parameters
            for param in interface.get('parameters', []):
                param_info = {
                    'name': param.get('name'),
                    'type': param.get('type_kind'),
                    'direction': param.get('direction'),
                    'optional': param.get('optional', False),
                    'description': param.get('parameter_text', ''),
                    'default': param.get('default_value', '')
                }
                
                direction = param.get('direction', '').lower()
                if direction == 'importing':
                    result['parameters']['importing'].append(param_info)
                elif direction == 'exporting':
                    result['parameters']['exporting'].append(param_info)
                elif direction == 'changing':
                    result['parameters']['changing'].append(param_info)
                elif direction == 'tables':
                    result['parameters']['tables'].append(param_info)
            
            return result
            
        except Exception as e:
            print(f"❌ Error getting function interface: {str(e)}")
            return {}
    
    def call_function(self, function_name: str, parameters: Dict[str, Any] = None,
                     save_result: bool = False, output_file: str = None) -> Dict[str, Any]:
        """
        Execute SAP function module with parameters
        
        Args:
            function_name: Name of RFC function module
            parameters: Dictionary of input parameters
            save_result: Whether to save result to file
            output_file: Custom output filename
            
        Returns:
            Dictionary containing function result
        """
        try:
            print(f"🔄 Calling function: {function_name}")
            
            # Execute function call
            if parameters:
                result = self.conn.call(function_name, **parameters)
            else:
                result = self.conn.call(function_name)
            
            print(f"✅ Function executed successfully")
            
            # Save result if requested
            if save_result or output_file:
                filename = output_file or f"{function_name}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
                self.save_result(result, filename)
            
            return result
            
        except Exception as e:
            print(f"❌ Error calling function {function_name}: {str(e)}")
            return {}
    
    def call_bapi(self, business_object: str, method: str, parameters: Dict[str, Any] = None) -> Dict[str, Any]:
        """
        Execute BAPI (Business Application Programming Interface)
        
        Common BAPIs:
        - BAPI_CUSTOMER_GETDETAIL2
        - BAPI_MATERIAL_GET_DETAIL  
        - BAPI_SALESORDER_GETSTATUS
        - BAPI_VENDOR_GETDETAIL
        """
        bapi_name = f"BAPI_{business_object.upper()}_{method.upper()}"
        return self.call_function(bapi_name, parameters)
    
    def get_system_info(self) -> Dict[str, Any]:
        """Get SAP system information"""
        try:
            # Get basic system info
            result = self.call_function('RFC_SYSTEM_INFO')
            
            # Get additional details
            system_info = {
                'system_info': result,
                'current_user': self.call_function('SUSR_USER_ADDR_READ', 
                                                  {'BNAME': self.conn.get_connection_attributes()['user']}),
                'server_time': self.call_function('GET_SYSTEM_DATETIME')
            }
            
            return system_info
            
        except Exception as e:
            print(f"❌ Error getting system info: {str(e)}")
            return {}
    
    def test_connection(self) -> bool:
        """Test SAP connection with simple RFC call"""
        try:
            result = self.call_function('RFC_PING')
            return True
        except Exception as e:
            print(f"❌ Connection test failed: {str(e)}")
            return False
    
    def list_available_functions(self, pattern: str = "*") -> list:
        """List available RFC function modules matching pattern"""
        try:
            result = self.call_function('RFC_FUNCTION_SEARCH',
                                      {'PATTERN': pattern,
                                       'FUNCNAME': '',
                                       'GROUPNAME': '',
                                       'LANGUAGE': 'EN'})
            
            functions = []
            if 'FUNCTIONS' in result:
                for func in result['FUNCTIONS']:
                    functions.append({
                        'name': func.get('FUNCNAME', ''),
                        'group': func.get('GROUPNAME', ''),
                        'text': func.get('TEXT', '')
                    })
            
            return functions
            
        except Exception as e:
            print(f"❌ Error listing functions: {str(e)}")
            return []
    
    def save_result(self, result: Dict[str, Any], filename: str):
        """Save function result to JSON file"""
        try:
            # Convert datetime objects to strings for JSON serialization
            def serialize_datetime(obj):
                if hasattr(obj, 'isoformat'):
                    return obj.isoformat()
                return str(obj)
            
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(result, f, indent=2, default=serialize_datetime, ensure_ascii=False)
            
            print(f"✅ Result saved to {filename}")
            
        except Exception as e:
            print(f"❌ Error saving result: {str(e)}")
    
    def format_result(self, result: Dict[str, Any], compact: bool = False) -> str:
        """Format function result for display"""
        try:
            if compact:
                return json.dumps(result, indent=2, default=str, ensure_ascii=False)
            else:
                return pprint.pformat(result, width=120)
                
        except Exception as e:
            return f"Error formatting result: {str(e)}"
    
    def close_connection(self):
        """Clean up SAP connection"""
        try:
            self.conn.close()
            print("✅ SAP connection closed")
        except:
            pass

def load_function_templates() -> Dict[str, Dict[str, Any]]:
    """Load predefined function call templates for common operations"""
    return {
        'customer_details': {
            'function': 'BAPI_CUSTOMER_GETDETAIL2',
            'description': 'Get customer master data details',
            'parameters': {
                'CUSTOMERNO': '0000001000'  # Example customer number
            }
        },
        'material_details': {
            'function': 'BAPI_MATERIAL_GET_DETAIL',
            'description': 'Get material master data',
            'parameters': {
                'MATERIAL': '000000000000000001',  # Example material
                'PLANT': '1000'
            }
        },
        'sales_order_status': {
            'function': 'BAPI_SALESORDER_GETSTATUS',
            'description': 'Get sales order status',
            'parameters': {
                'SALESDOCUMENT': '0000000001'  # Example sales order
            }
        },
        'user_info': {
            'function': 'SUSR_USER_ADDR_READ',
            'description': 'Get user address information',
            'parameters': {
                'BNAME': 'USER_NAME'  # Will be replaced with current user
            }
        },
        'company_code_info': {
            'function': 'BAPI_COMPANYCODE_GETDETAIL',
            'description': 'Get company code details',
            'parameters': {
                'COMPANYCODEID': '1000'  # Example company code
            }
        }
    }

def main():
    """Main execution function with command-line interface"""
    if len(sys.argv) < 2:
        print("SAP RFC Function Caller")
        print("\nUsage:")
        print("  python rfc_function_caller.py <config_file> [function_name] [param_file]")
        print("  python rfc_function_caller.py <config_file> --interactive")
        print("  python rfc_function_caller.py <config_file> --template <template_name>")
        print("\nExamples:")
        print("  python rfc_function_caller.py sap_config.json RFC_SYSTEM_INFO")
        print("  python rfc_function_caller.py sap_config.json BAPI_CUSTOMER_GETDETAIL2 params.json")
        print("  python rfc_function_caller.py sap_config.json --interactive")
        print("  python rfc_function_caller.py sap_config.json --template customer_details")
        sys.exit(1)
    
    config_file = sys.argv[1]
    
    # Load configuration
    try:
        with open(config_file, 'r') as f:
            config = json.load(f)
    except Exception as e:
        print(f"❌ Error loading config: {str(e)}")
        sys.exit(1)
    
    # Initialize RFC caller
    caller = SAPRFCCaller(config)
    
    try:
        # Test connection first
        if not caller.test_connection():
            print("❌ Connection test failed")
            sys.exit(1)
        
        # Handle different execution modes
        if len(sys.argv) > 2 and sys.argv[2] == '--interactive':
            # Interactive mode
            print("\n🔧 SAP RFC Function Caller - Interactive Mode")
            print("Available commands:")
            print("  call <function_name> - Call function without parameters")
            print("  interface <function_name> - Show function interface")
            print("  system - Show system information")
            print("  search <pattern> - Search for functions")
            print("  templates - Show available templates")
            print("  template <name> - Execute template")
            print("  quit - Exit")
            
            templates = load_function_templates()
            
            while True:
                command = input("\n> ").strip().split()
                
                if not command:
                    continue
                
                if command[0] == 'quit':
                    break
                elif command[0] == 'call' and len(command) > 1:
                    result = caller.call_function(command[1])
                    if result:
                        print("\n📋 Result:")
                        print(caller.format_result(result, compact=True))
                elif command[0] == 'interface' and len(command) > 1:
                    interface = caller.get_function_interface(command[1])
                    if interface:
                        print(json.dumps(interface, indent=2))
                elif command[0] == 'system':
                    info = caller.get_system_info()
                    print(caller.format_result(info, compact=True))
                elif command[0] == 'search' and len(command) > 1:
                    functions = caller.list_available_functions(command[1])
                    for func in functions[:20]:  # Limit to first 20 results
                        print(f"  {func['name']} - {func['text']}")
                    if len(functions) > 20:
                        print(f"  ... and {len(functions) - 20} more")
                elif command[0] == 'templates':
                    print("\nAvailable templates:")
                    for name, template in templates.items():
                        print(f"  {name}: {template['description']}")
                elif command[0] == 'template' and len(command) > 1:
                    template_name = command[1]
                    if template_name in templates:
                        template = templates[template_name]
                        params = template['parameters'].copy()
                        
                        # Replace placeholders
                        if 'BNAME' in params and params['BNAME'] == 'USER_NAME':
                            params['BNAME'] = config['user']
                        
                        result = caller.call_function(template['function'], params)
                        if result:
                            print(f"\n📋 {template['description']} Result:")
                            print(caller.format_result(result, compact=True))
                    else:
                        print(f"❌ Template '{template_name}' not found")
                else:
                    print("❌ Invalid command")
                    
        elif len(sys.argv) > 2 and sys.argv[2] == '--template':
            # Template mode
            if len(sys.argv) < 4:
                print("❌ Template name required")
                sys.exit(1)
                
            template_name = sys.argv[3]
            templates = load_function_templates()
            
            if template_name not in templates:
                print(f"❌ Template '{template_name}' not found")
                print("Available templates:", list(templates.keys()))
                sys.exit(1)
            
            template = templates[template_name]
            params = template['parameters'].copy()
            
            # Replace placeholders
            if 'BNAME' in params and params['BNAME'] == 'USER_NAME':
                params['BNAME'] = config['user']
            
            result = caller.call_function(template['function'], params, save_result=True)
            if result:
                print(f"\n📋 {template['description']} Result:")
                print(caller.format_result(result))
                
        else:
            # Direct function call mode
            function_name = sys.argv[2]
            parameters = {}
            
            # Load parameters from file if provided
            if len(sys.argv) > 3:
                try:
                    with open(sys.argv[3], 'r') as f:
                        parameters = json.load(f)
                except Exception as e:
                    print(f"❌ Error loading parameters: {str(e)}")
                    sys.exit(1)
            
            # Execute function
            result = caller.call_function(function_name, parameters, save_result=True)
            
            if result:
                print(f"\n📋 Function Result:")
                print(caller.format_result(result))
    
    finally:
        caller.close_connection()

if __name__ == "__main__":
    main()

path: scripts/sap_data_extractor.py
content: #!/usr/bin/env python3
"""
SAP Data Extractor - Generic table data extraction with RFC
Built by SAPCONET for enterprise SAP automation
"""

import pyrfc
import pandas as pd
import json
import sys
from typing import Dict, List, Optional, Any
from datetime import datetime

class SAPDataExtractor:
    """Generic SAP data extraction utility using RFC connections"""
    
    def __init__(self, connection_params: Dict[str, str]):
        """Initialize SAP connection"""
        try:
            self.conn = pyrfc.Connection(**connection_params)
            print(f"✅ Connected to SAP system: {connection_params.get('ashost', 'Unknown')}")
        except Exception as e:
            print(f"❌ SAP connection failed: {str(e)}")
            sys.exit(1)
    
    def extract_table_data(self, table_name: str, fields: Optional[List[str]] = None, 
                          where_clause: str = "", max_rows: int = 10000) -> pd.DataFrame:
        """
        Extract data from any SAP table using RFC_READ_TABLE
        
        Args:
            table_name: SAP table name (e.g., 'KNA1', 'VBAK', 'MARA')
            fields: List of fields to extract (None = all fields)
            where_clause: SQL WHERE clause condition
            max_rows: Maximum number of rows to extract
            
        Returns:
            pandas DataFrame with extracted data
        """
        try:
            # Prepare RFC call parameters
            params = {
                'QUERY_TABLE': table_name,
                'DELIMITER': '|',
                'ROWCOUNT': max_rows
            }
            
            # Add field selection if specified
            if fields:
                field_list = [{'FIELDNAME': field} for field in fields]
                params['FIELDS'] = field_list
            
            # Add WHERE clause if specified
            if where_clause:
                # Split long WHERE clauses into 72-character chunks
                where_parts = []
                for i in range(0, len(where_clause), 72):
                    where_parts.append({'TEXT': where_clause[i:i+72]})
                params['OPTIONS'] = where_parts
            
            print(f"🔄 Extracting data from table {table_name}...")
            
            # Execute RFC call
            result = self.conn.call('RFC_READ_TABLE', **params)
            
            # Parse results
            field_names = [field['FIELDNAME'] for field in result['FIELDS']]
            
            # Convert data rows to structured format
            data_rows = []
            for row in result['DATA']:
                row_data = row['WA'].split('|')
                # Ensure we have the right number of columns
                if len(row_data) == len(field_names):
                    data_rows.append(row_data)
                else:
                    print(f"⚠️ Skipping malformed row: {row['WA']}")
            
            # Create DataFrame
            df = pd.DataFrame(data_rows, columns=field_names)
            
            # Clean whitespace
            df = df.apply(lambda x: x.str.strip() if x.dtype == "object" else x)
            
            print(f"✅ Extracted {len(df)} rows from {table_name}")
            return df
            
        except Exception as e:
            print(f"❌ Error extracting from {table_name}: {str(e)}")
            return pd.DataFrame()
    
    def get_table_structure(self, table_name: str) -> pd.DataFrame:
        """Get table field definitions and metadata"""
        try:
            result = self.conn.call('RFC_READ_TABLE',
                                   QUERY_TABLE='DD03L',
                                   DELIMITER='|',
                                   FIELDS=[
                                       {'FIELDNAME': 'FIELDNAME'},
                                       {'FIELDNAME': 'DATATYPE'},
                                       {'FIELDNAME': 'LENG'},
                                       {'FIELDNAME': 'DECIMALS'},
                                       {'FIELDNAME': 'DOMNAME'},
                                       {'FIELDNAME': 'DDTEXT'}
                                   ],
                                   OPTIONS=[{'TEXT': f"TABNAME = '{table_name}' AND AS4LOCAL = 'A'"}])
            
            field_names = [field['FIELDNAME'] for field in result['FIELDS']]
            data_rows = []
            for row in result['DATA']:
                row_data = row['WA'].split('|')
                if len(row_data) == len(field_names):
                    data_rows.append(row_data)
            
            df = pd.DataFrame(data_rows, columns=field_names)
            print(f"✅ Retrieved structure for table {table_name}")
            return df
            
        except Exception as e:
            print(f"❌ Error getting table structure: {str(e)}")
            return pd.DataFrame()
    
    def extract_custom_query(self, query_definition: Dict[str, Any]) -> pd.DataFrame:
        """
        Execute predefined query configurations
        
        Query definition format:
        {
            "name": "Customer Master Data",
            "table": "KNA1", 
            "fields": ["KUNNR", "NAME1", "ORT01", "LAND1"],
            "where": "ERDAT >= '20240101'",
            "joins": [
                {"table": "KNVV", "on": "KUNNR = KUNNR", "fields": ["VKORG", "VTWEG"]}
            ]
        }
        """
        try:
            print(f"🔄 Executing query: {query_definition.get('name', 'Unnamed')}")
            
            # Start with main table
            main_df = self.extract_table_data(
                table_name=query_definition['table'],
                fields=query_definition.get('fields'),
                where_clause=query_definition.get('where', ''),
                max_rows=query_definition.get('max_rows', 10000)
            )
            
            # Handle joins if specified
            if 'joins' in query_definition and not main_df.empty:
                for join_def in query_definition['joins']:
                    join_df = self.extract_table_data(
                        table_name=join_def['table'],
                        fields=join_def.get('fields'),
                        max_rows=query_definition.get('max_rows', 10000)
                    )
                    
                    if not join_df.empty:
                        # Simple join on specified field
                        join_field = join_def['on'].split('=')[0].strip()
                        main_df = pd.merge(main_df, join_df, on=join_field, how='left')
            
            return main_df
            
        except Exception as e:
            print(f"❌ Error executing custom query: {str(e)}")
            return pd.DataFrame()
    
    def export_to_excel(self, data: pd.DataFrame, filename: str, sheet_name: str = 'SAP_Data'):
        """Export DataFrame to Excel with formatting"""
        try:
            with pd.ExcelWriter(filename, engine='openpyxl') as writer:
                data.to_excel(writer, sheet_name=sheet_name, index=False)
                
                # Add some basic formatting
                worksheet = writer.sheets[sheet_name]
                
                # Auto-adjust column widths
                for idx, col in enumerate(data.columns):
                    max_length = max(len(str(col)), data[col].astype(str).str.len().max())
                    worksheet.column_dimensions[chr(65 + idx)].width = min(max_length + 2, 50)
                
                # Add header formatting
                for cell in worksheet[1]:
                    cell.font = cell.font.copy(bold=True)
                    
            print(f"✅ Data exported to {filename}")
            
        except Exception as e:
            print(f"❌ Error exporting to Excel: {str(e)}")
    
    def close_connection(self):
        """Clean up SAP connection"""
        try:
            self.conn.close()
            print("✅ SAP connection closed")
        except:
            pass

def load_connection_config(config_file: str) -> Dict[str, str]:
    """Load SAP connection parameters from JSON config file"""
    try:
        with open(config_file, 'r') as f:
            config = json.load(f)
        
        # Validate required parameters
        required_params = ['ashost', 'sysnr', 'client', 'user', 'passwd']
        for param in required_params:
            if param not in config:
                raise ValueError(f"Missing required parameter: {param}")
        
        return config
        
    except Exception as e:
        print(f"❌ Error loading config: {str(e)}")
        sys.exit(1)

def main():
    """Main execution function with command-line interface"""
    if len(sys.argv) < 2:
        print("Usage: python sap_data_extractor.py <config_file> [table_name] [output_file]")
        print("\nExample:")
        print("  python sap_data_extractor.py sap_config.json KNA1 customer_data.xlsx")
        sys.exit(1)
    
    config_file = sys.argv[1]
    table_name = sys.argv[2] if len(sys.argv) > 2 else None
    output_file = sys.argv[3] if len(sys.argv) > 3 else None
    
    # Load configuration
    config = load_connection_config(config_file)
    
    # Initialize extractor
    extractor = SAPDataExtractor(config)
    
    try:
        if table_name:
            # Extract specific table
            data = extractor.extract_table_data(table_name)
            
            if not data.empty:
                print(f"\n📊 Sample data from {table_name}:")
                print(data.head())
                print(f"\nTotal rows: {len(data)}")
                
                # Export if filename provided
                if output_file:
                    extractor.export_to_excel(data, output_file, table_name)
            else:
                print(f"❌ No data found in table {table_name}")
        else:
            # Interactive mode
            print("\n🔧 SAP Data Extractor - Interactive Mode")
            print("Available commands:")
            print("  table <name> - Extract data from table")
            print("  structure <name> - Show table structure")
            print("  export <filename> - Export last result to Excel")
            print("  quit - Exit")
            
            last_data = pd.DataFrame()
            
            while True:
                command = input("\n> ").strip().split()
                
                if not command:
                    continue
                    
                if command[0] == 'quit':
                    break
                elif command[0] == 'table' and len(command) > 1:
                    last_data = extractor.extract_table_data(command[1])
                    if not last_data.empty:
                        print(last_data.head(10))
                elif command[0] == 'structure' and len(command) > 1:
                    structure = extractor.get_table_structure(command[1])
                    if not structure.empty:
                        print(structure)
                elif command[0] == 'export' and len(command) > 1:
                    if not last_data.empty:
                        extractor.export_to_excel(last_data, command[1])
                    else:
                        print("❌ No data to export")
                else:
                    print("❌ Invalid command")
    
    finally:
        extractor.close_connection()

if __name__ == "__main__":
    main()

Security scan verdicts — ClawScan: suspicious | static analysis: clean | VirusTotal: suspicious | SkillSpector: suspicious (CRITICAL)