Files
cmasa/app/Controller/Inv/JualController.php
T
2026-10-29 13:34:31 +07:00

568 lines
31 KiB
PHP

<?php
/*******************************************************************
PHP Class : /Controller/Inv/JualController
Description : Transaksi Penjualan
Created By : Siau Pheng ([email protected]).
Created Date : May 22th, 2010.
Last Modified : September 27th, 2026.
(c) 3FONIA Software; WWW.3FONIA.COM.
*******************************************************************/
declare(strict_types=1);
namespace App\Controller\Inv;
use App\Utils\Inv;
use App\Utils\Gel;
use flight\Engine;
use flight\database\SimplePdo;
use flight\Session;
use Webapp\DB\SQL;
use Webapp\Web\Form;
use Webapp\Web\Param;
use Webapp\Web\Table;
class JualController {
private array $web_app;
private array $app_gel;
private int $id_cab;
private int $id_member;
private int $id_grup_member;
private string $mode;
private string $mode_detail;
private string $no_jual;
private bool $is_pend;
private int $id_inv;
private int $id_satuan;
private int $id_varian;
private Inv $inv;
private Gel $gel;
protected Engine $app;
protected SimplePdo $db;
public function __construct(Engine $app, SimplePdo $db, Session $session) {
$this->app = $app;
$this->db = $db;
$this->web_app = (array) $session->get('WEB_APP');
$this->app_gel = (array) $session->get('APP_GEL');
$this->id_cab = Param::Int("CabID", $session->get('APP_INV')['CABANGID']);
$this->id_member = Param::Int("MemberID", 0);
$this->id_grup_member = Param::Int("Grup_MemberID", $session->get('APP_INV')['ECERANID']);
$this->mode = Param::Get("mode", "");
$this->mode_detail = Param::Get("mode_detail", "");
$this->no_jual = Param::Get("No_Jual", "");
$this->is_pend = str_contains($this->no_jual, "JUAL") === true;
$this->id_inv = Param::Int("InvID", 0);
$this->id_satuan = Param::Int("SatuanID", 0);
$this->id_varian = Param::Int("VarianID", 0);
$this->inv = new Inv($app);
$this->gel = new Gel($app);
}
public function table_detail() {
if (in_array($this->mode_detail, ["insert","update","delete"])) {
$iqty = Param::Float("Qty", 0) * -1;
$disk_rp = Param::Float("Disk_Rupiah", 0);
$disk_psn = Param::Float("Disk_Persen", 0);
if ($disk_psn > 0) $disk_rp = Param::Float("Harga_Jual", 0) * $disk_psn * 0.01;
if ($iqty === 0) $disk_rp = 0;
$sql = new SQL($this->app);
$sql->set_table("tmp_inv_detail");
$sql->add_param("No_Ref", $this->no_jual);
$sql->add_param("InvID");
$sql->add_param("SatuanID");
$sql->add_param("VarianID");
$sql->add_param("Qty", $iqty);
$sql->add_param("Harga_Beli");
$sql->add_param("Harga_Jual");
$sql->add_param("Disk_Rupiah", $disk_rp);
$sql->add_param("Total_Diskon", "Disk_Rupiah*-Qty", true);
$sql->add_param_unix();
$sql->add_param_userid();
$sql->add_where("ID");
$sql->add_where("No_Ref", $this->no_jual);
if ( $this->mode_detail === "insert" ) {
$sql->InsertDB();
} else if ( $this->mode_detail === "update" ) {
$sql->UpdateDB();
} else if ( $this->mode_detail === "delete" ) {
$sql->DeleteDB();
}
}
$tsql = ''; $asql = [$this->no_jual]; $qtabel = "inv_detail";
if ($this->is_pend) $qtabel = "tmp_inv_detail";
if (in_array($this->mode, ["add","edit"])) {
if ($this->mode === "add") { $tsql = " AND Unix=?"; $asql[] = $this->app->user()->unix(); }
$qtabel = "tmp_inv_detail";
}
$obj = new Table($this->app);
$obj->set_table("(SELECT * FROM ".$qtabel." WHERE No_Ref=?".$tsql.") D LEFT JOIN vi_inv_produk P ON (D.InvID=P.InvID AND D.SatuanID=P.SatuanID AND D.VarianID=P.VarianID)", "D.*,-D.Qty Qty2,P.Kode_SKU,P.Nama_Lengkap,(-D.Qty*D.Harga_Jual)-D.Total_Diskon Total", "", $asql);
$obj->set_footer("COUNT(*) Harga_Jual,SUM(D.Total_Diskon) Disk_Rupiah,SUM((-D.Qty*D.Harga_Jual)-D.Total_Diskon) Total");
$obj->add_field("ID", "No", "c");
$obj->add_field("InvID", "InvID", "hid");
$obj->add_field("SatuanID", "SatuanID", "hid");
$obj->add_field("VarianID", "VarianID", "hid");
$obj->add_field("Kode_SKU", "SKU", "c");
$obj->add_field("Nama_Lengkap", "Nama Barang", "awr");
$obj->add_field("Qty2", "Qty", "r", "rupiah2");
$obj->add_field("Harga_Jual", "Harga @", "r", "rupiah", "items");
$obj->add_field("Disk_Rupiah", "Diskon @", "r", "rupiah", "rupiah");
$obj->add_field("Total", "Jumlah", "r", "rupiah", "rupiah");
$obj->add_field("Promo", "S", "c", [0=>"N",1=>"T",2=>"D",3=>"P",4=>"H"]);
$obj->set_field_order("ID", "D");
if (in_array($this->mode, ["add","edit"])) {
$obj->add_row_btn("clipboard", "Ubah", "JualJS.detail_ubah");
$obj->add_row_btn("trash", "Hapus", "JualJS.detail_hapus", "Unix", $this->app->user()->unix());
$obj->set_func_btn("JualJS.produk_brow", '<i class="bi-table me-1"></i> Browse');
}
$ajson[] = $obj->json_table("divDetailTabel");
$this->app->json($ajson);
}
public function brow_tx() {
$tcari = Param::Get("Cari_TX");
$tsql1 = ''; $tsql2 = ''; $asql = [$this->id_cab];
if (!empty($tcari)) {
$tsql2 .= "CONCAT(J.No_Jual,DATE_FORMAT(J.Tgl_Jual,'%d-%m-%Y'),B.Nama_Member) LIKE ?";
array_push($asql, '%' . $tcari . '%');
}
$obj = new Table($this->app);
$obj->set_table("(SELECT *,Total_Jual-Total_Diskon Jumlah FROM inv_jual WHERE POS=0 AND CabID=?".$tsql1.") J LEFT JOIN para_member B ON (J.MemberID=B.MemberID)", "J.*,B.Nama_Member", $tsql2, $asql);
$obj->add_field("No_Jual", "No. Trans", "c");
$obj->add_field("Tgl_Jual", "Tgl. Trans", "c", "sqltgl", "", "val-tgl");
$obj->add_field("Nama_Member", "Nama Member", "awr");
$obj->add_field("Total_Jual", "Sub. Total", "r", "rupiah2");
$obj->add_field("Total_Diskon", "Diskon", "r", "rupiah2");
$obj->add_field("Jumlah", "Jumlah", "r", "rupiah2");
$obj->set_field_order("No_Jual", "D");
$obj->set_func_select("JualJS.tx_select");
$this->app->json([ $obj->db_table("divBrowTX") ]);
}
public function brow_pending() {
$obj = new Table($this->app);
$obj->set_table("(SELECT *,Total_Jual-Total_Diskon Jumlah FROM inv_jual_pend WHERE POS=0 AND CabID=? AND UserID=?) J LEFT JOIN para_member B ON (J.MemberID=B.MemberID)", "J.*,B.Nama_Member", "", [$this->id_cab, $this->app->user()->id()]);
$obj->add_field("No_Jual", "No. Trans", "c");
$obj->add_field("Tgl_Jual", "Tgl. Pending", "c", "sqltgl", "", "val-tgl");
$obj->add_field("Nama_Member", "Nama Member", "awr");
$obj->add_field("Total_Jual", "Sub. Total", "r", "rupiah2");
$obj->add_field("Total_Diskon", "Diskon", "r", "rupiah2");
$obj->add_field("Jumlah", "Jumlah", "r", "rupiah2");
$obj->set_field_order("No_Jual", "D");
$obj->add_row_btn("save", "Pilih", "JualJS.pending_select");
if ($this->app->user()->is_level(1)) $obj->add_row_btn("trash", "Hapus", "JualJS.pending_delete", "UserID", $this->app->user()->id());
$this->app->json([ $obj->db_table("divBrowPending") ]);
}
public function brow_member() {
$tcari = Param::Get("Cari_Member");
$tsql = ''; $asql = [1];
if (!empty($tcari)) {
$tsql .= " AND CONCAT_WS(Kode_Member,Nama_Member,Alamat_Member,Telp_Member) LIKE ?";
$asql[] = '%' . $tcari . '%';
}
$obj = new Table($this->app);
$obj->set_table("para_member", "*", "Aktif=?".$tsql, $asql);
$obj->add_field("MemberID", "ID", "hid");
$obj->add_field("Grup_MemberID", "Grup ID", "hid");
$obj->add_field("Kode_Member", "Kode", "c");
$obj->add_field("Nama_Member", "Nama Member", "awr");
$obj->add_field("Alamat_Member", "Alamat", "awr");
$obj->add_field("Telp_Member", "Telp.", "awr");
$obj->set_field_order("Nama_Member", "A");
$obj->set_func_select("JualJS.member_select");
$this->app->json([ $obj->db_table("divBrowMember") ]);
}
public function brow_produk() {
$tcari = Param::Get("Cari_Produk");
$tsql = ''; $asql = [1, $this->id_grup_member];
if (!empty($tcari)) {
$tsql .= " AND Barcode_Nama LIKE ?";
$asql[] = '%' . $tcari . '%';
}
$obj = new Table($this->app);
$obj->set_table("inv_produk_join", "*", "Aktif=? AND Grup_MemberID=? AND Harga_Jual>0".$tsql, $asql);
$obj->add_field("InvID", "ID", "hid");
$obj->add_field("SatuanID", "ID", "hid");
$obj->add_field("VarianID", "ID", "hid");
$obj->add_field("Kode_SKU", "SKU", "c");
$obj->add_field("Kode_Barcode", "Barcode", "c");
$obj->add_field("Nama_Lengkap", "Nama Barang", "awr");
$obj->add_field("Harga_Jual", "Harga Jual", "r", "rupiah");
$obj->set_field_order("Kode_SKU", "A");
$obj->set_func_select("JualJS.produk_select");
$this->app->json([ $obj->db_table("divBrowProduk") ]);
}
public function auto_member() {
$tcari = Param::Get("Auto_Query", "");
$ajson['autodata'] = [];
$stat = $this->db->runQuery("SELECT MemberID,Grup_MemberID,Kode_Member,Nama_Member,CONCAT(IF(Kode_Member='','',CONCAT(Kode_Member,' - ')),Nama_Member) Kode_Nama FROM para_member WHERE Aktif=1 AND CONCAT(Kode_Member,Nama_Member,Alamat_Member,Telp_Member) LIKE ? ORDER BY Nama_Member LIMIT 50", ['%'.$tcari.'%']);
while ($row = $stat->fetch(SimplePdo::FETCH_ASSOC)) {
$ajson['autodata'][] = ['value'=>$row['MemberID'], 'text'=>$row['Kode_Nama'], 'html'=>'<span class="text-primary">'.$row['Kode_Member'].'</span> '.$row['Nama_Member'], 'data'=>$row['Grup_MemberID'], 'bc'=>0];
}
$this->app->json($ajson);
}
public function auto_produk() {
$tcari = Param::Get("Auto_Query", "");
$ajson['autodata'] = [];
$bcode = 0; $arec = [];
if (is_numeric($tcari) && strlen($tcari) === 8) {
// Cari by Member
// M : Grup_Member
$_row = $this->db->fetchRow("SELECT MemberID InvID,Nama_Member Nama_Lengkap,CONCAT('M:',Grup_MemberID) Data2 FROM para_member WHERE Aktif=1 AND Kode_Member=?", [$tcari]);
if ($_row) {
$bcode = 1;
$arec = $_row->getData();
}
}
// Cari by SKU + Barcode
// P : Satuan : Varian : Harga_Pokok : Harga_Jual : Stok
if ($bcode === 0) {
$_row = $this->db->fetchRow("SELECT P.InvID,P.Nama_Lengkap,CONCAT('P:',P.SatuanID,':',P.VarianID,':',CONVERT(P.Harga_Pokok USING UTF8),':',CONVERT(P.Harga_Jual USING UTF8),':',CONVERT(IFNULL(X.Stok,0) USING UTF8)) Data2 FROM (SELECT * FROM inv_produk_join WHERE Aktif=1 AND Harga_Jual>0 AND Grup_MemberID=? AND (Kode_SKU=? OR Kode_Barcode=?)) P LEFT JOIN inv_stok X ON (X.CabID=? AND X.InvID=P.InvID)", [$this->id_grup_member, $tcari, $tcari, $this->id_cab]);
if ($_row) {
$bcode = 1;
$arec = $_row->getData();
}
}
if ($bcode === 1) {
$ajson['autodata'][] = ['value'=>$arec['InvID'], 'text'=>$arec['Nama_Lengkap'], 'data'=>$arec['Data2'], 'bc'=>1];
} else {
$stat = $this->db->runQuery("SELECT P.InvID,P.Nama_Lengkap,P.Kode_SKU,IF(IFNULL(X.Stok,0)=0,'KOSONG',ROUND(X.Stok/P.Qty,2)) Sisa_Stok,P.Harga_Jual,CONCAT('P:',P.SatuanID,':',P.VarianID,':',CONVERT(P.Harga_Pokok USING UTF8),':',CONVERT(P.Harga_Jual USING UTF8),':',CONVERT(IFNULL(X.Stok,0) USING UTF8)) Data2 FROM (SELECT * FROM inv_produk_join WHERE Barcode_Nama LIKE ? AND Aktif=1 AND Harga_Jual>0 AND Grup_MemberID=?) P LEFT JOIN inv_stok X ON (X.CabID=? AND X.InvID=P.InvID) ORDER BY P.Nama_Produk,P.Qty LIMIT 50", ['%'.$tcari.'%', $this->id_grup_member, $this->id_cab]);
while ($row = $stat->fetch(SimplePdo::FETCH_ASSOC)) {
$ajson['autodata'][] = ['value'=>$row['InvID'], 'text'=>$row['Nama_Lengkap'], 'html'=>'<span class="text-primary">'.$row['Kode_SKU'].'</span> '.$row['Nama_Lengkap'].' - <strong>Rp'.rupiah($row['Harga_Jual']).'</strong> <span class="text-danger">('.(string) $row['Sisa_Stok'].')</span>', 'data'=>$row['Data2'], 'bc'=>0];
}
}
$this->app->json($ajson);
}
public function form_master() {
$ajson = [ 'error'=>"", 'html'=>"" ];
$atabel = [];
if ($this->mode === "pending-edit") {
$this->inv->Pending_Edit($this->no_jual);
$atabel = $this->Data_Jual($this->no_jual);
$this->mode = "edit";
} else if ($this->mode === "pending-save") {
$b_baru = false;
if (str_ends_with($this->no_jual, "#00")) {
$b_baru = true;
$no_lama = $this->no_jual;
$this->no_jual = $this->Pending_Nomor();
$this->inv->Pending_Save($no_lama, $this->no_jual);
}
$apending = $this->db->fetchRow("SELECT SUM(-Qty*Harga_Jual) Jual,SUM(Total_Diskon) Diskon FROM tmp_inv_detail WHERE No_Ref=?", [$this->no_jual]) ?? ['Jual'=>0, 'Diskon'=>0];
$sql = new SQL($this->app);
$sql->set_table("inv_jual_pend");
$sql->add_param("No_Jual", $this->no_jual);
$sql->add_param_date("Tgl_Jual");
$sql->add_param("CabID");
$sql->add_param("MemberID");
$sql->add_param("Total_Jual", $apending['Jual']);
$sql->add_param("Total_Diskon", $apending['Diskon']);
$sql->add_param("POS", 0);
$sql->add_param_userid();
$sql->add_where("No_Jual", $this->no_jual);
if ($b_baru) $sql->InsertDB();
else $sql->UpdateDB();
$atabel = $this->Data_Jual();
} else if ($this->mode === "pending-delete") {
$this->inv->Pending_Delete($this->no_jual);
$this->db->delete("inv_jual_pend", "No_Jual=?", [$this->no_jual]);
$atabel = $this->Data_Jual();
} else if ($this->mode === "add") {
$atabel = $this->Data_Jual("", true);
} else if ($this->mode === "edit") {
$this->inv->Detail_Copy($this->no_jual, true);
$atabel = $this->Data_Jual($this->no_jual);
} else if ($this->mode === "save") {
$tgl_jual = Param::Get("Tgl_Jual", "");
$no_lama = $this->no_jual;
if ($this->is_pend) {
$this->no_jual = $this->inv->Nomor_POS("FJ", $tgl_jual, true);
if (!str_ends_with($no_lama, "#00")) $this->db->delete("inv_jual_pend", "No_Jual=?", [$no_lama]);
}
$this->inv->Detail_Save($this->no_jual, 5, $this->id_cab, $tgl_jual, $this->is_pend, $no_lama);
$ajual = $this->db->fetchRow("SELECT SUM(-Qty*Harga_Jual) Jual, SUM(Total_Diskon) Diskon, SUM(-Qty*Harga_Beli) HPP FROM inv_detail WHERE No_Ref=?", [$this->no_jual]) ?? ['Jual'=>0, 'Diskon'=>0, 'HPP'=>0];
$sql = new SQL($this->app);
$sql->set_table("inv_jual");
$sql->add_param_date("Tgl_Jual");
$sql->add_param("CabID", $this->id_cab);
$sql->add_param("MemberID");
$sql->add_param("Total_Jual", $ajual['Jual']);
$sql->add_param("Total_Diskon", $ajual['Diskon']);
$sql->add_param("Total_HPP", $ajual['HPP']);
$sql->add_param("POS", 0);
$sql->add_param_stamp();
$sql->add_param_userid();
$sql->add_where("No_Jual", $this->no_jual);
$sql->UpdateDB();
$this->gel->Update_Lunas_Buy($this->id_member);
// PROSES MEMBER POINT
if ($this->id_member > 0) {
$apoint = $this->db->fetchColumn("SELECT Point_TipeID FROM inv_point_tipe WHERE Aktif=1 ORDER BY Point_TipeID") ?? [];
if (count($apoint) > 0) {
$amember = $this->db->fetchRow("SELECT Grup_MemberID,IM,Kode_Member FROM para_member WHERE MemberID=?", [$this->id_member]);
if ($amember && ($amember['IM'] === 1 || ($amember['IM'] === 0 && !empty($amember['Kode_Member'])))) {
$this->db->runQuery("DELETE FROM inv_point_tx WHERE No_TX=?", [$this->no_jual]);
foreach ($apoint as $id_tipe) {
if ($amember['IM'] === 0 && $id_tipe === 1) continue;
$tot_point = $this->inv->Point_Hitung($this->no_jual, $tgl_jual, $amember['Grup_MemberID'], 0, $id_tipe);
if ($tot_point > 0) $this->db->runQuery("INSERT INTO inv_point_tx (No_TX,Tgl_TX,Point_TipeID,CabID,MemberID,Point,Nilai_Point,DateStamp,UserID) VALUES (?, ?, ?, ?, ?, ?, ?, NOW(), ?)", [$this->no_jual, tgl_sql2str($tgl_jual), $id_tipe, $this->id_cab, $this->id_member, $tot_point, $tot_point, $this->app->user()->id()]);
}
}
}
}
// PROSES POSTING GL
$ainfo = $this->db->fetchRow("SELECT J.*,B.Nama_Member,(J.Total_Jual-J.Total_Diskon) Tagihan FROM (SELECT * FROM inv_jual WHERE No_Jual=?) J LEFT JOIN para_member B ON (B.MemberID=J.MemberID)", [$this->no_jual]);
if (count($ainfo) > 0) {
$ajurnal = [
'Kode_Jurnal' => $ainfo['No_Jual'],
'TipeID' => 8,
'CabID' => $ainfo['CabID'],
'Tanggal' => tgl_sql2str($ainfo['Tgl_Jual']),
'Kode_Ref' => $ainfo['No_Jual'],
'Catatan' => "Penjualan : ".$ainfo['No_Jual']." | ".$ainfo['Nama_Member']." | ".$this->app->user()->username()
];
$adetail = [
[ 'Kode_Rek' => $this->app_gel['HPP'], 'DK' => "D", 'Jumlah' => $ainfo['Total_HPP'] ],
[ 'Kode_Rek' => $this->app_gel['STOK'], 'DK' => "K", 'Jumlah' => $ainfo['Total_HPP'] ],
[ 'Kode_Rek' => $this->app_gel['PIU_USAHA'], 'DK' => "D", 'Jumlah' => $ainfo['Tagihan'], 'MemberID' => $ainfo['MemberID'] ],
[ 'Kode_Rek' => $this->app_gel['JUAL'], 'DK' => "K", 'Jumlah' => $ainfo['Tagihan'] ]
];
$this->gel->Jurnal_Post($ajurnal, $adetail);
}
$atabel = $this->Data_Jual($this->no_jual);
$this->mode = "view";
} else if ($this->mode === "cancel") {
if (str_ends_with($this->no_jual, "#00") || !$this->is_pend) $this->inv->Detail_Cancel($this->no_jual);
$atabel = $this->Data_Jual();
} else {
$atabel = $this->Data_Jual($this->no_jual);
}
$enable = in_array($this->mode, ["add","edit"]) ? true : false;
$form = new Form($this->app);
$tnota = $form->textbox("_", "No_Jual", $atabel['No_Jual'], !$enable, true, "text", "nomor transaksi");
$ttglnota = $form->datebox("_", "Tgl_Jual", $atabel['Tgl_Jual'], $enable, true);
$ttgllunas = $form->datebox("_", "Tgl_Lunas", $atabel['Tgl_Lunas'], false, false);
$tcab = $form->option_db("_", "CabID", $atabel['CabID'], $enable, false, "para_cabang", ["CabID","Nama_Cab"], "Aktif=1 ORDER BY Nama_Cab", [0,"&nbsp;"]);
$tmember = $form->textauto("_", "Nama_Member", ['value'=>$atabel['MemberID'],'text'=>$atabel['Nama_Member']], true, true, "nama member");
$tpiutang = $form->textbox("_", "Total_Piutang", 0, false, false, "double");
$ajson['html'] = '
<div class="row">
<div class="col-sm-12 col-lg-6">
<div class="row mb-1">
<label class="col-sm-5 col-lg-3 col-form-label" for="No_Jual">Nomor Transaksi</label>
<div class="col"><div class="input-group">'.$tnota.'<button id="butBrow" class="btn btn-info" type="button"><i class="bi-search"></i></button></div></div>
</div>
<div class="row mb-1">
<label class="col-sm-5 col-lg-3 col-form-label" for="Tgl_Jual">Tanggal Transaksi</label>
<div class="col-sm-7 col-lg-5">'.$ttglnota.'</div>
</div>
<div class="row mb-1 collapse iextra" id="iex1">
<label class="col-sm-5 col-lg-3 col-form-label">Tanggal Lunas</label>
<div class="col-sm-7 col-lg-5">'.$ttgllunas.'</div>
</div>
</div>
<div class="col-sm-12 col-lg-6">
<div class="row mb-1">
<label class="col-sm-5 col-lg-3 col-form-label" for="CabID">Nama Cabang</label>
<div class="col">'.$tcab.'</div>
</div>
<div class="row mb-1">
<label class="col-sm-5 col-lg-3 col-form-label" for="MemberID">Nama Member<span class="float-end"><a class="text-decoration-none text-active" type="button" data-bs-toggle="collapse" data-bs-target=".iextra" aria-expanded="false" aria-controls="iex1 iex2"><i class="fw-bolder bi-arrows-expand"></i></a></span></label>
<div class="col"><div class="input-group">'.$tmember.'<button id="butBrowMember" class="btn btn-info" type="button"><i class="bi-people-fill"></i></button></div></div>
</div>
<div class="row mb-1 collapse iextra" id="iex2">
<label class="col-sm-5 col-lg-3 col-form-label">Jumlah Piutang</label>
<div class="col">'.$tpiutang.'</div>
</div>
</div>
</div>
<div class="row mb-1"><div class="col"><hr class="my-1"></div></div>
<div class="row mb-1'.(in_array($this->mode, ['add','edit']) ? '' : ' d-none').'">
<div class="col-sm-9 col-lg-10">
<input type="search" class="form-control fs-5" id="Nama_Produk" value="" placeholder="Scan SKU / Barcode / Ketik Nama Barang" autocomplete="off" />
</div>
<div class="col-sm-3 col-lg-2">
<input type="double" class="form-control double fs-5" id="POS_Qty" value="1.00" maxlength="10" />
</div>
</div>
<input type="hidden" id="MemberID" value="'.$atabel['MemberID'].'" >
<input type="hidden" id="Grup_MemberID" value="'.$atabel['Grup_MemberID'].'" >
<input type="hidden" id="Lunas" value="'.$atabel['Lunas'].'" >
<input type="hidden" id="mode" value="'.$this->mode.'" >';
$this->app->json($ajson);
}
public function form_produk() {
$id = (int) Param::Get("ID", 0);
$atabel = [ 'ID'=>$id, 'InvID'=>$this->id_inv, 'SatuanID'=>$this->id_satuan, 'VarianID'=>$this->id_varian, 'Kode_SKU'=>"", 'Kode_Barcode'=>"", 'Nama_Lengkap'=>"", 'Satuan_Kemasan'=>"", 'Qty'=>0, 'Harga_Beli'=>0, 'Harga_Jual'=>0, 'Disk_Rupiah'=>0 ];
if ($id > 0) {
$_row = $this->db->fetchRow("SELECT ID,-Qty Qty,Harga_Beli,Harga_Jual,Disk_Rupiah FROM tmp_inv_detail WHERE No_Ref=? AND ID=?", [$this->no_jual, $id]);
if ($_row) $atabel = array_merge($atabel, $_row->getData());
}
if ($this->id_inv > 0 && $this->id_satuan > 0) {
$_row = $this->db->fetchRow("SELECT Kode_SKU,Kode_Barcode,Nama_Lengkap,Satuan_Kemasan,Harga_Pokok Harga_Beli,Harga_Jual FROM inv_produk_join WHERE InvID=? AND SatuanID=? AND VarianID=? AND Grup_MemberID=?", [$this->id_inv, $this->id_satuan, $this->id_varian, $this->id_grup_member]);
if ($_row) $atabel = array_merge($atabel, $_row->getData());
}
$form = new Form($this->app);
$tsku = $form->textbox("_", "Kode_SKU", $atabel['Kode_SKU']. " / " .$atabel['Kode_Barcode'], false);
$tnama = $form->textbox("_", "Nama_Lengkap", $atabel['Nama_Lengkap'], false);
$tqty = $form->textbox("_", "Qty", $atabel['Qty'], true, true, "double");
$tjual = $form->textbox("_", "Harga_Jual", $atabel['Harga_Jual'], false, false, "double");
$tdisrp = $form->textbox("_", "Disk_Rupiah", $atabel['Disk_Rupiah'], true, true, "double");
$tdispn = $form->textbox("_", "Disk_Persen", 0, true, false, "double");
$ttot = $form->textbox("_", "Jumlah", 0, false, false, "double");
$tsat = $form->textbox("_", "Nama_Satuan", $atabel['Satuan_Kemasan'], false);
$ajson['html'] = '
<div class="row mb-1">
<label class="col-sm-4 col-lg-3 col-form-label">Kode SKU / Barcode</label>
<div class="col">'.$tsku.'</div>
</div>
<div class="row mb-1">
<label class="col-sm-4 col-lg-3 col-form-label">Nama Barang</label>
<div class="col">'.$tnama.'</div>
</div>
<div class="row mb-1"><hr class="my-1"></div>
<div class="row mb-1">
<label class="col-sm-4 col-lg-3 col-form-label" for="Qty">Qty</label>
<div class="col-sm-4 col-lg-5"><div class="input-group">'.$tqty.$tsat.'</div></div>
</div>
<div class="row mb-1">
<label class="col-sm-4 col-lg-3 col-form-label">Harga (@)</label>
<div class="col-sm-8 col-lg-5">'.$tjual.'</div>
</div>
<div class="row mb-1">
<label class="col-sm-4 col-lg-3 col-form-label" for="Disk_Rupiah">Diskon (@)</label>
<div class="col-sm-8 col-lg-5">'.$tdisrp.'</div>
<div class="col-sm-3 col-lg-3"><div class="input-group"><div class="input-group-text">&thickapprox;</div>'.$tdispn.'<div class="input-group-text">%</div></div></div>
</div>
<div class="row mb-1">
<label class="col-sm-4 col-lg-3 col-form-label">Sub Total</label>
<div class="col-sm-8 col-lg-5">'.$ttot.'</div>
</div>
<input type="hidden" id="ID" value="'.$atabel['ID'].'" >
<input type="hidden" id="InvID" value="'.$atabel['InvID'].'" >
<input type="hidden" id="SatuanID" value="'.$atabel['SatuanID'].'" >
<input type="hidden" id="VarianID" value="'.$atabel['VarianID'].'" >
<input type="hidden" id="Harga_Beli" value="'.$atabel['Harga_Beli'].'" >
<input type="hidden" id="mode_detail" value="'.$this->mode_detail.'" >';
$this->app->json($ajson);
}
public function proses_delete() {
if ($this->is_pend === false) {
$this->db->runQuery("DELETE FROM inv_jual WHERE No_Jual=?", [$this->no_jual]);
$this->db->runQuery("DELETE FROM inv_detail WHERE No_Ref=?", [$this->no_jual]);
// PROSES POSTING GL
$this->db->runQuery("DELETE FROM gel_jurnal WHERE Kode_Jurnal=?", [$this->no_jual]);
$this->db->runQuery("DELETE FROM gel_jurnal_detail WHERE Kode_Jurnal=?", [$this->no_jual]);
// PROSES MEMBER POINT
if ($this->id_member > 0) $this->db->runQuery("DELETE FROM inv_point_tx WHERE No_TX=?", [$this->no_jual]);
} else {
$this->db->runQuery("DELETE FROM inv_jual_pend WHERE No_Jual=?", [$this->no_jual]);
$this->db->runQuery("DELETE FROM tmp_inv_detail WHERE No_Ref=?", [$this->no_jual]);
}
$this->app->json([ 'status' => true ]);
}
public function update_piutang() {
$_piut = $this->db->fetchField("SELECT SUM(Total_Jual-Total_Diskon-Total_Bayar-Total_Potong) Jumlah FROM inv_jual WHERE MemberID=? AND Lunas=0", [$this->id_member]) ?? 0;
$this->app->json([ ['type'=>"form", 'id'=>"Total_Piutang", 'value'=>rupiah2($_piut)] ]);
}
public function index() {
$this->app->json(['html' => '
<div class="fade-in">
<div class="card"><div class="card-body">
<ul class="nav nav-tabs" role="tablist">
<li class="nav-item" role="presentation">
<button class="nav-link active" id="tx-tab" data-bs-toggle="tab" data-bs-target="#tx" type="button" role="tab" aria-controls="tx" aria-selected="true"><i class="bi-database me-2"></i>Transaksi Penjualan</button>
</li>
<li class="nav-item ms-auto">
<button class="btn btn-primary mb-1 ms-2" id="butTambah" type="button"><i class="bi-plus-lg me-2"></i>Tambah</button>
<button class="btn btn-info mb-1 ms-2" id="butUbah" type="button"><i class="bi-clipboard me-2"></i>Ubah</button>
<button class="btn btn-warning mb-1 ms-2" id="butHapus" type="button"><i class="bi-trash me-2"></i>Hapus</button>
<button class="btn btn-info mb-1 ms-2" id="butPendingBrow" type="button"><i class="bi-cloud me-2"></i>Pending</button>
<button class="btn btn-secondary mb-1 ms-2 dropdown-toggle" id="butPrint" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"><i class="bi-printer me-2"></i>Cetak</button>
<div class="dropdown-menu" aria-labelledby="butPrint">
<a class="dropdown-item" href="#" id="printNota">Cetak Nota</a>
<a class="dropdown-item" href="#" id="printPOS">Cetak POS</a>
</div>
<button class="btn btn-danger mb-1 ms-2" id="butBatal" type="button"><i class="bi-x-lg me-2"></i>Batal</button>
<button class="btn btn-warning mb-1 ms-2" id="butPendingSimpan" type="button"><i class="bi-cloud-upload me-2"></i>Simpan Pending</button>
<button class="btn btn-success mb-1 ms-2" id="butSimpan" type="button"><i class="bi-save me-2"></i>Simpan</button>
</li>
</ul>
<div class="tab-content border border-top-0 p-3">
<div class="tab-pane fade active show" id="tx" role="tabpanel" aria-labelledby="tx-tab">
<div id="divTXMaster">&nbsp;</div>
<div id="divDetailTabel">&nbsp;</div>
</div>
</div>
</div></div>
</div>'
]);
}
private function Data_Jual(string $nomor="", bool $baru=false): array {
$aparam = [
'No_Jual' => $nomor,
'Tgl_Jual' => tgl_ymd(),
'Tgl_Lunas' => "0000-00-00",
'CabID' => $this->id_cab,
'MemberID' => $this->id_member,
'Grup_MemberID' => $this->id_grup_member,
'Nama_Member' => "",
'Lunas' => 0
];
if ($baru) $aparam['No_Jual'] = "JUAL".$this->web_app['SERVER_ID'].(string) $this->id_cab.$this->app->user()->id(3)."#00";
if (!empty($nomor)) {
$tabel_jual = (str_contains($nomor, "JUAL") === false) ? "inv_jual" : "inv_jual_pend";
$row = $this->db->fetchRow("SELECT * FROM ".$tabel_jual." WHERE CabID=? AND No_Jual=?", [$this->id_cab, $nomor]);
if ($row) $aparam = array_merge($aparam, $row->getData());
if ($aparam['MemberID'] > 0) {
$row = $this->db->fetchRow("SELECT Grup_MemberID,Nama_Member FROM para_member WHERE MemberID=?", [$aparam['MemberID']]);
if ($row) $aparam = array_merge($aparam, $row->getData());
}
}
return $aparam;
}
private function Pending_Nomor(): string {
$tno = "JUAL".$this->web_app['SERVER_ID'].(string) $this->id_cab.$this->app->user()->id(3)."#";
$ino = (int) $this->db->fetchField("SELECT MAX(RIGHT(No_Jual,2)) FROM inv_jual_pend WHERE No_Jual LIKE ?", [$tno.'%']) ?? 0;
$tno .= isi_nol(++$ino, 2);
return $tno;
}
}