Files
accounting_dev_v2/application/libraries/NumberingService.php
T
2026-09-11 16:03:00 +07:00

83 lines
3.0 KiB
PHP

<?php
defined('BASEPATH') OR exit('No direct script access allowed');
require_once APPPATH . 'exceptions/BusinessException.php';
class NumberingService
{
private $CI;
private $sequenceTableAvailable;
public function __construct()
{
$this->CI =& get_instance();
$this->CI->config->load('accounting', true);
$this->CI->load->library('CompanyContext');
$this->sequenceTableAvailable = $this->CI->db->table_exists('document_sequences');
}
public function next($type, $date = null)
{
$date = $date ?: date('Y-m-d');
$timestamp = strtotime($date);
if ($timestamp === false) {
throw new BusinessException('Tanggal penomoran dokumen tidak valid.');
}
$settings = (array) $this->CI->config->item('document_numbering', 'accounting');
if (!isset($settings[$type])) {
throw new BusinessException('Jenis penomoran "' . $type . '" belum dikonfigurasi.');
}
$prefix = $settings[$type]['prefix'] . '-' . date('Ymd', $timestamp) . '-';
$padding = (int) $settings[$type]['padding'];
$period = date('Ymd', $timestamp);
if ($this->sequenceTableAvailable) {
$initialValue = $this->nextLegacyValue($type, $prefix);
$number = $this->nextAtomicValue($type, $period, $prefix, $initialValue);
} else {
$number = $this->nextLegacyValue($type, $prefix);
}
return $prefix . str_pad($number, $padding, '0', STR_PAD_LEFT);
}
private function nextAtomicValue($type, $period, $prefix, $initialValue)
{
$companyId = (int) $this->CI->companycontext->id();
$sql = 'INSERT INTO document_sequences (company_id, document_type, period_key, prefix, current_value, updated_at) '
. 'VALUES (?, ?, ?, ?, ?, NOW()) '
. 'ON DUPLICATE KEY UPDATE prefix = VALUES(prefix), current_value = LAST_INSERT_ID(current_value + 1), updated_at = NOW()';
if (!$this->CI->db->query($sql, array($companyId, $type, $period, $prefix, $initialValue))) {
throw new RuntimeException('Gagal mengambil nomor dokumen berikutnya.');
}
if ($this->CI->db->affected_rows() === 1) {
return (int) $initialValue;
}
return (int) $this->CI->db->insert_id();
}
private function nextLegacyValue($type, $prefix)
{
$source = $type === 'invoice' ? array('invoices', 'no_invoice') : array('journals', 'no_ref');
$builder = $this->CI->db->select($source[1]);
if ($this->CI->db->field_exists('company_id', $source[0])) $builder->where('company_id', (int)$this->CI->companycontext->id());
$row = $builder->like($source[1], $prefix, 'after')
->order_by($source[1], 'DESC')
->limit(1)
->get($source[0])
->row();
if (!$row) {
return 1;
}
$value = $row->{$source[1]};
return ((int) substr($value, strlen($prefix))) + 1;
}
}