Add vendor publish to document system
Replace the old snapshot-based system for vendors with the publish document system, mirroring the prior processing activity / DPIA / TIA migration. Includes the GraphQL mutation, MCP tool, CLI command, n8n operation, frontend publish dialog, e2e tests, and a prosemirror register template covering vendor profile fields plus per-vendor sections for services, contacts, risk assessments, compliance reports, BAA and DPA agreements. The vendor register lives as a generated DocumentTypeRegister document on the organization, reused across publishes (the major version bumps on every republish). Approvers can be passed in to create a draft pending approval; otherwise the version is published immediately. The frontend Vendors page exposes a Publish button and a Document link button when the document exists, and pre-fills the previous default approvers. Remove snapshot mode entirely from vendors and their sub-entities: drop snapshotId/sourceId from GraphQL Vendor type and VendorFilter; remove SnapshotsTypeVendors from the snapshot registry and delete Vendors.Snapshot, VendorSnapshotter interface and all *.InsertVendorSnapshots methods on contacts, services, risk assessments, compliance reports, BAA and DPA. Drop the snapshot routes and banner from the frontend. The snapshot_id columns remain in the database but are now filtered out with snapshot_id IS NULL. Add Get/Upsert/Clear GeneratedDocumentID methods on Vendor backed by a new vendors_document_id column on generated_documents, matching the ProcessingActivity/Finding/Obligation pattern. Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
16
pkg/coredata/migrations/20260428T152537Z.sql
Normal file
16
pkg/coredata/migrations/20260428T152537Z.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
-- Copyright (c) 2026 Probo Inc <hello@getprobo.com>.
|
||||
--
|
||||
-- Permission to use, copy, modify, and/or distribute this software for any
|
||||
-- purpose with or without fee is hereby granted, provided that the above
|
||||
-- copyright notice and this permission notice appear in all copies.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
-- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
-- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
-- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
-- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
|
||||
-- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
-- PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
ALTER TABLE generated_documents
|
||||
ADD COLUMN vendors_document_id TEXT REFERENCES documents(id) ON DELETE SET NULL;
|
||||
@@ -124,7 +124,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND type NOT IN ('STATEMENTS_OF_APPLICABILITY', 'DATA', 'ASSETS')
|
||||
AND type = 'RISKS'
|
||||
AND %s
|
||||
`
|
||||
|
||||
@@ -164,7 +164,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND type NOT IN ('STATEMENTS_OF_APPLICABILITY', 'DATA', 'ASSETS')
|
||||
AND type = 'RISKS'
|
||||
AND %s
|
||||
`
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@ type (
|
||||
|
||||
const (
|
||||
SnapshotsTypeRisks SnapshotsType = "RISKS"
|
||||
SnapshotsTypeVendors SnapshotsType = "VENDORS"
|
||||
SnapshotsTypeAssets SnapshotsType = "ASSETS"
|
||||
SnapshotsTypeData SnapshotsType = "DATA"
|
||||
SnapshotsTypeFindings SnapshotsType = "FINDINGS"
|
||||
@@ -37,7 +36,6 @@ const (
|
||||
func SnapshotsTypes() []SnapshotsType {
|
||||
return []SnapshotsType{
|
||||
SnapshotsTypeRisks,
|
||||
SnapshotsTypeVendors,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -59,8 +57,6 @@ func (st *SnapshotsType) Scan(value any) error {
|
||||
switch s {
|
||||
case SnapshotsTypeRisks.String():
|
||||
*st = SnapshotsTypeRisks
|
||||
case SnapshotsTypeVendors.String():
|
||||
*st = SnapshotsTypeVendors
|
||||
case SnapshotsTypeAssets.String():
|
||||
*st = SnapshotsTypeAssets
|
||||
case SnapshotsTypeData.String():
|
||||
|
||||
@@ -30,8 +30,6 @@ func GetSnapshottable(snapshotType SnapshotsType) (Snapshottable, error) {
|
||||
switch snapshotType {
|
||||
case SnapshotsTypeRisks:
|
||||
return Risks{}, nil
|
||||
case SnapshotsTypeVendors:
|
||||
return Vendors{}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported snapshot type: %s", snapshotType)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,113 @@ import (
|
||||
"go.probo.inc/probo/pkg/page"
|
||||
)
|
||||
|
||||
func (v Vendor) GetGeneratedDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
organizationID gid.GID,
|
||||
) (*gid.GID, error) {
|
||||
var documentID *gid.GID
|
||||
|
||||
err := conn.QueryRow(
|
||||
ctx,
|
||||
`
|
||||
SELECT
|
||||
vendors_document_id
|
||||
FROM
|
||||
generated_documents
|
||||
WHERE
|
||||
organization_id = @organization_id
|
||||
`,
|
||||
pgx.NamedArgs{"organization_id": organizationID},
|
||||
).Scan(&documentID)
|
||||
if errors.Is(err, pgx.ErrNoRows) {
|
||||
return nil, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("cannot get vendor list document ID: %w", err)
|
||||
}
|
||||
|
||||
return documentID, nil
|
||||
}
|
||||
|
||||
func (v Vendor) UpsertGeneratedDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
organizationID gid.GID,
|
||||
tenantID gid.TenantID,
|
||||
documentID gid.GID,
|
||||
) error {
|
||||
now := time.Now()
|
||||
|
||||
_, err := conn.Exec(
|
||||
ctx,
|
||||
`
|
||||
INSERT INTO generated_documents (
|
||||
organization_id,
|
||||
tenant_id,
|
||||
vendors_document_id,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@organization_id,
|
||||
@tenant_id,
|
||||
@vendors_document_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
ON CONFLICT (organization_id) DO UPDATE
|
||||
SET
|
||||
vendors_document_id = @vendors_document_id,
|
||||
updated_at = @updated_at
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"organization_id": organizationID,
|
||||
"tenant_id": tenantID,
|
||||
"vendors_document_id": documentID,
|
||||
"created_at": now,
|
||||
"updated_at": now,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot upsert vendor list document ID: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Vendor) ClearGeneratedDocumentID(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
documentIDs []gid.GID,
|
||||
) error {
|
||||
ids := make([]string, len(documentIDs))
|
||||
for i, id := range documentIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
_, err := conn.Exec(
|
||||
ctx,
|
||||
`
|
||||
UPDATE
|
||||
generated_documents
|
||||
SET
|
||||
vendors_document_id = NULL,
|
||||
updated_at = @now
|
||||
WHERE
|
||||
vendors_document_id = ANY(@ids)
|
||||
`,
|
||||
pgx.NamedArgs{
|
||||
"ids": ids,
|
||||
"now": time.Now(),
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot clear vendor list document references: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type (
|
||||
Vendor struct {
|
||||
ID gid.GID `db:"id"`
|
||||
@@ -52,17 +159,11 @@ type (
|
||||
SecurityPageURL *string `db:"security_page_url"`
|
||||
TrustPageURL *string `db:"trust_page_url"`
|
||||
ShowOnTrustCenter bool `db:"show_on_trust_center"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Vendors []*Vendor
|
||||
|
||||
VendorSnapshotter interface {
|
||||
InsertVendorSnapshots(ctx context.Context, conn pg.Tx, scope Scoper, organizationID, snapshotID gid.GID) error
|
||||
}
|
||||
)
|
||||
|
||||
func (v Vendor) CursorKey(orderBy VendorOrderField) page.CursorKey {
|
||||
@@ -123,8 +224,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -191,8 +290,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -253,8 +350,6 @@ INSERT INTO
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
@@ -282,8 +377,6 @@ VALUES (
|
||||
@security_page_url,
|
||||
@trust_page_url,
|
||||
@show_on_trust_center,
|
||||
@snapshot_id,
|
||||
@source_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
@@ -313,8 +406,6 @@ VALUES (
|
||||
"security_page_url": v.SecurityPageURL,
|
||||
"trust_page_url": v.TrustPageURL,
|
||||
"show_on_trust_center": v.ShowOnTrustCenter,
|
||||
"snapshot_id": v.SnapshotID,
|
||||
"source_id": v.SourceID,
|
||||
"created_at": v.CreatedAt,
|
||||
"updated_at": v.UpdatedAt,
|
||||
}
|
||||
@@ -355,7 +446,8 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND snapshot_id IS NULL
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
@@ -375,6 +467,67 @@ WHERE
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (v *Vendors) LoadAllByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
category,
|
||||
headquarter_address,
|
||||
legal_name,
|
||||
website_url,
|
||||
privacy_policy_url,
|
||||
service_level_agreement_url,
|
||||
data_processing_agreement_url,
|
||||
business_associate_agreement_url,
|
||||
subprocessors_list_url,
|
||||
certifications,
|
||||
countries,
|
||||
business_owner_profile_id,
|
||||
security_owner_profile_id,
|
||||
status_page_url,
|
||||
terms_of_service_url,
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendors
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND snapshot_id IS NULL
|
||||
ORDER BY name ASC
|
||||
`
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query vendors: %w", err)
|
||||
}
|
||||
|
||||
vendors, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Vendor])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect vendors: %w", err)
|
||||
}
|
||||
|
||||
*v = vendors
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Vendors) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
@@ -408,8 +561,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -417,6 +568,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND snapshot_id IS NULL
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
@@ -613,8 +765,6 @@ WITH vend AS (
|
||||
v.security_page_url,
|
||||
v.trust_page_url,
|
||||
v.show_on_trust_center,
|
||||
v.snapshot_id,
|
||||
v.source_id,
|
||||
v.created_at,
|
||||
v.updated_at
|
||||
FROM
|
||||
@@ -648,8 +798,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -749,8 +897,6 @@ WITH vend AS (
|
||||
v.security_page_url,
|
||||
v.trust_page_url,
|
||||
v.show_on_trust_center,
|
||||
v.snapshot_id,
|
||||
v.source_id,
|
||||
v.created_at,
|
||||
v.updated_at
|
||||
FROM
|
||||
@@ -784,8 +930,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -846,8 +990,6 @@ WITH vend AS (
|
||||
v.security_page_url,
|
||||
v.trust_page_url,
|
||||
v.show_on_trust_center,
|
||||
v.snapshot_id,
|
||||
v.source_id,
|
||||
v.created_at,
|
||||
v.updated_at
|
||||
FROM
|
||||
@@ -881,8 +1023,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -944,8 +1084,6 @@ WITH vend AS (
|
||||
v.security_page_url,
|
||||
v.trust_page_url,
|
||||
v.show_on_trust_center,
|
||||
v.snapshot_id,
|
||||
v.source_id,
|
||||
v.created_at,
|
||||
v.updated_at
|
||||
FROM
|
||||
@@ -979,8 +1117,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -1034,6 +1170,7 @@ filtered_vendors AS (
|
||||
vendors v
|
||||
WHERE
|
||||
v.tenant_id = @tenant_id
|
||||
AND v.snapshot_id IS NULL
|
||||
)
|
||||
SELECT
|
||||
pav.processing_activity_id,
|
||||
@@ -1106,8 +1243,6 @@ WITH vend AS (
|
||||
v.security_page_url,
|
||||
v.trust_page_url,
|
||||
v.show_on_trust_center,
|
||||
v.snapshot_id,
|
||||
v.source_id,
|
||||
v.created_at,
|
||||
v.updated_at
|
||||
FROM
|
||||
@@ -1141,8 +1276,6 @@ SELECT
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -1169,108 +1302,3 @@ ORDER BY name ASC
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Vendors) Snapshot(ctx context.Context, conn pg.Tx, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
for _, snapshotter := range []VendorSnapshotter{
|
||||
Vendors{},
|
||||
VendorServices{},
|
||||
VendorContacts{},
|
||||
VendorRiskAssessments{},
|
||||
VendorComplianceReports{},
|
||||
VendorBusinessAssociateAgreements{},
|
||||
VendorDataPrivacyAgreements{},
|
||||
} {
|
||||
if err := snapshotter.InsertVendorSnapshots(ctx, conn, scope, organizationID, snapshotID); err != nil {
|
||||
return fmt.Errorf("cannot create vendor snapshots: (%T) %w", snapshotter, err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v Vendors) InsertVendorSnapshots(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
INSERT INTO vendors (
|
||||
tenant_id,
|
||||
id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
name,
|
||||
description,
|
||||
category,
|
||||
headquarter_address,
|
||||
legal_name,
|
||||
website_url,
|
||||
privacy_policy_url,
|
||||
service_level_agreement_url,
|
||||
data_processing_agreement_url,
|
||||
business_associate_agreement_url,
|
||||
subprocessors_list_url,
|
||||
certifications,
|
||||
countries,
|
||||
business_owner_profile_id,
|
||||
security_owner_profile_id,
|
||||
status_page_url,
|
||||
terms_of_service_url,
|
||||
security_page_url,
|
||||
trust_page_url,
|
||||
show_on_trust_center,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_entity_type),
|
||||
@snapshot_id,
|
||||
v.id,
|
||||
v.organization_id,
|
||||
v.name,
|
||||
v.description,
|
||||
v.category,
|
||||
v.headquarter_address,
|
||||
v.legal_name,
|
||||
v.website_url,
|
||||
v.privacy_policy_url,
|
||||
v.service_level_agreement_url,
|
||||
v.data_processing_agreement_url,
|
||||
v.business_associate_agreement_url,
|
||||
v.subprocessors_list_url,
|
||||
v.certifications,
|
||||
v.countries,
|
||||
v.business_owner_profile_id,
|
||||
v.security_owner_profile_id,
|
||||
v.status_page_url,
|
||||
v.terms_of_service_url,
|
||||
v.security_page_url,
|
||||
v.trust_page_url,
|
||||
v.show_on_trust_center,
|
||||
v.created_at,
|
||||
v.updated_at
|
||||
FROM vendors v
|
||||
WHERE %s AND organization_id = @organization_id AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_entity_type": VendorEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ type (
|
||||
ValidFrom *time.Time `db:"valid_from"`
|
||||
ValidUntil *time.Time `db:"valid_until"`
|
||||
FileID gid.GID `db:"file_id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -84,8 +82,6 @@ SELECT
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -93,6 +89,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
@@ -116,6 +113,60 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vbaas *VendorBusinessAssociateAgreements) LoadByVendorIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
vendorIDs []gid.GID,
|
||||
) error {
|
||||
if len(vendorIDs) == 0 {
|
||||
*vbaas = VendorBusinessAssociateAgreements{}
|
||||
return nil
|
||||
}
|
||||
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendor_business_associate_agreements
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = ANY(@vendor_ids)
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
ids := make([]string, len(vendorIDs))
|
||||
for i, id := range vendorIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
args := pgx.NamedArgs{"vendor_ids": ids}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query vendor business associate agreements: %w", err)
|
||||
}
|
||||
|
||||
agreements, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[VendorBusinessAssociateAgreement])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect vendor business associate agreements: %w", err)
|
||||
}
|
||||
|
||||
*vbaas = agreements
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vbaa *VendorBusinessAssociateAgreement) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
@@ -130,8 +181,6 @@ SELECT
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -215,8 +264,6 @@ INSERT INTO
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
@@ -228,8 +275,6 @@ VALUES (
|
||||
@valid_from,
|
||||
@valid_until,
|
||||
@file_id,
|
||||
@snapshot_id,
|
||||
@source_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
@@ -238,8 +283,6 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
||||
valid_from = EXCLUDED.valid_from,
|
||||
valid_until = EXCLUDED.valid_until,
|
||||
file_id = EXCLUDED.file_id,
|
||||
snapshot_id = EXCLUDED.snapshot_id,
|
||||
source_id = EXCLUDED.source_id,
|
||||
updated_at = EXCLUDED.updated_at
|
||||
`
|
||||
args := pgx.StrictNamedArgs{
|
||||
@@ -250,8 +293,6 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
||||
"valid_from": vbaa.ValidFrom,
|
||||
"valid_until": vbaa.ValidUntil,
|
||||
"file_id": vbaa.FileID,
|
||||
"snapshot_id": vbaa.SnapshotID,
|
||||
"source_id": vbaa.SourceID,
|
||||
"created_at": vbaa.CreatedAt,
|
||||
"updated_at": vbaa.UpdatedAt,
|
||||
}
|
||||
@@ -317,65 +358,3 @@ WHERE
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
return err
|
||||
}
|
||||
|
||||
func (v VendorBusinessAssociateAgreements) InsertVendorSnapshots(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
WITH
|
||||
snapshot_vendors AS (
|
||||
SELECT id, source_id
|
||||
FROM vendors
|
||||
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||
)
|
||||
INSERT INTO vendor_business_associate_agreements (
|
||||
tenant_id,
|
||||
id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_business_associate_agreement_entity_type),
|
||||
@snapshot_id,
|
||||
vbaa.id,
|
||||
vbaa.organization_id,
|
||||
sv.id,
|
||||
vbaa.valid_from,
|
||||
vbaa.valid_until,
|
||||
vbaa.file_id,
|
||||
vbaa.created_at,
|
||||
vbaa.updated_at
|
||||
FROM vendor_business_associate_agreements vbaa
|
||||
INNER JOIN snapshot_vendors sv ON sv.source_id = vbaa.vendor_id
|
||||
WHERE %s AND vbaa.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_business_associate_agreement_entity_type": VendorBusinessAssociateAgreementEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor business associate agreement snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ type (
|
||||
ValidUntil *time.Time `db:"valid_until"`
|
||||
ReportName string `db:"report_name"`
|
||||
ReportFileId *gid.GID `db:"report_file_id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -86,8 +84,6 @@ SELECT
|
||||
valid_until,
|
||||
report_name,
|
||||
report_file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -95,6 +91,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
AND %s
|
||||
`
|
||||
|
||||
@@ -119,6 +116,63 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vcs *VendorComplianceReports) LoadByVendorIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
vendorIDs []gid.GID,
|
||||
) error {
|
||||
if len(vendorIDs) == 0 {
|
||||
*vcs = VendorComplianceReports{}
|
||||
return nil
|
||||
}
|
||||
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
report_date,
|
||||
valid_until,
|
||||
report_name,
|
||||
report_file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendor_compliance_reports
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = ANY(@vendor_ids)
|
||||
AND snapshot_id IS NULL
|
||||
ORDER BY
|
||||
vendor_id, report_date DESC
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
ids := make([]string, len(vendorIDs))
|
||||
for i, id := range vendorIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
args := pgx.NamedArgs{"vendor_ids": ids}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query vendor compliance reports: %w", err)
|
||||
}
|
||||
|
||||
vendorComplianceReports, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[VendorComplianceReport])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect vendor compliance reports: %w", err)
|
||||
}
|
||||
|
||||
*vcs = vendorComplianceReports
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vcr *VendorComplianceReport) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
@@ -134,8 +188,6 @@ SELECT
|
||||
valid_until,
|
||||
report_name,
|
||||
report_file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -251,67 +303,3 @@ RETURNING report_file_id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vcrs VendorComplianceReports) InsertVendorSnapshots(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
WITH
|
||||
snapshot_vendors AS (
|
||||
SELECT id, source_id
|
||||
FROM vendors
|
||||
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||
)
|
||||
INSERT INTO vendor_compliance_reports (
|
||||
tenant_id,
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
vendor_id,
|
||||
report_date,
|
||||
valid_until,
|
||||
report_name,
|
||||
report_file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_compliance_report_entity_type),
|
||||
@organization_id,
|
||||
@snapshot_id,
|
||||
vcr.id,
|
||||
sv.id,
|
||||
vcr.report_date,
|
||||
vcr.valid_until,
|
||||
vcr.report_name,
|
||||
vcr.report_file_id,
|
||||
vcr.created_at,
|
||||
vcr.updated_at
|
||||
FROM vendor_compliance_reports vcr
|
||||
INNER JOIN snapshot_vendors sv ON sv.source_id = vcr.vendor_id
|
||||
WHERE %s AND vcr.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_compliance_report_entity_type": VendorComplianceReportEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor compliance report snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ type (
|
||||
Email *mail.Addr `db:"email"`
|
||||
Phone *string `db:"phone"`
|
||||
Role *string `db:"role"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -88,8 +86,6 @@ SELECT
|
||||
email,
|
||||
phone,
|
||||
role,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -141,8 +137,6 @@ SELECT
|
||||
email,
|
||||
phone,
|
||||
role,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -150,6 +144,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
AND %s
|
||||
`
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||
@@ -176,6 +171,63 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vc *VendorContacts) LoadByVendorIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
vendorIDs []gid.GID,
|
||||
) error {
|
||||
if len(vendorIDs) == 0 {
|
||||
*vc = VendorContacts{}
|
||||
return nil
|
||||
}
|
||||
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
full_name,
|
||||
email,
|
||||
phone,
|
||||
role,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendor_contacts
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = ANY(@vendor_ids)
|
||||
AND snapshot_id IS NULL
|
||||
ORDER BY
|
||||
vendor_id, full_name ASC
|
||||
`
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
ids := make([]string, len(vendorIDs))
|
||||
for i, id := range vendorIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
args := pgx.StrictNamedArgs{"vendor_ids": ids}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query vendor contacts: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
vendorContacts, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[VendorContact])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect vendor contacts: %w", err)
|
||||
}
|
||||
|
||||
*vc = vendorContacts
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vc VendorContact) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
@@ -296,67 +348,3 @@ WHERE
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vc VendorContacts) InsertVendorSnapshots(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
WITH
|
||||
snapshot_vendors AS (
|
||||
SELECT id, source_id
|
||||
FROM vendors
|
||||
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||
)
|
||||
INSERT INTO vendor_contacts (
|
||||
tenant_id,
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
vendor_id,
|
||||
full_name,
|
||||
email,
|
||||
phone,
|
||||
role,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_contact_entity_type),
|
||||
@organization_id,
|
||||
@snapshot_id,
|
||||
vc.id,
|
||||
sv.id,
|
||||
vc.full_name,
|
||||
vc.email,
|
||||
vc.phone,
|
||||
vc.role,
|
||||
vc.created_at,
|
||||
vc.updated_at
|
||||
FROM vendor_contacts vc
|
||||
INNER JOIN snapshot_vendors sv ON sv.source_id = vc.vendor_id
|
||||
WHERE %s AND vc.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_contact_entity_type": VendorContactEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor contact snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -36,8 +36,6 @@ type (
|
||||
ValidFrom *time.Time `db:"valid_from"`
|
||||
ValidUntil *time.Time `db:"valid_until"`
|
||||
FileID gid.GID `db:"file_id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -84,8 +82,6 @@ SELECT
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -93,6 +89,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
@@ -116,6 +113,60 @@ LIMIT 1;
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vdpas *VendorDataPrivacyAgreements) LoadByVendorIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
vendorIDs []gid.GID,
|
||||
) error {
|
||||
if len(vendorIDs) == 0 {
|
||||
*vdpas = VendorDataPrivacyAgreements{}
|
||||
return nil
|
||||
}
|
||||
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendor_data_privacy_agreements
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = ANY(@vendor_ids)
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
ids := make([]string, len(vendorIDs))
|
||||
for i, id := range vendorIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
args := pgx.NamedArgs{"vendor_ids": ids}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query vendor data privacy agreements: %w", err)
|
||||
}
|
||||
|
||||
agreements, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[VendorDataPrivacyAgreement])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect vendor data privacy agreements: %w", err)
|
||||
}
|
||||
|
||||
*vdpas = agreements
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vdpa *VendorDataPrivacyAgreement) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
@@ -130,8 +181,6 @@ SELECT
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -215,8 +264,6 @@ INSERT INTO
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
@@ -228,8 +275,6 @@ VALUES (
|
||||
@valid_from,
|
||||
@valid_until,
|
||||
@file_id,
|
||||
@snapshot_id,
|
||||
@source_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
@@ -238,8 +283,6 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
||||
valid_from = EXCLUDED.valid_from,
|
||||
valid_until = EXCLUDED.valid_until,
|
||||
file_id = EXCLUDED.file_id,
|
||||
snapshot_id = EXCLUDED.snapshot_id,
|
||||
source_id = EXCLUDED.source_id,
|
||||
updated_at = EXCLUDED.updated_at
|
||||
`
|
||||
args := pgx.StrictNamedArgs{
|
||||
@@ -250,8 +293,6 @@ ON CONFLICT (organization_id, vendor_id) DO UPDATE SET
|
||||
"valid_from": vdpa.ValidFrom,
|
||||
"valid_until": vdpa.ValidUntil,
|
||||
"file_id": vdpa.FileID,
|
||||
"snapshot_id": vdpa.SnapshotID,
|
||||
"source_id": vdpa.SourceID,
|
||||
"created_at": vdpa.CreatedAt,
|
||||
"updated_at": vdpa.UpdatedAt,
|
||||
}
|
||||
@@ -316,65 +357,3 @@ WHERE
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
return err
|
||||
}
|
||||
|
||||
func (vdpa VendorDataPrivacyAgreements) InsertVendorSnapshots(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
WITH
|
||||
snapshot_vendors AS (
|
||||
SELECT id, source_id
|
||||
FROM vendors
|
||||
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||
)
|
||||
INSERT INTO vendor_data_privacy_agreements (
|
||||
tenant_id,
|
||||
id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
valid_from,
|
||||
valid_until,
|
||||
file_id,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_data_privacy_agreement_entity_type),
|
||||
@snapshot_id,
|
||||
vdpa.id,
|
||||
vdpa.organization_id,
|
||||
sv.id,
|
||||
vdpa.valid_from,
|
||||
vdpa.valid_until,
|
||||
vdpa.file_id,
|
||||
vdpa.created_at,
|
||||
vdpa.updated_at
|
||||
FROM vendor_data_privacy_agreements vdpa
|
||||
INNER JOIN snapshot_vendors sv ON sv.source_id = vdpa.vendor_id
|
||||
WHERE %s AND vdpa.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_data_privacy_agreement_entity_type": VendorDataPrivacyAgreementEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor data privacy agreement snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -16,19 +16,16 @@ package coredata
|
||||
|
||||
import (
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.probo.inc/probo/pkg/gid"
|
||||
)
|
||||
|
||||
type (
|
||||
VendorFilter struct {
|
||||
showOnTrustCenter *bool
|
||||
snapshotID **gid.GID
|
||||
}
|
||||
)
|
||||
|
||||
func NewVendorFilter(snapshotID **gid.GID, showOnTrustCenter *bool) *VendorFilter {
|
||||
func NewVendorFilter(showOnTrustCenter *bool) *VendorFilter {
|
||||
return &VendorFilter{
|
||||
snapshotID: snapshotID,
|
||||
showOnTrustCenter: showOnTrustCenter,
|
||||
}
|
||||
}
|
||||
@@ -42,17 +39,6 @@ func (f *VendorFilter) SQLArguments() pgx.StrictNamedArgs {
|
||||
args["show_on_trust_center"] = nil
|
||||
}
|
||||
|
||||
if f.snapshotID == nil {
|
||||
args["has_snapshot_filter"] = false
|
||||
args["filter_snapshot_id"] = nil
|
||||
} else if *f.snapshotID == nil {
|
||||
args["has_snapshot_filter"] = true
|
||||
args["filter_snapshot_id"] = nil
|
||||
} else {
|
||||
args["has_snapshot_filter"] = true
|
||||
args["filter_snapshot_id"] = **f.snapshotID
|
||||
}
|
||||
|
||||
return args
|
||||
}
|
||||
|
||||
@@ -64,14 +50,5 @@ func (f *VendorFilter) SQLFragment() string {
|
||||
show_on_trust_center = @show_on_trust_center::boolean
|
||||
ELSE TRUE
|
||||
END
|
||||
AND
|
||||
CASE
|
||||
WHEN @has_snapshot_filter::boolean = false THEN TRUE
|
||||
WHEN @has_snapshot_filter::boolean = true AND @filter_snapshot_id::text IS NOT NULL THEN
|
||||
snapshot_id = @filter_snapshot_id::text
|
||||
WHEN @has_snapshot_filter::boolean = true AND @filter_snapshot_id::text IS NULL THEN
|
||||
snapshot_id IS NULL
|
||||
ELSE TRUE
|
||||
END
|
||||
)`
|
||||
}
|
||||
|
||||
@@ -37,8 +37,6 @@ type (
|
||||
DataSensitivity DataSensitivity `db:"data_sensitivity"`
|
||||
BusinessImpact BusinessImpact `db:"business_impact"`
|
||||
Notes *string `db:"notes"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -137,8 +135,6 @@ SELECT
|
||||
data_sensitivity,
|
||||
business_impact,
|
||||
notes,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -186,8 +182,6 @@ SELECT
|
||||
data_sensitivity,
|
||||
business_impact,
|
||||
notes,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -195,6 +189,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
ORDER BY
|
||||
created_at DESC
|
||||
LIMIT 1;
|
||||
@@ -238,8 +233,6 @@ SELECT
|
||||
data_sensitivity,
|
||||
business_impact,
|
||||
notes,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -247,6 +240,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
AND %s
|
||||
`
|
||||
|
||||
@@ -271,66 +265,59 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v VendorRiskAssessments) InsertVendorSnapshots(
|
||||
func (r *VendorRiskAssessments) LoadByVendorIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
vendorIDs []gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
WITH
|
||||
snapshot_vendors AS (
|
||||
SELECT id, source_id
|
||||
FROM vendors
|
||||
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||
)
|
||||
INSERT INTO vendor_risk_assessments (
|
||||
tenant_id,
|
||||
id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
expires_at,
|
||||
data_sensitivity,
|
||||
business_impact,
|
||||
notes,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_risk_assessment_entity_type),
|
||||
@snapshot_id,
|
||||
vra.id,
|
||||
vra.organization_id,
|
||||
sv.id,
|
||||
vra.expires_at,
|
||||
vra.data_sensitivity,
|
||||
vra.business_impact,
|
||||
vra.notes,
|
||||
vra.created_at,
|
||||
vra.updated_at
|
||||
FROM vendor_risk_assessments vra
|
||||
INNER JOIN snapshot_vendors sv ON sv.source_id = vra.vendor_id
|
||||
WHERE %s AND vra.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_risk_assessment_entity_type": VendorRiskAssessmentEntityType,
|
||||
if len(vendorIDs) == 0 {
|
||||
*r = VendorRiskAssessments{}
|
||||
return nil
|
||||
}
|
||||
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
expires_at,
|
||||
data_sensitivity,
|
||||
business_impact,
|
||||
notes,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendor_risk_assessments
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = ANY(@vendor_ids)
|
||||
AND snapshot_id IS NULL
|
||||
ORDER BY
|
||||
vendor_id, created_at DESC
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
ids := make([]string, len(vendorIDs))
|
||||
for i, id := range vendorIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
args := pgx.StrictNamedArgs{"vendor_ids": ids}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor risk assessment snapshots: %w", err)
|
||||
return fmt.Errorf("cannot query risk assessments: %w", err)
|
||||
}
|
||||
|
||||
assessments, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[VendorRiskAssessment])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect risk assessments: %w", err)
|
||||
}
|
||||
|
||||
*r = assessments
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -34,8 +34,6 @@ type (
|
||||
VendorID gid.GID `db:"vendor_id"`
|
||||
Name string `db:"name"`
|
||||
Description *string `db:"description"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
@@ -81,8 +79,6 @@ SELECT
|
||||
vendor_id,
|
||||
name,
|
||||
description,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -132,8 +128,6 @@ SELECT
|
||||
vendor_id,
|
||||
name,
|
||||
description,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
@@ -141,6 +135,7 @@ FROM
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = @vendor_id
|
||||
AND snapshot_id IS NULL
|
||||
AND %s
|
||||
`
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), cursor.SQLFragment())
|
||||
@@ -167,6 +162,61 @@ WHERE
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vs *VendorServices) LoadByVendorIDs(
|
||||
ctx context.Context,
|
||||
conn pg.Querier,
|
||||
scope Scoper,
|
||||
vendorIDs []gid.GID,
|
||||
) error {
|
||||
if len(vendorIDs) == 0 {
|
||||
*vs = VendorServices{}
|
||||
return nil
|
||||
}
|
||||
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
vendor_id,
|
||||
name,
|
||||
description,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
vendor_services
|
||||
WHERE
|
||||
%s
|
||||
AND vendor_id = ANY(@vendor_ids)
|
||||
AND snapshot_id IS NULL
|
||||
ORDER BY
|
||||
vendor_id, name ASC
|
||||
`
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
ids := make([]string, len(vendorIDs))
|
||||
for i, id := range vendorIDs {
|
||||
ids[i] = id.String()
|
||||
}
|
||||
|
||||
args := pgx.StrictNamedArgs{"vendor_ids": ids}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query vendor services: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
vendorServices, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[VendorService])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect vendor services: %w", err)
|
||||
}
|
||||
|
||||
*vs = vendorServices
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vs VendorService) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
@@ -277,63 +327,3 @@ WHERE
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (vs VendorServices) InsertVendorSnapshots(
|
||||
ctx context.Context,
|
||||
conn pg.Tx,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
snapshotID gid.GID,
|
||||
) error {
|
||||
query := `
|
||||
WITH
|
||||
snapshot_vendors AS (
|
||||
SELECT id, source_id
|
||||
FROM vendors
|
||||
WHERE organization_id = @organization_id AND snapshot_id = @snapshot_id
|
||||
)
|
||||
INSERT INTO vendor_services (
|
||||
tenant_id,
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
vendor_id,
|
||||
name,
|
||||
description,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
@tenant_id,
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @vendor_service_entity_type),
|
||||
@organization_id,
|
||||
@snapshot_id,
|
||||
vs.id,
|
||||
sv.id,
|
||||
vs.name,
|
||||
vs.description,
|
||||
vs.created_at,
|
||||
vs.updated_at
|
||||
FROM vendor_services vs
|
||||
INNER JOIN snapshot_vendors sv ON sv.source_id = vs.vendor_id
|
||||
WHERE %s AND vs.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"vendor_service_entity_type": VendorServiceEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert vendor service snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user