changes
This commit is contained in:
@@ -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}
|
||||
Reference in New Issue
Block a user