<?php
namespace App\Controllers\Admin;

use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Psr\Log\LoggerInterface;

use App\Controllers\BaseController;
use CodeIgniter\API\ResponseTrait;

use App\Libraries\Pluploadhandler;

use App\Models\Kkmodel;
use App\Models\Kolektormodel;
use App\Models\Operatormodel;
use App\Models\Tarifmodel;
use App\Models\Diskonmodel;
use App\Models\Invoicemodel;
use App\Models\Strukmodel;
use App\Models\Strukdetailmodel;
use App\Models\Transaksimodel;
use App\Models\Buktibayarmodel;
use App\Models\Jenispembayaranmodel;
// use App\Models\Tunggakanmodel;
use App\Models\Historytransmodel;

use Dompdf\Dompdf;
use Dompdf\Options;
use Endroid\QrCode\Color\Color;
use Endroid\QrCode\Encoding\Encoding;
use Endroid\QrCode\ErrorCorrectionLevel;
use Endroid\QrCode\QrCode;
use Endroid\QrCode\RoundBlockSizeMode;
use Endroid\QrCode\Writer\PngWriter;

class Transaksi extends BaseController
{
    use ResponseTrait;

    private $user;

    public function initController(RequestInterface $request, ResponseInterface $response, LoggerInterface $logger) 
    {
        parent::initController($request, $response, $logger);
        $this->user = service("user_data");
    }

    private function check_access(){
        $user = service("user_data");
        if($user->data->group != 'admin'){
            return false;
        }else{
            return true;
        }
    }

    public function index(){
        $data['user'] = $this->user->data;

        $db = db_connect();
        $data['total_draft'] = $db->table("transaksi")->where("flag_validasi","0")->countAllResults();
        $data['total_pending'] = $db->table("transaksi")->where("flag_validasi","1")->countAllResults();
        $data['total_completed'] = $db->table("transaksi")->where("flag_validasi","2")->countAllResults();
        $data['total_canceled'] = $db->table("transaksi")->where("flag_validasi","3")->countAllResults();

        return view('admin/transaksi/index',$data);
    }

    public function pending(){
        $data['user'] = $this->user->data;

        $db = db_connect();
        $data['total_draft'] = $db->table("transaksi")->where("flag_validasi","0")->countAllResults();
        $data['total_pending'] = $db->table("transaksi")->where("flag_validasi","1")->countAllResults();
        $data['total_completed'] = $db->table("transaksi")->where("flag_validasi","2")->countAllResults();
        $data['total_canceled'] = $db->table("transaksi")->where("flag_validasi","3")->countAllResults();

        return view('admin/transaksi/pending',$data);
    }

    public function ajax_dt(){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Transaksimodel();
        return $DataModel->GetDT($data_post,"");
    }

    public function ajax_dt_pending(){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Transaksimodel();
        $extra = "(flag_validasi = '1')";
        return $DataModel->GetDT($data_post,$extra);
    }

    public function add() {
        $data['user'] = $this->user->data;

        return view('admin/transaksi/add',$data);
    }

    public function add_save()
    {
        $data = array();
        $data['user'] = $this->user->data;
        $data['status'] = 'success';

        $request = [
            'id_grup_transaksi' => $this->request->getPost('id_grup_transaksi',FILTER_SANITIZE_ADD_SLASHES),
            'id_kolektor' => $this->request->getPost('id_kolektor',FILTER_SANITIZE_ADD_SLASHES),
            'tanggal' => $this->request->getPost('tanggal',FILTER_SANITIZE_ADD_SLASHES),
            'id_operator' => $this->user->data->id_operator,
            'created_by' => $this->user->data->id_auth,
            'updated_by' => $this->user->data->id_auth
        ];

        $validation = \Config\Services::validation();
        $validation->setRule('id_grup_transaksi', 'Grup Transaksi', 'required');
        $validation->setRule('tanggal', 'Tanggal', 'required');

        if (!$validation->run($request)) {
            return $this->fail($validation->getErrors(),400,null,'input');
        }else{
            $operatormodel = new Operatormodel();
            $request["id_operator"] = $operatormodel->getOperatorIdFromAuth($this->user->data->id_auth);

            $tmodel = new Transaksimodel();
            $tmodel->db->transBegin();
            $id = $tmodel->insert($request);
            if($tmodel->db->transStatus() === false){
                $tmodel->db->transRollback();
                return $this->fail($tmodel->errors(),400,null,'db');
            }else{
                $tmodel->db->transCommit();

                $kode = $tmodel->getNewKode();
                if (empty($kode)){
                    return $this->fail(["error" => "Empty Kode"],400,null,'db');
                }
                $request = ["kode" => $kode];
                $tmodel->update($id, $request);

                $data['id'] = $id;
                return $this->respond($data,200);
            }
        }
    }

    public function view($id) {
        $data['user'] = $this->user->data;
        $tmodel = new Transaksimodel();

        $builder = $tmodel->builder("vtransaksi");
        $data['transaksi'] = $builder->where("id_transaksi",$id)->get()->getRow();
        $data['total_transaksi'] = 0;
        $data['total_diskon'] = 0;
        $data['total_akhir'] = 0;

        $detail_transaksi = array();
        $builder = $tmodel->builder("vstruk");
        $data_struk = $builder->where("id_transaksi",$id)->get()->getResultArray();
        $detail_transaksi = array();
        $no = 0;
        foreach($data_struk as $item){
            $detail_transaksi[$no]["id_struk"] = $item["id_struk"];
            $detail_transaksi[$no]["id_kk"] = $item["id_kk"];
            $detail_transaksi[$no]["nomor_struk"] = $item["nomor"];
            $detail_transaksi[$no]["kode_kk"] = $item["kode_kk"];
            $detail_transaksi[$no]["alamat"] = $item["nama_jalan"].', '.$item["nama_blok"].', '.$item["nomor_rumah"];
            $detail_transaksi[$no]["total"] = $item["total_struk"];
            $detail_transaksi[$no]["total_diskon"] = $item["total_diskon"];
            $detail_transaksi[$no]["total_akhir"] = $item["total_akhir"];
            $data['total_transaksi'] += $item["total_struk"];
            $data['total_diskon'] += $item["total_diskon"];
            $data['total_akhir'] += $item["total_akhir"];
            $detail_transaksi[$no]["periode"] = "";

            $periode = array();
            $builder = $tmodel->builder("vstrukdetail");
            $data_struk_detail = $builder->where("id_struk",$item["id_struk"])->get()->getResultArray();
            foreach($data_struk_detail as $item2){
                $periode[] = $item2['bulan'].'-'.$item2['tahun'];
            }
            $detail_transaksi[$no]["periode"] = implode(",",$periode);
            $no++;
        }

        $data['detail_transaksi'] = $detail_transaksi;

        $data_total = [
            "total" => $data['total_transaksi'],
            "total_diskon" => $data['total_diskon'],
            "total_akhir" => $data['total_akhir']
        ];
        $tmodel->update($id,$data_total);

        $buktibayarmodel = new Buktibayarmodel();
        $data['bukti_bayar'] = $buktibayarmodel->where("id_transaksi",$id)->findAll();
        
        $jenispembayaranmodel = new Jenispembayaranmodel();
        $data['jenis_pembayaran'] = $jenispembayaranmodel->findAll();
        return view('admin/transaksi/view',$data);
    }

    public function update()
    {
        $data = array();
        $data['status'] = 'success';

        $id_transaksi = $this->request->getPost('id_transaksi',FILTER_SANITIZE_ADD_SLASHES);
        $request = [
            'id_grup_transaksi' => $this->request->getPost('id_grup_transaksi',FILTER_SANITIZE_ADD_SLASHES),
            'id_kolektor' => $this->request->getPost('id_kolektor',FILTER_SANITIZE_ADD_SLASHES),
            'tanggal' => $this->request->getPost('tanggal',FILTER_SANITIZE_ADD_SLASHES),
            'id_operator' => $this->user->data->id_operator,
            'updated_by' => $this->user->data->id_auth
        ];

        $validation = \Config\Services::validation();
        $validation->setRule('id_grup_transaksi', 'Grup Transaksi', 'required');
        $validation->setRule('tanggal', 'Tanggal', 'required');

        if (!$validation->run($request)) {
            return $this->fail($validation->getErrors(),400,null,'input');
        }else{
            $operatormodel = new Operatormodel();
            $request["id_operator"] = $operatormodel->getOperatorIdFromAuth($this->user->data->id_auth);
            
            $tmodel = new Transaksimodel();

            if ($tmodel->update($id_transaksi,$request))
            {
                $data['id'] = $id_transaksi;
                return $this->respond($data,200);
            }else{
                return $this->fail(["error" => "Database Error!"],400,null,'db');
            }
        }
    }

    public function add_detail($id_transaksi, $id_kk) {
        $data['user'] = $this->user->data;

        $transaksimodel = new Transaksimodel();
        $invoicemodel = new Invoicemodel();
        $historytransmodel = new Historytransmodel();

        $builder = $transaksimodel->builder("vtransaksi");
        $data['transaksi'] = $builder->where("id_transaksi",$id_transaksi)->get()->getRow();

        $builder = $historytransmodel->builder();
        $builder->where("id_kk",$id_kk);
        $builder->orderBy("tahun","DESC");
        $builder->orderBy("bulan","DESC");
        $row = $builder->get()->getRow();
        if(!$row){
            return $this->view($id_transaksi);
        }

        $startYear = $row->tahun;
        $startMonth = $row->bulan + 1;
        if ($startMonth > 12){
            $startYear+=1;
            $startMonth=1;
        }

        $invoicebuilder = $invoicemodel->builder();
        $invoicebuilder->where("id_kk",$id_kk);
        $invoicebuilder->where("flag_close","0");
        $invoicebuilder->orderBy("tahun","asc");
        $invoicebuilder->orderBy("bulan","asc");
        $invoice = $invoicebuilder->get(1)->getRow();

        $start_periode = strtotime($startYear."-".str_pad($startMonth,2,"0",STR_PAD_LEFT)."-01");
        $invoice_periode = strtotime($invoice->tahun."-".str_pad($invoice->bulan,2,"0",STR_PAD_LEFT)."-01");
        if($invoice_periode < $start_periode){
            $startYear = $invoice->tahun;
            $startMonth = $invoice->bulan;
        }

        $data_iuran = array();
        $currentYear = date('Y') + 1;
        $currentMonth = 12;

        $year = $startYear;
        $month = $startMonth;
        $no=0;
        $total = 0;
        $total_diskon = 0;
        $total_akhir = 0;
        $group_year = $year;
        $group_year_visible = true;
        while ($year < $currentYear || ($year == $currentYear && $month <= $currentMonth)) {
            $tarif = 0;
            $id_tarif = "";

            $diskon = 0;
            $id_diskon = 0;

            $tarifmodel = new Tarifmodel();
            $db_tarif = $tarifmodel->db;
            $cek_date = $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-01";
            $query_tarif = $db_tarif->query("select * from tarif where id_kk='".$id_kk."' and start_date <='".$cek_date."' and (end_date >= '".$cek_date."' or end_date='9999-12-31') and deleted_at is null order by end_date desc");

            $tarif_row = $query_tarif->getRow();

            if($tarif_row != null){
                $id_tarif = $tarif_row->id_tarif;
                $tarif = $tarif_row->nominal;
            }else{
                $query_tarif = $db_tarif->query("select * from tarif where id_kk='".$id_kk."' and deleted_at is null order by end_date desc");

                $tarif_row = $query_tarif->getRow();

                if($tarif_row != null){
                    $id_tarif = $tarif_row->id_tarif;
                    $tarif = $tarif_row->nominal;
                }
            }

            $diskonmodel = new Diskonmodel();
            $db_diskon = $diskonmodel->db;
            $cek_date = $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-01";
            $query_diskon = $db_diskon->query("select * from diskon where id_kk='".$id_kk."' and start_date <='".$cek_date."' and (end_date >= '".$cek_date."' or end_date='9999-12-31') and deleted_at is null order by end_date desc");

            $diskon_row = $query_diskon->getRow();

            if($diskon_row != null){
                $id_diskon = $diskon_row->id_diskon;
                $diskon = $diskon_row->nominal;
            }

            $builder_model = $invoicemodel->builder("invoice");
            $builder_model->where("id_kk",$id_kk);
            $builder_model->where("tahun",$year);
            $builder_model->where("bulan",$month);
            $invoice = $builder_model->get()->getRow();

            if ($invoice != null){
                if(($invoice->flag_close == '0')){
                    //invoice masih open
                    $strukdetailmodel = new Strukdetailmodel();
                    $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
                    $strukdetailbuilder->where("id_invoice",$invoice->id_invoice);
                    $strukdetailbuilder->where("id_transaksi != ",$id_transaksi);
                    $strukdetailbuilder->where("flag_batal","0");
                    $strukdetail = $strukdetailbuilder->get()->getRow();

                    if((is_null($strukdetail))){
                        //invoice masih open dan bisa jadi dimiliki oleh transaksi ini atau belum ada transaksi
                        if(($invoice->nominal != $tarif) || ($invoice->nominal_diskon != $diskon)){
                            //update tarif invoice dengan yg terbaru
                            $update = [
                                "id_tarif" => $id_tarif,
                                "id_diskon" => $id_diskon,
                                "nominal" => $tarif,
                                "nominal_diskon" => $diskon,
                                "nominal_akhir" => ($tarif - $diskon)
                            ];
                            $invoicemodel->update($invoice->id_invoice,$update);
                            $invoice->nominal = $tarif;
                            $invoice->nominal_diskon = $diskon;
                            $invoice->nominal_akhir = ($tarif-$diskon);
                        }

                        $strukdetailmodel = new Strukdetailmodel();
                        $strukdetail_builder = $strukdetailmodel->builder("vstrukdetail");
                        $strukdetail_builder->where("id_invoice",$invoice->id_invoice);
                        $strukdetail_builder->where("id_transaksi",$id_transaksi);
                        $strukdetail = $strukdetail_builder->get()->getRow();
                        $data_iuran[$no]["checked"] = "";
                        if($strukdetail != null){
                            $data_iuran[$no]["checked"] = "checked";
                            $total += $invoice->nominal;
                            $total_diskon += $invoice->nominal_diskon;
                            $total_akhir += $invoice->nominal_akhir;
                        }
                        $strukdetail_builder->db()->close();

                        $data_iuran[$no]["id_invoice"] = $invoice->id_invoice;
                        $data_iuran[$no]["status"] = "";
                    }
                    // else{
                    //     //invoice masih open dan ada di transaksi lain
                    //     $data_iuran[$no]["checked"] = "";
                    //     $data_iuran[$no]["id_invoice"] = "";
                    //     $data_iuran[$no]["status"] = "Open in another transaction";
                    // }
                }
                elseif(($invoice->flag_close == '1')){
                    $strukdetailmodel = new Strukdetailmodel();
                    $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
                    $strukdetailbuilder->where("id_invoice",$invoice->id_invoice);
                    $strukdetailbuilder->where("id_transaksi != ",$id_transaksi);
                    $strukdetail = $strukdetailbuilder->get()->getRow();
                    if((is_null($strukdetail))){
                        //invoice closed dan mungkin dimiliki oleh transaksi ini
                        $strukdetailmodel = new Strukdetailmodel();
                        $strukdetail_builder = $strukdetailmodel->builder();
                        $strukdetail_builder->where("id_invoice",$invoice->id_invoice);
                        $strukdetail = $strukdetail_builder->get()->getRow();
                        
                        $data_iuran[$no]["checked"] = "checked";
                        $total += $invoice->nominal;
                        $total_diskon += $invoice->nominal_diskon;
                        $total_akhir += $invoice->nominal_akhir;
                        $strukdetailmodel->db->close();

                        $data_iuran[$no]["id_invoice"] = "";
                        $data_iuran[$no]["status"] = "Paid Here.";
                    }else{
                        //Invoice sudah close dan dimiliki oleh transaksi lain
                        $data_iuran[$no]["id_invoice"] = "";
                        $data_iuran[$no]["status"] = "Paid";
                    }   
                }
                //else{
                //     //Invoice sudah close dan dimiliki oleh transaksi lain
                //     $data_iuran[$no]["id_invoice"] = "";
                //     $data_iuran[$no]["status"] = "Unknown";
                // }

                // $data_iuran[$no]["nomor_invoice"] = $invoice->nomor;
                // $data_iuran[$no]["tahun"] = $invoice->tahun;
                // $data_iuran[$no]["bulan"] = $invoice->bulan;
                // $data_iuran[$no]["nominal"] = $invoice->nominal;
                // $data_iuran[$no]["nominal_diskon"] = $invoice->nominal_diskon;
                // $data_iuran[$no]["nominal_akhir"] = $invoice->nominal_akhir;
                // $data_iuran[$no]["flag_close"] = $invoice->flag_close;

                $data_iuran[$no]["nomor_invoice"] = $invoice->nomor;
                $data_iuran[$no]["tahun"] = $invoice->tahun;
                $data_iuran[$no]["bulan"] = $invoice->bulan;
                $data_iuran[$no]["nominal"] = $invoice->nominal;
                $data_iuran[$no]["nominal_diskon"] = $invoice->nominal_diskon;
                $data_iuran[$no]["nominal_akhir"] = $invoice->nominal_akhir;
                $data_iuran[$no]["flag_close"] = $invoice->flag_close;
            }else{
                //invoice belum ada lanjut buat invoice
                if(!empty($id_tarif)){
                    //pastikan tarif ada
                    $cek_date = $year.str_pad($month,2,"0",STR_PAD_LEFT);
                    $data_iuran[$no]["nomor_invoice"] = $invoicemodel->getNewKode($cek_date);
                    if (empty($data_iuran[$no]["nomor_invoice"])){
                        return $this->fail(["error" => "New Invoice Number Error!"],400,null,'db');
                    }

                    $input_invoice = [
                        "id_grup_transaksi" => $data['transaksi']->id_grup_transaksi,
                        "id_tarif" => $id_tarif,
                        "id_diskon" => $id_diskon,
                        "id_kk" => $id_kk,
                        "nomor" => $data_iuran[$no]["nomor_invoice"],
                        "bulan" => $month,
                        "tahun" => $year,
                        "nominal" => $tarif,
                        "nominal_diskon" => $diskon,
                        "nominal_akhir" => ($tarif - $diskon),
                        "created_by" => $this->user->data->id_auth,
                        "updated_by" => $this->user->data->id_auth
                    ];

                    $id_invoice = $invoicemodel->insert($input_invoice);
                    $invoice = $invoicemodel->where("id_invoice",$id_invoice)->first();
                    
                    $data_iuran[$no]["id_invoice"] = $id_invoice;
                    $data_iuran[$no]["nomor_invoice"] = $invoice['nomor'];
                    $data_iuran[$no]["tahun"] = $invoice['tahun'];
                    $data_iuran[$no]["bulan"] = $invoice['bulan'];
                    $data_iuran[$no]["nominal"] = $invoice['nominal'];
                    $data_iuran[$no]["nominal_diskon"] = $invoice['nominal_diskon'];
                    $data_iuran[$no]["nominal_akhir"] = $invoice['nominal_akhir'];
                    $data_iuran[$no]["flag_close"] = $invoice['flag_close'];
                    $data_iuran[$no]["checked"] = "";
                    $data_iuran[$no]["status"] = "";
                }else{
                    //tarif tidak ada, jgn buat invoice tampilkan not available
                    $data_iuran[$no]["id_invoice"] = "";
                    $data_iuran[$no]["nomor_invoice"] = "";
                    $data_iuran[$no]["tahun"] = $year;
                    $data_iuran[$no]["bulan"] = $month;
                    $data_iuran[$no]["nominal"] = 0;
                    $data_iuran[$no]["nominal_diskon"] = 0;
                    $data_iuran[$no]["nominal_akhir"] = 0;
                    $data_iuran[$no]["flag_close"] = 0;
                    $data_iuran[$no]["checked"] = "";
                    $data_iuran[$no]["status"] = "Tarif Not Available";
                }
            }

            $no++;
            $month++;
            if ($month > 12) {
                $month = 1;
                $year++;
            }
        }

        $kkmodel = new Kkmodel();
        $kk_builder = $kkmodel->builder("vkk");
        $kk_builder->where("id_kk",$id_kk);
        $kk = $kk_builder->get()->getRow();

        $data['invoice'] = $data_iuran;
        $data['kk'] = $kk;
        $data['total'] = $total;
        $data['total_diskon'] = $total_diskon;
        $data['total_akhir'] = $total_akhir;

        return view('admin/transaksi/add_detail',$data);
    }

    public function add_detail_simple($id_transaksi, $id_kk) {
        $data['user'] = $this->user->data;

        $transaksimodel = new Transaksimodel();
        $historytransmodel = new Historytransmodel();
        $invoicemodel = new Invoicemodel();

        $builder = $transaksimodel->builder("vtransaksi");
        $data['transaksi'] = $builder->where("id_transaksi",$id_transaksi)->get()->getRow();

        $builder = $historytransmodel->builder();
        $builder->where("id_kk",$id_kk);
        $row = $builder->get()->getRow();
        if(!$row){
            return $this->view($id_transaksi);
        }

        $startYear = $row->tahun;
        $startMonth = $row->bulan + 1;
        if ($startMonth > 12){
            $startYear+=1;
            $startMonth=1;
        }

        $invoicebuilder = $invoicemodel->builder();
        $invoicebuilder->where("id_kk",$id_kk);
        $invoicebuilder->where("flag_close","0");
        $invoicebuilder->orderBy("tahun","asc");
        $invoicebuilder->orderBy("bulan","asc");
        $invoice = $invoicebuilder->get(1)->getRow();

        $start_periode = strtotime($startYear."-".str_pad($startMonth,2,"0",STR_PAD_LEFT)."-01");
        $invoice_periode = strtotime($invoice->tahun."-".str_pad($invoice->bulan,2,"0",STR_PAD_LEFT)."-01");
        if($invoice_periode < $start_periode){
            $startYear = $invoice->tahun;
            $startMonth = $invoice->bulan;
        }

        $data_iuran = array();
        $currentYear = date('Y') + 1;
        $currentMonth = 12;

        $kkmodel = new Kkmodel();
        $kk_builder = $kkmodel->builder("vkk");
        $kk_builder->where("id_kk",$id_kk);
        $kk = $kk_builder->get()->getRow();

        $data['invoice'] = $data_iuran;
        $data['kk'] = $kk;
        $data['start_periode'] = $startYear."-".str_pad($startMonth,2,"0",STR_PAD_LEFT);
        $data['end_periode'] = $currentYear."-".str_pad($currentMonth,2,"0",STR_PAD_LEFT);

        return view('admin/transaksi/add_detail_simple',$data);
    }

    public function cancel_detail($id_transaksi, $id_kk) {
        $data['user'] = $this->user->data;

        $transaksimodel = new Transaksimodel();
        $transaksi = $transaksimodel->find($id_transaksi);

        if(($transaksi["flag_batal"] == '0') && ($transaksi["flag_validasi"] <= 1)){
            $strukmodel = new Strukmodel();
            $strukmodel->db->transComplete();
            $strukmodel->where("id_transaksi",$id_transaksi)->where("id_kk",$id_kk)->delete();
            if($strukmodel->db->transFailure){
                $strukmodel->db->transRollback();
                return $this->fail(["error" => "Cancel Failed"],400,null,'db');
            }

            $update = [
                "total" => 0,
                "total_diskon" => 0,
                "total_akhir" => 0
            ];

            $strukmodel = new Strukmodel();
            $struks = $strukmodel->where("id_transaksi",$id_transaksi)->findAll();
            foreach($struks as $struk){
                $update["total"] += $struk["total"];
                $update["total_diskon"] += $struk["total_diskon"];
                $update["total_akhir"] += $struk["total_akhir"];
            }

            $transaksimodel = new Transaksimodel();
            $transaksimodel->db->transBegin();
            $transaksimodel->update($id_transaksi,$update);
            if($transaksimodel->db->transFailure){
                $strukmodel->db->transRollback();
                $transaksimodel->db->transRollback();
                return $this->fail(["error" => "Transaksi update failed"],400,null,'db');
            }

            $strukmodel->db->transComplete();
            $transaksimodel->db->transComplete();
        }

        return redirect()->to('transaksi/view/'.$id_transaksi);
    }

    public function update_detail()
    {
        $data = array();
        $data['status'] = 'success';

        $id_transaksi = $this->request->getPost('id_transaksi',FILTER_SANITIZE_ADD_SLASHES);
        $id_kk = $this->request->getPost('id_kk',FILTER_SANITIZE_ADD_SLASHES);
        $check_iuran = $this->request->getPost('check_iuran',FILTER_SANITIZE_ADD_SLASHES);

        if (empty($id_transaksi) || empty($id_kk) || is_null($check_iuran)) {
            return $this->fail(["error" => "Invalid Data"],400,null,'db');
        }

        $transaksimodel = new Transaksimodel();
        $invoicemodel = new Invoicemodel();
        $strukmodel = new Strukmodel();
        $strukdetailmodel = new Strukdetailmodel();

        $transaksibuilder = $transaksimodel->builder();
        $transaksibuilder->where("id_transaksi");
        $transaksi = $transaksibuilder->get()->getRow();
        if($transaksi){
            if($transaksi->flag_validasi != "0"){
                return $this->fail(["error" => "Invalid Operation"],400,null,'db');
            }
        }

        $strukmodel->db->transBegin();
        $struk_builder = $strukmodel->builder();
        $struk_builder->where("id_transaksi",$id_transaksi);
        $struk_builder->where("id_kk",$id_kk);
        $data_struk = $struk_builder->get()->getRow();
        $id_struk = "";

        if ($data_struk!=null){
            $id_struk = $data_struk->id_struk;
        }else{
            //Struk untuk transaksi dan kk ini belum ada, buat baru
            $data_struk = [
                "id_transaksi" => $id_transaksi,
                "id_kk" => $id_kk 
            ];

            $id_struk = $strukmodel->insert($data_struk);
            if(empty($id_struk)){
                return $this->fail(["error" => "Struk creating failed"],400,null,'db');
            }
        }

        $total = 0;
        $total_diskon = 0;
        $total_akhir = 0;

        //clear detail struk untuk transaksi ini
        $strukdetail_builder = $strukdetailmodel->builder();
        $strukdetailmodel->db->transBegin();
        $strukdetail_builder->delete(["id_struk" => $id_struk]);

        //insert baru untuk tiap bulan iuran
        foreach($check_iuran as $iuran){
            $invoice = $invoicemodel->find($iuran);
            //pastikan invoice masih open
            if($invoice["flag_close"] == "1"){
                $strukmodel->db->transRollback();
                $strukdetailmodel->db->transRollback();
                return $this->fail(["error" => "Invoice sudah di closed"],400,null,'db');
            }

            //pastikan invoice tidak dibuka di transaksi lain
            $strukdetailmodel = new Strukdetailmodel();
            $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
            $strukdetailbuilder->where("id_invoice",$invoice["id_invoice"]);
            $strukdetailbuilder->where("id_transaksi != ",$id_transaksi);
            $strukdetailbuilder->where("flag_batal","0");
            $strukdetail = $strukdetailbuilder->get()->getRow();
            if($strukdetail != null){
                $strukmodel->db->transRollback();
                $strukdetailmodel->db->transRollback();
                return $this->fail(["error" => "Invoice sudah di open di transaksi lain"],400,null,'db');
            }

            $detail_struk=[
                "id_struk_detail" => date("YmdHis.u").$id_struk.$invoice["id_invoice"],
                "id_struk" => $id_struk,
                "id_invoice" => $invoice["id_invoice"],
                "bulan" => $invoice["bulan"],
                "tahun" => $invoice["tahun"],
                "nominal" => $invoice["nominal"],
                "nominal_diskon" => $invoice["nominal_diskon"],
                "nominal_total" => $invoice["nominal_akhir"],
                "created_by" => $this->user->data->id_auth,
                "updated_by" => $this->user->data->id_auth
            ];
            $total += $invoice['nominal'];
            $total_diskon += $invoice['nominal_diskon'];
            $total_akhir += $invoice['nominal_akhir'];
            $strukdetailmodel->insert($detail_struk);

            if($strukdetailmodel->db->transFailure){
                $strukmodel->db->transRollback();
                $strukdetailmodel->db->transRollback();
                return $this->fail(["error" => "Invalid Struk Detail"],400,null,'db');
            }
        }

        //update total di struk
        $data_struk = [
            "total" => $total,
            "total_diskon" => $total_diskon,
            "total_akhir" => $total_akhir 
        ];

        $strukmodel->update($id_struk,$data_struk);
        if($strukmodel->db->transFailure){
            $strukdetailmodel->db->transRollback();
            $strukmodel->db->transRollback();
            return $this->fail(["error" => "Struk update failed"],400,null,'db');
        }

        //Update data di transaksi
        $update = [
            "total" => 0,
            "total_diskon" => 0,
            "total_akhir" => 0
        ];

        $strukmodel = new Strukmodel();
        $struks = $strukmodel->where("id_transaksi",$id_transaksi)->findAll();
        foreach($struks as $struk){
            $update["total"] += $struk["total"];
            $update["total_diskon"] += $struk["total_diskon"];
            $update["total_akhir"] += $struk["total_akhir"];
        }

        $transaksimodel = new Transaksimodel();
        $transaksimodel->db->transBegin();
        $transaksimodel->update($id_transaksi,$update);
        if($transaksimodel->db->transFailure){
            $strukdetailmodel->db->transRollback();
            $strukmodel->db->transRollback();
            $transaksimodel->db->transRollback();
            return $this->fail(["error" => "Transaksi update failed"],400,null,'db');
        }

        $strukmodel->db->transComplete();
        $strukdetailmodel->db->transComplete();
        $transaksimodel->db->transComplete();

        $data["id_transaksi"] = $id_transaksi;
        $data["id_kk"] = $id_kk;
        $data["id_struk"] = $id_struk;
        return $this->respond($data,200);
    }

    public function update_detail_simple()
    {
        $data = array();
        $data['status'] = 'success';

        $id_transaksi = $this->request->getPost('id_transaksi',FILTER_SANITIZE_ADD_SLASHES);
        $id_kk = $this->request->getPost('id_kk',FILTER_SANITIZE_ADD_SLASHES);
        $start_periode = $this->request->getPost('start_periode',FILTER_SANITIZE_ADD_SLASHES);
        $end_periode = $this->request->getPost('end_periode',FILTER_SANITIZE_ADD_SLASHES);

        if (empty($id_transaksi) || empty($id_kk) || is_null($start_periode) || is_null($end_periode)) {
            return $this->fail(["error" => "Invalid Data"],400,null,'db');
        }

        $csperiode = strtotime($start_periode."-01");
        $ceperiode = strtotime($end_periode."-01");

        if($ceperiode < $csperiode){
            return $this->fail(["error" => "Invalid Periode"],400,null,'db');
        }

        $transaksimodel = new Transaksimodel();
        $invoicemodel = new Invoicemodel();
        $strukmodel = new Strukmodel();
        $strukdetailmodel = new Strukdetailmodel();

        $transaksibuilder = $transaksimodel->builder();
        $transaksibuilder->where("id_transaksi",$id_transaksi);
        $transaksi = $transaksibuilder->get()->getRow();
        if($transaksi){
            if($transaksi->flag_validasi != "0"){
                return $this->fail(["error" => "Invalid Operation"],400,null,'db');
            }
        }else{
            return $this->fail(["error" => "Transaksi not found!"],400,null,'db');
        }

        $strukmodel->db->transBegin();
        $struk_builder = $strukmodel->builder();
        $struk_builder->where("id_transaksi",$id_transaksi);
        $struk_builder->where("id_kk",$id_kk);
        $data_struk = $struk_builder->get()->getRow();
        $id_struk = "";

        if ($data_struk!=null){
            $id_struk = $data_struk->id_struk;
        }else{
            //Struk untuk transaksi dan kk ini belum ada, buat baru
            $data_struk = [
                "id_transaksi" => $id_transaksi,
                "id_kk" => $id_kk 
            ];

            $id_struk = $strukmodel->insert($data_struk);
            if(empty($id_struk)){
                return $this->fail(["error" => "Struk creating failed"],400,null,'db');
            }
        }

        $total = 0;
        $total_diskon = 0;
        $total_akhir = 0;

        //clear detail struk untuk transaksi ini
        $strukdetail_builder = $strukdetailmodel->builder();
        $strukdetailmodel->db->transBegin();
        $strukdetail_builder->delete(["id_struk" => $id_struk]);

        //insert baru untuk tiap bulan iuran
        $speriode = explode("-",$start_periode);
        $startYear = $speriode[0];
        $startMonth = (int) $speriode[1];

        $eperiode = explode("-",$end_periode);
        $currentYear = $eperiode[0];
        $currentMonth = (int) $eperiode[1];

        $year = $startYear;
        $month = $startMonth;

        $no=0;
        $total = 0;
        $total_diskon = 0;
        $total_akhir = 0;
        while ($year < $currentYear || ($year == $currentYear && $month <= $currentMonth)) {
            $tarif = 0;
            $id_tarif = "";

            $diskon = 0;
            $id_diskon = 0;

            $tarifmodel = new Tarifmodel();
            $db_tarif = $tarifmodel->db;
            $cek_date = $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-01";
            $query_tarif = $db_tarif->query("select * from tarif where id_kk='".$id_kk."' and start_date <='".$cek_date."' and (end_date >= '".$cek_date."' or end_date='9999-12-31') and deleted_at is null order by end_date desc");

            $tarif_row = $query_tarif->getRow();

            if($tarif_row != null){
                $id_tarif = $tarif_row->id_tarif;
                $tarif = $tarif_row->nominal;
            }else{
                $query_tarif = $db_tarif->query("select * from tarif where id_kk='".$id_kk."' and deleted_at is null order by end_date desc");

                $tarif_row = $query_tarif->getRow();

                if($tarif_row != null){
                    $id_tarif = $tarif_row->id_tarif;
                    $tarif = $tarif_row->nominal;
                }
            }

            $diskonmodel = new Diskonmodel();
            $db_diskon = $diskonmodel->db;
            $cek_date = $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-01";
            $query_diskon = $db_diskon->query("select * from diskon where id_kk='".$id_kk."' and start_date <='".$cek_date."' and (end_date >= '".$cek_date."' or end_date='9999-12-31') and deleted_at is null order by end_date desc");

            $diskon_row = $query_diskon->getRow();

            if($diskon_row != null){
                $id_diskon = $diskon_row->id_diskon;
                $diskon = $diskon_row->nominal;
            }

            $builder_model = $invoicemodel->builder("invoice");
            $builder_model->where("id_kk",$id_kk);
            $builder_model->where("tahun",$year);
            $builder_model->where("bulan",$month);
            $invoice = $builder_model->get()->getRow();

            if ($invoice != null){
                if(($invoice->flag_close == '0')){
                    //invoice masih open
                    $strukdetailmodel = new Strukdetailmodel();
                    $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
                    $strukdetailbuilder->where("id_invoice",$invoice->id_invoice);
                    $strukdetailbuilder->where("id_transaksi != ",$id_transaksi);
                    $strukdetailbuilder->where("flag_batal","0");
                    $strukdetail = $strukdetailbuilder->get()->getRow();

                    if((is_null($strukdetail))){
                        //invoice masih open dan bisa jadi dimiliki oleh transaksi ini atau belum ada transaksi
                        if(($invoice->nominal != $tarif) || ($invoice->nominal_diskon != $diskon)){
                            //update tarif invoice dengan yg terbaru
                            $update = [
                                "id_tarif" => $id_tarif,
                                "id_diskon" => $id_diskon,
                                "nominal" => $tarif,
                                "nominal_diskon" => $diskon,
                                "nominal_akhir" => ($tarif - $diskon)
                            ];
                            $invoicemodel->update($invoice->id_invoice,$update);
                            $invoice->nominal = $tarif;
                            $invoice->nominal_diskon = $diskon;
                            $invoice->nominal_akhir = ($tarif-$diskon);
                        }

                        $detail_struk=[
                            "id_struk_detail" => date("YmdHis.u").$id_struk.$invoice->id_invoice,
                            "id_struk" => $id_struk,
                            "id_invoice" => $invoice->id_invoice,
                            "bulan" => $invoice->bulan,
                            "tahun" => $invoice->tahun,
                            "nominal" => $invoice->nominal,
                            "nominal_diskon" => $invoice->nominal_diskon,
                            "nominal_total" => $invoice->nominal_akhir,
                            "created_by" => $this->user->data->id_auth,
                            "updated_by" => $this->user->data->id_auth
                        ];
                        $total += $invoice->nominal;
                        $total_diskon += $invoice->nominal_diskon;
                        $total_akhir += $invoice->nominal_akhir;
                        $strukdetailmodel->insert($detail_struk);

                        if($strukdetailmodel->db->transFailure){
                            $strukmodel->db->transRollback();
                            $strukdetailmodel->db->transRollback();
                            return $this->fail(["error" => "Invalid Struk Detail"],400,null,'db');
                        }
                    }
                }
            }else{
                //invoice belum ada lanjut buat strukdetail saja
                if(!empty($id_tarif)){
                    //pastikan tarif ada
                    $cek_date = $year.str_pad($month,2,"0",STR_PAD_LEFT);
                    $data_iuran[$no]["nomor_invoice"] = $invoicemodel->getNewKode($cek_date);
                    if (empty($data_iuran[$no]["nomor_invoice"])){
                        return $this->fail(["error" => "New Invoice Number Error!"],400,null,'db');
                    }

                    $input_invoice = [
                        "id_grup_transaksi" => $transaksi->id_grup_transaksi,
                        "id_tarif" => $id_tarif,
                        "id_diskon" => $id_diskon,
                        "id_kk" => $id_kk,
                        "nomor" => $data_iuran[$no]["nomor_invoice"],
                        "bulan" => $month,
                        "tahun" => $year,
                        "nominal" => $tarif,
                        "nominal_diskon" => $diskon,
                        "nominal_akhir" => ($tarif - $diskon),
                        "created_by" => $this->user->data->id_auth,
                        "updated_by" => $this->user->data->id_auth
                    ];

                    $id_invoice = $invoicemodel->insert($input_invoice);
                    $invoice = $invoicemodel->where("id_invoice",$id_invoice)->first();

                    $detail_struk=[
                        "id_struk_detail" => date("YmdHis.u").$id_struk."N",
                        "id_struk" => $id_struk,
                        "id_invoice" => $id_invoice,
                        "bulan" => $month,
                        "tahun" => $year,
                        "nominal" => $tarif,
                        "nominal_diskon" => $diskon,
                        "nominal_total" => ($tarif - $diskon),
                        "created_by" => $this->user->data->id_auth,
                        "updated_by" => $this->user->data->id_auth
                    ];
                    $total += $tarif;
                    $total_diskon += $diskon;
                    $total_akhir += ($tarif - $diskon);
                    $strukdetailmodel->insert($detail_struk);

                    if($strukdetailmodel->db->transFailure){
                        $strukmodel->db->transRollback();
                        $strukdetailmodel->db->transRollback();
                        return $this->fail(["error" => "Invalid Struk Detail"],400,null,'db');
                    }
                }
            }

            $no++;
            $month++;
            if ($month > 12) {
                $month = 1;
                $year++;
            }
        }

        //update total di struk
        $data_struk = [
            "total" => $total,
            "total_diskon" => $total_diskon,
            "total_akhir" => $total_akhir 
        ];

        $strukmodel->update($id_struk,$data_struk);
        if($strukmodel->db->transFailure){
            $strukdetailmodel->db->transRollback();
            $strukmodel->db->transRollback();
            return $this->fail(["error" => "Struk update failed"],400,null,'db');
        }

        //Update data di transaksi
        $update = [
            "total" => 0,
            "total_diskon" => 0,
            "total_akhir" => 0
        ];

        $strukmodel = new Strukmodel();
        $struks = $strukmodel->where("id_transaksi",$id_transaksi)->findAll();
        foreach($struks as $struk){
            $update["total"] += $struk["total"];
            $update["total_diskon"] += $struk["total_diskon"];
            $update["total_akhir"] += $struk["total_akhir"];
        }

        $transaksimodel = new Transaksimodel();
        $transaksimodel->db->transBegin();
        $transaksimodel->update($id_transaksi,$update);
        if($transaksimodel->db->transFailure){
            $strukdetailmodel->db->transRollback();
            $strukmodel->db->transRollback();
            $transaksimodel->db->transRollback();
            return $this->fail(["error" => "Transaksi update failed"],400,null,'db');
        }

        $strukmodel->db->transComplete();
        $strukdetailmodel->db->transComplete();
        $transaksimodel->db->transComplete();

        $data["id_transaksi"] = $id_transaksi;
        $data["id_kk"] = $id_kk;
        $data["id_struk"] = $id_struk;
        return $this->respond($data,200);
    }

    public function delete()
    {
        $data = array();
        $data['status'] = 'success';

        $id = $this->request->getPost('id',FILTER_SANITIZE_ADD_SLASHES);

        $tmodel = new Transaksimodel();
        if ($tmodel->delete($id))
        {
            return $this->respond($data,200);
        }else{
            return $this->fail(["error" => "Database Error!"],400,null,'db');
        }
    }

    public function batal()
    {
        $data = array();
        $data['status'] = 'success';

        $id_transaksi = $this->request->getPost('id_transaksi',FILTER_SANITIZE_ADD_SLASHES);
        $request = [
            'flag_batal' => "1",
            'flag_validasi' => "3",
            'tanggal_validasi' => date("Y-m-d"),
            'keterangan' => $this->request->getPost('keterangan',FILTER_SANITIZE_ADD_SLASHES),
            'updated_by' => $this->user->data->id_auth
        ];

        $tmodel = new Transaksimodel();
        $tmodel->db->transBegin();
        $tmodel->update($id_transaksi,$request);

        if($tmodel->db->transFailure){
            $tmodel->db->transRollback();
            return $this->fail(["error" => "Database Error!"],400,null,'db');
        }

        $data['id'] = $id_transaksi;

        $strukdetailmodel = new Strukdetailmodel();
        $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
        $strukdetailbuilder->where("id_transaksi",$id_transaksi);
        $strukdetail = $strukdetailbuilder->get()->getResultArray();
        $invoicemodel = new Invoicemodel();
        $invoicemodel->db->transBegin();
        foreach($strukdetail as $item){
            $invoicemodel->update($item["id_invoice"],["flag_close" => "0"]);
            if($invoicemodel->db->transFailure){
                $invoicemodel->db->transRollback();
                $tmodel->db->transRollback();
                return $this->fail(["error" => "Database Error!"],400,null,'db');
            }
        }

        $invoicemodel->db->transCommit();
        $tmodel->db->transCommit();

        return $this->respond($data,200);
    }

    public function selesai()
    {
        $data = array();
        $data['status'] = 'success';

        $id_transaksi = $this->request->getPost('id_transaksi',FILTER_SANITIZE_ADD_SLASHES);
        $request = [
            'flag_batal' => "0",
            'flag_validasi' => "2",
            'tanggal_validasi' => date("Y-m-d H:i:s"),
            'id_jenis_pembayaran' => $this->request->getPost('id_jenis_pembayaran',FILTER_SANITIZE_ADD_SLASHES),
            'tanggal_pembayaran' => $this->request->getPost('tanggal_pembayaran',FILTER_SANITIZE_ADD_SLASHES),
            'pembayar' => $this->request->getPost('pembayar',FILTER_SANITIZE_ADD_SLASHES),
            'no_telp' => $this->request->getPost('no_telp',FILTER_SANITIZE_ADD_SLASHES),
            'keterangan_validasi' => $this->request->getPost('keterangan',FILTER_SANITIZE_ADD_SLASHES),
            'id_operator' => $this->user->data->id_operator,
            'updated_by' => $this->user->data->id_auth
        ];

        $validation = \Config\Services::validation();
        $validation->setRule('id_jenis_pembayaran', 'Jenis Pembayaran', 'required');
        $validation->setRule('pembayar', 'Nama Pembayar', 'required');
        $validation->setRule('tanggal_pembayaran', 'Tanggal Pembayaran', 'required');
        $validation->setRule('no_telp', 'Nomor Telepon', 'required');

        if (!$validation->run($request)) {
            return $this->fail($validation->getErrors(),400,null,'input');
        }

        $tmodel = new Transaksimodel();
        $transaksibuilder = $tmodel->builder();
        $transaksibuilder->where("id_transaksi",$id_transaksi);
        $transaksi = $transaksibuilder->get()->getRow();

        $tmodel = new Transaksimodel();
        $tmodel->db->transBegin();
        $tmodel->update($id_transaksi,$request);
        if($tmodel->db->transFailure){
            $tmodel->db->transRollback();
            return $this->fail(["error" => "Database Error!"],400,null,'db');
        }

        $data['id'] = $id_transaksi;
        $trackingperiode = array();

        $strukdetailmodel = new Strukdetailmodel();
        $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
        $strukdetailbuilder->where("id_transaksi",$id_transaksi);
        $strukdetail = $strukdetailbuilder->get()->getResultArray();

        $invoicemodel = new Invoicemodel();
        $invoicemodel->db->transBegin();
        foreach($strukdetail as $item){
            $invoicemodel->update($item["id_invoice"],["flag_close" => "1"]);
            if($invoicemodel->db->transFailure){
                $invoicemodel->db->transRollback();
                $tmodel->db->transRollback();
                return $this->fail(["error" => "Database Error!"],400,null,'db');
            }

            if(!isset($trackingperiode[$item["id_kk"]])){
                $trackingperiode[$item["id_kk"]] = strtotime($item["tahun_invoice"]."-".str_pad($item["bulan_invoice"],2,"0",STR_PAD_LEFT)."-01");
            }else{
                $tampperiode = strtotime($item["tahun_invoice"]."-".str_pad($item["bulan_invoice"],2,"0",STR_PAD_LEFT)."-01");
                if($tampperiode > $trackingperiode[$item["id_kk"]]){
                    $trackingperiode[$item["id_kk"]] = $tampperiode;
                }
            }
            
        }

        $strukmodel = new Strukmodel();
        $strukbuilder = $strukmodel->builder();
        $strukbuilder->where("id_transaksi",$id_transaksi);
        $struks = $strukbuilder->get()->getResultObject();

        if(is_null($struks)){
            $invoicemodel->db->transRollback();
            $tmodel->db->transRollback();
            return $this->fail(["error" => "Struk Not Found!"],400,null,'db');
        }

        foreach($struks as $struk){
            $tahunbulan = date("Ym");
            $kode = $strukmodel->getNewKode($tahunbulan);
            if(empty($kode)){
                $invoicemodel->db->transRollback();
                $tmodel->db->transRollback();
                return $this->fail(["error" => "Generate Nomor Error!"],400,null,'db');
            }

            $strukmodel->db->transBegin();
            $strukmodel->update($struk->id_struk,["nomor" => $kode]);
            if($strukmodel->db->transFailure){
                $strukmodel->db->transRollback();
                $invoicemodel->db->transRollback();
                $tmodel->db->transRollback();
                return $this->fail(["error" => "Database Error!"],400,null,'db');
            }
            $tmodel->db->transCommit();
            $invoicemodel->db->transCommit();
            $strukmodel->db->transCommit();
        }

        foreach($trackingperiode as $key=>$item){
            $historytransmodel = new Historytransmodel();
            $historytransbuilder = $historytransmodel->builder();
            $historytransbuilder->where("id_kk",$key);
            $history = $historytransbuilder->get()->getRow();
            
            if($history){
                $tampperiode = strtotime($history->tahun."-".str_pad($history->bulan,2,"0",STR_PAD_LEFT)."-01");
                if($item > $tampperiode){
                    $update = [
                        "bulan" => date("n",$item),
                        "tahun" => date("Y",$item)
                    ];
                    $historytransmodel->update($history->id_history_trans,$update);
                }
            }else{
                $insert = [
                    "id_grup_transaksi" => $transaksi->id_grup_transaksi,
                    "id_kk" => $key,
                    "bulan" => date("n",$item),
                    "tahun" => date("Y",$item)
                ];
                $historytransmodel->insert($insert);
            }
        }

        return $this->respond($data,200);
    }

    public function upload(){
        $data = array();
        $data['status'] = 'success';

        $id_transaksi = $this->request->getPost('id_transaksi',FILTER_SANITIZE_ADD_SLASHES);
        $file = $this->request->getFile('file');

        if (!$id_transaksi || !$file || !$file->isValid()) {
            return $this->fail('ID atau file tidak valid.', 400);
        }

        $allowedTypes = ['image/jpeg', 'image/png', 'image/jpg', 'image/gif'];
        if (!in_array($file->getMimeType(), $allowedTypes)) {
            return $this->fail('File bukan gambar yang diizinkan.', 400);
        }

        $newName = $id_transaksi . '_' . time() . '.' . $file->getExtension();

        $uploadPath = FCPATH .'bukti_bayar/';
        $file->move($uploadPath, $newName);

        // $buktibayarmodel = new Buktibayarmodel();
        // $buktibayar = $buktibayarmodel->where("id_transaksi",$id_transaksi)->first();
        // if($buktibayar){
        //     if (file_exists(FCPATH . 'bukti_bayar/' . $buktibayar["fnama"])) {
        //         unlink(FCPATH . 'bukti_bayar/' . $buktibayar["fnama"]);
        //     }
        // }

        // $buktibayarmodel = new Buktibayarmodel();
        // $buktibayarmodel->where("id_transaksi",$id_transaksi)->delete();
        
        $buktibayarmodel = new Buktibayarmodel();
        $insert = [
            "id_transaksi" => $id_transaksi,
            "fnama" => $newName
        ];
        $buktibayarmodel->insert($insert);
        return $this->respond($data,200);
    }

    public function upload2()
    {
        $id_transaksi = $this->request->getPost('key',FILTER_SANITIZE_ADD_SLASHES);

        $ph = new PluploadHandler(array(
            'target_dir' => 'bukti_bayar/',
            'allow_extensions' => 'jpg,jpeg,png,gif,bmp'
        ));

        $ph->sendNoCacheHeaders();
        $ph->sendCORSHeaders();

        if ($result = $ph->handleUpload()) {
            if (isset($result['done']))
            {
                $buktibayarmodel = new Buktibayarmodel();
                $insert = [
                    "id_transaksi" => $id_transaksi,
                    "fnama" => $result['name']
                ];
                
                $id_bukti_bayar = $buktibayarmodel->insert($insert);
                if ($id_bukti_bayar)
                {
                    die(json_encode(array(
                        'OK' => 1,
                        'id' => $id_bukti_bayar,
                        'info' => $result
                    )));
                }else{
                    if (file_exists('bukti_bayar/'.$result['name'])){
                        unlink('bukti_bayar/'.$result['name']);
                    }
                    die(json_encode(array(
                        'OK' => 0,
                        'error' => array(
                            'code' => '400',
                            'message' => 'Update Failed'
                        )
                    )));
                }
            }else{
                if (file_exists('bukti_bayar/'.$result['name'])){
                    unlink('bukti_bayar/'.$result['name']);
                }
                die(json_encode(array(
                    'OK' => 0,
                    'error' => array(
                        'code' => $ph->getErrorCode(),
                        'message' => $ph->getErrorMessage()
                    )
                )));
            }
        }else{
            die(json_encode(array(
                'OK' => 0,
                'error' => array(
                    'code' => $ph->getErrorCode(),
                    'message' => $ph->getErrorMessage()
                )
            )));
        }
    }

    public function download_bukti_bayar($id_transaksi){
        $buktibayarmodel = new Buktibayarmodel();
        $data = $buktibayarmodel->where("id_transaksi",$id_transaksi)->first();
        if($data){
            $filePath = FCPATH . 'bukti_bayar/' . $data["fnama"];

            if (!file_exists($filePath)) {
                return $this->failNotFound('File tidak ditemukan.');
            }

            return $this->response->download($filePath, null); // null = pakai nama asli
        }else{
            return $this->failNotFound('File tidak ditemukan.');
        }
    }

    public function delete_bukti_bayar(){
        $data = array();
        $data['status'] = 'success';

        $id_bukti_bayar = $this->request->getPost('id_bukti_bayar',FILTER_SANITIZE_ADD_SLASHES);
        $buktibayarmodel = new Buktibayarmodel();
        $bukti = $buktibayarmodel->where("id_bukti_bayar",$id_bukti_bayar)->first();
        if($bukti){
            $filePath = FCPATH . 'bukti_bayar/' . $bukti["fnama"];

            if (file_exists($filePath)) {
                unlink(FCPATH . 'bukti_bayar/' . $bukti["fnama"]);
            }

            $buktibayarmodel = new Buktibayarmodel();
            $buktibayarmodel->where("id_bukti_bayar",$id_bukti_bayar)->delete();
            return $this->respond($data,200);
        }else{
            return $this->fail(["error" => "Database Error!"],400,null,'db');
        }
    }

    public function cetak_struk($id_struk){
        $user = $this->user->data;
        $data = array();
        $data["company_name"] = COMPANY_NAME;
        $data["company_logo"] = base_url("img/logo_company.png");

        $strukmodel = new Strukmodel();
        $strukbuilder = $strukmodel->builder("vstruk");
        $strukbuilder->where("id_struk",$id_struk);
        $strukbuilder->where("flag_validasi","2");
        $struk = $strukbuilder->get()->getRow();
        if($struk == null){
            die("Struk Not Available!");
        }

        $data["tanggal"] = $struk->tanggal;
        $data["nomor_transaksi"] = $struk->kode_transaksi;
        $data["nomor_struk"] = $struk->nomor;
        $data['kode_rumah'] = $struk->kode_kk;
        $data['nama_pemilik'] = $struk->nama_pemilik;
        $data['alamat'] = $struk->jalan.', '.$struk->blok.', No. '.$struk->nomor_rumah;
        $data['nominal'] = $struk->total_akhir;
        $data['operator'] = empty($struk->nama_operator) ? $user->nama : $struk->nama_operator;
        $data['kolektor'] = $struk->nama_kolektor;
        $data['jenis_pembayaran'] = $struk->jenis_pembayaran;
        $data['tanggal_pembayaran'] = $struk->tanggal_pembayaran;
        $data['receiver'] = $struk->pembayar;
        $data['no_telp'] = $struk->no_telp;

        // ===== Data Transaksi ===== //
        $qr_text = base_url().'transaksi/struk/'.$struk->id_struk;

        // ===== Buat QR Code ===== //
        $writer = new PngWriter();
        $qrCode = new QrCode(
            data: $qr_text,
            encoding: new Encoding('UTF-8'),
            errorCorrectionLevel: ErrorCorrectionLevel::Low,
            size: 100,
            margin: 0,
            roundBlockSizeMode: RoundBlockSizeMode::Margin,
            foregroundColor: new Color(0, 0, 0),
            backgroundColor: new Color(255, 255, 255)
        );

        $result = $writer->write($qrCode);

        ob_start();
        $result->saveToFile('php://output');
        $imageData = ob_get_clean();
        $base64 = base64_encode($imageData);
        $imgSrc = 'data:image/png;base64,' . $base64;

        $data['qr_code'] = $imgSrc;

        $periode = array();
        $invoice = array();

        $strukdetailmodel = new Strukdetailmodel();
        $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
        $strukdetail = $strukdetailbuilder->where("id_struk",$id_struk)->get()->getResultArray();
        foreach($strukdetail as $item){
            $periode[] = $item['bulan'].'-'.$item['tahun'];
            $invoice[] = $item["nomor_invoice"];
        }
        $data["periode"] = implode(", ",$periode);
        $data["nomor_invoice"] = implode(", ",$invoice);

        $html = view('print/struk', $data);

        while (ob_get_level()) {
            ob_end_clean();
        }

        $options = new Options();
        $options->set('isRemoteEnabled', true);
        $dompdf = new Dompdf($options);
        $dompdf->loadHtml($html);
        $dompdf->setPaper([0, 0, 93.2, 241.3], 'portrait'); // 1/3 folio
        $dompdf->render();
        $dompdf->stream('struk_pembayaran.pdf', ['Attachment' => false]);
    }

    public function cetak_multi_struk($id_transaksi){
        $user = $this->user->data;
        $data = array();
        $data["company_name"] = COMPANY_NAME;
        $data["company_logo"] = base_url("img/logo_company.png");
        $data['struks'] = array();

        $strukmodel = new Strukmodel();
        $strukbuilder = $strukmodel->builder("vstruk");
        $strukbuilder->where("id_transaksi",$id_transaksi);
        $strukbuilder->where("flag_validasi","2");
        $struk = $strukbuilder->get()->getResultObject();
        if($struk == null){
            die("Struk Not Available!");
        }

        $i=0;
        foreach($struk as $item){
            $data['struks'][$i]["tanggal"] = $item->tanggal;
            $data['struks'][$i]["nomor_transaksi"] = $item->kode_transaksi;
            $data['struks'][$i]["nomor_struk"] = $item->nomor;
            $data['struks'][$i]['kode_rumah'] = $item->kode_kk;
            $data['struks'][$i]['nama_pemilik'] = $item->nama_pemilik;
            $data['struks'][$i]['alamat'] = $item->jalan.', '.$item->blok.', No. '.$item->nomor_rumah;
            $data['struks'][$i]['nominal'] = $item->total_akhir;
            $data['struks'][$i]['operator'] = empty($item->nama_operator) ? $user->nama : $item->nama_operator;
            $data['struks'][$i]['kolektor'] = $item->nama_kolektor;
            $data['struks'][$i]['jenis_pembayaran'] = $item->jenis_pembayaran;
            $data['struks'][$i]['tanggal_pembayaran'] = $item->tanggal_pembayaran;
            $data['struks'][$i]['receiver'] = $item->pembayar;
            $data['struks'][$i]['no_telp'] = $item->no_telp;

             // ===== Data Transaksi ===== //
            $qr_text = base_url().'transaksi/struk/'.$item->id_struk;

            // ===== Buat QR Code ===== //
            $writer = new PngWriter();
            $qrCode = new QrCode(
                data: $qr_text,
                encoding: new Encoding('UTF-8'),
                errorCorrectionLevel: ErrorCorrectionLevel::Low,
                size: 100,
                margin: 0,
                roundBlockSizeMode: RoundBlockSizeMode::Margin,
                foregroundColor: new Color(0, 0, 0),
                backgroundColor: new Color(255, 255, 255)
            );

            $result = $writer->write($qrCode);

            ob_start();
            $result->saveToFile('php://output');
            $imageData = ob_get_clean();
            $base64 = base64_encode($imageData);
            $imgSrc = 'data:image/png;base64,' . $base64;
            
            $data['struks'][$i]['qr_code'] = $imgSrc;

            $periode = array();
            $invoice = array();

            $strukdetailmodel = new Strukdetailmodel();
            $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
            $strukdetail = $strukdetailbuilder->where("id_struk",$item->id_struk)->get()->getResultArray();
            foreach($strukdetail as $item){
                $periode[] = $item['bulan'].'-'.$item['tahun'];
                $invoice[] = $item["nomor_invoice"];
            }
            $data['struks'][$i]["periode"] = implode(", ",$periode);
            $data['struks'][$i]["nomor_invoice"] = implode(", ",$invoice);

            $i++;
        }

        $html = view('print/multiple_struk', $data);
        
        while (ob_get_level()) {
            ob_end_clean();
        }

        $options = new Options();
        $options->set('isRemoteEnabled', true);
        $dompdf = new Dompdf($options);
        $dompdf->loadHtml($html);
        $dompdf->setPaper([0, 0, 93.2, 241.3], 'portrait'); // 1/3 folio
        $dompdf->render();
        $dompdf->stream('struk_pembayaran.pdf', ['Attachment' => false]);
    }

    public function cetak_multi_struk_kantor($tanggal_awal, $tanggal_akhir){
        $user = $this->user->data;
        $data = array();
        $data["company_name"] = COMPANY_NAME;
        $data["company_logo"] = base_url("img/logo_company.png");
        $data['struks'] = array();

        $strukmodel = new Strukmodel();
        $strukbuilder = $strukmodel->builder("vstruk");
        $strukbuilder->where("tanggal between '".$tanggal_awal."' and '".$tanggal_akhir."'");
        $strukbuilder->where("((id_kolektor is null) or (id_kolektor=''))");
        $strukbuilder->where("flag_validasi","2");
        $struk = $strukbuilder->get()->getResultObject();
        if($struk == null){
            die("Struk Not Available!");
        }

        $i=0;
        foreach($struk as $item){
            $data['struks'][$i]["tanggal"] = $item->tanggal;
            $data['struks'][$i]["nomor_transaksi"] = $item->kode_transaksi;
            $data['struks'][$i]["nomor_struk"] = $item->nomor;
            $data['struks'][$i]['kode_rumah'] = $item->kode_kk;
            $data['struks'][$i]['nama_pemilik'] = $item->nama_pemilik;
            $data['struks'][$i]['alamat'] = $item->jalan.', '.$item->blok.', No. '.$item->nomor_rumah;
            $data['struks'][$i]['nominal'] = $item->total_akhir;
            $data['struks'][$i]['operator'] = empty($item->nama_operator) ? $user->nama : $item->nama_operator;
            $data['struks'][$i]['kolektor'] = $item->nama_kolektor;
            $data['struks'][$i]['jenis_pembayaran'] = $item->jenis_pembayaran;
            $data['struks'][$i]['tanggal_pembayaran'] = $item->tanggal_pembayaran;
            $data['struks'][$i]['receiver'] = $item->pembayar;
            $data['struks'][$i]['no_telp'] = $item->no_telp;

             // ===== Data Transaksi ===== //
            $qr_text = base_url().'transaksi/struk/'.$item->id_struk;

            // ===== Buat QR Code ===== //
            $writer = new PngWriter();
            $qrCode = new QrCode(
                data: $qr_text,
                encoding: new Encoding('UTF-8'),
                errorCorrectionLevel: ErrorCorrectionLevel::Low,
                size: 100,
                margin: 0,
                roundBlockSizeMode: RoundBlockSizeMode::Margin,
                foregroundColor: new Color(0, 0, 0),
                backgroundColor: new Color(255, 255, 255)
            );

            $result = $writer->write($qrCode);

            ob_start();
            $result->saveToFile('php://output');
            $imageData = ob_get_clean();
            $base64 = base64_encode($imageData);
            $imgSrc = 'data:image/png;base64,' . $base64;
            
            $data['struks'][$i]['qr_code'] = $imgSrc;

            $periode = array();
            $invoice = array();

            $strukdetailmodel = new Strukdetailmodel();
            $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
            $strukdetail = $strukdetailbuilder->where("id_struk",$item->id_struk)->get()->getResultArray();
            foreach($strukdetail as $item){
                $periode[] = $item['bulan'].'-'.$item['tahun'];
                $invoice[] = $item["nomor_invoice"];
            }
            $data['struks'][$i]["periode"] = implode(", ",$periode);
            $data['struks'][$i]["nomor_invoice"] = implode(", ",$invoice);

            $i++;
        }

        $html = view('print/multiple_struk', $data);

        while (ob_get_level()) {
            ob_end_clean();
        }
        $dompdf = new \Dompdf\Dompdf();
        $dompdf->loadHtml($html);
        $dompdf->setPaper([0, 0, 612, 312], 'portrait'); // 1/3 folio
        $dompdf->render();
        $dompdf->stream('struk_pembayaran_kantor.pdf', ['Attachment' => false]);
    }

    public function cetak_multi_struk_kolektor($tanggal_awal, $tanggal_akhir){
        $user = $this->user->data;
        $data = array();
        $data["company_name"] = COMPANY_NAME;
        $data["company_logo"] = base_url("img/logo_company.png");
        $data['struks'] = array();

        $strukmodel = new Strukmodel();
        $strukbuilder = $strukmodel->builder("vstruk");
        $strukbuilder->where("tanggal between '".$tanggal_awal."' and '".$tanggal_akhir."'");
        $strukbuilder->where("((not id_kolektor is null) and (id_kolektor <> ''))");
        $strukbuilder->where("flag_validasi","2");
        $struk = $strukbuilder->get()->getResultObject();
        if($struk == null){
            die("Struk Not Available!");
        }

        $i=0;
        foreach($struk as $item){
            $data['struks'][$i]["tanggal"] = $item->tanggal;
            $data['struks'][$i]["nomor_transaksi"] = $item->kode_transaksi;
            $data['struks'][$i]["nomor_struk"] = $item->nomor;
            $data['struks'][$i]['kode_rumah'] = $item->kode_kk;
            $data['struks'][$i]['nama_pemilik'] = $item->nama_pemilik;
            $data['struks'][$i]['alamat'] = $item->jalan.', '.$item->blok.', No. '.$item->nomor_rumah;
            $data['struks'][$i]['nominal'] = $item->total_akhir;
            $data['struks'][$i]['operator'] = empty($item->nama_operator) ? $user->nama : $item->nama_operator;
            $data['struks'][$i]['kolektor'] = $item->nama_kolektor;
            $data['struks'][$i]['jenis_pembayaran'] = $item->jenis_pembayaran;
            $data['struks'][$i]['tanggal_pembayaran'] = $item->tanggal_pembayaran;
            $data['struks'][$i]['receiver'] = $item->pembayar;
            $data['struks'][$i]['no_telp'] = $item->no_telp;

             // ===== Data Transaksi ===== //
            $qr_text = base_url().'transaksi/struk/'.$item->id_struk;

            // ===== Buat QR Code ===== //
            $writer = new PngWriter();
            $qrCode = new QrCode(
                data: $qr_text,
                encoding: new Encoding('UTF-8'),
                errorCorrectionLevel: ErrorCorrectionLevel::Low,
                size: 100,
                margin: 0,
                roundBlockSizeMode: RoundBlockSizeMode::Margin,
                foregroundColor: new Color(0, 0, 0),
                backgroundColor: new Color(255, 255, 255)
            );

            $result = $writer->write($qrCode);

            ob_start();
            $result->saveToFile('php://output');
            $imageData = ob_get_clean();
            $base64 = base64_encode($imageData);
            $imgSrc = 'data:image/png;base64,' . $base64;
            
            $data['struks'][$i]['qr_code'] = $imgSrc;

            $periode = array();
            $invoice = array();

            $strukdetailmodel = new Strukdetailmodel();
            $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
            $strukdetail = $strukdetailbuilder->where("id_struk",$item->id_struk)->get()->getResultArray();
            foreach($strukdetail as $item){
                $periode[] = $item['bulan'].'-'.$item['tahun'];
                $invoice[] = $item["nomor_invoice"];
            }
            $data['struks'][$i]["periode"] = implode(", ",$periode);
            $data['struks'][$i]["nomor_invoice"] = implode(", ",$invoice);

            $i++;
        }

        $html = view('print/multiple_struk', $data);

        while (ob_get_level()) {
            ob_end_clean();
        }
        
        $dompdf = new \Dompdf\Dompdf();
        $dompdf->loadHtml($html);
        $dompdf->setPaper([0, 0, 612, 312], 'portrait'); // 1/3 folio
        $dompdf->render();
        $dompdf->stream('struk_pembayaran_kolektor.pdf', ['Attachment' => false]);

    }

    public function cetak_bukti_bayar($tanggal_awal, $tanggal_akhir){
        $data = array();
        $data["company_name"] = COMPANY_NAME;
        $data["start_date"] = $tanggal_awal;
        $data["end_date"] = $tanggal_akhir;
        $data['bukti'] = array();

        $buktimodel = new Buktibayarmodel();
        $buktibuilder = $buktimodel->builder("vbuktibayar");
        $buktibuilder->where("tanggal between '".$tanggal_awal."' and '".$tanggal_akhir."'");
        $buktibuilder->where("flag_validasi","2");
        $bukti = $buktibuilder->get()->getResultObject();
        if($bukti == null){
            die("Bukti Not Available!");
        }

        $i=0;
        foreach($bukti as $item){
            $data['bukti'][$i]["nomor"] = $item->kode;
            $data['bukti'][$i]["tanggal"] = (empty($item->tanggal_pembayaran) ? $item->tanggal : $item->tanggal_pembayaran);
            $data['bukti'][$i]["fnama"] = $item->fnama;

            $lokalPath = FCPATH . 'bukti_bayar/' . $item->fnama;
            $type = pathinfo($lokalPath, PATHINFO_EXTENSION);
            $isi_gambar = file_get_contents($lokalPath);
            $base64 = 'data:image/' . $type . ';base64,' . base64_encode($isi_gambar);

            $data['bukti'][$i]["gambar"] = $base64;
            $i++;
        }

        $html = view('print/bukti_bayar', $data);
        while (ob_get_level()) {
            ob_end_clean();
        }
        $dompdf = new \Dompdf\Dompdf();
        $dompdf->loadHtml($html);
        $dompdf->setPaper('A4', 'portrait');
        $dompdf->render();
        $dompdf->stream('bukti_bayar.pdf', ['Attachment' => false]);
        //return view('print/bukti_bayar', $data);

    }

    public function pembatalan(){
        $data['user'] = $this->user->data;

        $db = db_connect();
        $data['total_canceled'] = $db->table("transaksi")->where("flag_validasi","3")->countAllResults();

        return view('admin/transaksi/pembatalan/index',$data);
    }

    public function ajax_dt_pembatalan(){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Transaksimodel();
        $extra = "((flag_validasi = 3) or (flag_batal=1))";
        return $DataModel->GetDT($data_post,$extra);
    }

    public function view_pembatalan($id) {
        $data['user'] = $this->user->data;
        $tmodel = new Transaksimodel();

        $builder = $tmodel->builder("vtransaksi");
        $data['transaksi'] = $builder->where("id_transaksi",$id)->get()->getRow();
        $data['total_transaksi'] = 0;
        $data['total_diskon'] = 0;
        $data['total_akhir'] = 0;

        $detail_transaksi = array();
        $builder = $tmodel->builder("vstruk");
        $data_struk = $builder->where("id_transaksi",$id)->get()->getResultArray();
        $detail_transaksi = array();
        $no = 0;
        foreach($data_struk as $item){
            $detail_transaksi[$no]["id_struk"] = $item["id_struk"];
            $detail_transaksi[$no]["id_kk"] = $item["id_kk"];
            $detail_transaksi[$no]["nomor_struk"] = $item["nomor"];
            $detail_transaksi[$no]["kode_kk"] = $item["kode_kk"];
            $detail_transaksi[$no]["alamat"] = $item["nama_jalan"].', '.$item["nama_blok"].','.$item["nomor_rumah"];
            $detail_transaksi[$no]["total"] = $item["total_struk"];
            $detail_transaksi[$no]["total_diskon"] = $item["total_diskon"];
            $detail_transaksi[$no]["total_akhir"] = $item["total_akhir"];
            $data['total_transaksi'] += $item["total_struk"];
            $data['total_diskon'] += $item["total_diskon"];
            $data['total_akhir'] += $item["total_akhir"];
            $detail_transaksi[$no]["periode"] = "";

            $periode = array();
            $builder = $tmodel->builder("vstrukdetail");
            $data_struk_detail = $builder->where("id_struk",$item["id_struk"])->get()->getResultArray();
            foreach($data_struk_detail as $item2){
                $periode[] = $item2['bulan'].'-'.$item2['tahun'];
            }
            $detail_transaksi[$no]["periode"] = implode(",",$periode);
            $no++;
        }

        $data['detail_transaksi'] = $detail_transaksi;

        $data_total = [
            "total" => $data['total_transaksi'],
            "total_diskon" => $data['total_diskon'],
            "total_akhir" => $data['total_akhir']
        ];
        $tmodel->update($id,$data_total);

        $buktibayarmodel = new Buktibayarmodel();
        $data['bukti_bayar'] = $buktibayarmodel->where("id_transaksi",$id)->findAll();
        return view('admin/transaksi/pembatalan/view',$data);
    }

    public function warga(){
        $data['user'] = $this->user->data;

        $db = db_connect();
        $data['total_kk'] = $db->table("kk")->where("deleted_at is null")->countAllResults();
        $transaksimodel = new Transaksimodel();
        $data['total_penerimaan'] = $transaksimodel->getTotalPenerimaan();
        $data['total_tunggakan'] = $transaksimodel->getTotalTunggakan();

        return view('admin/transaksi/warga/index',$data);
    }

    public function ajax_dt_warga(){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Transaksimodel();
        return $DataModel->GetDTWarga($data_post,"");
    }

    public function warga_detail($id_kk){
        $data['user'] = $this->user->data;
        
        $kkmodel = new Kkmodel();
        $kkbuilder = $kkmodel->builder("vkk_rekap");
        $kkbuilder->where("id_kk",$id_kk);
        $data["kk"] = $kkbuilder->get()->getRow();
        
        if(!$data["kk"]){
            return redirect()->to("transaksi/warga");
        }

        return view('admin/transaksi/warga/detail',$data);
    }

    public function ajax_dt_warga_tunggakan($id_kk){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Invoicemodel();
        $extra = "((id_kk ='".$id_kk."'))";
        return $DataModel->GetDTOpen($data_post,$extra);
    }

    public function ajax_dt_warga_penerimaan($id_kk){
        $data_post = [
            'draw' => $this->request->getPost('draw'),
            'columns' => $this->request->getPost('columns'),
            'order' => $this->request->getPost('order'),
            'start' => $this->request->getPost('start'),
            'length' => $this->request->getPost('length'),
            'search' => $this->request->getPost('search'),
            'searchBuilder' => $this->request->getPost('searchBuilder'),
        ];
        $DataModel = new Strukmodel();
        $extra = "((id_kk ='".$id_kk."') and (flag_validasi='2'))";
        return $DataModel->GetDT($data_post,$extra);
    }

    public function pelunasan_invoice()
    {
        $data['user'] = $this->user->data;

        $db = db_connect();
        $data['total_kk'] = $db->table("kk")->countAll();
        $data['total_open_invoice'] = $db->table("invoice")->where("flag_close","0")->countAllResults();

        return view('admin/transaksi/pelunasan_invoice',$data);
    }

    public function proses_pelunasan_invoice() {
        $startDate = $this->request->getPost('start_date');
        $endDate = $this->request->getPost('end_date');
        $page = $this->request->getPost('page');
        $limit = $this->request->getPost('limit');
        $id_grup_transaksi = $this->request->getPost('id_grup_transaksi');
        $id_kk = $this->request->getPost('id_kk');

        if(empty($id_grup_transaksi) || empty($id_kk)){
            return $this->response->setJSON([
                'success' => false,
                'hasNext' => false
            ]);
        }

        $offset = ($page - 1) * $limit;

        $kkmodel = new Kkmodel();
        //$wargaList = $kkmodel->orderBy('id_kk')->findAll($limit, $offset);

        $invoicemodel = new Invoicemodel();
        // Loop semua tanggal antara start dan end (bisa bulanan atau harian tergantung logikamu)
        $current = strtotime($startDate);
        $end = strtotime($endDate);

        while ($current <= $end) {
            $month = date('m', $current);
            $year = date('Y', $current);

            $existing = $invoicemodel
                ->where('id_kk', $id_kk)
                ->where('bulan', $month)
                ->where('tahun', $year)
                ->first();

            $tarif = 0;
            $id_tarif = "";

            $diskon = 0;
            $id_diskon = 0;

            $tarifmodel = new Tarifmodel();
            $db_tarif = $tarifmodel->db;
            $cek_date = $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-01";
            $query_tarif = $db_tarif->query("select * from tarif where id_kk='".$id_kk."' and start_date <='".$cek_date."' and (end_date >= '".$cek_date."' or end_date='9999-12-31') and deleted_at is null order by end_date desc");

            $tarif_row = $query_tarif->getRow();

            if($tarif_row != null){
                $id_tarif = $tarif_row->id_tarif;
                $tarif = $tarif_row->nominal;
            }

            $diskonmodel = new Diskonmodel();
            $db_diskon = $diskonmodel->db;
            $cek_date = $year."-".str_pad($month,2,"0",STR_PAD_LEFT)."-01";
            $query_diskon = $db_diskon->query("select * from diskon where id_kk='".$id_kk."' and start_date <='".$cek_date."' and (end_date >= '".$cek_date."' or end_date='9999-12-31') and deleted_at is null order by end_date desc");

            $diskon_row = $query_diskon->getRow();

            if($diskon_row != null){
                $id_diskon = $diskon_row->id_diskon;
                $diskon = $diskon_row->nominal;
            }

            if ($existing) {
                if($existing['flag_close'] == '0'){
                    $tmodel = new Transaksimodel();
                    $strukmodel = new Strukmodel();
                    $strukdetailmodel = new Strukdetailmodel();

                    $tmodel->db->transBegin();
                    $strukmodel->db->transBegin();
                    $strukdetailmodel->db->transBegin();

                    $request = [
                        'id_grup_transaksi' => $id_grup_transaksi,
                        'id_kolektor' => "",
                        'tanggal' => date("Y-m-d H:i:s", $current),
                        'id_operator' => $this->user->data->id_operator,
                        'created_by' => $this->user->data->id_auth,
                        'updated_by' => $this->user->data->id_auth
                    ];

                    $id_transaksi = $tmodel->insert($request);
                    if($tmodel->db->transStatus() === false){
                        $tmodel->db->transRollback();
                    }else{
                        $data_struk = [
                            "id_transaksi" => $id_transaksi,
                            "id_kk" => $id_kk 
                        ];
                        $id_struk = $strukmodel->insert($data_struk);

                        $total = 0;
                        $total_diskon = 0;
                        $total_akhir = 0;

                        //clear detail struk untuk transaksi ini
                        $strukdetail_builder = $strukdetailmodel->builder();
                        $strukdetailmodel->db->transBegin();
                        $strukdetail_builder->delete(["id_struk" => $id_struk]);
                        
                        $strukdetailmodel = new Strukdetailmodel();
                        $strukdetailbuilder = $strukdetailmodel->builder("vstrukdetail");
                        $strukdetailbuilder->where("id_invoice",$existing["id_invoice"]);
                        $strukdetailbuilder->where("id_transaksi != ",$id_transaksi);
                        $strukdetailbuilder->where("flag_batal","0");
                        $strukdetail = $strukdetailbuilder->get()->getRow();
                        if($strukdetail != null){
                            $strukmodel->db->transRollback();
                            $strukdetailmodel->db->transRollback();
                            $tmodel->db->transRollback();
                        }else{
                            $detail_struk=[
                                "id_struk_detail" => date("YmdHis.u").$id_struk.$existing["id_invoice"],
                                "id_struk" => $id_struk,
                                "id_invoice" => $existing["id_invoice"],
                                "bulan" => $existing["bulan"],
                                "tahun" => $existing["tahun"],
                                "nominal" => $existing["nominal"],
                                "nominal_diskon" => $existing["nominal_diskon"],
                                "nominal_total" => $existing["nominal_akhir"],
                                "created_by" => $this->user->data->id_auth,
                                "updated_by" => $this->user->data->id_auth
                            ];
                            $total += $existing['nominal'];
                            $total_diskon += $existing['nominal_diskon'];
                            $total_akhir += $existing['nominal_akhir'];
                            $strukdetailmodel->insert($detail_struk);

                            if($strukdetailmodel->db->transFailure){
                                $strukmodel->db->transRollback();
                                $strukdetailmodel->db->transRollback();
                                $tmodel->db->transRollback();
                            }else{
                                //update total di struk
                                $data_struk = [
                                    "total" => $total,
                                    "total_diskon" => $total_diskon,
                                    "total_akhir" => $total_akhir 
                                ];

                                $strukmodel->update($id_struk,$data_struk);
                                if($strukmodel->db->transFailure){
                                    $strukdetailmodel->db->transRollback();
                                    $strukmodel->db->transRollback();
                                    $tmodel->db->transRollback();
                                }else{
                                    //Update data di transaksi
                                    $update = [
                                        "total" => 0,
                                        "total_diskon" => 0,
                                        "total_akhir" => 0
                                    ];

                                    $strukmodel = new Strukmodel();
                                    $struks = $strukmodel->where("id_transaksi",$id_transaksi)->findAll();
                                    foreach($struks as $struk){
                                        $update["total"] += $struk["total"];
                                        $update["total_diskon"] += $struk["total_diskon"];
                                        $update["total_akhir"] += $struk["total_akhir"];
                                    }

                                    $transaksimodel = new Transaksimodel();
                                    $transaksimodel->db->transBegin();
                                    $transaksimodel->update($id_transaksi,$update);
                                    if($transaksimodel->db->transFailure){
                                        $strukdetailmodel->db->transRollback();
                                        $strukmodel->db->transRollback();
                                        $transaksimodel->db->transRollback();
                                        $tmodel->db->transRollback();
                                    }else{
                                        $request = [
                                            'flag_batal' => "0",
                                            'flag_validasi' => "2",
                                            'tanggal_validasi' => date("Y-m-d H:i:s"),
                                            'id_jenis_pembayaran' => "1",
                                            'tanggal_pembayaran' => date("Y-m-d H:i:s",$current),
                                            'pembayar' => "",
                                            'no_telp' => "",
                                            'keterangan_validasi' => "Created By System",
                                            'id_operator' => $this->user->data->id_operator,
                                            'updated_by' => $this->user->data->id_auth
                                        ];

                                        $tmodel->update($id_transaksi,$request);
                                        if($tmodel->db->transFailure){
                                            $strukdetailmodel->db->transRollback();
                                            $strukmodel->db->transRollback();
                                            $transaksimodel->db->transRollback();
                                            $tmodel->db->transRollback();
                                        }else{
                                            $strukmodel->db->transComplete();
                                            $strukdetailmodel->db->transComplete();
                                            $transaksimodel->db->transComplete();
                                            $tmodel->db->transComplete();

                                            $tmodel = new Transaksimodel();
                                            $kode = $tmodel->getNewKode();
                                            $request = ["kode" => $kode];
                                            $tmodel->update($id_transaksi, $request);

                                            $invoicemodel = new Invoicemodel();
                                            $invoicemodel->update($existing["id_invoice"],["flag_close" => "1"]);

                                            $strukmodel = new Strukmodel();
                                            $strukbuilder = $strukmodel->builder();
                                            $strukbuilder->where("id_transaksi",$id_transaksi);
                                            $struks = $strukbuilder->get()->getResultObject();

                                            foreach($struks as $struk){
                                                $tahunbulan = date("Ym", $current);
                                                $kode = $strukmodel->getNewKode($tahunbulan);
                                                
                                                if(!empty($kode)){
                                                    $strukmodel->update($struk->id_struk,["nomor" => $kode]);
                                                }
                                            }
                                        }
                                    }
                                }
                            }
                        }
                    }
                }
            }

            $current = strtotime('+1 month', $current);
        }

        return $this->response->setJSON([
            'success' => true,
            'hasNext' => false
        ]);
    }
}
?>