Aplikasi POS Amigo, dibangun dengan JavaFX dengan Maven
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

497 lines
19 KiB

  1. /*
  2. * To change this license header, choose License Headers in Project Properties.
  3. * To change this template file, choose Tools | Templates
  4. * and open the template in the editor.
  5. */
  6. package id.amigogroup.posterminal.transaksi;
  7. import id.amigogroup.posterminal.api.AmigoPosRx;
  8. import id.amigogroup.posterminal.model.Barang;
  9. import id.amigogroup.posterminal.model.DNotaTunai;
  10. import id.amigogroup.posterminal.model.NoBarang;
  11. import id.amigogroup.posterminal.util.AmigoPosCache;
  12. import id.amigogroup.posterminal.util.AlertUtil;
  13. import id.amigogroup.posterminal.util.Fucout;
  14. import io.reactivex.Observable;
  15. import io.reactivex.Observer;
  16. import io.reactivex.disposables.Disposable;
  17. import java.net.HttpURLConnection;
  18. import java.net.URL;
  19. import java.util.List;
  20. import java.util.ResourceBundle;
  21. import javafx.application.Platform;
  22. import javafx.beans.property.ReadOnlyObjectWrapper;
  23. import javafx.collections.FXCollections;
  24. import javafx.collections.ObservableList;
  25. import javafx.fxml.FXML;
  26. import javafx.fxml.Initializable;
  27. import javafx.scene.control.Alert;
  28. import javafx.scene.control.Button;
  29. import javafx.scene.control.ButtonBar;
  30. import javafx.scene.control.ButtonType;
  31. import javafx.scene.control.ComboBox;
  32. import javafx.scene.control.Label;
  33. import javafx.scene.control.TableColumn;
  34. import javafx.scene.control.TableView;
  35. import javafx.scene.control.TextField;
  36. import javafx.scene.control.cell.PropertyValueFactory;
  37. import javafx.scene.input.KeyCode;
  38. import javafx.scene.input.KeyEvent;
  39. import javafx.scene.layout.AnchorPane;
  40. import javafx.scene.text.Text;
  41. import retrofit2.HttpException;
  42. /**
  43. * FXML Controller class
  44. *
  45. * @author ronal
  46. */
  47. public class FormTransaksiTunaiController implements Initializable {
  48. @FXML
  49. private AnchorPane apMain;
  50. @FXML
  51. private TextField fldScan;
  52. @FXML
  53. private Label lblNoNota;
  54. @FXML
  55. private TableView<TabelBarangTunai> tbvTransaksi;
  56. @FXML
  57. private TableColumn<TabelBarangTunai, Integer> tcNo;
  58. @FXML
  59. private TableColumn<TabelBarangTunai, String> tcKode;
  60. @FXML
  61. private TableColumn<TabelBarangTunai, String> tcNama;
  62. @FXML
  63. private TableColumn<TabelBarangTunai, String> tcUkur;
  64. @FXML
  65. private TableColumn<TabelBarangTunai, String> tcJumlah;
  66. @FXML
  67. private TableColumn<TabelBarangTunai, String> tcHarga;
  68. @FXML
  69. private TableColumn<TabelBarangTunai, String> tcDisc1;
  70. @FXML
  71. private TableColumn<TabelBarangTunai, String> tcDisc2;
  72. @FXML
  73. private TableColumn<TabelBarangTunai, ComboBox<String>> tcPromo;
  74. @FXML
  75. private TableColumn<TabelBarangTunai, String> tcSubtotal;
  76. @FXML
  77. private TableColumn<TabelBarangTunai, TextField> tcPramuniaga;
  78. @FXML
  79. private TableColumn<TabelBarangTunai, Button> tcAction;
  80. @FXML
  81. private Label txtTanggal;
  82. @FXML
  83. private Text lblGrandTotal;
  84. public final ObservableList<TabelBarangTunai> daftarTabelTransaksi = FXCollections.observableArrayList();
  85. public static final ButtonType btnAction = new ButtonType("BATAL", ButtonBar.ButtonData.YES);
  86. private String noNota = "";
  87. private AmigoPosRx posRx = new AmigoPosRx();
  88. public int total = 0;
  89. /**
  90. * Initializes the controller class.
  91. */
  92. @Override
  93. public void initialize(URL url, ResourceBundle rb) {
  94. Platform.runLater(() -> {
  95. fldScan.requestFocus();
  96. });
  97. tcNo.setCellValueFactory((TableColumn.CellDataFeatures<TabelBarangTunai, Integer> cell) -> {
  98. return new ReadOnlyObjectWrapper(tbvTransaksi.getItems().indexOf(cell.getValue()) + 1);
  99. });
  100. tcKode.setCellValueFactory(new PropertyValueFactory<>("kode"));
  101. tcNama.setCellValueFactory(new PropertyValueFactory<>("nama"));
  102. tcUkur.setCellValueFactory(new PropertyValueFactory<>("ukur"));
  103. tcJumlah.setCellValueFactory(new PropertyValueFactory<>("jumlah"));
  104. tcHarga.setCellValueFactory(new PropertyValueFactory<>("harga"));
  105. tcDisc1.setCellValueFactory(new PropertyValueFactory<>("disc1"));
  106. tcDisc2.setCellValueFactory(new PropertyValueFactory<>("disc2"));
  107. tcPromo.setCellValueFactory(new PropertyValueFactory<>("cbxPromo"));
  108. tcSubtotal.setCellValueFactory(new PropertyValueFactory<>("subTotal"));
  109. tcPramuniaga.setCellValueFactory(new PropertyValueFactory<>("fldPramuniaga"));
  110. tcAction.setCellValueFactory(new PropertyValueFactory<>("btnAction"));
  111. tbvTransaksi.setItems(daftarTabelTransaksi);
  112. lblGrandTotal.setText(Fucout.formatRupiah(0));
  113. }
  114. public void initData(String noNota, boolean baru) {
  115. if (!baru) {
  116. posRx.getDNotaTunaiByNoNota(noNota).subscribe(getDNotaTunaiObserver);
  117. }
  118. this.noNota = noNota;
  119. lblNoNota.setText(Fucout.getTextColon(noNota));
  120. setTanggal();
  121. }
  122. public void setTanggal() {
  123. java.util.Date skrg = new java.util.Date();
  124. java.text.SimpleDateFormat kal = new java.text.SimpleDateFormat("dd/MM/yyyy");
  125. txtTanggal.setText(kal.format(skrg));
  126. }
  127. private void refreshData(List<DNotaTunai> daftarNotaTunai) {
  128. daftarTabelTransaksi.clear();
  129. hitungTotal(daftarNotaTunai);
  130. String[] promo = {"Ulang Tahun", "Harbolnas", "Ultah Amigo"};
  131. for (DNotaTunai dNotaTunai : daftarNotaTunai) {
  132. //ComboBox
  133. ComboBox<String> cbxPromo = new ComboBox<>(FXCollections.observableArrayList(promo));
  134. cbxPromo.getSelectionModel().select("Ulang Tahun");
  135. //Button
  136. Button btnAction = new Button("BATAL");
  137. btnAction.setOnAction((t) -> {
  138. Alert alert = AlertUtil.getAlertError(
  139. AlertUtil.DIALOG_KONFIRMASI_MESSAGE,
  140. "Yakin ingin menghapus barang?");
  141. alert.initOwner(apMain.getScene().getWindow());
  142. alert.show();
  143. });
  144. //TextField
  145. TextField fldPramuniaga = new TextField(dNotaTunai.getKodePram());
  146. fldPramuniaga.setOnKeyPressed((t) -> {
  147. if (t.getCode() == KeyCode.ENTER) {
  148. fldScan.requestFocus();
  149. }
  150. });
  151. String namaBarang = "...";
  152. if (AmigoPosCache.getInstance().getDaftarBarang().containsKey(dNotaTunai.getKdBarang())) {
  153. namaBarang = Fucout.getText(AmigoPosCache.getInstance().getDaftarBarang()
  154. .get(dNotaTunai.getKdBarang()).getNamaBarang());
  155. }
  156. daftarTabelTransaksi.add(new TabelBarangTunai(
  157. Fucout.getText(dNotaTunai.getKdBarang()),
  158. namaBarang,
  159. Fucout.getText(dNotaTunai.getNoBarang()),
  160. Fucout.getText(String.valueOf(dNotaTunai.getJumlah())),
  161. Fucout.getText(Fucout.formatRibuan(dNotaTunai.getHargaJual())),
  162. Fucout.getText(Fucout.formatPersentase(dNotaTunai.getDiskon())),
  163. Fucout.getText(Fucout.formatPersentase(dNotaTunai.getDiskon2())),
  164. cbxPromo,
  165. Fucout.getText(Fucout.formatRibuan(
  166. dNotaTunai.getHargaJual() * dNotaTunai.getJumlah()
  167. )),
  168. fldPramuniaga,
  169. btnAction));
  170. if (!AmigoPosCache.getInstance().getDaftarBarang().containsKey(dNotaTunai.getKdBarang())) {
  171. posRx.getBarangByKodeBarang(dNotaTunai.getKdBarang()).subscribe(getBarangObserver);
  172. }
  173. }
  174. }
  175. public void addToTable(Barang barang, NoBarang noBarang) {
  176. if (barang != null && noBarang != null) {
  177. fldScan.setText("");
  178. if (noBarang.getStokOperasional() > 0) {
  179. boolean ada = false;
  180. for (TabelBarangTunai tbt : daftarTabelTransaksi) {
  181. if (tbt.getKode().equals(barang.getKodeBarang()) && tbt.getUkur().equals(noBarang.getNomor())) {
  182. if (tbt.getData() != null) {
  183. if (noBarang.getStokOperasional() >= tbt.getData().getJumlah() + 1) {
  184. tbt.getData().setJumlah(tbt.getData().getJumlah() + 1);
  185. tbt.setJumlah(String.valueOf(tbt.getData().getJumlah()));
  186. tbt.setSubTotal(Fucout.formatRibuan(
  187. tbt.getData().getJumlah() * tbt.getData().getHargaJual()));
  188. total += noBarang.getHargaJual();
  189. updateLabelGrandTotal();
  190. tbvTransaksi.refresh();
  191. } else {
  192. Platform.runLater(() -> {
  193. Alert alert = AlertUtil.getAlertWarning(
  194. "Stok Habis",
  195. "Tidak bisa menambahkan barang karena stok barang habis");
  196. alert.initOwner(apMain.getScene().getWindow());
  197. alert.show();
  198. });
  199. }
  200. }
  201. ada = true;
  202. break;
  203. }
  204. }
  205. if (!ada) {
  206. String[] promo = {"Ulang Tahun", "Harbolnas", "Ultah Amigo"};
  207. ComboBox<String> cbxPromo = new ComboBox<>(FXCollections.observableArrayList(promo));
  208. cbxPromo.getSelectionModel().select("Ulang Tahun");
  209. Button btnAction = new Button("BATAL");
  210. btnAction.setOnAction((t) -> {
  211. Alert alert = AlertUtil.getAlertDialogKonfirmasi(
  212. AlertUtil.DIALOG_KONFIRMASI_MESSAGE,
  213. "Yakin ingin menghapus barang?");
  214. alert.initOwner(apMain.getScene().getWindow());
  215. alert.show();
  216. });
  217. TextField fldPramuniaga = new TextField();
  218. fldPramuniaga.setOnKeyPressed((t) -> {
  219. if (t.getCode() == KeyCode.ENTER) {
  220. fldScan.requestFocus();
  221. }
  222. });
  223. DNotaTunai dNotaTunai = new DNotaTunai(
  224. noNota,
  225. barang.getKodeBarang(),
  226. barang.getNamaBarang(),
  227. 1,
  228. 0,
  229. 0,
  230. noBarang.getHargaJual(),
  231. noBarang.getHargaPokok(),
  232. "",
  233. 0);
  234. TabelBarangTunai tbt = new TabelBarangTunai(
  235. Fucout.getText(barang.getKodeBarang()),
  236. Fucout.getText(barang.getNamaBarang()),
  237. Fucout.getText(noBarang.getNomor()),
  238. String.valueOf(1),
  239. Fucout.getText(Fucout.formatRibuan(noBarang.getHargaJual())),
  240. "...",
  241. "...",
  242. cbxPromo,
  243. Fucout.getText(Fucout.formatRibuan(
  244. 1 * noBarang.getHargaJual())
  245. ),
  246. fldPramuniaga,
  247. btnAction);
  248. tbt.setData(dNotaTunai);
  249. total += noBarang.getHargaJual();
  250. updateLabelGrandTotal();
  251. daftarTabelTransaksi.add(tbt);
  252. }
  253. } else {
  254. Platform.runLater(() -> {
  255. Alert alert = AlertUtil.getAlertWarning(
  256. "Stok Habis",
  257. "Tidak bisa menambahkan barang karena stok barang habis");
  258. alert.initOwner(apMain.getScene().getWindow());
  259. alert.show();
  260. });
  261. }
  262. }
  263. }
  264. private int hitungTotal(List<DNotaTunai> daftarDNotaTunai) {
  265. int totalTemp = 0;
  266. for (DNotaTunai dNotaTunai : daftarDNotaTunai) {
  267. totalTemp += dNotaTunai.getJumlah() * dNotaTunai.getHargaJual();
  268. }
  269. total = totalTemp;
  270. updateLabelGrandTotal();
  271. return 0;
  272. }
  273. private void updateLabelGrandTotal() {
  274. lblGrandTotal.setText(Fucout.formatRupiah(total));
  275. }
  276. //SCAN BARANG
  277. @FXML
  278. void fldScanOnKeyPressed(KeyEvent event) {
  279. if (event.getCode() == KeyCode.ENTER) {
  280. String kodeFull = fldScan.getText();
  281. String kodeBarang = Fucout.getKodeBarangFromKodeFull(kodeFull);
  282. String ukur = Fucout.getNomorBarangFromKodeFull(kodeFull);
  283. if (AmigoPosCache.getInstance().getDaftarBarang().containsKey(kodeBarang)) {
  284. Barang barang = AmigoPosCache.getInstance().getDaftarBarang().get(kodeBarang);
  285. if (AmigoPosCache.getInstance().getDaftarNoBarang().containsKey(
  286. barang.getIdGabungan() + ukur)) {
  287. NoBarang noBarang = AmigoPosCache.getInstance().getDaftarNoBarang()
  288. .get(barang.getIdGabungan() + ukur);
  289. addToTable(barang, noBarang);
  290. } else {
  291. Observable.zip(posRx.getBarangByKodeBarang(kodeBarang),
  292. posRx.getNoBarangByIdGabunganNomor(barang.getIdGabungan(), ukur),
  293. (b, nB) -> new BarangFull(b, nB)).subscribe(getBarangFullGetNoBarangFromBarangObserver);
  294. }
  295. }
  296. if (!AmigoPosCache.getInstance().getDaftarBarang().containsKey(kodeBarang)) {
  297. Observable.zip(posRx.getBarangByKodeBarang(kodeBarang),
  298. Observable.just(ukur),
  299. (barang, nomor) -> {
  300. barang.setNomor(nomor);
  301. return barang;
  302. }).subscribe(getTambahBarangObserver);
  303. }
  304. }
  305. }
  306. Observer<List<DNotaTunai>> getDNotaTunaiObserver = new Observer<>() {
  307. @Override
  308. public void onSubscribe(Disposable dspsbl) {
  309. }
  310. @Override
  311. public void onNext(List<DNotaTunai> daftarDNotaTunai) {
  312. refreshData(daftarDNotaTunai);
  313. }
  314. @Override
  315. public void onError(Throwable error) {
  316. if (error instanceof HttpException) {
  317. switch (((HttpException) error).code()) {
  318. case HttpURLConnection.HTTP_NOT_FOUND:
  319. Platform.runLater(() -> {
  320. Alert alert = AlertUtil.getAlertError(
  321. AlertUtil.ERROR_TIDAK_DITEMUKAN_TITLE,
  322. "Data nota tidak ditemukan.");
  323. alert.initOwner(apMain.getScene().getWindow());
  324. alert.show();
  325. });
  326. }
  327. } else {
  328. AmigoPosRx.handleGenericError(error, apMain.getScene().getWindow());
  329. }
  330. }
  331. @Override
  332. public void onComplete() {
  333. }
  334. };
  335. Observer<Barang> getBarangObserver = new Observer<>() {
  336. @Override
  337. public void onSubscribe(Disposable dspsbl) {
  338. }
  339. @Override
  340. public void onNext(Barang b) {
  341. AmigoPosCache.getInstance().getDaftarBarang().put(b.getKodeBarang(), b);
  342. for (TabelBarangTunai tbt : daftarTabelTransaksi) {
  343. if (tbt.getKode().equals(b.getKodeBarang())) {
  344. tbt.setNama(b.getNamaBarang());
  345. tbvTransaksi.refresh();
  346. }
  347. };
  348. }
  349. @Override
  350. public void onError(Throwable error) {
  351. if (error instanceof HttpException) {
  352. switch (((HttpException) error).code()) {
  353. case HttpURLConnection.HTTP_NOT_FOUND:
  354. Platform.runLater(() -> {
  355. Alert alert = AlertUtil.getAlertError(
  356. AlertUtil.ERROR_TIDAK_DITEMUKAN_TITLE,
  357. "Barang dengan kode tersebut tidak ditemukan.");
  358. alert.initOwner(apMain.getScene().getWindow());
  359. alert.show();
  360. });
  361. }
  362. } else {
  363. AmigoPosRx.handleGenericError(error, apMain.getScene().getWindow());
  364. }
  365. }
  366. @Override
  367. public void onComplete() {
  368. }
  369. };
  370. Observer<Barang> getTambahBarangObserver = new Observer<>() {
  371. @Override
  372. public void onSubscribe(Disposable dspsbl) {
  373. }
  374. @Override
  375. public void onNext(Barang b) {
  376. Barang bClone = new Barang(b);
  377. bClone.setNomor(null);
  378. AmigoPosCache.getInstance().getDaftarBarang().put(b.getKodeBarang(), bClone);
  379. if (b.getNomor() != null && !b.getNomor().equals("")) {
  380. if (!AmigoPosCache.getInstance().getDaftarNoBarang().containsKey(
  381. b.getIdGabungan() + b.getNomor())) {
  382. Observable.zip(
  383. Observable.just(b),
  384. posRx.getNoBarangByIdGabunganNomor(b.getIdGabungan(), b.getNomor()),
  385. (barang, noBarang) -> new BarangFull(barang, noBarang))
  386. .subscribe(getBarangFullGetNoBarangFromBarangObserver);
  387. }
  388. }
  389. }
  390. @Override
  391. public void onError(Throwable error) {
  392. if (error instanceof HttpException) {
  393. switch (((HttpException) error).code()) {
  394. case HttpURLConnection.HTTP_NOT_FOUND:
  395. Platform.runLater(() -> {
  396. Alert alert = AlertUtil.getAlertError(
  397. AlertUtil.ERROR_TIDAK_DITEMUKAN_TITLE,
  398. "Barang dengan kode tersebut tidak ditemukan.");
  399. alert.initOwner(apMain.getScene().getWindow());
  400. alert.show();
  401. });
  402. }
  403. } else {
  404. AmigoPosRx.handleGenericError(error, apMain.getScene().getWindow());
  405. }
  406. }
  407. @Override
  408. public void onComplete() {
  409. }
  410. };
  411. Observer<BarangFull> getBarangFullGetNoBarangFromBarangObserver = new Observer<>() {
  412. @Override
  413. public void onSubscribe(Disposable dspsbl) {
  414. }
  415. @Override
  416. public void onNext(BarangFull bf) {
  417. addToTable(bf.getBarang(), bf.getNoBarang());
  418. }
  419. @Override
  420. public void onError(Throwable error) {
  421. if (error instanceof HttpException) {
  422. switch (((HttpException) error).code()) {
  423. case HttpURLConnection.HTTP_NOT_FOUND:
  424. Platform.runLater(() -> {
  425. Alert alert = AlertUtil.getAlertError(
  426. AlertUtil.ERROR_TIDAK_DITEMUKAN_TITLE,
  427. "Barang dengan kode tersebut tidak ditemukan.");
  428. alert.initOwner(apMain.getScene().getWindow());
  429. alert.show();
  430. });
  431. }
  432. } else {
  433. AmigoPosRx.handleGenericError(error, apMain.getScene().getWindow());
  434. }
  435. }
  436. @Override
  437. public void onComplete() {
  438. }
  439. };
  440. }