code wiki / _hdl_build / nx_estate.nx

nx_estate.nx source

↩ module page · 135 lines · 7972 B

1// nx_estate.nx -- LIB: renders a will's SCHEDULE OF ASSETS (a tangible-personal-property memorandum) from the 2// universal inventory's `estate` domain. Sovereign no-JS document: estate summary (net worth, item count), 3// per-beneficiary bequests with subtotals, residuary (unassigned) section, and the full asset schedule. 4// Boundary defense (rule 12): every asset name / owner is HTML-escaped. Money is integer CENTS (no float). 5// One more CONSUMER of the universal inventory (like the restaurant site is a consumer of the food engine). 6// license_tier: ORIGINAL 7import "nx_inventory.nx" 8import "nx_syscalls.nx" 9 10func er_streq(a: *u8, b: *u8) -> i64 { var i: i64 = 0; while a[i] != (0 as u8) { if a[i] != b[i] { return 0 } i = i + 1 } if b[i] != (0 as u8) { return 0 } return 1 } 11 12// unassigned assets carry this explicit sentinel owner -> the residuary estate. (NishiLang gotcha: an empty 13// string literal "" aliases to another literal's bytes, so never store "" -- use a real sentinel.) 14const ER_RESID: *u8 = "(residuary)" 15func er_is_residuary(o: *u8) -> i64 { return er_streq(o, ER_RESID) } 16 17// distinct owner strings (incl. "" = residuary) into owners_out (ptrs to copies); returns count 18func er_distinct_owners(inv_prefix: *u8, domain: *u8, owners_out: *i64) -> i64 { 19 let ids: *i64 = sys_mmap(8 * 256) as *i64 20 let n: i64 = iv_list(inv_prefix, domain, ids) 21 var c: i64 = 0 22 var i: i64 = 0 23 while i < n { 24 let ow: *u8 = sys_mmap(64) 25 iv_field_of(inv_prefix, domain, ids[i] as *u8, 7, ow) 26 var seen: i64 = 0 27 var j: i64 = 0 28 while j < c { if er_streq(owners_out[j] as *u8, ow) == 1 { seen = 1 } j = j + 1 } 29 if seen == 0 { owners_out[c] = ow as i64; c = c + 1 } 30 i = i + 1 31 } 32 return c 33} 34 35// total value (cents) of items willed to `owner` 36func er_owner_total(inv_prefix: *u8, domain: *u8, owner: *u8) -> i64 { 37 let ids: *i64 = sys_mmap(8 * 256) as *i64 38 let n: i64 = iv_list(inv_prefix, domain, ids) 39 var tot: i64 = 0 40 var i: i64 = 0 41 while i < n { 42 let ow: *u8 = sys_mmap(64) 43 iv_field_of(inv_prefix, domain, ids[i] as *u8, 7, ow) 44 if er_streq(ow, owner) == 1 { tot = tot + iv_value(inv_prefix, domain, ids[i] as *u8) } 45 i = i + 1 46 } 47 return tot 48} 49 50// emit one item row "<tr>...<td>$value</td></tr>" (cols depend on with_ben); returns new off 51func er_item_row(inv_prefix: *u8, domain: *u8, id: *u8, with_ben: i64, out: *u8, off: i64) -> i64 { 52 let f: *u8 = sys_mmap(128) 53 var o: i64 = off 54 o = as_append(out, o, "<tr><td>" as *u8) 55 iv_field_of(inv_prefix, domain, id, 0, f); o = as_append_escaped(out, o, f, as_len(f)) // name 56 o = as_append(out, o, "</td><td>" as *u8) 57 iv_field_of(inv_prefix, domain, id, 1, f); o = as_append_escaped(out, o, f, as_len(f)) // category 58 o = as_append(out, o, "</td><td>" as *u8) 59 iv_field_of(inv_prefix, domain, id, 4, f); o = as_append_escaped(out, o, f, as_len(f)) // location 60 if with_ben == 1 { 61 o = as_append(out, o, "</td><td>" as *u8) 62 iv_field_of(inv_prefix, domain, id, 7, f) // beneficiary 63 if er_is_residuary(f) == 1 { o = as_append(out, o, "(residuary)" as *u8) } else { o = as_append_escaped(out, o, f, as_len(f)) } 64 } 65 o = as_append(out, o, "</td><td class='v'>" as *u8) 66 o = iv_money(out, o, iv_value(inv_prefix, domain, id)) 67 o = as_append(out, o, "</td></tr>" as *u8) 68 return o 69} 70 71// render a per-beneficiary bequest section 72func er_owner_section(inv_prefix: *u8, domain: *u8, owner: *u8, out: *u8, off: i64) -> i64 { 73 var o: i64 = off 74 o = as_append(out, o, "<section class='ben'><h3>" as *u8) 75 if er_is_residuary(owner) == 1 { o = as_append(out, o, "Residuary estate (unassigned)" as *u8) } else { 76 o = as_append(out, o, "Bequeathed to " as *u8) 77 o = as_append_escaped(out, o, owner, as_len(owner)) 78 } 79 o = as_append(out, o, "</h3><table><tr><th>Item</th><th>Category</th><th>Location</th><th>Value</th></tr>" as *u8) 80 let ids: *i64 = sys_mmap(8 * 256) as *i64 81 let n: i64 = iv_list(inv_prefix, domain, ids) 82 var i: i64 = 0 83 while i < n { 84 let ow: *u8 = sys_mmap(64) 85 iv_field_of(inv_prefix, domain, ids[i] as *u8, 7, ow) 86 if er_streq(ow, owner) == 1 { o = er_item_row(inv_prefix, domain, ids[i] as *u8, 0, out, o) } 87 i = i + 1 88 } 89 o = as_append(out, o, "</table><p class='sub'>Subtotal: " as *u8) 90 o = iv_money(out, o, er_owner_total(inv_prefix, domain, owner)) 91 o = as_append(out, o, "</p></section>" as *u8) 92 return o 93} 94 95// render the full Schedule of Assets document (NUL-terminated); returns byte length. 96func er_render_schedule(inv_prefix: *u8, domain: *u8, estate_owner: *u8, out: *u8) -> i64 { 97 var o: i64 = 0 98 o = as_append(out, o, "<!doctype html><html lang='en'><head><meta charset='utf-8'><meta name='viewport' content='width=device-width,initial-scale=1'><title>Schedule of Assets</title><style>body{margin:0;font-family:Georgia,'Times New Roman',serif;color:#1c1c1c;background:#f6f4ef;line-height:1.5}.doc{max-width:720px;margin:0 auto;padding:32px 28px;background:#fff;box-shadow:0 1px 4px rgba(0,0,0,.08)}h1{font-size:1.5rem;margin:0 0 2px;text-align:center}.estof{text-align:center;color:#555;margin:0 0 18px}.summary{background:#f0ece3;border:1px solid #ddd5c6;border-radius:6px;padding:12px 16px;margin:0 0 22px}h3{font-size:1.05rem;border-bottom:1px solid #c9b896;padding-bottom:4px;margin:22px 0 8px}table{border-collapse:collapse;width:100%;font-size:.95rem}th{text-align:left;border-bottom:2px solid #c9b896;padding:5px 8px;color:#555}td{padding:5px 8px;border-bottom:1px solid #ece5d8}td.v{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}.sub{text-align:right;font-weight:700;margin:6px 0 0}.tot{font-size:1.1rem;font-weight:700}.ftr{margin-top:26px;border-top:1px solid #ddd5c6;padding-top:12px;color:#777;font-size:.82rem;text-align:center}</style></head><body><div class='doc'>" as *u8) 99 o = as_append(out, o, "<h1>Schedule of Assets</h1><p class='estof'>Estate of " as *u8) 100 o = as_append_escaped(out, o, estate_owner, as_len(estate_owner)) 101 o = as_append(out, o, "</p>" as *u8) 102 103 let ids: *i64 = sys_mmap(8 * 256) as *i64 104 let n: i64 = iv_list(inv_prefix, domain, ids) 105 let owners: *i64 = sys_mmap(8 * 64) as *i64 106 let no: i64 = er_distinct_owners(inv_prefix, domain, owners) 107 let total: i64 = iv_value_total(inv_prefix, domain) 108 109 o = as_append(out, o, "<div class='summary'><span class='tot'>Total estate value: " as *u8) 110 o = iv_money(out, o, total) 111 o = as_append(out, o, "</span><br>" as *u8) 112 o = iv_num(out, o, n) 113 o = as_append(out, o, " catalogued assets across " as *u8) 114 o = iv_num(out, o, no) 115 o = as_append(out, o, " distribution group(s).</div>" as *u8) 116 117 // named beneficiaries first 118 var i: i64 = 0 119 while i < no { if er_is_residuary(owners[i] as *u8) == 0 { o = er_owner_section(inv_prefix, domain, owners[i] as *u8, out, o) } i = i + 1 } 120 // residuary last 121 i = 0 122 while i < no { if er_is_residuary(owners[i] as *u8) == 1 { o = er_owner_section(inv_prefix, domain, owners[i] as *u8, out, o) } i = i + 1 } 123 124 // full schedule 125 o = as_append(out, o, "<h3>Full schedule</h3><table><tr><th>Item</th><th>Category</th><th>Location</th><th>Beneficiary</th><th>Value</th></tr>" as *u8) 126 i = 0 127 while i < n { o = er_item_row(inv_prefix, domain, ids[i] as *u8, 1, out, o); i = i + 1 } 128 o = as_append(out, o, "<tr><td colspan='4' class='tot'>Total</td><td class='v tot'>" as *u8) 129 o = iv_money(out, o, total) 130 o = as_append(out, o, "</td></tr></table>" as *u8) 131 132 o = as_append(out, o, "<p class='ftr'>Generated by the Nishi inventory engine &mdash; sovereign, no tracking. A tangible-personal-property memorandum for use with your will; review with your estate attorney.</p></div></body></html>" as *u8) 133 out[o] = 0 as u8 134 return o 135}