feat: add inventory receipt module with CRUD operations
- Implemented InventoryReceiptController for handling inventory receipt requests. - Created InventoryReceiptService for business logic related to inventory receipts. - Added InventoryReceiptRepository and InventoryReceiptLineRepository for database interactions. - Introduced DTOs for inventory receipt and line requests/responses. - Implemented filtering for inventory receipts in the query layer. - Added routes for inventory receipt operations in the API. - Enhanced document number generation to include client initials. - Updated database entities to support inventory receipts and lines. - Added utility functions for date and time conversions.
This commit is contained in:
parent
d29e2211cd
commit
e90fa96dd6
|
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/Caknoooo/go-gin-clean-starter/modules/auth"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/category"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/client"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt"
|
||||
maintenancegroup "github.com/Caknoooo/go-gin-clean-starter/modules/maintenance_group"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/menu"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/monitoring"
|
||||
|
|
@ -161,6 +162,7 @@ func main() {
|
|||
warehouse.RegisterRoutes(server, injector)
|
||||
zona.RegisterRoutes(server, injector)
|
||||
aisle.RegisterRoutes(server, injector)
|
||||
inventory_receipt.RegisterRoutes(server, injector)
|
||||
|
||||
// register swagger route
|
||||
server.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ type TInventoryReceiptEntity struct {
|
|||
|
||||
ClientID uuid.UUID `gorm:"type:uuid;index;" json:"client_id"`
|
||||
|
||||
ReceiptLines []TInventoryReceiptLineEntity `gorm:"foreignKey:InvReceiptID;references:ID"`
|
||||
Client M_Client `gorm:"foreignKey:ClientID;references:ID"`
|
||||
|
||||
FullAuditTrail
|
||||
|
|
@ -29,14 +30,30 @@ func (TInventoryReceiptEntity) TableName() string {
|
|||
}
|
||||
|
||||
// GenerateDocumentNumber generates a new document number for a client
|
||||
func GenerateDocumentNumber(db *gorm.DB, clientName string) (string, error) {
|
||||
func GenerateDocumentNumber(db *gorm.DB, clientId string) (string, error) {
|
||||
prefix := "RCPT"
|
||||
firstLetter := strings.ToUpper(string(clientName[0]))
|
||||
|
||||
// Ambil nama client berdasarkan clientId
|
||||
var client struct {
|
||||
Name string
|
||||
}
|
||||
if err := db.Table("m_clients").Select("name").Where("id = ?", clientId).First(&client).Error; err != nil {
|
||||
return "", fmt.Errorf("client not found")
|
||||
}
|
||||
if client.Name == "" {
|
||||
return "", fmt.Errorf("client name is empty")
|
||||
}
|
||||
words := strings.Fields(client.Name)
|
||||
initials := ""
|
||||
for _, w := range words {
|
||||
if len(w) > 0 {
|
||||
initials += strings.ToUpper(string(w[0]))
|
||||
}
|
||||
}
|
||||
// Cari document number terakhir untuk client ini
|
||||
var lastReceipt TInventoryReceiptEntity
|
||||
err := db.
|
||||
Joins("JOIN m_clients ON m_clients.id = t_inventory_receipts.client_id").
|
||||
Where("m_clients.name = ?", clientName).
|
||||
Where("client_id = ?", clientId).
|
||||
Order("document_number DESC").
|
||||
First(&lastReceipt).Error
|
||||
|
||||
|
|
@ -49,6 +66,6 @@ func GenerateDocumentNumber(db *gorm.DB, clientName string) (string, error) {
|
|||
}
|
||||
}
|
||||
|
||||
docNum := fmt.Sprintf("%s-%s-%04d", prefix, firstLetter, seq)
|
||||
docNum := fmt.Sprintf("%s-%s-%04d", prefix, initials, seq)
|
||||
return docNum, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ type TInventoryReceiptLineEntity struct {
|
|||
BatchNumber string `gorm:"type:varchar(100);" json:"batch_number"`
|
||||
RepackingSuggestion string `gorm:"type:text;" json:"repacking_suggestion"`
|
||||
|
||||
RepackUomID uuid.UUID `gorm:"type:uuid;index;" json:"repack_uom_id"`
|
||||
RepackUomID *uuid.UUID `gorm:"type:uuid;index;" json:"repack_uom_id"`
|
||||
InvReceiptID uuid.UUID `gorm:"type:uuid;index;" json:"inv_receipt_id"`
|
||||
ProductID uuid.UUID `gorm:"type:uuid;index;" json:"product_id"`
|
||||
ClientID uuid.UUID `gorm:"type:uuid;index;" json:"client_id"`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,182 @@
|
|||
package controller
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/dto"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/query"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/service"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/do"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InventoryReceiptController interface {
|
||||
Create(ctx *gin.Context)
|
||||
Update(ctx *gin.Context)
|
||||
Delete(ctx *gin.Context)
|
||||
GetById(ctx *gin.Context)
|
||||
GetAll(ctx *gin.Context)
|
||||
CreateLine(ctx *gin.Context)
|
||||
UpdateLine(ctx *gin.Context)
|
||||
DeleteLine(ctx *gin.Context)
|
||||
}
|
||||
|
||||
type inventoryReceiptController struct {
|
||||
receiptService service.InventoryReceiptService
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
// DeleteLine implements InventoryReceiptController.
|
||||
func (c *inventoryReceiptController) DeleteLine(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
if err := c.receiptService.DeleteLine(ctx, id); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_INVENTORY_RECEIPT_LINE, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_INVENTORY_RECEIPT_LINE, nil)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
// UpdateLine implements InventoryReceiptController.
|
||||
func (c *inventoryReceiptController) UpdateLine(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
var req dto.InventoryReceiptLineUpdateRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil)
|
||||
ctx.JSON(http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
updated, err := c.receiptService.UpdateLine(ctx, id, req)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_INVENTORY_RECEIPT_LINE, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_INVENTORY_RECEIPT_LINE, updated)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
// CreateLine implements InventoryReceiptController.
|
||||
func (c *inventoryReceiptController) CreateLine(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
var req dto.InventoryReceiptLineCreateRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil)
|
||||
ctx.JSON(http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
created, err := c.receiptService.CreateLine(ctx, id, req)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_CREATE_INVENTORY_RECEIPT_LINE, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_CREATE_INVENTORY_RECEIPT_LINE, created)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func (c *inventoryReceiptController) Create(ctx *gin.Context) {
|
||||
var req dto.InventoryReceiptCreateRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil)
|
||||
ctx.JSON(http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
created, err := c.receiptService.Create(ctx, req)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_CREATE_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_CREATE_INVENTORY_RECEIPT, created)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func (c *inventoryReceiptController) Update(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
var req dto.InventoryReceiptUpdateRequest
|
||||
if err := ctx.ShouldBindJSON(&req); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_DATA_FROM_BODY, err.Error(), nil)
|
||||
ctx.JSON(http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
updated, err := c.receiptService.Update(ctx, req, id)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_UPDATE_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_UPDATE_INVENTORY_RECEIPT, updated)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func (c *inventoryReceiptController) Delete(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
if err := c.receiptService.Delete(ctx, id); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_DELETE_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_DELETE_INVENTORY_RECEIPT, nil)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func (c *inventoryReceiptController) GetById(ctx *gin.Context) {
|
||||
id := ctx.Param("id")
|
||||
receipt, err := c.receiptService.GetById(ctx, id)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusNotFound, res)
|
||||
return
|
||||
}
|
||||
res := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_INVENTORY_RECEIPT, receipt)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func (c *inventoryReceiptController) GetAll(ctx *gin.Context) {
|
||||
clientId := ctx.DefaultQuery("client_id", "")
|
||||
var filter query.InventoryReceiptFilter
|
||||
filter.ClientID = clientId
|
||||
if err := ctx.ShouldBindQuery(&filter); err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
getAll := ctx.Query("get_all")
|
||||
if getAll != "" {
|
||||
receipts, _, err := c.receiptService.GetAll(ctx, filter)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusBadRequest, res)
|
||||
return
|
||||
}
|
||||
response := utils.BuildResponseSuccess(dto.MESSAGE_SUCCESS_GET_INVENTORY_RECEIPT, receipts)
|
||||
ctx.JSON(http.StatusOK, response)
|
||||
return
|
||||
}
|
||||
perPage := utils.ParseInt(ctx.DefaultQuery("per_page", "10"))
|
||||
page := utils.ParseInt(ctx.DefaultQuery("page", "1"))
|
||||
filter.PerPage = perPage
|
||||
filter.Page = (page - 1) * perPage
|
||||
receipts, total, err := c.receiptService.GetAll(ctx, filter)
|
||||
if err != nil {
|
||||
res := utils.BuildResponseFailed(dto.MESSAGE_FAILED_GET_INVENTORY_RECEIPT, err.Error(), nil)
|
||||
ctx.JSON(http.StatusInternalServerError, res)
|
||||
return
|
||||
}
|
||||
paginationResponse := utils.BuildPaginationResponse(perPage, page, total)
|
||||
res := utils.BuildResponseSuccessWithPagination(http.StatusOK, dto.MESSAGE_SUCCESS_GET_INVENTORY_RECEIPT, receipts, paginationResponse)
|
||||
ctx.JSON(http.StatusOK, res)
|
||||
}
|
||||
|
||||
func NewInventoryReceiptController(i *do.Injector, receiptService service.InventoryReceiptService) InventoryReceiptController {
|
||||
db := do.MustInvokeNamed[*gorm.DB](i, constants.DB)
|
||||
return &inventoryReceiptController{
|
||||
receiptService: receiptService,
|
||||
db: db,
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
package dto
|
||||
|
||||
import pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
|
||||
|
||||
const (
|
||||
MESSAGE_FAILED_CREATE_INVENTORY_RECEIPT = "failed create inventory receipt"
|
||||
MESSAGE_FAILED_CREATE_INVENTORY_RECEIPT_LINE = "failed create inventory receipt line"
|
||||
MESSAGE_SUCCESS_CREATE_INVENTORY_RECEIPT = "success create inventory receipt"
|
||||
MESSAGE_SUCCESS_CREATE_INVENTORY_RECEIPT_LINE = "success create inventory receipt line"
|
||||
MESSAGE_FAILED_GET_INVENTORY_RECEIPT = "failed get inventory receipt"
|
||||
MESSAGE_SUCCESS_GET_INVENTORY_RECEIPT = "success get inventory receipt"
|
||||
MESSAGE_FAILED_UPDATE_INVENTORY_RECEIPT = "failed update inventory receipt"
|
||||
MESSAGE_FAILED_UPDATE_INVENTORY_RECEIPT_LINE = "failed update inventory receipt line"
|
||||
MESSAGE_SUCCESS_UPDATE_INVENTORY_RECEIPT = "success update inventory receipt"
|
||||
MESSAGE_SUCCESS_UPDATE_INVENTORY_RECEIPT_LINE = "success update inventory receipt line"
|
||||
MESSAGE_FAILED_DELETE_INVENTORY_RECEIPT = "failed delete inventory receipt"
|
||||
MESSAGE_FAILED_DELETE_INVENTORY_RECEIPT_LINE = "failed delete inventory receipt line"
|
||||
MESSAGE_SUCCESS_DELETE_INVENTORY_RECEIPT = "success delete inventory receipt"
|
||||
MESSAGE_SUCCESS_DELETE_INVENTORY_RECEIPT_LINE = "success delete inventory receipt line"
|
||||
MESSAGE_FAILED_GET_DATA_FROM_BODY = "failed get data from body"
|
||||
)
|
||||
|
||||
type InventoryReceiptCreateRequest struct {
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
ReceiptDate string `json:"receipt_date"`
|
||||
Source string `json:"source"`
|
||||
QrCodeFile string `json:"qr_code_file"`
|
||||
ClientID string `json:"client_id" binding:"required"`
|
||||
ReceiptLines []InventoryReceiptLineCreateRequest `json:"inventory_lines,omitempty" binding:"dive"`
|
||||
}
|
||||
|
||||
type InventoryReceiptLineCreateRequest struct {
|
||||
Quantity float64 `json:"quantity"`
|
||||
BatchNumber string `json:"batch_number"`
|
||||
RepackingSuggestion string `json:"repacking_suggestion"`
|
||||
RepackUomID string `json:"repack_uom_id"`
|
||||
ProductID string `json:"product_id"`
|
||||
ClientID string `json:"client_id"`
|
||||
}
|
||||
|
||||
type InventoryReceiptUpdateRequest struct {
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
ReceiptDate string `json:"receipt_date"`
|
||||
Source string `json:"source"`
|
||||
QrCodeFile string `json:"qr_code_file"`
|
||||
}
|
||||
|
||||
type InventoryReceiptResponse struct {
|
||||
ID string `json:"id"`
|
||||
ReferenceNumber string `json:"reference_number"`
|
||||
DocumentNumber string `json:"document_number"`
|
||||
ReceiptDate string `json:"receipt_date"`
|
||||
Source string `json:"source"`
|
||||
QrCodeFile string `json:"qr_code_file"`
|
||||
Client pkgdto.IdNameResponse `json:"client"`
|
||||
ReceiptLines []InventoryReceiptLineResponse `json:"inventory_lines"`
|
||||
LineCount int `json:"line_count"`
|
||||
}
|
||||
|
||||
type InventoryReceiptLineResponse struct {
|
||||
ID string `json:"id"`
|
||||
Quantity float64 `json:"quantity"`
|
||||
BatchNumber string `json:"batch_number"`
|
||||
RepackingSuggestion string `json:"repacking_suggestion"`
|
||||
RepackUomID *string `json:"repack_uom_id"`
|
||||
Product InventoryReceiptLineProductResponse `json:"product"`
|
||||
ClientID string `json:"client_id"`
|
||||
}
|
||||
|
||||
type InventoryReceiptLineProductResponse struct {
|
||||
ID string `json:"id"`
|
||||
Name string `json:"name"`
|
||||
RefNumber string `json:"ref_number"`
|
||||
Uom pkgdto.IdNameResponse `json:"uom"`
|
||||
DimLength float64 `json:"dim_length"`
|
||||
DimWidth float64 `json:"dim_width"`
|
||||
DimHeight float64 `json:"dim_height"`
|
||||
DimUom pkgdto.IdNameResponse `json:"dim_uom"`
|
||||
}
|
||||
|
||||
type InventoryReceiptLineUpdateRequest struct {
|
||||
Quantity *float64 `json:"quantity"`
|
||||
BatchNumber *string `json:"batch_number"`
|
||||
RepackingSuggestion *string `json:"repacking_suggestion"`
|
||||
RepackUomID *string `json:"repack_uom_id"`
|
||||
ProductID *string `json:"product_id"`
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
package query
|
||||
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InventoryReceiptFilter struct {
|
||||
ClientID string `form:"client_id"`
|
||||
Source string `form:"source"`
|
||||
PerPage int `form:"per_page"`
|
||||
Page int `form:"page"`
|
||||
}
|
||||
|
||||
func ApplyInventoryReceiptFilters(db *gorm.DB, filter InventoryReceiptFilter) *gorm.DB {
|
||||
if filter.ClientID != "" {
|
||||
db = db.Where("client_id = ?", filter.ClientID)
|
||||
}
|
||||
if filter.Source != "" {
|
||||
db = db.Where("source ILIKE ?", "%"+filter.Source+"%")
|
||||
}
|
||||
return db
|
||||
}
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InventoryReceiptLineRepository interface {
|
||||
Create(ctx context.Context, tx *gorm.DB, line entities.TInventoryReceiptLineEntity) (entities.TInventoryReceiptLineEntity, error)
|
||||
GetById(ctx context.Context, tx *gorm.DB, id string) (entities.TInventoryReceiptLineEntity, error)
|
||||
GetAllByReceiptId(ctx context.Context, receiptId string) ([]entities.TInventoryReceiptLineEntity, error)
|
||||
Update(ctx context.Context, tx *gorm.DB, line entities.TInventoryReceiptLineEntity) (entities.TInventoryReceiptLineEntity, error)
|
||||
Delete(ctx context.Context, tx *gorm.DB, id string) error
|
||||
BulkCreate(ctx context.Context, tx *gorm.DB, lines []entities.TInventoryReceiptLineEntity) error
|
||||
DeleteByReceiptId(ctx context.Context, tx *gorm.DB, receiptId string) error
|
||||
}
|
||||
|
||||
type inventoryReceiptLineRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewInventoryReceiptLineRepository(db *gorm.DB) InventoryReceiptLineRepository {
|
||||
return &inventoryReceiptLineRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) Create(ctx context.Context, tx *gorm.DB, line entities.TInventoryReceiptLineEntity) (entities.TInventoryReceiptLineEntity, error) {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
if err := tx.WithContext(ctx).Create(&line).Error; err != nil {
|
||||
return line, err
|
||||
}
|
||||
return line, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) GetById(ctx context.Context, tx *gorm.DB, id string) (entities.TInventoryReceiptLineEntity, error) {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
var line entities.TInventoryReceiptLineEntity
|
||||
if err := tx.WithContext(ctx).Preload("Product").Preload("RepackUom").Preload("InvReceipt").Preload("Client").First(&line, "id = ?", id).Error; err != nil {
|
||||
return line, err
|
||||
}
|
||||
return line, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) GetAllByReceiptId(ctx context.Context, receiptId string) ([]entities.TInventoryReceiptLineEntity, error) {
|
||||
var lines []entities.TInventoryReceiptLineEntity
|
||||
if err := r.db.WithContext(ctx).Where("inv_receipt_id = ?", receiptId).Preload("Product").Preload("RepackUom").Preload("InvReceipt").Preload("Client").Find(&lines).Error; err != nil {
|
||||
return lines, err
|
||||
}
|
||||
return lines, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) Update(ctx context.Context, tx *gorm.DB, line entities.TInventoryReceiptLineEntity) (entities.TInventoryReceiptLineEntity, error) {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
if err := tx.WithContext(ctx).Model(&entities.TInventoryReceiptLineEntity{}).Where("id = ?", line.ID).Select("*").Updates(&line).Error; err != nil {
|
||||
return line, err
|
||||
}
|
||||
return line, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) Delete(ctx context.Context, tx *gorm.DB, id string) error {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
if err := tx.WithContext(ctx).Delete(&entities.TInventoryReceiptLineEntity{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) BulkCreate(ctx context.Context, tx *gorm.DB, lines []entities.TInventoryReceiptLineEntity) error {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
return tx.WithContext(ctx).Create(&lines).Error
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptLineRepository) DeleteByReceiptId(ctx context.Context, tx *gorm.DB, receiptId string) error {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
return tx.WithContext(ctx).Where("inv_receipt_id = ?", receiptId).Delete(&entities.TInventoryReceiptLineEntity{}).Error
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
package repository
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/query"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InventoryReceiptRepository interface {
|
||||
Create(ctx context.Context, tx *gorm.DB, receipt entities.TInventoryReceiptEntity) (entities.TInventoryReceiptEntity, error)
|
||||
GetById(ctx context.Context, tx *gorm.DB, id string) (entities.TInventoryReceiptEntity, error)
|
||||
GetAll(ctx context.Context, filter query.InventoryReceiptFilter) ([]entities.TInventoryReceiptEntity, int64, error)
|
||||
Update(ctx context.Context, tx *gorm.DB, receipt entities.TInventoryReceiptEntity) (entities.TInventoryReceiptEntity, error)
|
||||
Delete(ctx context.Context, tx *gorm.DB, id string) error
|
||||
}
|
||||
|
||||
type inventoryReceiptRepository struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewInventoryReceiptRepository(db *gorm.DB) InventoryReceiptRepository {
|
||||
return &inventoryReceiptRepository{db: db}
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptRepository) Create(ctx context.Context, tx *gorm.DB, receipt entities.TInventoryReceiptEntity) (entities.TInventoryReceiptEntity, error) {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
if err := tx.WithContext(ctx).Create(&receipt).Error; err != nil {
|
||||
return receipt, err
|
||||
}
|
||||
return receipt, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptRepository) GetById(ctx context.Context, tx *gorm.DB, id string) (entities.TInventoryReceiptEntity, error) {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
var receipt entities.TInventoryReceiptEntity
|
||||
if err := tx.WithContext(ctx).
|
||||
Preload("Client").
|
||||
Preload("ReceiptLines").
|
||||
Preload("ReceiptLines.Product").
|
||||
Preload("ReceiptLines.Product.Uom").
|
||||
Preload("ReceiptLines.Product.DimUom").
|
||||
First(&receipt, "id = ?", id).Error; err != nil {
|
||||
return receipt, err
|
||||
}
|
||||
return receipt, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptRepository) GetAll(ctx context.Context, filter query.InventoryReceiptFilter) ([]entities.TInventoryReceiptEntity, int64, error) {
|
||||
var receipts []entities.TInventoryReceiptEntity
|
||||
var total int64
|
||||
db := query.ApplyInventoryReceiptFilters(r.db, filter)
|
||||
db.Model(&entities.TInventoryReceiptEntity{}).Count(&total)
|
||||
if filter.PerPage > 0 && filter.Page > 0 {
|
||||
db = db.Offset((filter.Page - 1) * filter.PerPage).Limit(filter.PerPage)
|
||||
}
|
||||
if err := db.Preload("Client").Find(&receipts).Error; err != nil {
|
||||
return receipts, total, err
|
||||
}
|
||||
return receipts, total, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptRepository) Update(ctx context.Context, tx *gorm.DB, receipt entities.TInventoryReceiptEntity) (entities.TInventoryReceiptEntity, error) {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
if err := tx.WithContext(ctx).Model(&entities.TInventoryReceiptEntity{}).Where("id = ?", receipt.ID).Select("*").Updates(&receipt).Error; err != nil {
|
||||
return receipt, err
|
||||
}
|
||||
return receipt, nil
|
||||
}
|
||||
|
||||
func (r *inventoryReceiptRepository) Delete(ctx context.Context, tx *gorm.DB, id string) error {
|
||||
if tx == nil {
|
||||
tx = r.db
|
||||
}
|
||||
if err := tx.WithContext(ctx).Delete(&entities.TInventoryReceiptEntity{}, "id = ?", id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package inventory_receipt
|
||||
|
||||
import (
|
||||
"github.com/Caknoooo/go-gin-clean-starter/middlewares"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/auth/service"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/controller"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/pkg/constants"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/samber/do"
|
||||
)
|
||||
|
||||
func RegisterRoutes(server *gin.Engine, injector *do.Injector) {
|
||||
receiptController := do.MustInvoke[controller.InventoryReceiptController](injector)
|
||||
jwtService := do.MustInvokeNamed[service.JWTService](injector, constants.JWTService)
|
||||
|
||||
receiptRoutes := server.Group("/api/v1/inventory-receipts")
|
||||
{
|
||||
receiptRoutes.POST("", middlewares.Authenticate(jwtService), receiptController.Create)
|
||||
receiptRoutes.GET(":id", middlewares.Authenticate(jwtService), receiptController.GetById)
|
||||
receiptRoutes.PUT(":id", middlewares.Authenticate(jwtService), receiptController.Update)
|
||||
receiptRoutes.DELETE(":id", middlewares.Authenticate(jwtService), receiptController.Delete)
|
||||
receiptRoutes.GET("", middlewares.Authenticate(jwtService), receiptController.GetAll)
|
||||
receiptRoutes.POST(":id/lines", middlewares.Authenticate(jwtService), receiptController.CreateLine)
|
||||
receiptRoutes.PUT("lines/:id", middlewares.Authenticate(jwtService), receiptController.UpdateLine)
|
||||
receiptRoutes.DELETE("lines/:id", middlewares.Authenticate(jwtService), receiptController.DeleteLine)
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,391 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/Caknoooo/go-gin-clean-starter/database/entities"
|
||||
dtodomain "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/dto"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/query"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/repository"
|
||||
pkgdto "github.com/Caknoooo/go-gin-clean-starter/pkg/dto"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/pkg/utils"
|
||||
"github.com/google/uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type InventoryReceiptService interface {
|
||||
Create(ctx context.Context, req dtodomain.InventoryReceiptCreateRequest) (dtodomain.InventoryReceiptResponse, error)
|
||||
GetById(ctx context.Context, id string) (dtodomain.InventoryReceiptResponse, error)
|
||||
GetAll(ctx context.Context, filter query.InventoryReceiptFilter) ([]dtodomain.InventoryReceiptResponse, int64, error)
|
||||
Update(ctx context.Context, req dtodomain.InventoryReceiptUpdateRequest, id string) (dtodomain.InventoryReceiptResponse, error)
|
||||
Delete(ctx context.Context, id string) error
|
||||
CreateLine(ctx context.Context, receiptId string, req dtodomain.InventoryReceiptLineCreateRequest) (dtodomain.InventoryReceiptLineResponse, error)
|
||||
UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryReceiptLineUpdateRequest) (dtodomain.InventoryReceiptLineResponse, error)
|
||||
DeleteLine(ctx context.Context, lineId string) error
|
||||
}
|
||||
|
||||
type inventoryReceiptService struct {
|
||||
db *gorm.DB
|
||||
receiptRepo repository.InventoryReceiptRepository
|
||||
receiptLineRepo repository.InventoryReceiptLineRepository
|
||||
}
|
||||
|
||||
// DeleteLine implements InventoryReceiptService.
|
||||
func (s *inventoryReceiptService) DeleteLine(ctx context.Context, lineId string) error {
|
||||
return s.receiptLineRepo.Delete(ctx, nil, lineId)
|
||||
}
|
||||
|
||||
// UpdateLine implements InventoryReceiptService.
|
||||
func (s *inventoryReceiptService) UpdateLine(ctx context.Context, lineId string, req dtodomain.InventoryReceiptLineUpdateRequest) (dtodomain.InventoryReceiptLineResponse, error) {
|
||||
line, err := s.receiptLineRepo.GetById(ctx, nil, lineId)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
if req.Quantity != nil {
|
||||
line.Quantity = *req.Quantity
|
||||
}
|
||||
if req.BatchNumber != nil {
|
||||
line.BatchNumber = *req.BatchNumber
|
||||
}
|
||||
if req.RepackingSuggestion != nil {
|
||||
line.RepackingSuggestion = *req.RepackingSuggestion
|
||||
}
|
||||
if req.RepackUomID != nil {
|
||||
if *req.RepackUomID != "" {
|
||||
tmp, err := uuid.Parse(*req.RepackUomID)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
line.RepackUomID = &tmp
|
||||
} else {
|
||||
line.RepackUomID = nil
|
||||
}
|
||||
}
|
||||
if req.ProductID != nil {
|
||||
if *req.ProductID != "" {
|
||||
tmp, err := uuid.Parse(*req.ProductID)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
line.ProductID = tmp
|
||||
} else {
|
||||
line.ProductID = uuid.Nil
|
||||
}
|
||||
}
|
||||
updated, err := s.receiptLineRepo.Update(ctx, nil, line)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
var repackUomID *string
|
||||
if updated.RepackUomID != nil {
|
||||
tmp := updated.RepackUomID.String()
|
||||
repackUomID = &tmp
|
||||
}
|
||||
product := dtodomain.InventoryReceiptLineProductResponse{}
|
||||
if updated.Product.ID != uuid.Nil {
|
||||
product = dtodomain.InventoryReceiptLineProductResponse{
|
||||
ID: updated.Product.ID.String(),
|
||||
Name: updated.Product.Name,
|
||||
}
|
||||
}
|
||||
return dtodomain.InventoryReceiptLineResponse{
|
||||
ID: updated.ID.String(),
|
||||
Quantity: updated.Quantity,
|
||||
BatchNumber: updated.BatchNumber,
|
||||
RepackingSuggestion: updated.RepackingSuggestion,
|
||||
RepackUomID: repackUomID,
|
||||
Product: product,
|
||||
ClientID: updated.ClientID.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toInventoryReceiptResponse(e entities.TInventoryReceiptEntity) dtodomain.InventoryReceiptResponse {
|
||||
client := pkgdto.IdNameResponse{}
|
||||
if e.Client.ID != uuid.Nil {
|
||||
client = pkgdto.IdNameResponse{
|
||||
ID: e.Client.ID.String(),
|
||||
Name: e.Client.Name,
|
||||
}
|
||||
}
|
||||
|
||||
lines := make([]dtodomain.InventoryReceiptLineResponse, 0)
|
||||
for _, line := range e.ReceiptLines {
|
||||
product := dtodomain.InventoryReceiptLineProductResponse{}
|
||||
if line.Product.ID != uuid.Nil {
|
||||
product = dtodomain.InventoryReceiptLineProductResponse{
|
||||
ID: line.Product.ID.String(),
|
||||
Name: line.Product.Name,
|
||||
RefNumber: line.Product.RefNumber,
|
||||
Uom: pkgdto.IdNameResponse{
|
||||
ID: line.Product.Uom.ID.String(),
|
||||
Name: line.Product.Uom.Name,
|
||||
},
|
||||
DimLength: line.Product.DimLength,
|
||||
DimWidth: line.Product.DimWidth,
|
||||
DimHeight: line.Product.DimHeight,
|
||||
DimUom: pkgdto.IdNameResponse{
|
||||
ID: line.Product.DimUom.ID.String(),
|
||||
Name: line.Product.DimUom.Name,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
var repackUomID *string
|
||||
if line.RepackUomID != nil {
|
||||
tmp := line.RepackUomID.String()
|
||||
repackUomID = &tmp
|
||||
} else {
|
||||
repackUomID = nil
|
||||
}
|
||||
|
||||
lines = append(lines, dtodomain.InventoryReceiptLineResponse{
|
||||
ID: line.ID.String(),
|
||||
Quantity: line.Quantity,
|
||||
BatchNumber: line.BatchNumber,
|
||||
RepackingSuggestion: line.RepackingSuggestion,
|
||||
RepackUomID: repackUomID,
|
||||
Product: product,
|
||||
ClientID: line.ClientID.String(),
|
||||
})
|
||||
}
|
||||
|
||||
return dtodomain.InventoryReceiptResponse{
|
||||
ID: e.ID.String(),
|
||||
ReferenceNumber: e.ReferenceNumber,
|
||||
DocumentNumber: e.DocumentNumber,
|
||||
ReceiptDate: utils.DateTimeToString(e.ReceiptDate),
|
||||
Source: e.Source,
|
||||
QrCodeFile: e.QrCodeFile,
|
||||
// ClientID: e.ClientID.String(),
|
||||
Client: client,
|
||||
LineCount: len(lines),
|
||||
ReceiptLines: lines,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *inventoryReceiptService) Create(ctx context.Context, req dtodomain.InventoryReceiptCreateRequest) (dtodomain.InventoryReceiptResponse, error) {
|
||||
tx := s.db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
clientUUID, err := uuid.Parse(req.ClientID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
docNum, err := entities.GenerateDocumentNumber(s.db, req.ClientID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
receipt := entities.TInventoryReceiptEntity{
|
||||
ReferenceNumber: req.ReferenceNumber,
|
||||
DocumentNumber: docNum,
|
||||
ReceiptDate: utils.StringToDateTime(req.ReceiptDate),
|
||||
Source: req.Source,
|
||||
QrCodeFile: req.QrCodeFile,
|
||||
ClientID: clientUUID,
|
||||
}
|
||||
created, err := s.receiptRepo.Create(ctx, tx, receipt)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
// Bulk create lines
|
||||
var lines []entities.TInventoryReceiptLineEntity
|
||||
for _, lineReq := range req.ReceiptLines {
|
||||
var productUUID uuid.UUID
|
||||
if lineReq.ProductID != "" {
|
||||
productUUID, err = uuid.Parse(lineReq.ProductID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
} else {
|
||||
productUUID = uuid.Nil
|
||||
}
|
||||
var repackUomUUID *uuid.UUID
|
||||
if lineReq.RepackUomID != "" {
|
||||
tmp, err := uuid.Parse(lineReq.RepackUomID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
repackUomUUID = &tmp
|
||||
} else {
|
||||
repackUomUUID = nil
|
||||
}
|
||||
clientLineUUID, err := uuid.Parse(lineReq.ClientID)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
lines = append(lines, entities.TInventoryReceiptLineEntity{
|
||||
Quantity: lineReq.Quantity,
|
||||
BatchNumber: lineReq.BatchNumber,
|
||||
RepackingSuggestion: lineReq.RepackingSuggestion,
|
||||
RepackUomID: repackUomUUID,
|
||||
InvReceiptID: created.ID,
|
||||
ProductID: productUUID,
|
||||
ClientID: clientLineUUID,
|
||||
})
|
||||
}
|
||||
if len(lines) > 0 {
|
||||
err = s.receiptLineRepo.BulkCreate(ctx, tx, lines)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
}
|
||||
tx.Commit()
|
||||
result, err := s.receiptRepo.GetById(ctx, nil, created.ID.String())
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
return toInventoryReceiptResponse(result), nil
|
||||
}
|
||||
|
||||
func (s *inventoryReceiptService) GetById(ctx context.Context, id string) (dtodomain.InventoryReceiptResponse, error) {
|
||||
receipt, err := s.receiptRepo.GetById(ctx, nil, id)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
return toInventoryReceiptResponse(receipt), nil
|
||||
}
|
||||
|
||||
func (s *inventoryReceiptService) GetAll(ctx context.Context, filter query.InventoryReceiptFilter) ([]dtodomain.InventoryReceiptResponse, int64, error) {
|
||||
receipts, total, err := s.receiptRepo.GetAll(ctx, filter)
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
var responses []dtodomain.InventoryReceiptResponse
|
||||
for _, e := range receipts {
|
||||
responses = append(responses, toInventoryReceiptResponse(e))
|
||||
}
|
||||
if responses == nil {
|
||||
responses = make([]dtodomain.InventoryReceiptResponse, 0)
|
||||
}
|
||||
return responses, total, nil
|
||||
}
|
||||
|
||||
func (s *inventoryReceiptService) Update(ctx context.Context, req dtodomain.InventoryReceiptUpdateRequest, id string) (dtodomain.InventoryReceiptResponse, error) {
|
||||
tx := s.db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
receipt, err := s.receiptRepo.GetById(ctx, tx, id)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
if req.ReferenceNumber != "" {
|
||||
receipt.ReferenceNumber = req.ReferenceNumber
|
||||
}
|
||||
receipt.ReceiptDate = utils.StringToDateTime(req.ReceiptDate)
|
||||
receipt.Source = req.Source
|
||||
receipt.QrCodeFile = req.QrCodeFile
|
||||
updated, err := s.receiptRepo.Update(ctx, tx, receipt)
|
||||
if err != nil {
|
||||
tx.Rollback()
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
tx.Commit()
|
||||
result, err := s.receiptRepo.GetById(ctx, nil, updated.ID.String())
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptResponse{}, err
|
||||
}
|
||||
return toInventoryReceiptResponse(result), nil
|
||||
}
|
||||
|
||||
func (s *inventoryReceiptService) Delete(ctx context.Context, id string) error {
|
||||
tx := s.db.Begin()
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
if err := s.receiptRepo.Delete(ctx, tx, id); err != nil {
|
||||
tx.Rollback()
|
||||
return err
|
||||
}
|
||||
tx.Commit()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *inventoryReceiptService) CreateLine(ctx context.Context, receiptId string, req dtodomain.InventoryReceiptLineCreateRequest) (dtodomain.InventoryReceiptLineResponse, error) {
|
||||
receiptUUID, err := uuid.Parse(receiptId)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
var productUUID uuid.UUID
|
||||
if req.ProductID != "" {
|
||||
productUUID, err = uuid.Parse(req.ProductID)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
} else {
|
||||
productUUID = uuid.Nil
|
||||
}
|
||||
var repackUomUUID *uuid.UUID
|
||||
if req.RepackUomID != "" {
|
||||
tmp, err := uuid.Parse(req.RepackUomID)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
repackUomUUID = &tmp
|
||||
} else {
|
||||
repackUomUUID = nil
|
||||
}
|
||||
clientLineUUID, err := uuid.Parse(req.ClientID)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
line := entities.TInventoryReceiptLineEntity{
|
||||
Quantity: req.Quantity,
|
||||
BatchNumber: req.BatchNumber,
|
||||
RepackingSuggestion: req.RepackingSuggestion,
|
||||
RepackUomID: repackUomUUID,
|
||||
InvReceiptID: receiptUUID,
|
||||
ProductID: productUUID,
|
||||
ClientID: clientLineUUID,
|
||||
}
|
||||
created, err := s.receiptLineRepo.Create(ctx, nil, line)
|
||||
if err != nil {
|
||||
return dtodomain.InventoryReceiptLineResponse{}, err
|
||||
}
|
||||
var repackUomID *string
|
||||
if created.RepackUomID != nil {
|
||||
tmp := created.RepackUomID.String()
|
||||
repackUomID = &tmp
|
||||
}
|
||||
|
||||
product := dtodomain.InventoryReceiptLineProductResponse{}
|
||||
if created.Product.ID != uuid.Nil {
|
||||
product = dtodomain.InventoryReceiptLineProductResponse{
|
||||
ID: created.Product.ID.String(),
|
||||
Name: created.Product.Name,
|
||||
}
|
||||
}
|
||||
|
||||
return dtodomain.InventoryReceiptLineResponse{
|
||||
ID: created.ID.String(),
|
||||
Quantity: created.Quantity,
|
||||
BatchNumber: created.BatchNumber,
|
||||
RepackingSuggestion: created.RepackingSuggestion,
|
||||
RepackUomID: repackUomID,
|
||||
Product: product,
|
||||
ClientID: created.ClientID.String(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewInventoryReceiptService(db *gorm.DB, receiptRepo repository.InventoryReceiptRepository, receiptLineRepo repository.InventoryReceiptLineRepository) InventoryReceiptService {
|
||||
return &inventoryReceiptService{
|
||||
db: db,
|
||||
receiptRepo: receiptRepo,
|
||||
receiptLineRepo: receiptLineRepo,
|
||||
}
|
||||
}
|
||||
|
|
@ -2,6 +2,7 @@ package utils
|
|||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"golang.org/x/crypto/bcrypt"
|
||||
|
|
@ -48,3 +49,45 @@ func ParseUUID(s string) uuid.UUID {
|
|||
}
|
||||
return id
|
||||
}
|
||||
|
||||
// StringToDate parses a string to time.Time with layout "2006-01-02"
|
||||
func StringToDate(s string) time.Time {
|
||||
if t, err := time.Parse("2006-01-02", s); err == nil {
|
||||
now := time.Now()
|
||||
// Gabungkan tanggal dari input dengan jam:menit:detik dari waktu sekarang
|
||||
return time.Date(
|
||||
t.Year(), t.Month(), t.Day(),
|
||||
now.Hour(), now.Minute(), now.Second(), now.Nanosecond(),
|
||||
now.Location(),
|
||||
)
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// StringToDateTime parses a string to time.Time with layout "2006-01-02T15:04:05Z07:00"
|
||||
func StringToDateTime(s string) time.Time {
|
||||
// Coba parse RFC3339 dulu
|
||||
if t, err := time.Parse(time.RFC3339, s); err == nil {
|
||||
return t
|
||||
}
|
||||
// Jika gagal, coba parse "2006-01-02"
|
||||
if t, err := time.Parse("2006-01-02", s); err == nil {
|
||||
now := time.Now()
|
||||
// Gabungkan tanggal dari input dengan jam:menit:detik dari waktu sekarang
|
||||
return time.Date(
|
||||
t.Year(), t.Month(), t.Day(),
|
||||
now.Hour(), now.Minute(), now.Second(), now.Nanosecond(),
|
||||
now.Location(),
|
||||
)
|
||||
}
|
||||
// Jika gagal semua, return zero time
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
func DateToString(t time.Time) string {
|
||||
return t.Format("2006-01-02")
|
||||
}
|
||||
|
||||
func DateTimeToString(t time.Time) string {
|
||||
return t.Format(time.RFC3339)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,11 @@ import (
|
|||
aisleRepo "github.com/Caknoooo/go-gin-clean-starter/modules/aisle/repository"
|
||||
aisleService "github.com/Caknoooo/go-gin-clean-starter/modules/aisle/service"
|
||||
|
||||
inventoryReceiptController "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/controller"
|
||||
inventoryReceiptLineRepo "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/repository"
|
||||
inventoryReceiptRepo "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/repository"
|
||||
inventoryReceiptService "github.com/Caknoooo/go-gin-clean-starter/modules/inventory_receipt/service"
|
||||
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/user/controller"
|
||||
"github.com/Caknoooo/go-gin-clean-starter/modules/user/repository"
|
||||
userService "github.com/Caknoooo/go-gin-clean-starter/modules/user/service"
|
||||
|
|
@ -107,6 +112,8 @@ func RegisterDependencies(injector *do.Injector) {
|
|||
warehouseRepository := warehouseRepo.NewWarehouseRepository(db)
|
||||
zonaRepository := zonaRepo.NewZonaRepository(db)
|
||||
aisleRepository := aisleRepo.NewAisleRepository(db)
|
||||
inventoryReceiptRepository := inventoryReceiptRepo.NewInventoryReceiptRepository(db)
|
||||
inventoryReceiptLineRepository := inventoryReceiptLineRepo.NewInventoryReceiptLineRepository(db)
|
||||
|
||||
// Service
|
||||
userServ := userService.NewUserService(userRepository, refreshTokenRepository, jwtService, db)
|
||||
|
|
@ -122,6 +129,7 @@ func RegisterDependencies(injector *do.Injector) {
|
|||
warehouseServ := warehouseService.NewWarehouseService(warehouseRepository, db)
|
||||
zonaServ := zonaService.NewZonaService(zonaRepository, db)
|
||||
aisleServ := aisleService.NewAisleService(aisleRepository, db)
|
||||
inventoryReceiptServ := inventoryReceiptService.NewInventoryReceiptService(db, inventoryReceiptRepository, inventoryReceiptLineRepository)
|
||||
|
||||
// Controller
|
||||
do.Provide(
|
||||
|
|
@ -199,4 +207,9 @@ func RegisterDependencies(injector *do.Injector) {
|
|||
return aisleController.NewAisleController(aisleServ), nil
|
||||
},
|
||||
)
|
||||
do.Provide(
|
||||
injector, func(i *do.Injector) (inventoryReceiptController.InventoryReceiptController, error) {
|
||||
return inventoryReceiptController.NewInventoryReceiptController(i, inventoryReceiptServ), nil
|
||||
},
|
||||
)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue