Corin1998 commited on
Commit
975ceb1
·
verified ·
1 Parent(s): f4b2b34

Upload main.py

Browse files
Files changed (1) hide show
  1. main.py +21 -15
main.py CHANGED
@@ -122,6 +122,7 @@ class Invoice(SQLModel, table=True):
122
  due_date: Optional[date] = None
123
  notes: Optional[str] = None
124
 
 
125
  paid_at: Optional[datetime] = None
126
  paid_amount: Optional[float] = None
127
  payment_method: Optional[str] = None
@@ -158,6 +159,7 @@ class CreateInvoiceIn(BaseModel):
158
  customer_id: int
159
  due_date: Optional[date] = None
160
  notes: Optional[str] = None
 
161
  quote_id: Optional[int] = None
162
 
163
  class InvoiceItemIn(BaseModel):
@@ -286,7 +288,6 @@ def create_customer(payload: Customer, session: Session = Depends(get_session)):
286
  session.add(payload); session.commit(); session.refresh(payload)
287
  return payload
288
 
289
- # ---- Customers 一覧APIの置き換え ----
290
  @app.get("/customers", dependencies=[Depends(require_api_key)])
291
  def list_customers(
292
  q: Optional[str] = Query(default=None, description="free text search (name/email/phone)"),
@@ -294,25 +295,30 @@ def list_customers(
294
  offset: int = Query(0, ge=0),
295
  session: Session = Depends(get_session),
296
  ):
297
- stmt = select(Customer)
 
 
 
298
  if q:
299
  like = f"%{q}%"
300
- stmt = stmt.where(
301
  (Customer.name.ilike(like)) |
302
  (Customer.email.ilike(like)) |
303
  (Customer.phone.ilike(like))
304
  )
305
- # 修正済み:余計なインデントを削除
306
- total = session.exec(select(func.count()).select_from(stmt.subquery())).scalar_one()
307
- rows = session.exec(stmt.offset(offset).limit(limit)).all()
 
 
308
  return {"data": rows, "pagination": {"total": total, "limit": limit, "offset": offset}}
 
309
  # -------- Products --------
310
  @app.post("/products", dependencies=[Depends(require_api_key)])
311
  def create_product(payload: Product, session: Session = Depends(get_session)):
312
  session.add(payload); session.commit(); session.refresh(payload)
313
  return payload
314
 
315
- # ---- Products 一覧APIの total も同様に修正 ----
316
  @app.get("/products", dependencies=[Depends(require_api_key)])
317
  def list_products(
318
  limit: int = Query(50, ge=1, le=200),
@@ -320,7 +326,7 @@ def list_products(
320
  session: Session = Depends(get_session),
321
  ):
322
  base = select(Product)
323
- total = session.exec(select(func.count()).select_from(base.subquery())).scalar_one()
324
  rows = session.exec(base.offset(offset).limit(limit)).all()
325
  return {"data": rows, "pagination": {"total": total, "limit": limit, "offset": offset}}
326
 
@@ -365,21 +371,21 @@ def create_invoice(payload: CreateInvoiceIn, session: Session = Depends(get_sess
365
  inv = Invoice(customer_id=payload.customer_id, due_date=payload.due_date, notes=payload.notes)
366
  session.add(inv); session.commit(); session.refresh(inv)
367
 
 
368
  if payload.quote_id:
369
  q = session.get(Quote, payload.quote_id)
370
  if not q:
371
  raise HTTPException(404, "Quote not found to copy")
372
  q_items = session.exec(select(QuoteItem).where(QuoteItem.quote_id == payload.quote_id)).all()
373
  for it in q_items:
374
- new_item = InvoiceItem(
375
  invoice_id=inv.id,
376
  product_id=it.product_id,
377
  description=it.description,
378
  quantity=it.quantity,
379
  unit_price=it.unit_price,
380
  tax_rate=it.tax_rate,
381
- )
382
- session.add(new_item)
383
  session.commit()
384
 
385
  session.refresh(inv)
@@ -510,10 +516,10 @@ def wizard_create_invoice(payload: WizardInvoiceIn, session: Session = Depends(g
510
  except Exception as e:
511
  raise HTTPException(400, f"Wizard failed: {e}")
512
 
513
- # ---- ルート(UI ----
514
- @app.get("/", response_class=FileResponse)
515
- def root_ui():
516
- return FileResponse("static/app.html")
517
 
518
  # -------- ChatGPT router(最後に組み込む) --------
519
  from openai_integration import router as ai_router
 
122
  due_date: Optional[date] = None
123
  notes: Optional[str] = None
124
 
125
+ # 入金関連
126
  paid_at: Optional[datetime] = None
127
  paid_amount: Optional[float] = None
128
  payment_method: Optional[str] = None
 
159
  customer_id: int
160
  due_date: Optional[date] = None
161
  notes: Optional[str] = None
162
+ # 見積→請求コピー用
163
  quote_id: Optional[int] = None
164
 
165
  class InvoiceItemIn(BaseModel):
 
288
  session.add(payload); session.commit(); session.refresh(payload)
289
  return payload
290
 
 
291
  @app.get("/customers", dependencies=[Depends(require_api_key)])
292
  def list_customers(
293
  q: Optional[str] = Query(default=None, description="free text search (name/email/phone)"),
 
295
  offset: int = Query(0, ge=0),
296
  session: Session = Depends(get_session),
297
  ):
298
+ # 件数とデータ取得を素直に分ける(環境依存の例外を回避)
299
+ base = select(Customer)
300
+ count_stmt = select(func.count(Customer.id))
301
+
302
  if q:
303
  like = f"%{q}%"
304
+ cond = (
305
  (Customer.name.ilike(like)) |
306
  (Customer.email.ilike(like)) |
307
  (Customer.phone.ilike(like))
308
  )
309
+ base = base.where(cond)
310
+ count_stmt = count_stmt.where(cond)
311
+
312
+ total = session.exec(count_stmt).scalar() or 0
313
+ rows = session.exec(base.offset(offset).limit(limit)).all()
314
  return {"data": rows, "pagination": {"total": total, "limit": limit, "offset": offset}}
315
+
316
  # -------- Products --------
317
  @app.post("/products", dependencies=[Depends(require_api_key)])
318
  def create_product(payload: Product, session: Session = Depends(get_session)):
319
  session.add(payload); session.commit(); session.refresh(payload)
320
  return payload
321
 
 
322
  @app.get("/products", dependencies=[Depends(require_api_key)])
323
  def list_products(
324
  limit: int = Query(50, ge=1, le=200),
 
326
  session: Session = Depends(get_session),
327
  ):
328
  base = select(Product)
329
+ total = session.exec(select(func.count(Product.id))).scalar() or 0
330
  rows = session.exec(base.offset(offset).limit(limit)).all()
331
  return {"data": rows, "pagination": {"total": total, "limit": limit, "offset": offset}}
332
 
 
371
  inv = Invoice(customer_id=payload.customer_id, due_date=payload.due_date, notes=payload.notes)
372
  session.add(inv); session.commit(); session.refresh(inv)
373
 
374
+ # 見積→請求コピー
375
  if payload.quote_id:
376
  q = session.get(Quote, payload.quote_id)
377
  if not q:
378
  raise HTTPException(404, "Quote not found to copy")
379
  q_items = session.exec(select(QuoteItem).where(QuoteItem.quote_id == payload.quote_id)).all()
380
  for it in q_items:
381
+ session.add(InvoiceItem(
382
  invoice_id=inv.id,
383
  product_id=it.product_id,
384
  description=it.description,
385
  quantity=it.quantity,
386
  unit_price=it.unit_price,
387
  tax_rate=it.tax_rate,
388
+ ))
 
389
  session.commit()
390
 
391
  session.refresh(inv)
 
516
  except Exception as e:
517
  raise HTTPException(400, f"Wizard failed: {e}")
518
 
519
+ # ---- ルート(UI を /app に任せつつ、/ は API の案内) ----
520
+ @app.get("/")
521
+ def root():
522
+ return {"ok": True, "app": "mini-invoice-saas", "docs": "/docs", "ui": "/app/"}
523
 
524
  # -------- ChatGPT router(最後に組み込む) --------
525
  from openai_integration import router as ai_router