fix on shelf

This commit is contained in:
2026-08-31 15:51:36 +05:30
parent 4bce5ac854
commit d55f101834
11 changed files with 704 additions and 55 deletions

View File

@@ -46,6 +46,9 @@ type ProductRepository interface {
PublishProduct(tenantID, productID int, price, taxPercent float64) (int, error)
UnpublishProduct(tenantID, productID int) (int, error)
FindTenantProductByCatalogueRef(tenantid int, brand string, catalogueid int64) (*models.Products, error)
FindTenantProductByImageID(tenantid int, imageid string) (*models.Products, error)
SetCatalogueLink(productid int, imageid string, catalogueid int) error
ListCatalogueLinkedProducts(tenantid int) ([]models.Products, error)
CreateProductReturningID(product models.Products) (int, error)
GetImportedCatalogueRefs(tenantid int, brand string) ([]models.ImportedCatalogueRef, error)
GetTenantCategories(tenantid int) ([]models.TenantCategory, error)
@@ -1216,6 +1219,60 @@ func (r *productRepository) CreateProductReturningID(product models.Products) (i
return product.Productid, nil
}
// FindTenantProductByImageID looks up a tenant's snapshot by the catalogue's
// own stable key.
//
// Preferred over FindTenantProductByCatalogueRef wherever an image_id is
// available, because that one keys on a number the catalogue renumbers. After a
// re-scrape the id no longer names the product it was stored for, so the lookup
// misses, the import believes it is seeing the product for the first time, and
// the shop gets a second copy of something it already stocks.
//
// No brand in the key: image_id already carries it (`cheetos_chips_2d6bf74f`,
// `pepsico_kurkure_masala_munch_90g`) and is unique across the whole catalogue,
// which is exactly what the bare catalogueid is not.
func (r *productRepository) FindTenantProductByImageID(tenantid int, imageid string) (*models.Products, error) {
if strings.TrimSpace(imageid) == "" {
return nil, nil
}
var product models.Products
result := r.db.Table("products").
Where("tenantid = ? AND imageid = ?", tenantid, imageid).
First(&product)
if result.Error != nil {
if errors.Is(result.Error, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, result.Error
}
return &product, nil
}
// SetCatalogueLink repairs one product's pointer back into the catalogue.
//
// Both halves move together and both can be cleared, which is the point.
// `imageid` is what a product should be linked by from now on; a `catalogueid`
// of 0 marks a link that could not be repaired at all — the row it named is
// gone and the re-scrape left nothing matching behind it. Clearing it is not
// data loss: the pointer already pointed at nothing, and leaving it in place
// makes a browse screen claim the product is imported from a row that does not
// exist, and makes re-importing fail outright.
func (r *productRepository) SetCatalogueLink(productid int, imageid string, catalogueid int) error {
return r.db.Table("products").
Where("productid = ?", productid).
Updates(map[string]any{"imageid": imageid, "catalogueid": catalogueid}).Error
}
// ListCatalogueLinkedProducts returns every product of a tenant that claims to
// have come from the catalogue, so each claim can be checked.
func (r *productRepository) ListCatalogueLinkedProducts(tenantid int) ([]models.Products, error) {
products := make([]models.Products, 0)
err := r.db.Table("products").
Where("tenantid = ? AND catalogueid IS NOT NULL AND catalogueid != 0", tenantid).
Find(&products).Error
return products, err
}
// GetImportedCatalogueRefs returns the (brand, catalogueid) pairs this
// tenant has already imported, so a catalogue browse screen can mark items
// as already-imported without diffing full product lists client-side. Brand
@@ -1225,7 +1282,7 @@ func (r *productRepository) CreateProductReturningID(product models.Products) (i
func (r *productRepository) GetImportedCatalogueRefs(tenantid int, brand string) ([]models.ImportedCatalogueRef, error) {
refs := make([]models.ImportedCatalogueRef, 0)
query := r.db.Table("products").
Select("productbrand AS brand, catalogueid").
Select("productbrand AS brand, catalogueid, COALESCE(imageid, '') AS imageid").
Where("tenantid = ? AND catalogueid IS NOT NULL AND catalogueid != 0", tenantid)
if brand != "" {
query = query.Where("productbrand = ?", brand)
@@ -1289,9 +1346,9 @@ func (r *productRepository) UpdateProductCategory(productid, categoryid, subcate
// than three unrelated products — and until now it could only ever be set at
// CREATE time, by a caller that already knew the group id:
//
// products/create writes whatever the body carries, variants included
// importcatalogueproduct never sets it, so every imported product is 0
// UpdateProduct writes productlocations.status only, despite the name
// products/create writes whatever the body carries, variants included
// importcatalogueproduct never sets it, so every imported product is 0
// UpdateProduct writes productlocations.status only, despite the name
//
// Since importing from the catalogue is how products actually arrive, every
// product this console creates is ungrouped and there was no call that could