Metadata-Version: 2.4
Name: filekit-ljd
Version: 0.2.1
Summary: Simple file discovery and Excel processing toolkit for document workflows
Author-email: LJD-UwU <himexpe.interns@hisense.com>
Maintainer-email: LJD-UwU <himexpe.interns@hisense.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/LJD-UwU/filekit
Project-URL: Documentation, https://github.com/LJD-UwU/filekit#readme
Project-URL: Repository, https://github.com/LJD-UwU/filekit.git
Project-URL: Issues, https://github.com/LJD-UwU/filekit/issues
Keywords: file-search,file-discovery,excel-processing,document-processing,file-operations
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: openpyxl>=3.1.5
Requires-Dist: pandas>=3.0.2
Requires-Dist: tqdm>=4.67.3
Requires-Dist: PyMuPDF>=1.23.0
Dynamic: license-file

# 📁 filekit

Simple file discovery and Excel processing toolkit.

**Find files by type → Copy/Move → Process Excel → Get DataFrame**

[![Python 3.10+](https://img.shields.io/badge/python-3.10+-blue.svg)](https://www.python.org/downloads/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
[![Version](https://img.shields.io/badge/version-0.1.0-green.svg)](https://github.com/LJD-UwU/filekit)

---

## 🚀 Quick Start

### Installation

```bash
pip install filekit-ljd
```

### Basic Usage

```python
from filekit import find, ops

# Find the latest Manpower Budget file from predefined paths
file = find.manpower_budget()

# Copy to a local backup folder
backup = file.copy(r"C:\Temp\Backup")

# Process the Excel sheet and get a clean DataFrame
df = ops.clean_sheet(file, sheet="Sheet1", output=r"C:\Temp\result.xlsx")

print(df.head())
```

---

## ✨ Features

- **Smart file discovery** — finds the *most recent* file of a given type from predefined folder lists
- **Type-aware sorting** — each file type uses its own versioning/date logic (revision numbers, months, quarters)
- **Fluent file operations** — chainable `.copy()` and `.move()` that return new `FileObject` instances
- **Excel merged-cell expansion** — flattens merged cells into a normalized `Datos_Limpios` sheet before reading
- **Pandas integration** — every Excel processing call returns a `pd.DataFrame` ready for analysis
- **Progress feedback** — large Excel files show a `tqdm` progress bar automatically
- **Graceful not-found handling** — `FileObject` evaluates to `False` when no file is found, so `if file:` checks just work

---

## 📦 Installation

```bash
pip install filekit-ljd
```

### Requirements

| Package  | Minimum version |
|----------|-----------------|
| Python   | 3.10+           |
| openpyxl | 3.1.5+          |
| pandas   | 3.0.2+          |
| tqdm     | 4.67.3+         |

---

## 📖 API Documentation

### `find` — File Discovery

Import the singleton namespace:

```python
from filekit import find
```

All methods search the predefined paths in `paths_config.py` and return a `FileObject`.

| Method | Searches for |
|---|---|
| `find.manpower_budget()` | Latest Manpower Budget file (sorted by revision + month) |
| `find.manpower_documents()` | Latest Manpower Documents file (sorted by year, month, quarter) |
| `find.manpower()` | Latest general Manpower file (sorted by month + day) |
| `find.zj()` | Latest ZJ production file (sorted by date + version) |
| `find.real_time_production()` | Latest Real-Time Production file |

---

### `FileObject` — File Wrapper

`FileObject` wraps the path returned by `find.*()` and exposes file operations.

```python
file = find.manpower_budget()

# Check if a file was found
if file:
    print(f"Found: {file}")          # str(file) → full path string

# Copy to a destination folder (creates folders as needed)
backup = file.copy(r"C:\Backup")    # → FileObject pointing to the copy

# Move to a destination folder
archived = file.move(r"C:\Archive") # → FileObject pointing to the new location
```

| Method / Usage | Description |
|---|---|
| `str(file)` | Returns the full file path as a string |
| `bool(file)` | `True` if a file was found, `False` otherwise |
| `file.copy(destination)` | Copies file to `destination/` and returns a new `FileObject` |
| `file.move(destination)` | Moves file to `destination/` and returns a new `FileObject` |

> `copy()` and `move()` are chainable — both return a `FileObject` so you can keep operating on the result.

---

### `ops` — Excel Processing

Import the singleton namespace:

```python
from filekit import ops
```

#### `ops.clean_sheet(file, sheet, output)`

Expands merged cells in an Excel sheet and returns a `pd.DataFrame`.

```python
df = ops.clean_sheet(
    file,               # FileObject, str, or Path
    sheet="Sheet1",     # Sheet name to process (default: "Sheet1")
    output=None,        # Optional output path
)
```

| Parameter | Type | Description |
|---|---|---|
| `file` | `FileObject \| str \| Path` | Source Excel file |
| `sheet` | `str` | Sheet name to read (default `"Sheet1"`) |
| `output` | `str \| Path \| None` | If given, saves a new file with only the cleaned sheet; if `None`, overwrites the original |

**Returns:** `pd.DataFrame` — first row used as column headers.

> If `sheet` does not exist, the processor automatically falls back to the first sheet whose name contains `"sheet"` (case-insensitive).

---

### Low-level utilities

These are used internally but can be imported for custom workflows:

```python
from filekit.fileSelector import find_in_folder
from filekit.scanNameFiles import identify_file_type, get_file_info
from filekit.core.clean_sheet import CleanSheetProcessor, clean_sheet
```

#### `find_in_folder(folder_path, file_type)`

Searches a single folder for the most recent file of the given type.

```python
path = find_in_folder(r"C:\Reports", "MANPOWER_BUDGET")
# Returns: str path or None
```

#### `identify_file_type(file_path)`

Identifies the type of a file based on its name alone.

```python
identify_file_type("Manpower budget 2026 Rev 3.xlsx")  # → "MANPOWER_BUDGET"
identify_file_type("ZJ26042804-8170.xlsx")             # → "ZJ"
identify_file_type("Real-Time Production May.xlsx")    # → "REAL_TIME_PRODUCTION"
```

#### `CleanSheetProcessor` — step-by-step processing

Low-level class for fine-grained control over the Excel processing pipeline:

```python
from filekit.core.clean_sheet import CleanSheetProcessor

processor = CleanSheetProcessor(ruta="data.xlsx", nombre_hoja_origen="Sheet1")
processor.abrir()
processor.aplanar_merged_cells()
processor.guardar(ruta_salida="output.xlsx")
df = processor.obtener_dataframe()
```

---

## 🏗️ Project Structure

```
filekit/
├── finder/
│   └── simple.py           # find API — locates files by type from predefined paths
├── operations/
│   └── simple.py           # ops API — Excel processing operations
├── core/
│   ├── file.py             # FileObject — wraps paths with copy/move operations
│   └── clean_sheet.py      # CleanSheetProcessor — expands merged cells, returns DataFrame
├── fileSelector.py         # find_in_folder — single-folder file search
├── scanNameFiles.py        # identify_file_type — name-based type detection
├── validators.py           # Format validators for ZJ, Manpower subtypes
└── paths_config.py         # DEFAULT_PATHS — predefined search directories
```

### Module responsibilities

| Module | Responsibility |
|---|---|
| `finder/` | Orchestrates search across all predefined paths for a given type |
| `operations/` | High-level Excel processing, returns DataFrame |
| `core/file.py` | Chainable file copy/move wrapper |
| `core/clean_sheet.py` | Merged-cell expansion and DataFrame extraction |
| `fileSelector.py` | Single-folder search, delegates type detection to `scanNameFiles` |
| `scanNameFiles.py` | Identifies file type from filename patterns |
| `validators.py` | Validates ZJ format (`ZJ{YYMMDD}{DD}-{version}`) and Manpower subtypes |
| `paths_config.py` | Central dictionary of per-type search directories |

---

## 💡 Examples

### Example 1 — Basic file discovery

```python
from filekit import find

file = find.manpower_budget()

if file:
    print(f"Found: {file}")
else:
    print("No Manpower Budget file found in configured paths.")
```

### Example 2 — Copy and process in one chain

```python
from filekit import find, ops

file = find.manpower_budget()

# Copy to a working directory, then process the copy
working_copy = file.copy(r"C:\Work\Temp")
df = ops.clean_sheet(working_copy, sheet="Sheet1")

print(f"Rows: {len(df)}, Columns: {len(df.columns)}")
print(df.head())
```

### Example 3 — Save cleaned Excel and get DataFrame

```python
from filekit import find, ops

file = find.zj()
df = ops.clean_sheet(
    file,
    sheet="Data",
    output=r"C:\Reports\ZJ_clean.xlsx",   # saves a new file with only the clean sheet
)

# Continue analysis
summary = df.groupby("Line").sum()
```

### Example 4 — Operation chaining

```python
from filekit import find, ops

# Find → archive the original → process the archive
df = ops.clean_sheet(
    find.manpower().move(r"C:\archive"),
    sheet="Sheet1",
    output=r"C:\processed\manpower_clean.xlsx",
)
```

### Example 5 — Custom folder search (no predefined paths)

```python
from filekit.fileSelector import find_in_folder
from filekit.core.file import FileObject
from filekit import ops

path = find_in_folder(r"C:\MyReports", "MANPOWER_BUDGET")
if path:
    file = FileObject(path)
    df = ops.clean_sheet(file, sheet="Budget")
```

---

## ⚙️ Configuration

### Predefined Paths

Edit `filekit/paths_config.py` to configure which folders each file type searches:

```python
DEFAULT_PATHS = {
    "MANPOWER_BUDGET": [
        r"\\server\share\Manpower\Budget 2026",
        r"\\server\share\Manpower\Budget 2025",   # fallback
    ],
    "MANPOWER": [
        r"\\server\share\Manpower",
    ],
    "ZJ": [
        r"\\server\share\Production\ZJ",
    ],
    "MANPOWER_DOCUMENTS": [
        r"\\server\share\Manpower\Documents",
    ],
    "REAL_TIME_PRODUCTION": [
        r"\\server\share\Production\RealTime",
    ],
}
```

- Each key maps to a **list of folders** — tried in order, search stops at the first folder that yields a match.
- Types not present in `DEFAULT_PATHS` will return an empty `FileObject` from `find.*()`.

---

## 📂 Supported File Types

| Type key | Identified by | Latest-file logic |
|---|---|---|
| `MANPOWER_BUDGET` | `"MANPOWER"` + `"BUDGET"` in filename | Highest revision number, then month |
| `MANPOWER_DOCUMENTS` | `"MANPOWER"` + `"DOCUMENTS"` in filename | Latest year, then month, then quarter |
| `MANPOWER` | `"MANPOWER"` (no Budget/Documents) | Latest month + day |
| `ZJ` | Starts with `"ZJ"`, format `ZJ{YYMMDD}{DD}-{version}` | Latest date, then version number |
| `REAL_TIME_PRODUCTION` | `"REAL-TIME"` + `"PRODUCTION"` in filename | First match (single expected file) |

> **ZJ format example:** `ZJ26042804-8170.xlsx` → date `260428` (YYMMDD), version prefix `04`, version `8170`.  
> Files with `(1)`, `(2)` suffixes are treated as duplicates and sorted accordingly.

---

## 📄 License

MIT License — see [LICENSE](LICENSE) for details.

---

## 👤 Author

**LJD-UwU**
- Email: himexpe.interns@hisense.com
- GitHub: https://github.com/LJD-UwU
