changes
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -209,20 +209,44 @@ class DocumentGenerator:
|
|||||||
if not obj:
|
if not obj:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
import re
|
||||||
parts = field_path.split('.')
|
parts = field_path.split('.')
|
||||||
value = obj
|
value = obj
|
||||||
for part in parts:
|
for part in parts:
|
||||||
if value is None:
|
if value is None:
|
||||||
break
|
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]"
|
||||||
value = getattr(value, part, None)
|
array_match = re.match(r"(\w+)\[(\d+)\]", part)
|
||||||
|
|
||||||
# KIỂM TRA NẾU LÀ QUAN HỆ NGƯỢC (ForeignKey ngược hoặc ManyToMany)
|
if array_match:
|
||||||
# Trong Django, các quan hệ này trả về một Manager (có method 'all')
|
attr_name = array_match.group(1) # Lấy "payment_plan"
|
||||||
if hasattr(value, 'all') and not isinstance(value, models.Model):
|
index = int(array_match.group(2)) # Lấy 0
|
||||||
value = value.first() # Tự động lấy bản ghi đầu tiên
|
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# 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()
|
||||||
|
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def fetch_data(self):
|
def fetch_data(self):
|
||||||
|
|||||||
@@ -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',
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -1964,7 +1964,6 @@ class Transaction_Discount(models.Model):
|
|||||||
|
|
||||||
|
|
||||||
class Co_Ownership(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)
|
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)
|
people = models.ForeignKey(People, null=False, related_name='+', on_delete=models.PROTECT)
|
||||||
create_time = models.DateTimeField(null=True, auto_now_add=True)
|
create_time = models.DateTimeField(null=True, auto_now_add=True)
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ def evaluate_rule(rule: Rule, context: dict):
|
|||||||
|
|
||||||
print(f" Evaluating Rule: {left} {op} {right}")
|
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 left == right: return False
|
if op == "!=" and left == right: return False
|
||||||
if op == ">" and not (left > right): return False
|
if op == ">" and not (left > right): return False
|
||||||
|
|||||||
+28
-2
@@ -1,6 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
from django.db import models
|
||||||
|
|
||||||
def resolve_value(expr, context):
|
def resolve_value(expr, context):
|
||||||
"""
|
"""
|
||||||
@@ -64,10 +64,36 @@ def resolve_value(expr, context):
|
|||||||
|
|
||||||
root, *rest = key_path.split(".")
|
root, *rest = key_path.split(".")
|
||||||
val = context.get(root)
|
val = context.get(root)
|
||||||
|
|
||||||
for r in rest:
|
for r in rest:
|
||||||
if val is None:
|
if val is None:
|
||||||
return 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
|
return val
|
||||||
|
|
||||||
# =============================================
|
# =============================================
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
,kumduy,duy-pc,04.01.2026 23:48,file:///home/kumduy/.config/libreoffice/4;
|
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user