83 lines
3.0 KiB
PHP
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;
|
|
}
|
|
}
|