Added ability to copy transaction to new draft.
Build Web App / build-and-deploy (push) Successful in 18s Details

This commit is contained in:
Andrew Lalis 2026-07-01 15:20:20 -04:00
parent 710d77438f
commit 8bf19887ad
3 changed files with 51 additions and 2 deletions

View File

@ -216,7 +216,7 @@ function formatRecurringTransactionScheduleExpr(rt: RecurringTransactionResponse
>Delete</AppButton >Delete</AppButton
> >
</ButtonBar> </ButtonBar>
<ButtonBar> <ButtonBar v-if="draft.templateName !== null && draft.templateName.length > 0">
<AppButton <AppButton
icon="repeat" icon="repeat"
@click="addRecurringTransaction()" @click="addRecurringTransaction()"

View File

@ -93,6 +93,34 @@ async function onVendorClicked() {
) )
} }
} }
async function copyToDraft() {
if (!transaction.value) return
const tx = transaction.value
const newDraft = await transactionApi.addDraft({
templateName: null,
timestamp: tx.timestamp,
amount: tx.amount,
currencyCode: tx.currency.code,
description: tx.description,
internalTransfer: tx.internalTransfer,
vendorId: tx.vendor?.id ?? null,
categoryId: tx.category?.id ?? null,
creditedAccountId: tx.creditedAccount?.id ?? null,
debitedAccountId: tx.debitedAccount?.id ?? null,
tags: tx.tags,
lineItems: tx.lineItems.map((li) => {
return {
valuePerItem: li.valuePerItem,
quantity: li.quantity,
description: li.description,
categoryId: li.category?.id ?? null,
}
}),
attachmentIdsToRemove: [],
})
router.push(`/profiles/${getSelectedProfile(route)}/transaction-drafts/${newDraft.id}`)
}
</script> </script>
<template> <template>
<AppPage <AppPage
@ -240,5 +268,13 @@ async function onVendorClicked() {
>Delete</AppButton >Delete</AppButton
> >
</ButtonBar> </ButtonBar>
<ButtonBar>
<AppButton
icon="copy"
@click="copyToDraft()"
size="sm"
>Copy to New Draft</AppButton
>
</ButtonBar>
</AppPage> </AppPage>
</template> </template>

View File

@ -129,6 +129,7 @@ export class NewTransactionEditorContext implements TransactionEditorContextBase
callback: async (formData, route, router) => { callback: async (formData, route, router) => {
const api = new TransactionApiClient(getSelectedProfile(route)) const api = new TransactionApiClient(getSelectedProfile(route))
// Assume that form data is valid! // Assume that form data is valid!
createNewVendorIfNeeded(formData, api)
const data = toTransactionPayload(formData) const data = toTransactionPayload(formData)
const txn = await api.addTransaction(data, formData.attachmentsToUpload) const txn = await api.addTransaction(data, formData.attachmentsToUpload)
await router.replace(`/profiles/${getSelectedProfile(route)}/transactions/${txn.id}`) await router.replace(`/profiles/${getSelectedProfile(route)}/transactions/${txn.id}`)
@ -139,6 +140,7 @@ export class NewTransactionEditorContext implements TransactionEditorContextBase
disabled: !this.areChangesPresent(formData) || !isFormDataValidForDraftSave(formData), disabled: !this.areChangesPresent(formData) || !isFormDataValidForDraftSave(formData),
callback: async (formData, route, router) => { callback: async (formData, route, router) => {
const api = new TransactionApiClient(getSelectedProfile(route)) const api = new TransactionApiClient(getSelectedProfile(route))
createNewVendorIfNeeded(formData, api)
const data = toDraftPayload(formData) const data = toDraftPayload(formData)
const draft = await api.addDraft(data, formData.attachmentsToUpload) const draft = await api.addDraft(data, formData.attachmentsToUpload)
await router.replace( await router.replace(
@ -237,6 +239,7 @@ export class TransactionEditorContext implements TransactionEditorContextBase {
callback: async (formData, route, router) => { callback: async (formData, route, router) => {
const api = new TransactionApiClient(getSelectedProfile(route)) const api = new TransactionApiClient(getSelectedProfile(route))
// Assume that form data is valid! // Assume that form data is valid!
createNewVendorIfNeeded(formData, api)
const data = toTransactionPayload(formData) const data = toTransactionPayload(formData)
const txn = await api.updateTransaction( const txn = await api.updateTransaction(
this.existingTransaction.id, this.existingTransaction.id,
@ -275,7 +278,6 @@ export class DraftEditorContext implements TransactionEditorContextBase {
formData.debitedAccountId === null || formData.debitedAccountId === null ||
formData.creditedAccountId !== formData.debitedAccountId) && formData.creditedAccountId !== formData.debitedAccountId) &&
(formData.templateName === null || formData.templateName.length <= 32) (formData.templateName === null || formData.templateName.length <= 32)
console.log('Checking draft editor valid:', formData, result)
return result return result
} }
@ -328,6 +330,7 @@ export class DraftEditorContext implements TransactionEditorContextBase {
disabled: !this.areChangesPresent() || !this.isFormDataValid(formData), disabled: !this.areChangesPresent() || !this.isFormDataValid(formData),
callback: async (formData, route, router) => { callback: async (formData, route, router) => {
const api = new TransactionApiClient(getSelectedProfile(route)) const api = new TransactionApiClient(getSelectedProfile(route))
createNewVendorIfNeeded(formData, api)
const data = toDraftPayload(formData) const data = toDraftPayload(formData)
const draft = await api.updateDraft( const draft = await api.updateDraft(
this.existingDraft.id, this.existingDraft.id,
@ -461,6 +464,16 @@ function toTransactionPayload(formData: TransactionEditorFormFields): AddTransac
return payload return payload
} }
async function createNewVendorIfNeeded(
formData: TransactionEditorFormFields,
api: TransactionApiClient,
) {
if (formData.vendor && formData.vendor.id === -1) {
const vendor = await api.createVendor({ name: formData.vendor.name, description: null })
formData.vendor = vendor
}
}
async function goBackOrHome(router: Router, route: RouteLocation) { async function goBackOrHome(router: Router, route: RouteLocation) {
if (window.history.length > 0) { if (window.history.length > 0) {
await router.back() await router.back()