@@ -1,421 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
ComplianceRegistry struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Area *string `db:"area"`
|
||||
Source *string `db:"source"`
|
||||
Requirement *string `db:"requirement"`
|
||||
ActionsToBeImplemented *string `db:"actions_to_be_implemented"`
|
||||
Regulator *string `db:"regulator"`
|
||||
OwnerID gid.GID `db:"owner_id"`
|
||||
LastReviewDate *time.Time `db:"last_review_date"`
|
||||
DueDate *time.Time `db:"due_date"`
|
||||
Status ComplianceRegistryStatus `db:"status"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
ComplianceRegistries []*ComplianceRegistry
|
||||
)
|
||||
|
||||
func (cr *ComplianceRegistry) CursorKey(field ComplianceRegistryOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case ComplianceRegistryOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(cr.ID, cr.CreatedAt)
|
||||
case ComplianceRegistryOrderFieldLastReviewDate:
|
||||
return page.NewCursorKey(cr.ID, cr.LastReviewDate)
|
||||
case ComplianceRegistryOrderFieldDueDate:
|
||||
return page.NewCursorKey(cr.ID, cr.DueDate)
|
||||
case ComplianceRegistryOrderFieldStatus:
|
||||
return page.NewCursorKey(cr.ID, cr.Status)
|
||||
case ComplianceRegistryOrderFieldReferenceId:
|
||||
return page.NewCursorKey(cr.ID, cr.ReferenceID)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (cr *ComplianceRegistry) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
complianceRegistryID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
compliance_registries
|
||||
WHERE
|
||||
%s
|
||||
AND id = @compliance_registry_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"compliance_registry_id": complianceRegistryID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query compliance registry: %w", err)
|
||||
}
|
||||
|
||||
registry, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ComplianceRegistry])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect compliance registry: %w", err)
|
||||
}
|
||||
|
||||
*cr = registry
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (crs *ComplianceRegistries) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *ComplianceRegistryFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
compliance_registries
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count compliance registries: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (crs *ComplianceRegistries) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[ComplianceRegistryOrderField],
|
||||
filter *ComplianceRegistryFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
compliance_registries
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query compliance registries: %w", err)
|
||||
}
|
||||
|
||||
registries, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ComplianceRegistry])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect compliance registries: %w", err)
|
||||
}
|
||||
|
||||
*crs = registries
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr *ComplianceRegistry) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO compliance_registries (
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@organization_id,
|
||||
@reference_id,
|
||||
@area,
|
||||
@source,
|
||||
@requirement,
|
||||
@actions_to_be_implemented,
|
||||
@regulator,
|
||||
@owner_id,
|
||||
@last_review_date,
|
||||
@due_date,
|
||||
@status,
|
||||
@snapshot_id,
|
||||
@source_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": cr.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"organization_id": cr.OrganizationID,
|
||||
"reference_id": cr.ReferenceID,
|
||||
"area": cr.Area,
|
||||
"source": cr.Source,
|
||||
"requirement": cr.Requirement,
|
||||
"actions_to_be_implemented": cr.ActionsToBeImplemented,
|
||||
"regulator": cr.Regulator,
|
||||
"owner_id": cr.OwnerID,
|
||||
"last_review_date": cr.LastReviewDate,
|
||||
"due_date": cr.DueDate,
|
||||
"status": cr.Status,
|
||||
"snapshot_id": cr.SnapshotID,
|
||||
"source_id": cr.SourceID,
|
||||
"created_at": cr.CreatedAt,
|
||||
"updated_at": cr.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert compliance registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr *ComplianceRegistry) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE compliance_registries SET
|
||||
reference_id = @reference_id,
|
||||
area = @area,
|
||||
source = @source,
|
||||
requirement = @requirement,
|
||||
actions_to_be_implemented = @actions_to_be_implemented,
|
||||
regulator = @regulator,
|
||||
owner_id = @owner_id,
|
||||
last_review_date = @last_review_date,
|
||||
due_date = @due_date,
|
||||
status = @status,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": cr.ID,
|
||||
"reference_id": cr.ReferenceID,
|
||||
"area": cr.Area,
|
||||
"source": cr.Source,
|
||||
"requirement": cr.Requirement,
|
||||
"actions_to_be_implemented": cr.ActionsToBeImplemented,
|
||||
"regulator": cr.Regulator,
|
||||
"owner_id": cr.OwnerID,
|
||||
"last_review_date": cr.LastReviewDate,
|
||||
"due_date": cr.DueDate,
|
||||
"status": cr.Status,
|
||||
"updated_at": cr.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update compliance registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cr *ComplianceRegistry) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM compliance_registries
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"id": cr.ID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete compliance registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (crs ComplianceRegistries) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO compliance_registries (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @compliance_registry_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
r.id,
|
||||
r.organization_id,
|
||||
r.reference_id,
|
||||
r.area,
|
||||
r.source,
|
||||
r.requirement,
|
||||
r.actions_to_be_implemented,
|
||||
r.regulator,
|
||||
r.owner_id,
|
||||
r.last_review_date,
|
||||
r.due_date,
|
||||
r.status,
|
||||
r.created_at,
|
||||
r.updated_at
|
||||
FROM compliance_registries r
|
||||
WHERE %s AND r.organization_id = @organization_id AND r.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"compliance_registry_entity_type": ComplianceRegistryEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert compliance registry snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ComplianceRegistryOrderField string
|
||||
|
||||
const (
|
||||
ComplianceRegistryOrderFieldCreatedAt ComplianceRegistryOrderField = "CREATED_AT"
|
||||
ComplianceRegistryOrderFieldLastReviewDate ComplianceRegistryOrderField = "LAST_REVIEW_DATE"
|
||||
ComplianceRegistryOrderFieldDueDate ComplianceRegistryOrderField = "DUE_DATE"
|
||||
ComplianceRegistryOrderFieldStatus ComplianceRegistryOrderField = "STATUS"
|
||||
ComplianceRegistryOrderFieldReferenceId ComplianceRegistryOrderField = "REFERENCE_ID"
|
||||
)
|
||||
|
||||
func (p ComplianceRegistryOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ComplianceRegistryOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ComplianceRegistryOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *ComplianceRegistryOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(ComplianceRegistryOrderFieldCreatedAt),
|
||||
string(ComplianceRegistryOrderFieldLastReviewDate),
|
||||
string(ComplianceRegistryOrderFieldDueDate),
|
||||
string(ComplianceRegistryOrderFieldStatus),
|
||||
string(ComplianceRegistryOrderFieldReferenceId):
|
||||
*p = ComplianceRegistryOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid ComplianceRegistryOrderField value: %q", val)
|
||||
}
|
||||
@@ -20,18 +20,18 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
NonconformityRegistryFilter struct {
|
||||
ContinualImprovementFilter struct {
|
||||
snapshotID **gid.GID
|
||||
}
|
||||
)
|
||||
|
||||
func NewNonconformityRegistryFilter(snapshotID **gid.GID) *NonconformityRegistryFilter {
|
||||
return &NonconformityRegistryFilter{
|
||||
func NewContinualImprovementFilter(snapshotID **gid.GID) *ContinualImprovementFilter {
|
||||
return &ContinualImprovementFilter{
|
||||
snapshotID: snapshotID,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *NonconformityRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
func (f *ContinualImprovementFilter) SQLArguments() pgx.NamedArgs {
|
||||
args := pgx.NamedArgs{}
|
||||
|
||||
if f.snapshotID != nil && *f.snapshotID != nil {
|
||||
@@ -41,7 +41,7 @@ func (f *NonconformityRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
return args
|
||||
}
|
||||
|
||||
func (f *NonconformityRegistryFilter) SQLFragment() string {
|
||||
func (f *ContinualImprovementFilter) SQLFragment() string {
|
||||
if f.snapshotID == nil {
|
||||
return "TRUE"
|
||||
}
|
||||
55
pkg/coredata/continual_improvement_order_field.go
Normal file
55
pkg/coredata/continual_improvement_order_field.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ContinualImprovementOrderField string
|
||||
|
||||
const (
|
||||
ContinualImprovementOrderFieldCreatedAt ContinualImprovementOrderField = "CREATED_AT"
|
||||
ContinualImprovementOrderFieldTargetDate ContinualImprovementOrderField = "TARGET_DATE"
|
||||
ContinualImprovementOrderFieldStatus ContinualImprovementOrderField = "STATUS"
|
||||
ContinualImprovementOrderFieldPriority ContinualImprovementOrderField = "PRIORITY"
|
||||
ContinualImprovementOrderFieldReferenceId ContinualImprovementOrderField = "REFERENCE_ID"
|
||||
)
|
||||
|
||||
func (p ContinualImprovementOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ContinualImprovementOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ContinualImprovementOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *ContinualImprovementOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(ContinualImprovementOrderFieldCreatedAt),
|
||||
string(ContinualImprovementOrderFieldTargetDate),
|
||||
string(ContinualImprovementOrderFieldStatus),
|
||||
string(ContinualImprovementOrderFieldPriority),
|
||||
string(ContinualImprovementOrderFieldReferenceId):
|
||||
*p = ContinualImprovementOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid ContinualImprovementOrderField value: %q", val)
|
||||
}
|
||||
@@ -19,19 +19,19 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ContinualImprovementRegistriesPriority string
|
||||
type ContinualImprovementPriority string
|
||||
|
||||
const (
|
||||
ContinualImprovementRegistriesPriorityLow ContinualImprovementRegistriesPriority = "LOW"
|
||||
ContinualImprovementRegistriesPriorityMedium ContinualImprovementRegistriesPriority = "MEDIUM"
|
||||
ContinualImprovementRegistriesPriorityHigh ContinualImprovementRegistriesPriority = "HIGH"
|
||||
ContinualImprovementPriorityLow ContinualImprovementPriority = "LOW"
|
||||
ContinualImprovementPriorityMedium ContinualImprovementPriority = "MEDIUM"
|
||||
ContinualImprovementPriorityHigh ContinualImprovementPriority = "HIGH"
|
||||
)
|
||||
|
||||
func (cirp ContinualImprovementRegistriesPriority) String() string {
|
||||
return string(cirp)
|
||||
func (cip ContinualImprovementPriority) String() string {
|
||||
return string(cip)
|
||||
}
|
||||
|
||||
func (cirp *ContinualImprovementRegistriesPriority) Scan(value any) error {
|
||||
func (cip *ContinualImprovementPriority) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -39,22 +39,22 @@ func (cirp *ContinualImprovementRegistriesPriority) Scan(value any) error {
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ContinualImprovementRegistriesPriority: %T", value)
|
||||
return fmt.Errorf("unsupported type for ContinualImprovementPriority: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "LOW":
|
||||
*cirp = ContinualImprovementRegistriesPriorityLow
|
||||
*cip = ContinualImprovementPriorityLow
|
||||
case "MEDIUM":
|
||||
*cirp = ContinualImprovementRegistriesPriorityMedium
|
||||
*cip = ContinualImprovementPriorityMedium
|
||||
case "HIGH":
|
||||
*cirp = ContinualImprovementRegistriesPriorityHigh
|
||||
*cip = ContinualImprovementPriorityHigh
|
||||
default:
|
||||
return fmt.Errorf("invalid ContinualImprovementRegistriesPriority value: %q", s)
|
||||
return fmt.Errorf("invalid ContinualImprovementPriority value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cirp ContinualImprovementRegistriesPriority) Value() (driver.Value, error) {
|
||||
return cirp.String(), nil
|
||||
func (cip ContinualImprovementPriority) Value() (driver.Value, error) {
|
||||
return cip.String(), nil
|
||||
}
|
||||
@@ -1,383 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
ContinualImprovementRegistry struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Description *string `db:"description"`
|
||||
Source *string `db:"source"`
|
||||
OwnerID gid.GID `db:"owner_id"`
|
||||
TargetDate *time.Time `db:"target_date"`
|
||||
Status ContinualImprovementRegistriesStatus `db:"status"`
|
||||
Priority ContinualImprovementRegistriesPriority `db:"priority"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
ContinualImprovementRegistries []*ContinualImprovementRegistry
|
||||
)
|
||||
|
||||
func (cir *ContinualImprovementRegistry) CursorKey(field ContinualImprovementRegistriesOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case ContinualImprovementRegistriesOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(cir.ID, cir.CreatedAt)
|
||||
case ContinualImprovementRegistriesOrderFieldTargetDate:
|
||||
return page.NewCursorKey(cir.ID, cir.TargetDate)
|
||||
case ContinualImprovementRegistriesOrderFieldStatus:
|
||||
return page.NewCursorKey(cir.ID, cir.Status)
|
||||
case ContinualImprovementRegistriesOrderFieldPriority:
|
||||
return page.NewCursorKey(cir.ID, cir.Priority)
|
||||
case ContinualImprovementRegistriesOrderFieldReferenceId:
|
||||
return page.NewCursorKey(cir.ID, cir.ReferenceID)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (cir *ContinualImprovementRegistry) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
continualImprovementRegistryID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
continual_improvement_registries
|
||||
WHERE
|
||||
%s
|
||||
AND id = @continual_improvement_registry_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"continual_improvement_registry_id": continualImprovementRegistryID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query continual improvement registry: %w", err)
|
||||
}
|
||||
|
||||
registry, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ContinualImprovementRegistry])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect continual improvement registry: %w", err)
|
||||
}
|
||||
|
||||
*cir = registry
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cirs *ContinualImprovementRegistries) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *ContinualImprovementRegistryFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
continual_improvement_registries
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count continual improvement registries: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (cirs *ContinualImprovementRegistries) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[ContinualImprovementRegistriesOrderField],
|
||||
filter *ContinualImprovementRegistryFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
continual_improvement_registries
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query continual improvement registries: %w", err)
|
||||
}
|
||||
|
||||
registries, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ContinualImprovementRegistry])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect continual improvement registries: %w", err)
|
||||
}
|
||||
|
||||
*cirs = registries
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cir *ContinualImprovementRegistry) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO continual_improvement_registries (
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@organization_id,
|
||||
@reference_id,
|
||||
@description,
|
||||
@source,
|
||||
@owner_id,
|
||||
@target_date,
|
||||
@status,
|
||||
@priority,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": cir.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"organization_id": cir.OrganizationID,
|
||||
"reference_id": cir.ReferenceID,
|
||||
"description": cir.Description,
|
||||
"source": cir.Source,
|
||||
"owner_id": cir.OwnerID,
|
||||
"target_date": cir.TargetDate,
|
||||
"status": cir.Status,
|
||||
"priority": cir.Priority,
|
||||
"created_at": cir.CreatedAt,
|
||||
"updated_at": cir.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert continual improvement registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cir *ContinualImprovementRegistry) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE continual_improvement_registries SET
|
||||
reference_id = @reference_id,
|
||||
description = @description,
|
||||
source = @source,
|
||||
owner_id = @owner_id,
|
||||
target_date = @target_date,
|
||||
status = @status,
|
||||
priority = @priority,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": cir.ID,
|
||||
"reference_id": cir.ReferenceID,
|
||||
"description": cir.Description,
|
||||
"source": cir.Source,
|
||||
"owner_id": cir.OwnerID,
|
||||
"target_date": cir.TargetDate,
|
||||
"status": cir.Status,
|
||||
"priority": cir.Priority,
|
||||
"updated_at": cir.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update continual improvement registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cir *ContinualImprovementRegistry) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM continual_improvement_registries
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"id": cir.ID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete continual improvement registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cirs ContinualImprovementRegistries) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO continual_improvement_registries (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @continual_improvement_registry_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
r.id,
|
||||
r.organization_id,
|
||||
r.reference_id,
|
||||
r.description,
|
||||
r.source,
|
||||
r.owner_id,
|
||||
r.target_date,
|
||||
r.status,
|
||||
r.priority,
|
||||
r.created_at,
|
||||
r.updated_at
|
||||
FROM continual_improvement_registries r
|
||||
WHERE %s AND r.organization_id = @organization_id AND r.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"continual_improvement_registry_entity_type": ContinualImprovementRegistryEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert continual improvement registry snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ContinualImprovementRegistriesOrderField string
|
||||
|
||||
const (
|
||||
ContinualImprovementRegistriesOrderFieldCreatedAt ContinualImprovementRegistriesOrderField = "CREATED_AT"
|
||||
ContinualImprovementRegistriesOrderFieldTargetDate ContinualImprovementRegistriesOrderField = "TARGET_DATE"
|
||||
ContinualImprovementRegistriesOrderFieldStatus ContinualImprovementRegistriesOrderField = "STATUS"
|
||||
ContinualImprovementRegistriesOrderFieldPriority ContinualImprovementRegistriesOrderField = "PRIORITY"
|
||||
ContinualImprovementRegistriesOrderFieldReferenceId ContinualImprovementRegistriesOrderField = "REFERENCE_ID"
|
||||
)
|
||||
|
||||
func (p ContinualImprovementRegistriesOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ContinualImprovementRegistriesOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ContinualImprovementRegistriesOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *ContinualImprovementRegistriesOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(ContinualImprovementRegistriesOrderFieldCreatedAt),
|
||||
string(ContinualImprovementRegistriesOrderFieldTargetDate),
|
||||
string(ContinualImprovementRegistriesOrderFieldStatus),
|
||||
string(ContinualImprovementRegistriesOrderFieldPriority),
|
||||
string(ContinualImprovementRegistriesOrderFieldReferenceId):
|
||||
*p = ContinualImprovementRegistriesOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid ContinualImprovementRegistriesOrderField value: %q", val)
|
||||
}
|
||||
@@ -19,19 +19,19 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type NonconformityRegistryStatus string
|
||||
type ContinualImprovementStatus string
|
||||
|
||||
const (
|
||||
NonconformityRegistryStatusOpen NonconformityRegistryStatus = "OPEN"
|
||||
NonconformityRegistryStatusInProgress NonconformityRegistryStatus = "IN_PROGRESS"
|
||||
NonconformityRegistryStatusClosed NonconformityRegistryStatus = "CLOSED"
|
||||
ContinualImprovementStatusOpen ContinualImprovementStatus = "OPEN"
|
||||
ContinualImprovementStatusInProgress ContinualImprovementStatus = "IN_PROGRESS"
|
||||
ContinualImprovementStatusClosed ContinualImprovementStatus = "CLOSED"
|
||||
)
|
||||
|
||||
func (nrs NonconformityRegistryStatus) String() string {
|
||||
return string(nrs)
|
||||
func (cis ContinualImprovementStatus) String() string {
|
||||
return string(cis)
|
||||
}
|
||||
|
||||
func (nrs *NonconformityRegistryStatus) Scan(value any) error {
|
||||
func (cis *ContinualImprovementStatus) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -39,22 +39,22 @@ func (nrs *NonconformityRegistryStatus) Scan(value any) error {
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for NonconformityRegistryStatus: %T", value)
|
||||
return fmt.Errorf("unsupported type for ContinualImprovementStatus: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "OPEN":
|
||||
*nrs = NonconformityRegistryStatusOpen
|
||||
*cis = ContinualImprovementStatusOpen
|
||||
case "IN_PROGRESS":
|
||||
*nrs = NonconformityRegistryStatusInProgress
|
||||
*cis = ContinualImprovementStatusInProgress
|
||||
case "CLOSED":
|
||||
*nrs = NonconformityRegistryStatusClosed
|
||||
*cis = ContinualImprovementStatusClosed
|
||||
default:
|
||||
return fmt.Errorf("invalid NonconformityRegistryStatus value: %q", s)
|
||||
return fmt.Errorf("invalid ContinualImprovementStatus value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nrs NonconformityRegistryStatus) Value() (driver.Value, error) {
|
||||
return nrs.String(), nil
|
||||
func (cis ContinualImprovementStatus) Value() (driver.Value, error) {
|
||||
return cis.String(), nil
|
||||
}
|
||||
383
pkg/coredata/continual_improvements.go
Normal file
383
pkg/coredata/continual_improvements.go
Normal file
@@ -0,0 +1,383 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
ContinualImprovement struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Description *string `db:"description"`
|
||||
Source *string `db:"source"`
|
||||
OwnerID gid.GID `db:"owner_id"`
|
||||
TargetDate *time.Time `db:"target_date"`
|
||||
Status ContinualImprovementStatus `db:"status"`
|
||||
Priority ContinualImprovementPriority `db:"priority"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
ContinualImprovements []*ContinualImprovement
|
||||
)
|
||||
|
||||
func (ci *ContinualImprovement) CursorKey(field ContinualImprovementOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case ContinualImprovementOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(ci.ID, ci.CreatedAt)
|
||||
case ContinualImprovementOrderFieldTargetDate:
|
||||
return page.NewCursorKey(ci.ID, ci.TargetDate)
|
||||
case ContinualImprovementOrderFieldStatus:
|
||||
return page.NewCursorKey(ci.ID, ci.Status)
|
||||
case ContinualImprovementOrderFieldPriority:
|
||||
return page.NewCursorKey(ci.ID, ci.Priority)
|
||||
case ContinualImprovementOrderFieldReferenceId:
|
||||
return page.NewCursorKey(ci.ID, ci.ReferenceID)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (ci *ContinualImprovement) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
continualImprovementID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
continual_improvements
|
||||
WHERE
|
||||
%s
|
||||
AND id = @continual_improvement_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"continual_improvement_id": continualImprovementID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query continual improvement: %w", err)
|
||||
}
|
||||
|
||||
improvement, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ContinualImprovement])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect continual improvement: %w", err)
|
||||
}
|
||||
|
||||
*ci = improvement
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cis *ContinualImprovements) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *ContinualImprovementFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
continual_improvements
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count continual improvements: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (cis *ContinualImprovements) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[ContinualImprovementOrderField],
|
||||
filter *ContinualImprovementFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
continual_improvements
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query continual improvements: %w", err)
|
||||
}
|
||||
|
||||
improvements, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ContinualImprovement])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect continual improvements: %w", err)
|
||||
}
|
||||
|
||||
*cis = improvements
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ci *ContinualImprovement) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO continual_improvements (
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@organization_id,
|
||||
@reference_id,
|
||||
@description,
|
||||
@source,
|
||||
@owner_id,
|
||||
@target_date,
|
||||
@status,
|
||||
@priority,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": ci.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"organization_id": ci.OrganizationID,
|
||||
"reference_id": ci.ReferenceID,
|
||||
"description": ci.Description,
|
||||
"source": ci.Source,
|
||||
"owner_id": ci.OwnerID,
|
||||
"target_date": ci.TargetDate,
|
||||
"status": ci.Status,
|
||||
"priority": ci.Priority,
|
||||
"created_at": ci.CreatedAt,
|
||||
"updated_at": ci.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert continual improvement: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ci *ContinualImprovement) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE continual_improvements SET
|
||||
reference_id = @reference_id,
|
||||
description = @description,
|
||||
source = @source,
|
||||
owner_id = @owner_id,
|
||||
target_date = @target_date,
|
||||
status = @status,
|
||||
priority = @priority,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": ci.ID,
|
||||
"reference_id": ci.ReferenceID,
|
||||
"description": ci.Description,
|
||||
"source": ci.Source,
|
||||
"owner_id": ci.OwnerID,
|
||||
"target_date": ci.TargetDate,
|
||||
"status": ci.Status,
|
||||
"priority": ci.Priority,
|
||||
"updated_at": ci.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update continual improvement: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ci *ContinualImprovement) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM continual_improvements
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"id": ci.ID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete continual improvement: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cis ContinualImprovements) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO continual_improvements (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
source,
|
||||
owner_id,
|
||||
target_date,
|
||||
status,
|
||||
priority,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @continual_improvement_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
r.id,
|
||||
r.organization_id,
|
||||
r.reference_id,
|
||||
r.description,
|
||||
r.source,
|
||||
r.owner_id,
|
||||
r.target_date,
|
||||
r.status,
|
||||
r.priority,
|
||||
r.created_at,
|
||||
r.updated_at
|
||||
FROM continual_improvements r
|
||||
WHERE %s AND r.organization_id = @organization_id AND r.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"continual_improvement_entity_type": ContinualImprovementEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert continual improvement snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -43,11 +43,11 @@ const (
|
||||
FileEntityType
|
||||
VendorContactEntityType
|
||||
VendorDataPrivacyAgreementEntityType
|
||||
NonconformityRegistryEntityType
|
||||
ComplianceRegistryEntityType
|
||||
NonconformityEntityType
|
||||
ObligationEntityType
|
||||
VendorServiceEntityType
|
||||
SnapshotEntityType
|
||||
ContinualImprovementRegistryEntityType
|
||||
ProcessingActivityRegistryEntityType
|
||||
ContinualImprovementEntityType
|
||||
ProcessingActivityEntityType
|
||||
FrameworkExportEntityType
|
||||
)
|
||||
|
||||
51
pkg/coredata/migrations/20250905T122423Z.sql
Normal file
51
pkg/coredata/migrations/20250905T122423Z.sql
Normal file
@@ -0,0 +1,51 @@
|
||||
ALTER TYPE nonconformity_registries_status RENAME TO nonconformities_status;
|
||||
|
||||
ALTER TYPE snapshots_type
|
||||
RENAME VALUE 'NONCONFORMITY_REGISTRIES' TO 'NONCONFORMITIES';
|
||||
|
||||
ALTER TABLE nonconformity_registries RENAME TO nonconformities;
|
||||
|
||||
ALTER TABLE nonconformities RENAME CONSTRAINT nonconformity_registries_organization_id_fkey TO nonconformities_organization_id_fkey;
|
||||
ALTER TABLE nonconformities RENAME CONSTRAINT nonconformity_registries_owner_id_fkey TO nonconformities_owner_id_fkey;
|
||||
ALTER TABLE nonconformities RENAME CONSTRAINT nonconformity_registries_audit_id_fkey TO nonconformities_audit_id_fkey;
|
||||
ALTER TABLE nonconformities RENAME CONSTRAINT nonconformity_registries_snapshot_id_fkey TO nonconformities_snapshot_id_fkey;
|
||||
ALTER TABLE nonconformities RENAME CONSTRAINT nonconformity_registries_source_id_snapshot_id_key TO nonconformities_source_id_snapshot_id_key;
|
||||
|
||||
ALTER TYPE continual_improvement_registries_status RENAME TO continual_improvements_status;
|
||||
|
||||
ALTER TYPE snapshots_type
|
||||
RENAME VALUE 'CONTINUAL_IMPROVEMENT_REGISTRIES' TO 'CONTINUAL_IMPROVEMENTS';
|
||||
|
||||
ALTER TABLE continual_improvement_registries RENAME TO continual_improvements;
|
||||
|
||||
ALTER TABLE continual_improvements RENAME CONSTRAINT continual_improvement_registries_organization_id_fkey TO continual_improvements_organization_id_fkey;
|
||||
ALTER TABLE continual_improvements RENAME CONSTRAINT continual_improvement_registries_owner_id_fkey TO continual_improvements_owner_id_fkey;
|
||||
ALTER TABLE continual_improvements RENAME CONSTRAINT continual_improvement_registries_snapshot_id_fkey TO continual_improvements_snapshot_id_fkey;
|
||||
ALTER TABLE continual_improvements RENAME CONSTRAINT continual_improvement_registries_source_id_snapshot_id_key TO continual_improvements_source_id_snapshot_id_key;
|
||||
|
||||
ALTER TYPE processing_activity_registries_special_or_criminal_data RENAME TO processing_activities_special_or_criminal_data;
|
||||
ALTER TYPE processing_activity_registries_lawful_basis RENAME TO processing_activities_lawful_basis;
|
||||
ALTER TYPE processing_activity_registries_transfer_safeguards RENAME TO processing_activities_transfer_safeguards;
|
||||
ALTER TYPE processing_activity_registries_data_protection_impact_assessment RENAME TO processing_activities_data_protection_impact_assessment;
|
||||
ALTER TYPE processing_activity_registries_transfer_impact_assessment RENAME TO processing_activities_transfer_impact_assessment;
|
||||
|
||||
ALTER TYPE snapshots_type
|
||||
RENAME VALUE 'PROCESSING_ACTIVITY_REGISTRIES' TO 'PROCESSING_ACTIVITIES';
|
||||
|
||||
ALTER TABLE processing_activity_registries RENAME TO processing_activities;
|
||||
|
||||
ALTER TABLE processing_activities RENAME CONSTRAINT processing_activity_registries_organization_id_fkey TO processing_activities_organization_id_fkey;
|
||||
ALTER TABLE processing_activities RENAME CONSTRAINT processing_activity_registries_snapshot_id_fkey TO processing_activities_snapshot_id_fkey;
|
||||
ALTER TABLE processing_activities RENAME CONSTRAINT processing_activity_registries_source_id_snapshot_id_key TO processing_activities_source_id_snapshot_id_key;
|
||||
|
||||
ALTER TYPE compliance_registries_status RENAME TO obligations_status;
|
||||
|
||||
ALTER TYPE snapshots_type
|
||||
RENAME VALUE 'COMPLIANCE_REGISTRIES' TO 'OBLIGATIONS';
|
||||
|
||||
ALTER TABLE compliance_registries RENAME TO obligations;
|
||||
|
||||
ALTER TABLE obligations RENAME CONSTRAINT compliance_registries_organization_id_fkey TO obligations_organization_id_fkey;
|
||||
ALTER TABLE obligations RENAME CONSTRAINT compliance_registries_owner_id_fkey TO obligations_owner_id_fkey;
|
||||
ALTER TABLE obligations RENAME CONSTRAINT compliance_registries_snapshot_id_fkey TO obligations_snapshot_id_fkey;
|
||||
ALTER TABLE obligations RENAME CONSTRAINT compliance_registries_source_id_snapshot_id_key TO obligations_source_id_snapshot_id_key;
|
||||
415
pkg/coredata/nonconformity.go
Normal file
415
pkg/coredata/nonconformity.go
Normal file
@@ -0,0 +1,415 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
Nonconformity struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Description *string `db:"description"`
|
||||
AuditID gid.GID `db:"audit_id"`
|
||||
DateIdentified *time.Time `db:"date_identified"`
|
||||
RootCause string `db:"root_cause"`
|
||||
CorrectiveAction *string `db:"corrective_action"`
|
||||
OwnerID gid.GID `db:"owner_id"`
|
||||
DueDate *time.Time `db:"due_date"`
|
||||
Status NonconformityStatus `db:"status"`
|
||||
EffectivenessCheck *string `db:"effectiveness_check"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Nonconformities []*Nonconformity
|
||||
)
|
||||
|
||||
func (nc *Nonconformity) CursorKey(field NonconformityOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case NonconformityOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(nc.ID, nc.CreatedAt)
|
||||
case NonconformityOrderFieldDateIdentified:
|
||||
return page.NewCursorKey(nc.ID, nc.DateIdentified)
|
||||
case NonconformityOrderFieldDueDate:
|
||||
return page.NewCursorKey(nc.ID, nc.DueDate)
|
||||
case NonconformityOrderFieldStatus:
|
||||
return page.NewCursorKey(nc.ID, nc.Status)
|
||||
case NonconformityOrderFieldReferenceId:
|
||||
return page.NewCursorKey(nc.ID, nc.ReferenceID)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (nc *Nonconformity) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
nonconformityID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
nonconformities
|
||||
WHERE
|
||||
%s
|
||||
AND id = @nonconformity_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"nonconformity_id": nonconformityID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query nonconformity: %w", err)
|
||||
}
|
||||
|
||||
nonconformity, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Nonconformity])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect nonconformity: %w", err)
|
||||
}
|
||||
|
||||
*nc = nonconformity
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncs *Nonconformities) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *NonconformityFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
nonconformities
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count nonconformities: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (ncs *Nonconformities) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[NonconformityOrderField],
|
||||
filter *NonconformityFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
nonconformities
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query nonconformities: %w", err)
|
||||
}
|
||||
|
||||
nonconformities, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Nonconformity])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect nonconformities: %w", err)
|
||||
}
|
||||
|
||||
*ncs = nonconformities
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *Nonconformity) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO nonconformities (
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@organization_id,
|
||||
@reference_id,
|
||||
@description,
|
||||
@audit_id,
|
||||
@date_identified,
|
||||
@root_cause,
|
||||
@corrective_action,
|
||||
@owner_id,
|
||||
@due_date,
|
||||
@status,
|
||||
@effectiveness_check,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": nc.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"organization_id": nc.OrganizationID,
|
||||
"reference_id": nc.ReferenceID,
|
||||
"description": nc.Description,
|
||||
"audit_id": nc.AuditID,
|
||||
"date_identified": nc.DateIdentified,
|
||||
"root_cause": nc.RootCause,
|
||||
"corrective_action": nc.CorrectiveAction,
|
||||
"owner_id": nc.OwnerID,
|
||||
"due_date": nc.DueDate,
|
||||
"status": nc.Status,
|
||||
"effectiveness_check": nc.EffectivenessCheck,
|
||||
"created_at": nc.CreatedAt,
|
||||
"updated_at": nc.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert nonconformity: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *Nonconformity) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE nonconformities
|
||||
SET
|
||||
reference_id = @reference_id,
|
||||
description = @description,
|
||||
date_identified = @date_identified,
|
||||
root_cause = @root_cause,
|
||||
corrective_action = @corrective_action,
|
||||
due_date = @due_date,
|
||||
status = @status,
|
||||
effectiveness_check = @effectiveness_check,
|
||||
owner_id = @owner_id,
|
||||
audit_id = @audit_id,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": nc.ID,
|
||||
"reference_id": nc.ReferenceID,
|
||||
"description": nc.Description,
|
||||
"date_identified": nc.DateIdentified,
|
||||
"root_cause": nc.RootCause,
|
||||
"corrective_action": nc.CorrectiveAction,
|
||||
"due_date": nc.DueDate,
|
||||
"status": nc.Status,
|
||||
"effectiveness_check": nc.EffectivenessCheck,
|
||||
"owner_id": nc.OwnerID,
|
||||
"audit_id": nc.AuditID,
|
||||
"updated_at": nc.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update nonconformity: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nc *Nonconformity) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM nonconformities
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"id": nc.ID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete nonconformity: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ncs Nonconformities) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO nonconformities (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @nonconformity_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
nc.id,
|
||||
nc.organization_id,
|
||||
nc.reference_id,
|
||||
nc.description,
|
||||
nc.audit_id,
|
||||
nc.date_identified,
|
||||
nc.root_cause,
|
||||
nc.corrective_action,
|
||||
nc.owner_id,
|
||||
nc.due_date,
|
||||
nc.status,
|
||||
nc.effectiveness_check,
|
||||
nc.created_at,
|
||||
nc.updated_at
|
||||
FROM nonconformities nc
|
||||
WHERE %s AND nc.organization_id = @organization_id AND nc.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"nonconformity_entity_type": NonconformityEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert data snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -20,18 +20,18 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
ProcessingActivityRegistryFilter struct {
|
||||
NonconformityFilter struct {
|
||||
snapshotID **gid.GID
|
||||
}
|
||||
)
|
||||
|
||||
func NewProcessingActivityRegistryFilter(snapshotID **gid.GID) *ProcessingActivityRegistryFilter {
|
||||
return &ProcessingActivityRegistryFilter{
|
||||
func NewNonconformityFilter(snapshotID **gid.GID) *NonconformityFilter {
|
||||
return &NonconformityFilter{
|
||||
snapshotID: snapshotID,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ProcessingActivityRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
func (f *NonconformityFilter) SQLArguments() pgx.NamedArgs {
|
||||
args := pgx.NamedArgs{}
|
||||
|
||||
if f.snapshotID != nil && *f.snapshotID != nil {
|
||||
@@ -41,7 +41,7 @@ func (f *ProcessingActivityRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
return args
|
||||
}
|
||||
|
||||
func (f *ProcessingActivityRegistryFilter) SQLFragment() string {
|
||||
func (f *NonconformityFilter) SQLFragment() string {
|
||||
if f.snapshotID == nil {
|
||||
return "TRUE"
|
||||
}
|
||||
55
pkg/coredata/nonconformity_order_field.go
Normal file
55
pkg/coredata/nonconformity_order_field.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type NonconformityOrderField string
|
||||
|
||||
const (
|
||||
NonconformityOrderFieldCreatedAt NonconformityOrderField = "CREATED_AT"
|
||||
NonconformityOrderFieldDateIdentified NonconformityOrderField = "DATE_IDENTIFIED"
|
||||
NonconformityOrderFieldDueDate NonconformityOrderField = "DUE_DATE"
|
||||
NonconformityOrderFieldStatus NonconformityOrderField = "STATUS"
|
||||
NonconformityOrderFieldReferenceId NonconformityOrderField = "REFERENCE_ID"
|
||||
)
|
||||
|
||||
func (p NonconformityOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p NonconformityOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p NonconformityOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *NonconformityOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(NonconformityOrderFieldCreatedAt),
|
||||
string(NonconformityOrderFieldDateIdentified),
|
||||
string(NonconformityOrderFieldDueDate),
|
||||
string(NonconformityOrderFieldStatus),
|
||||
string(NonconformityOrderFieldReferenceId):
|
||||
*p = NonconformityOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid NonconformityOrderField value: %q", val)
|
||||
}
|
||||
@@ -1,415 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
NonconformityRegistry struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Description *string `db:"description"`
|
||||
AuditID gid.GID `db:"audit_id"`
|
||||
DateIdentified *time.Time `db:"date_identified"`
|
||||
RootCause string `db:"root_cause"`
|
||||
CorrectiveAction *string `db:"corrective_action"`
|
||||
OwnerID gid.GID `db:"owner_id"`
|
||||
DueDate *time.Time `db:"due_date"`
|
||||
Status NonconformityRegistryStatus `db:"status"`
|
||||
EffectivenessCheck *string `db:"effectiveness_check"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
NonconformityRegistries []*NonconformityRegistry
|
||||
)
|
||||
|
||||
func (nr *NonconformityRegistry) CursorKey(field NonconformityRegistryOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case NonconformityRegistryOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(nr.ID, nr.CreatedAt)
|
||||
case NonconformityRegistryOrderFieldDateIdentified:
|
||||
return page.NewCursorKey(nr.ID, nr.DateIdentified)
|
||||
case NonconformityRegistryOrderFieldDueDate:
|
||||
return page.NewCursorKey(nr.ID, nr.DueDate)
|
||||
case NonconformityRegistryOrderFieldStatus:
|
||||
return page.NewCursorKey(nr.ID, nr.Status)
|
||||
case NonconformityRegistryOrderFieldReferenceId:
|
||||
return page.NewCursorKey(nr.ID, nr.ReferenceID)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (nr *NonconformityRegistry) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
nonconformityRegistryID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
nonconformity_registries
|
||||
WHERE
|
||||
%s
|
||||
AND id = @nonconformity_registry_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"nonconformity_registry_id": nonconformityRegistryID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query nonconformity registry: %w", err)
|
||||
}
|
||||
|
||||
registry, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[NonconformityRegistry])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect nonconformity registry: %w", err)
|
||||
}
|
||||
|
||||
*nr = registry
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nrs *NonconformityRegistries) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *NonconformityRegistryFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
nonconformity_registries
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count nonconformity registries: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (nrs *NonconformityRegistries) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[NonconformityRegistryOrderField],
|
||||
filter *NonconformityRegistryFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
nonconformity_registries
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query nonconformity registries: %w", err)
|
||||
}
|
||||
|
||||
registries, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[NonconformityRegistry])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect nonconformity registries: %w", err)
|
||||
}
|
||||
|
||||
*nrs = registries
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nr *NonconformityRegistry) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO nonconformity_registries (
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@organization_id,
|
||||
@reference_id,
|
||||
@description,
|
||||
@audit_id,
|
||||
@date_identified,
|
||||
@root_cause,
|
||||
@corrective_action,
|
||||
@owner_id,
|
||||
@due_date,
|
||||
@status,
|
||||
@effectiveness_check,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": nr.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"organization_id": nr.OrganizationID,
|
||||
"reference_id": nr.ReferenceID,
|
||||
"description": nr.Description,
|
||||
"audit_id": nr.AuditID,
|
||||
"date_identified": nr.DateIdentified,
|
||||
"root_cause": nr.RootCause,
|
||||
"corrective_action": nr.CorrectiveAction,
|
||||
"owner_id": nr.OwnerID,
|
||||
"due_date": nr.DueDate,
|
||||
"status": nr.Status,
|
||||
"effectiveness_check": nr.EffectivenessCheck,
|
||||
"created_at": nr.CreatedAt,
|
||||
"updated_at": nr.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert nonconformity registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nr *NonconformityRegistry) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE nonconformity_registries
|
||||
SET
|
||||
reference_id = @reference_id,
|
||||
description = @description,
|
||||
date_identified = @date_identified,
|
||||
root_cause = @root_cause,
|
||||
corrective_action = @corrective_action,
|
||||
due_date = @due_date,
|
||||
status = @status,
|
||||
effectiveness_check = @effectiveness_check,
|
||||
owner_id = @owner_id,
|
||||
audit_id = @audit_id,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": nr.ID,
|
||||
"reference_id": nr.ReferenceID,
|
||||
"description": nr.Description,
|
||||
"date_identified": nr.DateIdentified,
|
||||
"root_cause": nr.RootCause,
|
||||
"corrective_action": nr.CorrectiveAction,
|
||||
"due_date": nr.DueDate,
|
||||
"status": nr.Status,
|
||||
"effectiveness_check": nr.EffectivenessCheck,
|
||||
"owner_id": nr.OwnerID,
|
||||
"audit_id": nr.AuditID,
|
||||
"updated_at": nr.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update nonconformity registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nr *NonconformityRegistry) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM nonconformity_registries
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"id": nr.ID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete nonconformity registry: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (nrs NonconformityRegistries) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO nonconformity_registries (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
description,
|
||||
audit_id,
|
||||
date_identified,
|
||||
root_cause,
|
||||
corrective_action,
|
||||
owner_id,
|
||||
due_date,
|
||||
status,
|
||||
effectiveness_check,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @nonconformity_registry_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
r.id,
|
||||
r.organization_id,
|
||||
r.reference_id,
|
||||
r.description,
|
||||
r.audit_id,
|
||||
r.date_identified,
|
||||
r.root_cause,
|
||||
r.corrective_action,
|
||||
r.owner_id,
|
||||
r.due_date,
|
||||
r.status,
|
||||
r.effectiveness_check,
|
||||
r.created_at,
|
||||
r.updated_at
|
||||
FROM nonconformity_registries r
|
||||
WHERE %s AND r.organization_id = @organization_id AND r.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"nonconformity_registry_entity_type": NonconformityRegistryEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert data snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type NonconformityRegistryOrderField string
|
||||
|
||||
const (
|
||||
NonconformityRegistryOrderFieldCreatedAt NonconformityRegistryOrderField = "CREATED_AT"
|
||||
NonconformityRegistryOrderFieldDateIdentified NonconformityRegistryOrderField = "DATE_IDENTIFIED"
|
||||
NonconformityRegistryOrderFieldDueDate NonconformityRegistryOrderField = "DUE_DATE"
|
||||
NonconformityRegistryOrderFieldStatus NonconformityRegistryOrderField = "STATUS"
|
||||
NonconformityRegistryOrderFieldReferenceId NonconformityRegistryOrderField = "REFERENCE_ID"
|
||||
)
|
||||
|
||||
func (p NonconformityRegistryOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p NonconformityRegistryOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p NonconformityRegistryOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *NonconformityRegistryOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(NonconformityRegistryOrderFieldCreatedAt),
|
||||
string(NonconformityRegistryOrderFieldDateIdentified),
|
||||
string(NonconformityRegistryOrderFieldDueDate),
|
||||
string(NonconformityRegistryOrderFieldStatus),
|
||||
string(NonconformityRegistryOrderFieldReferenceId):
|
||||
*p = NonconformityRegistryOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid NonconformityRegistryOrderField value: %q", val)
|
||||
}
|
||||
@@ -19,19 +19,19 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ComplianceRegistryStatus string
|
||||
type NonconformityStatus string
|
||||
|
||||
const (
|
||||
ComplianceRegistryStatusOpen ComplianceRegistryStatus = "OPEN"
|
||||
ComplianceRegistryStatusInProgress ComplianceRegistryStatus = "IN_PROGRESS"
|
||||
ComplianceRegistryStatusClosed ComplianceRegistryStatus = "CLOSED"
|
||||
NonconformityStatusOpen NonconformityStatus = "OPEN"
|
||||
NonconformityStatusInProgress NonconformityStatus = "IN_PROGRESS"
|
||||
NonconformityStatusClosed NonconformityStatus = "CLOSED"
|
||||
)
|
||||
|
||||
func (crs ComplianceRegistryStatus) String() string {
|
||||
return string(crs)
|
||||
func (ncs NonconformityStatus) String() string {
|
||||
return string(ncs)
|
||||
}
|
||||
|
||||
func (crs *ComplianceRegistryStatus) Scan(value any) error {
|
||||
func (ncs *NonconformityStatus) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -39,22 +39,22 @@ func (crs *ComplianceRegistryStatus) Scan(value any) error {
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ComplianceRegistryStatus: %T", value)
|
||||
return fmt.Errorf("unsupported type for NonconformityStatus: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "OPEN":
|
||||
*crs = ComplianceRegistryStatusOpen
|
||||
*ncs = NonconformityStatusOpen
|
||||
case "IN_PROGRESS":
|
||||
*crs = ComplianceRegistryStatusInProgress
|
||||
*ncs = NonconformityStatusInProgress
|
||||
case "CLOSED":
|
||||
*crs = ComplianceRegistryStatusClosed
|
||||
*ncs = NonconformityStatusClosed
|
||||
default:
|
||||
return fmt.Errorf("invalid ComplianceRegistryStatus value: %q", s)
|
||||
return fmt.Errorf("invalid NonconformityStatus value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (crs ComplianceRegistryStatus) Value() (driver.Value, error) {
|
||||
return crs.String(), nil
|
||||
func (ncs NonconformityStatus) Value() (driver.Value, error) {
|
||||
return ncs.String(), nil
|
||||
}
|
||||
421
pkg/coredata/obligation.go
Normal file
421
pkg/coredata/obligation.go
Normal file
@@ -0,0 +1,421 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"time"
|
||||
|
||||
"github.com/getprobo/probo/pkg/gid"
|
||||
"github.com/getprobo/probo/pkg/page"
|
||||
"github.com/jackc/pgx/v5"
|
||||
"go.gearno.de/kit/pg"
|
||||
)
|
||||
|
||||
type (
|
||||
Obligation struct {
|
||||
ID gid.GID `db:"id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
ReferenceID string `db:"reference_id"`
|
||||
Area *string `db:"area"`
|
||||
Source *string `db:"source"`
|
||||
Requirement *string `db:"requirement"`
|
||||
ActionsToBeImplemented *string `db:"actions_to_be_implemented"`
|
||||
Regulator *string `db:"regulator"`
|
||||
OwnerID gid.GID `db:"owner_id"`
|
||||
LastReviewDate *time.Time `db:"last_review_date"`
|
||||
DueDate *time.Time `db:"due_date"`
|
||||
Status ObligationStatus `db:"status"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
Obligations []*Obligation
|
||||
)
|
||||
|
||||
func (o *Obligation) CursorKey(field ObligationOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case ObligationOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(o.ID, o.CreatedAt)
|
||||
case ObligationOrderFieldLastReviewDate:
|
||||
return page.NewCursorKey(o.ID, o.LastReviewDate)
|
||||
case ObligationOrderFieldDueDate:
|
||||
return page.NewCursorKey(o.ID, o.DueDate)
|
||||
case ObligationOrderFieldStatus:
|
||||
return page.NewCursorKey(o.ID, o.Status)
|
||||
case ObligationOrderFieldReferenceId:
|
||||
return page.NewCursorKey(o.ID, o.ReferenceID)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (o *Obligation) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
obligationID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
obligations
|
||||
WHERE
|
||||
%s
|
||||
AND id = @obligation_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"obligation_id": obligationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query obligation: %w", err)
|
||||
}
|
||||
|
||||
obligation, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[Obligation])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect obligation: %w", err)
|
||||
}
|
||||
|
||||
*o = obligation
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (os *Obligations) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *ObligationFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
obligations
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
|
||||
row := conn.QueryRow(ctx, q, args)
|
||||
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count obligations: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (os *Obligations) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[ObligationOrderField],
|
||||
filter *ObligationFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
obligations
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
AND %s
|
||||
AND %s
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment(), filter.SQLFragment(), cursor.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"organization_id": organizationID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
maps.Copy(args, filter.SQLArguments())
|
||||
maps.Copy(args, cursor.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query obligations: %w", err)
|
||||
}
|
||||
|
||||
obligations, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[Obligation])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect obligations: %w", err)
|
||||
}
|
||||
|
||||
*os = obligations
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Obligation) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO obligations (
|
||||
id,
|
||||
tenant_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
created_at,
|
||||
updated_at
|
||||
) VALUES (
|
||||
@id,
|
||||
@tenant_id,
|
||||
@organization_id,
|
||||
@reference_id,
|
||||
@area,
|
||||
@source,
|
||||
@requirement,
|
||||
@actions_to_be_implemented,
|
||||
@regulator,
|
||||
@owner_id,
|
||||
@last_review_date,
|
||||
@due_date,
|
||||
@status,
|
||||
@snapshot_id,
|
||||
@source_id,
|
||||
@created_at,
|
||||
@updated_at
|
||||
)
|
||||
`
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": o.ID,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"organization_id": o.OrganizationID,
|
||||
"reference_id": o.ReferenceID,
|
||||
"area": o.Area,
|
||||
"source": o.Source,
|
||||
"requirement": o.Requirement,
|
||||
"actions_to_be_implemented": o.ActionsToBeImplemented,
|
||||
"regulator": o.Regulator,
|
||||
"owner_id": o.OwnerID,
|
||||
"last_review_date": o.LastReviewDate,
|
||||
"due_date": o.DueDate,
|
||||
"status": o.Status,
|
||||
"snapshot_id": o.SnapshotID,
|
||||
"source_id": o.SourceID,
|
||||
"created_at": o.CreatedAt,
|
||||
"updated_at": o.UpdatedAt,
|
||||
}
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert obligation: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Obligation) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE obligations SET
|
||||
reference_id = @reference_id,
|
||||
area = @area,
|
||||
source = @source,
|
||||
requirement = @requirement,
|
||||
actions_to_be_implemented = @actions_to_be_implemented,
|
||||
regulator = @regulator,
|
||||
owner_id = @owner_id,
|
||||
last_review_date = @last_review_date,
|
||||
due_date = @due_date,
|
||||
status = @status,
|
||||
updated_at = @updated_at
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"id": o.ID,
|
||||
"reference_id": o.ReferenceID,
|
||||
"area": o.Area,
|
||||
"source": o.Source,
|
||||
"requirement": o.Requirement,
|
||||
"actions_to_be_implemented": o.ActionsToBeImplemented,
|
||||
"regulator": o.Regulator,
|
||||
"owner_id": o.OwnerID,
|
||||
"last_review_date": o.LastReviewDate,
|
||||
"due_date": o.DueDate,
|
||||
"status": o.Status,
|
||||
"updated_at": o.UpdatedAt,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update obligation: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *Obligation) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM obligations
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
AND snapshot_id IS NULL
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"id": o.ID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete obligation: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (os Obligations) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO obligations (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
source_id,
|
||||
organization_id,
|
||||
reference_id,
|
||||
area,
|
||||
source,
|
||||
requirement,
|
||||
actions_to_be_implemented,
|
||||
regulator,
|
||||
owner_id,
|
||||
last_review_date,
|
||||
due_date,
|
||||
status,
|
||||
created_at,
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @obligation_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
o.id,
|
||||
o.organization_id,
|
||||
o.reference_id,
|
||||
o.area,
|
||||
o.source,
|
||||
o.requirement,
|
||||
o.actions_to_be_implemented,
|
||||
o.regulator,
|
||||
o.owner_id,
|
||||
o.last_review_date,
|
||||
o.due_date,
|
||||
o.status,
|
||||
o.created_at,
|
||||
o.updated_at
|
||||
FROM obligations o
|
||||
WHERE %s AND o.organization_id = @organization_id AND o.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"obligation_entity_type": ObligationEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert obligation snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -20,18 +20,18 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
ContinualImprovementRegistryFilter struct {
|
||||
ObligationFilter struct {
|
||||
snapshotID **gid.GID
|
||||
}
|
||||
)
|
||||
|
||||
func NewContinualImprovementRegistryFilter(snapshotID **gid.GID) *ContinualImprovementRegistryFilter {
|
||||
return &ContinualImprovementRegistryFilter{
|
||||
func NewObligationFilter(snapshotID **gid.GID) *ObligationFilter {
|
||||
return &ObligationFilter{
|
||||
snapshotID: snapshotID,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ContinualImprovementRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
func (f *ObligationFilter) SQLArguments() pgx.NamedArgs {
|
||||
args := pgx.NamedArgs{}
|
||||
|
||||
if f.snapshotID != nil && *f.snapshotID != nil {
|
||||
@@ -41,7 +41,7 @@ func (f *ContinualImprovementRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
return args
|
||||
}
|
||||
|
||||
func (f *ContinualImprovementRegistryFilter) SQLFragment() string {
|
||||
func (f *ObligationFilter) SQLFragment() string {
|
||||
if f.snapshotID == nil {
|
||||
return "TRUE"
|
||||
}
|
||||
55
pkg/coredata/obligation_order_field.go
Normal file
55
pkg/coredata/obligation_order_field.go
Normal file
@@ -0,0 +1,55 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ObligationOrderField string
|
||||
|
||||
const (
|
||||
ObligationOrderFieldCreatedAt ObligationOrderField = "CREATED_AT"
|
||||
ObligationOrderFieldLastReviewDate ObligationOrderField = "LAST_REVIEW_DATE"
|
||||
ObligationOrderFieldDueDate ObligationOrderField = "DUE_DATE"
|
||||
ObligationOrderFieldStatus ObligationOrderField = "STATUS"
|
||||
ObligationOrderFieldReferenceId ObligationOrderField = "REFERENCE_ID"
|
||||
)
|
||||
|
||||
func (p ObligationOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ObligationOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ObligationOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *ObligationOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(ObligationOrderFieldCreatedAt),
|
||||
string(ObligationOrderFieldLastReviewDate),
|
||||
string(ObligationOrderFieldDueDate),
|
||||
string(ObligationOrderFieldStatus),
|
||||
string(ObligationOrderFieldReferenceId):
|
||||
*p = ObligationOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid ObligationOrderField value: %q", val)
|
||||
}
|
||||
@@ -19,19 +19,19 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ContinualImprovementRegistriesStatus string
|
||||
type ObligationStatus string
|
||||
|
||||
const (
|
||||
ContinualImprovementRegistriesStatusOpen ContinualImprovementRegistriesStatus = "OPEN"
|
||||
ContinualImprovementRegistriesStatusInProgress ContinualImprovementRegistriesStatus = "IN_PROGRESS"
|
||||
ContinualImprovementRegistriesStatusClosed ContinualImprovementRegistriesStatus = "CLOSED"
|
||||
ObligationStatusOpen ObligationStatus = "OPEN"
|
||||
ObligationStatusInProgress ObligationStatus = "IN_PROGRESS"
|
||||
ObligationStatusClosed ObligationStatus = "CLOSED"
|
||||
)
|
||||
|
||||
func (cirs ContinualImprovementRegistriesStatus) String() string {
|
||||
return string(cirs)
|
||||
func (os ObligationStatus) String() string {
|
||||
return string(os)
|
||||
}
|
||||
|
||||
func (cirs *ContinualImprovementRegistriesStatus) Scan(value any) error {
|
||||
func (os *ObligationStatus) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -39,22 +39,22 @@ func (cirs *ContinualImprovementRegistriesStatus) Scan(value any) error {
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ContinualImprovementRegistriesStatus: %T", value)
|
||||
return fmt.Errorf("unsupported type for ObligationStatus: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "OPEN":
|
||||
*cirs = ContinualImprovementRegistriesStatusOpen
|
||||
*os = ObligationStatusOpen
|
||||
case "IN_PROGRESS":
|
||||
*cirs = ContinualImprovementRegistriesStatusInProgress
|
||||
*os = ObligationStatusInProgress
|
||||
case "CLOSED":
|
||||
*cirs = ContinualImprovementRegistriesStatusClosed
|
||||
*os = ObligationStatusClosed
|
||||
default:
|
||||
return fmt.Errorf("invalid ContinualImprovementRegistriesStatus value: %q", s)
|
||||
return fmt.Errorf("invalid ObligationStatus value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (cirs ContinualImprovementRegistriesStatus) Value() (driver.Value, error) {
|
||||
return cirs.String(), nil
|
||||
func (os ObligationStatus) Value() (driver.Value, error) {
|
||||
return os.String(), nil
|
||||
}
|
||||
@@ -27,49 +27,49 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
ProcessingActivityRegistry struct {
|
||||
ID gid.GID `db:"id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Name string `db:"name"`
|
||||
Purpose *string `db:"purpose"`
|
||||
DataSubjectCategory *string `db:"data_subject_category"`
|
||||
PersonalDataCategory *string `db:"personal_data_category"`
|
||||
SpecialOrCriminalData ProcessingActivityRegistrySpecialOrCriminalData `db:"special_or_criminal_data"`
|
||||
ConsentEvidenceLink *string `db:"consent_evidence_link"`
|
||||
LawfulBasis ProcessingActivityRegistryLawfulBasis `db:"lawful_basis"`
|
||||
Recipients *string `db:"recipients"`
|
||||
Location *string `db:"location"`
|
||||
InternationalTransfers bool `db:"international_transfers"`
|
||||
TransferSafeguards *ProcessingActivityRegistryTransferSafeguards `db:"transfer_safeguards"`
|
||||
RetentionPeriod *string `db:"retention_period"`
|
||||
SecurityMeasures *string `db:"security_measures"`
|
||||
DataProtectionImpactAssessment ProcessingActivityRegistryDataProtectionImpactAssessment `db:"data_protection_impact_assessment"`
|
||||
TransferImpactAssessment ProcessingActivityRegistryTransferImpactAssessment `db:"transfer_impact_assessment"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
ProcessingActivity struct {
|
||||
ID gid.GID `db:"id"`
|
||||
SnapshotID *gid.GID `db:"snapshot_id"`
|
||||
SourceID *gid.GID `db:"source_id"`
|
||||
OrganizationID gid.GID `db:"organization_id"`
|
||||
Name string `db:"name"`
|
||||
Purpose *string `db:"purpose"`
|
||||
DataSubjectCategory *string `db:"data_subject_category"`
|
||||
PersonalDataCategory *string `db:"personal_data_category"`
|
||||
SpecialOrCriminalData ProcessingActivitySpecialOrCriminalData `db:"special_or_criminal_data"`
|
||||
ConsentEvidenceLink *string `db:"consent_evidence_link"`
|
||||
LawfulBasis ProcessingActivityLawfulBasis `db:"lawful_basis"`
|
||||
Recipients *string `db:"recipients"`
|
||||
Location *string `db:"location"`
|
||||
InternationalTransfers bool `db:"international_transfers"`
|
||||
TransferSafeguards *ProcessingActivityTransferSafeguards `db:"transfer_safeguards"`
|
||||
RetentionPeriod *string `db:"retention_period"`
|
||||
SecurityMeasures *string `db:"security_measures"`
|
||||
DataProtectionImpactAssessment ProcessingActivityDataProtectionImpactAssessment `db:"data_protection_impact_assessment"`
|
||||
TransferImpactAssessment ProcessingActivityTransferImpactAssessment `db:"transfer_impact_assessment"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
UpdatedAt time.Time `db:"updated_at"`
|
||||
}
|
||||
|
||||
ProcessingActivityRegistries []*ProcessingActivityRegistry
|
||||
ProcessingActivities []*ProcessingActivity
|
||||
)
|
||||
|
||||
func (p *ProcessingActivityRegistry) CursorKey(field ProcessingActivityRegistryOrderField) page.CursorKey {
|
||||
func (p *ProcessingActivity) CursorKey(field ProcessingActivityOrderField) page.CursorKey {
|
||||
switch field {
|
||||
case ProcessingActivityRegistryOrderFieldCreatedAt:
|
||||
case ProcessingActivityOrderFieldCreatedAt:
|
||||
return page.NewCursorKey(p.ID, p.CreatedAt)
|
||||
case ProcessingActivityRegistryOrderFieldName:
|
||||
case ProcessingActivityOrderFieldName:
|
||||
return page.NewCursorKey(p.ID, p.Name)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("unsupported order by: %s", field))
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistry) LoadByID(
|
||||
func (p *ProcessingActivity) LoadByID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
processingActivityRegistryID gid.GID,
|
||||
processingActivityID gid.GID,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
@@ -95,45 +95,45 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
processing_activity_registries
|
||||
processing_activities
|
||||
WHERE
|
||||
%s
|
||||
AND id = @processing_activity_registry_id
|
||||
AND id = @processing_activity_id
|
||||
LIMIT 1;
|
||||
`
|
||||
|
||||
q = fmt.Sprintf(q, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{"processing_activity_registry_id": processingActivityRegistryID}
|
||||
args := pgx.StrictNamedArgs{"processing_activity_id": processingActivityID}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query processing activity registry: %w", err)
|
||||
return fmt.Errorf("cannot query processing activity: %w", err)
|
||||
}
|
||||
|
||||
processingActivityRegistry, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ProcessingActivityRegistry])
|
||||
processingActivity, err := pgx.CollectExactlyOneRow(rows, pgx.RowToStructByName[ProcessingActivity])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect processing activity registry: %w", err)
|
||||
return fmt.Errorf("cannot collect processing activity: %w", err)
|
||||
}
|
||||
|
||||
*p = processingActivityRegistry
|
||||
*p = processingActivity
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistries) CountByOrganizationID(
|
||||
func (p *ProcessingActivities) CountByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
filter *ProcessingActivityRegistryFilter,
|
||||
filter *ProcessingActivityFilter,
|
||||
) (int, error) {
|
||||
q := `
|
||||
SELECT
|
||||
COUNT(id)
|
||||
FROM
|
||||
processing_activity_registries
|
||||
processing_activities
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
@@ -151,19 +151,19 @@ WHERE
|
||||
var count int
|
||||
err := row.Scan(&count)
|
||||
if err != nil {
|
||||
return 0, fmt.Errorf("cannot count processing activity registries: %w", err)
|
||||
return 0, fmt.Errorf("cannot count processing activities: %w", err)
|
||||
}
|
||||
|
||||
return count, nil
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistries) LoadByOrganizationID(
|
||||
func (p *ProcessingActivities) LoadByOrganizationID(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
organizationID gid.GID,
|
||||
cursor *page.Cursor[ProcessingActivityRegistryOrderField],
|
||||
filter *ProcessingActivityRegistryFilter,
|
||||
cursor *page.Cursor[ProcessingActivityOrderField],
|
||||
filter *ProcessingActivityFilter,
|
||||
) error {
|
||||
q := `
|
||||
SELECT
|
||||
@@ -189,7 +189,7 @@ SELECT
|
||||
created_at,
|
||||
updated_at
|
||||
FROM
|
||||
processing_activity_registries
|
||||
processing_activities
|
||||
WHERE
|
||||
%s
|
||||
AND organization_id = @organization_id
|
||||
@@ -206,26 +206,26 @@ WHERE
|
||||
|
||||
rows, err := conn.Query(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot query processing activity registries: %w", err)
|
||||
return fmt.Errorf("cannot query processing activities: %w", err)
|
||||
}
|
||||
|
||||
processingActivityRegistries, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ProcessingActivityRegistry])
|
||||
processingActivities, err := pgx.CollectRows(rows, pgx.RowToAddrOfStructByName[ProcessingActivity])
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot collect processing activity registries: %w", err)
|
||||
return fmt.Errorf("cannot collect processing activities: %w", err)
|
||||
}
|
||||
|
||||
*p = processingActivityRegistries
|
||||
*p = processingActivities
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistry) Insert(
|
||||
func (p *ProcessingActivity) Insert(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
INSERT INTO processing_activity_registries (
|
||||
INSERT INTO processing_activities (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
@@ -301,19 +301,19 @@ INSERT INTO processing_activity_registries (
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert processing activity registry: %w", err)
|
||||
return fmt.Errorf("cannot insert processing activity: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistry) Update(
|
||||
func (p *ProcessingActivity) Update(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
UPDATE processing_activity_registries
|
||||
UPDATE processing_activities
|
||||
SET
|
||||
name = @name,
|
||||
purpose = @purpose,
|
||||
@@ -362,19 +362,19 @@ WHERE
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot update processing activity registry: %w", err)
|
||||
return fmt.Errorf("cannot update processing activity: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistry) Delete(
|
||||
func (p *ProcessingActivity) Delete(
|
||||
ctx context.Context,
|
||||
conn pg.Conn,
|
||||
scope Scoper,
|
||||
) error {
|
||||
q := `
|
||||
DELETE FROM processing_activity_registries
|
||||
DELETE FROM processing_activities
|
||||
WHERE
|
||||
%s
|
||||
AND id = @id
|
||||
@@ -388,15 +388,15 @@ WHERE
|
||||
|
||||
_, err := conn.Exec(ctx, q, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot delete processing activity registry: %w", err)
|
||||
return fmt.Errorf("cannot delete processing activity: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (pars ProcessingActivityRegistries) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
func (pas ProcessingActivities) Snapshot(ctx context.Context, conn pg.Conn, scope Scoper, organizationID, snapshotID gid.GID) error {
|
||||
query := `
|
||||
INSERT INTO processing_activity_registries (
|
||||
INSERT INTO processing_activities (
|
||||
id,
|
||||
tenant_id,
|
||||
snapshot_id,
|
||||
@@ -421,7 +421,7 @@ INSERT INTO processing_activity_registries (
|
||||
updated_at
|
||||
)
|
||||
SELECT
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @processing_activity_registry_entity_type),
|
||||
generate_gid(decode_base64_unpadded(@tenant_id), @processing_activity_entity_type),
|
||||
@tenant_id,
|
||||
@snapshot_id,
|
||||
par.id,
|
||||
@@ -443,23 +443,23 @@ SELECT
|
||||
par.transfer_impact_assessment,
|
||||
par.created_at,
|
||||
par.updated_at
|
||||
FROM processing_activity_registries par
|
||||
FROM processing_activities par
|
||||
WHERE %s AND par.organization_id = @organization_id AND par.snapshot_id IS NULL
|
||||
`
|
||||
|
||||
query = fmt.Sprintf(query, scope.SQLFragment())
|
||||
|
||||
args := pgx.StrictNamedArgs{
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"processing_activity_registry_entity_type": ProcessingActivityRegistryEntityType,
|
||||
"tenant_id": scope.GetTenantID(),
|
||||
"snapshot_id": snapshotID,
|
||||
"organization_id": organizationID,
|
||||
"processing_activity_entity_type": ProcessingActivityEntityType,
|
||||
}
|
||||
maps.Copy(args, scope.SQLArguments())
|
||||
|
||||
_, err := conn.Exec(ctx, query, args)
|
||||
if err != nil {
|
||||
return fmt.Errorf("cannot insert processing activity registry snapshots: %w", err)
|
||||
return fmt.Errorf("cannot insert processing activity snapshots: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -19,18 +19,18 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityRegistryTransferImpactAssessment string
|
||||
type ProcessingActivityDataProtectionImpactAssessment string
|
||||
|
||||
const (
|
||||
ProcessingActivityRegistryTransferImpactAssessmentNeeded ProcessingActivityRegistryTransferImpactAssessment = "NEEDED"
|
||||
ProcessingActivityRegistryTransferImpactAssessmentNotNeeded ProcessingActivityRegistryTransferImpactAssessment = "NOT_NEEDED"
|
||||
ProcessingActivityDataProtectionImpactAssessmentNeeded ProcessingActivityDataProtectionImpactAssessment = "NEEDED"
|
||||
ProcessingActivityDataProtectionImpactAssessmentNotNeeded ProcessingActivityDataProtectionImpactAssessment = "NOT_NEEDED"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityRegistryTransferImpactAssessment) String() string {
|
||||
func (p ProcessingActivityDataProtectionImpactAssessment) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistryTransferImpactAssessment) Scan(value any) error {
|
||||
func (p *ProcessingActivityDataProtectionImpactAssessment) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -38,20 +38,20 @@ func (p *ProcessingActivityRegistryTransferImpactAssessment) Scan(value any) err
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityRegistryTransferImpactAssessment: %T", value)
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityDataProtectionImpactAssessment: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "NEEDED":
|
||||
*p = ProcessingActivityRegistryTransferImpactAssessmentNeeded
|
||||
*p = ProcessingActivityDataProtectionImpactAssessmentNeeded
|
||||
case "NOT_NEEDED":
|
||||
*p = ProcessingActivityRegistryTransferImpactAssessmentNotNeeded
|
||||
*p = ProcessingActivityDataProtectionImpactAssessmentNotNeeded
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityRegistryTransferImpactAssessment value: %q", s)
|
||||
return fmt.Errorf("invalid ProcessingActivityDataProtectionImpactAssessment value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistryTransferImpactAssessment) Value() (driver.Value, error) {
|
||||
func (p ProcessingActivityDataProtectionImpactAssessment) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
@@ -20,18 +20,18 @@ import (
|
||||
)
|
||||
|
||||
type (
|
||||
ComplianceRegistryFilter struct {
|
||||
ProcessingActivityFilter struct {
|
||||
snapshotID **gid.GID
|
||||
}
|
||||
)
|
||||
|
||||
func NewComplianceRegistryFilter(snapshotID **gid.GID) *ComplianceRegistryFilter {
|
||||
return &ComplianceRegistryFilter{
|
||||
func NewProcessingActivityFilter(snapshotID **gid.GID) *ProcessingActivityFilter {
|
||||
return &ProcessingActivityFilter{
|
||||
snapshotID: snapshotID,
|
||||
}
|
||||
}
|
||||
|
||||
func (f *ComplianceRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
func (f *ProcessingActivityFilter) SQLArguments() pgx.NamedArgs {
|
||||
args := pgx.NamedArgs{}
|
||||
|
||||
if f.snapshotID != nil && *f.snapshotID != nil {
|
||||
@@ -41,7 +41,7 @@ func (f *ComplianceRegistryFilter) SQLArguments() pgx.NamedArgs {
|
||||
return args
|
||||
}
|
||||
|
||||
func (f *ComplianceRegistryFilter) SQLFragment() string {
|
||||
func (f *ProcessingActivityFilter) SQLFragment() string {
|
||||
if f.snapshotID == nil {
|
||||
return "TRUE"
|
||||
}
|
||||
69
pkg/coredata/processing_activity_lawful_basis.go
Normal file
69
pkg/coredata/processing_activity_lawful_basis.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityLawfulBasis string
|
||||
|
||||
const (
|
||||
ProcessingActivityLawfulBasisLegitimateInterest ProcessingActivityLawfulBasis = "LEGITIMATE_INTEREST"
|
||||
ProcessingActivityLawfulBasisConsent ProcessingActivityLawfulBasis = "CONSENT"
|
||||
ProcessingActivityLawfulBasisContractualNecessity ProcessingActivityLawfulBasis = "CONTRACTUAL_NECESSITY"
|
||||
ProcessingActivityLawfulBasisLegalObligation ProcessingActivityLawfulBasis = "LEGAL_OBLIGATION"
|
||||
ProcessingActivityLawfulBasisVitalInterests ProcessingActivityLawfulBasis = "VITAL_INTERESTS"
|
||||
ProcessingActivityLawfulBasisPublicTask ProcessingActivityLawfulBasis = "PUBLIC_TASK"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityLawfulBasis) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityLawfulBasis) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
s = v
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityLawfulBasis: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "LEGITIMATE_INTEREST":
|
||||
*p = ProcessingActivityLawfulBasisLegitimateInterest
|
||||
case "CONSENT":
|
||||
*p = ProcessingActivityLawfulBasisConsent
|
||||
case "CONTRACTUAL_NECESSITY":
|
||||
*p = ProcessingActivityLawfulBasisContractualNecessity
|
||||
case "LEGAL_OBLIGATION":
|
||||
*p = ProcessingActivityLawfulBasisLegalObligation
|
||||
case "VITAL_INTERESTS":
|
||||
*p = ProcessingActivityLawfulBasisVitalInterests
|
||||
case "PUBLIC_TASK":
|
||||
*p = ProcessingActivityLawfulBasisPublicTask
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityLawfulBasis value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityLawfulBasis) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
@@ -18,32 +18,32 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityRegistryOrderField string
|
||||
type ProcessingActivityOrderField string
|
||||
|
||||
const (
|
||||
ProcessingActivityRegistryOrderFieldCreatedAt ProcessingActivityRegistryOrderField = "CREATED_AT"
|
||||
ProcessingActivityRegistryOrderFieldName ProcessingActivityRegistryOrderField = "NAME"
|
||||
ProcessingActivityOrderFieldCreatedAt ProcessingActivityOrderField = "CREATED_AT"
|
||||
ProcessingActivityOrderFieldName ProcessingActivityOrderField = "NAME"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityRegistryOrderField) Column() string {
|
||||
func (p ProcessingActivityOrderField) Column() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistryOrderField) String() string {
|
||||
func (p ProcessingActivityOrderField) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistryOrderField) MarshalText() ([]byte, error) {
|
||||
func (p ProcessingActivityOrderField) MarshalText() ([]byte, error) {
|
||||
return []byte(p.String()), nil
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistryOrderField) UnmarshalText(text []byte) error {
|
||||
func (p *ProcessingActivityOrderField) UnmarshalText(text []byte) error {
|
||||
val := string(text)
|
||||
switch val {
|
||||
case string(ProcessingActivityRegistryOrderFieldCreatedAt),
|
||||
string(ProcessingActivityRegistryOrderFieldName):
|
||||
*p = ProcessingActivityRegistryOrderField(val)
|
||||
case string(ProcessingActivityOrderFieldCreatedAt),
|
||||
string(ProcessingActivityOrderFieldName):
|
||||
*p = ProcessingActivityOrderField(val)
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("invalid ProcessingActivityRegistryOrderField value: %q", val)
|
||||
return fmt.Errorf("invalid ProcessingActivityOrderField value: %q", val)
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityRegistryLawfulBasis string
|
||||
|
||||
const (
|
||||
ProcessingActivityRegistryLawfulBasisLegitimateInterest ProcessingActivityRegistryLawfulBasis = "LEGITIMATE_INTEREST"
|
||||
ProcessingActivityRegistryLawfulBasisConsent ProcessingActivityRegistryLawfulBasis = "CONSENT"
|
||||
ProcessingActivityRegistryLawfulBasisContractualNecessity ProcessingActivityRegistryLawfulBasis = "CONTRACTUAL_NECESSITY"
|
||||
ProcessingActivityRegistryLawfulBasisLegalObligation ProcessingActivityRegistryLawfulBasis = "LEGAL_OBLIGATION"
|
||||
ProcessingActivityRegistryLawfulBasisVitalInterests ProcessingActivityRegistryLawfulBasis = "VITAL_INTERESTS"
|
||||
ProcessingActivityRegistryLawfulBasisPublicTask ProcessingActivityRegistryLawfulBasis = "PUBLIC_TASK"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityRegistryLawfulBasis) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistryLawfulBasis) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
s = v
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityRegistryLawfulBasis: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "LEGITIMATE_INTEREST":
|
||||
*p = ProcessingActivityRegistryLawfulBasisLegitimateInterest
|
||||
case "CONSENT":
|
||||
*p = ProcessingActivityRegistryLawfulBasisConsent
|
||||
case "CONTRACTUAL_NECESSITY":
|
||||
*p = ProcessingActivityRegistryLawfulBasisContractualNecessity
|
||||
case "LEGAL_OBLIGATION":
|
||||
*p = ProcessingActivityRegistryLawfulBasisLegalObligation
|
||||
case "VITAL_INTERESTS":
|
||||
*p = ProcessingActivityRegistryLawfulBasisVitalInterests
|
||||
case "PUBLIC_TASK":
|
||||
*p = ProcessingActivityRegistryLawfulBasisPublicTask
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityRegistryLawfulBasis value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistryLawfulBasis) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityRegistryTransferSafeguards string
|
||||
|
||||
const (
|
||||
ProcessingActivityRegistryTransferSafeguardsStandardContractualClauses ProcessingActivityRegistryTransferSafeguards = "STANDARD_CONTRACTUAL_CLAUSES"
|
||||
ProcessingActivityRegistryTransferSafeguardsBindingCorporateRules ProcessingActivityRegistryTransferSafeguards = "BINDING_CORPORATE_RULES"
|
||||
ProcessingActivityRegistryTransferSafeguardsAdequacyDecision ProcessingActivityRegistryTransferSafeguards = "ADEQUACY_DECISION"
|
||||
ProcessingActivityRegistryTransferSafeguardsDerogations ProcessingActivityRegistryTransferSafeguards = "DEROGATIONS"
|
||||
ProcessingActivityRegistryTransferSafeguardsCodesOfConduct ProcessingActivityRegistryTransferSafeguards = "CODES_OF_CONDUCT"
|
||||
ProcessingActivityRegistryTransferSafeguardsCertificationMechanisms ProcessingActivityRegistryTransferSafeguards = "CERTIFICATION_MECHANISMS"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityRegistryTransferSafeguards) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistryTransferSafeguards) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
s = v
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityRegistryTransferSafeguards: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "STANDARD_CONTRACTUAL_CLAUSES":
|
||||
*p = ProcessingActivityRegistryTransferSafeguardsStandardContractualClauses
|
||||
case "BINDING_CORPORATE_RULES":
|
||||
*p = ProcessingActivityRegistryTransferSafeguardsBindingCorporateRules
|
||||
case "ADEQUACY_DECISION":
|
||||
*p = ProcessingActivityRegistryTransferSafeguardsAdequacyDecision
|
||||
case "DEROGATIONS":
|
||||
*p = ProcessingActivityRegistryTransferSafeguardsDerogations
|
||||
case "CODES_OF_CONDUCT":
|
||||
*p = ProcessingActivityRegistryTransferSafeguardsCodesOfConduct
|
||||
case "CERTIFICATION_MECHANISMS":
|
||||
*p = ProcessingActivityRegistryTransferSafeguardsCertificationMechanisms
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityRegistryTransferSafeguards value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistryTransferSafeguards) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
@@ -19,19 +19,19 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityRegistrySpecialOrCriminalData string
|
||||
type ProcessingActivitySpecialOrCriminalData string
|
||||
|
||||
const (
|
||||
ProcessingActivityRegistrySpecialOrCriminalDataYes ProcessingActivityRegistrySpecialOrCriminalData = "YES"
|
||||
ProcessingActivityRegistrySpecialOrCriminalDataNo ProcessingActivityRegistrySpecialOrCriminalData = "NO"
|
||||
ProcessingActivityRegistrySpecialOrCriminalDataPossible ProcessingActivityRegistrySpecialOrCriminalData = "POSSIBLE"
|
||||
ProcessingActivitySpecialOrCriminalDataYes ProcessingActivitySpecialOrCriminalData = "YES"
|
||||
ProcessingActivitySpecialOrCriminalDataNo ProcessingActivitySpecialOrCriminalData = "NO"
|
||||
ProcessingActivitySpecialOrCriminalDataPossible ProcessingActivitySpecialOrCriminalData = "POSSIBLE"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityRegistrySpecialOrCriminalData) String() string {
|
||||
func (p ProcessingActivitySpecialOrCriminalData) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistrySpecialOrCriminalData) Scan(value any) error {
|
||||
func (p *ProcessingActivitySpecialOrCriminalData) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -39,22 +39,22 @@ func (p *ProcessingActivityRegistrySpecialOrCriminalData) Scan(value any) error
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityRegistrySpecialOrCriminalData: %T", value)
|
||||
return fmt.Errorf("unsupported type for ProcessingActivitySpecialOrCriminalData: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "YES":
|
||||
*p = ProcessingActivityRegistrySpecialOrCriminalDataYes
|
||||
*p = ProcessingActivitySpecialOrCriminalDataYes
|
||||
case "NO":
|
||||
*p = ProcessingActivityRegistrySpecialOrCriminalDataNo
|
||||
*p = ProcessingActivitySpecialOrCriminalDataNo
|
||||
case "POSSIBLE":
|
||||
*p = ProcessingActivityRegistrySpecialOrCriminalDataPossible
|
||||
*p = ProcessingActivitySpecialOrCriminalDataPossible
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityRegistrySpecialOrCriminalData value: %q", s)
|
||||
return fmt.Errorf("invalid ProcessingActivitySpecialOrCriminalData value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistrySpecialOrCriminalData) Value() (driver.Value, error) {
|
||||
func (p ProcessingActivitySpecialOrCriminalData) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
@@ -19,18 +19,18 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityRegistryDataProtectionImpactAssessment string
|
||||
type ProcessingActivityTransferImpactAssessment string
|
||||
|
||||
const (
|
||||
ProcessingActivityRegistryDataProtectionImpactAssessmentNeeded ProcessingActivityRegistryDataProtectionImpactAssessment = "NEEDED"
|
||||
ProcessingActivityRegistryDataProtectionImpactAssessmentNotNeeded ProcessingActivityRegistryDataProtectionImpactAssessment = "NOT_NEEDED"
|
||||
ProcessingActivityTransferImpactAssessmentNeeded ProcessingActivityTransferImpactAssessment = "NEEDED"
|
||||
ProcessingActivityTransferImpactAssessmentNotNeeded ProcessingActivityTransferImpactAssessment = "NOT_NEEDED"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityRegistryDataProtectionImpactAssessment) String() string {
|
||||
func (p ProcessingActivityTransferImpactAssessment) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityRegistryDataProtectionImpactAssessment) Scan(value any) error {
|
||||
func (p *ProcessingActivityTransferImpactAssessment) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
@@ -38,20 +38,20 @@ func (p *ProcessingActivityRegistryDataProtectionImpactAssessment) Scan(value an
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityRegistryDataProtectionImpactAssessment: %T", value)
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityTransferImpactAssessment: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "NEEDED":
|
||||
*p = ProcessingActivityRegistryDataProtectionImpactAssessmentNeeded
|
||||
*p = ProcessingActivityTransferImpactAssessmentNeeded
|
||||
case "NOT_NEEDED":
|
||||
*p = ProcessingActivityRegistryDataProtectionImpactAssessmentNotNeeded
|
||||
*p = ProcessingActivityTransferImpactAssessmentNotNeeded
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityRegistryDataProtectionImpactAssessment value: %q", s)
|
||||
return fmt.Errorf("invalid ProcessingActivityTransferImpactAssessment value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityRegistryDataProtectionImpactAssessment) Value() (driver.Value, error) {
|
||||
func (p ProcessingActivityTransferImpactAssessment) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
69
pkg/coredata/processing_activity_transfer_safeguards.go
Normal file
69
pkg/coredata/processing_activity_transfer_safeguards.go
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) 2025 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.
|
||||
|
||||
package coredata
|
||||
|
||||
import (
|
||||
"database/sql/driver"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ProcessingActivityTransferSafeguards string
|
||||
|
||||
const (
|
||||
ProcessingActivityTransferSafeguardsStandardContractualClauses ProcessingActivityTransferSafeguards = "STANDARD_CONTRACTUAL_CLAUSES"
|
||||
ProcessingActivityTransferSafeguardsBindingCorporateRules ProcessingActivityTransferSafeguards = "BINDING_CORPORATE_RULES"
|
||||
ProcessingActivityTransferSafeguardsAdequacyDecision ProcessingActivityTransferSafeguards = "ADEQUACY_DECISION"
|
||||
ProcessingActivityTransferSafeguardsDerogations ProcessingActivityTransferSafeguards = "DEROGATIONS"
|
||||
ProcessingActivityTransferSafeguardsCodesOfConduct ProcessingActivityTransferSafeguards = "CODES_OF_CONDUCT"
|
||||
ProcessingActivityTransferSafeguardsCertificationMechanisms ProcessingActivityTransferSafeguards = "CERTIFICATION_MECHANISMS"
|
||||
)
|
||||
|
||||
func (p ProcessingActivityTransferSafeguards) String() string {
|
||||
return string(p)
|
||||
}
|
||||
|
||||
func (p *ProcessingActivityTransferSafeguards) Scan(value any) error {
|
||||
var s string
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
s = v
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
return fmt.Errorf("unsupported type for ProcessingActivityTransferSafeguards: %T", value)
|
||||
}
|
||||
|
||||
switch s {
|
||||
case "STANDARD_CONTRACTUAL_CLAUSES":
|
||||
*p = ProcessingActivityTransferSafeguardsStandardContractualClauses
|
||||
case "BINDING_CORPORATE_RULES":
|
||||
*p = ProcessingActivityTransferSafeguardsBindingCorporateRules
|
||||
case "ADEQUACY_DECISION":
|
||||
*p = ProcessingActivityTransferSafeguardsAdequacyDecision
|
||||
case "DEROGATIONS":
|
||||
*p = ProcessingActivityTransferSafeguardsDerogations
|
||||
case "CODES_OF_CONDUCT":
|
||||
*p = ProcessingActivityTransferSafeguardsCodesOfConduct
|
||||
case "CERTIFICATION_MECHANISMS":
|
||||
*p = ProcessingActivityTransferSafeguardsCertificationMechanisms
|
||||
default:
|
||||
return fmt.Errorf("invalid ProcessingActivityTransferSafeguards value: %q", s)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ProcessingActivityTransferSafeguards) Value() (driver.Value, error) {
|
||||
return p.String(), nil
|
||||
}
|
||||
@@ -24,14 +24,14 @@ type (
|
||||
)
|
||||
|
||||
const (
|
||||
SnapshotsTypeRisks SnapshotsType = "RISKS"
|
||||
SnapshotsTypeVendors SnapshotsType = "VENDORS"
|
||||
SnapshotsTypeAssets SnapshotsType = "ASSETS"
|
||||
SnapshotsTypeData SnapshotsType = "DATA"
|
||||
SnapshotsTypeNonConformityRegistries SnapshotsType = "NONCONFORMITY_REGISTRIES"
|
||||
SnapshotsTypeComplianceRegistries SnapshotsType = "COMPLIANCE_REGISTRIES"
|
||||
SnapshotsTypeContinualImprovementRegistries SnapshotsType = "CONTINUAL_IMPROVEMENT_REGISTRIES"
|
||||
SnapshotsTypeProcessingActivityRegistries SnapshotsType = "PROCESSING_ACTIVITY_REGISTRIES"
|
||||
SnapshotsTypeRisks SnapshotsType = "RISKS"
|
||||
SnapshotsTypeVendors SnapshotsType = "VENDORS"
|
||||
SnapshotsTypeAssets SnapshotsType = "ASSETS"
|
||||
SnapshotsTypeData SnapshotsType = "DATA"
|
||||
SnapshotsTypeNonconformities SnapshotsType = "NONCONFORMITIES"
|
||||
SnapshotsTypeObligations SnapshotsType = "OBLIGATIONS"
|
||||
SnapshotsTypeContinualImprovements SnapshotsType = "CONTINUAL_IMPROVEMENTS"
|
||||
SnapshotsTypeProcessingActivities SnapshotsType = "PROCESSING_ACTIVITIES"
|
||||
)
|
||||
|
||||
func (st SnapshotsType) String() string {
|
||||
@@ -58,14 +58,14 @@ func (st *SnapshotsType) Scan(value any) error {
|
||||
*st = SnapshotsTypeAssets
|
||||
case SnapshotsTypeData.String():
|
||||
*st = SnapshotsTypeData
|
||||
case SnapshotsTypeNonConformityRegistries.String():
|
||||
*st = SnapshotsTypeNonConformityRegistries
|
||||
case SnapshotsTypeComplianceRegistries.String():
|
||||
*st = SnapshotsTypeComplianceRegistries
|
||||
case SnapshotsTypeContinualImprovementRegistries.String():
|
||||
*st = SnapshotsTypeContinualImprovementRegistries
|
||||
case SnapshotsTypeProcessingActivityRegistries.String():
|
||||
*st = SnapshotsTypeProcessingActivityRegistries
|
||||
case SnapshotsTypeNonconformities.String():
|
||||
*st = SnapshotsTypeNonconformities
|
||||
case SnapshotsTypeObligations.String():
|
||||
*st = SnapshotsTypeObligations
|
||||
case SnapshotsTypeContinualImprovements.String():
|
||||
*st = SnapshotsTypeContinualImprovements
|
||||
case SnapshotsTypeProcessingActivities.String():
|
||||
*st = SnapshotsTypeProcessingActivities
|
||||
default:
|
||||
return fmt.Errorf("invalid SnapshotsType value: %q", s)
|
||||
}
|
||||
|
||||
@@ -34,14 +34,14 @@ func GetSnapshottable(snapshotType SnapshotsType) (Snapshottable, error) {
|
||||
return Risks{}, nil
|
||||
case SnapshotsTypeData:
|
||||
return Data{}, nil
|
||||
case SnapshotsTypeNonConformityRegistries:
|
||||
return NonconformityRegistries{}, nil
|
||||
case SnapshotsTypeComplianceRegistries:
|
||||
return ComplianceRegistries{}, nil
|
||||
case SnapshotsTypeContinualImprovementRegistries:
|
||||
return ContinualImprovementRegistries{}, nil
|
||||
case SnapshotsTypeProcessingActivityRegistries:
|
||||
return ProcessingActivityRegistries{}, nil
|
||||
case SnapshotsTypeNonconformities:
|
||||
return Nonconformities{}, nil
|
||||
case SnapshotsTypeObligations:
|
||||
return Obligations{}, nil
|
||||
case SnapshotsTypeContinualImprovements:
|
||||
return ContinualImprovements{}, nil
|
||||
case SnapshotsTypeProcessingActivities:
|
||||
return ProcessingActivities{}, nil
|
||||
case SnapshotsTypeVendors:
|
||||
return Vendors{}, nil
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user