pre-dev: initial commit
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -26,6 +26,7 @@ go.work.sum
|
||||
|
||||
# env file
|
||||
.env
|
||||
config.yml
|
||||
|
||||
# Editor/IDE
|
||||
# .idea/
|
||||
|
||||
1
README-APP.md
Normal file
1
README-APP.md
Normal file
@@ -0,0 +1 @@
|
||||
# APP DESIGN CONVENTION
|
||||
37
README-DB.md
Normal file
37
README-DB.md
Normal file
@@ -0,0 +1,37 @@
|
||||
# DATABASE MODELING CONVETION
|
||||
|
||||
## Naming
|
||||
1. Table names are written in combination, with the following rules:
|
||||
1. Basically uses `PascalCase`
|
||||
2. An underscore is used in `derived-table`, separating the original name and the derived name.
|
||||
3. A derived table is a table derived from another table but not used in the main flow of the business process.
|
||||
4. Examples of derived table implementations include:
|
||||
1. Archiving, for example: `Transaction_2019`, is an archive of the `Transaction` table for the year `2019`.
|
||||
2. Trashing for deleted data, for example: `Transaction_deleted`, stores data from the deleted `transaction` table.
|
||||
3. History for storing historical information, for example: `ProductStock_History`, stores historical data from the `ProductStock` table.
|
||||
2. Columns are written in combination, with the following rules:
|
||||
1. Basically, uses `PascalCase`
|
||||
2. Use underscores to represent relationships <span>`object`-`attribute`</span> or <span>`table`-`column`</span>
|
||||
<br />Example:
|
||||
1. `User_Id` represents the `User` object and the `Id` attribute
|
||||
2. `BestProduct_Code` represents the `BestProduct` object and the `Code` attribute
|
||||
3. When more than one column has a similar definition, a `prefix` can be added to indicate the column's purpose.
|
||||
<br />Example:
|
||||
1. `Admin_User_Id` represents the `Admin` of the `User` object and the `Id` attribute
|
||||
2. `Operator_User_Id` refers to the `Operator` of the `User` object and the `Id` column.
|
||||
3. Attributes/properties in JSON (for output purpose) are written in combination, with the following rules:
|
||||
1. Basically uses `camelCase`
|
||||
2. Using underscores to represent relationships <span>`object`-`attribute`</span> or <span>`table`-`column`</span>
|
||||
<br />Example:
|
||||
1. `user_id` represents the `User` object and the `Id` attribute.
|
||||
2. `bestProduct_code` represents the `bestProduct` object and the `code` attribute.
|
||||
3. When more than one column has a similar definition, a `prefix` can be added to indicate the column's purpose.
|
||||
<br />Example:
|
||||
1. `admin_user_id` refers to the `admin` of the `user` object and `id` attribute
|
||||
2. `operator_user_id` refers to the `operator` of the `user` object, column `id`
|
||||
3. `newArrival_bestProduct_code` refers to the `newArrival` of the `bestProduct` object, column `code`
|
||||
4. `favorite_bestProduct_code` refers to the `favorite` of the `bestProduct` object, column `code`
|
||||
|
||||
## Avoiding Circular Dependency
|
||||
1. Prioritize the child due to it's nature to define the foreign key. This means the child is allowed to import main entities that define the table, not the base.
|
||||
2. Parent imports the child's non main entities, can be the base or others depending on the needs.
|
||||
26
cmd/main-api/config.yml-example
Normal file
26
cmd/main-api/config.yml-example
Normal file
@@ -0,0 +1,26 @@
|
||||
appCfg:
|
||||
fullName: BPJS Bridge
|
||||
codeName: simrs-vx
|
||||
version: 0.1.0
|
||||
env: development
|
||||
lang: en
|
||||
|
||||
httpCfg:
|
||||
host:
|
||||
port:
|
||||
|
||||
loggerCfg:
|
||||
hideTime:
|
||||
hideLevel:
|
||||
|
||||
msCfg:
|
||||
dsn:
|
||||
|
||||
langCfg:
|
||||
active:
|
||||
path:
|
||||
fileName:
|
||||
|
||||
corsCfg:
|
||||
allowedOrigin:
|
||||
allowedMethod:
|
||||
14
cmd/main-api/main.go
Normal file
14
cmd/main-api/main.go
Normal file
@@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
a "github.com/karincake/apem"
|
||||
d "github.com/karincake/apem/db-gorm-pg"
|
||||
l "github.com/karincake/apem/logger-zerolog"
|
||||
m "github.com/karincake/apem/ms-redis"
|
||||
|
||||
h "simrs-vx/internal/interface/main-handler"
|
||||
)
|
||||
|
||||
func main() {
|
||||
a.Run(h.SetRoutes(), &l.O, &m.O, &d.O)
|
||||
}
|
||||
32
go.mod
Normal file
32
go.mod
Normal file
@@ -0,0 +1,32 @@
|
||||
module simrs-vx
|
||||
|
||||
go 1.23.0
|
||||
|
||||
toolchain go1.23.11
|
||||
|
||||
require (
|
||||
github.com/karincake/apem v0.0.16-e
|
||||
github.com/karincake/dodol v0.0.1
|
||||
gorm.io/gorm v1.25.10
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/go-redis/redis v6.15.9+incompatible // indirect
|
||||
github.com/google/go-cmp v0.7.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a // indirect
|
||||
github.com/jackc/pgx/v5 v5.4.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||
github.com/nxadm/tail v1.4.11 // indirect
|
||||
github.com/rs/zerolog v1.33.0 // indirect
|
||||
golang.org/x/crypto v0.40.0 // indirect
|
||||
golang.org/x/net v0.42.0 // indirect
|
||||
golang.org/x/sys v0.34.0 // indirect
|
||||
golang.org/x/text v0.27.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/postgres v1.5.7 // indirect
|
||||
)
|
||||
78
go.sum
Normal file
78
go.sum
Normal file
@@ -0,0 +1,78 @@
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg=
|
||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk=
|
||||
github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.4.3 h1:cxFyXhxlvAifxnkKKdlxv8XqUf59tDlYjnV5YYfsJJY=
|
||||
github.com/jackc/pgx/v5 v5.4.3/go.mod h1:Ig06C2Vu0t5qXC60W8sqIthScaEnFvojjj9dSljmHRA=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/karincake/apem v0.0.16-e h1:KGeQYmgNw8luidSWkZyGcMbW1PP3KMRCHMTEHQ7twU8=
|
||||
github.com/karincake/apem v0.0.16-e/go.mod h1:cQP2sJfDrLRIiwWoaLWw/z8uAya+DWu/FpmYeinMQXM=
|
||||
github.com/karincake/dodol v0.0.1 h1:jUXmJh1r0Ei4fmHPZ6IUkoplW/V9d27L63JEl6zudL0=
|
||||
github.com/karincake/dodol v0.0.1/go.mod h1:2f1NcvkvY0J3GMUkwILNDYVvRUpz0W3lpPp/Ha/Ld24=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
|
||||
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/gomega v1.33.1 h1:dsYjIxxSR755MDmKVsaFQTE22ChNBcuuTWgkUDSubOk=
|
||||
github.com/onsi/gomega v1.33.1/go.mod h1:U4R44UsT+9eLIaYRB2a5qajjtQYn0hauxvRm16AVYg0=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8=
|
||||
github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
|
||||
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
|
||||
golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs=
|
||||
golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA=
|
||||
golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4=
|
||||
golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
gorm.io/driver/postgres v1.5.7 h1:8ptbNJTDbEmhdr62uReG5BGkdQyeasu/FZHxI0IMGnM=
|
||||
gorm.io/driver/postgres v1.5.7/go.mod h1:3e019WlBaYI5o5LIdNV+LyxCMNtLOQETBXL2h4chKpA=
|
||||
gorm.io/gorm v1.25.10 h1:dQpO+33KalOA+aFYGlK+EfxcI5MbO7EP2yYygwh9h+s=
|
||||
gorm.io/gorm v1.25.10/go.mod h1:hbnx/Oo0ChWMn1BIhpy1oYozzpM15i4YPuHDmfYtwg8=
|
||||
26
internal/domain/_template/child/base/entity.go
Normal file
26
internal/domain/_template/child/base/entity.go
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of base-entity, results of the extraction of the attributes from the
|
||||
original entity.
|
||||
|
||||
NOTE:
|
||||
Make sure to use 'case-sensitive' option when searching
|
||||
|
||||
TODO:
|
||||
create several types according to the needs
|
||||
*/
|
||||
package base // adjust this
|
||||
|
||||
type Basic struct {
|
||||
Code string `json:"code" gorm:"uniqueIndex;not null;size:10"`
|
||||
Name string `json:"name" gorm:"not null;size:100"`
|
||||
}
|
||||
|
||||
type Default struct {
|
||||
Type_Code TypeCode `json:"type" gorm:"not null;size:10"`
|
||||
Status_Code StatusCode `json:"status" gorm:"not null;size:10"`
|
||||
}
|
||||
|
||||
type Extra struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
17
internal/domain/_template/child/base/tycovar.go
Normal file
17
internal/domain/_template/child/base/tycovar.go
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
A sample, part of the package that contains type, constants, and/or variables.
|
||||
*/
|
||||
package base // adjust this
|
||||
|
||||
type StatusCode string
|
||||
type TypeCode string
|
||||
|
||||
const (
|
||||
SCActive StatusCode = "active" // prefixed with SC that stands for StatusCode
|
||||
SCInactive StatusCode = "inactive"
|
||||
|
||||
TCPrimary TypeCode = "prim" // prefixed with TC that stands for TypeCode
|
||||
TCScondary TypeCode = "seco"
|
||||
TCTertiary TypeCode = "tert"
|
||||
)
|
||||
28
internal/domain/_template/child/entity.go
Normal file
28
internal/domain/_template/child/entity.go
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of struct to define an entity both in the application and database.
|
||||
Uses the base struct from the core package for the standard attributes.
|
||||
|
||||
The sampel is part of the the workaround sample on how to avoid the
|
||||
circle-depency. The child is used to define the relationship for the database.
|
||||
|
||||
TODO:
|
||||
- replace 'child' with the name of the package, ie: myentity
|
||||
- replace 'Child' with the name of the entity, ie: MyEntity
|
||||
*/
|
||||
package child
|
||||
|
||||
import (
|
||||
ecore "simrs-vx/internal/domain/base-entities/core"
|
||||
eb "simrs-vx/internal/domain/main-entities/child/base"
|
||||
ep "simrs-vx/internal/domain/main-entities/parent"
|
||||
)
|
||||
|
||||
type Child struct {
|
||||
ecore.Main
|
||||
eb.Basic
|
||||
Parent_Id int `json:"parent_id"`
|
||||
Pareng ep.Parent `json:"parent" gorm:"foreignKey:Parent_Id;references:Id"`
|
||||
eb.Default
|
||||
eb.Extra
|
||||
}
|
||||
21
internal/domain/_template/child/simple/entity.go
Normal file
21
internal/domain/_template/child/simple/entity.go
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of a case-entity that utilized the base according to the needs.
|
||||
|
||||
NOTE:
|
||||
Make sure to use 'case-sensitive' option when searching
|
||||
|
||||
TODO:
|
||||
replace 'child' with the name of the package, ie: myentity
|
||||
replace 'Child' with the name of the entity, ie: MyEntity
|
||||
*/
|
||||
package child
|
||||
|
||||
import (
|
||||
eb "simrs-vx/internal/domain/main-entities/child/base"
|
||||
)
|
||||
|
||||
type Child struct {
|
||||
Id int `json:"id"` // in many cases the usage of
|
||||
eb.Basic
|
||||
}
|
||||
26
internal/domain/_template/parent/base/entity.go
Normal file
26
internal/domain/_template/parent/base/entity.go
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of base-entity, results of the extraction of the attributes from the
|
||||
original entity.
|
||||
|
||||
NOTE:
|
||||
Make sure to use 'case-sensitive' option when searching
|
||||
|
||||
TODO:
|
||||
create several types according to the needs
|
||||
*/
|
||||
package base // adjust this
|
||||
|
||||
type Basic struct {
|
||||
Code string `json:"code" gorm:"uniqueIndex;not null;size:10"`
|
||||
Name string `json:"name" gorm:"not null;size:100"`
|
||||
}
|
||||
|
||||
type Default struct {
|
||||
Type_Code TypeCode `json:"type" gorm:"not null;size:10"`
|
||||
Status_Code StatusCode `json:"status" gorm:"not null;size:10"`
|
||||
}
|
||||
|
||||
type Extra struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
17
internal/domain/_template/parent/base/tycovar.go
Normal file
17
internal/domain/_template/parent/base/tycovar.go
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
A sample, part of the package that contains type, constants, and/or variables.
|
||||
*/
|
||||
package base // adjust this
|
||||
|
||||
type StatusCode string
|
||||
type TypeCode string
|
||||
|
||||
const (
|
||||
SCActive StatusCode = "active" // prefixed with SC that stands for StatusCode
|
||||
SCInactive StatusCode = "inactive"
|
||||
|
||||
TCPrimary TypeCode = "prim" // prefixed with TC that stands for TypeCode
|
||||
TCScondary TypeCode = "seco"
|
||||
TCTertiary TypeCode = "tert"
|
||||
)
|
||||
31
internal/domain/_template/parent/entity.go
Normal file
31
internal/domain/_template/parent/entity.go
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of struct to define an entity both in the application and database.
|
||||
Uses the base struct from the core package for the standard attributes.
|
||||
|
||||
The sampel shows a workaround on how to avoid the circle-depency which is a
|
||||
common problem when it involves the parent-child relationship. By default,
|
||||
the relationship is defined in the child entity, and when the parent entity
|
||||
needs to use the child as an attribute (array for example), the circle-depency
|
||||
happens.
|
||||
|
||||
To avoid this problem, the parent will have a case-entity like 'full' entity,
|
||||
which embeds the 'base' and the 'child' structs.
|
||||
|
||||
TODO:
|
||||
- replace 'parent' with the name of the package, ie: myentity
|
||||
- replace 'Parent' with the name of the entity, ie: MyEntity
|
||||
*/
|
||||
package parent
|
||||
|
||||
import (
|
||||
ecore "simrs-vx/internal/domain/base-entities/core"
|
||||
eb "simrs-vx/internal/domain/main-entities/parent/base"
|
||||
)
|
||||
|
||||
type Parent struct {
|
||||
ecore.Main
|
||||
eb.Basic
|
||||
eb.Default
|
||||
eb.Extra
|
||||
}
|
||||
24
internal/domain/_template/parent/full/entity.go
Normal file
24
internal/domain/_template/parent/full/entity.go
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of a case-entity that utilized the base according to the needs. In this
|
||||
sample, it imports the child entity, and uses it as an attribute. And by
|
||||
separating this entity from the original entity, it avoids the circle dependency.
|
||||
|
||||
TODO:
|
||||
replace 'parent' with the name of the package, ie: patient
|
||||
replace 'Parent' with the name of the entity, ie: Patient
|
||||
*/
|
||||
package parent
|
||||
|
||||
import (
|
||||
ec "simrs-vx/internal/domain/main-entities/child"
|
||||
eb "simrs-vx/internal/domain/main-entities/parent/base"
|
||||
// ec "simrs-vx/internal/domain/main-entities/child/minimal" // can use other case
|
||||
)
|
||||
|
||||
type Parent struct {
|
||||
Id int `json:"id"`
|
||||
eb.Basic
|
||||
eb.Default
|
||||
Childs []ec.Child `json:"childs" gorm:"foreignKey:Parent_Id;references:Id"`
|
||||
}
|
||||
19
internal/domain/_template/parent/minimal/entity.go
Normal file
19
internal/domain/_template/parent/minimal/entity.go
Normal file
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of a case-entity that utilized the base according to the needs.
|
||||
|
||||
TODO:
|
||||
replace 'parent' with the name of the package, ie: patient
|
||||
replace 'Parent' with the name of the entity, ie: Patient
|
||||
*/
|
||||
package parent
|
||||
|
||||
import (
|
||||
eb "simrs-vx/internal/domain/main-entities/parent/base"
|
||||
)
|
||||
|
||||
type Parent struct {
|
||||
Id int `json:"id"`
|
||||
eb.Basic
|
||||
eb.Default
|
||||
}
|
||||
26
internal/domain/_template/separated/base/entity.go
Normal file
26
internal/domain/_template/separated/base/entity.go
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of base-entity, results of the extraction of the attributes from the
|
||||
original entity.
|
||||
|
||||
NOTE:
|
||||
Make sure to use 'case-sensitive' option when searching
|
||||
|
||||
TODO:
|
||||
create several types according to the needs
|
||||
*/
|
||||
package base // adjust this
|
||||
|
||||
type Basic struct {
|
||||
Code string `json:"code" gorm:"uniqueIndex;not null;size:10"`
|
||||
Name string `json:"name" gorm:"not null;size:100"`
|
||||
}
|
||||
|
||||
type Default struct {
|
||||
Type_Code TypeCode `json:"type" gorm:"not null;size:10"`
|
||||
Status_Code StatusCode `json:"status" gorm:"not null;size:10"`
|
||||
}
|
||||
|
||||
type Extra struct {
|
||||
Description string `json:"description"`
|
||||
}
|
||||
13
internal/domain/_template/separated/base/helper.go
Normal file
13
internal/domain/_template/separated/base/helper.go
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
A sample, part of the package that contains functions.
|
||||
*/
|
||||
package base
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
func (b *Basic) ExtractName() []string {
|
||||
return strings.Split(b.Name, " ")
|
||||
}
|
||||
17
internal/domain/_template/separated/base/tycovar.go
Normal file
17
internal/domain/_template/separated/base/tycovar.go
Normal file
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
A sample, part of the package that contains type, constants, and/or variables.
|
||||
*/
|
||||
package base // adjust this
|
||||
|
||||
type StatusCode string
|
||||
type TypeCode string
|
||||
|
||||
const (
|
||||
SCActive StatusCode = "active" // prefixed with SC that stands for StatusCode
|
||||
SCInactive StatusCode = "inactive"
|
||||
|
||||
TCPrimary TypeCode = "prim" // prefixed with TC that stands for TypeCode
|
||||
TCScondary TypeCode = "seco"
|
||||
TCTertiary TypeCode = "tert"
|
||||
)
|
||||
34
internal/domain/_template/separated/entity.go
Normal file
34
internal/domain/_template/separated/entity.go
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of struct to define an entity both in the application and database.
|
||||
Uses the base struct from the core package for the standard attributes.
|
||||
|
||||
The original attributes are extracted and grouped into several parts (structs),
|
||||
which later embeded. The extracted attributes are stored into the subdirectory
|
||||
'base'.
|
||||
|
||||
The extraction is done to cover several cases regarding the eficiency the of
|
||||
the data retreiving by using only needed attributes. Each case has its own
|
||||
directory with the same struct name with the main entity that embeds the
|
||||
needed attributes from the 'base'.
|
||||
|
||||
NOTES:
|
||||
Make sure to use 'case-sensitive' option when doing search-replace
|
||||
|
||||
TODO:
|
||||
- replace 'separated' with the name of the package, ie: myentity
|
||||
- replace 'Separated' with the name of the entity, ie: MyEntity
|
||||
*/
|
||||
package separated
|
||||
|
||||
import (
|
||||
ecore "simrs-vx/internal/domain/base-entities/core"
|
||||
eb "simrs-vx/internal/domain/main-entities/separated/base"
|
||||
)
|
||||
|
||||
type Separated struct {
|
||||
ecore.Main // adjust this according to the needs
|
||||
eb.Basic
|
||||
eb.Default
|
||||
eb.Extra
|
||||
}
|
||||
21
internal/domain/_template/separated/minimal/entity.go
Normal file
21
internal/domain/_template/separated/minimal/entity.go
Normal file
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of a case-entity that utilized the base according to the needs.
|
||||
|
||||
NOTE:
|
||||
Make sure to use 'case-sensitive' option when searching
|
||||
|
||||
TODO:
|
||||
replace 'separated' with the name of the package, ie: myentity
|
||||
replace 'Separated' with the name of the entity, ie: MyEntity
|
||||
*/
|
||||
package separated
|
||||
|
||||
import (
|
||||
eb "simrs-vx/internal/domain/main-entities/separated/base"
|
||||
)
|
||||
|
||||
type Separated struct {
|
||||
Id int `json:"id"`
|
||||
eb.Basic
|
||||
}
|
||||
22
internal/domain/_template/separated/simple/entity.go
Normal file
22
internal/domain/_template/separated/simple/entity.go
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of a case-entity that utilized the base according to the needs.
|
||||
|
||||
NOTE:
|
||||
Make sure to use 'case-sensitive' option when searching
|
||||
|
||||
TODO:
|
||||
replace 'separated' with the name of the package, ie: myentity
|
||||
replace 'Separated' with the name of the entity, ie: MyEntity
|
||||
*/
|
||||
package separated
|
||||
|
||||
import (
|
||||
eb "simrs-vx/internal/domain/main-entities/separated/base"
|
||||
)
|
||||
|
||||
type Separated struct {
|
||||
Id int `json:"id"` // in many cases the usage of
|
||||
eb.Basic
|
||||
eb.Default
|
||||
}
|
||||
26
internal/domain/_template/single/dto.go
Normal file
26
internal/domain/_template/single/dto.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package single
|
||||
|
||||
type Createdto struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
|
||||
type ReadListDto struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type ReadDetailDto struct {
|
||||
Code string `json:"code"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
type Updatedto struct {
|
||||
Id uint `json:"id"`
|
||||
Createdto
|
||||
}
|
||||
|
||||
type Deletedto struct {
|
||||
Id uint `json:"id"`
|
||||
}
|
||||
25
internal/domain/_template/single/entity.go
Normal file
25
internal/domain/_template/single/entity.go
Normal file
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of struct to define an entity both in the application and database.
|
||||
Uses the base struct from the core package for the standard
|
||||
attributes.
|
||||
|
||||
NOTES:
|
||||
Make sure to use 'case-sensitive' option when doing search-replace
|
||||
|
||||
TODO:
|
||||
- replace 'single' with the name of the package, ie: 'patient'
|
||||
- replace 'Single' with the name of the entity, ie: 'Patient'
|
||||
*/
|
||||
package single
|
||||
|
||||
import (
|
||||
ecore "simrs-vx/internal/domain/base-entities/core"
|
||||
)
|
||||
|
||||
type Single struct {
|
||||
ecore.Main // adjust this according to the needs
|
||||
Code string `json:"code" gorm:"uniqueIndex;not null;size:10"`
|
||||
Name string `json:"name" gorm:"not null;size:100"`
|
||||
Description string `json:"description"`
|
||||
}
|
||||
0
internal/domain/base-entities/.keep
Normal file
0
internal/domain/base-entities/.keep
Normal file
11
internal/domain/base-entities/actor/entity.go
Normal file
11
internal/domain/base-entities/actor/entity.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package actor
|
||||
|
||||
type Actor struct {
|
||||
CreatedBy_User_Id uint `json:"createdBy_user_id"`
|
||||
UpdatedBy_User_Id uint `json:"updatedBy_user_id"`
|
||||
DeletedBy_User_Id uint `json:"deletedBy_user_id"`
|
||||
}
|
||||
|
||||
type Owner struct {
|
||||
OwnedBy_User_Id uint `json:"ownedBy_user_id"`
|
||||
}
|
||||
31
internal/domain/base-entities/core/entity.go
Normal file
31
internal/domain/base-entities/core/entity.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package core
|
||||
|
||||
import "gorm.io/gorm"
|
||||
|
||||
type Base struct {
|
||||
CreatedAt string `json:"createdAt"`
|
||||
UpdatedAt string `json:"updatedAt"`
|
||||
DeteledAt gorm.DeletedAt `json:"deletedAt,omitempty"`
|
||||
}
|
||||
|
||||
//
|
||||
type Main struct {
|
||||
Id uint `json:"id" gorm:"primaryKey"` // depends on the system architecture
|
||||
Base
|
||||
}
|
||||
|
||||
type TinyMain struct {
|
||||
Id uint8 `json:"id" gorm:"primaryKey"`
|
||||
Base
|
||||
}
|
||||
|
||||
type SmallMain struct {
|
||||
Id uint16 `json:"id" gorm:"primaryKey"`
|
||||
Base
|
||||
}
|
||||
|
||||
// Mainly for transaction
|
||||
type BigMain struct {
|
||||
Id uint64 `json:"id" gorm:"primaryKey"`
|
||||
Base
|
||||
}
|
||||
0
internal/infra/.keep
Normal file
0
internal/infra/.keep
Normal file
0
internal/interface/.keep
Normal file
0
internal/interface/.keep
Normal file
40
internal/interface/_template/crud/handler.go
Normal file
40
internal/interface/_template/crud/handler.go
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of the use-case that has fully CRUD functionality. Uses object with CRUD
|
||||
functions to satisfy CRUD interface so it will be able to be generated into
|
||||
CRUD routing.
|
||||
|
||||
Functions other than CRUD can be writen outside the object.
|
||||
*/
|
||||
package crud
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type myBase struct{}
|
||||
|
||||
var O myBase
|
||||
|
||||
func (obj myBase) Create(w http.ResponseWriter, r *http.Request) {
|
||||
// MULAI MEETING E
|
||||
// JIKA SUATU SAAT MAU OUTPUT XML, HANDLER YG MELAKUKAN
|
||||
// BUKAN CASE
|
||||
// YES MIRIP HANDLER
|
||||
// MEETING E MULAI
|
||||
}
|
||||
|
||||
func (obj myBase) Read(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (obj myBase) Update(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func (obj myBase) Delete(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func OtherFunc(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func AnotherFunc(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
16
internal/interface/_template/invoke-auth/handler.go
Normal file
16
internal/interface/_template/invoke-auth/handler.go
Normal file
@@ -0,0 +1,16 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Sample of a use-case that has fully CRUD functionality. User Id and the other
|
||||
things related to credentials are passed within the dto.
|
||||
*/
|
||||
package invokeauth
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func SomeFunc(w http.ResponseWriter, r *http.Request) {
|
||||
// if dto.User_Id > 0 {
|
||||
// query = query.Where("User_Id = ?", dto.User_Id)
|
||||
// }
|
||||
}
|
||||
15
internal/interface/_template/non-crud/handler.go
Normal file
15
internal/interface/_template/non-crud/handler.go
Normal file
@@ -0,0 +1,15 @@
|
||||
package crud
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type myBase struct{}
|
||||
|
||||
var O myBase
|
||||
|
||||
func SomeFunc(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
func Read(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
23
internal/interface/main-handler/home/handler.go
Normal file
23
internal/interface/main-handler/home/handler.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package home
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
)
|
||||
|
||||
func Home(w http.ResponseWriter, r *http.Request) {
|
||||
if r.URL.Path != "/" {
|
||||
jsonText, _ := json.Marshal(map[string]string{"message": "Resource can not be found!!"})
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write(jsonText)
|
||||
return
|
||||
}
|
||||
|
||||
jsonText, _ := json.Marshal(map[string]string{"message": "Welcome to the API"})
|
||||
w.Write(jsonText)
|
||||
}
|
||||
|
||||
func TempResponse(w http.ResponseWriter, r *http.Request) {
|
||||
jsonText, _ := json.Marshal(map[string]string{"message": "Nice move by the programmer, now tell him that he forgot this part"})
|
||||
w.Write(jsonText)
|
||||
}
|
||||
25
internal/interface/main-handler/main-handler.go
Normal file
25
internal/interface/main-handler/main-handler.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package handler
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
///// PKG
|
||||
handlerlogger "simrs-vx/pkg/middleware/handler-logger"
|
||||
|
||||
///// Internal
|
||||
"simrs-vx/internal/interface/main-handler/home"
|
||||
)
|
||||
|
||||
// One place route to relatively easier to manage, ESPECIALLY in tracking
|
||||
func SetRoutes() http.Handler {
|
||||
/////
|
||||
// a.RegisterExtCall(gs.Adjust)
|
||||
|
||||
r := http.NewServeMux()
|
||||
|
||||
/******************** Main ********************/
|
||||
r.HandleFunc("/", home.Home)
|
||||
|
||||
/////
|
||||
return handlerlogger.SetLog(r)
|
||||
}
|
||||
0
internal/use-case/.keep
Normal file
0
internal/use-case/.keep
Normal file
0
internal/use-case/_plugin-template/.keep
Normal file
0
internal/use-case/_plugin-template/.keep
Normal file
20
internal/use-case/_plugin-template/modifier/modifire.go
Normal file
20
internal/use-case/_plugin-template/modifier/modifire.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package modifier
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
e "simrs-vx/internal/domain/main-entities/single"
|
||||
)
|
||||
|
||||
// a sampel of modifying some input
|
||||
func ModifInput(input *e.Createdto, data *e.Single, tx *gorm.DB) error {
|
||||
input.Name = "Prefix_" + input.Name
|
||||
return nil
|
||||
}
|
||||
|
||||
// a sampel of utilizing transaction
|
||||
func CheckData(input *e.Createdto, data *e.Single, tx *gorm.DB) error {
|
||||
tx.Where("name = ?", input.Name)
|
||||
input.Name = "Prefix_" + input.Name
|
||||
return nil
|
||||
}
|
||||
0
internal/use-case/_use-case-template/.keep
Normal file
0
internal/use-case/_use-case-template/.keep
Normal file
59
internal/use-case/_use-case-template/crud/README.md
Normal file
59
internal/use-case/_use-case-template/crud/README.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Use-Case
|
||||
Standard pattern to be used to maintain the code scalability by providing
|
||||
middleware-based flow. Each function can have its own middlewares for
|
||||
pre- and post-processing.
|
||||
|
||||
According to the pattern above all of the case-functions runs only basic
|
||||
rdbms operations, like getting data or writing data. And it's all based
|
||||
on the data structure. The middlewares are used to for additional actions.
|
||||
|
||||
## How It's Done
|
||||
The use-case is divided into at least 2 parts:
|
||||
1. Case (`case.go`), where the `case` functions (the main functions) are stored
|
||||
2. Tycovar (`tycovar.go`), where package scoped types, const, and variables
|
||||
are stored
|
||||
|
||||
Optionally, there can be other parts, such as:
|
||||
1. Helper (`helper.go`), where internal functions are stored
|
||||
2. Middleware (`middleware.go`), where the pre- and post-processing functions
|
||||
are stored
|
||||
|
||||
Then proceed the following steps (example):
|
||||
1. Inside the `tycovar.go`, define the middleware types for each case
|
||||
functions. Make sure to:
|
||||
1. Include dto, table definition, and transaction for the parameters
|
||||
since the middlewares are to utilize or modifies one ot the parameters.
|
||||
2. Make all of the parameter pointer for easier handling.
|
||||
3. Return `error` for blocking purpose when error occurs.
|
||||
```go
|
||||
type createMw func(input *e.Createdto, tx *gorm.DB) error
|
||||
.
|
||||
.
|
||||
```
|
||||
2. Inside the `tycovar.go`, create variables in form of array to make it
|
||||
possible to have more than one middleware. There are 2 modes (pre- and
|
||||
post-processing) for each case functions:
|
||||
|
||||
```go
|
||||
var createPreMw []createMw
|
||||
var createPostMw []createMw
|
||||
.
|
||||
.
|
||||
```
|
||||
3. Inside the `middleware.go`, create the necessary middlewares
|
||||
```go
|
||||
func createPreMwAddNamePrefix(input *e.Createdto, tx *gorm.DB) error {
|
||||
input.Name = "Prefix_" + input.Name
|
||||
return nil
|
||||
}
|
||||
```
|
||||
4. Inside the `middleware.go`, append the middlewares during initialization.
|
||||
The order of the does not really is important, except there are steps that
|
||||
are dependent on each other.
|
||||
```go
|
||||
func init() {
|
||||
createPreMw = append(createPreMw, createPreMwAddNamePrefix)
|
||||
}
|
||||
```
|
||||
5. Loop through the middleware variables and call each middleware. Since there
|
||||
are 2 modes (pre- and post-processing), the order of the calls is important.
|
||||
55
internal/use-case/_use-case-template/crud/case.go
Normal file
55
internal/use-case/_use-case-template/crud/case.go
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Any functions that are available to be used externally.
|
||||
*/
|
||||
package crud
|
||||
|
||||
import (
|
||||
dg "github.com/karincake/apem/db-gorm-pg"
|
||||
d "github.com/karincake/dodol"
|
||||
|
||||
e "simrs-vx/internal/domain/main-entities/single"
|
||||
)
|
||||
|
||||
const source = "crud"
|
||||
|
||||
func Create(input e.Createdto) (*d.Data, error) {
|
||||
result, err := CreateData(input)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &d.Data{
|
||||
Meta: d.II{
|
||||
"source": source,
|
||||
"type": "list",
|
||||
"status": "created",
|
||||
},
|
||||
Data: result,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ReadList(input e.ReadListDto) (*d.Data, error) {
|
||||
data := d.Data{}
|
||||
query := dg.I
|
||||
query.Find(&data)
|
||||
if err := query.Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &d.Data{
|
||||
Meta: d.II{},
|
||||
Data: data,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func ReadDetail() {
|
||||
|
||||
}
|
||||
|
||||
func Update() {
|
||||
|
||||
}
|
||||
|
||||
func Delete() {
|
||||
|
||||
}
|
||||
13
internal/use-case/_use-case-template/crud/helper.go
Normal file
13
internal/use-case/_use-case-template/crud/helper.go
Normal file
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
Any functions that are used internally by the use-case
|
||||
*/
|
||||
package crud
|
||||
|
||||
import (
|
||||
e "simrs-vx/internal/domain/main-entities/single"
|
||||
)
|
||||
|
||||
func setData(src e.Createdto, dst *e.Single) {
|
||||
|
||||
}
|
||||
34
internal/use-case/_use-case-template/crud/lib.go
Normal file
34
internal/use-case/_use-case-template/crud/lib.go
Normal file
@@ -0,0 +1,34 @@
|
||||
package crud
|
||||
|
||||
import (
|
||||
e "simrs-vx/internal/domain/main-entities/single"
|
||||
|
||||
dg "github.com/karincake/apem/db-gorm-pg"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
func CreateData(input e.Createdto) (*e.Single, error) {
|
||||
data := e.Single{}
|
||||
|
||||
err := dg.I.Transaction(func(tx *gorm.DB) error {
|
||||
for i := range createPreMw {
|
||||
if err := createPreMw[i](&input, &data, dg.I); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if err := dg.I.Create(&data).Error; err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
for i := range createPostMw {
|
||||
if err := createPostMw[i](&input, &data, dg.I); err != nil {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return &data, err
|
||||
}
|
||||
10
internal/use-case/_use-case-template/crud/middleware.go
Normal file
10
internal/use-case/_use-case-template/crud/middleware.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package crud
|
||||
|
||||
import (
|
||||
pm "simrs-vx/internal/use-case/plugin/modifier"
|
||||
)
|
||||
|
||||
func init() {
|
||||
createPreMw = append(createPreMw, pm.ModifInput)
|
||||
createPreMw = append(createPreMw, pm.CheckData)
|
||||
}
|
||||
32
internal/use-case/_use-case-template/crud/tycovar.go
Normal file
32
internal/use-case/_use-case-template/crud/tycovar.go
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
DESCRIPTION:
|
||||
A sample, part of the package that contains type, constants, and/or variables.
|
||||
|
||||
In this sample it also provides type and variable regarding the needs of the
|
||||
middleware to separate from main use-case which has the basic CRUD
|
||||
functionality. The purpose of this is to make the code more maintainable.
|
||||
*/
|
||||
package crud
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
|
||||
e "simrs-vx/internal/domain/main-entities/single"
|
||||
)
|
||||
|
||||
type createMw func(input *e.Createdto, data *e.Single, tx *gorm.DB) error
|
||||
type readListMw func(input *e.ReadListDto, data *e.Single, tx *gorm.DB) error
|
||||
type readDetailMw func(input *e.ReadDetailDto, data *e.Single, tx *gorm.DB) error
|
||||
type updateMw func(input *e.ReadDetailDto, data *e.Single, tx *gorm.DB) error
|
||||
type deleteMw func(input *e.ReadDetailDto, data *e.Single, tx *gorm.DB) error
|
||||
|
||||
var createPreMw []createMw // preprocess middleware
|
||||
var createPostMw []createMw // postprocess middleware
|
||||
var readListPreMw []readListMw // ..
|
||||
var readListPostMw []readListMw // ..
|
||||
var readDetailPreMw []readDetailMw
|
||||
var readDetailPostMw []readDetailMw
|
||||
var udpatePreMw []readDetailMw
|
||||
var udpatePostMw []readDetailMw
|
||||
var deletePreMw []readDetailMw
|
||||
var deletePostMw []readDetailMw
|
||||
0
internal/use-case/main-use-case/.keep
Normal file
0
internal/use-case/main-use-case/.keep
Normal file
0
internal/use-case/plugin/.keep
Normal file
0
internal/use-case/plugin/.keep
Normal file
0
pkg/middleware/.keep
Normal file
0
pkg/middleware/.keep
Normal file
52
pkg/middleware/handler-logger/handler-logger.go
Normal file
52
pkg/middleware/handler-logger/handler-logger.go
Normal file
@@ -0,0 +1,52 @@
|
||||
package handlerloggermw
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
l "github.com/karincake/apem/loggera"
|
||||
lo "github.com/karincake/apem/loggero"
|
||||
)
|
||||
|
||||
var Logger l.LoggerItf
|
||||
|
||||
type wrappedWriter struct {
|
||||
http.ResponseWriter
|
||||
statusCode int
|
||||
}
|
||||
|
||||
func (w *wrappedWriter) WriteHeader(statusCode int) {
|
||||
w.statusCode = statusCode
|
||||
w.ResponseWriter.WriteHeader(statusCode)
|
||||
}
|
||||
|
||||
func SetLog(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
start := time.Now()
|
||||
wrapped := &wrappedWriter{
|
||||
ResponseWriter: w,
|
||||
statusCode: http.StatusOK,
|
||||
}
|
||||
|
||||
next.ServeHTTP(wrapped, r)
|
||||
Logger.Info().
|
||||
String("scope", "request").
|
||||
Int("status", wrapped.statusCode).
|
||||
String("method", r.Method).
|
||||
String("path", r.URL.Path).
|
||||
String("query", r.URL.RawQuery).
|
||||
String("duration", time.Since(start).String()).Send()
|
||||
})
|
||||
}
|
||||
|
||||
func WriteJson(data any) {
|
||||
lo.I.Println("Showing additional info for the payload")
|
||||
js, err := json.Marshal(data)
|
||||
if err == nil {
|
||||
fmt.Println(string(js))
|
||||
} else {
|
||||
fmt.Println("error converting data or result to json:", err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user