Fix referenced columns used in certain SQL queries + minor front fixes

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-02-09 10:13:57 +04:00
parent d235f4a86b
commit 29371662e2
14 changed files with 29 additions and 162 deletions

View File

@@ -19,7 +19,7 @@ function UserPageQueryLoader() {
if (!queryRef) { if (!queryRef) {
loadQuery({ userId }); loadQuery({ userId });
} }
}, [loadQuery, queryRef, userId]); });
if (!queryRef) return <LinkCardSkeleton />; if (!queryRef) return <LinkCardSkeleton />;

View File

@@ -80,7 +80,7 @@ export function MemberList(props: { fKey: MemberListFragment$key }) {
{membersPagination.data.members.totalCount === 0 {membersPagination.data.members.totalCount === 0
? ( ? (
<Tr> <Tr>
<Td colSpan={5} className="text-center text-txt-secondary"> <Td colSpan={7} className="text-center text-txt-secondary">
{__("No members")} {__("No members")}
</Td> </Td>
</Tr> </Tr>

View File

@@ -713,14 +713,14 @@ WITH last_signable_version AS (
FROM documents d FROM documents d
INNER JOIN document_versions dv ON dv.document_id = d.id INNER JOIN document_versions dv ON dv.document_id = d.id
INNER JOIN document_version_signatures dvs ON dvs.document_version_id = dv.id INNER JOIN document_version_signatures dvs ON dvs.document_version_id = dv.id
INNER JOIN peoples p ON dvs.signed_by = p.id INNER JOIN iam_membership_profiles p ON dvs.signed_by_profile_id = p.id
WHERE d.id = @document_id WHERE d.id = @document_id
AND p.primary_email_address = @user_email AND p.primary_email_address = @user_email
AND dv.version_number = ( AND dv.version_number = (
SELECT MAX(dv2.version_number) SELECT MAX(dv2.version_number)
FROM document_versions dv2 FROM document_versions dv2
INNER JOIN document_version_signatures dvs2 ON dvs2.document_version_id = dv2.id INNER JOIN document_version_signatures dvs2 ON dvs2.document_version_id = dv2.id
INNER JOIN peoples p2 ON dvs2.signed_by = p2.id INNER JOIN iam_membership_profiles p2 ON dvs2.signed_by_profile_id = p2.id
WHERE dv2.document_id = d.id WHERE dv2.document_id = d.id
AND p2.primary_email_address = @user_email AND p2.primary_email_address = @user_email
) )

View File

@@ -99,7 +99,7 @@ func (f *DocumentFilter) SQLFragment() string {
SELECT 1 SELECT 1
FROM document_versions dv FROM document_versions dv
INNER JOIN document_version_signatures dvs ON dv.id = dvs.document_version_id INNER JOIN document_version_signatures dvs ON dv.id = dvs.document_version_id
INNER JOIN peoples p ON dvs.signed_by = p.id INNER JOIN iam_membership_profiles p ON dvs.signed_by_profile_id = p.id
WHERE dv.document_id = documents.id WHERE dv.document_id = documents.id
AND dv.status = 'PUBLISHED' AND dv.status = 'PUBLISHED'
AND p.primary_email_address = @user_email::text AND p.primary_email_address = @user_email::text

View File

@@ -47,7 +47,7 @@ func (f *DocumentVersionFilter) SQLFragment() string {
OR EXISTS ( OR EXISTS (
SELECT 1 SELECT 1
FROM document_version_signatures dvs FROM document_version_signatures dvs
INNER JOIN peoples p ON dvs.signed_by = p.id INNER JOIN iam_membership_profiles p ON dvs.signed_by_profile_id = p.id
WHERE dvs.document_version_id = document_versions.id WHERE dvs.document_version_id = document_versions.id
AND p.primary_email_address = @user_email::text AND p.primary_email_address = @user_email::text
AND dvs.state IN ('REQUESTED', 'SIGNED') AND dvs.state IN ('REQUESTED', 'SIGNED')

View File

@@ -364,7 +364,7 @@ WITH sigs AS (
FROM FROM
document_version_signatures dvs document_version_signatures dvs
INNER JOIN INNER JOIN
peoples p ON dvs.signed_by_profile_id = p.id iam_membership_profile_id p ON dvs.signed_by_profile_id = p.id
WHERE WHERE
dvs.document_version_id = @document_version_id dvs.document_version_id = @document_version_id
ORDER BY ORDER BY
@@ -422,7 +422,7 @@ func (pvs *DocumentVersionSignature) IsSignedByUserEmail(
SELECT EXISTS ( SELECT EXISTS (
SELECT 1 SELECT 1
FROM document_version_signatures dvs FROM document_version_signatures dvs
INNER JOIN peoples p ON dvs.signed_by_profile_id = p.id INNER JOIN iam_membership_profiles p ON dvs.signed_by_profile_id = p.id
WHERE dvs.document_version_id = @document_version_id WHERE dvs.document_version_id = @document_version_id
AND p.primary_email_address = @user_email AND p.primary_email_address = @user_email
AND dvs.state = 'SIGNED' AND dvs.state = 'SIGNED'

View File

@@ -53,8 +53,8 @@ func (f *DocumentVersionSignatureFilter) SQLFragment() string {
THEN TRUE THEN TRUE
ELSE EXISTS ( ELSE EXISTS (
SELECT 1 SELECT 1
FROM peoples p FROM iam_membership_profiles p
WHERE p.id = signed_by WHERE p.id = signed_by_profile_id
AND ( AND (
( (
@active_contract::boolean = TRUE @active_contract::boolean = TRUE

View File

@@ -451,14 +451,14 @@ func (p *MembershipProfiles) LoadAwaitingSigning(
q := ` q := `
WITH signatories AS ( WITH signatories AS (
SELECT SELECT
signed_by signed_by_profile_id
FROM FROM
document_version_signatures document_version_signatures
WHERE WHERE
%s %s
AND state = 'REQUESTED' AND state = 'REQUESTED'
GROUP BY GROUP BY
signed_by signed_by_profile_id
) )
SELECT SELECT
p.id, p.id,

View File

@@ -74,9 +74,14 @@ func (mpk MembershipProfileKind) String() string {
} }
func (mpk *MembershipProfileKind) Scan(value any) error { func (mpk *MembershipProfileKind) Scan(value any) error {
val, ok := value.(string) var val string
if !ok { switch v := value.(type) {
return fmt.Errorf("invalid scan source for MembershipProfileKind, expected string got %T", value) case string:
val = v
case []byte:
val = string(v)
default:
return fmt.Errorf("unsupported type for MembershipProfileKind: %T", value)
} }
return mpk.UnmarshalText([]byte(val)) return mpk.UnmarshalText([]byte(val))

View File

@@ -1,53 +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 (
"time"
"github.com/jackc/pgx/v5"
)
type (
PeopleFilter struct {
excludeContractEnded *bool
currentDate time.Time
}
)
func NewPeopleFilter(excludeContractEnded *bool) *PeopleFilter {
return &PeopleFilter{
excludeContractEnded: excludeContractEnded,
currentDate: time.Now(),
}
}
func (f *PeopleFilter) SQLArguments() pgx.StrictNamedArgs {
return pgx.StrictNamedArgs{
"exclude_contract_ended": f.excludeContractEnded,
"current_date": f.currentDate,
}
}
func (f *PeopleFilter) SQLFragment() string {
return `
(
CASE
WHEN @exclude_contract_ended::boolean IS NOT NULL AND @exclude_contract_ended::boolean = true THEN
(contract_end_date IS NULL OR contract_end_date >= @current_date::date)
ELSE TRUE
END
)`
}

View File

@@ -1,87 +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 (
PeopleKind uint8
)
const (
PeopleKindEmployee PeopleKind = iota
PeopleKindContractor
PeopleKindServiceAccount
)
func PeopleKinds() []PeopleKind {
return []PeopleKind{
PeopleKindEmployee,
PeopleKindContractor,
PeopleKindServiceAccount,
}
}
func (ps PeopleKind) MarshalText() ([]byte, error) {
return []byte(ps.String()), nil
}
func (ps *PeopleKind) UnmarshalText(data []byte) error {
val := string(data)
switch val {
case PeopleKindEmployee.String():
*ps = PeopleKindEmployee
case PeopleKindContractor.String():
*ps = PeopleKindContractor
case PeopleKindServiceAccount.String():
*ps = PeopleKindServiceAccount
default:
return fmt.Errorf("invalid PeopleKind value: %q", val)
}
return nil
}
func (ts PeopleKind) String() string {
var val string
switch ts {
case PeopleKindEmployee:
val = "EMPLOYEE"
case PeopleKindContractor:
val = "CONTRACTOR"
case PeopleKindServiceAccount:
val = "SERVICE_ACCOUNT"
}
return val
}
func (pk *PeopleKind) Scan(value any) error {
val, ok := value.(string)
if !ok {
return fmt.Errorf("invalid scan source for PeopleKind, expected string got %T", value)
}
return pk.UnmarshalText([]byte(val))
}
func (pk PeopleKind) Value() (driver.Value, error) {
return pk.String(), nil
}

View File

@@ -175,7 +175,7 @@ WITH rsks AS (
INNER JOIN INNER JOIN
risks_measures rm ON r.id = rm.risk_id risks_measures rm ON r.id = rm.risk_id
LEFT JOIN LEFT JOIN
peoples p ON r.owner_profile_id = p.id iam_membership_profiles p ON r.owner_profile_id = p.id
WHERE WHERE
rm.measure_id = @measure_id rm.measure_id = @measure_id
) )
@@ -293,7 +293,7 @@ WITH rsks AS (
FROM FROM
risks r risks r
LEFT JOIN LEFT JOIN
peoples p ON r.owner_profile_id = p.id iam_membership_profiles p ON r.owner_profile_id = p.id
WHERE WHERE
r.organization_id = @organization_id r.organization_id = @organization_id
) )

View File

@@ -196,7 +196,7 @@ func (upr *UpdateProfileRequest) Validate() error {
v := validator.New() v := validator.New()
v.Check(upr.ID, "id", validator.Required(), validator.GID(coredata.MembershipProfileEntityType)) v.Check(upr.ID, "id", validator.Required(), validator.GID(coredata.MembershipProfileEntityType))
v.Check(upr.Kind, "kind", validator.OneOfSlice(coredata.PeopleKinds())) v.Check(upr.Kind, "kind", validator.OneOfSlice(coredata.MembershipProfileKinds()))
v.Check(upr.FullName, "full_name", validator.SafeTextNoNewLine(NameMaxLength)) v.Check(upr.FullName, "full_name", validator.SafeTextNoNewLine(NameMaxLength))
v.CheckEach(upr.AdditionalEmailAddresses, "additional_email_addresses", func(index int, item any) { v.CheckEach(upr.AdditionalEmailAddresses, "additional_email_addresses", func(index int, item any) {
v.Check(item, fmt.Sprintf("additional_email_addresses[%d]", index), validator.Required(), validator.NotEmpty()) v.Check(item, fmt.Sprintf("additional_email_addresses[%d]", index), validator.Required(), validator.NotEmpty())
@@ -996,7 +996,9 @@ func (s *OrganizationService) UpdateProfile(ctx context.Context, req *UpdateProf
profile.AdditionalEmailAddresses = req.AdditionalEmailAddresses profile.AdditionalEmailAddresses = req.AdditionalEmailAddresses
profile.Position = *req.Position if req.Position != nil {
profile.Position = *req.Position
}
if req.ContractStartDate != nil { if req.ContractStartDate != nil {
profile.ContractStartDate = *req.ContractStartDate profile.ContractStartDate = *req.ContractStartDate

View File

@@ -462,7 +462,7 @@ func (s *DocumentService) Create(
func (s *DocumentService) ListSigningRequests( func (s *DocumentService) ListSigningRequests(
ctx context.Context, ctx context.Context,
organizationID gid.GID, organizationID gid.GID,
peopleID gid.GID, profileID gid.GID,
) ([]map[string]any, error) { ) ([]map[string]any, error) {
q := ` q := `
SELECT SELECT
@@ -476,7 +476,7 @@ FROM
INNER JOIN organizations o ON o.id = p.organization_id INNER JOIN organizations o ON o.id = p.organization_id
WHERE WHERE
p.tenant_id = $1 p.tenant_id = $1
AND pvs.signed_by = $2 AND pvs.signed_by_profile_id = $2
AND pvs.signed_at IS NULL AND pvs.signed_at IS NULL
AND pv.status = 'PUBLISHED' AND pv.status = 'PUBLISHED'
AND pv.version_number = ( AND pv.version_number = (
@@ -491,7 +491,7 @@ WHERE
err := s.svc.pg.WithConn( err := s.svc.pg.WithConn(
ctx, ctx,
func(conn pg.Conn) error { func(conn pg.Conn) error {
rows, err := conn.Query(ctx, q, s.svc.scope.GetTenantID(), peopleID) rows, err := conn.Query(ctx, q, s.svc.scope.GetTenantID(), profileID)
if err != nil { if err != nil {
return fmt.Errorf("cannot query documents: %w", err) return fmt.Errorf("cannot query documents: %w", err)
} }