您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

543 行
25KB

  1. <%
  2. ' Auto-generated Controller: OrderApi
  3. ' Generated on 7/28/2026 2:56:29 PM
  4. ' Generator: generateController.vbs v1.0
  5. '
  6. ' Remember to:
  7. ' 1. Add to app/controllers/autoload_controllers.asp
  8. ' 2. Register in core/lib.ControllerRegistry.asp
  9. ' 3. Add routes in public/Default.asp
  10. Class OrderApiController_Class
  11. Private m_useLayout
  12. Private m_title
  13. Private Sub Class_Initialize()
  14. m_useLayout = False ' this controller returns JSON only, never the shared HTML layout
  15. m_title = "OrderApi"
  16. End Sub
  17. Public Property Get useLayout
  18. useLayout = m_useLayout
  19. End Property
  20. Public Property Let useLayout(v)
  21. m_useLayout = v
  22. End Property
  23. Public Property Get Title
  24. Title = m_title
  25. End Property
  26. Public Property Let Title(v)
  27. m_title = v
  28. End Property
  29. '-------------------------------------------------------------------------------------------------------------------
  30. ' POST: accept the completed SurveyJS order-details form (as JSON) for the order matching ?token=
  31. '-------------------------------------------------------------------------------------------------------------------
  32. Public Sub SubmitOrderDetails()
  33. Response.ContentType = "application/json"
  34. If Request.ServerVariables("REQUEST_METHOD") <> "POST" Then
  35. WriteJsonError "405 Method Not Allowed", "This endpoint only accepts POST."
  36. Exit Sub
  37. End If
  38. Dim token, order
  39. token = Trim(Request.QueryString("token"))
  40. Set order = Nothing
  41. If Len(token) > 0 Then Set order = OrdersRepository().FindByToken(token)
  42. If order Is Nothing Then
  43. WriteJsonError "404 Not Found", "Order not found."
  44. Exit Sub
  45. End If
  46. If order("TokenExpiresAt") < Now() Then
  47. WriteJsonError "410 Gone", "This order link has expired. Please request a new one."
  48. Exit Sub
  49. End If
  50. Dim csrfToken : csrfToken = Request.ServerVariables("HTTP_X_CSRF_TOKEN")
  51. If Not HTMLSecurity().IsValidAntiCSRFToken("Order.Continue", csrfToken) Then
  52. WriteJsonError "403 Forbidden", "Your form session expired. Please refresh the page and try again."
  53. Exit Sub
  54. End If
  55. Dim answers
  56. On Error Resume Next
  57. json().loadJSON GetRawJsonFromRequest()
  58. If Err.Number <> 0 Then
  59. Err.Clear
  60. On Error GoTo 0
  61. WriteJsonError "400 Bad Request", "Could not read the submitted form data."
  62. Exit Sub
  63. End If
  64. On Error GoTo 0
  65. Set answers = json().data
  66. Dim validationError : validationError = ValidateAnswers(answers)
  67. If Len(validationError) > 0 Then
  68. WriteJsonError "400 Bad Request", validationError
  69. Exit Sub
  70. End If
  71. Dim model : Set model = New POBO_OrderDetails
  72. On Error Resume Next
  73. MapOrderDetailsAnswers model, answers
  74. model.SubmittedAt = Now()
  75. If Err.Number <> 0 Then
  76. Err.Clear
  77. On Error GoTo 0
  78. WriteJsonError "400 Bad Request", "The submitted data could not be processed. Please check your entries and try again."
  79. Exit Sub
  80. End If
  81. On Error GoTo 0
  82. On Error Resume Next
  83. OrderDetailsRepository().SaveForOrder order("OrderID"), model
  84. If Err.Number <> 0 Then
  85. Err.Clear
  86. On Error GoTo 0
  87. WriteJsonError "500 Internal Server Error", "Could not save your order details. Please try again."
  88. Exit Sub
  89. End If
  90. On Error GoTo 0
  91. ' Best-effort: the order is already safely persisted at this point, so an SMTP hiccup
  92. ' should not turn a successful submission into a failed one.
  93. SendOrderDetailsEmail order, model
  94. Response.Write "{""success"":true}"
  95. End Sub
  96. '-------------------------------------------------------------------------------------------------------------------
  97. ' Order-confirmation email
  98. '-------------------------------------------------------------------------------------------------------------------
  99. Private Sub SendOrderDetailsEmail(order, model)
  100. On Error Resume Next
  101. Dim smtpPort : smtpPort = GetAppSetting("SmtpPort")
  102. If Not IsNumeric(smtpPort) Then smtpPort = 25
  103. Dim mail : Set mail = CDOEmail()
  104. mail.SMTPServer = GetAppSetting("SmtpServer")
  105. mail.SMTPPort = CInt(smtpPort)
  106. mail.SMTPUsername = GetAppSetting("SmtpUsername")
  107. mail.SMTPPassword = GetAppSetting("SmtpPassword")
  108. mail.SMTPUseSSL = (LCase(GetAppSetting("SmtpUseSSL")) = "true")
  109. mail.From = GetAppSetting("SmtpFromAddress")
  110. mail.Subject = "Your Purple Envelope order details - Jurisdiction " & order("JurisdictionNumber")
  111. mail.IsBodyHTML = True
  112. mail.Body = BuildOrderDetailsEmailBody(order, model)
  113. mail.AddRecipient "To", order("Email")
  114. mail.Send
  115. Err.Clear
  116. On Error GoTo 0
  117. End Sub
  118. Private Function BuildOrderDetailsEmailBody(order, model)
  119. Dim html
  120. html = "<!doctype html><html><body style=""margin:0; padding:0; background:#faf7fd; font-family:Arial, Helvetica, sans-serif;"">" & _
  121. "<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"" style=""background:#faf7fd; padding:24px 0;""><tr><td align=""center"">" & _
  122. "<table role=""presentation"" width=""600"" cellpadding=""0"" cellspacing=""0"" style=""background:#ffffff; border-radius:12px; overflow:hidden; box-shadow:0 4px 16px rgba(36,16,58,0.08);"">" & _
  123. "<tr><td style=""background:#24103a; padding:24px 32px;"">" & _
  124. "<span style=""color:#ffffff; font-weight:700; font-size:18px;"">KCI Purple Envelope Order Confirmation</span>" & _
  125. "</td></tr>" & _
  126. "<tr><td style=""padding:32px;"">" & _
  127. "<div style=""color:#7c3bc0; font-weight:800; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;"">Order Received</div>" & _
  128. "<h1 style=""color:#201a27; font-size:22px; margin:6px 0 4px; font-family:Arial, Helvetica, sans-serif;"">Thanks! We've received your order details.</h1>" & _
  129. "<p style=""color:#6d6574; font-size:13px; margin:0 0 8px;"">Jurisdiction number <strong style=""color:#201a27;"">" & H(order("JurisdictionNumber")) & "</strong>" & _
  130. " &middot; submitted " & H(EmailDate(model.SubmittedAt)) & "</p>"
  131. html = html & EmailSection("Contact Information", _
  132. EmailRow("Contact Name", model.ContactName) & _
  133. EmailRow("Municipality", model.Municipality) & _
  134. EmailRow("Phone", model.Phone))
  135. If IsTrue(model.PurpleWantsQuote) Then
  136. Dim purpleBlueProviderLine
  137. purpleBlueProviderLine = LabelPurpleBlueProvider(model.PurpleBlueProvider)
  138. If purpleBlueProviderLine = "Other" And Len(Trim(model.PurpleBlueProviderOther & "")) > 0 Then
  139. purpleBlueProviderLine = model.PurpleBlueProviderOther
  140. End If
  141. html = html & EmailSection("Purple Ballot Envelopes", _
  142. EmailRow("Envelope stock", LabelEnvelopeStock(model.PurpleEnvelopeStock)) & _
  143. EmailRow("Print option", LabelPrintOption(model.PurplePrintOption)) & _
  144. EmailRow("Also wants KCI blue envelopes", EmailYesNo(model.PurpleWantsBlueEnvelopes)) & _
  145. EmailRow("Blue envelope provider", purpleBlueProviderLine) & _
  146. EmailRow("Print style", LabelPrintStyle(model.PurplePrintStyle)) & _
  147. EmailRow("Color coding by", LabelColorCodingBy(model.PurpleColorCodingBy)) & _
  148. EmailRow("Number of precincts", model.PurplePrecinctCount) & _
  149. EmailRow("Colors requested", model.PurpleColorNames) & _
  150. EmailRow("Track with TrackMI Ballot", EmailYesNo(model.PurpleTrackMIBallot)) & _
  151. EmailRow("Extra envelopes requested", model.PurpleExtraEnvelopeQty))
  152. End If
  153. If IsTrue(model.BlueWantsQuote) Then
  154. ' City/permit number are always collected for an own-organization permit - a
  155. ' permit lookup can't be done from the nonprofit authorization code alone, so
  156. ' that code is additional information when nonprofit status is Yes, not a
  157. ' replacement for city/permit number.
  158. Dim bluePermitLine
  159. bluePermitLine = ""
  160. If LabelPermitOwnership(model.BluePermitOwnership) = "My organization's permit" Then
  161. bluePermitLine = EmailRow("City of permit holder", model.BluePermitCity) & _
  162. EmailRow("Permit number", model.BluePermitNumber)
  163. If IsTrue(model.BlueHasNonprofitStatus) Then
  164. bluePermitLine = bluePermitLine & EmailRow("Nonprofit authorization code", model.BlueNonprofitAuthCode)
  165. End If
  166. End If
  167. html = html & EmailSection("Blue AV Envelopes", _
  168. EmailRow("Print permit", EmailYesNo(model.BluePrintPermit)) & _
  169. EmailRow("Permit ownership", LabelPermitOwnership(model.BluePermitOwnership)) & _
  170. EmailRow("Confirmed nonprofit status with USPS", EmailYesNo(model.BlueHasNonprofitStatus)) & _
  171. bluePermitLine)
  172. End If
  173. If IsTrue(model.MailingWantsService) Then
  174. html = html & EmailSection("Ballot Mailing Service", _
  175. EmailRow("Postage", LabelPostageOption(model.MailingPostageOption)) & _
  176. EmailRow("Nonprofit status with USPS", LabelNonprofitStatus(model.MailingHasNonprofitStatus)) & _
  177. EmailRow("Estimated quantity", model.MailingEstimatedQuantity) & _
  178. EmailRow("Preferred pickup date", EmailDate(model.MailingPickupDate)))
  179. End If
  180. If NumOrZero(model.SecrecySleevesQty) > 0 Or NumOrZero(model.IVotedStickerRolls) > 0 Or NumOrZero(model.FutureVoterStickerRolls) > 0 Or Len(Trim(model.SpecialRequests & "")) > 0 Then
  181. html = html & EmailSection("Additional Election Items", _
  182. EmailRow("Secrecy sleeves (quantity)", model.SecrecySleevesQty) & _
  183. EmailRow("""I Voted"" stickers (rolls of 250)", model.IVotedStickerRolls) & _
  184. EmailRow("""Future Voter"" stickers (rolls of 500)", model.FutureVoterStickerRolls) & _
  185. EmailRow("Special requests", model.SpecialRequests))
  186. End If
  187. html = html & "<p style=""color:#6d6574; font-size:12px; margin-top:24px;"">Questions about this order? Just reply to this email.</p>" & _
  188. "</td></tr>" & _
  189. "<tr><td style=""background:#f0e7f8; padding:16px 32px; text-align:center;"">" & _
  190. "<span style=""color:#6529a0; font-size:11px;"">Purple Envelope &middot; Addressing &amp; Barcoding</span>" & _
  191. "</td></tr>" & _
  192. "</table></td></tr></table></body></html>"
  193. BuildOrderDetailsEmailBody = html
  194. End Function
  195. Private Function EmailSection(sectionTitle, rowsHtml)
  196. If Len(rowsHtml) = 0 Then
  197. EmailSection = ""
  198. Else
  199. EmailSection = "<h2 style=""color:#4d1d78; font-size:14px; margin:24px 0 8px; padding-top:16px; border-top:1px solid #f0e7f8; font-family:Arial, Helvetica, sans-serif;"">" & _
  200. H(sectionTitle) & "</h2>" & _
  201. "<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"">" & rowsHtml & "</table>"
  202. End If
  203. End Function
  204. Private Function EmailRow(label, value)
  205. If Len(Trim(value & "")) = 0 Then
  206. EmailRow = ""
  207. Else
  208. EmailRow = "<tr>" & _
  209. "<td style=""padding:6px 0; color:#6d6574; font-size:13px; width:45%; vertical-align:top;"">" & H(label) & "</td>" & _
  210. "<td style=""padding:6px 0; color:#201a27; font-size:13px; font-weight:600;"">" & H(value) & "</td>" & _
  211. "</tr>"
  212. End If
  213. End Function
  214. ' Null-safe boolean check for gating whole sections - a section's top-level "do you want
  215. ' this?" question isn't marked required client-side, so it may be missing (Null) rather
  216. ' than explicitly false.
  217. Private Function IsTrue(v)
  218. If IsNull(v) Then
  219. IsTrue = False
  220. Else
  221. IsTrue = CBool(v)
  222. End If
  223. End Function
  224. Private Function EmailYesNo(v)
  225. If IsNull(v) Then
  226. EmailYesNo = ""
  227. ElseIf CBool(v) Then
  228. EmailYesNo = "Yes"
  229. Else
  230. EmailYesNo = "No"
  231. End If
  232. End Function
  233. Private Function EmailDate(v)
  234. If IsNull(v) Then
  235. EmailDate = ""
  236. Else
  237. On Error Resume Next
  238. EmailDate = MonthName(Month(v)) & " " & Day(v) & ", " & Year(v)
  239. If Err.Number <> 0 Then EmailDate = ""
  240. Err.Clear
  241. On Error GoTo 0
  242. End If
  243. End Function
  244. Private Function NumOrZero(v)
  245. If IsNull(v) Or Not IsNumeric(v) Then
  246. NumOrZero = 0
  247. Else
  248. NumOrZero = CDbl(v)
  249. End If
  250. End Function
  251. ' Human-readable labels for the coded choice values written by continue.asp's SurveyJS
  252. ' model - falls back to the raw code for anything unrecognized rather than hiding it.
  253. Private Function LabelPrintOption(code)
  254. Select Case CStr(code & "")
  255. Case "AddressesAndPermit" : LabelPrintOption = "Addresses and state of Michigan permit"
  256. Case "PermitOnly" : LabelPrintOption = "State of Michigan permit only"
  257. Case Else : LabelPrintOption = CStr(code & "")
  258. End Select
  259. End Function
  260. Private Function LabelPurpleBlueProvider(code)
  261. Select Case CStr(code & "")
  262. Case "ElectionSource" : LabelPurpleBlueProvider = "ElectionSource"
  263. Case "PSI" : LabelPurpleBlueProvider = "PSI"
  264. Case "Spectrum" : LabelPurpleBlueProvider = "Spectrum"
  265. Case "Other" : LabelPurpleBlueProvider = "Other"
  266. Case Else : LabelPurpleBlueProvider = CStr(code & "")
  267. End Select
  268. End Function
  269. Private Function LabelPermitOwnership(code)
  270. Select Case CStr(code & "")
  271. Case "KCIPermit" : LabelPermitOwnership = "KCI permit"
  272. Case "OwnPermit" : LabelPermitOwnership = "My organization's permit"
  273. Case Else : LabelPermitOwnership = CStr(code & "")
  274. End Select
  275. End Function
  276. Private Function LabelEnvelopeStock(code)
  277. Select Case CStr(code & "")
  278. Case "KCIStock" : LabelEnvelopeStock = "KCI's stock"
  279. Case "OwnStock" : LabelEnvelopeStock = "My own stock"
  280. Case Else : LabelEnvelopeStock = CStr(code & "")
  281. End Select
  282. End Function
  283. Private Function LabelPrintStyle(code)
  284. Select Case CStr(code & "")
  285. Case "ColorCoding" : LabelPrintStyle = "Color Coding"
  286. Case "BlackOnly" : LabelPrintStyle = "Black Ink Only"
  287. Case Else : LabelPrintStyle = CStr(code & "")
  288. End Select
  289. End Function
  290. Private Function LabelColorCodingBy(code)
  291. Select Case CStr(code & "")
  292. Case "Precinct" : LabelColorCodingBy = "Precinct"
  293. Case "Election" : LabelColorCodingBy = "Election"
  294. Case Else : LabelColorCodingBy = CStr(code & "")
  295. End Select
  296. End Function
  297. Private Function LabelPostageOption(code)
  298. Select Case CStr(code & "")
  299. Case "FirstClass" : LabelPostageOption = "Yes, at First Class Rate ($0.721/pc.)"
  300. Case "NonprofitRate" : LabelPostageOption = "Yes, at Nonprofit Rate ($0.263/pc.)"
  301. Case "PresortStandard" : LabelPostageOption = "Yes, at Presort Standard Rate ($0.473/pc.)"
  302. Case "No" : LabelPostageOption = "No"
  303. Case Else : LabelPostageOption = CStr(code & "")
  304. End Select
  305. End Function
  306. Private Function LabelNonprofitStatus(code)
  307. Select Case CStr(code & "")
  308. Case "Yes" : LabelNonprofitStatus = "Yes"
  309. Case "No" : LabelNonprofitStatus = "No"
  310. Case "NotSure" : LabelNonprofitStatus = "I'm not sure"
  311. Case Else : LabelNonprofitStatus = CStr(code & "")
  312. End Select
  313. End Function
  314. '-------------------------------------------------------------------------------------------------------------------
  315. ' Re-validates the submission server-side, mirroring the SurveyJS required/enum rules in
  316. ' continue.asp - the client-side checks are a UX convenience, not something the server can
  317. ' trust. Returns "" if valid, or a "; "-joined list of validation error messages.
  318. '-------------------------------------------------------------------------------------------------------------------
  319. Private Function ValidateAnswers(answers)
  320. Dim errors() : ReDim errors(-1)
  321. RequireNonEmptyString errors, answers, "ContactName", "Contact name is required."
  322. RequireNonEmptyString errors, answers, "Municipality", "Municipality is required."
  323. RequireNonEmptyString errors, answers, "Phone", "Phone number is required."
  324. RequireEnum errors, answers, "PurpleEnvelopeStock", Array("KCIStock", "OwnStock")
  325. RequireEnum errors, answers, "PurplePrintOption", Array("AddressesAndPermit", "PermitOnly")
  326. RequireEnum errors, answers, "PurpleBlueProvider", Array("ElectionSource", "PSI", "Spectrum", "Other")
  327. RequireEnum errors, answers, "PurplePrintStyle", Array("ColorCoding", "BlackOnly")
  328. RequireEnum errors, answers, "PurpleColorCodingBy", Array("Precinct", "Election")
  329. RequireEnum errors, answers, "BluePermitOwnership", Array("KCIPermit", "OwnPermit")
  330. RequireEnum errors, answers, "MailingPostageOption", Array("FirstClass", "NonprofitRate", "PresortStandard", "No")
  331. RequireEnum errors, answers, "MailingHasNonprofitStatus", Array("Yes", "No", "NotSure")
  332. RequireBoolean errors, answers, "PurpleWantsQuote"
  333. RequireBoolean errors, answers, "PurpleWantsBlueEnvelopes"
  334. RequireBoolean errors, answers, "PurpleTrackMIBallot"
  335. RequireBoolean errors, answers, "BlueWantsQuote"
  336. RequireBoolean errors, answers, "BluePrintPermit"
  337. RequireBoolean errors, answers, "BlueHasNonprofitStatus"
  338. RequireBoolean errors, answers, "MailingWantsService"
  339. RequireNonNegativeInteger errors, answers, "PurplePrecinctCount"
  340. RequireNonNegativeInteger errors, answers, "PurpleExtraEnvelopeQty"
  341. RequireNonNegativeInteger errors, answers, "MailingEstimatedQuantity"
  342. RequireNonNegativeInteger errors, answers, "SecrecySleevesQty"
  343. RequireNonNegativeInteger errors, answers, "IVotedStickerRolls"
  344. RequireNonNegativeInteger errors, answers, "FutureVoterStickerRolls"
  345. RequireValidDate errors, answers, "MailingPickupDate"
  346. If UBound(errors) >= 0 Then
  347. ValidateAnswers = Join(errors, "; ")
  348. Else
  349. ValidateAnswers = ""
  350. End If
  351. End Function
  352. Private Sub AddValidationError(ByRef errors, msg)
  353. ReDim Preserve errors(UBound(errors) + 1)
  354. errors(UBound(errors)) = msg
  355. End Sub
  356. ' Required on the client (page 1) - re-checked here since the client can't be trusted.
  357. Private Sub RequireNonEmptyString(ByRef errors, answers, key, msg)
  358. Dim v : v = AnswerValue(answers, key)
  359. If IsNull(v) Or Len(Trim(v & "")) = 0 Then AddValidationError errors, msg
  360. End Sub
  361. ' Only checked when present - these questions are conditionally hidden by visibleIf, so a
  362. ' missing value just means the question wasn't shown, not an invalid submission.
  363. Private Sub RequireEnum(ByRef errors, answers, key, allowedValues)
  364. Dim v : v = AnswerValue(answers, key)
  365. If Not IsNull(v) Then
  366. Dim found : found = False
  367. Dim i
  368. For i = 0 To UBound(allowedValues)
  369. If CStr(v) = allowedValues(i) Then found = True
  370. Next
  371. If Not found Then AddValidationError errors, key & " has an invalid value."
  372. End If
  373. End Sub
  374. Private Sub RequireBoolean(ByRef errors, answers, key)
  375. Dim v : v = AnswerValue(answers, key)
  376. If Not IsNull(v) Then
  377. If TypeName(v) <> "Boolean" Then AddValidationError errors, key & " must be true or false."
  378. End If
  379. End Sub
  380. Private Sub RequireNonNegativeInteger(ByRef errors, answers, key)
  381. Dim v : v = AnswerValue(answers, key)
  382. If Not IsNull(v) Then
  383. If Not IsNumeric(v) Then
  384. AddValidationError errors, key & " must be a number."
  385. ElseIf CDbl(v) < 0 Then
  386. AddValidationError errors, key & " cannot be negative."
  387. ElseIf CDbl(v) <> Int(CDbl(v)) Then
  388. AddValidationError errors, key & " must be a whole number."
  389. End If
  390. End If
  391. End Sub
  392. Private Sub RequireValidDate(ByRef errors, answers, key)
  393. Dim v : v = AnswerValue(answers, key)
  394. If Not IsNull(v) Then
  395. If Len(Trim(v & "")) > 0 And Not IsDate(v) Then
  396. AddValidationError errors, key & " is not a valid date."
  397. End If
  398. End If
  399. End Sub
  400. '-------------------------------------------------------------------------------------------------------------------
  401. ' Private helpers
  402. '-------------------------------------------------------------------------------------------------------------------
  403. Private Sub MapOrderDetailsAnswers(ByRef model, answers)
  404. ' Contact
  405. model.ContactName = AnswerValue(answers, "ContactName")
  406. model.Municipality = AnswerValue(answers, "Municipality")
  407. model.Phone = AnswerValue(answers, "Phone")
  408. ' Purple envelope
  409. model.PurpleWantsQuote = AnswerValue(answers, "PurpleWantsQuote")
  410. model.PurpleEnvelopeStock = AnswerValue(answers, "PurpleEnvelopeStock")
  411. model.PurplePrintOption = AnswerValue(answers, "PurplePrintOption")
  412. model.PurpleWantsBlueEnvelopes = AnswerValue(answers, "PurpleWantsBlueEnvelopes")
  413. model.PurpleBlueProvider = AnswerValue(answers, "PurpleBlueProvider")
  414. model.PurpleBlueProviderOther = AnswerValue(answers, "PurpleBlueProviderOther")
  415. model.PurplePrintStyle = AnswerValue(answers, "PurplePrintStyle")
  416. model.PurpleColorCodingBy = AnswerValue(answers, "PurpleColorCodingBy")
  417. model.PurplePrecinctCount = AnswerValue(answers, "PurplePrecinctCount")
  418. model.PurpleColorNames = AnswerValue(answers, "PurpleColorNames")
  419. model.PurpleTrackMIBallot = AnswerValue(answers, "PurpleTrackMIBallot")
  420. model.PurpleExtraEnvelopeQty = AnswerValue(answers, "PurpleExtraEnvelopeQty")
  421. ' Blue envelope
  422. model.BlueWantsQuote = AnswerValue(answers, "BlueWantsQuote")
  423. model.BluePrintPermit = AnswerValue(answers, "BluePrintPermit")
  424. model.BluePermitOwnership = AnswerValue(answers, "BluePermitOwnership")
  425. model.BlueHasNonprofitStatus = AnswerValue(answers, "BlueHasNonprofitStatus")
  426. model.BlueNonprofitAuthCode = AnswerValue(answers, "BlueNonprofitAuthCode")
  427. model.BluePermitCity = AnswerValue(answers, "BluePermitCity")
  428. model.BluePermitNumber = AnswerValue(answers, "BluePermitNumber")
  429. ' Mailing service
  430. model.MailingWantsService = AnswerValue(answers, "MailingWantsService")
  431. model.MailingPostageOption = AnswerValue(answers, "MailingPostageOption")
  432. model.MailingHasNonprofitStatus = AnswerValue(answers, "MailingHasNonprofitStatus")
  433. model.MailingEstimatedQuantity = AnswerValue(answers, "MailingEstimatedQuantity")
  434. model.MailingPickupDate = AnswerValue(answers, "MailingPickupDate")
  435. ' Additional items
  436. model.SecrecySleevesQty = AnswerValue(answers, "SecrecySleevesQty")
  437. model.IVotedStickerRolls = AnswerValue(answers, "IVotedStickerRolls")
  438. model.FutureVoterStickerRolls = AnswerValue(answers, "FutureVoterStickerRolls")
  439. model.SpecialRequests = AnswerValue(answers, "SpecialRequests")
  440. End Sub
  441. ' Returns the value for key in a parsed aspJSON Dictionary, or Null if the question was
  442. ' skipped (hidden by visibleIf logic and so never included in SurveyJS's result data).
  443. Private Function AnswerValue(answers, key)
  444. If answers.Exists(key) Then
  445. AnswerValue = answers.Item(key)
  446. Else
  447. AnswerValue = Null
  448. End If
  449. End Function
  450. Private Sub WriteJsonError(statusLine, message)
  451. Response.Status = statusLine
  452. Response.Write "{""success"":false,""error"":" & JsonEncodeString(message) & "}"
  453. End Sub
  454. Private Function JsonEncodeString(s)
  455. Dim out : out = s
  456. out = Replace(out, "\", "\\")
  457. out = Replace(out, """", "\""")
  458. out = Replace(out, Chr(10), "\n")
  459. out = Replace(out, Chr(13), "\r")
  460. JsonEncodeString = """" & out & """"
  461. End Function
  462. End Class
  463. ' Singleton instance
  464. Dim OrderApiController_Class__Singleton
  465. Function OrderApiController()
  466. If IsEmpty(OrderApiController_Class__Singleton) Then
  467. Set OrderApiController_Class__Singleton = New OrderApiController_Class
  468. End If
  469. Set OrderApiController = OrderApiController_Class__Singleton
  470. End Function
  471. %>

Powered by TurnKey Linux.