Skip to content
Open

11 #31

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 14 additions & 7 deletions openapi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ servers:
security:
# This makes every route by default auth protected
- BearerAuthHeader: [] # Authorization header
- BearerAuthCookie: [] # Token in cookie
- BearerAuthCookie: [] # Token in cookie
components:
securitySchemes:
BearerAuthHeader:
Expand Down Expand Up @@ -59,15 +59,16 @@ components:
type: string
members:
type: array
$ref: "#/components/schemas/Member"
items:
$ref: "#/components/schemas/Member"
items:
type: array
$ref: "#/components/schemas/Item"
items:
$ref: "#/components/schemas/Item"
money_balance:
type: integer
required:
- name
- members
- money_balance
requestBodies:
register:
Expand All @@ -93,7 +94,7 @@ components:
content:
application/json:
schema:
$ref: '#/components/schemas/Item'
$ref: "#/components/schemas/Item"
schemas:
UserCredentials:
type: object
Expand Down Expand Up @@ -127,7 +128,7 @@ components:
properties:
id:
type: integer
# readOnly: true # TODO unfortunately ogen doesn't support readOnly marker. But we want to reuse this schema for posting
# readOnly: true # TODO unfortunately ogen doesn't support readOnly marker. But we want to reuse this schema for posting
# as well as getting for simplicity. So for now, the convention would be to set the id to 0 as it will get ignored either way.
timestamp:
type: integer
Expand All @@ -142,6 +143,12 @@ components:
type: integer
reimbursement:
type: boolean
# New participant list should be returned from expense_participants schema
participants:
type: array
items:
$ref: "#/components/schemas/Member"

required:
- id
- timestamp
Expand All @@ -153,7 +160,7 @@ components:
type: object
properties:
id:
type: string
type: integer
name:
type: string
displayName:
Expand Down
98 changes: 95 additions & 3 deletions server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package main
import (
"context"
"database/sql"
"fmt"
"log"
"net/http"
"os"
Expand Down Expand Up @@ -71,8 +72,79 @@ func (h *Handler) GroupsNonauthedGet(ctx context.Context) ([]api.Group, error) {
}

func (h *Handler) GroupsIDGet(ctx context.Context, params api.GroupsIDGetParams) (*api.GroupOverview, error) {
// TODO task #4
return nil, nil
//IDs
g_id := int64(params.ID)
userid := ctx.Value("user_id").(int64)

//authorID
group, _ := qs.GetGroupByID(ctx, g_id)

// Fetch members of the group
members, _ := qs.GetMembersOfGroup(ctx, g_id)

var apiMembers []api.Member

for _, member := range members {
apiMembers = append(apiMembers, api.Member{
ID: int(member.ID),
Name: member.Username,
})
}
// new schema EP added converting to of type memeber th query of Expense_participants
eps, _ := qs.Expense_participants(ctx, 1)
var ep_members []api.Member

for _, ep := range eps {
ep_members = append(ep_members, api.Member{
ID: int(ep.MemberID),
Name: ep.Username,
DisplayName: ep.Displayname,
})

}
// Fetch items of the group
items, _ := qs.GetItemsOfGroup(ctx, g_id)

var apiItems []api.Item

for _, item := range items {
apiItems = append(apiItems, api.Item{
ID: int(item.ID),
Timestamp: int(item.Timestamp),
Name: item.Name,
Price: item.Price,
AuthorID: int(item.AuthorID),
GroupID: int(g_id),
// The new participant list!!!!!!
Participants: ep_members,
})
}
// Calculate money balance for the group
netAmountParams := data.GetNetAmountForUserInGroupParams{
AuthorID: userid,
GroupID: g_id,
}

netAmount, err := qs.GetNetAmountForUserInGroup(ctx, netAmountParams)
if err != nil {
return nil, fmt.Errorf("failed to fetch net amount: %w", err)
}
var balance int

if netAmount.Valid {
balance = int(netAmount.Float64)
} else {
balance = 0
}

groupOverview := &api.GroupOverview{
Name: group.Name,
Members: apiMembers,
Items: apiItems,
MoneyBalance: balance,
}

return groupOverview, nil
}

func (h *Handler) GroupsIDMembersPost(ctx context.Context, req *api.GroupsIDMembersPostReq, params api.GroupsIDMembersPostParams) error {
Expand All @@ -98,14 +170,34 @@ func (h *Handler) GroupsIDItemsGet(ctx context.Context, params api.GroupsIDItems
}

func (h *Handler) GroupsIDItemsPost(ctx context.Context, req *api.Item, params api.GroupsIDItemsPostParams) (int, error) {
g, _ := qs.AddItemToGroup(ctx, data.AddItemToGroupParams{
// Add the new item to the 'items' table
g, err := qs.AddItemToGroup(ctx, data.AddItemToGroupParams{
Name: req.Name,
Timestamp: int64(req.Timestamp),
Price: req.Price,
GroupID: int64(params.ID),
AuthorID: int64(req.AuthorID),
Reimbursement: sql.NullBool{Bool: req.Reimbursement.Value, Valid: req.Reimbursement.Set},
})
if err != nil {
return 0, err
}

// Ensure participants are passed in the request
if len(req.Participants) == 0 {
return 0, fmt.Errorf("no participants provided")
}

// Add participants to the 'expense_participants' table
for _, member := range req.Participants {
err := qs.AddExpenseParticipant(ctx, data.AddExpenseParticipantParams{
ItemID: g, // The ID of the item that was just added
MemberID: int64(member.ID), // The ID of the participant to add
})
if err != nil {
return 0, err
}
}

return int(g), nil
}
Expand Down
26 changes: 26 additions & 0 deletions server/query.sql
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,29 @@ FROM member_groups mg1
INNER JOIN member_groups mg2 ON mg1.group_id = mg2.group_id
WHERE mg1.member_id = ? AND mg2.member_id <> 3
GROUP BY mg2.member_id;


-- name: GetGroupByID :one
SELECT
id,
name
FROM
groups
WHERE
id = ?;

-- name: Expense_participants :many
SELECT
ep.member_id,
i.name AS item_name,
m.username,
m.displayName
FROM expense_participants ep
JOIN items i ON ep.item_id = i.id
JOIN members m ON ep.member_id = m.id
WHERE ep.item_id = ?;

-- name: AddExpenseParticipant :exec
INSERT INTO expense_participants (item_id, member_id) VALUES (?, ?);


8 changes: 8 additions & 0 deletions server/schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,11 @@ CREATE TABLE items ( --bs: medium
FOREIGN KEY (group_id) REFERENCES groups (id),
FOREIGN KEY (author_id) REFERENCES members (id)
);

CREATE TABLE expense_participants ( --bs: medium
item_id INTEGER NOT NULL, --bs: rel
member_id INTEGER NOT NULL, --bs: rel
PRIMARY KEY (item_id, member_id), -- Composite primary key (ensures unique pairs)
FOREIGN KEY (item_id) REFERENCES items (id), -- Foreign key constraint to items table
FOREIGN KEY (member_id) REFERENCES members (id) -- Foreign key constraint to members table
);
16 changes: 10 additions & 6 deletions web/src/routes/g/[slug]/+page.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
import shoppingBagIcon from "@ktibow/iconset-material-symbols/shopping-bag";
import priceIcon from "@ktibow/iconset-material-symbols/price-check";
import check from "@ktibow/iconset-material-symbols/check";
import { PUBLIC_SERVER_URL } from "$env/static/public";
import { PUBLIC_SERVER_URL } from "$env/static/public";
export let data;
let name = "";
let price = "";

let addItem = (e : Event) => {
let addItem = (e: Event) => {
e.preventDefault();
const item = {
id: 14,
Expand All @@ -24,12 +24,10 @@
method: "POST",
body: JSON.stringify(item),
}).then((_) => {
data.items = [item, ...data.items]

data.items = [item, ...data.items];
});
};
let open = true;

</script>

<div class="screen">
Expand Down Expand Up @@ -68,6 +66,12 @@
<div class="fabpos">
<FAB icon={check} size="large"></FAB>
</div>
<div>
<h2>
Balance:
{data.balance}
</h2>
</div>
</form>
</SideSheet>
{/if}
Expand All @@ -78,7 +82,7 @@
display: flex;
align-items: flex-start;
height: 100%;
gap:1rem;
gap: 1rem;
}
.contents {
padding: 1rem;
Expand Down
28 changes: 15 additions & 13 deletions web/src/routes/g/[slug]/+page.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import api from '$lib/api/api';
import { error as errorOut } from '@sveltejs/kit';
import api from "$lib/api/api";
import { error as errorOut } from "@sveltejs/kit";

export async function load({ params }) {
const {
data, // only present if 2XX response
error, // only present if 4XX or 5XX response
response
} = await api.GET("/groups/{id}/items", {params:{path: { id: params.slug}}})
if (response.status != 200) {
errorOut(response.status, response.statusText);
}

return { group_id: params.slug, items: data }

const {
data, // only present if 2XX response
error,
response,
} = await api.GET("/groups/{id}", { params: { path: { id: params.slug } } });
if (response.status != 200) {
errorOut(response.status, response.statusText);
}
return {
items: data!.items,
group_id: params.slug,
balance: data?.money_balance,
};
}