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):
|
||||||
|
|||||||
17
app/migrations/0346_remove_co_ownership_code.py
Normal file
17
app/migrations/0346_remove_co_ownership_code.py
Normal 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',
|
||||||
|
),
|
||||||
|
]
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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.
BIN
static/contract/2. Đơn Đăng kí nguyện vọng một người.docx
Normal file
BIN
static/contract/2. Đơn Đăng kí nguyện vọng một người.docx
Normal file
Binary file not shown.
BIN
static/contract/2. Đơn Đăng kí nguyện vọng tổ chức.docx
Normal file
BIN
static/contract/2. Đơn Đăng kí nguyện vọng tổ chức.docx
Normal file
Binary file not shown.
BIN
static/contract/2. Đơn Đăng kí nguyện vọng đồng sở hữu.docx
Normal file
BIN
static/contract/2. Đơn Đăng kí nguyện vọng đồng sở hữu.docx
Normal file
Binary file not shown.
BIN
static/contract/3. Thoả thuận thực hiện nguyện vọng cá nhân.docx
Normal file
BIN
static/contract/3. Thoả thuận thực hiện nguyện vọng cá nhân.docx
Normal file
Binary file not shown.
BIN
static/contract/3. Thoả thuận thực hiện nguyện vọng tổ chức.docx
Normal file
BIN
static/contract/3. Thoả thuận thực hiện nguyện vọng tổ chức.docx
Normal file
Binary file not shown.
Binary file not shown.
BIN
static/contract/6. Biên bản thanh lý TTTHNV cá nhân.docx
Normal file
BIN
static/contract/6. Biên bản thanh lý TTTHNV cá nhân.docx
Normal file
Binary file not shown.
BIN
static/contract/6. Biên bản thanh lý TTTHNV tổ chức.docx
Normal file
BIN
static/contract/6. Biên bản thanh lý TTTHNV tổ chức.docx
Normal file
Binary file not shown.
BIN
static/contract/6. Biên bản thanh lý TTTHNV đồng sở hữu.docx
Normal file
BIN
static/contract/6. Biên bản thanh lý TTTHNV đồng sở hữu.docx
Normal file
Binary file not shown.
Reference in New Issue
Block a user