This commit is contained in:
anhduy-tech
2026-01-05 13:40:51 +07:00
parent f43da98b0e
commit 4fd1aae08f
21 changed files with 76 additions and 10 deletions

View File

@@ -209,19 +209,43 @@ class DocumentGenerator:
if not obj:
return None
import re
parts = field_path.split('.')
value = obj
for part in parts:
if value is None:
break
# Lấy thuộc tính từ object
# 1. Kiểm tra nếu part chứa index mảng, ví dụ: "payment_plan[0]"
array_match = re.match(r"(\w+)\[(\d+)\]", part)
if array_match:
attr_name = array_match.group(1) # Lấy "payment_plan"
index = int(array_match.group(2)) # Lấy 0
# Lấy list từ object
value = getattr(value, attr_name, None)
# Truy cập phần tử theo index
try:
if isinstance(value, (list, tuple)):
value = value[index]
elif hasattr(value, 'all'): # QuerySet
value = value[index]
except (IndexError, TypeError):
return None
else:
# 2. Xử lý truy cập thuộc tính hoặc key của Dict (JSON)
if isinstance(value, dict):
# Nếu là dict (phần tử trong JSONField), dùng .get()
value = value.get(part)
else:
# Nếu là object, dùng getattr()
value = getattr(value, part, None)
# KIỂM TRA NẾU LÀ QUAN HỆ NGƯỢC (ForeignKey ngược hoặc ManyToMany)
# Trong Django, các quan hệ này trả về một Manager (có method 'all')
# 3. Hỗ trợ lấy bản ghi đầu tiên nếu gặp Quan hệ ngược (Manager)
if hasattr(value, 'all') and not isinstance(value, models.Model):
value = value.first() # Tự động lấy bản ghi đầu tiên
value = value.first()
return value

View File

@@ -0,0 +1,17 @@
# Generated by Django 5.1.7 on 2026-01-04 17:54
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('app', '0345_alter_co_ownership_transaction'),
]
operations = [
migrations.RemoveField(
model_name='co_ownership',
name='code',
),
]

View File

@@ -1964,7 +1964,6 @@ class Transaction_Discount(models.Model):
class Co_Ownership(models.Model):
code = models.CharField(max_length=30, null=False, unique=True)
transaction = models.ForeignKey(Transaction, null=False, related_name='co_op', on_delete=models.PROTECT)
people = models.ForeignKey(People, null=False, related_name='+', on_delete=models.PROTECT)
create_time = models.DateTimeField(null=True, auto_now_add=True)

View File

@@ -54,6 +54,7 @@ def evaluate_rule(rule: Rule, context: dict):
print(f" Evaluating Rule: {left} {op} {right}")
if op == "IN" and left not in right: return False
if op == "==" and left != right: return False
if op == "!=" and left == right: return False
if op == ">" and not (left > right): return False

View File

@@ -1,6 +1,6 @@
import re
from datetime import datetime
from django.db import models
def resolve_value(expr, context):
"""
@@ -64,10 +64,36 @@ def resolve_value(expr, context):
root, *rest = key_path.split(".")
val = context.get(root)
for r in rest:
if val is None:
return None
val = getattr(val, r, None) if not isinstance(val, dict) else val.get(r)
# 1. Xử lý truy cập index mảng, ví dụ: payment_plan[0]
array_match = re.match(r"(\w+)\[(\d+)\]", r)
if array_match:
attr_name = array_match.group(1)
index = int(array_match.group(2))
# Lấy list/queryset
val = getattr(val, attr_name, None) if not isinstance(val, dict) else val.get(attr_name)
try:
if hasattr(val, 'all'): # Django QuerySet/Manager
val = val[index]
else: # List thông thường
val = val[index]
except (IndexError, TypeError, KeyError):
return None
else:
# 2. Xử lý truy cập thuộc tính hoặc dict key
if isinstance(val, dict):
val = val.get(r)
else:
val = getattr(val, r, None)
# 3. Hỗ trợ tự động lấy bản ghi đầu tiên nếu là Manager (1-n)
if hasattr(val, 'all') and not isinstance(val, models.Model):
val = val.first()
return val
# =============================================

View File

@@ -1 +0,0 @@
,kumduy,duy-pc,04.01.2026 23:48,file:///home/kumduy/.config/libreoffice/4;