mattrguerra/meridian-ops-boardmainPrivate on GitHub, published here in full

projection.ts

Language TypeScript4.0 KB125 lines

packages/plinth-client/src/projection.ts

  1. /**
  2. * What the sync keeps from a Plinth order.
  3. *
  4. * Not the Northgate rules. The agency's Plinth schema notes classify fields for a
  5. * client-facing integration where an unverified caller might see the response;
  6. * hence their very aggressive `strip` list. This dashboard is internal, behind
  7. * auth, read by a small team who already have Plinth logins. Those constraints do
  8. * not transfer.
  9. *
  10. * The line used here is the team's existing data-handling rule:
  11. *
  12. * "Client names in an order context are fine. Contact details, addresses, and
  13. * payment information are not."
  14. *
  15. * There is a practical reason on top of the policy one. The snapshot database is
  16. * a new copy of customer data in a new place. Keeping a name and a company costs
  17. * nothing and makes every row readable at a glance. Keeping billing addresses,
  18. * emails, and phone numbers turns this dashboard's storage into a secondary PII
  19. * store that has to be secured, backed up, and eventually deleted, in exchange
  20. * for fields no panel displays.
  21. *
  22. * If a panel ever needs a dropped field, add it here deliberately rather than
  23. * widening the projection "just in case."
  24. */
  25. /** Order-level fields the snapshot keeps. */
  26. export const ORDER_FIELDS = [
  27. 'order_ref',
  28. 'status_code',
  29. 'status_label',
  30. 'closed_on', // NOTE: order PLACED datetime, despite the name.
  31. 'grand_total',
  32. 'subtotal',
  33. 'shipping_total',
  34. 'discount_total',
  35. 'ship_weight',
  36. 'account_ref',
  37. 'account_kind',
  38. 'shop',
  39. 'dept_ref',
  40. 'customer_group', // Retail / Palladium Partner / ...: segment, not PII
  41. 'sales_rep', // null on every order sampled so far
  42. 'press_name', // the VENDOR, not a designer
  43. 'production_owner', // order-level assignment
  44. 'account_owner', // note the spelling; also per product line (see PRODUCT_FIELDS)
  45. 'proof_approver',
  46. 'tracking_no',
  47. 'carier_name', // sic
  48. 'purchase_order',
  49. ] as const
  50. /** Identifying-but-useful. Kept per the data-handling rule above: names in an order context. */
  51. export const ORDER_IDENTITY_FIELDS = [
  52. 'first_name',
  53. 'last_name',
  54. 'company_name',
  55. 'ship_company',
  56. ] as const
  57. /** Product-line fields. Where the real design/production status lives. */
  58. export const PRODUCT_FIELDS = [
  59. 'line_ref',
  60. 'item_ref',
  61. 'line_status',
  62. 'line_status_code', // preferred over the name
  63. 'production_owner', // the designer
  64. 'account_owner', // the CS rep (note the spelling)
  65. 'item_name',
  66. 'qty',
  67. 'unit_price',
  68. 'item_size',
  69. 'kit_flag',
  70. 'storage_days',
  71. ] as const
  72. /**
  73. * Explicitly dropped. Listed rather than merely omitted so the decision is
  74. * visible and reversible, and so nobody re-adds them by accident.
  75. */
  76. export const DROPPED_FIELDS = {
  77. contact: ['email', 'phone'],
  78. addresses: [
  79. 'ship_name',
  80. 'ship_street',
  81. 'ship_district',
  82. 'ship_city',
  83. 'ship_postcode',
  84. 'ship_region',
  85. 'ship_region_code',
  86. 'ship_country',
  87. 'bill_name',
  88. 'bill_company',
  89. 'bill_street',
  90. 'bill_district',
  91. 'bill_city',
  92. 'bill_postcode',
  93. 'bill_region',
  94. 'bill_region_code',
  95. 'bill_country',
  96. ],
  97. payment: ['tax_total'],
  98. /**
  99. * Artwork URL sets. Dropped for size, not sensitivity: a five-panel booth
  100. * carries ~36 CloudFront URLs across customer-supplied, print-ready, and
  101. * thumbnail variants. Nothing on the dashboard renders them, and persisting
  102. * them would multiply snapshot size for no gain. Fetch on demand from a
  103. * detail view if one is ever built.
  104. */
  105. artwork: ['printfile_info'],
  106. } as const
  107. const KEEP = new Set<string>([...ORDER_FIELDS, ...ORDER_IDENTITY_FIELDS])
  108. const KEEP_PRODUCT = new Set<string>(PRODUCT_FIELDS)
  109. export function projectOrder(raw: Record<string, unknown>): Record<string, unknown> {
  110. const out: Record<string, unknown> = {}
  111. for (const k of Object.keys(raw)) if (KEEP.has(k)) out[k] = raw[k]
  112. return out
  113. }
  114. export function projectProduct(raw: Record<string, unknown>): Record<string, unknown> {
  115. const out: Record<string, unknown> = {}
  116. for (const k of Object.keys(raw)) if (KEEP_PRODUCT.has(k)) out[k] = raw[k]
  117. return out
  118. }