Use type instead of isAccount flag
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
parent
32439e3e87
commit
ae9e9d34c9
@ -130,7 +130,7 @@ func (q *Queries) GetAccountsWithBalance(ctx context.Context, budgetID uuid.UUID
|
|||||||
}
|
}
|
||||||
|
|
||||||
const searchAccounts = `-- name: SearchAccounts :many
|
const searchAccounts = `-- name: SearchAccounts :many
|
||||||
SELECT accounts.id, accounts.budget_id, accounts.name, true as is_account FROM accounts
|
SELECT accounts.id, accounts.budget_id, accounts.name, 'account' as type FROM accounts
|
||||||
WHERE accounts.budget_id = $1
|
WHERE accounts.budget_id = $1
|
||||||
AND accounts.name LIKE $2
|
AND accounts.name LIKE $2
|
||||||
ORDER BY accounts.name
|
ORDER BY accounts.name
|
||||||
@ -142,10 +142,10 @@ type SearchAccountsParams struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SearchAccountsRow struct {
|
type SearchAccountsRow struct {
|
||||||
ID uuid.UUID
|
ID uuid.UUID
|
||||||
BudgetID uuid.UUID
|
BudgetID uuid.UUID
|
||||||
Name string
|
Name string
|
||||||
IsAccount bool
|
Type interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SearchAccounts(ctx context.Context, arg SearchAccountsParams) ([]SearchAccountsRow, error) {
|
func (q *Queries) SearchAccounts(ctx context.Context, arg SearchAccountsParams) ([]SearchAccountsRow, error) {
|
||||||
@ -161,7 +161,7 @@ func (q *Queries) SearchAccounts(ctx context.Context, arg SearchAccountsParams)
|
|||||||
&i.ID,
|
&i.ID,
|
||||||
&i.BudgetID,
|
&i.BudgetID,
|
||||||
&i.Name,
|
&i.Name,
|
||||||
&i.IsAccount,
|
&i.Type,
|
||||||
); err != nil {
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -118,7 +118,8 @@ func (q *Queries) GetCategoryGroups(ctx context.Context, budgetID uuid.UUID) ([]
|
|||||||
}
|
}
|
||||||
|
|
||||||
const searchCategories = `-- name: SearchCategories :many
|
const searchCategories = `-- name: SearchCategories :many
|
||||||
SELECT CONCAT(category_groups.name, ' : ', categories.name) as name, categories.id FROM categories
|
SELECT CONCAT(category_groups.name, ' : ', categories.name) as name, categories.id, 'category' as type
|
||||||
|
FROM categories
|
||||||
INNER JOIN category_groups ON categories.category_group_id = category_groups.id
|
INNER JOIN category_groups ON categories.category_group_id = category_groups.id
|
||||||
WHERE category_groups.budget_id = $1
|
WHERE category_groups.budget_id = $1
|
||||||
AND categories.name LIKE $2
|
AND categories.name LIKE $2
|
||||||
@ -133,6 +134,7 @@ type SearchCategoriesParams struct {
|
|||||||
type SearchCategoriesRow struct {
|
type SearchCategoriesRow struct {
|
||||||
Name interface{}
|
Name interface{}
|
||||||
ID uuid.UUID
|
ID uuid.UUID
|
||||||
|
Type interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SearchCategories(ctx context.Context, arg SearchCategoriesParams) ([]SearchCategoriesRow, error) {
|
func (q *Queries) SearchCategories(ctx context.Context, arg SearchCategoriesParams) ([]SearchCategoriesRow, error) {
|
||||||
@ -144,7 +146,7 @@ func (q *Queries) SearchCategories(ctx context.Context, arg SearchCategoriesPara
|
|||||||
var items []SearchCategoriesRow
|
var items []SearchCategoriesRow
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i SearchCategoriesRow
|
var i SearchCategoriesRow
|
||||||
if err := rows.Scan(&i.Name, &i.ID); err != nil {
|
if err := rows.Scan(&i.Name, &i.ID, &i.Type); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
items = append(items, i)
|
items = append(items, i)
|
||||||
|
@ -58,7 +58,7 @@ func (q *Queries) GetPayees(ctx context.Context, budgetID uuid.UUID) ([]Payee, e
|
|||||||
}
|
}
|
||||||
|
|
||||||
const searchPayees = `-- name: SearchPayees :many
|
const searchPayees = `-- name: SearchPayees :many
|
||||||
SELECT payees.id, payees.budget_id, payees.name FROM payees
|
SELECT payees.id, payees.budget_id, payees.name, 'payee' as type FROM payees
|
||||||
WHERE payees.budget_id = $1
|
WHERE payees.budget_id = $1
|
||||||
AND payees.name LIKE $2
|
AND payees.name LIKE $2
|
||||||
ORDER BY payees.name
|
ORDER BY payees.name
|
||||||
@ -69,16 +69,28 @@ type SearchPayeesParams struct {
|
|||||||
Search string
|
Search string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Queries) SearchPayees(ctx context.Context, arg SearchPayeesParams) ([]Payee, error) {
|
type SearchPayeesRow struct {
|
||||||
|
ID uuid.UUID
|
||||||
|
BudgetID uuid.UUID
|
||||||
|
Name string
|
||||||
|
Type interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) SearchPayees(ctx context.Context, arg SearchPayeesParams) ([]SearchPayeesRow, error) {
|
||||||
rows, err := q.db.QueryContext(ctx, searchPayees, arg.BudgetID, arg.Search)
|
rows, err := q.db.QueryContext(ctx, searchPayees, arg.BudgetID, arg.Search)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
var items []Payee
|
var items []SearchPayeesRow
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var i Payee
|
var i SearchPayeesRow
|
||||||
if err := rows.Scan(&i.ID, &i.BudgetID, &i.Name); err != nil {
|
if err := rows.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.BudgetID,
|
||||||
|
&i.Name,
|
||||||
|
&i.Type,
|
||||||
|
); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
items = append(items, i)
|
items = append(items, i)
|
||||||
|
@ -22,7 +22,7 @@ GROUP BY accounts.id, accounts.name
|
|||||||
ORDER BY accounts.name;
|
ORDER BY accounts.name;
|
||||||
|
|
||||||
-- name: SearchAccounts :many
|
-- name: SearchAccounts :many
|
||||||
SELECT accounts.id, accounts.budget_id, accounts.name, true as is_account FROM accounts
|
SELECT accounts.id, accounts.budget_id, accounts.name, 'account' as type FROM accounts
|
||||||
WHERE accounts.budget_id = @budget_id
|
WHERE accounts.budget_id = @budget_id
|
||||||
AND accounts.name LIKE @search
|
AND accounts.name LIKE @search
|
||||||
ORDER BY accounts.name;
|
ORDER BY accounts.name;
|
||||||
|
@ -21,7 +21,8 @@ WHERE category_groups.budget_id = $1
|
|||||||
ORDER BY category_groups.name, categories.name;
|
ORDER BY category_groups.name, categories.name;
|
||||||
|
|
||||||
-- name: SearchCategories :many
|
-- name: SearchCategories :many
|
||||||
SELECT CONCAT(category_groups.name, ' : ', categories.name) as name, categories.id FROM categories
|
SELECT CONCAT(category_groups.name, ' : ', categories.name) as name, categories.id, 'category' as type
|
||||||
|
FROM categories
|
||||||
INNER JOIN category_groups ON categories.category_group_id = category_groups.id
|
INNER JOIN category_groups ON categories.category_group_id = category_groups.id
|
||||||
WHERE category_groups.budget_id = @budget_id
|
WHERE category_groups.budget_id = @budget_id
|
||||||
AND categories.name LIKE @search
|
AND categories.name LIKE @search
|
||||||
|
@ -10,7 +10,7 @@ WHERE payees.budget_id = $1
|
|||||||
ORDER BY name;
|
ORDER BY name;
|
||||||
|
|
||||||
-- name: SearchPayees :many
|
-- name: SearchPayees :many
|
||||||
SELECT payees.* FROM payees
|
SELECT payees.*, 'payee' as type FROM payees
|
||||||
WHERE payees.budget_id = @budget_id
|
WHERE payees.budget_id = @budget_id
|
||||||
AND payees.name LIKE @search
|
AND payees.name LIKE @search
|
||||||
ORDER BY payees.name;
|
ORDER BY payees.name;
|
||||||
|
@ -15,9 +15,9 @@ import (
|
|||||||
type NewTransactionPayload struct {
|
type NewTransactionPayload struct {
|
||||||
Date JSONDate `json:"date"`
|
Date JSONDate `json:"date"`
|
||||||
Payee struct {
|
Payee struct {
|
||||||
ID uuid.NullUUID
|
ID uuid.NullUUID
|
||||||
Name string
|
Name string
|
||||||
IsAccount bool
|
Type string
|
||||||
} `json:"payee"`
|
} `json:"payee"`
|
||||||
CategoryID uuid.NullUUID `json:"categoryId"`
|
CategoryID uuid.NullUUID `json:"categoryId"`
|
||||||
Memo string `json:"memo"`
|
Memo string `json:"memo"`
|
||||||
@ -56,7 +56,7 @@ func (h *Handler) newTransaction(c *gin.Context) {
|
|||||||
AccountID: payload.AccountID,
|
AccountID: payload.AccountID,
|
||||||
}
|
}
|
||||||
|
|
||||||
if payload.Payee.IsAccount {
|
if payload.Payee.Type == "account" {
|
||||||
err := h.CreateTransferForOtherAccount(newTransaction, amount, payload, c)
|
err := h.CreateTransferForOtherAccount(newTransaction, amount, payload, c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.AbortWithError(http.StatusInternalServerError, err)
|
c.AbortWithError(http.StatusInternalServerError, err)
|
||||||
@ -103,7 +103,10 @@ func (h *Handler) CreateTransferForOtherAccount(newTransaction postgres.CreateTr
|
|||||||
newTransaction.CategoryID = uuid.NullUUID{}
|
newTransaction.CategoryID = uuid.NullUUID{}
|
||||||
|
|
||||||
_, err := h.Service.CreateTransaction(c.Request.Context(), newTransaction)
|
_, err := h.Service.CreateTransaction(c.Request.Context(), newTransaction)
|
||||||
return fmt.Errorf("create transfer transaction: %w", err)
|
if err != nil {
|
||||||
|
return fmt.Errorf("create transfer transaction: %w", err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetPayeeID(context context.Context, payload NewTransactionPayload, h *Handler) (uuid.NullUUID, error) {
|
func GetPayeeID(context context.Context, payload NewTransactionPayload, h *Handler) (uuid.NullUUID, error) {
|
||||||
|
@ -6,23 +6,26 @@ import { useBudgetsStore } from "../stores/budget";
|
|||||||
export interface Suggestion {
|
export interface Suggestion {
|
||||||
ID: string
|
ID: string
|
||||||
Name: string
|
Name: string
|
||||||
|
Type: string
|
||||||
}
|
}
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
text: String,
|
text: String,
|
||||||
id: String | undefined,
|
id: String | undefined,
|
||||||
model: String
|
model: String,
|
||||||
|
type?: string | undefined,
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const SearchQuery = ref(props.text || "");
|
const SearchQuery = ref(props.text || "");
|
||||||
const Suggestions = ref<Array<Suggestion>>([]);
|
const Suggestions = ref<Array<Suggestion>>([]);
|
||||||
const emit = defineEmits(["update:id", "update:text"]);
|
const emit = defineEmits(["update:id", "update:text", "update:type"]);
|
||||||
watch(SearchQuery, () => {
|
watch(SearchQuery, () => {
|
||||||
load(SearchQuery.value);
|
load(SearchQuery.value);
|
||||||
});
|
});
|
||||||
function load(text: String) {
|
function load(text: String) {
|
||||||
emit('update:id', null);
|
emit('update:id', null);
|
||||||
emit('update:text', text);
|
emit('update:text', text);
|
||||||
|
emit('update:type', undefined);
|
||||||
if (text == "") {
|
if (text == "") {
|
||||||
Suggestions.value = [];
|
Suggestions.value = [];
|
||||||
return;
|
return;
|
||||||
@ -53,6 +56,7 @@ function keypress(e: KeyboardEvent) {
|
|||||||
function selectElement(element: Suggestion) {
|
function selectElement(element: Suggestion) {
|
||||||
emit('update:id', element.ID);
|
emit('update:id', element.ID);
|
||||||
emit('update:text', element.Name);
|
emit('update:text', element.Name);
|
||||||
|
emit('update:type', element.Type);
|
||||||
Suggestions.value = [];
|
Suggestions.value = [];
|
||||||
};
|
};
|
||||||
function select(e: MouseEvent) {
|
function select(e: MouseEvent) {
|
||||||
@ -67,6 +71,7 @@ function select(e: MouseEvent) {
|
|||||||
function clear() {
|
function clear() {
|
||||||
emit('update:id', null);
|
emit('update:id', null);
|
||||||
emit('update:text', SearchQuery.value);
|
emit('update:text', SearchQuery.value);
|
||||||
|
emit('update:type', undefined);
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { computed } from "vue";
|
import { computed, ref } from "vue";
|
||||||
import Autocomplete from './Autocomplete.vue'
|
import Autocomplete from './Autocomplete.vue'
|
||||||
import { useAccountStore } from '../stores/budget-account'
|
import { useAccountStore } from '../stores/budget-account'
|
||||||
import DateInput from "./DateInput.vue";
|
import DateInput from "./DateInput.vue";
|
||||||
@ -10,12 +10,14 @@ const props = defineProps<{
|
|||||||
|
|
||||||
const accountStore = useAccountStore();
|
const accountStore = useAccountStore();
|
||||||
const TX = accountStore.Transactions.get(props.transactionid)!;
|
const TX = accountStore.Transactions.get(props.transactionid)!;
|
||||||
|
const payeeType = ref<string|undefined>(undefined);
|
||||||
|
|
||||||
const payload = computed(() => JSON.stringify({
|
const payload = computed(() => JSON.stringify({
|
||||||
date: TX.Date.toISOString().split("T")[0],
|
date: TX.Date.toISOString().split("T")[0],
|
||||||
payee: {
|
payee: {
|
||||||
Name: TX.Payee,
|
Name: TX.Payee,
|
||||||
ID: TX.PayeeID,
|
ID: TX.PayeeID,
|
||||||
|
Type: payeeType.value,
|
||||||
},
|
},
|
||||||
categoryId: TX.CategoryID,
|
categoryId: TX.CategoryID,
|
||||||
memo: TX.Memo,
|
memo: TX.Memo,
|
||||||
@ -36,7 +38,7 @@ function saveTransaction(e: MouseEvent) {
|
|||||||
<DateInput class="border-b-2 border-black" v-model="TX.Date" />
|
<DateInput class="border-b-2 border-black" v-model="TX.Date" />
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width: 150px;">
|
<td style="max-width: 150px;">
|
||||||
<Autocomplete v-model:text="TX.Payee" v-model:id="TX.PayeeID" model="payees" />
|
<Autocomplete v-model:text="TX.Payee" v-model:id="TX.PayeeID" v-model:type="payeeType" model="payees" />
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width: 200px;">
|
<td style="max-width: 200px;">
|
||||||
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
||||||
|
@ -24,6 +24,8 @@ const TX = ref<Transaction>({
|
|||||||
TransferAccount: "",
|
TransferAccount: "",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const payeeType = ref<string|undefined>(undefined);
|
||||||
|
|
||||||
const payload = computed(() => JSON.stringify({
|
const payload = computed(() => JSON.stringify({
|
||||||
budgetId: props.budgetid,
|
budgetId: props.budgetid,
|
||||||
accountId: props.accountid,
|
accountId: props.accountid,
|
||||||
@ -31,6 +33,7 @@ const payload = computed(() => JSON.stringify({
|
|||||||
payee: {
|
payee: {
|
||||||
Name: TX.value.Payee,
|
Name: TX.value.Payee,
|
||||||
ID: TX.value.PayeeID,
|
ID: TX.value.PayeeID,
|
||||||
|
Type: payeeType.value,
|
||||||
},
|
},
|
||||||
categoryId: TX.value.CategoryID,
|
categoryId: TX.value.CategoryID,
|
||||||
memo: TX.value.Memo,
|
memo: TX.value.Memo,
|
||||||
@ -51,7 +54,7 @@ function saveTransaction(e: MouseEvent) {
|
|||||||
<DateInput class="border-b-2 border-black" v-model="TX.Date" />
|
<DateInput class="border-b-2 border-black" v-model="TX.Date" />
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width: 150px;">
|
<td style="max-width: 150px;">
|
||||||
<Autocomplete v-model:text="TX.Payee" v-model:id="TX.PayeeID" model="payees" />
|
<Autocomplete v-model:text="TX.Payee" v-model:id="TX.PayeeID" v-model:type="payeeType" model="payees" />
|
||||||
</td>
|
</td>
|
||||||
<td style="max-width: 200px;">
|
<td style="max-width: 200px;">
|
||||||
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
<Autocomplete v-model:text="TX.Category" v-model:id="TX.CategoryID" model="categories" />
|
||||||
|
Loading…
x
Reference in New Issue
Block a user