feat: Parameterize fixed asset import and deletion scripts with command-line arguments and update the README.
This commit is contained in:
parent
359b1a2278
commit
3803078318
@ -1,31 +1,70 @@
|
||||
# Fixed Asset Import Script
|
||||
# Fixed Asset Import Tools
|
||||
|
||||
This script imports fixed assets from `Fixed Asset Kipas.xlsx` into Odoo 17 database `kipasdbclone5`.
|
||||
This folder contains scripts to manage the import and lifecycle of fixed assets in Odoo 17.
|
||||
|
||||
## Features
|
||||
- **Avoids Double Posting**: Sets assets to 'Running' (Open) state manually, bypassing the Journal Entry creation for Asset Recognition.
|
||||
- **Depreciation Calculation**: Adjusts the "Accumulated Depreciation Per Dec 31" from Excel to "Per Oct 31" (Opening Balance Date) by subtracting 2 months of depreciation.
|
||||
- **Model Handling**: Automatically maps categories. Creates `Peralatan Dapur` model if missing (copying from `Peralatan Inventaris`).
|
||||
- **Cutoff Date**: Skips assets acquired after Oct 31, 2025.
|
||||
## 1. Import Script (`import_fixed_assets.py`)
|
||||
Imports assets from an Excel file, handling depreciation calculation and creating the assets in "Running" state to avoid opening balance duplication.
|
||||
|
||||
### Features
|
||||
- **Avoids Double Posting**: Sets assets to 'Running' manually.
|
||||
- **Asset Code**: Maps Column B ("Kode Barang") to `asset_code`.
|
||||
- **Historical Cleanup**: Deletes draft moves `<= Cutoff Date` to keep the books clean.
|
||||
- **Auto-Model**: Creates missing asset models (e.g. "PERALATAN DAPUR") on the fly.
|
||||
|
||||
### Usage
|
||||
Run the script providing the path to `odoo-bin`, `odoo.conf`, the Excel file, and the database name:
|
||||
|
||||
## Usage
|
||||
Run the script using the Odoo virtual environment:
|
||||
```bash
|
||||
/home/suherdy/Pythoncode/odoo17/.venv/bin/python /home/suherdy/Pythoncode/odoo17/scripts/import_fixed_assets.py
|
||||
/path/to/venv/bin/python scripts/import_fixed_assets.py \
|
||||
<path_to_odoo_bin> \
|
||||
<path_to_odoo_conf> \
|
||||
<path_to_excel_file> \
|
||||
<database_name>
|
||||
```
|
||||
|
||||
## Logic Details
|
||||
1. **Accumulated Depreciation**:
|
||||
- Uses Excel column R (Accum Depr Dec 31).
|
||||
- `Accum Oct 31 = Accum Dec 31 - (2 * Monthly Depreciation)`.
|
||||
- If asset is fully depreciated (End Date <= Oct 31), uses `Accum Dec 31` as is.
|
||||
2. **State**:
|
||||
- Assets are created in `draft`.
|
||||
- `compute_depreciation_board()` is called to generate Draft moves for future depreciation (subtracted by imported amount).
|
||||
- `state` is manually Set to `open`.
|
||||
- Result: No historical moves posted. Future moves are Draft (to be posted by cron/user). No Asset Recognition entry.
|
||||
**Example:**
|
||||
```bash
|
||||
/home/suherdy/Pythoncode/odoo17/.venv/bin/python scripts/import_fixed_assets.py \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo/odoo-bin \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo.conf \
|
||||
"/home/suherdy/Pythoncode/odoo17/Fixed Asset Kipas.xlsx" \
|
||||
kipasdbclone5
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
- `openpyxl`
|
||||
- `python-dateutil`
|
||||
- Odoo configuration file at `../odoo.conf`
|
||||
---
|
||||
|
||||
## 2. Post Depreciation (`post_depreciation.py`)
|
||||
Posts all **Draft** depreciation entries found in the system up to a specific date (default: today). This is useful to "catch up" depreciation for Nov/Dec 2025 after import.
|
||||
|
||||
### Usage
|
||||
```bash
|
||||
/home/suherdy/Pythoncode/odoo17/.venv/bin/python scripts/post_depreciation.py
|
||||
```
|
||||
*Note: You may need to edit the `POST_UP_TO_DATE` variable inside the script to target a specific date.*
|
||||
|
||||
---
|
||||
|
||||
## 3. Delete All Assets (`delete_all_assets.py`)
|
||||
**⚠ WARNING**: This script deletes **ALL** fixed assets and their related journal entries (posted or draft). Use this only if you need to wipe clean and re-import.
|
||||
|
||||
### Usage
|
||||
Run the script providing the path to `odoo-bin`, `odoo.conf`, and the database name:
|
||||
|
||||
```bash
|
||||
/path/to/venv/bin/python scripts/delete_all_assets.py \
|
||||
<path_to_odoo_bin> \
|
||||
<path_to_odoo_conf> \
|
||||
<database_name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
/home/suherdy/Pythoncode/odoo17/.venv/bin/python scripts/delete_all_assets.py \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo/odoo-bin \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo.conf \
|
||||
kipasdbclone5
|
||||
```
|
||||
|
||||
## Requirements
|
||||
1. **Modules**: The `asset_code_field` custom module (in `customaddons/`) must be installed.
|
||||
2. **Python Packages**: `openpyxl`, `python-dateutil`.
|
||||
|
||||
@ -1,24 +1,38 @@
|
||||
import sys
|
||||
import os
|
||||
# ---------------- CONFIGURATION ----------------
|
||||
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
os.chdir(PROJECT_ROOT)
|
||||
import argparse
|
||||
|
||||
ODOO_PATH = os.path.join(PROJECT_ROOT, 'odoo')
|
||||
CONF_FILE = os.path.join(PROJECT_ROOT, 'odoo.conf')
|
||||
DB_NAME = 'kipasdbclone5'
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Delete All Fixed Assets from Odoo")
|
||||
parser.add_argument("odoo_bin_path", help="Path to odoo-bin executable")
|
||||
parser.add_argument("conf_path", help="Path to odoo.conf")
|
||||
parser.add_argument("db_name", help="Database name")
|
||||
|
||||
if ODOO_PATH not in sys.path:
|
||||
sys.path.append(ODOO_PATH)
|
||||
args = parser.parse_args()
|
||||
|
||||
import odoo
|
||||
from odoo import api, SUPERUSER_ID
|
||||
odoo_bin_path = os.path.abspath(args.odoo_bin_path)
|
||||
conf_path = os.path.abspath(args.conf_path)
|
||||
db_name = args.db_name
|
||||
|
||||
# Add Odoo to sys.path
|
||||
odoo_root = os.path.dirname(odoo_bin_path)
|
||||
if odoo_root not in sys.path:
|
||||
sys.path.append(odoo_root)
|
||||
|
||||
# Change CWD to config directory to handle relative paths in config
|
||||
os.chdir(os.path.dirname(conf_path))
|
||||
|
||||
def delete_assets():
|
||||
print(f"Initializing Odoo Environment for database: {DB_NAME}...")
|
||||
try:
|
||||
odoo.tools.config.parse_config(['-c', CONF_FILE])
|
||||
registry = odoo.registry(DB_NAME)
|
||||
import odoo
|
||||
from odoo import api, SUPERUSER_ID
|
||||
except ImportError:
|
||||
print(f"Error: Could not import 'odoo' module from {odoo_root}. Make sure odoo-bin path is correct.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Initializing Odoo Environment for database: {db_name}...")
|
||||
try:
|
||||
odoo.tools.config.parse_config(['-c', conf_path])
|
||||
registry = odoo.registry(db_name)
|
||||
except Exception as e:
|
||||
print(f"Error initializing Odoo: {e}")
|
||||
return
|
||||
@ -49,12 +63,6 @@ def delete_assets():
|
||||
moves.unlink() # Deleting moves first cleans up the relation
|
||||
|
||||
# 3. Reset Assets to Draft
|
||||
# Some assets might be 'open' or 'close' or 'cancelled'.
|
||||
# To delete, they often need to be in draft or cancelled state depending on logic,
|
||||
# but unlink() in Odoo 17 account_asset usually checks if they are NOT in open/paused/close.
|
||||
# So we must write state = draft.
|
||||
|
||||
# Check for assets that are not draft
|
||||
non_draft_assets = assets.filtered(lambda a: a.state != 'draft')
|
||||
if non_draft_assets:
|
||||
print(f"Setting {len(non_draft_assets)} assets to draft state...")
|
||||
@ -74,4 +82,4 @@ def delete_assets():
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
delete_assets()
|
||||
main()
|
||||
|
||||
@ -1,31 +1,46 @@
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
import openpyxl
|
||||
from datetime import datetime, date
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
||||
# ---------------- CONFIGURATION ----------------
|
||||
PROJECT_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
|
||||
# Change CWD to Project Root so relative paths in odoo.conf work
|
||||
os.chdir(PROJECT_ROOT)
|
||||
|
||||
ODOO_PATH = os.path.join(PROJECT_ROOT, 'odoo')
|
||||
CONF_FILE = os.path.join(PROJECT_ROOT, 'odoo.conf')
|
||||
EXCEL_FILE = os.path.join(PROJECT_ROOT, 'Fixed Asset Kipas.xlsx')
|
||||
DB_NAME = 'kipasdbclone5'
|
||||
# Constants
|
||||
CUTOFF_DATE = date(2025, 10, 31)
|
||||
|
||||
if ODOO_PATH not in sys.path:
|
||||
sys.path.append(ODOO_PATH)
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Import Fixed Assets to Odoo")
|
||||
parser.add_argument("odoo_bin_path", help="Path to odoo-bin executable")
|
||||
parser.add_argument("conf_path", help="Path to odoo.conf")
|
||||
parser.add_argument("excel_path", help="Path to the Excel file")
|
||||
parser.add_argument("db_name", help="Database name")
|
||||
|
||||
import odoo
|
||||
from odoo import api, SUPERUSER_ID
|
||||
args = parser.parse_args()
|
||||
|
||||
odoo_bin_path = os.path.abspath(args.odoo_bin_path)
|
||||
conf_path = os.path.abspath(args.conf_path)
|
||||
excel_path = os.path.abspath(args.excel_path)
|
||||
db_name = args.db_name
|
||||
|
||||
# Add Odoo to sys.path
|
||||
odoo_root = os.path.dirname(odoo_bin_path)
|
||||
if odoo_root not in sys.path:
|
||||
sys.path.append(odoo_root)
|
||||
|
||||
# Change CWD to config directory to handle relative paths in config (like addons_path)
|
||||
os.chdir(os.path.dirname(conf_path))
|
||||
|
||||
def import_assets():
|
||||
print(f"Initializing Odoo Environment for database: {DB_NAME}...")
|
||||
try:
|
||||
odoo.tools.config.parse_config(['-c', CONF_FILE])
|
||||
registry = odoo.registry(DB_NAME)
|
||||
import odoo
|
||||
from odoo import api, SUPERUSER_ID
|
||||
except ImportError:
|
||||
print(f"Error: Could not import 'odoo' module from {odoo_root}. Make sure odoo-bin path is correct.")
|
||||
sys.exit(1)
|
||||
|
||||
print(f"Initializing Odoo Environment for database: {db_name}...")
|
||||
try:
|
||||
odoo.tools.config.parse_config(['-c', conf_path])
|
||||
registry = odoo.registry(db_name)
|
||||
except Exception as e:
|
||||
print(f"Error initializing Odoo: {e}")
|
||||
return
|
||||
@ -35,7 +50,7 @@ def import_assets():
|
||||
print("Connected to Odoo.")
|
||||
try:
|
||||
ensure_models(env)
|
||||
process_import(env)
|
||||
process_import(env, excel_path)
|
||||
cr.commit()
|
||||
print("Changes committed to database.")
|
||||
except Exception as e:
|
||||
@ -100,9 +115,9 @@ def ensure_models(env):
|
||||
env['account.asset'].create(vals)
|
||||
print(f"Created model '{config['name']}'.")
|
||||
|
||||
def process_import(env):
|
||||
print(f"Reading Excel file: {EXCEL_FILE}...")
|
||||
wb = openpyxl.load_workbook(EXCEL_FILE, data_only=True)
|
||||
def process_import(env, excel_file):
|
||||
print(f"Reading Excel file: {excel_file}...")
|
||||
wb = openpyxl.load_workbook(excel_file, data_only=True)
|
||||
ws = wb.active
|
||||
|
||||
current_category_name = None
|
||||
@ -232,4 +247,4 @@ def process_import(env):
|
||||
print(f"\nTotal Assets Imported: {count}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
import_assets()
|
||||
main()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user