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.

437 lines
16 KiB

  1. package id.amigogroup.posterminal;
  2. import com.fasterxml.jackson.core.JsonProcessingException;
  3. import com.fasterxml.jackson.databind.ObjectMapper;
  4. import id.amigogroup.posterminal.api.AmigoPosRx;
  5. import id.amigogroup.posterminal.model.Pelanggan;
  6. import id.amigogroup.posterminal.pencarian.DialogCariBarangController;
  7. import id.amigogroup.posterminal.pencarian.DialogCariNotaTundaController;
  8. import id.amigogroup.posterminal.pencarian.DialogCariPelangganController;
  9. import id.amigogroup.posterminal.pencarian.DialogCetakUlangNotaController;
  10. import id.amigogroup.posterminal.transaksi.DialogKonfirmasiReturController;
  11. import id.amigogroup.posterminal.transaksi.DialogTambahNotaController;
  12. import id.amigogroup.posterminal.transaksi.FormTransaksiReturController;
  13. import id.amigogroup.posterminal.transaksi.FormTransaksiTunaiController;
  14. import id.amigogroup.posterminal.util.AlertUtil;
  15. import id.amigogroup.posterminal.util.Fucout;
  16. import io.reactivex.Observable;
  17. import static io.reactivex.Observable.error;
  18. import io.reactivex.Observer;
  19. import io.reactivex.disposables.Disposable;
  20. import java.io.IOException;
  21. import java.net.HttpURLConnection;
  22. import java.net.URL;
  23. import java.util.ArrayList;
  24. import java.util.HashMap;
  25. import java.util.List;
  26. import java.util.Map;
  27. import java.util.Optional;
  28. import java.util.ResourceBundle;
  29. import java.util.logging.Level;
  30. import java.util.logging.Logger;
  31. import javafx.application.Platform;
  32. import javafx.event.ActionEvent;
  33. import javafx.fxml.FXML;
  34. import javafx.fxml.FXMLLoader;
  35. import javafx.fxml.Initializable;
  36. import javafx.scene.Node;
  37. import javafx.scene.Parent;
  38. import javafx.scene.Scene;
  39. import javafx.scene.control.Alert;
  40. import javafx.scene.control.Button;
  41. import javafx.scene.control.Label;
  42. import javafx.scene.control.ScrollPane;
  43. import javafx.scene.image.Image;
  44. import javafx.scene.input.KeyCode;
  45. import javafx.scene.input.KeyCodeCombination;
  46. import javafx.scene.input.KeyCombination;
  47. import javafx.scene.layout.BorderPane;
  48. import javafx.scene.layout.VBox;
  49. import javafx.stage.Stage;
  50. import retrofit2.HttpException;
  51. public class FormUtamaController implements Initializable {
  52. @FXML
  53. private BorderPane bpMain;
  54. @FXML
  55. private ScrollPane spMainContent;
  56. @FXML
  57. private ScrollPane spNavigasi;
  58. @FXML
  59. private VBox vbNavigasi;
  60. @FXML
  61. private Label lblNamaLogin;
  62. @FXML
  63. private Button btnTunai1Static;
  64. @FXML
  65. private Button btnRetur1Static;
  66. @FXML
  67. private Button btnTunai2Static;
  68. @FXML
  69. private Label lblMemberNonMember;
  70. @FXML
  71. private Label lblNamaPelanggan;
  72. @FXML
  73. private Label lblTglLahirPelanggan;
  74. @FXML
  75. private Label lblNoTelpPelanggan;
  76. private final FormFactory formFactory = new FormFactory();
  77. private final List<Button> navigasi = new ArrayList<>();
  78. private int notaState = -1;
  79. private String tipeNotaState = "";
  80. private int jumlahNota = 0;
  81. private final char NOTA_PREV = 'p';
  82. private final char NOTA_NEXT = 'n';
  83. private Observable<Pelanggan> pelangganObs;
  84. /**
  85. * Initializes the controller class.
  86. */
  87. @Override
  88. public void initialize(URL url, ResourceBundle rb) {
  89. AmigoPosRx posRx = new AmigoPosRx();
  90. //Kode Nur Indah Suciati (00334), Kode Wuryaningsih/RT (010004)
  91. updateLabelMemberNonMember();
  92. Platform.runLater(() -> {
  93. posRx.getPelangganByKodeMember("00334").subscribe(pelangganObserver);
  94. });
  95. if (SystemValue.karyawanLogin != null) {
  96. lblNamaLogin.setText(Fucout.getTextColon(SystemValue.karyawanLogin.getNama()));
  97. }
  98. initShorcuts();
  99. //STATIC FUNCTION, hilangkan jika sudah tidak dipakai
  100. navigasi.add(btnTunai1Static);
  101. navigasi.add(btnRetur1Static);
  102. navigasi.add(btnTunai2Static);
  103. jumlahNota = 3;
  104. btnTunai1Static.setOnAction((event) -> {
  105. posRx.getPelangganByKodeMember("010004").subscribe(pelangganObserver);
  106. setContent(loadNota("", FormConstanta.TRANSAKSI_TUNAI));
  107. updateSelectedNota(event);
  108. tipeNotaState = Fucout.TIPE_NOTA_TUNAI;
  109. });
  110. btnRetur1Static.setOnAction((event) -> {
  111. setContent(loadNota("", FormConstanta.TRANSAKSI_RETUR));
  112. updateSelectedNota(event);
  113. tipeNotaState = Fucout.TIPE_NOTA_RETUR;
  114. });
  115. btnTunai2Static.setOnAction((event) -> {
  116. setContent(loadNota("", FormConstanta.TRANSAKSI_TUNAI));
  117. updateSelectedNota(event);
  118. tipeNotaState = Fucout.TIPE_NOTA_TUNAI;
  119. });
  120. }
  121. private void updateLabelPelanggan(Pelanggan p) {
  122. updateLabelMemberNonMember();
  123. if (Fucout.checkBirthday(p.getTglLahir())) {
  124. Alert alertUltah = AlertUtil.getAlertUlangTahun(p.getNama());
  125. alertUltah.initOwner(bpMain.getScene().getWindow());
  126. alertUltah.show();
  127. }
  128. lblNamaPelanggan.setText(Fucout.getTextColon(p.getNama()));
  129. lblTglLahirPelanggan.setText(Fucout.getTextColon(Fucout.formatTanggal(p.getTglLahir())));
  130. lblNoTelpPelanggan.setText(Fucout.getTextColon(
  131. !p.getTelp().equals("") && !p.getPonsel().equals("")
  132. ? p.getTelp() + System.lineSeparator() + p.getPonsel() : p.getTelp() + p.getPonsel()));
  133. }
  134. private void updateLabelMemberNonMember() {
  135. if (SystemValue.isMember) {
  136. lblMemberNonMember.setText("Member");
  137. } else {
  138. lblMemberNonMember.setText("Non Member");
  139. }
  140. }
  141. private void updateSelectedNota(ActionEvent event) {
  142. Button buttonSource = (Button) event.getSource();
  143. notaState = navigasi.indexOf(buttonSource);
  144. Fucout.scrollToNode(spNavigasi, buttonSource);
  145. // if (!tableState.equals(buttonSource.getText().toLowerCase())) {
  146. // switch (buttonSource.getText().toLowerCase()) {
  147. // case BTN_TUNAI:
  148. // //ambil data tunai
  149. // tableState = BTN_TUNAI;
  150. // System.out.println("ambil data tunai");
  151. // break;
  152. // case BTN_BAWA_DULU:
  153. // //ambil data bawa dulu
  154. // tableState = BTN_BAWA_DULU;
  155. // System.out.println("ambil data bawa dulu");
  156. // break;
  157. // case BTN_BON:
  158. // //ambil data bon
  159. // tableState = BTN_BON;
  160. // System.out.println("ambil data bon");
  161. // break;
  162. // case BTN_RETUR:
  163. // //ambil data retur
  164. // tableState = BTN_RETUR;
  165. // System.out.println("ambil data retur");
  166. // break;
  167. // }
  168. // }
  169. for (Button button : navigasi) {
  170. if (button.equals(buttonSource)) {
  171. if (!button.getStyleClass().contains("button-navigasi-transaksi-selected")) {
  172. button.getStyleClass().add("button-navigasi-transaksi-selected");
  173. }
  174. } else {
  175. if (button.getStyleClass().contains("button-navigasi-transaksi-selected")) {
  176. button.getStyleClass().remove("button-navigasi-transaksi-selected");
  177. }
  178. }
  179. }
  180. // fldScan.requestFocus();
  181. }
  182. private Button generateButtonNota(String noNota, String tipeNota, String tipeTeks) {
  183. Button button = new Button(tipeTeks + ": " + noNota);
  184. button.getStyleClass().add("button-navigasi-transaksi");
  185. button.setMaxWidth(Double.MAX_VALUE);
  186. button.setOnAction((event) -> {
  187. setContent(loadNota("", tipeNota));
  188. tipeNotaState = tipeNota;
  189. updateSelectedNota(event);
  190. });
  191. return button;
  192. }
  193. private Node loadNota(String noNota, String tipe) {
  194. Node node = null;
  195. FXMLLoader loader = new FXMLLoader();
  196. try {
  197. switch (tipe) {
  198. case FormConstanta.TRANSAKSI_TUNAI:
  199. loader.setLocation(getClass().getResource("/fxml/FormTransaksiTunai.fxml"));
  200. node = loader.load();
  201. FormTransaksiTunaiController fttc = loader.getController();
  202. // fetc.initData(noNota);
  203. break;
  204. case FormConstanta.TRANSAKSI_RETUR:
  205. loader.setLocation(getClass().getResource("/fxml/FormTransaksiRetur.fxml"));
  206. node = loader.load();
  207. FormTransaksiReturController ftrc = loader.getController();
  208. // fetc.initData(noNota);
  209. break;
  210. }
  211. } catch (IOException ex) {
  212. Logger.getLogger(FormUtamaController.class.getName()).log(Level.SEVERE, null, ex);
  213. }
  214. return node;
  215. }
  216. private void loadNota(char operasi) {
  217. switch (operasi) {
  218. case NOTA_PREV:
  219. if (notaState == -1) {
  220. notaState = jumlahNota - 1;
  221. } else {
  222. notaState--;
  223. if (notaState < 0) {
  224. notaState = jumlahNota - 1;
  225. }
  226. }
  227. break;
  228. case NOTA_NEXT:
  229. if (notaState == -1) {
  230. notaState = 0;
  231. } else {
  232. notaState++;
  233. if (notaState >= jumlahNota) {
  234. notaState = 0;
  235. }
  236. }
  237. break;
  238. }
  239. if (notaState >= 0 && notaState < jumlahNota) {
  240. navigasi.get(notaState).fire();
  241. }
  242. }
  243. private void initShorcuts() {
  244. Map<KeyCombination, Runnable> listShortcuts = new HashMap<>();
  245. KeyCombination kcPrevNota = new KeyCodeCombination(KeyCode.F1);
  246. Runnable rnPrevNota = () -> {
  247. loadNota(NOTA_PREV);
  248. };
  249. listShortcuts.put(kcPrevNota, rnPrevNota);
  250. KeyCombination kcNextNota = new KeyCodeCombination(KeyCode.F2);
  251. Runnable rnNextNota = () -> {
  252. loadNota(NOTA_NEXT);
  253. };
  254. listShortcuts.put(kcNextNota, rnNextNota);
  255. KeyCombination kcCariBarang = new KeyCodeCombination(KeyCode.F5);
  256. Runnable rnCariBarang = () -> {
  257. DialogCariBarangController dialogCariBarang = new DialogCariBarangController();
  258. dialogCariBarang.initOwner(bpMain.getScene().getWindow());
  259. Optional<String> result = dialogCariBarang.showAndWait();
  260. System.out.println(result);
  261. };
  262. listShortcuts.put(kcCariBarang, rnCariBarang);
  263. KeyCombination kcCariPelanggan = new KeyCodeCombination(KeyCode.F6);
  264. Runnable rnCariPelanggan = () -> {
  265. DialogCariPelangganController dialogCariPelanggan = new DialogCariPelangganController();
  266. dialogCariPelanggan.initOwner(bpMain.getScene().getWindow());
  267. Optional<String> result = dialogCariPelanggan.showAndWait();
  268. System.out.println(result);
  269. };
  270. listShortcuts.put(kcCariPelanggan, rnCariPelanggan);
  271. KeyCombination kcCariNotaTunda = new KeyCodeCombination(KeyCode.F7);
  272. Runnable rnCariNotaTunda = () -> {
  273. DialogCariNotaTundaController dialogCariNotaTunda = new DialogCariNotaTundaController();
  274. dialogCariNotaTunda.initOwner(bpMain.getScene().getWindow());
  275. Optional<String> result = dialogCariNotaTunda.showAndWait();
  276. System.out.println(result);
  277. };
  278. listShortcuts.put(kcCariNotaTunda, rnCariNotaTunda);
  279. KeyCombination kcCariCetakUlangNota = new KeyCodeCombination(KeyCode.P, KeyCombination.CONTROL_DOWN);
  280. Runnable rnCetakUlangNota = () -> {
  281. DialogCetakUlangNotaController dialogCetakUlangNota = new DialogCetakUlangNotaController();
  282. dialogCetakUlangNota.initOwner(bpMain.getScene().getWindow());
  283. Optional<String> result = dialogCetakUlangNota.showAndWait();
  284. System.out.println(result);
  285. };
  286. listShortcuts.put(kcCariCetakUlangNota, rnCetakUlangNota);
  287. KeyCombination kcCheckout = new KeyCodeCombination(KeyCode.F8);
  288. Runnable rnCheckout = () -> {
  289. switch (tipeNotaState) {
  290. case Fucout.TIPE_NOTA_TUNAI:
  291. setContent(formFactory.getForm(FormConstanta.BAYAR, this));
  292. break;
  293. case Fucout.TIPE_NOTA_RETUR:
  294. DialogKonfirmasiReturController dialogKonfirmasiRetur = new DialogKonfirmasiReturController();
  295. dialogKonfirmasiRetur.initOwner(bpMain.getScene().getWindow());
  296. dialogKonfirmasiRetur.showAndWait();
  297. break;
  298. }
  299. };
  300. listShortcuts.put(kcCheckout, rnCheckout);
  301. KeyCombination kcLogout = new KeyCodeCombination(KeyCode.L, KeyCombination.CONTROL_DOWN);
  302. Runnable rnLogout = () -> {
  303. try {
  304. generateNewWindow("/fxml/FormLogin.fxml").show();
  305. Stage thisStage = (Stage) bpMain.getScene().getWindow();
  306. thisStage.close();
  307. } catch (IOException ex) {
  308. Logger.getLogger(FormUtamaController.class.getName()).log(Level.SEVERE, null, ex);
  309. }
  310. };
  311. listShortcuts.put(kcLogout, rnLogout);
  312. Platform.runLater(() -> {
  313. bpMain.getScene().getAccelerators().putAll(listShortcuts);
  314. });
  315. }
  316. public void setContent(Node node) {
  317. try {
  318. spMainContent.setContent(node);
  319. } catch (NullPointerException npe) {
  320. Logger.getLogger(FormUtamaController.class
  321. .getName()).log(Level.SEVERE, null, npe);
  322. // AlertGenerate.getAlert(AlertGenerate.FXML_FAIL).show();
  323. }
  324. }
  325. public Stage generateNewWindow(String url) throws IOException {
  326. Stage stage = new Stage();
  327. Parent root;
  328. root = FXMLLoader.load(getClass().getResource(url));
  329. Scene scene = new Scene(root);
  330. stage.setTitle(Fucout.APP_TITLE);
  331. stage.getIcons().add(new Image(Fucout.APP_ICON));
  332. stage.setScene(scene);
  333. return stage;
  334. }
  335. @FXML
  336. void btnTambahNotaOnAction(ActionEvent event) {
  337. DialogTambahNotaController dialogTambahNota = new DialogTambahNotaController();
  338. dialogTambahNota.initOwner(bpMain.getScene().getWindow());
  339. Optional<String> hasilReturn = dialogTambahNota.showAndWait();
  340. if (hasilReturn.isPresent() && hasilReturn.get().equals("Tambah")) {
  341. Button buttonBaru = generateButtonNota("10-0220-0000X",
  342. FormConstanta.TRANSAKSI_TUNAI,
  343. Fucout.TIPE_NOTA_TUNAI);
  344. navigasi.add(buttonBaru);
  345. vbNavigasi.getChildren().add(buttonBaru);
  346. jumlahNota++;
  347. }
  348. }
  349. Observer<Pelanggan> pelangganObserver = new Observer<Pelanggan>() {
  350. @Override
  351. public void onSubscribe(Disposable dspsbl) {
  352. }
  353. @Override
  354. public void onNext(Pelanggan p) {
  355. ObjectMapper mapper = new ObjectMapper();
  356. try {
  357. System.out.println(mapper.writeValueAsString(p));
  358. } catch (JsonProcessingException ex) {
  359. Logger.getLogger(FormUtamaController.class.getName()).log(Level.SEVERE, null, ex);
  360. }
  361. if (p != null) {
  362. SystemValue.isMember = true;
  363. SystemValue.member = p;
  364. updateLabelPelanggan(p);
  365. }
  366. }
  367. @Override
  368. public void onError(Throwable error) {
  369. if (error instanceof HttpException) {
  370. switch (((HttpException) error).code()) {
  371. case HttpURLConnection.HTTP_NOT_FOUND:
  372. Alert alert = AlertUtil.getAlertError(
  373. AlertUtil.ERROR_TIDAK_DITEMUKAN_TITLE,
  374. "Pelanggan dengan kode member tersebut tidak ditemukan.");
  375. alert.initOwner(bpMain.getScene().getWindow());
  376. alert.show();
  377. }
  378. } else {
  379. Alert alert = AlertUtil.getAlertError(
  380. AlertUtil.ERROR_TIDAK_TERDUGA_TITLE,
  381. "Terjadi kesalahan yang tidak terduga.");
  382. alert.initOwner(bpMain.getScene().getWindow());
  383. alert.show();
  384. Logger.getLogger(FormUtamaController.class.getName()).log(Level.SEVERE, null, error);
  385. }
  386. }
  387. @Override
  388. public void onComplete() {
  389. }
  390. };
  391. }