Aplikasi POS Amigo, dibangun dengan JavaFX dengan Maven
您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

547 行
21 KiB

  1. package id.amigogroup.posterminal;
  2. import id.amigogroup.posterminal.api.AmigoPosRx;
  3. import id.amigogroup.posterminal.model.Pelanggan;
  4. import id.amigogroup.posterminal.pencarian.DialogCariBarangController;
  5. import id.amigogroup.posterminal.pencarian.DialogCariNotaTundaController;
  6. import id.amigogroup.posterminal.pencarian.DialogCariPelangganController;
  7. import id.amigogroup.posterminal.pencarian.DialogCetakUlangNotaController;
  8. import id.amigogroup.posterminal.transaksi.BarangFull;
  9. import id.amigogroup.posterminal.transaksi.DialogKonfirmasiReturController;
  10. import id.amigogroup.posterminal.transaksi.DialogTambahNotaController;
  11. import id.amigogroup.posterminal.transaksi.FormTransaksiReturController;
  12. import id.amigogroup.posterminal.transaksi.FormTransaksiTunaiController;
  13. import id.amigogroup.posterminal.util.AlertUtil;
  14. import id.amigogroup.posterminal.util.Fucout;
  15. import io.reactivex.Observer;
  16. import io.reactivex.disposables.Disposable;
  17. import java.io.IOException;
  18. import java.net.HttpURLConnection;
  19. import java.net.URL;
  20. import java.util.ArrayList;
  21. import java.util.HashMap;
  22. import java.util.List;
  23. import java.util.Map;
  24. import java.util.Optional;
  25. import java.util.ResourceBundle;
  26. import java.util.logging.Level;
  27. import java.util.logging.Logger;
  28. import javafx.application.Platform;
  29. import javafx.event.ActionEvent;
  30. import javafx.fxml.FXML;
  31. import javafx.fxml.FXMLLoader;
  32. import javafx.fxml.Initializable;
  33. import javafx.scene.Node;
  34. import javafx.scene.Parent;
  35. import javafx.scene.Scene;
  36. import javafx.scene.control.Alert;
  37. import javafx.scene.control.Button;
  38. import javafx.scene.control.Label;
  39. import javafx.scene.control.ScrollPane;
  40. import javafx.scene.control.TextField;
  41. import javafx.scene.image.Image;
  42. import javafx.scene.input.KeyCode;
  43. import javafx.scene.input.KeyCodeCombination;
  44. import javafx.scene.input.KeyCombination;
  45. import javafx.scene.input.KeyEvent;
  46. import javafx.scene.layout.BorderPane;
  47. import javafx.scene.layout.VBox;
  48. import javafx.stage.Stage;
  49. import retrofit2.HttpException;
  50. public class FormUtamaController implements Initializable {
  51. @FXML
  52. private BorderPane bpMain;
  53. @FXML
  54. private ScrollPane spMainContent;
  55. @FXML
  56. private ScrollPane spNavigasi;
  57. @FXML
  58. private VBox vbNavigasi;
  59. @FXML
  60. private Button btnTambahNota;
  61. @FXML
  62. private Label lblNamaLogin;
  63. @FXML
  64. private Label lblMemberNonMember;
  65. @FXML
  66. private Label lblKodePelanggan;
  67. @FXML
  68. private Label lblNamaPelanggan;
  69. @FXML
  70. private Label lblTglLahirPelanggan;
  71. @FXML
  72. private Label lblNoTelpPelanggan;
  73. @FXML
  74. private TextField tfScanMember;
  75. private final FormFactory formFactory = new FormFactory();
  76. private final List<Button> navigasi = new ArrayList<>();
  77. private int notaState = -1;
  78. private String tipeTransaksiState = "";
  79. private int jumlahNota = 0;
  80. private final char NOTA_PREV = 'p';
  81. private final char NOTA_NEXT = 'n';
  82. private final NotaContent notaContent = new NotaContent();
  83. private final AmigoPosRx posRx = new AmigoPosRx();
  84. /**
  85. * Initializes the controller class.
  86. */
  87. @Override
  88. public void initialize(URL url, ResourceBundle rb) {
  89. //Kode Sri Sumarmi (i140411), Nur Indah Suciati (00334), Kode Wuryaningsih/RT (010004)
  90. updateLabelMemberNonMember();
  91. if (SystemValue.karyawanLogin != null) {
  92. lblNamaLogin.setText(Fucout.getTextColon(SystemValue.karyawanLogin.getNama()));
  93. }
  94. initShorcuts();
  95. }
  96. private void updateLabelPelanggan(Pelanggan p) {
  97. updateLabelMemberNonMember();
  98. if (Fucout.checkBirthday(p.getTglLahir())) {
  99. Alert alertUltah = AlertUtil.getAlertUlangTahun(p.getNama());
  100. alertUltah.initOwner(bpMain.getScene().getWindow());
  101. alertUltah.show();
  102. }
  103. lblKodePelanggan.setText(Fucout.getTextColon(p.getAlias()));
  104. lblNamaPelanggan.setText(Fucout.getTextColon(p.getNama()));
  105. lblTglLahirPelanggan.setText(Fucout.getTextColon(Fucout.formatTanggal(p.getTglLahir())));
  106. lblNoTelpPelanggan.setText(Fucout.getTextColon(
  107. !p.getTelp().equals("") && !p.getPonsel().equals("")
  108. ? p.getTelp() + System.lineSeparator() + p.getPonsel() : p.getTelp() + p.getPonsel()));
  109. }
  110. private void updateLabelMemberNonMember() {
  111. if (SystemValue.isMember) {
  112. lblMemberNonMember.setText("Member");
  113. } else {
  114. lblMemberNonMember.setText("Non Member");
  115. }
  116. }
  117. private void updateSelectedNota(ActionEvent event) {
  118. Button buttonSource = (Button) event.getSource();
  119. notaState = navigasi.indexOf(buttonSource);
  120. Fucout.scrollToNode(spNavigasi, buttonSource);
  121. for (Button button : navigasi) {
  122. if (button.equals(buttonSource)) {
  123. if (!button.getStyleClass().contains("button-navigasi-transaksi-selected")) {
  124. button.getStyleClass().add("button-navigasi-transaksi-selected");
  125. }
  126. } else {
  127. if (button.getStyleClass().contains("button-navigasi-transaksi-selected")) {
  128. button.getStyleClass().remove("button-navigasi-transaksi-selected");
  129. }
  130. }
  131. }
  132. // fldScan.requestFocus();
  133. }
  134. private Button generateButtonNota(String noNota, String tipeNota, String tipeTeks, boolean baru) {
  135. Button button = new Button(tipeTeks + ": " + noNota);
  136. button.getStyleClass().add("button-navigasi-transaksi");
  137. button.setMaxWidth(Double.MAX_VALUE);
  138. button.setOnAction((event) -> {
  139. setContent(loadNota(noNota, tipeNota, baru));
  140. tipeTransaksiState = tipeNota;
  141. updateSelectedNota(event);
  142. });
  143. return button;
  144. }
  145. private Node loadNota(String noNota, String tipe, boolean baru) {
  146. Node node = null;
  147. FXMLLoader loader = new FXMLLoader();
  148. try {
  149. switch (tipe) {
  150. case FormConstanta.TRANSAKSI_TUNAI:
  151. loader.setLocation(getClass().getResource("/fxml/FormTransaksiTunai.fxml"));
  152. node = loader.load();
  153. FormTransaksiTunaiController fttc = loader.getController();
  154. notaContent.controllerTunai = fttc;
  155. fttc.initData(noNota, baru);
  156. break;
  157. case FormConstanta.TRANSAKSI_RETUR:
  158. loader.setLocation(getClass().getResource("/fxml/FormTransaksiRetur.fxml"));
  159. node = loader.load();
  160. FormTransaksiReturController ftrc = loader.getController();
  161. ftrc.initData(noNota, baru);
  162. break;
  163. }
  164. } catch (IOException ex) {
  165. Logger.getLogger(FormUtamaController.class.getName()).log(Level.SEVERE, null, ex);
  166. }
  167. return node;
  168. }
  169. private void loadNota(char operasi) {
  170. switch (operasi) {
  171. case NOTA_PREV:
  172. if (notaState == -1) {
  173. notaState = jumlahNota - 1;
  174. } else {
  175. notaState--;
  176. if (notaState < 0) {
  177. notaState = jumlahNota - 1;
  178. }
  179. }
  180. break;
  181. case NOTA_NEXT:
  182. if (notaState == -1) {
  183. notaState = 0;
  184. } else {
  185. notaState++;
  186. if (notaState >= jumlahNota) {
  187. notaState = 0;
  188. }
  189. }
  190. break;
  191. }
  192. if (notaState >= 0 && notaState < jumlahNota) {
  193. navigasi.get(notaState).fire();
  194. }
  195. }
  196. private void initShorcuts() {
  197. Map<KeyCombination, Runnable> listShortcuts = new HashMap<>();
  198. KeyCombination kcPrevNota = new KeyCodeCombination(KeyCode.F1);
  199. Runnable rnPrevNota = () -> {
  200. loadNota(NOTA_PREV);
  201. };
  202. listShortcuts.put(kcPrevNota, rnPrevNota);
  203. KeyCombination kcNextNota = new KeyCodeCombination(KeyCode.F2);
  204. Runnable rnNextNota = () -> {
  205. loadNota(NOTA_NEXT);
  206. };
  207. listShortcuts.put(kcNextNota, rnNextNota);
  208. KeyCombination kcCariBarang = new KeyCodeCombination(KeyCode.F5);
  209. Runnable rnCariBarang = () -> {
  210. DialogCariBarangController dialogCariBarang = new DialogCariBarangController();
  211. dialogCariBarang.initOwner(bpMain.getScene().getWindow());
  212. Optional<BarangFull> result = dialogCariBarang.showAndWait();
  213. if (result.isPresent()) {
  214. BarangFull barangFull = result.get();
  215. switch (tipeTransaksiState) {
  216. case FormConstanta.TRANSAKSI_TUNAI:
  217. if (notaContent.controllerTunai != null) {
  218. if (barangFull.getBarang() != null && barangFull.getNoBarang() != null
  219. && barangFull.getBarang().getIdGabungan().equals(barangFull.getNoBarang().getIdGabungan())) {
  220. notaContent.controllerTunai.addToTable(barangFull.getBarang(), barangFull.getNoBarang());
  221. } else {
  222. Alert alert = AlertUtil.getAlertWarning(
  223. AlertUtil.ERROR_TIDAK_LENGKAP_TITLE,
  224. "Data Barang yang didapat tidak lengkap sehingga tidak bisa ditambahkan ke nota.");
  225. alert.initOwner(bpMain.getScene().getWindow());
  226. alert.show();
  227. }
  228. }
  229. break;
  230. case FormConstanta.TRANSAKSI_RETUR:
  231. break;
  232. }
  233. }
  234. };
  235. listShortcuts.put(kcCariBarang, rnCariBarang);
  236. KeyCombination kcCariPelanggan = new KeyCodeCombination(KeyCode.F6);
  237. Runnable rnCariPelanggan = () -> {
  238. DialogCariPelangganController dialogCariPelanggan = new DialogCariPelangganController();
  239. dialogCariPelanggan.initOwner(bpMain.getScene().getWindow());
  240. Optional<Pelanggan> result = dialogCariPelanggan.showAndWait();
  241. if (result.isPresent() && result.get() != null) {
  242. SystemValue.member = result.get();
  243. SystemValue.isMember = true;
  244. updateLabelPelanggan(result.get());
  245. updateLabelMemberNonMember();
  246. }
  247. };
  248. listShortcuts.put(kcCariPelanggan, rnCariPelanggan);
  249. KeyCombination kcCariNotaTunda = new KeyCodeCombination(KeyCode.F7);
  250. Runnable rnCariNotaTunda = () -> {
  251. DialogCariNotaTundaController dialogCariNotaTunda = new DialogCariNotaTundaController();
  252. dialogCariNotaTunda.initOwner(bpMain.getScene().getWindow());
  253. Optional<String> result = dialogCariNotaTunda.showAndWait();
  254. };
  255. listShortcuts.put(kcCariNotaTunda, rnCariNotaTunda);
  256. KeyCombination kcCheckout = new KeyCodeCombination(KeyCode.F8);
  257. Runnable rnCheckout = () -> {
  258. switch (tipeTransaksiState) {
  259. case FormConstanta.TRANSAKSI_TUNAI:
  260. setContent(formFactory.getForm(FormConstanta.BAYAR, this));
  261. break;
  262. case FormConstanta.TRANSAKSI_RETUR:
  263. DialogKonfirmasiReturController dialogKonfirmasiRetur = new DialogKonfirmasiReturController();
  264. dialogKonfirmasiRetur.initOwner(bpMain.getScene().getWindow());
  265. dialogKonfirmasiRetur.showAndWait();
  266. break;
  267. }
  268. };
  269. listShortcuts.put(kcCheckout, rnCheckout);
  270. KeyCombination kcCariCetakUlangNota = new KeyCodeCombination(KeyCode.P, KeyCombination.CONTROL_DOWN);
  271. Runnable rnCetakUlangNota = () -> {
  272. DialogCetakUlangNotaController dialogCetakUlangNota = new DialogCetakUlangNotaController();
  273. dialogCetakUlangNota.initOwner(bpMain.getScene().getWindow());
  274. Optional<String> result = dialogCetakUlangNota.showAndWait();
  275. };
  276. listShortcuts.put(kcCariCetakUlangNota, rnCetakUlangNota);
  277. KeyCombination kcTambah = new KeyCodeCombination(KeyCode.T, KeyCombination.CONTROL_DOWN);
  278. Runnable rnTambah = () -> {
  279. btnTambahNota.fire();
  280. };
  281. listShortcuts.put(kcTambah, rnTambah);
  282. KeyCombination kcScanMember = new KeyCodeCombination(KeyCode.S, KeyCombination.CONTROL_DOWN);
  283. Runnable rnScanMember = () -> {
  284. tfScanMember.requestFocus();
  285. };
  286. listShortcuts.put(kcScanMember, rnScanMember);
  287. KeyCombination kcLogout = new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN);
  288. Runnable rnLogout = () -> {
  289. try {
  290. generateNewWindow("/fxml/FormLogin.fxml").show();
  291. Stage thisStage = (Stage) bpMain.getScene().getWindow();
  292. thisStage.close();
  293. } catch (IOException ex) {
  294. Logger.getLogger(FormUtamaController.class.getName()).log(Level.SEVERE, null, ex);
  295. }
  296. };
  297. listShortcuts.put(kcLogout, rnLogout);
  298. Platform.runLater(() -> {
  299. bpMain.getScene().getAccelerators().putAll(listShortcuts);
  300. });
  301. }
  302. public void setContent(Node node) {
  303. try {
  304. spMainContent.setContent(node);
  305. } catch (NullPointerException npe) {
  306. Logger.getLogger(FormUtamaController.class
  307. .getName()).log(Level.SEVERE, null, npe);
  308. // AlertGenerate.getAlert(AlertGenerate.FXML_FAIL).show();
  309. }
  310. }
  311. public Stage generateNewWindow(String url) throws IOException {
  312. Stage stage = new Stage();
  313. Parent root;
  314. root = FXMLLoader.load(getClass().getResource(url));
  315. Scene scene = new Scene(root);
  316. stage.setTitle(Fucout.APP_TITLE);
  317. stage.getIcons().add(new Image(Fucout.APP_ICON));
  318. stage.setScene(scene);
  319. return stage;
  320. }
  321. @FXML
  322. void btnTambahNotaOnAction(ActionEvent event) {
  323. DialogTambahNotaController dialogTambahNota = new DialogTambahNotaController();
  324. dialogTambahNota.initOwner(bpMain.getScene().getWindow());
  325. Optional<String> hasilReturn = dialogTambahNota.showAndWait();
  326. if (hasilReturn.isPresent()) {
  327. if (hasilReturn.get().equals("Baru:Tunai")) {
  328. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_TUNAI)) {
  329. setContent(null);
  330. }
  331. if (notaContent.btnTunai != null) {
  332. navigasi.remove(notaContent.btnTunai);
  333. vbNavigasi.getChildren().remove(notaContent.btnTunai);
  334. }
  335. Button buttonBaru = generateButtonNota(Fucout.getNoNotaTemporary(),
  336. FormConstanta.TRANSAKSI_TUNAI,
  337. Fucout.TEKS_TIPE_NOTA_TUNAI,
  338. true);
  339. navigasi.add(buttonBaru);
  340. vbNavigasi.getChildren().add(buttonBaru);
  341. notaContent.btnTunai = buttonBaru;
  342. jumlahNota++;
  343. } else if (hasilReturn.get().equals("Baru:Bon")) {
  344. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_BON)) {
  345. setContent(null);
  346. }
  347. if (notaContent.btnBon != null) {
  348. navigasi.remove(notaContent.btnBon);
  349. vbNavigasi.getChildren().remove(notaContent.btnBon);
  350. }
  351. Button buttonBaru = generateButtonNota("B-" + Fucout.getNoNotaTemporary(),
  352. FormConstanta.TRANSAKSI_BON,
  353. Fucout.TEKS_TIPE_NOTA_BON,
  354. true);
  355. navigasi.add(buttonBaru);
  356. vbNavigasi.getChildren().add(buttonBaru);
  357. notaContent.btnBon = buttonBaru;
  358. jumlahNota++;
  359. } else if (hasilReturn.get().equals("Baru:Bawa Dulu")) {
  360. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_BAWA)) {
  361. setContent(null);
  362. }
  363. if (notaContent.btnBawa != null) {
  364. navigasi.remove(notaContent.btnBawa);
  365. vbNavigasi.getChildren().remove(notaContent.btnBawa);
  366. }
  367. Button buttonBaru = generateButtonNota("W-" + Fucout.getNoNotaTemporary(),
  368. FormConstanta.TRANSAKSI_BAWA,
  369. Fucout.TEKS_TIPE_NOTA_BAWA,
  370. true);
  371. navigasi.add(buttonBaru);
  372. vbNavigasi.getChildren().add(buttonBaru);
  373. notaContent.btnBawa = buttonBaru;
  374. jumlahNota++;
  375. } else if (hasilReturn.get().equals("Baru:Retur")) {
  376. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_RETUR)) {
  377. setContent(null);
  378. }
  379. if (notaContent.btnRetur != null) {
  380. navigasi.remove(notaContent.btnRetur);
  381. vbNavigasi.getChildren().remove(notaContent.btnRetur);
  382. }
  383. Button buttonBaru = generateButtonNota("R-" + Fucout.getNoNotaTemporary(),
  384. FormConstanta.TRANSAKSI_RETUR,
  385. Fucout.TEKS_TIPE_NOTA_RETUR,
  386. true);
  387. navigasi.add(buttonBaru);
  388. vbNavigasi.getChildren().add(buttonBaru);
  389. notaContent.btnRetur = buttonBaru;
  390. jumlahNota++;
  391. } else if (hasilReturn.get().contains("Checkout:")) {
  392. String noNota = hasilReturn.get().substring(9);
  393. Button buttonBaru = null;
  394. switch (noNota.charAt(0)) {
  395. case Fucout.KODE_NOTA_BON:
  396. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_BON)) {
  397. setContent(null);
  398. }
  399. break;
  400. case Fucout.KODE_NOTA_BAWA:
  401. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_BAWA)) {
  402. setContent(null);
  403. }
  404. break;
  405. case Fucout.KODE_NOTA_RETUR:
  406. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_RETUR)) {
  407. setContent(null);
  408. }
  409. if (notaContent.btnRetur != null) {
  410. navigasi.remove(notaContent.btnRetur);
  411. vbNavigasi.getChildren().remove(notaContent.btnRetur);
  412. }
  413. buttonBaru = generateButtonNota(noNota,
  414. FormConstanta.TRANSAKSI_RETUR,
  415. Fucout.TEKS_TIPE_NOTA_RETUR,
  416. false);
  417. notaContent.btnRetur = buttonBaru;
  418. break;
  419. default:
  420. if (tipeTransaksiState.equals(FormConstanta.TRANSAKSI_TUNAI)) {
  421. setContent(null);
  422. }
  423. if (notaContent.btnTunai != null) {
  424. navigasi.remove(notaContent.btnTunai);
  425. vbNavigasi.getChildren().remove(notaContent.btnTunai);
  426. }
  427. buttonBaru = generateButtonNota(noNota,
  428. FormConstanta.TRANSAKSI_TUNAI,
  429. Fucout.TEKS_TIPE_NOTA_TUNAI,
  430. false);
  431. notaContent.btnTunai = buttonBaru;
  432. break;
  433. }
  434. if (buttonBaru != null) {
  435. navigasi.add(buttonBaru);
  436. vbNavigasi.getChildren().add(buttonBaru);
  437. jumlahNota++;
  438. }
  439. }
  440. }
  441. }
  442. //scan member
  443. @FXML
  444. void scanMemberOnPressed(KeyEvent event) {
  445. if (event.getCode() == KeyCode.ENTER) {
  446. posRx.getPelangganByKodeMember(tfScanMember.getText()).subscribe(pelangganObserver);
  447. }
  448. }
  449. Observer<Pelanggan> pelangganObserver = new Observer<Pelanggan>() {
  450. @Override
  451. public void onSubscribe(Disposable dspsbl) {
  452. }
  453. @Override
  454. public void onNext(Pelanggan p) {
  455. if (p != null) {
  456. SystemValue.isMember = true;
  457. SystemValue.member = p;
  458. updateLabelPelanggan(p);
  459. }
  460. }
  461. @Override
  462. public void onError(Throwable error) {
  463. if (error instanceof HttpException) {
  464. switch (((HttpException) error).code()) {
  465. case HttpURLConnection.HTTP_NOT_FOUND:
  466. Alert alert = AlertUtil.getAlertError(
  467. AlertUtil.ERROR_TIDAK_DITEMUKAN_TITLE,
  468. "Pelanggan dengan kode member tersebut tidak ditemukan.");
  469. alert.initOwner(bpMain.getScene().getWindow());
  470. alert.show();
  471. }
  472. } else {
  473. AmigoPosRx.handleGenericError(error, bpMain.getScene().getWindow());
  474. }
  475. }
  476. @Override
  477. public void onComplete() {
  478. }
  479. };
  480. private class NotaContent {
  481. Button btnTunai;
  482. FormTransaksiTunaiController controllerTunai = null;
  483. Button btnBawa;
  484. Button btnBon;
  485. Button btnRetur;
  486. FormTransaksiReturController controllerRetur = null;
  487. }
  488. }