This commit is contained in:
anhduy-tech
2026-02-04 21:01:54 +07:00
parent f297a5e1b4
commit 5b360753d8
11 changed files with 552 additions and 204 deletions

View File

@@ -288,3 +288,88 @@ def lookup_data_action(params, context):
except Exception as e:
print(f" [LOOKUP] EXCEPTION: {str(e)}")
raise e
# ============================
# Quét và phân bổ toàn bộ bút toán còn phần dư
# ============================
@register_action("ALLOCATE_ALL_PENDING", schema={})
def allocate_all_pending_action(params, context):
"""
Quét toàn bộ Internal_Entry có allocation_remain > 0 (type CR),
group by product_id, gọi phân bổ cho từng product cho đến khi hết.
"""
from app.payment import allocate_payment_to_schedules, allocate_penalty_reduction
from decimal import Decimal
Internal_Entry = apps.get_model("app", "Internal_Entry")
Payment_Schedule = apps.get_model("app", "Payment_Schedule")
Product_Booked = apps.get_model("app", "Product_Booked")
Transaction_Current = apps.get_model("app", "Transaction_Current")
Transaction_Detail = apps.get_model("app", "Transaction_Detail")
# ---------- Lấy toàn bộ product_id còn entry chưa phân bổ hết ----------
product_ids = list(
Internal_Entry.objects.filter(
type__code="CR",
allocation_remain__gt=0,
product__isnull=False
)
.values_list("product_id", flat=True)
.distinct()
)
print(f" [ALLOCATE_ALL] Tìm được {len(product_ids)} product có entry còn phần dư")
if not product_ids:
return {"total_products": 0, "results": []}
# ---------- DEBUG: dump trạng thái trước khi phân bổ ----------
for pid in product_ids:
print(f"\n [DEBUG] ===== Product {pid} — trạng thái TRƯỚC phân bổ =====")
# Entries
entries = Internal_Entry.objects.filter(
product_id=pid, type__code="CR", allocation_remain__gt=0
).order_by("date", "create_time")
for e in entries:
print(f" Entry id={e.id} | account_id={e.account_id} | amount={e.amount} | allocation_remain={e.allocation_remain} | date={e.date}")
# Lấy txn_detail của product
booked = Product_Booked.objects.filter(product_id=pid).first()
if not booked or not booked.transaction:
print(f" !! Không có Product_Booked / Transaction")
continue
txn = booked.transaction
txn_detail = None
try:
current = Transaction_Current.objects.get(transaction=txn)
txn_detail = current.detail
except Exception:
txn_detail = Transaction_Detail.objects.filter(transaction=txn).order_by("-create_time").first()
if not txn_detail:
print(f" !! Không có Transaction_Detail")
continue
# Schedules
all_schedules = Payment_Schedule.objects.filter(txn_detail=txn_detail).order_by("cycle", "from_date")
unpaid = all_schedules.filter(status__id=1)
print(f" Tổng schedule: {all_schedules.count()} | Chưa thanh toán (status=1): {unpaid.count()}")
for s in all_schedules:
print(f" Schedule id={s.id} | cycle={s.cycle} | status_id={s.status_id} | amount_remain={s.amount_remain} | penalty_remain={s.penalty_remain} | remain_amount={s.remain_amount}")
# ---------- Chạy phân bổ ----------
results = []
for product_id in product_ids:
try:
normal = allocate_payment_to_schedules(product_id)
reduction = allocate_penalty_reduction(product_id)
results.append({"product_id": product_id, "normal": normal, "reduction": reduction})
print(f" [ALLOCATE_ALL] Product {product_id}: OK — normal={normal}")
except Exception as e:
print(f" [ALLOCATE_ALL] Product {product_id}: ERROR - {str(e)}")
results.append({"product_id": product_id, "error": str(e)})
return {"total_products": len(product_ids), "results": results}