feat(plantare): schema v12 — bilateral signed columns + repo
Adds the deferred bilateral columns to Plantares (plantare-bilateral.md §"Schema delta"), all nullable/defaulted so v1 local rows coexist untouched: - pledgeId (the shared id both parties key their row by), debtorKey / creditorKey, debtorSignature / creditorSignature, movementId (the shared hand-over Movement for the provenance DAG), remoteState (proposed/accepted/declined — the handshake, distinct from status), returnKind (similar/workHours/other, default similar) + workHours. Repo: createPlantare grows optional bilateral params; plantareByPledgeId looks a row up by the shared id; applyPlantareSignatures counter-stamps an incoming accept; setPlantareRemoteState records a decline. The JSON codec carries every new field so they ride backups. Versioned migration is guarded/idempotent like the others; schema v12 dumped, test helper regenerated, migration test covers v1..v11 → v12. db + data + services 295/295 green.
This commit is contained in:
parent
516f1f50bc
commit
bec0f78fa1
11 changed files with 5322 additions and 17 deletions
|
|
@ -1867,14 +1867,27 @@ class VarietyRepository {
|
|||
String? owedDescription,
|
||||
int? dueBy,
|
||||
String? note,
|
||||
// Bilateral signed form (plantare-bilateral.md) — all optional so a plain
|
||||
// local note stays a v1 row with these null.
|
||||
String? id,
|
||||
int? madeOn,
|
||||
String? pledgeId,
|
||||
String? debtorKey,
|
||||
String? creditorKey,
|
||||
String? debtorSignature,
|
||||
String? creditorSignature,
|
||||
String? movementId,
|
||||
PlantareRemoteState? remoteState,
|
||||
PlantareReturnKind returnKind = PlantareReturnKind.similar,
|
||||
double? workHours,
|
||||
}) async {
|
||||
final (created, updated) = await _stamp();
|
||||
final id = idGen.newId();
|
||||
final rowId = id ?? idGen.newId();
|
||||
await _db
|
||||
.into(_db.plantares)
|
||||
.insert(
|
||||
PlantaresCompanion.insert(
|
||||
id: id,
|
||||
id: rowId,
|
||||
createdAt: created,
|
||||
updatedAt: updated,
|
||||
lastAuthor: nodeId,
|
||||
|
|
@ -1882,12 +1895,75 @@ class VarietyRepository {
|
|||
varietyId: Value(varietyId),
|
||||
counterparty: Value(counterparty),
|
||||
owedDescription: Value(owedDescription),
|
||||
madeOn: created,
|
||||
madeOn: madeOn ?? created,
|
||||
dueBy: Value(dueBy),
|
||||
note: Value(note),
|
||||
pledgeId: Value(pledgeId),
|
||||
debtorKey: Value(debtorKey),
|
||||
creditorKey: Value(creditorKey),
|
||||
debtorSignature: Value(debtorSignature),
|
||||
creditorSignature: Value(creditorSignature),
|
||||
movementId: Value(movementId),
|
||||
remoteState: Value(remoteState),
|
||||
returnKind: Value(returnKind),
|
||||
workHours: Value(workHours),
|
||||
),
|
||||
);
|
||||
return id;
|
||||
return rowId;
|
||||
}
|
||||
|
||||
/// The local row holding the bilateral pledge [pledgeId], or null. Both parties
|
||||
/// key their own row by the shared pledge id so accepts/declines reconcile.
|
||||
Future<Plantare?> plantareByPledgeId(String pledgeId) =>
|
||||
(_db.select(_db.plantares)
|
||||
..where((p) => p.pledgeId.equals(pledgeId))
|
||||
..limit(1))
|
||||
.getSingleOrNull();
|
||||
|
||||
/// Applies a counterparty's stub(s) and the new handshake [remoteState] to the
|
||||
/// row for [pledgeId] (e.g. on receiving an `accept`). No-op if unknown.
|
||||
Future<void> applyPlantareSignatures({
|
||||
required String pledgeId,
|
||||
String? debtorSignature,
|
||||
String? creditorSignature,
|
||||
PlantareRemoteState? remoteState,
|
||||
String? movementId,
|
||||
}) async {
|
||||
final (_, updated) = await _stamp();
|
||||
await (_db.update(_db.plantares)
|
||||
..where((p) => p.pledgeId.equals(pledgeId)))
|
||||
.write(
|
||||
PlantaresCompanion(
|
||||
debtorSignature:
|
||||
debtorSignature == null ? const Value.absent() : Value(debtorSignature),
|
||||
creditorSignature: creditorSignature == null
|
||||
? const Value.absent()
|
||||
: Value(creditorSignature),
|
||||
movementId:
|
||||
movementId == null ? const Value.absent() : Value(movementId),
|
||||
remoteState:
|
||||
remoteState == null ? const Value.absent() : Value(remoteState),
|
||||
updatedAt: Value(updated),
|
||||
lastAuthor: Value(nodeId),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// Moves the row for [pledgeId] to a new handshake [state] (e.g. `declined`).
|
||||
Future<void> setPlantareRemoteState(
|
||||
String pledgeId,
|
||||
PlantareRemoteState state,
|
||||
) async {
|
||||
final (_, updated) = await _stamp();
|
||||
await (_db.update(_db.plantares)
|
||||
..where((p) => p.pledgeId.equals(pledgeId)))
|
||||
.write(
|
||||
PlantaresCompanion(
|
||||
remoteState: Value(state),
|
||||
updatedAt: Value(updated),
|
||||
lastAuthor: Value(nodeId),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
/// All live commitments, newest first (for the Plantares screen).
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue