Skip to content

Instantly share code, notes, and snippets.

@erikdstock
Created July 16, 2020 23:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erikdstock/09dc318dfea84f5f4f307fc2a487aecd to your computer and use it in GitHub Desktop.
Save erikdstock/09dc318dfea84f5f4f307fc2a487aecd to your computer and use it in GitHub Desktop.
Example method of organizing sangria type
package graphql.models
import java.text.DecimalFormat
import sangria.validation.ValueCoercionViolation
import json.SprayJsonConversions
import sangria.macros.derive.{
deriveObjectType, AddFields, ObjectTypeDescription, ObjectTypeName
}
import sangria.schema.{
Argument, BooleanType, Field, IntType, LongType, OptionInputType, ScalarAlias,
StringType
}
import sangria.marshalling.sprayJson._
case class Money(units: Long) {
def displayAmount(
fractionalDigits: Int,
groupingSeparator: Char,
decimalSeparator: Char,
showFractionalAmount: Boolean
): String = {
require(units >= 0 && units < Math.pow(2, 53), MoneyUnitCoercionViolation)
val formatter = new DecimalFormat()
val symbols = formatter.getDecimalFormatSymbols
symbols.setGroupingSeparator(groupingSeparator)
symbols.setDecimalSeparator(decimalSeparator)
formatter.setDecimalFormatSymbols(symbols)
formatter.setMinimumFractionDigits(
if (showFractionalAmount) fractionalDigits else 0
)
formatter.setMaximumFractionDigits(fractionalDigits)
val displayAmount = units / scala.math.pow(10, fractionalDigits)
formatter.format(
if (showFractionalAmount) displayAmount else Math.ceil(displayAmount)
)
}
}
object Money extends SprayJsonConversions {
case object MoneyUnitCoercionViolation
extends ValueCoercionViolation("Number exceeds 2^53 ")
val MoneyUnitType = ScalarAlias[Long, Long](
LongType,
identity,
(l: Long) =>
if (l >= 0 && l < Math.pow(2, 53)) Right(l)
else Left(MoneyUnitCoercionViolation)
)
val fractionalDigits = Argument.createWithDefault(
"fractionalDigits",
OptionInputType(IntType),
Some("Number of decimal places for the currency."),
2
)
val groupingSeparator =
Argument.createWithDefault(
"groupingSeparator",
OptionInputType(CharType),
Some("The 1000s separator."),
','
)
val decimalSeparator =
Argument.createWithDefault(
"decimalSeparator",
OptionInputType(CharType),
Some("The decimal separator."),
'.'
)
val showFractionalAmount = Argument.createWithDefault(
"showFractionalDigits",
OptionInputType(BooleanType),
Some("Whether to show the fractional units."),
true
)
lazy val MoneyType = deriveObjectType[Unit, Money](
ObjectTypeName("Money"),
ObjectTypeDescription("Represents currency units and formatting"),
AddFields(
Field(
"displayAmount",
StringType,
description = Some("Formatted string version of currency amount"),
arguments = List(
fractionalDigits,
groupingSeparator,
decimalSeparator,
showFractionalAmount
),
resolve = c =>
c.value.displayAmount(
c.arg(fractionalDigits),
c.arg(groupingSeparator),
c.arg(decimalSeparator),
c.arg(showFractionalAmount)
)
)
)
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment