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

542 行
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=""display:inline-block; width:34px; height:34px; border-radius:50%; background:#7c3bc0; color:#fff; font-weight:800; font-size:12px; text-align:center; line-height:34px; vertical-align:middle;"">PE</span>" & _
  125. "<span style=""color:#ffffff; font-weight:700; font-size:16px; margin-left:10px; vertical-align:middle;"">Purple Envelope</span>" & _
  126. "<div style=""color:#dcc9ef; font-size:11px; margin-top:2px;"">Addressing &amp; Barcoding</div>" & _
  127. "</td></tr>" & _
  128. "<tr><td style=""padding:32px;"">" & _
  129. "<div style=""color:#7c3bc0; font-weight:800; font-size:11px; letter-spacing:0.06em; text-transform:uppercase;"">Order Received</div>" & _
  130. "<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>" & _
  131. "<p style=""color:#6d6574; font-size:13px; margin:0 0 8px;"">Jurisdiction number <strong style=""color:#201a27;"">" & H(order("JurisdictionNumber")) & "</strong>" & _
  132. " &middot; submitted " & H(EmailDate(model.SubmittedAt)) & "</p>"
  133. html = html & EmailSection("Contact Information", _
  134. EmailRow("Contact Name", model.ContactName) & _
  135. EmailRow("Municipality", model.Municipality) & _
  136. EmailRow("Phone", model.Phone))
  137. If IsTrue(model.PurpleWantsQuote) Then
  138. Dim purpleBlueProviderLine
  139. purpleBlueProviderLine = LabelPurpleBlueProvider(model.PurpleBlueProvider)
  140. If purpleBlueProviderLine = "Other" And Len(Trim(model.PurpleBlueProviderOther & "")) > 0 Then
  141. purpleBlueProviderLine = model.PurpleBlueProviderOther
  142. End If
  143. html = html & EmailSection("Purple Ballot Envelopes", _
  144. EmailRow("Envelope stock", LabelEnvelopeStock(model.PurpleEnvelopeStock)) & _
  145. EmailRow("Print option", LabelPrintOption(model.PurplePrintOption)) & _
  146. EmailRow("Also wants KCI blue envelopes", EmailYesNo(model.PurpleWantsBlueEnvelopes)) & _
  147. EmailRow("Blue envelope provider", purpleBlueProviderLine) & _
  148. EmailRow("Print style", LabelPrintStyle(model.PurplePrintStyle)) & _
  149. EmailRow("Color coding by", LabelColorCodingBy(model.PurpleColorCodingBy)) & _
  150. EmailRow("Number of precincts", model.PurplePrecinctCount) & _
  151. EmailRow("Colors requested", model.PurpleColorNames) & _
  152. EmailRow("Track with TrackMI Ballot", EmailYesNo(model.PurpleTrackMIBallot)) & _
  153. EmailRow("Extra envelopes requested", model.PurpleExtraEnvelopeQty))
  154. End If
  155. If IsTrue(model.BlueWantsQuote) Then
  156. Dim bluePermitLine
  157. bluePermitLine = ""
  158. If LabelPermitOwnership(model.BluePermitOwnership) = "My organization's permit" Then
  159. If IsTrue(model.BlueHasNonprofitStatus) Then
  160. bluePermitLine = EmailRow("Nonprofit authorization code", model.BlueNonprofitAuthCode)
  161. Else
  162. bluePermitLine = EmailRow("City of permit holder", model.BluePermitCity) & _
  163. EmailRow("Permit number", model.BluePermitNumber)
  164. End If
  165. End If
  166. html = html & EmailSection("Blue AV Envelopes", _
  167. EmailRow("Print permit", EmailYesNo(model.BluePrintPermit)) & _
  168. EmailRow("Permit ownership", LabelPermitOwnership(model.BluePermitOwnership)) & _
  169. EmailRow("Confirmed nonprofit status with USPS", EmailYesNo(model.BlueHasNonprofitStatus)) & _
  170. bluePermitLine)
  171. End If
  172. If IsTrue(model.MailingWantsService) Then
  173. html = html & EmailSection("Ballot Mailing Service", _
  174. EmailRow("Postage", LabelPostageOption(model.MailingPostageOption)) & _
  175. EmailRow("Nonprofit status with USPS", LabelNonprofitStatus(model.MailingHasNonprofitStatus)) & _
  176. EmailRow("Estimated quantity", model.MailingEstimatedQuantity) & _
  177. EmailRow("Preferred pickup date", EmailDate(model.MailingPickupDate)))
  178. End If
  179. If NumOrZero(model.SecrecySleevesQty) > 0 Or NumOrZero(model.IVotedStickerRolls) > 0 Or NumOrZero(model.FutureVoterStickerRolls) > 0 Or Len(Trim(model.SpecialRequests & "")) > 0 Then
  180. html = html & EmailSection("Additional Election Items", _
  181. EmailRow("Secrecy sleeves (quantity)", model.SecrecySleevesQty) & _
  182. EmailRow("""I Voted"" stickers (rolls of 250)", model.IVotedStickerRolls) & _
  183. EmailRow("""Future Voter"" stickers (rolls of 500)", model.FutureVoterStickerRolls) & _
  184. EmailRow("Special requests", model.SpecialRequests))
  185. End If
  186. html = html & "<p style=""color:#6d6574; font-size:12px; margin-top:24px;"">Questions about this order? Just reply to this email.</p>" & _
  187. "</td></tr>" & _
  188. "<tr><td style=""background:#f0e7f8; padding:16px 32px; text-align:center;"">" & _
  189. "<span style=""color:#6529a0; font-size:11px;"">Purple Envelope &middot; Addressing &amp; Barcoding</span>" & _
  190. "</td></tr>" & _
  191. "</table></td></tr></table></body></html>"
  192. BuildOrderDetailsEmailBody = html
  193. End Function
  194. Private Function EmailSection(sectionTitle, rowsHtml)
  195. If Len(rowsHtml) = 0 Then
  196. EmailSection = ""
  197. Else
  198. 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;"">" & _
  199. H(sectionTitle) & "</h2>" & _
  200. "<table role=""presentation"" width=""100%"" cellpadding=""0"" cellspacing=""0"">" & rowsHtml & "</table>"
  201. End If
  202. End Function
  203. Private Function EmailRow(label, value)
  204. If Len(Trim(value & "")) = 0 Then
  205. EmailRow = ""
  206. Else
  207. EmailRow = "<tr>" & _
  208. "<td style=""padding:6px 0; color:#6d6574; font-size:13px; width:45%; vertical-align:top;"">" & H(label) & "</td>" & _
  209. "<td style=""padding:6px 0; color:#201a27; font-size:13px; font-weight:600;"">" & H(value) & "</td>" & _
  210. "</tr>"
  211. End If
  212. End Function
  213. ' Null-safe boolean check for gating whole sections - a section's top-level "do you want
  214. ' this?" question isn't marked required client-side, so it may be missing (Null) rather
  215. ' than explicitly false.
  216. Private Function IsTrue(v)
  217. If IsNull(v) Then
  218. IsTrue = False
  219. Else
  220. IsTrue = CBool(v)
  221. End If
  222. End Function
  223. Private Function EmailYesNo(v)
  224. If IsNull(v) Then
  225. EmailYesNo = ""
  226. ElseIf CBool(v) Then
  227. EmailYesNo = "Yes"
  228. Else
  229. EmailYesNo = "No"
  230. End If
  231. End Function
  232. Private Function EmailDate(v)
  233. If IsNull(v) Then
  234. EmailDate = ""
  235. Else
  236. On Error Resume Next
  237. EmailDate = MonthName(Month(v)) & " " & Day(v) & ", " & Year(v)
  238. If Err.Number <> 0 Then EmailDate = ""
  239. Err.Clear
  240. On Error GoTo 0
  241. End If
  242. End Function
  243. Private Function NumOrZero(v)
  244. If IsNull(v) Or Not IsNumeric(v) Then
  245. NumOrZero = 0
  246. Else
  247. NumOrZero = CDbl(v)
  248. End If
  249. End Function
  250. ' Human-readable labels for the coded choice values written by continue.asp's SurveyJS
  251. ' model - falls back to the raw code for anything unrecognized rather than hiding it.
  252. Private Function LabelPrintOption(code)
  253. Select Case CStr(code & "")
  254. Case "AddressesAndPermit" : LabelPrintOption = "Addresses and state of Michigan permit"
  255. Case "PermitOnly" : LabelPrintOption = "State of Michigan permit only"
  256. Case Else : LabelPrintOption = CStr(code & "")
  257. End Select
  258. End Function
  259. Private Function LabelPurpleBlueProvider(code)
  260. Select Case CStr(code & "")
  261. Case "ElectionSource" : LabelPurpleBlueProvider = "ElectionSource"
  262. Case "PSI" : LabelPurpleBlueProvider = "PSI"
  263. Case "Spectrum" : LabelPurpleBlueProvider = "Spectrum"
  264. Case "Other" : LabelPurpleBlueProvider = "Other"
  265. Case Else : LabelPurpleBlueProvider = CStr(code & "")
  266. End Select
  267. End Function
  268. Private Function LabelPermitOwnership(code)
  269. Select Case CStr(code & "")
  270. Case "KCIPermit" : LabelPermitOwnership = "KCI permit"
  271. Case "OwnPermit" : LabelPermitOwnership = "My organization's permit"
  272. Case Else : LabelPermitOwnership = CStr(code & "")
  273. End Select
  274. End Function
  275. Private Function LabelEnvelopeStock(code)
  276. Select Case CStr(code & "")
  277. Case "KCIStock" : LabelEnvelopeStock = "KCI's stock"
  278. Case "OwnStock" : LabelEnvelopeStock = "My own stock"
  279. Case Else : LabelEnvelopeStock = CStr(code & "")
  280. End Select
  281. End Function
  282. Private Function LabelPrintStyle(code)
  283. Select Case CStr(code & "")
  284. Case "ColorCoding" : LabelPrintStyle = "Color Coding"
  285. Case "BlackOnly" : LabelPrintStyle = "Black Ink Only"
  286. Case Else : LabelPrintStyle = CStr(code & "")
  287. End Select
  288. End Function
  289. Private Function LabelColorCodingBy(code)
  290. Select Case CStr(code & "")
  291. Case "Precinct" : LabelColorCodingBy = "Precinct"
  292. Case "Election" : LabelColorCodingBy = "Election"
  293. Case Else : LabelColorCodingBy = CStr(code & "")
  294. End Select
  295. End Function
  296. Private Function LabelPostageOption(code)
  297. Select Case CStr(code & "")
  298. Case "FirstClass" : LabelPostageOption = "Yes, at First Class Rate ($0.721/pc.)"
  299. Case "NonprofitRate" : LabelPostageOption = "Yes, at Nonprofit Rate ($0.263/pc.)"
  300. Case "PresortStandard" : LabelPostageOption = "Yes, at Presort Standard Rate ($0.473/pc.)"
  301. Case "No" : LabelPostageOption = "No"
  302. Case Else : LabelPostageOption = CStr(code & "")
  303. End Select
  304. End Function
  305. Private Function LabelNonprofitStatus(code)
  306. Select Case CStr(code & "")
  307. Case "Yes" : LabelNonprofitStatus = "Yes"
  308. Case "No" : LabelNonprofitStatus = "No"
  309. Case "NotSure" : LabelNonprofitStatus = "I'm not sure"
  310. Case Else : LabelNonprofitStatus = CStr(code & "")
  311. End Select
  312. End Function
  313. '-------------------------------------------------------------------------------------------------------------------
  314. ' Re-validates the submission server-side, mirroring the SurveyJS required/enum rules in
  315. ' continue.asp - the client-side checks are a UX convenience, not something the server can
  316. ' trust. Returns "" if valid, or a "; "-joined list of validation error messages.
  317. '-------------------------------------------------------------------------------------------------------------------
  318. Private Function ValidateAnswers(answers)
  319. Dim errors() : ReDim errors(-1)
  320. RequireNonEmptyString errors, answers, "ContactName", "Contact name is required."
  321. RequireNonEmptyString errors, answers, "Municipality", "Municipality is required."
  322. RequireNonEmptyString errors, answers, "Phone", "Phone number is required."
  323. RequireEnum errors, answers, "PurpleEnvelopeStock", Array("KCIStock", "OwnStock")
  324. RequireEnum errors, answers, "PurplePrintOption", Array("AddressesAndPermit", "PermitOnly")
  325. RequireEnum errors, answers, "PurpleBlueProvider", Array("ElectionSource", "PSI", "Spectrum", "Other")
  326. RequireEnum errors, answers, "PurplePrintStyle", Array("ColorCoding", "BlackOnly")
  327. RequireEnum errors, answers, "PurpleColorCodingBy", Array("Precinct", "Election")
  328. RequireEnum errors, answers, "BluePermitOwnership", Array("KCIPermit", "OwnPermit")
  329. RequireEnum errors, answers, "MailingPostageOption", Array("FirstClass", "NonprofitRate", "PresortStandard", "No")
  330. RequireEnum errors, answers, "MailingHasNonprofitStatus", Array("Yes", "No", "NotSure")
  331. RequireBoolean errors, answers, "PurpleWantsQuote"
  332. RequireBoolean errors, answers, "PurpleWantsBlueEnvelopes"
  333. RequireBoolean errors, answers, "PurpleTrackMIBallot"
  334. RequireBoolean errors, answers, "BlueWantsQuote"
  335. RequireBoolean errors, answers, "BluePrintPermit"
  336. RequireBoolean errors, answers, "BlueHasNonprofitStatus"
  337. RequireBoolean errors, answers, "MailingWantsService"
  338. RequireNonNegativeInteger errors, answers, "PurplePrecinctCount"
  339. RequireNonNegativeInteger errors, answers, "PurpleExtraEnvelopeQty"
  340. RequireNonNegativeInteger errors, answers, "MailingEstimatedQuantity"
  341. RequireNonNegativeInteger errors, answers, "SecrecySleevesQty"
  342. RequireNonNegativeInteger errors, answers, "IVotedStickerRolls"
  343. RequireNonNegativeInteger errors, answers, "FutureVoterStickerRolls"
  344. RequireValidDate errors, answers, "MailingPickupDate"
  345. If UBound(errors) >= 0 Then
  346. ValidateAnswers = Join(errors, "; ")
  347. Else
  348. ValidateAnswers = ""
  349. End If
  350. End Function
  351. Private Sub AddValidationError(ByRef errors, msg)
  352. ReDim Preserve errors(UBound(errors) + 1)
  353. errors(UBound(errors)) = msg
  354. End Sub
  355. ' Required on the client (page 1) - re-checked here since the client can't be trusted.
  356. Private Sub RequireNonEmptyString(ByRef errors, answers, key, msg)
  357. Dim v : v = AnswerValue(answers, key)
  358. If IsNull(v) Or Len(Trim(v & "")) = 0 Then AddValidationError errors, msg
  359. End Sub
  360. ' Only checked when present - these questions are conditionally hidden by visibleIf, so a
  361. ' missing value just means the question wasn't shown, not an invalid submission.
  362. Private Sub RequireEnum(ByRef errors, answers, key, allowedValues)
  363. Dim v : v = AnswerValue(answers, key)
  364. If Not IsNull(v) Then
  365. Dim found : found = False
  366. Dim i
  367. For i = 0 To UBound(allowedValues)
  368. If CStr(v) = allowedValues(i) Then found = True
  369. Next
  370. If Not found Then AddValidationError errors, key & " has an invalid value."
  371. End If
  372. End Sub
  373. Private Sub RequireBoolean(ByRef errors, answers, key)
  374. Dim v : v = AnswerValue(answers, key)
  375. If Not IsNull(v) Then
  376. If TypeName(v) <> "Boolean" Then AddValidationError errors, key & " must be true or false."
  377. End If
  378. End Sub
  379. Private Sub RequireNonNegativeInteger(ByRef errors, answers, key)
  380. Dim v : v = AnswerValue(answers, key)
  381. If Not IsNull(v) Then
  382. If Not IsNumeric(v) Then
  383. AddValidationError errors, key & " must be a number."
  384. ElseIf CDbl(v) < 0 Then
  385. AddValidationError errors, key & " cannot be negative."
  386. ElseIf CDbl(v) <> Int(CDbl(v)) Then
  387. AddValidationError errors, key & " must be a whole number."
  388. End If
  389. End If
  390. End Sub
  391. Private Sub RequireValidDate(ByRef errors, answers, key)
  392. Dim v : v = AnswerValue(answers, key)
  393. If Not IsNull(v) Then
  394. If Len(Trim(v & "")) > 0 And Not IsDate(v) Then
  395. AddValidationError errors, key & " is not a valid date."
  396. End If
  397. End If
  398. End Sub
  399. '-------------------------------------------------------------------------------------------------------------------
  400. ' Private helpers
  401. '-------------------------------------------------------------------------------------------------------------------
  402. Private Sub MapOrderDetailsAnswers(ByRef model, answers)
  403. ' Contact
  404. model.ContactName = AnswerValue(answers, "ContactName")
  405. model.Municipality = AnswerValue(answers, "Municipality")
  406. model.Phone = AnswerValue(answers, "Phone")
  407. ' Purple envelope
  408. model.PurpleWantsQuote = AnswerValue(answers, "PurpleWantsQuote")
  409. model.PurpleEnvelopeStock = AnswerValue(answers, "PurpleEnvelopeStock")
  410. model.PurplePrintOption = AnswerValue(answers, "PurplePrintOption")
  411. model.PurpleWantsBlueEnvelopes = AnswerValue(answers, "PurpleWantsBlueEnvelopes")
  412. model.PurpleBlueProvider = AnswerValue(answers, "PurpleBlueProvider")
  413. model.PurpleBlueProviderOther = AnswerValue(answers, "PurpleBlueProviderOther")
  414. model.PurplePrintStyle = AnswerValue(answers, "PurplePrintStyle")
  415. model.PurpleColorCodingBy = AnswerValue(answers, "PurpleColorCodingBy")
  416. model.PurplePrecinctCount = AnswerValue(answers, "PurplePrecinctCount")
  417. model.PurpleColorNames = AnswerValue(answers, "PurpleColorNames")
  418. model.PurpleTrackMIBallot = AnswerValue(answers, "PurpleTrackMIBallot")
  419. model.PurpleExtraEnvelopeQty = AnswerValue(answers, "PurpleExtraEnvelopeQty")
  420. ' Blue envelope
  421. model.BlueWantsQuote = AnswerValue(answers, "BlueWantsQuote")
  422. model.BluePrintPermit = AnswerValue(answers, "BluePrintPermit")
  423. model.BluePermitOwnership = AnswerValue(answers, "BluePermitOwnership")
  424. model.BlueHasNonprofitStatus = AnswerValue(answers, "BlueHasNonprofitStatus")
  425. model.BlueNonprofitAuthCode = AnswerValue(answers, "BlueNonprofitAuthCode")
  426. model.BluePermitCity = AnswerValue(answers, "BluePermitCity")
  427. model.BluePermitNumber = AnswerValue(answers, "BluePermitNumber")
  428. ' Mailing service
  429. model.MailingWantsService = AnswerValue(answers, "MailingWantsService")
  430. model.MailingPostageOption = AnswerValue(answers, "MailingPostageOption")
  431. model.MailingHasNonprofitStatus = AnswerValue(answers, "MailingHasNonprofitStatus")
  432. model.MailingEstimatedQuantity = AnswerValue(answers, "MailingEstimatedQuantity")
  433. model.MailingPickupDate = AnswerValue(answers, "MailingPickupDate")
  434. ' Additional items
  435. model.SecrecySleevesQty = AnswerValue(answers, "SecrecySleevesQty")
  436. model.IVotedStickerRolls = AnswerValue(answers, "IVotedStickerRolls")
  437. model.FutureVoterStickerRolls = AnswerValue(answers, "FutureVoterStickerRolls")
  438. model.SpecialRequests = AnswerValue(answers, "SpecialRequests")
  439. End Sub
  440. ' Returns the value for key in a parsed aspJSON Dictionary, or Null if the question was
  441. ' skipped (hidden by visibleIf logic and so never included in SurveyJS's result data).
  442. Private Function AnswerValue(answers, key)
  443. If answers.Exists(key) Then
  444. AnswerValue = answers.Item(key)
  445. Else
  446. AnswerValue = Null
  447. End If
  448. End Function
  449. Private Sub WriteJsonError(statusLine, message)
  450. Response.Status = statusLine
  451. Response.Write "{""success"":false,""error"":" & JsonEncodeString(message) & "}"
  452. End Sub
  453. Private Function JsonEncodeString(s)
  454. Dim out : out = s
  455. out = Replace(out, "\", "\\")
  456. out = Replace(out, """", "\""")
  457. out = Replace(out, Chr(10), "\n")
  458. out = Replace(out, Chr(13), "\r")
  459. JsonEncodeString = """" & out & """"
  460. End Function
  461. End Class
  462. ' Singleton instance
  463. Dim OrderApiController_Class__Singleton
  464. Function OrderApiController()
  465. If IsEmpty(OrderApiController_Class__Singleton) Then
  466. Set OrderApiController_Class__Singleton = New OrderApiController_Class
  467. End If
  468. Set OrderApiController = OrderApiController_Class__Singleton
  469. End Function
  470. %>

Powered by TurnKey Linux.