package repository import ( "context" "github.com/Caknoooo/go-gin-clean-starter/database/entities" "github.com/Caknoooo/go-gin-clean-starter/modules/product/query" "github.com/google/uuid" "gorm.io/gorm" "gorm.io/gorm/clause" ) type ProductRepository interface { Create(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error) GetById(ctx context.Context, tx *gorm.DB, productId string) (entities.MProductEntity, error) GetAll(ctx context.Context, filter query.ProductFilter) ([]entities.MProductEntity, int64, error) Update(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error) Delete(ctx context.Context, tx *gorm.DB, productId string) error AssignCrossReference(ctx context.Context, tx *gorm.DB, productId string, vendorIds []string) error RemoveCrossReference(ctx context.Context, tx *gorm.DB, productId string, vendorIds []string) error } type productRepository struct { db *gorm.DB } func (r *productRepository) AssignCrossReference(ctx context.Context, tx *gorm.DB, productId string, vendorIds []string) error { if tx == nil { tx = r.db } productUUID, err := uuid.Parse(productId) if err != nil { return err } var crossRefs []entities.MCrossReferenceEntity for _, vendorId := range vendorIds { vendorUUID, err := uuid.Parse(vendorId) if err != nil { return err } crossRefs = append(crossRefs, entities.MCrossReferenceEntity{ ProductID: productUUID, VendorID: vendorUUID, }) } if err := tx.WithContext(ctx). Model(&entities.MCrossReferenceEntity{}). Clauses(clause.OnConflict{DoNothing: true}). Create(&crossRefs).Error; err != nil { return err } return nil } func (r *productRepository) RemoveCrossReference(ctx context.Context, tx *gorm.DB, productId string, vendorIds []string) error { if tx == nil { tx = r.db } productUUID, err := uuid.Parse(productId) if err != nil { return err } var vendorUUIDs []uuid.UUID for _, vendorId := range vendorIds { vendorUUID, err := uuid.Parse(vendorId) if err != nil { return err } vendorUUIDs = append(vendorUUIDs, vendorUUID) } if err := tx.WithContext(ctx). Where("product_id = ? AND vendor_id IN ?", productUUID, vendorUUIDs). Delete(&entities.MCrossReferenceEntity{}).Error; err != nil { return err } return nil } func NewProductRepository(db *gorm.DB) ProductRepository { return &productRepository{db: db} } func (r *productRepository) Create(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error) { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Create(&product).Error; err != nil { return product, err } return product, nil } func (r *productRepository) GetById(ctx context.Context, tx *gorm.DB, productId string) (entities.MProductEntity, error) { if tx == nil { tx = r.db } var product entities.MProductEntity if err := tx.WithContext(ctx). Preload("Client"). Preload("Category"). Preload("Uom"). Preload("DimUom"). Preload("WeightUom"). Preload("VolumeUom"). Preload("MinStockUom"). Preload("MaxStockUom"). Preload("LeadTimeUom"). Preload("UomToUom"). Preload("CrossReferences"). Preload("CrossReferences.Vendor"). Preload("InventoryStorages"). Preload("InventoryTransactions"). Preload("InventoryTransactions.Client"). Preload("InventoryTransactions.Aisle"). Preload("InventoryTransactions.InvReceipt"). Preload("InventoryTransactions.InvReceipt.ReceiptLines"). Preload("InventoryTransactions.InvReceipt.ReceiptLines.Product"). Preload("InventoryTransactions.InvIssue"). Preload("InventoryTransactions.InvIssue.IssueLines"). Preload("InventoryTransactions.InvIssue.IssueLines.Product"). Preload("InventoryTransactions.InvMove"). Preload("InventoryTransactions.InvMove.MovementLines"). Preload("InventoryTransactions.InvMove.MovementLines.Product"). First(&product, "id = ?", productId).Error; err != nil { return product, err } return product, nil } func (r *productRepository) GetAll(ctx context.Context, filter query.ProductFilter) ([]entities.MProductEntity, int64, error) { var products []entities.MProductEntity var total int64 db := r.db.Model(&entities.MProductEntity{}) db = query.ApplyProductFilters(db, filter) if err := db.Count(&total).Error; err != nil { return nil, 0, err } err := db.Limit(filter.PerPage).Offset(filter.Page).Find(&products).Error return products, total, err } func (r *productRepository) Update(ctx context.Context, tx *gorm.DB, product entities.MProductEntity) (entities.MProductEntity, error) { if tx == nil { tx = r.db } if err := tx.WithContext(ctx). Model(&entities.MProductEntity{}). Where("id = ?", product.ID). Updates(product).Error; err != nil { return product, err } return product, nil } func (r *productRepository) Delete(ctx context.Context, tx *gorm.DB, productId string) error { if tx == nil { tx = r.db } if err := tx.WithContext(ctx).Delete(&entities.MProductEntity{}, "id = ?", productId).Error; err != nil { return err } return nil }