2026-04-16 10:15:28 +00:00
|
|
|
package platform
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
2026-04-17 15:20:17 +00:00
|
|
|
"strconv"
|
2026-04-16 10:15:28 +00:00
|
|
|
"time"
|
|
|
|
|
|
2026-04-22 19:54:06 +00:00
|
|
|
"github.com/Gleipnir-Technology/bob"
|
2026-04-16 10:15:28 +00:00
|
|
|
"github.com/Gleipnir-Technology/bob/dialect/psql"
|
|
|
|
|
"github.com/Gleipnir-Technology/bob/dialect/psql/sm"
|
|
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/db"
|
|
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/db/models"
|
2026-04-16 17:15:20 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/platform/background"
|
2026-04-17 15:20:17 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/platform/event"
|
2026-04-16 10:15:28 +00:00
|
|
|
"github.com/Gleipnir-Technology/nidus-sync/platform/types"
|
|
|
|
|
"github.com/aarondl/opt/omit"
|
|
|
|
|
"github.com/aarondl/opt/omitnull"
|
2026-04-17 21:40:04 +00:00
|
|
|
//"github.com/rs/zerolog/log"
|
2026-04-22 19:54:06 +00:00
|
|
|
"github.com/stephenafamo/scan"
|
2026-04-16 10:15:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func ComplianceRequestMailerCreate(ctx context.Context, user User, site_id int32) (int32, error) {
|
|
|
|
|
txn, err := db.PGInstance.BobDB.BeginTx(ctx, nil)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("start txn: %w", err)
|
|
|
|
|
}
|
|
|
|
|
defer txn.Rollback(ctx)
|
|
|
|
|
site, err := models.FindSite(ctx, txn, site_id)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("find site: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if site.OrganizationID != user.Organization.ID {
|
|
|
|
|
return 0, fmt.Errorf("permission denied")
|
|
|
|
|
}
|
|
|
|
|
features, err := models.Features.Query(
|
|
|
|
|
models.SelectWhere.Features.SiteID.EQ(site.ID),
|
|
|
|
|
).All(ctx, txn)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("find features: %w", err)
|
|
|
|
|
}
|
|
|
|
|
feature_ids := make([]int32, len(features))
|
|
|
|
|
for i, f := range features {
|
|
|
|
|
feature_ids[i] = f.ID
|
|
|
|
|
}
|
|
|
|
|
feature_pools, err := models.FeaturePools.Query(
|
|
|
|
|
sm.Where(
|
|
|
|
|
models.FeaturePools.Columns.FeatureID.EQ(psql.Any(feature_ids)),
|
|
|
|
|
),
|
|
|
|
|
).All(ctx, txn)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("find feature pools: %w", err)
|
|
|
|
|
}
|
|
|
|
|
if len(feature_pools) != 1 {
|
|
|
|
|
return 0, fmt.Errorf("wrong number of pools: %d", len(feature_pools))
|
|
|
|
|
}
|
|
|
|
|
feature_pool := feature_pools[0]
|
|
|
|
|
var feature *models.Feature
|
|
|
|
|
for _, f := range features {
|
|
|
|
|
if f.ID == feature_pool.FeatureID {
|
|
|
|
|
feature = f
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if feature == nil {
|
|
|
|
|
return 0, fmt.Errorf("match feature %d", feature_pool.FeatureID)
|
|
|
|
|
}
|
|
|
|
|
location := types.Location{
|
|
|
|
|
Latitude: feature.LocationLatitude.GetOr(0),
|
|
|
|
|
Longitude: feature.LocationLongitude.GetOr(0),
|
|
|
|
|
}
|
|
|
|
|
signal, err := SignalCreateFromPool(ctx, txn, user, site.ID, feature_pool.FeatureID, location)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("create signal from ppol: %w", err)
|
|
|
|
|
}
|
|
|
|
|
lead_id, err := leadCreate(ctx, txn, user, *signal, site.ID, &location)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("create lead from ppol: %w", err)
|
|
|
|
|
}
|
|
|
|
|
public_id, err := GenerateReportID()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("create public id: %w", err)
|
|
|
|
|
}
|
|
|
|
|
setter := models.ComplianceReportRequestSetter{
|
|
|
|
|
Created: omit.From(time.Now()),
|
|
|
|
|
Creator: omit.From(int32(user.ID)),
|
|
|
|
|
// ID
|
|
|
|
|
PublicID: omit.From(public_id),
|
|
|
|
|
LeadID: omitnull.From(*lead_id),
|
|
|
|
|
}
|
|
|
|
|
req, err := models.ComplianceReportRequests.Insert(&setter).One(ctx, txn)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("create compliance report request: %w", err)
|
|
|
|
|
}
|
2026-04-16 17:15:20 +00:00
|
|
|
err = background.NewComplianceMailer(ctx, txn, req.ID)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("create background compliance mailer job: %w", err)
|
|
|
|
|
}
|
2026-04-17 15:20:17 +00:00
|
|
|
event.Updated(event.TypeSite, user.Organization.ID, strconv.Itoa(int(site.ID)))
|
2026-04-16 10:49:06 +00:00
|
|
|
txn.Commit(ctx)
|
2026-04-17 15:20:17 +00:00
|
|
|
|
2026-04-16 10:15:28 +00:00
|
|
|
return req.ID, nil
|
|
|
|
|
}
|
2026-04-17 20:51:07 +00:00
|
|
|
|
|
|
|
|
func ComplianceReportRequestByLeadID(ctx context.Context, lead_ids []int32) (map[int32][]*types.ComplianceReportRequest, error) {
|
|
|
|
|
rows, err := models.ComplianceReportRequests.Query(
|
|
|
|
|
sm.Where(models.ComplianceReportRequests.Columns.LeadID.EQ(psql.Any(lead_ids))),
|
|
|
|
|
).All(ctx, db.PGInstance.BobDB)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return nil, fmt.Errorf("query reports: %w", err)
|
|
|
|
|
}
|
|
|
|
|
results := make(map[int32][]*types.ComplianceReportRequest, len(lead_ids))
|
2026-04-17 20:58:21 +00:00
|
|
|
for _, lead_id := range lead_ids {
|
|
|
|
|
results[lead_id] = make([]*types.ComplianceReportRequest, 0)
|
|
|
|
|
}
|
2026-04-17 20:51:07 +00:00
|
|
|
for _, row := range rows {
|
2026-04-17 21:40:04 +00:00
|
|
|
lead_id := row.LeadID.MustGet()
|
|
|
|
|
crrs, ok := results[lead_id]
|
2026-04-17 20:51:07 +00:00
|
|
|
if !ok {
|
|
|
|
|
return nil, fmt.Errorf("impossible")
|
|
|
|
|
}
|
|
|
|
|
crrs = append(crrs, types.ComplianceReportRequestFromModel(row))
|
2026-04-17 21:40:04 +00:00
|
|
|
results[lead_id] = crrs
|
2026-04-17 20:51:07 +00:00
|
|
|
}
|
|
|
|
|
return results, nil
|
|
|
|
|
}
|
2026-04-21 21:35:40 +00:00
|
|
|
func ComplianceReportRequestFromPublicID(ctx context.Context, public_id string) (*types.ComplianceReportRequest, error) {
|
|
|
|
|
row, err := models.ComplianceReportRequests.Query(
|
|
|
|
|
sm.Where(models.ComplianceReportRequests.Columns.PublicID.EQ(psql.Arg(public_id))),
|
|
|
|
|
).One(ctx, db.PGInstance.BobDB)
|
|
|
|
|
if err != nil {
|
|
|
|
|
if err.Error() == "sql: no rows in result set" {
|
|
|
|
|
return nil, nil
|
|
|
|
|
}
|
|
|
|
|
return nil, fmt.Errorf("query CRR: %w", err)
|
|
|
|
|
}
|
|
|
|
|
return types.ComplianceReportRequestFromModel(row), nil
|
|
|
|
|
}
|
2026-04-22 19:54:06 +00:00
|
|
|
func OrganizationIDForComplianceReportRequest(ctx context.Context, public_id string) (int32, error) {
|
|
|
|
|
type _Row struct {
|
|
|
|
|
ID int32 `db:"organization_id"`
|
|
|
|
|
}
|
|
|
|
|
row, err := bob.One(ctx, db.PGInstance.BobDB, psql.Select(
|
|
|
|
|
sm.Columns(
|
|
|
|
|
models.Sites.Columns.OrganizationID,
|
|
|
|
|
),
|
|
|
|
|
sm.From(models.ComplianceReportRequests.NameAs()),
|
|
|
|
|
sm.InnerJoin(models.Leads.NameAs()).On(
|
|
|
|
|
models.ComplianceReportRequests.Columns.LeadID.EQ(models.Leads.Columns.ID)),
|
|
|
|
|
sm.InnerJoin(models.Sites.NameAs()).On(
|
|
|
|
|
models.Leads.Columns.SiteID.EQ(models.Sites.Columns.ID)),
|
|
|
|
|
sm.Where(models.ComplianceReportRequests.Columns.PublicID.EQ(psql.Arg(public_id))),
|
|
|
|
|
), scan.StructMapper[_Row]())
|
|
|
|
|
if err != nil {
|
|
|
|
|
return 0, fmt.Errorf("query compliance report request")
|
|
|
|
|
}
|
|
|
|
|
return row.ID, nil
|
|
|
|
|
}
|