from datetime import date, timedelta from sqlalchemy import Integer, extract, or_, func, cast from app.models.invoice import Invoice, InvoiceStatus, InvoiceType from app.services.company_service import CompanyService class InvoiceRepository: def base_query(self, company_id=None): if company_id is None: company = CompanyService.get_current_company() company_id = company.id if company else None query = Invoice.query if company_id: query = query.filter(Invoice.company_id == company_id) return query def incoming_query(self, company_id=None): query = self.base_query(company_id) return query.filter( Invoice.invoice_type != InvoiceType.SALE, ~Invoice.source.in_(['issued', 'nfz']), ) def query_filtered(self, form_data, company_id=None): query = self.incoming_query(company_id) month = form_data.get('month') year = form_data.get('year') quick_filter = form_data.get('quick_filter') min_amount = form_data.get('min_amount') max_amount = form_data.get('max_amount') if month: query = query.filter(extract('month', Invoice.issue_date) == int(month)) if year: query = query.filter(extract('year', Invoice.issue_date) == int(year)) if form_data.get('contractor'): query = query.filter(Invoice.contractor_name.ilike(f"%{form_data['contractor']}%")) if form_data.get('nip'): query = query.filter(Invoice.contractor_nip.ilike(f"%{form_data['nip']}%")) if form_data.get('invoice_type'): query = query.filter(Invoice.invoice_type == InvoiceType(form_data['invoice_type'])) if form_data.get('status'): query = query.filter(Invoice.status == InvoiceStatus(form_data['status'])) if min_amount: query = query.filter(Invoice.gross_amount >= float(min_amount)) if max_amount: query = query.filter(Invoice.gross_amount <= float(max_amount)) if form_data.get('search'): term = f"%{form_data['search']}%" query = query.filter(or_(Invoice.invoice_number.ilike(term), Invoice.ksef_number.ilike(term), Invoice.contractor_name.ilike(term), Invoice.contractor_nip.ilike(term))) today = date.today() if quick_filter == 'this_month': query = query.filter(extract('month', Invoice.issue_date) == today.month, extract('year', Invoice.issue_date) == today.year) elif quick_filter == 'previous_month': prev = today.replace(day=1) - timedelta(days=1) query = query.filter(extract('month', Invoice.issue_date) == prev.month, extract('year', Invoice.issue_date) == prev.year) elif quick_filter == 'unread': query = query.filter(Invoice.is_unread.is_(True)) elif quick_filter == 'error': query = query.filter(Invoice.status == InvoiceStatus.ERROR) elif quick_filter == 'to_send': query = query.filter(Invoice.status.in_([InvoiceStatus.NEW, InvoiceStatus.READ])) return query.order_by(Invoice.issue_date.desc(), Invoice.id.desc()) def get_by_ksef_number(self, ksef_number, company_id=None): return self.base_query(company_id).filter_by(ksef_number=ksef_number).first() def monthly_summary(self, company_id=None): return self.base_query(company_id).with_entities( extract('year', Invoice.issue_date).label('year'), extract('month', Invoice.issue_date).label('month'), func.count(Invoice.id).label('count'), func.sum(Invoice.net_amount).label('net'), func.sum(Invoice.vat_amount).label('vat'), func.sum(Invoice.gross_amount).label('gross'), ).group_by('year', 'month').order_by(extract('year', Invoice.issue_date).desc(), extract('month', Invoice.issue_date).desc()).all() def summary_query(self, company_id=None, *, period='month', search=None): query = self.base_query(company_id) if search: like = f'%{search}%' query = query.filter(or_( Invoice.invoice_number.ilike(like), Invoice.ksef_number.ilike(like), Invoice.contractor_name.ilike(like), Invoice.contractor_nip.ilike(like), )) year_expr = extract('year', Invoice.issue_date) month_expr = extract('month', Invoice.issue_date) quarter_expr = ((month_expr - 1) / 3 + 1) columns = [ year_expr.label('year'), func.count(Invoice.id).label('count'), func.sum(Invoice.net_amount).label('net'), func.sum(Invoice.vat_amount).label('vat'), func.sum(Invoice.gross_amount).label('gross'), ] group_by = [year_expr] order_by = [year_expr.desc()] if period == 'month': columns.append(month_expr.label('month')) group_by.append(month_expr) order_by.append(month_expr.desc()) elif period == 'quarter': quarter_cast = cast(quarter_expr, Integer) columns.append(quarter_cast.label('quarter')) group_by.append(quarter_cast) order_by.append(quarter_cast.desc()) return query.with_entities(*columns).group_by(*group_by).order_by(*order_by).all()