Auto-sync permit competitors in monitoring PF
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 35s

This commit is contained in:
Grendgi
2026-06-05 12:09:51 +03:00
parent 76975c3c6c
commit 6966e6810c
7 changed files with 333 additions and 44 deletions

View File

@@ -386,30 +386,53 @@ func (a *App) DeleteProject(ctx context.Context, ownerID, projectID int64) error
return tx.Commit()
}
func (a *App) DeleteListing(ctx context.Context, ownerID, listingID int64) error {
var id int64
err := a.DB.QueryRowContext(ctx, `
SELECT l.id
FROM competitor_listings l JOIN projects p ON p.id = l.project_id
WHERE l.id = ? AND p.owner_id = ?`, listingID, ownerID).Scan(&id)
type DeletedListing struct {
Listing *Listing
ProjectTitle string
ProjectDeal string
OwnerChatID *string
}
func (a *App) DeleteListing(ctx context.Context, ownerID, listingID int64) (*DeletedListing, error) {
row := a.DB.QueryRowContext(ctx, listingSelect()+`
JOIN projects p ON p.id = l.project_id
WHERE l.id = ? AND p.owner_id = ?`, listingID, ownerID)
listing, err := scanListing(row, false)
if errors.Is(err, sql.ErrNoRows) {
return ErrNotFound
return nil, ErrNotFound
}
if err != nil {
return err
return nil, err
}
deleted := &DeletedListing{Listing: listing}
var deal string
var chat sql.NullString
if err := a.DB.QueryRowContext(ctx, `
SELECT p.title, p.deal_type, e.tg_chat_id
FROM projects p
JOIN employees e ON e.id = p.owner_id
WHERE p.id = ? AND p.owner_id = ?`, listing.ProjectID, ownerID).
Scan(&deleted.ProjectTitle, &deal, &chat); err != nil {
return nil, err
}
deleted.ProjectDeal = enumDealOut(deal)
deleted.OwnerChatID = nullableString(chat)
tx, err := a.DB.BeginTx(ctx, nil)
if err != nil {
return err
return nil, err
}
defer tx.Rollback()
if _, err := tx.ExecContext(ctx, `DELETE FROM price_history WHERE listing_id = ?`, id); err != nil {
return err
if _, err := tx.ExecContext(ctx, `DELETE FROM price_history WHERE listing_id = ?`, listing.ID); err != nil {
return nil, err
}
if _, err := tx.ExecContext(ctx, `DELETE FROM competitor_listings WHERE id = ?`, id); err != nil {
return err
if _, err := tx.ExecContext(ctx, `DELETE FROM competitor_listings WHERE id = ?`, listing.ID); err != nil {
return nil, err
}
return tx.Commit()
if err := tx.Commit(); err != nil {
return nil, err
}
return deleted, nil
}
func (a *App) ListingByID(ctx context.Context, id int64, withHistory bool) (*Listing, error) {
@@ -547,18 +570,19 @@ func (a *App) PriceHistory(ctx context.Context, listingID int64) ([]PricePoint,
func listingSelect() string {
return `
SELECT l.id, l.project_id, l.source, l.external_id, l.url, l.title, l.agent_name,
l.agency_name, l.current_price, l.currency, l.status, l.first_seen_at, l.last_seen_at
l.agency_name, l.permit_number, l.auto_discovered, l.current_price, l.currency, l.status, l.first_seen_at, l.last_seen_at
FROM competitor_listings l`
}
func scanListing(row rowScanner, _ bool) (*Listing, error) {
var l Listing
var source, status string
var title, agent, agency, currency, firstSeen, lastSeen sql.NullString
var title, agent, agency, permit, currency, firstSeen, lastSeen sql.NullString
var price sql.NullFloat64
var autoDiscovered bool
if err := row.Scan(
&l.ID, &l.ProjectID, &source, &l.ExternalID, &l.URL, &title, &agent, &agency,
&price, &currency, &status, &firstSeen, &lastSeen,
&permit, &autoDiscovered, &price, &currency, &status, &firstSeen, &lastSeen,
); err != nil {
return nil, err
}
@@ -566,6 +590,8 @@ func scanListing(row rowScanner, _ bool) (*Listing, error) {
l.Title = nullableString(title)
l.AgentName = nullableString(agent)
l.AgencyName = nullableString(agency)
l.PermitNumber = nullableString(permit)
l.AutoDiscovered = autoDiscovered
l.CurrentPrice = nullableFloat(price)
l.Currency = nullableString(currency)
l.Status = enumStatusOut(status)