package com.restapi.domain import com.fasterxml.jackson.core.JsonParser import com.fasterxml.jackson.databind.DeserializationContext import com.fasterxml.jackson.databind.JsonDeserializer import com.fasterxml.jackson.databind.annotation.JsonDeserialize import io.ebean.Model import io.ebean.annotation.* import io.ebean.annotation.Index import java.time.LocalDate import java.time.LocalDateTime import java.util.* import javax.persistence.* data class Comments(val text: String = "", val by: String = "", val at: LocalDateTime = LocalDateTime.now()) data class POProducts(val productId: String = "", val productName: String = "", val unitPrice :Double = 0.0, val quantity: Double = 0.0, val description :String = "") enum class ApprovalStatus { PENDING, APPROVED, REJECTED } @MappedSuperclass abstract class BaseModel : Model() { @Id @GeneratedValue var sysPk: Long = 0 @SoftDelete @DbDefault("false") var deleted: Boolean = false @Version @DbDefault("1") var version: Int = 0 @WhenCreated @DbDefault("now()") var createdAt: LocalDateTime = LocalDateTime.now() @WhenModified @DbDefault("now()") var modifiedAt: LocalDateTime? = null @WhoCreated var createdBy: String = "" @WhoModified var modifiedBy: String? = null var deletedOn: LocalDateTime? = null var deletedBy: String? = null @DbDefault("0") var currentApprovalLevel: Int = 0 @DbDefault("0") var requiredApprovalLevels: Int = 0 @Enumerated(EnumType.STRING) @DbDefault("APPROVED") var approvalStatus: ApprovalStatus = ApprovalStatus.APPROVED @DbArray @DbDefault("{}") var tags: MutableList = arrayListOf() @DbJsonB @DbDefault("[]") var comments: MutableList = arrayListOf() } @MappedSuperclass abstract class BaseTenantModel : BaseModel() { @TenantId var tenantId: String = "" } @Entity open class TenantModel : BaseModel() { @Index(unique = true) var name: String = "" var domain: String = "" var mobile: List = emptyList() var emails: List = emptyList() @DbJsonB var preferences: MutableMap = hashMapOf() } enum class AuditType { CREATE, UPDATE, DELETE, VIEW, APPROVE, REJECT } @Entity @Index(columnNames = ["audit_type", "entity", "unique_identifier", "tenant_id", "created_by"]) open class AuditLog : BaseTenantModel() { @Enumerated(EnumType.STRING) var auditType: AuditType = AuditType.CREATE var entity: String = "" var uniqueIdentifier: String = "" @DbJsonB @Index( definition = "create index audit_log_values_idx on audit_log using GIN (data)", platforms = [Platform.POSTGRES] ) var data: Map = hashMapOf() @DbJsonB @Index( definition = "create index audit_log_changes_idx on audit_log using GIN (changes)", platforms = [Platform.POSTGRES] ) var changes: Map = hashMapOf() } @Entity open class EntityModel : BaseTenantModel() { @Index(unique = true) @JsonDeserialize(using = SafeStringDeserializer::class) var name: String = "" //a kts script that will return true/false along with errors before saving var preSaveScript: String? = "" //a kts script that will do something ... returns void var postSaveScript: String? = "" //this will create extra actions/roles in keycloak //the default actions are create, update, view, delete @DbArray @DbDefault("{}") var actions: List = emptyList() //allow only these fields, if this is empty, then all fields are allowed @DbArray @DbDefault("{}") var allowedFields: List = emptyList() //enforce field types, if this is present, only fields that are present is validated @DbJsonB @DbDefault("{}") var allowedFieldTypes: Map = hashMapOf() //when an entity is saved/updated audit logs will be populated, when this is empty, all fields are logged @DbArray @DbDefault("{}") var auditLogFields: List = emptyList() @DbJsonB @DbDefault("{}") var preferences: MutableMap = hashMapOf() //if '0' then its auto saved, no approval steps are required, for further steps, //a user needs to have ROLE_ENTITY_APPROVE_LEVEL1, ROLE_ENTITY_APPROVE_LEVEL2 roles for further approvals @DbDefault("0") var approvalLevels: Int = 0 } enum class JobFrequencyType { SPECIFIC, EVERY, CRON } enum class JobType { SCRIPT, DB } @Entity @Index(unique = true, name = "sql_unique_id", columnNames = ["entity_name", "sql_id", "tenant_id"]) open class SqlModel : BaseTenantModel() { @JsonDeserialize(using = SafeStringDeserializer::class) var sqlId: String = "" var entityName: String = "" @Column(columnDefinition = "text") var sql: String = "" } @Entity open class JobModel : BaseTenantModel() { @Index(unique = true) var jobName: String = "" @Enumerated(EnumType.STRING) var jobType: JobType = JobType.SCRIPT var jobPath: String = "" @DbArray var tenants: List = emptyList() @Enumerated(EnumType.STRING) var jobFrequencyType = JobFrequencyType.EVERY var frequency: String = "1h" } @Entity @Index(unique = true, name = "entity_unique_id", columnNames = ["entity_name", "unique_identifier", "tenant_id"]) open class DataModel : BaseTenantModel() { @JsonDeserialize(using = SafeStringDeserializer::class) var uniqueIdentifier: String = "" @JsonDeserialize(using = SafeStringDeserializer::class) var entityName: String = "" @Index(definition = "create index data_jsonb_idx on data_model using GIN (data) ", platforms = [Platform.POSTGRES]) @DbJsonB var data: MutableMap = hashMapOf() } @Entity @Index(unique = true, name = "unique_session_id", columnNames = ["session_id"]) open class AnonSession : BaseTenantModel() { var sessionId: String? = null var ip: String? = null var firstSeenAt: LocalDateTime? = null var lastSeenAt: LocalDateTime? = null @DbJsonB var headerMap: Map = hashMapOf() } class SafeStringDeserializer : JsonDeserializer() { private val regex = Regex("^[a-zA-Z0-9\\-_\\.]+$") override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): String { val text = p.text if (!regex.matches(text)) throw IllegalArgumentException() return text } } data class ContactPerson(val name: String = "", val email: String = "", val mobile: String = "") @Entity open class Vendor :BaseTenantModel() { var name :String = "" var msme :String = "" var gstNumber :String = "" var address :String = "" var rating :Double = 0.0 @DbJsonB var contacts :List = mutableListOf() } @Entity open class PurchaseOrder :BaseTenantModel() { @DbJsonB var products :MutableList = mutableListOf() @ManyToOne var vendor :Vendor? = null var referenceQuotation :String? = "" var totalAmount :Double = 0.0 var poNum: String = "" var poDate: LocalDate? = null var validTill: LocalDate? = null @DbArray var tnc: List? = arrayListOf() @DbArray var documents: MutableList? = arrayListOf() } enum class UOM { NOS, LTR, MTR, ALL } @Entity open class Product :BaseTenantModel() { var id: Long? = null var name :String = "" var description :String = "" var hsnCode :String = "" @Enumerated(EnumType.STRING) var uom: UOM? = null } @Entity open class Quotation :BaseTenantModel() { @DbJsonB var products :MutableList = mutableListOf() @ManyToOne var vendor :Vendor? = null var totalAmount :Double = 0.0 var reqForQuoteNum: String? = "" var quoteNum: String = "" var quoteDate: LocalDate? = null var validTill: LocalDate? = null @DbArray var tnc: List = arrayListOf() @DbArray var documents: MutableList = arrayListOf() } enum class DocType{ PO, QUOTE, INVOICE, ALL } @Entity open class Document :BaseTenantModel() { var name :String = "" @Enumerated(EnumType.STRING) var typeOfDoc :DocType? = null //could be quoteNum, PoNum, InvoiceNum var refId: String? = null var description :String = "" var url :String = "" var docDate :LocalDate? = null var vendor :Vendor? = null } enum class RFQStatus{ DELIVERED, PO, QUOTE, CANCELLED } @Entity open class ReqForQuote :BaseTenantModel() { @DbArray var potentialVendors :List? = null @Enumerated(EnumType.STRING) var status :RFQStatus? = null // @DbArray // var docs :List? = null @DbJsonB var products :List? = null var reqForQuoteNum: String? = null var openTill: LocalDate? = null }