diff --git a/src/stores/invoices.ts b/src/stores/invoices.ts new file mode 100644 index 0000000..a9760c4 --- /dev/null +++ b/src/stores/invoices.ts @@ -0,0 +1,138 @@ +import { defineStore } from 'pinia' +import { ref } from 'vue' +import { invoke } from '@tauri-apps/api/core' + +export interface Invoice { + id?: number + client_id: number + invoice_number: string + date: string + due_date?: string + subtotal: number + tax_rate: number + tax_amount: number + discount: number + total: number + notes?: string + status: string + template_id?: string +} + +export interface InvoiceItem { + id?: number + invoice_id: number + description: string + quantity: number + rate: number + amount: number + time_entry_id?: number +} + +export const useInvoicesStore = defineStore('invoices', () => { + const invoices = ref([]) + const loading = ref(false) + + async function fetchInvoices() { + loading.value = true + try { + invoices.value = await invoke('get_invoices') + } catch (error) { + console.error('Failed to fetch invoices:', error) + } finally { + loading.value = false + } + } + + async function createInvoice(invoice: Invoice): Promise { + try { + const id = await invoke('create_invoice', { invoice }) + invoices.value.unshift({ ...invoice, id: Number(id) }) + return Number(id) + } catch (error) { + console.error('Failed to create invoice:', error) + return null + } + } + + async function updateInvoice(invoice: Invoice): Promise { + try { + await invoke('update_invoice', { invoice }) + const index = invoices.value.findIndex(i => i.id === invoice.id) + if (index !== -1) { + invoices.value[index] = invoice + } + return true + } catch (error) { + console.error('Failed to update invoice:', error) + return false + } + } + + async function updateInvoiceTemplate(id: number, templateId: string): Promise { + try { + await invoke('update_invoice_template', { id, templateId }) + const index = invoices.value.findIndex(i => i.id === id) + if (index !== -1) { + invoices.value[index].template_id = templateId + } + return true + } catch (error) { + console.error('Failed to update invoice template:', error) + return false + } + } + + async function deleteInvoice(id: number): Promise { + try { + await invoke('delete_invoice', { id }) + invoices.value = invoices.value.filter(i => i.id !== id) + return true + } catch (error) { + console.error('Failed to delete invoice:', error) + return false + } + } + + async function getInvoiceItems(invoiceId: number): Promise { + try { + return await invoke('get_invoice_items', { invoiceId }) + } catch (error) { + console.error('Failed to fetch invoice items:', error) + return [] + } + } + + async function createInvoiceItem(item: InvoiceItem): Promise { + try { + return await invoke('create_invoice_item', { item }) + } catch (error) { + console.error('Failed to create invoice item:', error) + return null + } + } + + async function saveInvoiceItems(invoiceId: number, items: { description: string; quantity: number; unit_price: number }[]): Promise { + for (const item of items) { + await createInvoiceItem({ + invoice_id: invoiceId, + description: item.description, + quantity: item.quantity, + rate: item.unit_price, + amount: item.quantity * item.unit_price, + }) + } + } + + return { + invoices, + loading, + fetchInvoices, + createInvoice, + updateInvoice, + updateInvoiceTemplate, + deleteInvoice, + getInvoiceItems, + createInvoiceItem, + saveInvoiceItems + } +})