Skip to content

Instantly share code, notes, and snippets.

@DiggesT
Last active September 7, 2023 09:57
Show Gist options
  • Save DiggesT/fc3b18c4b8cb3f8a6283fdf411b1f669 to your computer and use it in GitHub Desktop.
Save DiggesT/fc3b18c4b8cb3f8a6283fdf411b1f669 to your computer and use it in GitHub Desktop.
Document scala backend
package io.foldables.ratio.services.clients.model
import java.time.OffsetDateTime
import java.time.{LocalDate}
import java.util.UUID
import cats.implicits.*
import io.circe.generic.semiauto.*
import io.circe.{Decoder, Encoder, parser}
import sttp.tapir.Schema.SName
import sttp.tapir.Schema
import io.github.arainko.ducktape.*
import io.foldables.ratio.common.{MkId}
import io.foldables.ratio.common.data.Metadata
import io.foldables.ratio.services.auth.model.{Actor}
import io.foldables.ratio.services.clients.model.Document
//Классы образцы (Case classes) похожи на обычные классы с несколькими ключевыми отличиями
//Классы образцы хороши для моделирования неизменяемых данных
//сущность клиента, все необходимые данные, которые будут занесены в БД
//дополнить электронноой карточкой, записями
case class Client(
// Person.Id
firstName: String, // should be Person.Name?
middleName: Option[String],
lastName: String,
document: Document.Russia.Passport
// birthday: Option[LocalDate]
// date of registration
// electronic card
// list of visit records
)
object Client:
// UUID is a class that represents an immutable universally unique identifier (UUID).
// Opaque types offer a sound abstraction over implementation details, without imposing performance overhead
opaque type Id = UUID // final class UUID: UUID
object Id extends MkId[Id](identity, identity)
// metadata is data that describes other data
type Meta = Metadata.Default[Id]
// client with meta
final case class WithMeta(meta: Meta, origin: Client)
object WithMeta:
// Semi-automatic codec derivation.
// This object provides helpers for creating [[io.circe.Decoder]] and [[io.circe.ObjectEncoder]]
// instances for case classes, "incomplete" case classes, sealed trait hierarchies, etc.
given Decoder[WithMeta] = deriveDecoder[WithMeta]
given Encoder[WithMeta] = deriveEncoder[WithMeta]
// With tapir, you can describe HTTP API endpoints as immutable Scala values.
// Each endpoint can contain a number of input and output parameters
given Schema[WithMeta] = Schema
.derived[WithMeta]
.copy(name = Some(Schema.SName("ClientWithMeta")))
// new client
final case class New(
createdBy: Actor.Id,
firstName: String,
middleName: Option[String],
lastName: String,
document: Document.Russia.Passport
):
def withMeta(meta: Meta): Client.WithMeta =
Client.WithMeta(meta, this.to[Client])
object New:
given Decoder[New] = deriveDecoder[New]
given Encoder[New] = deriveEncoder[New]
given Schema[New] =
Schema.derived[New].copy(name = Some(SName("ClientNew")))
/** For frontend-form (createdBy comes from HTTP headers) */
final case class Base(
firstName: String,
middleName: Option[String],
lastName: String,
document: Document.Russia.Passport
):
def toNew(createdBy: Actor.Id): Client.New =
this
.into[Client.New]
.transform(Field.const(_.createdBy, createdBy))
object Base:
given Decoder[Base] = deriveDecoder[Base]
given Encoder[Base] = deriveEncoder[Base]
given Schema[Base] =
Schema.derived[Base].copy(name = Some(SName("ClientBase")))
given Decoder[Client] = deriveDecoder[Client]
given Encoder[Client] = deriveEncoder[Client]
given Schema[Client] = Schema.derived[Client]
package io.foldables.ratio.services.clients.model
import java.time.{LocalDate}
import java.util.UUID
import io.circe.generic.semiauto.*
import io.circe.{Decoder, Encoder, parser}
import sttp.tapir.Schema.SName
import sttp.tapir.Schema
import io.foldables.ratio.common.{MkId}
import io.foldables.ratio.common.data.Metadata
import io.foldables.ratio.services.auth.model.Person
case class Document(
// documentId: Id, UUID?
ownerId: Person.Id,
documentType: Document.DocumentType
)
object Document:
opaque type Id = UUID
object Id extends MkId[Id](identity, identity)
type Meta = Metadata.Default[Id]
final case class WithMeta(meta: Meta, origin: Document)
object WithMeta:
given Decoder[WithMeta] = deriveDecoder[WithMeta]
given Encoder[WithMeta] = deriveEncoder[WithMeta]
given Schema[WithMeta] = Schema
.derived[WithMeta]
.copy(name = Some(Schema.SName("DocumentWithMeta")))
sealed trait DocumentType {
// some generic parameters
id: String
} // given Decoder/Encoder?
// object DocumentType:
// given Decoder[DocumentType] = Decoder[DocumentType].emap(fromString)
// given Encoder[DocumentType] = Encoder[DocumentType].contramap(_.asString)
// given Schema[DocumentType] =
// Schema
// .derivedEnumeration[DocumentType](Some(_.asString))
// .copy(name = Some(Schema.SName("DocumentType")))
object Russia:
case class Passport(
series: String,
number: String,
date: LocalDate,
department: String,
subdivision: String
) extends DocumentType
object Passport:
given Decoder[Passport] = deriveDecoder[Passport]
given Encoder[Passport] = deriveEncoder[Passport]
given Schema[Passport] =
Schema
.derived[Passport]
.copy(name = Some(SName("DocumentRussiaPassport")))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment