This commit is contained in:
anhduy-tech
2026-01-05 13:41:04 +07:00
parent f43da98b0e
commit 4fd1aae08f
21 changed files with 76 additions and 10 deletions
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+28 -4
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
@@ -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',
),
]
-1
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)
+1
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
+28 -2
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
# =============================================
@@ -1 +0,0 @@
,kumduy,duy-pc,04.01.2026 23:48,file:///home/kumduy/.config/libreoffice/4;