feat: Implement auto_post='at_date' for future depreciation entries in import and fix scripts, and add a check_auto_post utility.
This commit is contained in:
parent
0b925cadec
commit
add87ea10d
@ -7,6 +7,8 @@ Imports assets from an Excel file, handling depreciation calculation and creatin
|
||||
|
||||
### Features
|
||||
- **Avoids Double Posting**: Sets assets to 'Running' manually.
|
||||
- **Auto-Posting**: Automatically posts depreciation entries for **past and current dates**.
|
||||
- **Cron Ready**: Sets future depreciation entries to `auto_post='at_date'` so Odoo's standard cron picks them up.
|
||||
- **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.
|
||||
@ -51,12 +53,53 @@ Posts all **Draft** depreciation entries found in the system up to a specific da
|
||||
/home/suherdy/Pythoncode/odoo17/odoo/odoo-bin \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo.conf \
|
||||
kipasdbclone5 \
|
||||
kipasdbclone5 \
|
||||
--date 2026-01-21
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Delete All Assets (`delete_all_assets.py`)
|
||||
## 3. Post Missing Depreciations (`post_missing_depreciations.py`)
|
||||
Use this script to retroactive fix assets that were imported but have their depreciation entries stuck in **Draft** state.
|
||||
|
||||
### Features
|
||||
- Finds all **Running** assets.
|
||||
- Posts `Draft` depreciation moves for **past and current dates**.
|
||||
- Updates **future** `Draft` moves to have `auto_post='at_date'`, ensuring Odoo's cron processes them later.
|
||||
|
||||
### Usage
|
||||
```bash
|
||||
/path/to/venv/bin/python scripts/post_missing_depreciations.py \
|
||||
<path_to_odoo_bin> \
|
||||
<path_to_odoo_conf> \
|
||||
<database_name>
|
||||
```
|
||||
|
||||
**Example:**
|
||||
```bash
|
||||
/home/suherdy/Pythoncode/odoo17/.venv/bin/python scripts/post_missing_depreciations.py \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo/odoo-bin \
|
||||
/home/suherdy/Pythoncode/odoo17/odoo.conf \
|
||||
kipasdbclone5
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. Check Auto Post Status (`check_auto_post.py`)
|
||||
A simple diagnostic utility to check if the `auto_post` field is correctly set on draft depreciation moves.
|
||||
|
||||
### Usage
|
||||
```bash
|
||||
/path/to/venv/bin/python scripts/check_auto_post.py \
|
||||
<path_to_odoo_bin> \
|
||||
<path_to_odoo_conf> \
|
||||
<database_name>
|
||||
```
|
||||
|
||||
|
||||
---
|
||||
|
||||
## 5. 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
|
||||
|
||||
65
check_auto_post.py
Normal file
65
check_auto_post.py
Normal file
@ -0,0 +1,65 @@
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
from datetime import date
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Check Auto Post Status of Draft Depreciation Entries")
|
||||
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")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
odoo_bin_path = os.path.abspath(args.odoo_bin_path)
|
||||
conf_path = os.path.abspath(args.conf_path)
|
||||
db_name = args.db_name
|
||||
|
||||
odoo_dir = os.path.dirname(odoo_bin_path)
|
||||
if odoo_dir not in sys.path:
|
||||
sys.path.insert(0, odoo_dir)
|
||||
|
||||
os.chdir(os.path.dirname(conf_path))
|
||||
|
||||
try:
|
||||
import odoo
|
||||
from odoo import api, SUPERUSER_ID
|
||||
except ImportError:
|
||||
print(f"Error: Could not import 'odoo' module.")
|
||||
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
|
||||
|
||||
with registry.cursor() as cr:
|
||||
env = api.Environment(cr, SUPERUSER_ID, {})
|
||||
print("Connected to Odoo.")
|
||||
|
||||
check_assets(env)
|
||||
|
||||
def check_assets(env):
|
||||
assets = env['account.asset'].search([('state', '=', 'open')], limit=5)
|
||||
print(f"Checking first {len(assets)} running assets...")
|
||||
|
||||
for asset in assets:
|
||||
print(f"\nAsset: {asset.name}")
|
||||
draft_moves = asset.depreciation_move_ids.filtered(lambda m: m.state == 'draft')
|
||||
if not draft_moves:
|
||||
print(" No draft moves found.")
|
||||
continue
|
||||
|
||||
print(f" Found {len(draft_moves)} draft moves.")
|
||||
# Check distinct auto_post values
|
||||
auto_post_values = set(draft_moves.mapped('auto_post'))
|
||||
print(f" 'auto_post' values in draft moves: {auto_post_values}")
|
||||
|
||||
for move in draft_moves[:3]:
|
||||
print(f" - Date: {move.date}, auto_post: {move.auto_post}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@ -259,7 +259,11 @@ def process_import(env, excel_file):
|
||||
asset.write({'state': 'open'})
|
||||
|
||||
# FIX: Explicitly post the depreciation moves like Odoo's validate() method does
|
||||
asset.depreciation_move_ids.filtered(lambda move: move.state != 'posted')._post()
|
||||
# BUT only up to today. Future entries will be auto-posted by standard Odoo cron.
|
||||
# We explicitly set auto_post to 'at_date' for future entries to ensure the cron picks them up.
|
||||
today = date.today()
|
||||
asset.depreciation_move_ids.filtered(lambda move: move.state != 'posted' and move.date <= today)._post()
|
||||
asset.depreciation_move_ids.filtered(lambda move: move.state == 'draft' and move.date > today).write({'auto_post': 'at_date'})
|
||||
|
||||
|
||||
print(f"Imported: {asset.name} | Val: {original_value} | Oct31: {accum_depr_oct31:,.2f}")
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import sys
|
||||
import os
|
||||
import argparse
|
||||
from datetime import date
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Post Missing Depreciation Entries for Running Assets")
|
||||
@ -58,8 +59,10 @@ def process_assets(env):
|
||||
count_moves_posted = 0
|
||||
|
||||
for asset in assets:
|
||||
# Find draft moves for this asset
|
||||
moves_to_post = asset.depreciation_move_ids.filtered(lambda m: m.state == 'draft')
|
||||
# Find draft moves for this asset UP TO TODAY
|
||||
# Future moves are handled by Odoo's auto_post cron
|
||||
today = date.today()
|
||||
moves_to_post = asset.depreciation_move_ids.filtered(lambda m: m.state == 'draft' and m.date <= today)
|
||||
|
||||
if not moves_to_post:
|
||||
continue
|
||||
@ -67,17 +70,15 @@ def process_assets(env):
|
||||
print(f"Asset '{asset.name}' has {len(moves_to_post)} draft moves. Posting...")
|
||||
|
||||
# Post them
|
||||
# We use _post() directly as it's the internal method used by validate()
|
||||
# avoiding some higher level checks that might block us if dates are weird,
|
||||
# though standard validate() uses _post().
|
||||
# Note: account.move.action_post() is the public method.
|
||||
# validate() in account_asset.py calls:
|
||||
# asset.depreciation_move_ids.filtered(lambda move: move.state != 'posted')._post()
|
||||
# So we stick to that.
|
||||
moves_to_post._post()
|
||||
|
||||
count_assets_fixed += 1
|
||||
count_moves_posted += len(moves_to_post)
|
||||
|
||||
# Also ensure FUTURE draft moves are set to auto_post='at_date'
|
||||
future_moves = asset.depreciation_move_ids.filtered(lambda m: m.state == 'draft' and m.date > today)
|
||||
if future_moves:
|
||||
future_moves.write({'auto_post': 'at_date'})
|
||||
|
||||
print(f"\nSummary:")
|
||||
print(f" Assets processed: {len(assets)}")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user