feat: 매출/매입 관리 API 구현

- 매출(Sale) 및 매입(Purchase) CRUD API 구현
- 문서번호 자동 생성 (SL/PU + YYYYMMDD + 시퀀스)
- 상태 관리 (draft → confirmed → invoiced)
- 확정(confirm) 및 요약(summary) 기능 추가
- BelongsToTenant, SoftDeletes 적용
- Swagger API 문서 작성 완료

추가된 파일:
- 마이그레이션: sales, purchases 테이블
- 모델: Sale, Purchase
- 서비스: SaleService, PurchaseService
- 컨트롤러: SaleController, PurchaseController
- FormRequest: Store/Update 4개
- Swagger: SaleApi.php, PurchaseApi.php

API 엔드포인트 (14개):
- GET/POST /v1/sales, /v1/purchases
- GET/PUT/DELETE /v1/{sales,purchases}/{id}
- POST /v1/{sales,purchases}/{id}/confirm
- GET /v1/{sales,purchases}/summary
This commit is contained in:
2025-12-17 22:14:48 +09:00
parent 0eb9fb8501
commit cbed92a95c
16 changed files with 2022 additions and 10 deletions

View File

@@ -4,7 +4,9 @@
use App\Http\Controllers\Api\V1\AdminController;
use App\Http\Controllers\Api\V1\ApiController;
use App\Http\Controllers\Api\V1\AttendanceController;
use App\Http\Controllers\Api\V1\BankAccountController;
use App\Http\Controllers\Api\V1\BoardController;
use App\Http\Controllers\Api\V1\CardController;
use App\Http\Controllers\Api\V1\CategoryController;
use App\Http\Controllers\Api\V1\CategoryFieldController;
use App\Http\Controllers\Api\V1\CategoryLogController;
@@ -14,6 +16,7 @@
use App\Http\Controllers\Api\V1\ClientGroupController;
use App\Http\Controllers\Api\V1\CommonController;
use App\Http\Controllers\Api\V1\DepartmentController;
use App\Http\Controllers\Api\V1\DepositController;
use App\Http\Controllers\Api\V1\Design\AuditLogController as DesignAuditLogController;
use App\Http\Controllers\Api\V1\Design\BomCalculationController;
use App\Http\Controllers\Api\V1\Design\BomTemplateController as DesignBomTemplateController;
@@ -35,35 +38,34 @@
use App\Http\Controllers\Api\V1\ItemsBomController;
use App\Http\Controllers\Api\V1\ItemsController;
use App\Http\Controllers\Api\V1\ItemsFileController;
// use App\Http\Controllers\Api\V1\MaterialController; // REMOVED: materials 테이블 삭제됨
use App\Http\Controllers\Api\V1\LeaveController;
use App\Http\Controllers\Api\V1\MenuController;
use App\Http\Controllers\Api\V1\ModelSetController;
// use App\Http\Controllers\Api\V1\MaterialController; // REMOVED: materials 테이블 삭제됨
use App\Http\Controllers\Api\V1\PermissionController;
use App\Http\Controllers\Api\V1\PostController;
use App\Http\Controllers\Api\V1\PricingController;
use App\Http\Controllers\Api\V1\QuoteController;
use App\Http\Controllers\Api\V1\RefreshController;
// use App\Http\Controllers\Api\V1\ProductBomItemController; // REMOVED: products 테이블 삭제됨
// use App\Http\Controllers\Api\V1\ProductController; // REMOVED: products 테이블 삭제됨
use App\Http\Controllers\Api\V1\PricingController;
use App\Http\Controllers\Api\V1\PurchaseController;
use App\Http\Controllers\Api\V1\QuoteController;
use App\Http\Controllers\Api\V1\RefreshController;
use App\Http\Controllers\Api\V1\RegisterController;
use App\Http\Controllers\Api\V1\RoleController;
use App\Http\Controllers\Api\V1\RolePermissionController;
use App\Http\Controllers\Api\V1\BankAccountController;
use App\Http\Controllers\Api\V1\CardController;
use App\Http\Controllers\Api\V1\DepositController;
use App\Http\Controllers\Api\V1\WithdrawalController;
use App\Http\Controllers\Api\V1\SaleController;
use App\Http\Controllers\Api\V1\SiteController;
use App\Http\Controllers\Api\V1\TenantController;
use App\Http\Controllers\Api\V1\TenantFieldSettingController;
// 설계 전용 (디자인 네임스페이스)
use App\Http\Controllers\Api\V1\TenantOptionGroupController;
// 설계 전용 (디자인 네임스페이스)
use App\Http\Controllers\Api\V1\TenantOptionValueController;
use App\Http\Controllers\Api\V1\TenantStatFieldController;
use App\Http\Controllers\Api\V1\TenantUserProfileController;
use App\Http\Controllers\Api\V1\UserController;
// 모델셋 관리 (견적 시스템)
use App\Http\Controllers\Api\V1\UserRoleController;
// 모델셋 관리 (견적 시스템)
use App\Http\Controllers\Api\V1\WithdrawalController;
use App\Http\Controllers\Api\V1\WorkSettingController;
use Illuminate\Support\Facades\Route;
@@ -316,6 +318,28 @@
Route::delete('/{id}', [WithdrawalController::class, 'destroy'])->whereNumber('id')->name('v1.withdrawals.destroy');
});
// Sale API (매출 관리)
Route::prefix('sales')->group(function () {
Route::get('', [SaleController::class, 'index'])->name('v1.sales.index');
Route::post('', [SaleController::class, 'store'])->name('v1.sales.store');
Route::get('/summary', [SaleController::class, 'summary'])->name('v1.sales.summary');
Route::get('/{id}', [SaleController::class, 'show'])->whereNumber('id')->name('v1.sales.show');
Route::put('/{id}', [SaleController::class, 'update'])->whereNumber('id')->name('v1.sales.update');
Route::delete('/{id}', [SaleController::class, 'destroy'])->whereNumber('id')->name('v1.sales.destroy');
Route::post('/{id}/confirm', [SaleController::class, 'confirm'])->whereNumber('id')->name('v1.sales.confirm');
});
// Purchase API (매입 관리)
Route::prefix('purchases')->group(function () {
Route::get('', [PurchaseController::class, 'index'])->name('v1.purchases.index');
Route::post('', [PurchaseController::class, 'store'])->name('v1.purchases.store');
Route::get('/summary', [PurchaseController::class, 'summary'])->name('v1.purchases.summary');
Route::get('/{id}', [PurchaseController::class, 'show'])->whereNumber('id')->name('v1.purchases.show');
Route::put('/{id}', [PurchaseController::class, 'update'])->whereNumber('id')->name('v1.purchases.update');
Route::delete('/{id}', [PurchaseController::class, 'destroy'])->whereNumber('id')->name('v1.purchases.destroy');
Route::post('/{id}/confirm', [PurchaseController::class, 'confirm'])->whereNumber('id')->name('v1.purchases.confirm');
});
// Permission API
Route::prefix('permissions')->group(function () {
Route::get('departments/{dept_id}/menu-matrix', [PermissionController::class, 'deptMenuMatrix'])->name('v1.permissions.deptMenuMatrix'); // 부서별 권한 메트릭스