109 lines
5.3 KiB
Python
109 lines
5.3 KiB
Python
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()
|