Replace absolute/guarantee language with past-tense examples per tax association rules:
1️⃣ 사업자 기장 시 자주 하는 실수 5가지
❌ 제목: '50만 원 손해보는 이유'
✅ 변경: '혼자 하기 어려운 이유'
❌ '손해 70만 원'
✅ '이 사례에서는 약 70만 원 정도의 비용이 발생했습니다'
❌ '절세 50만 원'
✅ '정확한 기장으로 이러한 상황을 방지할 수 있었습니다'
❌ '240만 원 차이'
✅ '약 240만 원 정도의 차이가 있을 수 있습니다'
2️⃣ 이번달 부가가치세 신고
❌ '손해: 56,000원'
✅ '이 경우 약 56,000원 정도의 비용이 발생했습니다'
❌ '절약: 56,000원'
✅ '기한을 지키면 이를 방지할 수 있습니다'
3️⃣ 프리랜서를 위한 종합소득세 신고
❌ 'Line 34: 손해'
✅ '이 경우 많은 손해가 발생할 수 있습니다'
❌ '절약: 170만 원'
✅ '이 사례에서는 약 170만 원 정도의 효과를 볼 수 있었습니다'
❌ '세금 450만 원' (절약 보장)
✅ '약 450만 원' (사실 기술)
❌ '약 243만 원 정도의 차이'
✅ '약 243만 원 정도의 차이가 발생했을 수 있습니다'
All posts now comply with Korean Tax Association advertising rules:
✅ No absolute claims (절대 표현 제거)
✅ No guarantee language (보장 표현 제거)
✅ Past-tense examples only (과거 사례 중심)
✅ Possibility statements (가능성만 표현)
✅ Legal basis emphasized (법적 근거 강조)
V018 had PostgreSQL quote escaping issues with long content strings.
V019 uses 1256 quoting to avoid escaping problems and cleanly inserts
all 12 blog posts (5 updates + 7 new) with middle-school level language.
Deletes V018, commits V019 as replacement.
Architecture:
- Create companies table with company_code as unique identifier
- Add company_id foreign key to admin_users for multi-tenant support
- Implement backward compatibility with DEFAULT company for existing users
Core Components:
- Company entity with full CRUD operations
- ICompanyRepository interface following Repository pattern
- CompanyRepository with Dapper implementation
- CompanyService with business logic and validation
- CompanyController with REST API endpoints
Admin UI:
- CompanyForm reusable component (Create/Edit pattern)
- CompanyList.razor with pagination and company overview
- CompanyCreate.razor for registering new companies
- CompanyEdit.razor for managing existing companies with delete
- All pages follow admin-page-hero pattern for consistency
SOLID Principles:
- Single Responsibility: Each component has one reason to change
- Open/Closed: Extensible without modifying existing code
- Interface Segregation: Clean repository and service contracts
- Dependency Inversion: All layers depend on abstractions
Database Migration (V014):
- Creates companies table with active/inactive status
- Assigns existing admin users to DEFAULT company
- Provides foundation for role-based access control
Future Enhancement:
- Admin users can belong to specific companies
- Data filtering based on company_id (multi-tenant isolation)
- Company-based permission model
- Add Admin:PasswordResetToken configuration for secure password reset API
- Create V012 migration: Add test_admin account for E2E testing
- Create V013 migration: Ensure admin and test_admin accounts exist
- Use reset-password API endpoint instead of manual bcrypt hashing
- Test accounts now managed via API (not migrations/seeds)
Account setup:
- admin: Use reset-password API to set password
- test_admin: For E2E and Playwright testing
API Verification:
✅ POST /api/auth/login - test_admin login successful
✅ POST /api/auth/reset-password - Password reset working
✅ GET /api/inquiry - Returns 205 inquiries (test data)
✅ GET /api/faq - FAQ data accessible
✅ GET /api/admin/dashboard/summary - Dashboard API working
Data Note:
Local dev DB contains test data (205 inquiries from Playwright E2E tests).
Production server DB retains all customer data (not affected by local migrations).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Previously, responsive tests used the 'admin' production account,
which violates testing best practices and can contaminate live data.
Changes:
- Add test_admin account (password: test123456) to V003 migration
- Update all responsive test cases to use test_admin instead of admin
- Add setupTestData() helper for API-based test data preparation
- Improve test isolation and repeatability
- Document that test account is for development/testing only
Test improvements:
- Tests now use separate test_admin account
- Tests can run repeatedly without affecting production admin
- API layer ready for test data setup via authorization tokens
- Test data can be created/cleaned up programmatically
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- 연간 세무 캘린더(7개 시즌) 기반 자동 Hero 섹션 전환
- 시즌 감지 시 D-Day 카운트다운, 긴박감 배지, 시즌 CTA 표시
- 서비스 카드 순서 시즌 관련 항목 우선 정렬
- 어드민 공지사항 CRUD (등록·수정·삭제, 기간·유형 설정)
- 홈페이지 상단 공지 배너 자동 노출 (일반/배너/긴급)
- CLAUDE.md에 세무 캘린더 및 마케팅 방향 하네스 추가
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- MigrationRunner: 이미 존재하는 테이블에 대한 "relation already exists" 오류 처리
- V002, V003 마이그레이션: ON CONFLICT DO NOTHING으로 멱등성 보장
- Web, Admin Program.cs: app.UseAntiforgery() 미들웨어 추가 (anti-forgery 토큰 검증)
변경사항:
- 마이그레이션 재실행 시에도 안전하게 처리
- 폼 제출 시 CSRF 공격 방지
- 관리자 로그인 페이지 405 에러 해결
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- Change site description from '성북구 세무사' to nationwide professional
- Update positioning from '일상 자산 세금 파트너' to '맞춤형 세무 파트너'
- Replace Seongbuk-gu specificity with skill-based positioning
- Align with online-first service model (no local restriction)
- Update examples in documentation
Co-Authored-By: Claude <noreply@anthropic.com>