mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-23 23:05:44 +00:00
Feat[BE-261]: creating Entity and repository for each table expenses
This commit is contained in:
@@ -1,18 +1,30 @@
|
|||||||
package entities
|
package entities
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"database/sql"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Expense struct {
|
type Expense struct {
|
||||||
Id uint `gorm:"primaryKey"`
|
Id uint64 `gorm:"primaryKey;autoIncrement"`
|
||||||
Name string `gorm:"not null;uniqueIndex:idx_name,where:deleted_at IS NULL"`
|
ReferenceNumber *string `gorm:"type:varchar(50)"`
|
||||||
CreatedBy uint `gorm:"not null"`
|
SupplierId *uint64 `gorm:""`
|
||||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
Category string `gorm:"type:varchar(50);not null"`
|
||||||
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
PoNumber string `gorm:"uniqueIndex;not null;type:varchar(50)"`
|
||||||
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
DocumentPath sql.NullString `gorm:"type:json"`
|
||||||
|
ExpenseDate time.Time `gorm:"type:date;not null"`
|
||||||
|
GrandTotal float64 `gorm:"type:numeric(15,3);default:0"`
|
||||||
|
Note *string `gorm:"type:text"`
|
||||||
|
CreatedBy *uint64 `gorm:""`
|
||||||
|
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||||
|
|
||||||
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
|
// Relations
|
||||||
|
Supplier *Supplier `gorm:"foreignKey:SupplierId;references:Id"`
|
||||||
|
CreatedUser *User `gorm:"foreignKey:CreatedBy;references:Id"`
|
||||||
|
Nonstocks []ExpenseNonstock `gorm:"foreignKey:ExpenseId;references:Id"`
|
||||||
|
LatestApproval *Approval `gorm:"-" json:"latest_approval,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
package entities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExpenseNonstock struct {
|
||||||
|
Id uint64 `gorm:"primaryKey;autoIncrement"`
|
||||||
|
ExpenseId *uint64 `gorm:""`
|
||||||
|
ProjectFlockKandangId *uint64 `gorm:""`
|
||||||
|
NonstockId *uint64 `gorm:""`
|
||||||
|
Qty float64 `gorm:"type:numeric(15,3);not null"`
|
||||||
|
UnitPrice float64 `gorm:"type:numeric(15,3);not null"`
|
||||||
|
TotalPrice float64 `gorm:"type:numeric(15,3);not null"`
|
||||||
|
Note *string `gorm:"type:text"`
|
||||||
|
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
Expense *Expense `gorm:"foreignKey:ExpenseId;references:Id"`
|
||||||
|
ProjectFlockKandang *ProjectFlockKandang `gorm:"foreignKey:ProjectFlockKandangId;references:Id"`
|
||||||
|
Nonstock *Nonstock `gorm:"foreignKey:NonstockId;references:Id"`
|
||||||
|
Realizations []ExpenseRealization `gorm:"foreignKey:ExpenseNonstockId;references:Id"`
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package entities
|
||||||
|
|
||||||
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExpenseRealization struct {
|
||||||
|
Id uint64 `gorm:"primaryKey;autoIncrement"`
|
||||||
|
ExpenseNonstockId *uint64 `gorm:""`
|
||||||
|
RealizationQty float64 `gorm:"type:numeric(15,3);not null"`
|
||||||
|
RealizationUnitPrice float64 `gorm:"type:numeric(15,3);not null"`
|
||||||
|
RealizationTotalPrice float64 `gorm:"type:numeric(15,3);not null"`
|
||||||
|
RealizationDate time.Time `gorm:"type:date;not null"`
|
||||||
|
Note *string `gorm:"type:text"`
|
||||||
|
CreatedBy *uint64 `gorm:""`
|
||||||
|
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||||
|
UpdatedAt time.Time `gorm:"autoUpdateTime"`
|
||||||
|
DeletedAt gorm.DeletedAt `gorm:"index" json:"-"`
|
||||||
|
|
||||||
|
// Relations
|
||||||
|
ExpenseNonstock *ExpenseNonstock `gorm:"foreignKey:ExpenseNonstockId;references:Id"`
|
||||||
|
CreatedUser *User `gorm:"foreignKey:CreatedBy;references:Id"`
|
||||||
|
}
|
||||||
@@ -10,44 +10,52 @@ import (
|
|||||||
// === DTO Structs ===
|
// === DTO Structs ===
|
||||||
|
|
||||||
type ExpenseBaseDTO struct {
|
type ExpenseBaseDTO struct {
|
||||||
Id uint `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
Name string `json:"name"`
|
PoNumber string `json:"po_number"`
|
||||||
|
ExpenseDate time.Time `json:"expense_date"`
|
||||||
|
GrandTotal float64 `json:"grand_total"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExpenseListDTO struct {
|
type ExpenseListDTO struct {
|
||||||
Id uint `json:"id"`
|
Id uint64 `json:"id"`
|
||||||
Name string `json:"name"`
|
ReferenceNumber string `json:"reference_number"`
|
||||||
CreatedUser *userDTO.UserBaseDTO `json:"created_user"`
|
PoNumber string `json:"po_number"`
|
||||||
CreatedAt time.Time `json:"created_at"`
|
Category string `json:"category"`
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
ExpenseDate time.Time `json:"expense_date"`
|
||||||
}
|
GrandTotal float64 `json:"grand_total"`
|
||||||
|
CreatedUser *userDTO.UserBaseDTO `json:"created_user,omitempty"`
|
||||||
type ExpenseDetailDTO struct {
|
CreatedAt time.Time `json:"created_at"`
|
||||||
ExpenseListDTO
|
UpdatedAt time.Time `json:"updated_at"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// === Mapper Functions ===
|
// === Mapper Functions ===
|
||||||
|
|
||||||
func ToExpenseBaseDTO(e entity.Expense) ExpenseBaseDTO {
|
func ToExpenseBaseDTO(e entity.Expense) ExpenseBaseDTO {
|
||||||
return ExpenseBaseDTO{
|
return ExpenseBaseDTO{
|
||||||
Id: e.Id,
|
Id: e.Id,
|
||||||
Name: e.Name,
|
PoNumber: e.PoNumber,
|
||||||
|
ExpenseDate: e.ExpenseDate,
|
||||||
|
GrandTotal: e.GrandTotal,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToExpenseListDTO(e entity.Expense) ExpenseListDTO {
|
func ToExpenseListDTO(e entity.Expense) ExpenseListDTO {
|
||||||
var createdUser *userDTO.UserBaseDTO
|
var createdUser *userDTO.UserBaseDTO
|
||||||
if e.CreatedUser.Id != 0 {
|
if e.CreatedUser.Id != 0 {
|
||||||
mapped := userDTO.ToUserBaseDTO(e.CreatedUser)
|
mapped := userDTO.ToUserBaseDTO(*e.CreatedUser)
|
||||||
createdUser = &mapped
|
createdUser = &mapped
|
||||||
}
|
}
|
||||||
|
|
||||||
return ExpenseListDTO{
|
return ExpenseListDTO{
|
||||||
Id: e.Id,
|
Id: e.Id,
|
||||||
Name: e.Name,
|
ReferenceNumber: *e.ReferenceNumber,
|
||||||
CreatedAt: e.CreatedAt,
|
PoNumber: e.PoNumber,
|
||||||
UpdatedAt: e.UpdatedAt,
|
Category: e.Category,
|
||||||
CreatedUser: createdUser,
|
ExpenseDate: e.ExpenseDate,
|
||||||
|
GrandTotal: e.GrandTotal,
|
||||||
|
CreatedAt: e.CreatedAt,
|
||||||
|
UpdatedAt: e.UpdatedAt,
|
||||||
|
CreatedUser: createdUser,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,9 +66,3 @@ func ToExpenseListDTOs(e []entity.Expense) []ExpenseListDTO {
|
|||||||
}
|
}
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func ToExpenseDetailDTO(e entity.Expense) ExpenseDetailDTO {
|
|
||||||
return ExpenseDetailDTO{
|
|
||||||
ExpenseListDTO: ToExpenseListDTO(e),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
package repository
|
package repository
|
||||||
|
|
||||||
import (
|
import (
|
||||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
"context"
|
||||||
|
|
||||||
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ExpenseRepository interface {
|
type ExpenseRepository interface {
|
||||||
repository.BaseRepository[entity.Expense]
|
repository.BaseRepository[entity.Expense]
|
||||||
|
IdExists(ctx context.Context, id uint64) (bool, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type ExpenseRepositoryImpl struct {
|
type ExpenseRepositoryImpl struct {
|
||||||
@@ -19,3 +22,7 @@ func NewExpenseRepository(db *gorm.DB) ExpenseRepository {
|
|||||||
BaseRepositoryImpl: repository.NewBaseRepository[entity.Expense](db),
|
BaseRepositoryImpl: repository.NewBaseRepository[entity.Expense](db),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *ExpenseRepositoryImpl) IdExists(ctx context.Context, id uint64) (bool, error) {
|
||||||
|
return repository.Exists[entity.Expense](ctx, r.DB(), uint(id))
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExpenseNonstockRepository interface {
|
||||||
|
repository.BaseRepository[entity.ExpenseNonstock]
|
||||||
|
IdExists(ctx context.Context, id uint64) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExpenseNonstockRepositoryImpl struct {
|
||||||
|
*repository.BaseRepositoryImpl[entity.ExpenseNonstock]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExpenseNonstockRepository(db *gorm.DB) ExpenseNonstockRepository {
|
||||||
|
return &ExpenseNonstockRepositoryImpl{
|
||||||
|
BaseRepositoryImpl: repository.NewBaseRepository[entity.ExpenseNonstock](db),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ExpenseNonstockRepositoryImpl) IdExists(ctx context.Context, id uint64) (bool, error) {
|
||||||
|
return repository.Exists[entity.ExpenseNonstock](ctx, r.DB(), uint(id))
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package repository
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||||
|
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ExpenseRealizationRepository interface {
|
||||||
|
repository.BaseRepository[entity.ExpenseRealization]
|
||||||
|
IdExists(ctx context.Context, id uint64) (bool, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
type ExpenseRealizationRepositoryImpl struct {
|
||||||
|
*repository.BaseRepositoryImpl[entity.ExpenseRealization]
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewExpenseRealizationRepository(db *gorm.DB) ExpenseRealizationRepository {
|
||||||
|
return &ExpenseRealizationRepositoryImpl{
|
||||||
|
BaseRepositoryImpl: repository.NewBaseRepository[entity.ExpenseRealization](db),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *ExpenseRealizationRepositoryImpl) IdExists(ctx context.Context, id uint64) (bool, error) {
|
||||||
|
return repository.Exists[entity.ExpenseRealization](ctx, r.DB(), uint(id))
|
||||||
|
}
|
||||||
@@ -79,8 +79,11 @@ func (s *expenseService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createdBy := uint64(1)
|
||||||
createBody := &entity.Expense{
|
createBody := &entity.Expense{
|
||||||
Name: req.Name,
|
PoNumber: req.PoNumber,
|
||||||
|
Category: req.Category,
|
||||||
|
CreatedBy: &createdBy,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
|
if err := s.Repository.CreateOne(c.Context(), createBody, nil); err != nil {
|
||||||
@@ -88,7 +91,7 @@ func (s *expenseService) CreateOne(c *fiber.Ctx, req *validation.Create) (*entit
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.GetOne(c, createBody.Id)
|
return s.GetOne(c, uint(createBody.Id))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) (*entity.Expense, error) {
|
func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint) (*entity.Expense, error) {
|
||||||
@@ -98,8 +101,11 @@ func (s expenseService) UpdateOne(c *fiber.Ctx, req *validation.Update, id uint)
|
|||||||
|
|
||||||
updateBody := make(map[string]any)
|
updateBody := make(map[string]any)
|
||||||
|
|
||||||
if req.Name != nil {
|
if req.PoNumber != nil {
|
||||||
updateBody["name"] = *req.Name
|
updateBody["po_number"] = *req.PoNumber
|
||||||
|
}
|
||||||
|
if req.Category != nil {
|
||||||
|
updateBody["category"] = *req.Category
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(updateBody) == 0 {
|
if len(updateBody) == 0 {
|
||||||
|
|||||||
@@ -1,11 +1,13 @@
|
|||||||
package validation
|
package validation
|
||||||
|
|
||||||
type Create struct {
|
type Create struct {
|
||||||
Name string `json:"name" validate:"required_strict,min=3"`
|
PoNumber string `json:"po_number" validate:"required,max=50"`
|
||||||
|
Category string `json:"category" validate:"required,max=50"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Update struct {
|
type Update struct {
|
||||||
Name *string `json:"name,omitempty" validate:"omitempty"`
|
PoNumber *string `json:"po_number,omitempty" validate:"omitempty,max=50"`
|
||||||
|
Category *string `json:"category,omitempty" validate:"omitempty,max=50"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
|
|||||||
@@ -241,6 +241,23 @@ var MarketingApprovalSteps = map[approvalutils.ApprovalStep]string{
|
|||||||
MarketingDeliveryOrder: "Delivery Order",
|
MarketingDeliveryOrder: "Delivery Order",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Expense Approval
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
|
||||||
|
const (
|
||||||
|
ApprovalWorkflowExpense approvalutils.ApprovalWorkflowKey = approvalutils.ApprovalWorkflowKey("EXPENSES")
|
||||||
|
ExpenseStepPengajuan approvalutils.ApprovalStep = 1
|
||||||
|
ExpenseStepManager approvalutils.ApprovalStep = 2
|
||||||
|
ExpenseStepFinance approvalutils.ApprovalStep = 3
|
||||||
|
)
|
||||||
|
|
||||||
|
var ExpenseApprovalSteps = map[approvalutils.ApprovalStep]string{
|
||||||
|
ExpenseStepPengajuan: "Pengajuan",
|
||||||
|
ExpenseStepManager: "Manager",
|
||||||
|
ExpenseStepFinance: "Finance",
|
||||||
|
}
|
||||||
|
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
// Validators
|
// Validators
|
||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user