Skip to content

Commit

Permalink
feat: creating invoices
Browse files Browse the repository at this point in the history
  • Loading branch information
JustSamuel committed Oct 28, 2024
1 parent 224b6c3 commit 7bcfdc6
Show file tree
Hide file tree
Showing 26 changed files with 732 additions and 114 deletions.
2 changes: 1 addition & 1 deletion apps/dashboard/src/components/ActionButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
</template>

<script setup lang="ts">
import { computed, ref, watch } from 'vue';
import { ref, watch } from 'vue';
import Button from 'primevue/button';
const props = defineProps({
Expand Down
13 changes: 9 additions & 4 deletions apps/dashboard/src/components/FindUser.vue
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { onMounted, type PropType, ref, watch } from "vue";
import type { Ref } from "vue";
import apiService from "@/services/ApiService";
import { debounce } from "lodash";
import type { BaseUserResponse, UserResponse } from "@sudosos/sudosos-client";
import { type BaseUserResponse, GetAllUsersTypeEnum, type UserResponse } from "@sudosos/sudosos-client";
const lastQuery = ref("");
const selectedUser = ref(null);
Expand All @@ -31,7 +31,7 @@ const loading = ref(false);
const users: Ref<(BaseUserResponse & { fullName: string })[]> = ref([]);
const emits = defineEmits(['update:value']);
defineProps({
const props = defineProps({
value: {
type: Object as PropType<UserResponse>,
},
Expand All @@ -40,6 +40,11 @@ defineProps({
required: false,
default: ''
},
type: {
type: String as PropType<GetAllUsersTypeEnum>,
required: false,
default: undefined
}
});
const transformUsers = (userData: BaseUserResponse[]) => {
Expand All @@ -51,7 +56,7 @@ const transformUsers = (userData: BaseUserResponse[]) => {
const debouncedSearch = debounce((e: any) => {
loading.value = true;
apiService.user.getAllUsers(50, 0, e.value).then((res) => {
apiService.user.getAllUsers(50, 0, e.value, undefined, undefined, undefined, props.type).then((res) => {
users.value = transformUsers(res.data.records); // Transform users
}).finally(() => {
loading.value = false;
Expand All @@ -67,7 +72,7 @@ const filterUsers = (e: any) => {
};
onMounted(async () => {
apiService.user.getAllUsers(10, 0).then((res) => {
apiService.user.getAllUsers(10, 0, undefined, undefined, undefined, undefined, props.type).then((res) => {
users.value = transformUsers(res.data.records); // Transform users
});
});
Expand Down
10 changes: 8 additions & 2 deletions apps/dashboard/src/components/InputUserSpan.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
<span class="my-0">{{ label }}</span>
<FindUser :placeholder="placeholder"
v-model="internalValue"
:disabled="disabled"/>
:disabled="disabled"
:type="type"/>
</span>
<div class="flex justify-content-end">
<ErrorSpan :error="errors"/>
Expand All @@ -17,7 +18,7 @@
import ErrorSpan from "@/components/ErrorSpan.vue";
import { onMounted, type PropType, ref, watch } from "vue";
import FindUser from "@/components/FindUser.vue";
import type { BaseUserResponse } from "@sudosos/sudosos-client";
import { type BaseUserResponse, GetAllUsersTypeEnum } from "@sudosos/sudosos-client";
const emit = defineEmits(['update:value']);
Expand Down Expand Up @@ -48,6 +49,11 @@ const props = defineProps({
required: false,
default: false
},
type: {
type: String as PropType<GetAllUsersTypeEnum>,
required: false,
default: undefined
}
});
const internalValue = ref();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@
{{ formatPrice((mutation.data as FinancialMutation).amount) }}
</div>

<!-- Fines get green -->
<!-- Fines get red -->
<div v-else-if="isFine(mutation.data.type)" style="color: #d40000"
class="font-bold">
{{ formatPrice((mutation.data as FinancialMutation).amount, true) }}
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/locales/en/modules/financial.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"missingPdf": "PDF is missing or generation failed",
"deleted": "Invoice has been deleted.",
"dirty": "Invoice amount does not match transfer amount.",
"total": "The current total on the invoice is {total}"
"total": "The current total on the invoice is {total}",
"create": "Create invoice"
},
"payout": {
"title": "Payout overview",
Expand Down
3 changes: 2 additions & 1 deletion apps/dashboard/src/locales/nl/modules/financial.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@
"missingPdf": "PDF ontbreekt of genereren is mislukt",
"deleted": "Factuur is verwijderd.",
"dirty": "De factuurbedrag komt niet overeen met de overboeking.",
"total": "Het huidige totaal op de factuur is {total}"
"total": "Het huidige totaal op de factuur is {total}",
"create": "Factuur aanmaken"
},
"payout": {
"title": "Uitbetalingsoverzicht",
Expand Down
2 changes: 2 additions & 0 deletions apps/dashboard/src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import DataView from "primevue/dataview";
import InputNumber from "primevue/inputnumber";
import Dialog from "primevue/dialog";
import Steps from "primevue/steps";
import Divider from "primevue/divider";
import 'primeicons/primeicons.css';
import Dropdown from "primevue/dropdown";
import Checkbox from "primevue/checkbox";
Expand Down Expand Up @@ -83,6 +84,7 @@ app.component('ToggleButton', ToggleButton);
app.component('Steps', Steps);
app.component('Calendar', Calendar);
app.component('ConfirmDialog', ConfirmDialog);
app.component('Divider', Divider);

populateStoresFromToken(apiService).then(() => {
app.mount('#app');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import FormCard from "@/components/FormCard.vue";
import { computed, onBeforeMount, ref, watch } from "vue";
import type { InvoiceResponse } from "@sudosos/sudosos-client";
import InvoiceAddressingForm from "@/modules/financial/components/invoice/forms/InvoiceAddressingForm.vue";
import InvoiceAddressingForm from "@/modules/financial/components/invoice/forms/InvoiceUpdateAddressingForm.vue";
import { updateInvoiceAddressingObject } from "@/utils/validation-schema";
import { schemaToForm } from "@/utils/formUtils";
import { InvoiceStatusResponseStateEnum } from "@sudosos/sudosos-client/src/api";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<template>
<CardComponent header="Create Invoice">
<ActionButton
type="submit"
:disabled="disabled"
:label="t('common.create')"
:submitting="form.context.isSubmitting.value"
:result="form.success?.value != null"
@click="form.submit"
/>
</CardComponent>
</template>

<script setup lang="ts">
import CardComponent from "@/components/CardComponent.vue";
import { computed, type PropType } from "vue";
import { type Form, getProperty, setSubmit, setSuccess } from "@/utils/formUtils";
import * as yup from "yup";
import { createInvoiceObject } from "@/utils/validation-schema";
import ActionButton from "@/components/ActionButton.vue";
import { useI18n } from "vue-i18n";
import type { CreateInvoiceRequest } from "@sudosos/sudosos-client";
import { useAuthStore } from "@sudosos/sudosos-frontend-common";
import apiService from "@/services/ApiService";
import { useToast } from "primevue/usetoast";
import { handleError } from "@/utils/errorUtils";
const { t } = useI18n();
const toast = useToast();
const disabled = computed(() => {
return !props.form?.context.meta.value.valid || getProperty(props.form, "forId") === undefined;
});
const props = defineProps({
form: {
type: Object as PropType<Form<yup.InferType<typeof createInvoiceObject>>>,
required: true,
},
});
const authStore = useAuthStore();
setSubmit(props.form, props.form.context.handleSubmit(async (values) => {
const byId = authStore.user?.id;
if (byId === undefined) {
setSuccess(props.form, false);
return;
}
const request: CreateInvoiceRequest = {
forId: values.forId,
byId,
addressee: values.addressee,
description: values.description,
reference: values.reference,
transactionIDs: values.transactionIDs,
street: values.street,
postalCode: values.postalCode,
city: values.city,
country: values.country,
date: values.date,
attention: values.attention,
amount: values.transactionTotal,
};
await apiService.invoices.createInvoice(request).then(() => {
toast.add({
severity: 'success',
summary: t('common.toast.success.success'),
detail: t('common.toast.success.invoiceCreated'),
life: 3000,
});
setSuccess(props.form, true);
props.form.context.resetForm();
}).catch((error) => {
setSuccess(props.form, false);
handleError(error, toast);
});
}));
</script>

<style scoped lang="scss">
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
<template>
<FormCard :header="t('modules.financial.forms.invoice.addressing')" :enable-edit="false">
<div class="flex flex-column justify-content-between gap-2">
<InvoiceBaseAddressingForm :form="form" :edit="edit"/>
</div>
</FormCard>
</template>

<script setup lang="ts">
import FormCard from "@/components/FormCard.vue";
import { computed, type PropType } from "vue";
import { createInvoiceObject } from "@/utils/validation-schema";
import { type Form, getProperty } from "@/utils/formUtils";
import { useI18n } from "vue-i18n";
import * as yup from "yup";
import InvoiceBaseAddressingForm from "@/modules/financial/components/invoice/forms/InvoiceBaseAddressingForm.vue";
const { t } = useI18n();
const edit = computed(() => {
const forId = getProperty(props.form, "forId");
return forId !== undefined;
});
const props = defineProps({
form: {
type: Object as PropType<Form<yup.InferType<typeof createInvoiceObject>>>,
required: true,
},
});
</script>

<style scoped lang="scss">
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<template>
<FormCard :header="t('modules.financial.forms.invoice.settings')" :enable-edit="false">
<div class="flex flex-column justify-content-between gap-2">
<InvoiceBaseSettingsForm :form="form" :edit="edit"/>
</div>
</FormCard>
</template>

<script setup lang="ts">
import FormCard from "@/components/FormCard.vue";
import { computed, type PropType } from "vue";
import { createInvoiceObject } from "@/utils/validation-schema";
import { type Form, getProperty } from "@/utils/formUtils";
import { useI18n } from "vue-i18n";
import * as yup from "yup";
import InvoiceBaseSettingsForm from "@/modules/financial/components/invoice/forms/InvoiceBaseSettingsForm.vue";
const { t } = useI18n();
const edit = computed(() => {
const forId = getProperty(props.form, "forId");
return forId !== undefined;
});
const props = defineProps({
form: {
type: Object as PropType<Form<yup.InferType<typeof createInvoiceObject>>>,
required: true,
},
});
</script>

<style scoped lang="scss">
</style>
Loading

0 comments on commit 7bcfdc6

Please sign in to comment.