Fix family publishing, concurrent edits and session consistency
This commit is contained in:
+27
-8
@@ -51,8 +51,11 @@ class Family:
|
||||
if kind == 'event':
|
||||
item.update(createdAt=old.get('createdAt', item['updatedAt']) if old else item['updatedAt'],
|
||||
createdBy=old.get('createdBy', user['username']) if old else user['username'])
|
||||
if item['status'] == 'published':
|
||||
item['publishedAt'] = old.get('publishedAt', item['updatedAt']) if old else item['updatedAt']
|
||||
# Withdrawal and restoration must retain the first publication time.
|
||||
if old and old.get('publishedAt'):
|
||||
item['publishedAt'] = old['publishedAt']
|
||||
elif item['status'] == 'published':
|
||||
item['publishedAt'] = item['updatedAt']
|
||||
# Revision and record are committed together, so concurrent forms cannot overwrite silently.
|
||||
a.DB.execute('INSERT OR REPLACE INTO ' + table + ' VALUES (?,?)', (item['id'], json.dumps(item)))
|
||||
a.DB.execute('INSERT OR REPLACE INTO settings VALUES (?,?)', ('familyRevision', json.dumps(revision + 1)))
|
||||
@@ -64,7 +67,7 @@ class Family:
|
||||
a = self.a
|
||||
item = {'id': old['id'] if old else secrets.token_hex(8)}
|
||||
for key, maximum, required in [('title', 160, True), ('eventDate', 10, True),
|
||||
('summary', 400, False), ('sourceName', 160, False),
|
||||
('sourceName', 160, False),
|
||||
('sourceUrl', 2000, False)]:
|
||||
item[key] = a.clean_text(data.get(key, ''), maximum, required)
|
||||
try:
|
||||
@@ -72,16 +75,17 @@ class Family:
|
||||
raise ValueError()
|
||||
except ValueError:
|
||||
raise a.Problem('记事日期请填写有效日期,格式为 YYYY-MM-DD')
|
||||
body = data.get('body', '')
|
||||
if not isinstance(body, str) or len(body) > 12000 or any(ord(c) < 32 and c not in '\r\n\t' for c in body):
|
||||
raise a.Problem('记事正文格式不正确,最多 12000 字')
|
||||
item['body'] = body.strip()
|
||||
for key, maximum, label in [('summary', 400, '摘要'), ('body', 12000, '正文')]:
|
||||
value = data.get(key, '')
|
||||
if not isinstance(value, str) or len(value) > maximum or any(ord(c) < 32 and c not in '\r\n\t' for c in value):
|
||||
raise a.Problem(f'记事{label}格式不正确,最多 {maximum} 字')
|
||||
item[key] = value.strip()
|
||||
item['personIds'] = data.get('personIds', [])
|
||||
if (not isinstance(item['personIds'], list) or len(item['personIds']) > 200
|
||||
or any(not isinstance(p, str) or not a.get_object('people', p) for p in item['personIds'])):
|
||||
raise a.Problem('请选择有效的关联人物,最多 200 位')
|
||||
item['personIds'] = list(dict.fromkeys(item['personIds']))
|
||||
item['status'] = data.get('status', 'draft')
|
||||
item['status'] = data.get('status', old.get('status', 'draft') if old else 'draft')
|
||||
item['archived'] = data.get('archived', old.get('archived', False) if old else False)
|
||||
if item['status'] not in ('draft', 'published') or not isinstance(item['archived'], bool):
|
||||
raise a.Problem('记事状态不正确')
|
||||
@@ -127,8 +131,22 @@ class Family:
|
||||
item['archived'] = data.get('archived', False)
|
||||
if not isinstance(item['archived'], bool):
|
||||
raise a.Problem('归档状态不正确')
|
||||
if not old or item['birthDate'] != old.get('birthDate', ''):
|
||||
self.check_birth_order([e for e in a.objects('family_links')
|
||||
if item['id'] in (e['fromId'], e['toId'])], item)
|
||||
return item
|
||||
|
||||
def check_birth_order(self, links, proposed_person=None):
|
||||
people = {p['id']: p for p in self.a.objects('people')}
|
||||
if proposed_person:
|
||||
people[proposed_person['id']] = proposed_person
|
||||
for edge in links:
|
||||
if not edge.get('active') or edge['kind'] != 'parent' or edge.get('lineage') != 'biological':
|
||||
continue
|
||||
parent, child = people.get(edge['fromId']), people.get(edge['toId'])
|
||||
if parent and child and parent.get('birthDate') and child.get('birthDate') and parent['birthDate'] >= child['birthDate']:
|
||||
raise self.a.Problem('亲生父母的出生日期必须早于子女,请核对日期或亲子属性')
|
||||
|
||||
def link(self, data, old):
|
||||
a = self.a
|
||||
left, right = data.get('fromId'), data.get('toId')
|
||||
@@ -148,6 +166,7 @@ class Family:
|
||||
item = dict(id=old['id'] if old else secrets.token_hex(8), fromId=left, toId=right, kind=kind,
|
||||
lineage=lineage if kind == 'parent' else 'unspecified', active=active,
|
||||
note=a.clean_text(data.get('note', ''), 300))
|
||||
self.check_birth_order([item])
|
||||
links = [e for e in a.objects('family_links') if e.get('active') and e['id'] != item['id']]
|
||||
if active:
|
||||
for e in links:
|
||||
|
||||
Reference in New Issue
Block a user