Files
sam-manage/app/Models/Finance/JournalEntry.php
김보곤 34788e854c feat:일반전표입력 페이지 전면 개편 - 계좌입출금 기반 분개 시스템
- 3탭 구조로 전면 재작성 (은행거래분개, 수동전표, 전표목록)
- JournalEntryController에 bankTransactions, storeFromBank, bankJournals, deleteBankJournal API 추가
- JournalEntry 모델에 source_type, source_key fillable 및 헬퍼 메서드 추가
- 은행거래 목록에서 분개 모달로 복식부기 전표 생성
- 입금/출금에 따라 보통예금(103) 자동 세팅
- 분개 완료/미분개 상태 표시 및 필터링
- 기존 수동전표, 전표목록 기능 그대로 유지

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-10 17:58:33 +09:00

98 lines
2.5 KiB
PHP

<?php
namespace App\Models\Finance;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Support\Facades\DB;
class JournalEntry extends Model
{
use SoftDeletes;
protected $table = 'journal_entries';
protected $fillable = [
'tenant_id',
'entry_no',
'entry_date',
'entry_type',
'description',
'total_debit',
'total_credit',
'status',
'source_type',
'source_key',
'created_by_name',
'attachment_note',
];
protected $casts = [
'entry_date' => 'date',
'total_debit' => 'integer',
'total_credit' => 'integer',
];
public function lines()
{
return $this->hasMany(JournalEntryLine::class)->orderBy('line_no');
}
public function scopeForTenant($query, $tenantId)
{
return $query->where('tenant_id', $tenantId);
}
/**
* 분개 완료된 source_key 일괄 조회
*/
public static function getJournaledSourceKeys(int $tenantId, string $sourceType, array $sourceKeys): array
{
if (empty($sourceKeys)) {
return [];
}
return static::where('tenant_id', $tenantId)
->where('source_type', $sourceType)
->whereIn('source_key', $sourceKeys)
->pluck('source_key')
->toArray();
}
/**
* source_key로 분개 전표 조회 (ID 포함)
*/
public static function getJournalBySourceKey(int $tenantId, string $sourceType, string $sourceKey)
{
return static::where('tenant_id', $tenantId)
->where('source_type', $sourceType)
->where('source_key', $sourceKey)
->first();
}
/**
* 전표번호 자동채번: JE-YYYYMMDD-NNN
*/
public static function generateEntryNo($tenantId, $date)
{
$dateStr = date('Ymd', strtotime($date));
$prefix = "JE-{$dateStr}-";
// withTrashed: soft-deleted 레코드도 포함하여 채번 (DB unique 제약 충돌 방지)
$last = static::withTrashed()
->where('tenant_id', $tenantId)
->where('entry_no', 'like', $prefix . '%')
->lockForUpdate()
->orderByDesc('entry_no')
->value('entry_no');
if ($last) {
$seq = (int) substr($last, -3) + 1;
} else {
$seq = 1;
}
return $prefix . str_pad($seq, 3, '0', STR_PAD_LEFT);
}
}