feat: implement user profile retrieval with roles and permissions caching

This commit is contained in:
Tran Anh Tuan
2026-05-12 14:36:50 +07:00
parent e81a248a61
commit 902caa222f
17 changed files with 671 additions and 19 deletions

View File

@@ -0,0 +1,197 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: invoice_item.sql
package db
import (
"context"
"github.com/jackc/pgx/v5/pgtype"
)
const createInvoiceItem = `-- name: CreateInvoiceItem :one
INSERT INTO invoice_items (invoice_id,component_id,original_component_id, required_quantity,actual_quantity, is_substituted, is_short, shortage_quantity, note, metadata)
VALUES (
$1,
$2,
$3,
$4,
$5,
$6,
$7,
$8,
$9,
$10
)
RETURNING id, invoice_id, component_id, original_component_id, required_quantity, actual_quantity, is_substituted, is_short, shortage_quantity, note, metadata
`
type CreateInvoiceItemParams struct {
InvoiceID int64 `db:"invoice_id" json:"invoiceId"`
ComponentID int64 `db:"component_id" json:"componentId"`
OriginalComponentID pgtype.Int8 `db:"original_component_id" json:"originalComponentId"`
RequiredQuantity int32 `db:"required_quantity" json:"requiredQuantity"`
ActualQuantity int32 `db:"actual_quantity" json:"actualQuantity"`
IsSubstituted bool `db:"is_substituted" json:"isSubstituted"`
IsShort bool `db:"is_short" json:"isShort"`
ShortageQuantity int32 `db:"shortage_quantity" json:"shortageQuantity"`
Note pgtype.Text `db:"note" json:"note"`
Metadata []byte `db:"metadata" json:"metadata"`
}
func (q *Queries) CreateInvoiceItem(ctx context.Context, arg CreateInvoiceItemParams) (InvoiceItem, error) {
row := q.db.QueryRow(ctx, createInvoiceItem,
arg.InvoiceID,
arg.ComponentID,
arg.OriginalComponentID,
arg.RequiredQuantity,
arg.ActualQuantity,
arg.IsSubstituted,
arg.IsShort,
arg.ShortageQuantity,
arg.Note,
arg.Metadata,
)
var i InvoiceItem
err := row.Scan(
&i.ID,
&i.InvoiceID,
&i.ComponentID,
&i.OriginalComponentID,
&i.RequiredQuantity,
&i.ActualQuantity,
&i.IsSubstituted,
&i.IsShort,
&i.ShortageQuantity,
&i.Note,
&i.Metadata,
)
return i, err
}
const deleteInvoiceItem = `-- name: DeleteInvoiceItem :execrows
DELETE FROM invoice_items
WHERE id = $1
`
func (q *Queries) DeleteInvoiceItem(ctx context.Context, id int64) (int64, error) {
result, err := q.db.Exec(ctx, deleteInvoiceItem, id)
if err != nil {
return 0, err
}
return result.RowsAffected(), nil
}
const getInvoiceItemByID = `-- name: GetInvoiceItemByID :one
SELECT id, invoice_id, component_id, original_component_id, required_quantity, actual_quantity, is_substituted, is_short, shortage_quantity, note, metadata FROM invoice_items
WHERE id = $1
`
func (q *Queries) GetInvoiceItemByID(ctx context.Context, id int64) (InvoiceItem, error) {
row := q.db.QueryRow(ctx, getInvoiceItemByID, id)
var i InvoiceItem
err := row.Scan(
&i.ID,
&i.InvoiceID,
&i.ComponentID,
&i.OriginalComponentID,
&i.RequiredQuantity,
&i.ActualQuantity,
&i.IsSubstituted,
&i.IsShort,
&i.ShortageQuantity,
&i.Note,
&i.Metadata,
)
return i, err
}
const listInvoiceItems = `-- name: ListInvoiceItems :many
SELECT id, invoice_id, component_id, original_component_id, required_quantity, actual_quantity, is_substituted, is_short, shortage_quantity, note, metadata FROM invoice_items
`
func (q *Queries) ListInvoiceItems(ctx context.Context) ([]InvoiceItem, error) {
rows, err := q.db.Query(ctx, listInvoiceItems)
if err != nil {
return nil, err
}
defer rows.Close()
var items []InvoiceItem
for rows.Next() {
var i InvoiceItem
if err := rows.Scan(
&i.ID,
&i.InvoiceID,
&i.ComponentID,
&i.OriginalComponentID,
&i.RequiredQuantity,
&i.ActualQuantity,
&i.IsSubstituted,
&i.IsShort,
&i.ShortageQuantity,
&i.Note,
&i.Metadata,
); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}
const updateInvoiceItem = `-- name: UpdateInvoiceItem :one
UPDATE invoice_items
SET required_quantity = coalesce($1, required_quantity),
actual_quantity = coalesce($2, actual_quantity),
is_substituted = coalesce($3, is_substituted),
is_short = coalesce($4, is_short),
shortage_quantity = coalesce($5, shortage_quantity),
note = coalesce($6, note),
metadata = coalesce($7, metadata)
WHERE id = $8
RETURNING id, invoice_id, component_id, original_component_id, required_quantity, actual_quantity, is_substituted, is_short, shortage_quantity, note, metadata
`
type UpdateInvoiceItemParams struct {
RequiredQuantity int32 `db:"required_quantity" json:"requiredQuantity"`
ActualQuantity int32 `db:"actual_quantity" json:"actualQuantity"`
IsSubstituted bool `db:"is_substituted" json:"isSubstituted"`
IsShort bool `db:"is_short" json:"isShort"`
ShortageQuantity int32 `db:"shortage_quantity" json:"shortageQuantity"`
Note pgtype.Text `db:"note" json:"note"`
Metadata []byte `db:"metadata" json:"metadata"`
ID int64 `db:"id" json:"id"`
}
func (q *Queries) UpdateInvoiceItem(ctx context.Context, arg UpdateInvoiceItemParams) (InvoiceItem, error) {
row := q.db.QueryRow(ctx, updateInvoiceItem,
arg.RequiredQuantity,
arg.ActualQuantity,
arg.IsSubstituted,
arg.IsShort,
arg.ShortageQuantity,
arg.Note,
arg.Metadata,
arg.ID,
)
var i InvoiceItem
err := row.Scan(
&i.ID,
&i.InvoiceID,
&i.ComponentID,
&i.OriginalComponentID,
&i.RequiredQuantity,
&i.ActualQuantity,
&i.IsSubstituted,
&i.IsShort,
&i.ShortageQuantity,
&i.Note,
&i.Metadata,
)
return i, err
}

View File

@@ -0,0 +1,46 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.30.0
// source: permission.sql
package db
import (
"context"
"github.com/google/uuid"
"github.com/jackc/pgx/v5/pgtype"
)
const getPermissionsByUserID = `-- name: GetPermissionsByUserID :many
SELECT DISTINCT p.name, p.description
FROM user_roles ur
JOIN role_permissions rp ON rp.role_id = ur.role_id
JOIN permissions p ON p.id = rp.permission_id
WHERE ur.user_id = $1
`
type GetPermissionsByUserIDRow struct {
Name string `db:"name" json:"name"`
Description pgtype.Text `db:"description" json:"description"`
}
func (q *Queries) GetPermissionsByUserID(ctx context.Context, userID uuid.UUID) ([]GetPermissionsByUserIDRow, error) {
rows, err := q.db.Query(ctx, getPermissionsByUserID, userID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []GetPermissionsByUserIDRow
for rows.Next() {
var i GetPermissionsByUserIDRow
if err := rows.Scan(&i.Name, &i.Description); err != nil {
return nil, err
}
items = append(items, i)
}
if err := rows.Err(); err != nil {
return nil, err
}
return items, nil
}

View File

@@ -24,6 +24,7 @@ type Querier interface {
CreateInvoice(ctx context.Context, arg CreateInvoiceParams) (Invoice, error)
CreateInvoiceConfig(ctx context.Context, arg CreateInvoiceConfigParams) (InvoiceConfig, error)
CreateInvoiceConfigItem(ctx context.Context, arg CreateInvoiceConfigItemParams) (InvoiceConfigItem, error)
CreateInvoiceItem(ctx context.Context, arg CreateInvoiceItemParams) (InvoiceItem, error)
CreateRole(ctx context.Context, arg CreateRoleParams) (Role, error)
CreateRoom(ctx context.Context, arg CreateRoomParams) (Room, error)
CreateShelve(ctx context.Context, arg CreateShelveParams) (Shelf, error)
@@ -39,6 +40,7 @@ type Querier interface {
DeleteInvoice(ctx context.Context, id int64) (int64, error)
DeleteInvoiceConfig(ctx context.Context, id int64) (int64, error)
DeleteInvoiceConfigItem(ctx context.Context, id int64) (int64, error)
DeleteInvoiceItem(ctx context.Context, id int64) (int64, error)
DeleteRole(ctx context.Context, id uuid.UUID) (int64, error)
DeleteRoom(ctx context.Context, id int64) (int64, error)
DeleteShelve(ctx context.Context, id int64) (int64, error)
@@ -55,6 +57,8 @@ type Querier interface {
GetInvoiceByID(ctx context.Context, id int64) (Invoice, error)
GetInvoiceConfigByID(ctx context.Context, id int64) (InvoiceConfig, error)
GetInvoiceConfigItemByID(ctx context.Context, id int64) (InvoiceConfigItem, error)
GetInvoiceItemByID(ctx context.Context, id int64) (InvoiceItem, error)
GetPermissionsByUserID(ctx context.Context, userID uuid.UUID) ([]GetPermissionsByUserIDRow, error)
GetRoleByID(ctx context.Context, id uuid.UUID) (Role, error)
GetRoomByID(ctx context.Context, id int64) (Room, error)
GetShelveByID(ctx context.Context, id int64) (Shelf, error)
@@ -74,6 +78,7 @@ type Querier interface {
ListContainers(ctx context.Context) ([]Container, error)
ListInvoiceConfigItems(ctx context.Context) ([]InvoiceConfigItem, error)
ListInvoiceConfigs(ctx context.Context) ([]InvoiceConfig, error)
ListInvoiceItems(ctx context.Context) ([]InvoiceItem, error)
ListInvoices(ctx context.Context) ([]Invoice, error)
ListRoles(ctx context.Context) ([]Role, error)
ListRooms(ctx context.Context) ([]Room, error)
@@ -93,6 +98,7 @@ type Querier interface {
UpdateInvoice(ctx context.Context, arg UpdateInvoiceParams) (Invoice, error)
UpdateInvoiceConfig(ctx context.Context, arg UpdateInvoiceConfigParams) (InvoiceConfig, error)
UpdateInvoiceConfigItem(ctx context.Context, arg UpdateInvoiceConfigItemParams) (InvoiceConfigItem, error)
UpdateInvoiceItem(ctx context.Context, arg UpdateInvoiceItemParams) (InvoiceItem, error)
UpdateRole(ctx context.Context, arg UpdateRoleParams) (Role, error)
UpdateRoom(ctx context.Context, arg UpdateRoomParams) (Room, error)
UpdateShelve(ctx context.Context, arg UpdateShelveParams) (Shelf, error)