mirror of
https://gitlab.com/mbugroup/lti-api.git
synced 2026-05-20 13:31:56 +00:00
Merge branch 'feat/BE/Sprint-6' of https://gitlab.com/mbugroup/lti-api into feat/BE/US-278/Purchase-Expedition-bop
This commit is contained in:
@@ -8,7 +8,8 @@ type ProductWarehouse struct {
|
||||
Quantity float64 `gorm:"column:qty;type:numeric(15,3);default:0"`
|
||||
|
||||
// Relations
|
||||
Product Product `gorm:"foreignKey:ProductId;references:Id"`
|
||||
Warehouse Warehouse `gorm:"foreignKey:WarehouseId;references:Id"`
|
||||
StockLogs []StockLog `gorm:"foreignKey:ProductWarehouseId;references:Id"`
|
||||
Product Product `gorm:"foreignKey:ProductId;references:Id"`
|
||||
Warehouse Warehouse `gorm:"foreignKey:WarehouseId;references:Id"`
|
||||
ProjectFlockKandang *ProjectFlockKandang `gorm:"foreignKey:ProjectFlockKandangId;references:Id"`
|
||||
StockLogs []StockLog `gorm:"foreignKey:ProductWarehouseId;references:Id"`
|
||||
}
|
||||
|
||||
@@ -5,11 +5,13 @@ import (
|
||||
)
|
||||
|
||||
type ProjectBudget struct {
|
||||
Id uint `gorm:"primaryKey"`
|
||||
Qty float64 `gorm:"type:numeric(15,3);not null"`
|
||||
Price float64 `gorm:"type:numeric(15,3);not null"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
Id uint `gorm:"primaryKey"`
|
||||
ProjectFlockId uint `gorm:"not null"`
|
||||
NonstockId uint `gorm:"not null"`
|
||||
Qty float64 `gorm:"type:numeric(15,3);not null"`
|
||||
Price float64 `gorm:"type:numeric(15,3);not null"`
|
||||
CreatedAt time.Time `gorm:"autoCreateTime"`
|
||||
|
||||
Nonstock *Nonstock `gorm:"foreignKey:Id;references:Id"`
|
||||
ProjectFlock *ProjectFlock `gorm:"foreignKey:Id;references:Id"`
|
||||
Nonstock *Nonstock `gorm:"foreignKey:NonstockId;references:Id"`
|
||||
ProjectFlock *ProjectFlock `gorm:"foreignKey:ProjectFlockId;references:Id"`
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ type ProjectFlock struct {
|
||||
CreatedUser User `gorm:"foreignKey:CreatedBy;references:Id"`
|
||||
Kandangs []Kandang `gorm:"many2many:project_flock_kandangs;joinTableForeignKey:project_flock_id;joinTableReferences:kandang_id" json:"kandangs,omitempty"`
|
||||
KandangHistory []ProjectFlockKandang `gorm:"foreignKey:ProjectFlockId;references:Id" json:"-"`
|
||||
Budgets []ProjectBudget `gorm:"foreignKey:ProjectFlockId;references:Id" json:"-"`
|
||||
|
||||
LatestApproval *Approval `gorm:"-" json:"-"`
|
||||
}
|
||||
|
||||
@@ -53,6 +53,28 @@ func (u *ClosingController) GetAll(c *fiber.Ctx) error {
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ClosingController) GetOne(c *fiber.Ctx) error {
|
||||
param := c.Params("id")
|
||||
|
||||
id, err := strconv.Atoi(param)
|
||||
if err != nil || id <= 0 {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid id")
|
||||
}
|
||||
|
||||
result, err := u.ClosingService.GetProjectFlockByID(c, uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).
|
||||
JSON(response.Success{
|
||||
Code: fiber.StatusOK,
|
||||
Status: "success",
|
||||
Message: "Retrieved closing information successfully",
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ClosingController) GetClosingSummary(c *fiber.Ctx) error {
|
||||
param := c.Params("projectFlockId")
|
||||
|
||||
@@ -74,3 +96,30 @@ func (u *ClosingController) GetClosingSummary(c *fiber.Ctx) error {
|
||||
Data: result,
|
||||
})
|
||||
}
|
||||
|
||||
func (u *ClosingController) GetPenjualan(c *fiber.Ctx) error {
|
||||
param := c.Params("project_flock_id")
|
||||
|
||||
projectFlockID, err := strconv.Atoi(param)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Project Flock Id")
|
||||
}
|
||||
|
||||
projectFlock, err := u.ClosingService.GetProjectFlockByID(c, uint(projectFlockID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
result, err := u.ClosingService.GetPenjualan(c, uint(projectFlockID))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).
|
||||
JSON(response.Success{
|
||||
Code: fiber.StatusOK,
|
||||
Status: "success",
|
||||
Message: "Get closing penjualan successfully",
|
||||
Data: dto.ToPenjualanRealisasiResponseDTO(projectFlock.Category, uint(projectFlockID), result),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -0,0 +1,109 @@
|
||||
package dto
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
deliveryOrdersDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/delivery-orderss/dto"
|
||||
customerDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/customers/dto"
|
||||
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
|
||||
productDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/products/dto"
|
||||
)
|
||||
|
||||
// === Response DTO ===
|
||||
|
||||
type SalesDTO struct {
|
||||
Id uint `json:"id"`
|
||||
RealizationDate time.Time `json:"realization_date"`
|
||||
Age int `json:"age"`
|
||||
DoNumber string `json:"do_number"`
|
||||
Product *productDTO.ProductRelationDTO `json:"product,omitempty"`
|
||||
Customer *customerDTO.CustomerRelationDTO `json:"customer,omitempty"`
|
||||
Qty float64 `json:"qty"`
|
||||
Weight float64 `json:"weight"`
|
||||
AvgWeight float64 `json:"avg_weight"`
|
||||
Price float64 `json:"price"`
|
||||
TotalPrice float64 `json:"total_price"`
|
||||
Kandang *kandangDTO.KandangRelationDTO `json:"kandang,omitempty"`
|
||||
PaymentStatus string `json:"payment_status"`
|
||||
}
|
||||
|
||||
type PenjualanRealisasiResponseDTO struct {
|
||||
ProjectType string `json:"project_type"`
|
||||
FlockId uint `json:"flock_id"`
|
||||
Period int `json:"period"`
|
||||
Sales []SalesDTO `json:"sales"`
|
||||
}
|
||||
|
||||
// === Mapper Functions ===
|
||||
|
||||
func ToSalesDTO(e entity.MarketingDeliveryProduct) SalesDTO {
|
||||
|
||||
// todo: usia ayam masih dummy
|
||||
age := 0
|
||||
|
||||
var product *productDTO.ProductRelationDTO
|
||||
if e.MarketingProduct.ProductWarehouse.Product.Id != 0 {
|
||||
mapped := productDTO.ToProductRelationDTO(e.MarketingProduct.ProductWarehouse.Product)
|
||||
product = &mapped
|
||||
}
|
||||
|
||||
var customer *customerDTO.CustomerRelationDTO
|
||||
if e.MarketingProduct.Marketing.Customer.Id != 0 {
|
||||
mapped := customerDTO.ToCustomerRelationDTO(e.MarketingProduct.Marketing.Customer)
|
||||
customer = &mapped
|
||||
}
|
||||
|
||||
var kandang *kandangDTO.KandangRelationDTO
|
||||
if e.MarketingProduct.ProductWarehouse.ProjectFlockKandang != nil && e.MarketingProduct.ProductWarehouse.ProjectFlockKandang.Kandang.Id != 0 {
|
||||
mapped := kandangDTO.ToKandangRelationDTO(e.MarketingProduct.ProductWarehouse.ProjectFlockKandang.Kandang)
|
||||
kandang = &mapped
|
||||
}
|
||||
|
||||
doNumber := deliveryOrdersDTO.GenerateDeliveryOrderNumber(e.MarketingProduct.Marketing.SoNumber, e.DeliveryDate, e.MarketingProduct.ProductWarehouse.Warehouse.Id)
|
||||
|
||||
return SalesDTO{
|
||||
Id: e.Id,
|
||||
RealizationDate: *e.DeliveryDate,
|
||||
Age: age,
|
||||
DoNumber: doNumber,
|
||||
Product: product,
|
||||
Customer: customer,
|
||||
Qty: e.Qty,
|
||||
Weight: e.TotalWeight,
|
||||
AvgWeight: e.AvgWeight,
|
||||
Price: e.UnitPrice,
|
||||
TotalPrice: e.TotalPrice,
|
||||
Kandang: kandang,
|
||||
PaymentStatus: "Paid",
|
||||
}
|
||||
}
|
||||
|
||||
func ToSalesDTOs(e []entity.MarketingDeliveryProduct) []SalesDTO {
|
||||
result := make([]SalesDTO, len(e))
|
||||
for i, r := range e {
|
||||
result[i] = ToSalesDTO(r)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func ToPenjualanRealisasiResponseDTO(projectType string, projectFlockID uint, e []entity.MarketingDeliveryProduct) PenjualanRealisasiResponseDTO {
|
||||
period := extractPeriodFromRealisasi(e)
|
||||
return PenjualanRealisasiResponseDTO{
|
||||
ProjectType: projectType,
|
||||
FlockId: projectFlockID,
|
||||
Period: period,
|
||||
Sales: ToSalesDTOs(e),
|
||||
}
|
||||
}
|
||||
|
||||
func extractPeriodFromRealisasi(realisasi []entity.MarketingDeliveryProduct) int {
|
||||
if len(realisasi) > 0 {
|
||||
for _, item := range realisasi {
|
||||
if item.MarketingProduct.ProductWarehouse.ProjectFlockKandang != nil {
|
||||
return item.MarketingProduct.ProductWarehouse.ProjectFlockKandang.Period
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
rClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories"
|
||||
sClosing "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/services"
|
||||
rMarketings "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||
rProjectFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
|
||||
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||
sUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||
)
|
||||
@@ -18,11 +21,13 @@ type ClosingModule struct{}
|
||||
func (ClosingModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
|
||||
closingRepo := rClosing.NewClosingRepository(db)
|
||||
userRepo := rUser.NewUserRepository(db)
|
||||
|
||||
projectFlockRepo := rProjectFlock.NewProjectflockRepository(db)
|
||||
marketingRepo := rMarketings.NewMarketingRepository(db)
|
||||
marketingDeliveryProductRepo := rMarketings.NewMarketingDeliveryProductRepository(db)
|
||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||
approvalService := commonSvc.NewApprovalService(approvalRepo)
|
||||
|
||||
closingService := sClosing.NewClosingService(closingRepo, approvalService, validate)
|
||||
closingService := sClosing.NewClosingService(closingRepo, projectFlockRepo, marketingRepo, marketingDeliveryProductRepo, approvalService, validate)
|
||||
userService := sUser.NewUserService(userRepo, validate)
|
||||
|
||||
ClosingRoutes(router, userService, closingService)
|
||||
|
||||
@@ -21,5 +21,6 @@ func ClosingRoutes(v1 fiber.Router, u user.UserService, s closing.ClosingService
|
||||
// route.Delete("/:id", m.Auth(u), ctrl.DeleteOne)
|
||||
|
||||
route.Get("/", ctrl.GetAll)
|
||||
route.Get("/:project_flock_id/penjualan", ctrl.GetPenjualan)
|
||||
route.Get("/:projectFlockId", ctrl.GetClosingSummary)
|
||||
}
|
||||
|
||||
@@ -9,6 +9,9 @@ import (
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/modules/closings/dto"
|
||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/repositories"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/closings/validations"
|
||||
marketingDeliveryProductRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||
marketingRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||
projectflockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/utils"
|
||||
approvalutils "gitlab.com/mbugroup/lti-api.git/internal/utils/approvals"
|
||||
|
||||
@@ -20,22 +23,30 @@ import (
|
||||
|
||||
type ClosingService interface {
|
||||
GetAll(ctx *fiber.Ctx, params *validation.Query) ([]entity.ProjectFlock, int64, error)
|
||||
GetProjectFlockByID(ctx *fiber.Ctx, id uint) (*entity.ProjectFlock, error)
|
||||
GetPenjualan(ctx *fiber.Ctx, projectFlockID uint) ([]entity.MarketingDeliveryProduct, error)
|
||||
GetClosingSummary(ctx *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error)
|
||||
}
|
||||
|
||||
type closingService struct {
|
||||
Log *logrus.Logger
|
||||
Validate *validator.Validate
|
||||
Repository repository.ClosingRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
Log *logrus.Logger
|
||||
Validate *validator.Validate
|
||||
Repository repository.ClosingRepository
|
||||
ProjectFlockRepo projectflockRepository.ProjectflockRepository
|
||||
MarketingRepo marketingRepository.MarketingRepository
|
||||
MarketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
}
|
||||
|
||||
func NewClosingService(repo repository.ClosingRepository, approvalSvc commonSvc.ApprovalService, validate *validator.Validate) ClosingService {
|
||||
func NewClosingService(repo repository.ClosingRepository, projectFlockRepo projectflockRepository.ProjectflockRepository, marketingRepo marketingRepository.MarketingRepository, marketingDeliveryProductRepo marketingDeliveryProductRepository.MarketingDeliveryProductRepository, approvalSvc commonSvc.ApprovalService, validate *validator.Validate) ClosingService {
|
||||
return &closingService{
|
||||
Log: utils.Log,
|
||||
Validate: validate,
|
||||
Repository: repo,
|
||||
ApprovalSvc: approvalSvc,
|
||||
Log: utils.Log,
|
||||
Validate: validate,
|
||||
Repository: repo,
|
||||
ProjectFlockRepo: projectFlockRepo,
|
||||
MarketingRepo: marketingRepo,
|
||||
MarketingDeliveryProductRepo: marketingDeliveryProductRepo,
|
||||
ApprovalSvc: approvalSvc,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,6 +82,43 @@ func (s closingService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity
|
||||
return closings, total, nil
|
||||
}
|
||||
|
||||
func (s closingService) GetProjectFlockByID(c *fiber.Ctx, id uint) (*entity.ProjectFlock, error) {
|
||||
projectFlock, err := s.ProjectFlockRepo.GetByID(c.Context(), id, s.withRelations)
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "Project Flock not found")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return projectFlock, nil
|
||||
}
|
||||
|
||||
func (s closingService) GetPenjualan(c *fiber.Ctx, projectFlockID uint) ([]entity.MarketingDeliveryProduct, error) {
|
||||
|
||||
realisasi, err := s.MarketingDeliveryProductRepo.GetDeliveryProductsByProjectFlockID(c.Context(), projectFlockID, func(db *gorm.DB) *gorm.DB {
|
||||
return db.
|
||||
Preload("MarketingProduct").
|
||||
Preload("MarketingProduct.ProductWarehouse").
|
||||
Preload("MarketingProduct.ProductWarehouse.Product").
|
||||
Preload("MarketingProduct.ProductWarehouse.Product.ProductCategory").
|
||||
Preload("MarketingProduct.ProductWarehouse.Product.Uom").
|
||||
Preload("MarketingProduct.ProductWarehouse.Product.Flags").
|
||||
Preload("MarketingProduct.ProductWarehouse.Warehouse").
|
||||
Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang").
|
||||
Preload("MarketingProduct.ProductWarehouse.ProjectFlockKandang.Kandang").
|
||||
Preload("MarketingProduct.Marketing").
|
||||
Preload("MarketingProduct.Marketing.Customer").
|
||||
Order("marketing_delivery_products.delivery_date DESC")
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(realisasi) == 0 {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "Penjualan realisasi not found")
|
||||
}
|
||||
return realisasi, nil
|
||||
}
|
||||
|
||||
func (s closingService) GetClosingSummary(c *fiber.Ctx, projectFlockID uint) (*dto.ClosingSummaryDTO, error) {
|
||||
if projectFlockID == 0 {
|
||||
return nil, fiber.NewError(fiber.StatusBadRequest, "Invalid project flock id")
|
||||
|
||||
@@ -151,12 +151,16 @@ func (u *ExpenseController) UpdateOne(c *fiber.Ctx) error {
|
||||
}
|
||||
|
||||
req.Documents = form.File["documents"]
|
||||
if transactionDate := c.FormValue("transaction_date"); transactionDate != "" {
|
||||
|
||||
transactionDate := c.FormValue("transaction_date")
|
||||
if transactionDate != "" {
|
||||
req.TransactionDate = &transactionDate
|
||||
}
|
||||
|
||||
categoryVal := c.FormValue("category")
|
||||
req.Category = &categoryVal
|
||||
if categoryVal != "" {
|
||||
req.Category = &categoryVal
|
||||
}
|
||||
|
||||
supplierIDVal := c.FormValue("supplier_id")
|
||||
if supplierIDVal != "" {
|
||||
@@ -312,13 +316,18 @@ func (u *ExpenseController) UpdateRealization(c *fiber.Ctx) error {
|
||||
|
||||
req.Documents = form.File["documents"]
|
||||
|
||||
req.RealizationDate = c.FormValue("realization_date")
|
||||
realizationDate := c.FormValue("realization_date")
|
||||
if realizationDate != "" {
|
||||
req.RealizationDate = &realizationDate
|
||||
}
|
||||
|
||||
realizationsJSON := c.FormValue("realizations")
|
||||
if realizationsJSON != "" {
|
||||
if err := json.Unmarshal([]byte(realizationsJSON), &req.Realizations); err != nil {
|
||||
var realizations []validation.RealizationItem
|
||||
if err := json.Unmarshal([]byte(realizationsJSON), &realizations); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Invalid realizations JSON: %v", err))
|
||||
}
|
||||
req.Realizations = &realizations
|
||||
}
|
||||
|
||||
expense, err := u.ExpenseService.UpdateRealization(c, uint(id), &req)
|
||||
|
||||
@@ -14,6 +14,8 @@ func ExpenseRoutes(v1 fiber.Router, u user.UserService, s expense.ExpenseService
|
||||
|
||||
route := v1.Group("/expenses")
|
||||
route.Use(m.Auth(u))
|
||||
|
||||
// route.Use(m.Auth(u))
|
||||
// route.Get("/", m.Auth(u), ctrl.GetAll)
|
||||
// route.Post("/", m.Auth(u), ctrl.CreateOne)
|
||||
// route.Get("/:id", m.Auth(u), ctrl.GetOne)
|
||||
|
||||
@@ -732,10 +732,10 @@ func (s *expenseService) UpdateRealization(c *fiber.Ctx, expenseID uint, req *va
|
||||
expenseRepoTx := repository.NewExpenseRepository(tx)
|
||||
|
||||
// Check if only updating documents
|
||||
updateDataOnly := len(req.Realizations) == 0 && len(req.Documents) > 0
|
||||
updateDataOnly := req.Realizations == nil && len(req.Documents) > 0
|
||||
|
||||
if len(req.Realizations) > 0 {
|
||||
for _, realizationItem := range req.Realizations {
|
||||
if req.Realizations != nil {
|
||||
for _, realizationItem := range *req.Realizations {
|
||||
|
||||
expenseNonstockID := realizationItem.ExpenseNonstockID
|
||||
|
||||
@@ -770,6 +770,12 @@ func (s *expenseService) UpdateRealization(c *fiber.Ctx, expenseID uint, req *va
|
||||
|
||||
}
|
||||
|
||||
if req.RealizationDate != nil {
|
||||
if err := expenseRepoTx.PatchOne(c.Context(), expenseID, map[string]interface{}{"realization_date": *req.RealizationDate}, nil); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to update realization date")
|
||||
}
|
||||
}
|
||||
|
||||
if len(req.Documents) > 0 {
|
||||
if err := s.processDocuments(c, expenseRepoTx, expenseID, req.Documents, true); err != nil {
|
||||
return err
|
||||
|
||||
@@ -5,11 +5,11 @@ import (
|
||||
)
|
||||
|
||||
type Create struct {
|
||||
PoNumber string `form:"po_number" json:"po_number" validate:"omitempty,max=50"`
|
||||
TransactionDate string `form:"transaction_date" json:"transaction_date" validate:"required,datetime=2006-01-02"`
|
||||
Category string `form:"category" json:"category" validate:"required,oneof=BOP NON-BOP"`
|
||||
SupplierID uint64 `form:"supplier_id" json:"supplier_id" validate:"required,gt=0"`
|
||||
Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
|
||||
PoNumber string `form:"po_number" json:"po_number" validate:"omitempty,max=50"`
|
||||
TransactionDate string `form:"transaction_date" json:"transaction_date" validate:"required,datetime=2006-01-02"`
|
||||
Category string `form:"category" json:"category" validate:"required,oneof=BOP NON-BOP"`
|
||||
SupplierID uint64 `form:"supplier_id" json:"supplier_id" validate:"required,gt=0"`
|
||||
Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
|
||||
ExpenseNonstocks []ExpenseNonstock `form:"expense_nonstocks" json:"expense_nonstocks" validate:"required,min=1,dive"`
|
||||
}
|
||||
|
||||
@@ -26,11 +26,11 @@ type CostItem struct {
|
||||
}
|
||||
|
||||
type Update struct {
|
||||
TransactionDate *string `form:"transaction_date" json:"transaction_date" validate:"omitempty,datetime=2006-01-02"`
|
||||
Category *string `form:"category" json:"category" validate:"omitempty,oneof=BOP NON-BOP"`
|
||||
SupplierID *uint64 `form:"supplier_id" json:"supplier_id" validate:"omitempty,gt=0"`
|
||||
TransactionDate *string `form:"transaction_date" json:"transaction_date" validate:"omitempty,datetime=2006-01-02"`
|
||||
Category *string `form:"category" json:"category" validate:"omitempty,oneof=BOP NON-BOP"`
|
||||
SupplierID *uint64 `form:"supplier_id" json:"supplier_id" validate:"omitempty,gt=0"`
|
||||
Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
|
||||
ExpenseNonstocks *[]ExpenseNonstock `form:"expense_nonstocks" json:"expense_nonstocks" validate:"omitempty,min=1,dive"`
|
||||
Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
|
||||
}
|
||||
|
||||
type Query struct {
|
||||
@@ -46,9 +46,9 @@ type CreateRealization struct {
|
||||
}
|
||||
|
||||
type UpdateRealization struct {
|
||||
RealizationDate string `form:"realization_date" json:"realization_date" validate:"omitempty,datetime=2006-01-02"`
|
||||
RealizationDate *string `form:"realization_date" json:"realization_date" validate:"omitempty,datetime=2006-01-02"`
|
||||
Documents []*multipart.FileHeader `form:"documents" json:"documents" validate:"omitempty,dive"`
|
||||
Realizations []RealizationItem `form:"realizations" json:"realizations" validate:"required,min=1,dive"`
|
||||
Realizations *[]RealizationItem `form:"realizations" json:"realizations" validate:"omitempty,min=1,dive"`
|
||||
}
|
||||
|
||||
type RealizationItem struct {
|
||||
|
||||
@@ -198,7 +198,7 @@ func (s *adjustmentService) AdjustmentHistory(c *fiber.Ctx, query *validation.Qu
|
||||
|
||||
db = s.withRelations(db)
|
||||
|
||||
db = db.Where("log_type = ?", entity.LogTypeAdjustment)
|
||||
db = db.Where("loggable_type = ?", entity.LogTypeAdjustment)
|
||||
|
||||
if query.TransactionType != "" {
|
||||
db = db.Where("transaction_type = ?", strings.ToUpper(query.TransactionType))
|
||||
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
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 MarketingDeliveryProductRepository interface {
|
||||
repository.BaseRepository[entity.MarketingDeliveryProduct]
|
||||
GetByMarketingProductID(ctx context.Context, marketingProductID uint) (*entity.MarketingDeliveryProduct, error)
|
||||
GetByMarketingId(ctx context.Context, marketingId uint) ([]entity.MarketingDeliveryProduct, error)
|
||||
}
|
||||
|
||||
type MarketingDeliveryProductRepositoryImpl struct {
|
||||
*repository.BaseRepositoryImpl[entity.MarketingDeliveryProduct]
|
||||
}
|
||||
|
||||
func NewMarketingDeliveryProductRepository(db *gorm.DB) MarketingDeliveryProductRepository {
|
||||
return &MarketingDeliveryProductRepositoryImpl{
|
||||
BaseRepositoryImpl: repository.NewBaseRepository[entity.MarketingDeliveryProduct](db),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MarketingDeliveryProductRepositoryImpl) GetByMarketingProductID(ctx context.Context, marketingProductID uint) (*entity.MarketingDeliveryProduct, error) {
|
||||
var deliveryProduct entity.MarketingDeliveryProduct
|
||||
if err := r.DB().WithContext(ctx).Where("marketing_product_id = ?", marketingProductID).First(&deliveryProduct).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &deliveryProduct, nil
|
||||
}
|
||||
|
||||
func (r *MarketingDeliveryProductRepositoryImpl) GetByMarketingId(ctx context.Context, marketingId uint) ([]entity.MarketingDeliveryProduct, error) {
|
||||
var deliveryProducts []entity.MarketingDeliveryProduct
|
||||
|
||||
// Raw query untuk mengambil delivery products berdasarkan marketing ID dengan preload MarketingProduct
|
||||
// Filter: hanya ambil yang sudah memiliki delivery_date (delivery date tidak null)
|
||||
if err := r.DB().WithContext(ctx).
|
||||
Preload("MarketingProduct").
|
||||
Joins("INNER JOIN marketing_products mp ON marketing_delivery_products.marketing_product_id = mp.id").
|
||||
Where("mp.marketing_id = ?", marketingId).
|
||||
Where("marketing_delivery_products.delivery_date IS NOT NULL").
|
||||
Order("marketing_delivery_products.id ASC").
|
||||
Find(&deliveryProducts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deliveryProducts, nil
|
||||
}
|
||||
@@ -44,7 +44,7 @@ func (s productWarehouseService) withRelations(db *gorm.DB) *gorm.DB {
|
||||
Preload("Warehouse.Location").
|
||||
Preload("Warehouse.Area").
|
||||
Preload("Warehouse.Kandang").
|
||||
Preload("CreatedUser")
|
||||
Preload("ProjectFlockKandang")
|
||||
}
|
||||
|
||||
func (s productWarehouseService) GetAll(c *fiber.Ctx, params *validation.Query) ([]entity.ProductWarehouse, int64, error) {
|
||||
@@ -104,7 +104,7 @@ func (s productWarehouseService) GetAll(c *fiber.Ctx, params *validation.Query)
|
||||
|
||||
db = s.Repository.ApplyFlagsFilter(db, cleanFlags)
|
||||
|
||||
return db.Order("created_at DESC").Order("updated_at DESC")
|
||||
return db.Order("product_warehouses.id DESC")
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
|
||||
@@ -319,15 +319,20 @@ func groupDeliveryProducts(products []MarketingDeliveryProductDTO, soNumber stri
|
||||
})
|
||||
|
||||
for i := range groups {
|
||||
if groups[i].DeliveryDate != nil {
|
||||
dateStr := groups[i].DeliveryDate.Format("20060102")
|
||||
groups[i].DoNumber = fmt.Sprintf("%s-%s-%d", soNumber, dateStr, groups[i].Warehouse.Id)
|
||||
}
|
||||
groups[i].DoNumber = GenerateDeliveryOrderNumber(soNumber, groups[i].DeliveryDate, groups[i].Warehouse.Id)
|
||||
}
|
||||
|
||||
return groups
|
||||
}
|
||||
|
||||
func GenerateDeliveryOrderNumber(soNumber string, deliveryDate *time.Time, warehouseId uint) string {
|
||||
dateStr := ""
|
||||
if deliveryDate != nil {
|
||||
dateStr = deliveryDate.Format("20060102")
|
||||
}
|
||||
return fmt.Sprintf("%s-%s-%d", soNumber, dateStr, warehouseId)
|
||||
}
|
||||
|
||||
func getVehicleNumber(e entity.MarketingProduct) string {
|
||||
if e.DeliveryProduct != nil && e.DeliveryProduct.VehicleNumber != "" {
|
||||
return e.DeliveryProduct.VehicleNumber
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
|
||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
rMarketingDeliveryProduct "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories"
|
||||
sDeliveryOrders "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/delivery-orderss/services"
|
||||
rMarketing "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||
rUser "gitlab.com/mbugroup/lti-api.git/internal/modules/users/repositories"
|
||||
@@ -22,7 +21,7 @@ type DeliveryOrdersModule struct{}
|
||||
func (DeliveryOrdersModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
|
||||
marketingRepo := rMarketing.NewMarketingRepository(db)
|
||||
marketingProductRepo := rMarketing.NewMarketingProductRepository(db)
|
||||
marketingDeliveryProductRepo := rMarketingDeliveryProduct.NewMarketingDeliveryProductRepository(db)
|
||||
marketingDeliveryProductRepo := rMarketing.NewMarketingDeliveryProductRepository(db)
|
||||
userRepo := rUser.NewUserRepository(db)
|
||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||
approvalSvc := commonSvc.NewApprovalService(approvalRepo)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package delivery_orderss
|
||||
|
||||
import (
|
||||
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/delivery-orderss/controllers"
|
||||
deliveryOrders "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/delivery-orderss/services"
|
||||
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||
@@ -17,6 +17,7 @@ func DeliveryOrdersRoutes(v1 fiber.Router, u user.UserService, s deliveryOrders.
|
||||
|
||||
// Sisanya di group /delivery-orders
|
||||
route := v1.Group("/delivery-orders")
|
||||
route.Use(m.Auth(u))
|
||||
|
||||
// route.Get("/", m.Auth(u), ctrl.GetAll)
|
||||
// route.Post("/", m.Auth(u), ctrl.CreateOne)
|
||||
|
||||
@@ -8,9 +8,8 @@ import (
|
||||
|
||||
commonRepo "gitlab.com/mbugroup/lti-api.git/internal/common/repository"
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
marketingDeliveryProductRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||
"gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/delivery-orderss/dto"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/delivery-orderss/validations"
|
||||
@@ -35,14 +34,14 @@ type deliveryOrdersService struct {
|
||||
Validate *validator.Validate
|
||||
MarketingRepo marketingRepo.MarketingRepository
|
||||
MarketingProductRepo marketingRepo.MarketingProductRepository
|
||||
MarketingDeliveryProductRepo marketingDeliveryProductRepo.MarketingDeliveryProductRepository
|
||||
MarketingDeliveryProductRepo marketingRepo.MarketingDeliveryProductRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
}
|
||||
|
||||
func NewDeliveryOrdersService(
|
||||
marketingRepo marketingRepo.MarketingRepository,
|
||||
marketingProductRepo marketingRepo.MarketingProductRepository,
|
||||
marketingDeliveryProductRepo marketingDeliveryProductRepo.MarketingDeliveryProductRepository,
|
||||
marketingDeliveryProductRepo marketingRepo.MarketingDeliveryProductRepository,
|
||||
approvalSvc commonSvc.ApprovalService,
|
||||
validate *validator.Validate,
|
||||
) DeliveryOrdersService {
|
||||
@@ -200,7 +199,7 @@ func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create)
|
||||
err = s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||||
|
||||
marketingProductRepositoryTx := marketingRepo.NewMarketingProductRepository(dbTransaction)
|
||||
marketingDeliveryProductRepositoryTx := marketingDeliveryProductRepo.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
marketingDeliveryProductRepositoryTx := marketingRepo.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||
|
||||
allMarketingProducts, err := marketingProductRepositoryTx.GetByMarketingID(c.Context(), req.MarketingId)
|
||||
@@ -259,7 +258,6 @@ func (s *deliveryOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create)
|
||||
|
||||
}
|
||||
|
||||
|
||||
approvalAction := entity.ApprovalActionApproved
|
||||
if _, err := approvalSvcTx.CreateApproval(
|
||||
c.Context(),
|
||||
@@ -301,7 +299,7 @@ func (s deliveryOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, i
|
||||
err := s.MarketingRepo.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||||
|
||||
marketingProductRepositoryTx := marketingRepo.NewMarketingProductRepository(dbTransaction)
|
||||
marketingDeliveryProductRepositoryTx := marketingDeliveryProductRepo.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
marketingDeliveryProductRepositoryTx := marketingRepo.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
|
||||
allMarketingProducts, err := marketingProductRepositoryTx.GetByMarketingID(c.Context(), id)
|
||||
if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
|
||||
+55
@@ -1,6 +1,8 @@
|
||||
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"
|
||||
@@ -8,6 +10,9 @@ import (
|
||||
|
||||
type MarketingDeliveryProductRepository interface {
|
||||
repository.BaseRepository[entity.MarketingDeliveryProduct]
|
||||
GetDeliveryProductsByProjectFlockID(ctx context.Context, projectFlockID uint, callback func(*gorm.DB) *gorm.DB) ([]entity.MarketingDeliveryProduct, error)
|
||||
GetByMarketingId(ctx context.Context, marketingId uint) ([]entity.MarketingDeliveryProduct, error)
|
||||
GetByMarketingProductID(ctx context.Context, marketingProductID uint) (*entity.MarketingDeliveryProduct, error)
|
||||
}
|
||||
|
||||
type MarketingDeliveryProductRepositoryImpl struct {
|
||||
@@ -19,3 +24,53 @@ func NewMarketingDeliveryProductRepository(db *gorm.DB) MarketingDeliveryProduct
|
||||
BaseRepositoryImpl: repository.NewBaseRepository[entity.MarketingDeliveryProduct](db),
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MarketingDeliveryProductRepositoryImpl) GetDeliveryProductsByProjectFlockID(ctx context.Context, projectFlockID uint, callback func(*gorm.DB) *gorm.DB) ([]entity.MarketingDeliveryProduct, error) {
|
||||
var deliveryProducts []entity.MarketingDeliveryProduct
|
||||
|
||||
// JOIN digunakan untuk filter WHERE clause ke ProjectFlockID yang berada 3 level relasi atas
|
||||
// Entity relations digunakan di Preload (callback) untuk load data, bukan untuk filter
|
||||
db := r.DB().WithContext(ctx).
|
||||
Joins("JOIN marketing_products ON marketing_products.id = marketing_delivery_products.marketing_product_id").
|
||||
Joins("JOIN product_warehouses ON product_warehouses.id = marketing_products.product_warehouse_id").
|
||||
Joins("JOIN project_flock_kandangs ON project_flock_kandangs.id = product_warehouses.project_flock_kandang_id").
|
||||
Where("project_flock_kandangs.project_flock_id = ?", projectFlockID).
|
||||
Distinct("marketing_delivery_products.*")
|
||||
|
||||
if callback != nil {
|
||||
db = callback(db)
|
||||
}
|
||||
|
||||
if err := db.Find(&deliveryProducts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deliveryProducts, nil
|
||||
}
|
||||
|
||||
func (r *MarketingDeliveryProductRepositoryImpl) GetByMarketingId(ctx context.Context, marketingId uint) ([]entity.MarketingDeliveryProduct, error) {
|
||||
var deliveryProducts []entity.MarketingDeliveryProduct
|
||||
|
||||
// JOIN untuk filter by marketing_id yang ada di related table
|
||||
db := r.DB().WithContext(ctx).
|
||||
Joins("JOIN marketing_products ON marketing_products.id = marketing_delivery_products.marketing_product_id").
|
||||
Where("marketing_products.marketing_id = ?", marketingId)
|
||||
|
||||
if err := db.Find(&deliveryProducts).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return deliveryProducts, nil
|
||||
}
|
||||
|
||||
func (r *MarketingDeliveryProductRepositoryImpl) GetByMarketingProductID(ctx context.Context, marketingProductID uint) (*entity.MarketingDeliveryProduct, error) {
|
||||
var deliveryProduct entity.MarketingDeliveryProduct
|
||||
|
||||
if err := r.DB().WithContext(ctx).
|
||||
Where("marketing_product_id = ?", marketingProductID).
|
||||
First(&deliveryProduct).Error; err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &deliveryProduct, nil
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package sales_orders
|
||||
|
||||
import (
|
||||
// m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
controller "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/controllers"
|
||||
salesOrders "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/services"
|
||||
user "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
|
||||
@@ -14,6 +14,7 @@ func SalesOrdersRoutes(v1 fiber.Router, u user.UserService, s salesOrders.SalesO
|
||||
|
||||
v1.Delete("/:id", ctrl.DeleteOne)
|
||||
route := v1.Group("/sales-orders")
|
||||
route.Use(m.Auth(u))
|
||||
|
||||
// route.Post("/", m.Auth(u), ctrl.CreateOne)
|
||||
// route.Patch("/:id", m.Auth(u), ctrl.UpdateOne)
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
commonSvc "gitlab.com/mbugroup/lti-api.git/internal/common/service"
|
||||
entity "gitlab.com/mbugroup/lti-api.git/internal/entities"
|
||||
m "gitlab.com/mbugroup/lti-api.git/internal/middleware"
|
||||
rInvMarketingDeliveryProduct "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/marketing-delivery-products/repositories"
|
||||
productWarehouseRepo "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/repositories"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/marketing/sales-orders/validations"
|
||||
@@ -125,7 +124,7 @@ func (s *salesOrdersService) CreateOne(c *fiber.Ctx, req *validation.Create) (*e
|
||||
|
||||
marketingRepoTx := repository.NewMarketingRepository(dbTransaction)
|
||||
marketingProductRepoTx := repository.NewMarketingProductRepository(dbTransaction)
|
||||
invDeliveryRepoTx := rInvMarketingDeliveryProduct.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
invDeliveryRepoTx := repository.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||
|
||||
marketing = &entity.Marketing{
|
||||
@@ -220,7 +219,7 @@ func (s salesOrdersService) UpdateOne(c *fiber.Ctx, req *validation.Update, id u
|
||||
marketingRepoTx := repository.NewMarketingRepository(dbTransaction)
|
||||
marketingProductRepoTx := repository.NewMarketingProductRepository(dbTransaction)
|
||||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||
invDeliveryRepoTx := rInvMarketingDeliveryProduct.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
invDeliveryRepoTx := repository.NewMarketingDeliveryProductRepository(dbTransaction)
|
||||
|
||||
updateBody := make(map[string]any)
|
||||
if req.CustomerId != 0 {
|
||||
@@ -527,7 +526,7 @@ func (s salesOrdersService) Approval(c *fiber.Ctx, req *validation.Approve) ([]e
|
||||
return updated, nil
|
||||
}
|
||||
|
||||
func (s *salesOrdersService) createMarketingProductWithDelivery(ctx context.Context, marketingId uint, rp validation.CreateMarketingProduct, marketingProductRepo repository.MarketingProductRepository, invDeliveryRepo rInvMarketingDeliveryProduct.MarketingDeliveryProductRepository) error {
|
||||
func (s *salesOrdersService) createMarketingProductWithDelivery(ctx context.Context, marketingId uint, rp validation.CreateMarketingProduct, marketingProductRepo repository.MarketingProductRepository, invDeliveryRepo repository.MarketingDeliveryProductRepository) error {
|
||||
|
||||
marketingProduct := &entity.MarketingProduct{
|
||||
MarketingId: marketingId,
|
||||
|
||||
@@ -329,3 +329,29 @@ func (u *ProjectflockController) LookupProjectFlockKandang(c *fiber.Ctx) error {
|
||||
Message: "Get projectflock kandang successfully",
|
||||
Data: dtoResult})
|
||||
}
|
||||
|
||||
func (u *ProjectflockController) Resubmit(c *fiber.Ctx) error {
|
||||
param := c.Params("id")
|
||||
req := new(validation.Resubmit)
|
||||
|
||||
id, err := strconv.Atoi(param)
|
||||
if err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid Id")
|
||||
}
|
||||
if err := c.BodyParser(req); err != nil {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
|
||||
}
|
||||
|
||||
result, err := u.ProjectflockService.Resubmit(c, req, uint(id))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.Status(fiber.StatusOK).
|
||||
JSON(response.Success{
|
||||
Code: fiber.StatusOK,
|
||||
Status: "success",
|
||||
Message: "Resubmit projectflock successfully",
|
||||
Data: dto.ToProjectFlockListDTO(*result),
|
||||
})
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
fcrDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/fcrs/dto"
|
||||
kandangDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/dto"
|
||||
locationDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/locations/dto"
|
||||
nonstockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/dto"
|
||||
|
||||
// pfutils "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/utils"
|
||||
userDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/users/dto"
|
||||
@@ -24,15 +25,16 @@ type ProjectFlockRelationDTO struct {
|
||||
|
||||
type ProjectFlockListDTO struct {
|
||||
ProjectFlockRelationDTO
|
||||
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
|
||||
Category string `json:"category"`
|
||||
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
|
||||
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
|
||||
Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"`
|
||||
CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Approval approvalDTO.ApprovalRelationDTO `json:"approval"`
|
||||
Area *areaDTO.AreaRelationDTO `json:"area,omitempty"`
|
||||
Category string `json:"category"`
|
||||
Fcr *fcrDTO.FcrRelationDTO `json:"fcr,omitempty"`
|
||||
Location *locationDTO.LocationRelationDTO `json:"location,omitempty"`
|
||||
Kandangs []KandangWithProjectFlockIdDTO `json:"kandangs,omitempty"`
|
||||
ProjectBudgets []ProjectBudgetDTO `json:"project_budgets,omitempty"`
|
||||
CreatedUser *userDTO.UserRelationDTO `json:"created_user"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
Approval approvalDTO.ApprovalRelationDTO `json:"approval"`
|
||||
}
|
||||
|
||||
type KandangWithProjectFlockIdDTO struct {
|
||||
@@ -51,6 +53,13 @@ type KandangPeriodSummaryDTO struct {
|
||||
Period int `json:"period"`
|
||||
}
|
||||
|
||||
type ProjectBudgetDTO struct {
|
||||
Id uint `json:"id"`
|
||||
Qty float64 `json:"qty"`
|
||||
Price float64 `json:"price"`
|
||||
Nonstock *nonstockDTO.NonstockRelationDTO `json:"nonstock,omitempty"`
|
||||
}
|
||||
|
||||
func ToProjectFlockListDTOWithPeriod(e entity.ProjectFlock, period int) ProjectFlockListDTO {
|
||||
var createdUser *userDTO.UserRelationDTO
|
||||
if e.CreatedUser.Id != 0 {
|
||||
@@ -110,6 +119,7 @@ func ToProjectFlockListDTOWithPeriod(e entity.ProjectFlock, period int) ProjectF
|
||||
ProjectFlockRelationDTO: createProjectFlockRelationDTO(e, period),
|
||||
Area: areaSummary,
|
||||
Kandangs: kandangSummaries,
|
||||
ProjectBudgets: ToProjectBudgetDTOs(e.Budgets),
|
||||
Category: e.Category,
|
||||
Fcr: fcrSummary,
|
||||
Location: locationSummary,
|
||||
@@ -184,3 +194,26 @@ func createProjectFlockRelationDTO(e entity.ProjectFlock, period int) ProjectFlo
|
||||
FlockName: e.FlockName,
|
||||
}
|
||||
}
|
||||
|
||||
func ToProjectBudgetDTO(e entity.ProjectBudget) ProjectBudgetDTO {
|
||||
var nonstockRef *nonstockDTO.NonstockRelationDTO
|
||||
if e.Nonstock != nil && e.Nonstock.Id != 0 {
|
||||
mapped := nonstockDTO.ToNonstockRelationDTO(*e.Nonstock)
|
||||
nonstockRef = &mapped
|
||||
}
|
||||
|
||||
return ProjectBudgetDTO{
|
||||
Id: e.Id,
|
||||
Qty: e.Qty,
|
||||
Price: e.Price,
|
||||
Nonstock: nonstockRef,
|
||||
}
|
||||
}
|
||||
|
||||
func ToProjectBudgetDTOs(e []entity.ProjectBudget) []ProjectBudgetDTO {
|
||||
result := make([]ProjectBudgetDTO, len(e))
|
||||
for i, r := range e {
|
||||
result[i] = ToProjectBudgetDTO(r)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
@@ -12,7 +12,9 @@ import (
|
||||
rProductWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/inventory/product-warehouses/repositories"
|
||||
rFlock "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
|
||||
rKandang "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
|
||||
rNonstock "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/repositories"
|
||||
rWarehouse "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
|
||||
rProjectBudget "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
rProjectflock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
|
||||
sProjectflock "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/services"
|
||||
@@ -27,10 +29,12 @@ type ProjectflockModule struct{}
|
||||
func (ProjectflockModule) RegisterRoutes(router fiber.Router, db *gorm.DB, validate *validator.Validate) {
|
||||
flockRepo := rFlock.NewFlockRepository(db)
|
||||
kandangRepo := rKandang.NewKandangRepository(db)
|
||||
nonstockRepo := rNonstock.NewNonstockRepository(db)
|
||||
projectflockRepo := rProjectflock.NewProjectflockRepository(db)
|
||||
projectflockKandangRepo := rProjectflock.NewProjectFlockKandangRepository(db)
|
||||
warehouseRepo := rWarehouse.NewWarehouseRepository(db)
|
||||
productWarehouseRepo := rProductWarehouse.NewProductWarehouseRepository(db)
|
||||
projectBudgetRepo := rProjectBudget.NewProjectBudgetRepository(db)
|
||||
userRepo := rUser.NewUserRepository(db)
|
||||
|
||||
approvalRepo := commonRepo.NewApprovalRepository(db)
|
||||
@@ -39,7 +43,7 @@ func (ProjectflockModule) RegisterRoutes(router fiber.Router, db *gorm.DB, valid
|
||||
panic(fmt.Sprintf("failed to register project flock approval workflow: %v", err))
|
||||
}
|
||||
|
||||
projectflockService := sProjectflock.NewProjectflockService(projectflockRepo, flockRepo, kandangRepo, projectflockKandangRepo, warehouseRepo, productWarehouseRepo, approvalService, validate)
|
||||
projectflockService := sProjectflock.NewProjectflockService(projectflockRepo, flockRepo, kandangRepo, projectflockKandangRepo, warehouseRepo, productWarehouseRepo, projectBudgetRepo, nonstockRepo, approvalService, validate)
|
||||
userService := sUser.NewUserService(userRepo, validate)
|
||||
|
||||
ProjectflockRoutes(router, userService, projectflockService)
|
||||
|
||||
@@ -54,7 +54,10 @@ func (r *ProjectflockRepositoryImpl) WithDefaultRelations() func(*gorm.DB) *gorm
|
||||
Preload("Location").
|
||||
Preload("Kandangs").
|
||||
Preload("KandangHistory").
|
||||
Preload("KandangHistory.Kandang")
|
||||
Preload("KandangHistory.Kandang").
|
||||
Preload("Budgets").
|
||||
Preload("Budgets.Nonstock").
|
||||
Preload("Budgets.Nonstock.Uom")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,5 +23,6 @@ func ProjectflockRoutes(v1 fiber.Router, u user.UserService, s projectflock.Proj
|
||||
route.Get("/kandangs/lookup", ctrl.LookupProjectFlockKandang)
|
||||
route.Post("/approvals", ctrl.Approval)
|
||||
route.Get("/locations/:location_id/periods", ctrl.GetPeriodSummary)
|
||||
route.Put("/:id/resubmit", ctrl.Resubmit)
|
||||
|
||||
}
|
||||
|
||||
@@ -15,7 +15,9 @@ import (
|
||||
flockDTO "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/dto"
|
||||
flockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/flocks/repositories"
|
||||
kandangRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/kandangs/repositories"
|
||||
nonstockRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/nonstocks/repositories"
|
||||
warehouseRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/master/warehouses/repositories"
|
||||
projectBudgetRepository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
repository "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/repositories"
|
||||
pfutils "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/utils"
|
||||
validation "gitlab.com/mbugroup/lti-api.git/internal/modules/production/project_flocks/validations"
|
||||
@@ -39,6 +41,7 @@ type ProjectflockService interface {
|
||||
GetPeriodSummary(ctx *fiber.Ctx, locationID uint) ([]KandangPeriodSummary, error)
|
||||
GetProjectPeriods(ctx *fiber.Ctx, projectIDs []uint) (map[uint]int, error)
|
||||
Approval(ctx *fiber.Ctx, req *validation.Approve) ([]entity.ProjectFlock, error)
|
||||
Resubmit(ctx *fiber.Ctx, req *validation.Resubmit, id uint) (*entity.ProjectFlock, error)
|
||||
}
|
||||
|
||||
type projectflockService struct {
|
||||
@@ -47,8 +50,10 @@ type projectflockService struct {
|
||||
Repository repository.ProjectflockRepository
|
||||
FlockRepo flockRepository.FlockRepository
|
||||
KandangRepo kandangRepository.KandangRepository
|
||||
NonstockRepo nonstockRepository.NonstockRepository
|
||||
WarehouseRepo warehouseRepository.WarehouseRepository
|
||||
ProductWarehouseRepo productWarehouseRepository.ProductWarehouseRepository
|
||||
ProjectBudgetRepo projectBudgetRepository.ProjectBudgetRepository
|
||||
PivotRepo repository.ProjectFlockKandangRepository
|
||||
ApprovalSvc commonSvc.ApprovalService
|
||||
approvalWorkflow approvalutils.ApprovalWorkflowKey
|
||||
@@ -67,8 +72,11 @@ func NewProjectflockService(
|
||||
pivotRepo repository.ProjectFlockKandangRepository,
|
||||
warehouseRepo warehouseRepository.WarehouseRepository,
|
||||
productWarehouseRepo productWarehouseRepository.ProductWarehouseRepository,
|
||||
projectBudgetRepo projectBudgetRepository.ProjectBudgetRepository,
|
||||
nonstockRepo nonstockRepository.NonstockRepository,
|
||||
approvalSvc commonSvc.ApprovalService,
|
||||
validate *validator.Validate,
|
||||
|
||||
) ProjectflockService {
|
||||
return &projectflockService{
|
||||
Log: utils.Log,
|
||||
@@ -76,6 +84,7 @@ func NewProjectflockService(
|
||||
Repository: repo,
|
||||
FlockRepo: flockRepo,
|
||||
KandangRepo: kandangRepo,
|
||||
NonstockRepo: nonstockRepo,
|
||||
WarehouseRepo: warehouseRepo,
|
||||
ProductWarehouseRepo: productWarehouseRepo,
|
||||
PivotRepo: pivotRepo,
|
||||
@@ -289,7 +298,6 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
|
||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||||
projectRepo := repository.NewProjectflockRepository(dbTransaction)
|
||||
|
||||
// Generate unique flock name (sequential per base name, starting from 1)
|
||||
generatedName, _, err := s.generateSequentialFlockName(c.Context(), projectRepo, canonicalBase, 1, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -300,7 +308,6 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
|
||||
return err
|
||||
}
|
||||
|
||||
// Compute period per kandang so every kandang maintains its own cycle history.
|
||||
periods, err := projectRepo.GetNextPeriodsForKandangs(c.Context(), kandangIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -309,6 +316,10 @@ func (s *projectflockService) CreateOne(c *fiber.Ctx, req *validation.Create) (*
|
||||
return err
|
||||
}
|
||||
|
||||
if err := s.UpsertProjectBudget(c.Context(), dbTransaction, createBody.Id, req.ProjectBudgets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
action := entity.ApprovalActionCreated
|
||||
approvalSvcTx := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||
_, err = approvalSvcTx.CreateApproval(
|
||||
@@ -1044,3 +1055,139 @@ func (s projectflockService) kandangRepoWithTx(tx *gorm.DB) kandangRepository.Ka
|
||||
}
|
||||
return kandangRepository.NewKandangRepository(s.Repository.DB())
|
||||
}
|
||||
|
||||
func (s projectflockService) Resubmit(c *fiber.Ctx, req *validation.Resubmit, id uint) (*entity.ProjectFlock, error) {
|
||||
if err := s.Validate.Struct(req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
actorID, err := m.ActorIDFromContext(c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
existing, err := s.Repository.GetByID(c.Context(), id, s.Repository.WithDefaultRelations())
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "Project flock tidak ditemukan")
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data project flock")
|
||||
}
|
||||
|
||||
kandangIDs := uniqueUintSlice(req.KandangIds)
|
||||
kandangs, err := s.KandangRepo.GetByIDs(c.Context(), kandangIDs, nil)
|
||||
if err != nil {
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "Beberapa kandang tidak ditemukan")
|
||||
}
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengambil data kandang")
|
||||
}
|
||||
if len(kandangs) != len(kandangIDs) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "Beberapa kandang tidak ditemukan")
|
||||
}
|
||||
|
||||
for _, pb := range req.ProjectBudgets {
|
||||
if err := commonSvc.EnsureRelations(c.Context(),
|
||||
commonSvc.RelationCheck{Name: "Nonstock", ID: &pb.NonstockId, Exists: s.NonstockRepo.IdExists},
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
err = s.Repository.DB().WithContext(c.Context()).Transaction(func(dbTransaction *gorm.DB) error {
|
||||
|
||||
approvalSvc := commonSvc.NewApprovalService(commonRepo.NewApprovalRepository(dbTransaction))
|
||||
|
||||
var period int = 1
|
||||
if len(existing.KandangHistory) > 0 {
|
||||
period = existing.KandangHistory[0].Period
|
||||
}
|
||||
|
||||
periods := make(map[uint]int, len(kandangIDs))
|
||||
for _, kandangID := range kandangIDs {
|
||||
periods[kandangID] = period
|
||||
}
|
||||
|
||||
if err := s.attachKandangs(c.Context(), dbTransaction, existing.Id, kandangIDs, periods); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.UpsertProjectBudget(c.Context(), dbTransaction, existing.Id, req.ProjectBudgets); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
action := entity.ApprovalActionUpdated
|
||||
_, err = approvalSvc.CreateApproval(
|
||||
c.Context(),
|
||||
utils.ApprovalWorkflowProjectFlock,
|
||||
existing.Id,
|
||||
utils.ProjectFlockStepPengajuan,
|
||||
&action,
|
||||
actorID,
|
||||
nil,
|
||||
)
|
||||
return err
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
if fiberErr, ok := err.(*fiber.Error); ok {
|
||||
return nil, fiberErr
|
||||
}
|
||||
if errors.Is(err, gorm.ErrRecordNotFound) {
|
||||
return nil, fiber.NewError(fiber.StatusNotFound, "Project flock tidak ditemukan")
|
||||
}
|
||||
|
||||
return nil, fiber.NewError(fiber.StatusInternalServerError, "Gagal mengajukan ulang project flock")
|
||||
}
|
||||
|
||||
return s.getOneEntityOnly(c, id)
|
||||
}
|
||||
|
||||
func (s projectflockService) UpsertProjectBudget(ctx context.Context, dbTransaction *gorm.DB, projectFlockID uint, budgets []validation.ProjectBudget) error {
|
||||
|
||||
if len(budgets) == 0 {
|
||||
return nil
|
||||
}
|
||||
budgetRepo := projectBudgetRepository.NewProjectBudgetRepository(dbTransaction)
|
||||
|
||||
nonstockMap := make(map[uint]bool)
|
||||
relationChecks := make([]commonSvc.RelationCheck, 0, len(budgets))
|
||||
for _, b := range budgets {
|
||||
if nonstockMap[b.NonstockId] {
|
||||
return fiber.NewError(fiber.StatusBadRequest, fmt.Sprintf("Duplicate nonstock_id: %d", b.NonstockId))
|
||||
}
|
||||
nonstockMap[b.NonstockId] = true
|
||||
nonstockID := b.NonstockId
|
||||
relationChecks = append(relationChecks, commonSvc.RelationCheck{
|
||||
Name: "Nonstock",
|
||||
ID: &nonstockID,
|
||||
Exists: s.NonstockRepo.IdExists,
|
||||
})
|
||||
}
|
||||
|
||||
if err := commonSvc.EnsureRelations(ctx, relationChecks...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := budgetRepo.DeleteMany(ctx, func(q *gorm.DB) *gorm.DB {
|
||||
return q.Where("project_flock_id = ?", projectFlockID)
|
||||
}); err != nil && err != gorm.ErrRecordNotFound {
|
||||
return err
|
||||
}
|
||||
|
||||
records := make([]*entity.ProjectBudget, 0, len(budgets))
|
||||
for _, b := range budgets {
|
||||
records = append(records, &entity.ProjectBudget{
|
||||
ProjectFlockId: projectFlockID,
|
||||
NonstockId: b.NonstockId,
|
||||
Price: b.Price,
|
||||
Qty: b.Qty,
|
||||
})
|
||||
}
|
||||
|
||||
if err := budgetRepo.CreateMany(ctx, records, nil); err != nil {
|
||||
return fiber.NewError(fiber.StatusInternalServerError, "Failed to save project budgets")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package validation
|
||||
|
||||
type Create struct {
|
||||
FlockName string `json:"flock_name" validate:"required_strict"`
|
||||
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
|
||||
Category string `json:"category" validate:"required_strict"`
|
||||
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
|
||||
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
|
||||
KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"`
|
||||
FlockName string `json:"flock_name" validate:"required_strict"`
|
||||
AreaId uint `json:"area_id" validate:"required_strict,number,gt=0"`
|
||||
Category string `json:"category" validate:"required_strict"`
|
||||
FcrId uint `json:"fcr_id" validate:"required_strict,number,gt=0"`
|
||||
LocationId uint `json:"location_id" validate:"required_strict,number,gt=0"`
|
||||
KandangIds []uint `json:"kandang_ids" validate:"required,min=1,dive,gt=0"`
|
||||
ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required,min=1,dive"`
|
||||
}
|
||||
|
||||
type Update struct {
|
||||
@@ -36,3 +37,14 @@ type Approve struct {
|
||||
ApprovableIds []uint `json:"approvable_ids" validate:"required_strict,min=1,dive,gt=0"`
|
||||
Notes *string `json:"notes,omitempty" validate:"omitempty,max=500"`
|
||||
}
|
||||
|
||||
type ProjectBudget struct {
|
||||
NonstockId uint `json:"nonstock_id" validate:"required_strict,number,gt=0"`
|
||||
Price float64 `json:"price" validate:"required_strict,number,gt=0"`
|
||||
Qty float64 `json:"qty" validate:"required_strict,number,gt=0"`
|
||||
}
|
||||
|
||||
type Resubmit struct {
|
||||
KandangIds []uint `json:"kandang_ids" validate:"required_strict,min=1,dive,gt=0"`
|
||||
ProjectBudgets []ProjectBudget `json:"project_budgets" validate:"required_strict,min=1,dive"`
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ func (r *StockLogRepositoryImpl) GetByFlaggable(ctx context.Context, logType str
|
||||
var stockLogs []*entity.StockLog
|
||||
|
||||
err := r.DB().WithContext(ctx).
|
||||
Where("log_type = ? AND log_id = ?", logType, logId).
|
||||
Where("loggable_type = ? AND log_id = ?", logType, logId).
|
||||
Preload("ProductWarehouse").
|
||||
Preload("ProductWarehouse.Product").
|
||||
Preload("ProductWarehouse.Warehouse").
|
||||
|
||||
@@ -154,12 +154,14 @@ const (
|
||||
ApprovalWorkflowProjectFlock approvalutils.ApprovalWorkflowKey = approvalutils.ApprovalWorkflowKey("PROJECT_FLOCKS")
|
||||
ProjectFlockStepPengajuan approvalutils.ApprovalStep = 1
|
||||
ProjectFlockStepAktif approvalutils.ApprovalStep = 2
|
||||
ProjectFlockStepSelesai approvalutils.ApprovalStep = 3
|
||||
)
|
||||
|
||||
// projectFlockApprovalSteps keeps the workflow step definitions for project flock approvals.
|
||||
var ProjectFlockApprovalSteps = map[approvalutils.ApprovalStep]string{
|
||||
ProjectFlockStepPengajuan: "Pengajuan",
|
||||
ProjectFlockStepAktif: "Aktif",
|
||||
ProjectFlockStepSelesai: "Selesai",
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user