/** * Shared Accounting Period Store Factory * * Creates a Pinia store for accounting period selection that can be used by any ROA2WEB application. * Each app passes its own apiService and store references. * * Usage: * import { createAccountingPeriodStore } from '@shared/frontend/stores/accountingPeriod'; * import { apiService } from '../services/api'; * import { useAuthStore } from './auth'; * import { useCompanyStore } from './companies'; * export const useAccountingPeriodStore = createAccountingPeriodStore(apiService, useAuthStore, useCompanyStore); */ import { defineStore } from "pinia"; import { ref, computed } from "vue"; /** * Factory function to create an accounting period store * @param {Object} apiService - Axios instance configured for the app's API * @param {Function} useAuthStore - Reference to the auth store function * @param {Function} useCompanyStore - Reference to the company store function * @returns {Function} Pinia store definition */ export function createAccountingPeriodStore(apiService, useAuthStore, useCompanyStore) { return defineStore("accountingPeriod", () => { // State const periods = ref([]); const selectedPeriod = ref(null); const isLoading = ref(false); const error = ref(null); // Getters const hasPeriods = computed(() => periods.value.length > 0); const currentPeriod = computed(() => selectedPeriod.value); // Computed date range for current period (first/last day of month) const dateRange = computed(() => { if (!selectedPeriod.value) return { dateFrom: null, dateTo: null }; const { an, luna } = selectedPeriod.value; const firstDay = new Date(an, luna - 1, 1); const lastDay = new Date(an, luna, 0); return { dateFrom: firstDay, dateTo: lastDay, }; }); // localStorage helpers const getStorageKey = () => { const authStore = useAuthStore(); const companyStore = useCompanyStore(); const username = authStore.user?.username; const companyId = companyStore.selectedCompany?.id_firma; if (!username || !companyId) return null; return `selected_period_${username}_${companyId}`; }; const initializeSelectedPeriod = () => { const key = getStorageKey(); if (!key) return null; const saved = localStorage.getItem(key); if (saved) { try { return JSON.parse(saved); } catch (e) { localStorage.removeItem(key); } } return null; }; const persistSelectedPeriod = (period) => { const key = getStorageKey(); if (key && period) { localStorage.setItem(key, JSON.stringify(period)); } }; // Actions const loadPeriods = async (companyId) => { if (!companyId) return { success: false }; isLoading.value = true; error.value = null; try { const response = await apiService.get("/calendar/periods", { params: { company: companyId }, }); periods.value = response.data.periods || []; // Try to restore saved period or use most recent const saved = initializeSelectedPeriod(); if (saved) { const exists = periods.value.find( (p) => p.an === saved.an && p.luna === saved.luna ); if (exists) { selectedPeriod.value = exists; } else if (response.data.current_period) { setSelectedPeriod(response.data.current_period); } } else if (response.data.current_period) { setSelectedPeriod(response.data.current_period); } return { success: true }; } catch (err) { error.value = err.response?.data?.detail || "Failed to load periods"; return { success: false, error: error.value }; } finally { isLoading.value = false; } }; const setSelectedPeriod = (period) => { selectedPeriod.value = period; persistSelectedPeriod(period); }; const resetToLatest = () => { if (periods.value.length > 0) { setSelectedPeriod(periods.value[0]); } }; const reset = () => { periods.value = []; selectedPeriod.value = null; isLoading.value = false; error.value = null; }; return { // State periods, selectedPeriod, isLoading, error, // Getters hasPeriods, currentPeriod, dateRange, // Actions loadPeriods, setSelectedPeriod, resetToLatest, reset, }; }); }