diff --git a/reports-app/backend/app/models/invoice.py b/reports-app/backend/app/models/invoice.py index 4d57f73..844e509 100644 --- a/reports-app/backend/app/models/invoice.py +++ b/reports-app/backend/app/models/invoice.py @@ -64,6 +64,8 @@ class InvoiceListResponse(BaseModel): page_size: int has_more: bool accounting_period: Optional[dict] = Field(default=None, description="Perioada contabilă (an, luna)") + # Total sold din TOATE facturile filtrate (nu doar pagina curentă) + total_sold_all: Decimal = Field(default=Decimal('0.00'), description="Total sold din toate facturile filtrate") class InvoiceSummary(BaseModel): """Rezumat pentru facturi - pentru dashboard""" diff --git a/reports-app/backend/app/models/treasury.py b/reports-app/backend/app/models/treasury.py index 3208868..bc652fd 100644 --- a/reports-app/backend/app/models/treasury.py +++ b/reports-app/backend/app/models/treasury.py @@ -44,4 +44,9 @@ class RegisterListResponse(BaseModel): page: int page_size: int has_more: bool - accounting_period: Optional[AccountingPeriod] = None \ No newline at end of file + accounting_period: Optional[AccountingPeriod] = None + # Totaluri din TOATE înregistrările filtrate (nu doar pagina curentă) + sold_precedent_all: Decimal = Decimal('0.00') + total_incasari_all: Decimal = Decimal('0.00') + total_plati_all: Decimal = Decimal('0.00') + sold_final_all: Decimal = Decimal('0.00') \ No newline at end of file diff --git a/reports-app/backend/app/models/trial_balance.py b/reports-app/backend/app/models/trial_balance.py index 2e84b87..c370411 100644 --- a/reports-app/backend/app/models/trial_balance.py +++ b/reports-app/backend/app/models/trial_balance.py @@ -49,6 +49,18 @@ class TrialBalancePagination(BaseModel): page_size: int = Field(description="Items per page") +class TrialBalanceTotals(BaseModel): + """ + Totals for all 6 columns from all filtered records (not just current page) + """ + total_sold_precedent_debit: Decimal = Decimal('0.00') + total_sold_precedent_credit: Decimal = Decimal('0.00') + total_rulaj_lunar_debit: Decimal = Decimal('0.00') + total_rulaj_lunar_credit: Decimal = Decimal('0.00') + total_sold_final_debit: Decimal = Decimal('0.00') + total_sold_final_credit: Decimal = Decimal('0.00') + + class TrialBalanceResponse(BaseModel): """ Complete response for trial balance endpoint diff --git a/reports-app/backend/app/services/invoice_service.py b/reports-app/backend/app/services/invoice_service.py index fe6d134..e5b44f6 100644 --- a/reports-app/backend/app/services/invoice_service.py +++ b/reports-app/backend/app/services/invoice_service.py @@ -142,7 +142,16 @@ class InvoiceService: count_query = f"SELECT COUNT(*) FROM ({base_query})" cursor.execute(count_query, params) total_count = cursor.fetchone()[0] - + + # Query pentru TOTAL SOLD din TOATE facturile filtrate (nu doar pagina curentă) + total_sold_query = f""" + SELECT NVL(SUM(sold), 0) as total_sold + FROM ({base_query}) + """ + cursor.execute(total_sold_query, params) + total_sold_result = cursor.fetchone() + total_sold_all = Decimal(str(total_sold_result[0])) if total_sold_result else Decimal('0.00') + # Get accounting period - use params if provided, else from calendar if use_param_period: accounting_period = { @@ -226,7 +235,9 @@ class InvoiceService: page=filter_params.page, page_size=filter_params.page_size, has_more=len(invoices) == filter_params.page_size, - accounting_period=accounting_period + accounting_period=accounting_period, + # Total sold din TOATE facturile filtrate + total_sold_all=total_sold_all ) @staticmethod diff --git a/reports-app/backend/app/services/treasury_service.py b/reports-app/backend/app/services/treasury_service.py index 3cb3fab..9840f1b 100644 --- a/reports-app/backend/app/services/treasury_service.py +++ b/reports-app/backend/app/services/treasury_service.py @@ -253,6 +253,58 @@ class TreasuryService: cursor.execute(count_plsql, count_params) total_count = total_count_var.getvalue() + # Query pentru TOTALURI din TOATE înregistrările filtrate (nu doar pagina curentă) + # sold_precedent = suma sold pentru rânduri cu dataact IS NULL + # total_incasari = suma incasari pentru rânduri cu dataact IS NOT NULL + # total_plati = suma plati pentru rânduri cu dataact IS NOT NULL + totals_plsql = f""" + DECLARE + v_an NUMBER; + v_luna NUMBER; + BEGIN + -- Obține anul și luna din parametri sau calendar + {period_select} + + {schema}.PACK_SESIUNE.SETAN(v_an); + {schema}.PACK_SESIUNE.SETLUNA(v_luna); + + -- Sold precedent: suma sold pentru rânduri fără dată (opening balance) + SELECT NVL(SUM(sold), 0) INTO :sold_precedent_all + FROM ({base_select}) sub{where_clause} + WHERE dataact IS NULL; + + -- Total încasări: suma incasari pentru rânduri cu dată (transactions) + SELECT NVL(SUM(incasari), 0) INTO :total_incasari_all + FROM ({base_select}) sub{where_clause} + WHERE dataact IS NOT NULL; + + -- Total plăți: suma plati pentru rânduri cu dată (transactions) + SELECT NVL(SUM(plati), 0) INTO :total_plati_all + FROM ({base_select}) sub{where_clause} + WHERE dataact IS NOT NULL; + END; + """ + + sold_precedent_all_var = cursor.var(oracledb.NUMBER) + total_incasari_all_var = cursor.var(oracledb.NUMBER) + total_plati_all_var = cursor.var(oracledb.NUMBER) + + totals_params = { + 'sold_precedent_all': sold_precedent_all_var, + 'total_incasari_all': total_incasari_all_var, + 'total_plati_all': total_plati_all_var + } + if use_param_period: + totals_params['param_an'] = filter_params.an + totals_params['param_luna'] = filter_params.luna + + cursor.execute(totals_plsql, totals_params) + + sold_precedent_all = Decimal(str(sold_precedent_all_var.getvalue() or 0)) + total_incasari_all = Decimal(str(total_incasari_all_var.getvalue() or 0)) + total_plati_all = Decimal(str(total_plati_all_var.getvalue() or 0)) + sold_final_all = sold_precedent_all + total_incasari_all - total_plati_all + # Procesare rezultate registers = [] total_incasari = Decimal('0.00') @@ -288,7 +340,12 @@ class TreasuryService: page=filter_params.page, page_size=filter_params.page_size, has_more=len(registers) == filter_params.page_size, - accounting_period=AccountingPeriod(an=accounting_year, luna=accounting_month) + accounting_period=AccountingPeriod(an=accounting_year, luna=accounting_month), + # Totaluri din TOATE înregistrările filtrate + sold_precedent_all=sold_precedent_all, + total_incasari_all=total_incasari_all, + total_plati_all=total_plati_all, + sold_final_all=sold_final_all ) @staticmethod diff --git a/reports-app/backend/app/services/trial_balance_service.py b/reports-app/backend/app/services/trial_balance_service.py index a33667f..7fd8132 100644 --- a/reports-app/backend/app/services/trial_balance_service.py +++ b/reports-app/backend/app/services/trial_balance_service.py @@ -135,6 +135,29 @@ class TrialBalanceService: cursor.execute(count_query, params) total_count = cursor.fetchone()[0] + # Query pentru TOTALURI din TOATE înregistrările filtrate (nu doar pagina curentă) + totals_query = f""" + SELECT + NVL(SUM(PRECDEB), 0) as total_prec_deb, + NVL(SUM(PRECCRED), 0) as total_prec_cred, + NVL(SUM(RULDEB), 0) as total_rul_deb, + NVL(SUM(RULCRED), 0) as total_rul_cred, + NVL(SUM(SOLDDEB), 0) as total_sold_deb, + NVL(SUM(SOLDCRED), 0) as total_sold_cred + FROM ({base_query}) + """ + cursor.execute(totals_query, params) + totals_row = cursor.fetchone() + + totals = { + "total_sold_precedent_debit": Decimal(str(totals_row[0])) if totals_row else Decimal('0.00'), + "total_sold_precedent_credit": Decimal(str(totals_row[1])) if totals_row else Decimal('0.00'), + "total_rulaj_lunar_debit": Decimal(str(totals_row[2])) if totals_row else Decimal('0.00'), + "total_rulaj_lunar_credit": Decimal(str(totals_row[3])) if totals_row else Decimal('0.00'), + "total_sold_final_debit": Decimal(str(totals_row[4])) if totals_row else Decimal('0.00'), + "total_sold_final_credit": Decimal(str(totals_row[5])) if totals_row else Decimal('0.00') + } + # Add sorting base_query += f" ORDER BY {sort_by.upper()} {sort_order.upper()}" @@ -189,5 +212,7 @@ class TrialBalanceService: "an": an, "cont_filter": cont_filter, "denumire_filter": denumire_filter - } + }, + # Totaluri din TOATE înregistrările filtrate (nu doar pagina curentă) + "totals": totals } diff --git a/reports-app/frontend/src/stores/invoices.js b/reports-app/frontend/src/stores/invoices.js index f240295..3dbf7f1 100644 --- a/reports-app/frontend/src/stores/invoices.js +++ b/reports-app/frontend/src/stores/invoices.js @@ -8,6 +8,8 @@ export const useInvoicesStore = defineStore("invoices", () => { const isLoading = ref(false); const error = ref(null); const accountingPeriod = ref({ an: null, luna: null }); + // Total sold din TOATE facturile filtrate (nu doar pagina curentă) + const totalSoldAll = ref(0); const filters = ref({ company: null, type: "CLIENTI", // CLIENTI or FURNIZORI @@ -106,6 +108,9 @@ export const useInvoicesStore = defineStore("invoices", () => { invoices.value = response.data.invoices || []; pagination.value.totalRecords = response.data.total_count || 0; + // Store total sold from ALL filtered invoices (not just current page) + totalSoldAll.value = response.data.total_sold_all || 0; + // Store accounting period if available if (response.data.accounting_period) { accountingPeriod.value = response.data.accounting_period; @@ -152,6 +157,7 @@ export const useInvoicesStore = defineStore("invoices", () => { isLoading.value = false; error.value = null; accountingPeriod.value = { an: null, luna: null }; + totalSoldAll.value = 0; clearFilters(); pagination.value = { page: 1, @@ -170,6 +176,7 @@ export const useInvoicesStore = defineStore("invoices", () => { isLoading, error, accountingPeriod, + totalSoldAll, filters, pagination, diff --git a/reports-app/frontend/src/stores/treasury.js b/reports-app/frontend/src/stores/treasury.js index e1b9be7..5c21388 100644 --- a/reports-app/frontend/src/stores/treasury.js +++ b/reports-app/frontend/src/stores/treasury.js @@ -14,6 +14,11 @@ export const useTreasuryStore = defineStore("treasury", () => { const totals = ref({ total_incasari: 0, total_plati: 0, + // Totaluri din TOATE înregistrările filtrate (nu doar pagina curentă) + sold_precedent_all: 0, + total_incasari_all: 0, + total_plati_all: 0, + sold_final_all: 0, }); const accountingPeriod = ref({ an: null, luna: null }); @@ -38,6 +43,11 @@ export const useTreasuryStore = defineStore("treasury", () => { totals.value = { total_incasari: response.data.total_incasari, total_plati: response.data.total_plati, + // Totaluri din TOATE înregistrările filtrate (nu doar pagina curentă) + sold_precedent_all: response.data.sold_precedent_all || 0, + total_incasari_all: response.data.total_incasari_all || 0, + total_plati_all: response.data.total_plati_all || 0, + sold_final_all: response.data.sold_final_all || 0, }; // Store accounting period if available diff --git a/reports-app/frontend/src/stores/trialBalance.js b/reports-app/frontend/src/stores/trialBalance.js index c406ca9..d252234 100644 --- a/reports-app/frontend/src/stores/trialBalance.js +++ b/reports-app/frontend/src/stores/trialBalance.js @@ -11,6 +11,16 @@ export const useTrialBalanceStore = defineStore("trialBalance", () => { const isLoading = ref(false); const error = ref(null); + // Totaluri din TOATE înregistrările filtrate (nu doar pagina curentă) + const totals = ref({ + total_sold_precedent_debit: 0, + total_sold_precedent_credit: 0, + total_rulaj_lunar_debit: 0, + total_rulaj_lunar_credit: 0, + total_sold_final_debit: 0, + total_sold_final_credit: 0, + }); + const filters = ref({ luna: new Date().getMonth() + 1, // Current month (1-12) an: new Date().getFullYear(), // Current year @@ -83,6 +93,11 @@ export const useTrialBalanceStore = defineStore("trialBalance", () => { totalPages: paginationData.total_pages, }; + // Store totals from ALL filtered records (not just current page) + if (response.data.data.totals) { + totals.value = response.data.data.totals; + } + return { success: true }; } else { throw new Error("Invalid response format"); @@ -146,6 +161,14 @@ export const useTrialBalanceStore = defineStore("trialBalance", () => { trialBalanceData.value = []; isLoading.value = false; error.value = null; + totals.value = { + total_sold_precedent_debit: 0, + total_sold_precedent_credit: 0, + total_rulaj_lunar_debit: 0, + total_rulaj_lunar_credit: 0, + total_sold_final_debit: 0, + total_sold_final_credit: 0, + }; filters.value = { luna: new Date().getMonth() + 1, an: new Date().getFullYear(), @@ -169,6 +192,7 @@ export const useTrialBalanceStore = defineStore("trialBalance", () => { trialBalanceData, isLoading, error, + totals, filters, pagination, sorting, diff --git a/reports-app/frontend/src/views/BankCashRegisterView.vue b/reports-app/frontend/src/views/BankCashRegisterView.vue index c0871b0..6ac9276 100644 --- a/reports-app/frontend/src/views/BankCashRegisterView.vue +++ b/reports-app/frontend/src/views/BankCashRegisterView.vue @@ -115,33 +115,34 @@ +
Sold Precedent: {{ formatCurrency(computedTotals.soldPrecedent) }}{{ formatCurrency(treasuryStore.totals.sold_precedent_all) }}
Încasări: {{ - formatCurrency(computedTotals.incasari) + formatCurrency(treasuryStore.totals.total_incasari_all) }}
Plăți: {{ - formatCurrency(computedTotals.plati) + formatCurrency(treasuryStore.totals.total_plati_all) }}
Sold Final: {{ formatCurrency(computedTotals.soldFinal) }}{{ formatCurrency(treasuryStore.totals.sold_final_all) }}
@@ -325,34 +326,6 @@ const truncateText = (text, maxLength = 100) => { return text.substring(0, maxLength) + "..."; }; -// Computed totals - separate sold precedent from actual transactions -// Rows with dataact = null are opening balances (sold precedent) -const computedTotals = computed(() => { - let soldPrecedent = 0; - let incasari = 0; - let plati = 0; - - treasuryStore.registers.forEach((row) => { - if (row.dataact === null || row.dataact === undefined) { - // Opening balance row - the sold value is the opening balance - soldPrecedent += parseFloat(row.sold) || 0; - } else { - // Transaction row - incasari += parseFloat(row.incasari) || 0; - plati += parseFloat(row.plati) || 0; - } - }); - - const soldFinal = soldPrecedent + incasari - plati; - - return { - soldPrecedent, - incasari, - plati, - soldFinal, - }; -}); - // Check if current filter is a VALUTA type (to show Valuta column) const isValutaType = computed(() => { return ( diff --git a/reports-app/frontend/src/views/InvoicesView.vue b/reports-app/frontend/src/views/InvoicesView.vue index 607d97f..5de2ca0 100644 --- a/reports-app/frontend/src/views/InvoicesView.vue +++ b/reports-app/frontend/src/views/InvoicesView.vue @@ -128,6 +128,17 @@ + + +
+
+ Total Sold: + + {{ formatCurrency(invoicesStore.totalSoldAll) }} + +
+
+ - - -
- Total Sold: - {{ - formatCurrency(totalSold) - }} -
@@ -272,12 +275,6 @@ const pagination = ref({ }); // Computed -const totalSold = computed(() => { - return invoicesStore.invoiceList.reduce((sum, invoice) => { - return sum + (parseFloat(invoice.soldfinal) || 0); - }, 0); -}); - const accountingPeriodText = computed(() => { // Use the global period store return periodStore.selectedPeriod?.display_name || ""; @@ -739,29 +736,6 @@ watch( display: block; } -.total-sold { - display: flex; - justify-content: flex-end; - align-items: center; - gap: 1rem; - padding: 1rem; - margin-top: 1rem; - border-top: 2px solid var(--surface-border); - background-color: var(--surface-50); -} - -.total-sold-label { - font-weight: 600; - font-size: 1.1rem; - color: var(--text-color); -} - -.total-sold-value { - font-weight: 700; - font-size: 1.3rem; - color: var(--primary-color); -} - /* Enhanced striped rows with better contrast - same as Trial Balance */ .table-card :deep(.p-datatable .p-datatable-tbody > tr) { transition: background-color 0.2s ease; diff --git a/reports-app/frontend/src/views/TrialBalanceView.vue b/reports-app/frontend/src/views/TrialBalanceView.vue index 6160a62..b336709 100644 --- a/reports-app/frontend/src/views/TrialBalanceView.vue +++ b/reports-app/frontend/src/views/TrialBalanceView.vue @@ -97,6 +97,35 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + +
Sold PrecedentRulaj LunarSold Final
Debit{{ formatCurrency(trialBalanceStore.totals.total_sold_precedent_debit) }}{{ formatCurrency(trialBalanceStore.totals.total_rulaj_lunar_debit) }}{{ formatCurrency(trialBalanceStore.totals.total_sold_final_debit) }}
Credit{{ formatCurrency(trialBalanceStore.totals.total_sold_precedent_credit) }}{{ formatCurrency(trialBalanceStore.totals.total_rulaj_lunar_credit) }}{{ formatCurrency(trialBalanceStore.totals.total_sold_final_credit) }}
+
+